From 760dd035044cda8bd6e1004dba1077d3f081f5e2 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 10 Mar 2020 19:49:49 +0100 Subject: [PATCH 1/4] Download qhull at build-or-sdist time. --- .gitignore | 2 + extern/libqhull/COPYING.txt | 38 - extern/libqhull/geom.c | 1234 --------- extern/libqhull/geom.h | 176 -- extern/libqhull/geom2.c | 2094 --------------- extern/libqhull/global.c | 2217 ---------------- extern/libqhull/io.c | 4062 ----------------------------- extern/libqhull/io.h | 159 -- extern/libqhull/libqhull.c | 1403 ---------- extern/libqhull/libqhull.h | 1140 -------- extern/libqhull/mem.c | 576 ---- extern/libqhull/mem.h | 222 -- extern/libqhull/merge.c | 3628 -------------------------- extern/libqhull/merge.h | 178 -- extern/libqhull/poly.c | 1205 --------- extern/libqhull/poly.h | 296 --- extern/libqhull/poly2.c | 3222 ----------------------- extern/libqhull/qhull_a.h | 150 -- extern/libqhull/qset.c | 1340 ---------- extern/libqhull/qset.h | 490 ---- extern/libqhull/random.c | 245 -- extern/libqhull/random.h | 34 - extern/libqhull/rboxlib.c | 870 ------ extern/libqhull/stat.c | 717 ----- extern/libqhull/stat.h | 543 ---- extern/libqhull/user.c | 536 ---- extern/libqhull/user.h | 909 ------- extern/libqhull/usermem.c | 94 - extern/libqhull/userprintf.c | 66 - extern/libqhull/userprintf_rbox.c | 53 - setup.py | 20 +- setupext.py | 8 +- 32 files changed, 26 insertions(+), 27901 deletions(-) delete mode 100644 extern/libqhull/COPYING.txt delete mode 100644 extern/libqhull/geom.c delete mode 100644 extern/libqhull/geom.h delete mode 100644 extern/libqhull/geom2.c delete mode 100644 extern/libqhull/global.c delete mode 100644 extern/libqhull/io.c delete mode 100644 extern/libqhull/io.h delete mode 100644 extern/libqhull/libqhull.c delete mode 100644 extern/libqhull/libqhull.h delete mode 100644 extern/libqhull/mem.c delete mode 100644 extern/libqhull/mem.h delete mode 100644 extern/libqhull/merge.c delete mode 100644 extern/libqhull/merge.h delete mode 100644 extern/libqhull/poly.c delete mode 100644 extern/libqhull/poly.h delete mode 100644 extern/libqhull/poly2.c delete mode 100644 extern/libqhull/qhull_a.h delete mode 100644 extern/libqhull/qset.c delete mode 100644 extern/libqhull/qset.h delete mode 100644 extern/libqhull/random.c delete mode 100644 extern/libqhull/random.h delete mode 100644 extern/libqhull/rboxlib.c delete mode 100644 extern/libqhull/stat.c delete mode 100644 extern/libqhull/stat.h delete mode 100644 extern/libqhull/user.c delete mode 100644 extern/libqhull/user.h delete mode 100644 extern/libqhull/usermem.c delete mode 100644 extern/libqhull/userprintf.c delete mode 100644 extern/libqhull/userprintf_rbox.c diff --git a/.gitignore b/.gitignore index ee4a0eb7aef6..395f8be25efb 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,5 @@ lib/z.lib ######################### lib/matplotlib/backends/web_backend/node_modules/ lib/matplotlib/backends/web_backend/package-lock.json + +extern/qhull-*/ diff --git a/extern/libqhull/COPYING.txt b/extern/libqhull/COPYING.txt deleted file mode 100644 index 2895ec6a32f1..000000000000 --- a/extern/libqhull/COPYING.txt +++ /dev/null @@ -1,38 +0,0 @@ - Qhull, Copyright (c) 1993-2015 - - C.B. Barber - Arlington, MA - - and - - The National Science and Technology Research Center for - Computation and Visualization of Geometric Structures - (The Geometry Center) - University of Minnesota - - email: qhull@qhull.org - -This software includes Qhull from C.B. Barber and The Geometry Center. -Qhull is copyrighted as noted above. Qhull is free software and may -be obtained via http from www.qhull.org. It may be freely copied, modified, -and redistributed under the following conditions: - -1. All copyright notices must remain intact in all files. - -2. A copy of this text file must be distributed along with any copies - of Qhull that you redistribute; this includes copies that you have - modified, or copies of programs or other software products that - include Qhull. - -3. If you modify Qhull, you must include a notice giving the - name of the person performing the modification, the date of - modification, and the reason for such modification. - -4. When distributing modified versions of Qhull, or other software - products that include Qhull, you must provide notice that the original - source code may be obtained as noted above. - -5. There is no warranty or other guarantee of fitness for Qhull, it is - provided solely "as is". Bug reports or fixes may be sent to - qhull_bug@qhull.org; the authors may or may not act on them as - they desire. diff --git a/extern/libqhull/geom.c b/extern/libqhull/geom.c deleted file mode 100644 index 71444f05a4c1..000000000000 --- a/extern/libqhull/geom.c +++ /dev/null @@ -1,1234 +0,0 @@ -/*
  ---------------------------------
-
-   geom.c
-   geometric routines of qhull
-
-   see qh-geom.htm and geom.h
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/geom.c#2 $$Change: 1995 $
-   $DateTime: 2015/10/13 21:59:42 $$Author: bbarber $
-
-   infrequent code goes into geom2.c
-*/
-
-#include "qhull_a.h"
-
-/*---------------------------------
-
-  qh_distplane( point, facet, dist )
-    return distance from point to facet
-
-  returns:
-    dist
-    if qh.RANDOMdist, joggles result
-
-  notes:
-    dist > 0 if point is above facet (i.e., outside)
-    does not error (for qh_sortfacets, qh_outerinner)
-
-  see:
-    qh_distnorm in geom2.c
-    qh_distplane [geom.c], QhullFacet::distance, and QhullHyperplane::distance are copies
-*/
-void qh_distplane(pointT *point, facetT *facet, realT *dist) {
-  coordT *normal= facet->normal, *coordp, randr;
-  int k;
-
-  switch (qh hull_dim){
-  case 2:
-    *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1];
-    break;
-  case 3:
-    *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1] + point[2] * normal[2];
-    break;
-  case 4:
-    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3];
-    break;
-  case 5:
-    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4];
-    break;
-  case 6:
-    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5];
-    break;
-  case 7:
-    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6];
-    break;
-  case 8:
-    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6]+point[7]*normal[7];
-    break;
-  default:
-    *dist= facet->offset;
-    coordp= point;
-    for (k=qh hull_dim; k--; )
-      *dist += *coordp++ * *normal++;
-    break;
-  }
-  zinc_(Zdistplane);
-  if (!qh RANDOMdist && qh IStracing < 4)
-    return;
-  if (qh RANDOMdist) {
-    randr= qh_RANDOMint;
-    *dist += (2.0 * randr / qh_RANDOMmax - 1.0) *
-      qh RANDOMfactor * qh MAXabs_coord;
-  }
-  if (qh IStracing >= 4) {
-    qh_fprintf(qh ferr, 8001, "qh_distplane: ");
-    qh_fprintf(qh ferr, 8002, qh_REAL_1, *dist);
-    qh_fprintf(qh ferr, 8003, "from p%d to f%d\n", qh_pointid(point), facet->id);
-  }
-  return;
-} /* distplane */
-
-
-/*---------------------------------
-
-  qh_findbest( point, startfacet, bestoutside, qh_ISnewfacets, qh_NOupper, dist, isoutside, numpart )
-    find facet that is furthest below a point
-    for upperDelaunay facets
-      returns facet only if !qh_NOupper and clearly above
-
-  input:
-    starts search at 'startfacet' (can not be flipped)
-    if !bestoutside(qh_ALL), stops at qh.MINoutside
-
-  returns:
-    best facet (reports error if NULL)
-    early out if isoutside defined and bestdist > qh.MINoutside
-    dist is distance to facet
-    isoutside is true if point is outside of facet
-    numpart counts the number of distance tests
-
-  see also:
-    qh_findbestnew()
-
-  notes:
-    If merging (testhorizon), searches horizon facets of coplanar best facets because
-    after qh_distplane, this and qh_partitionpoint are the most expensive in 3-d
-      avoid calls to distplane, function calls, and real number operations.
-    caller traces result
-    Optimized for outside points.   Tried recording a search set for qh_findhorizon.
-    Made code more complicated.
-
-  when called by qh_partitionvisible():
-    indicated by qh_ISnewfacets
-    qh.newfacet_list is list of simplicial, new facets
-    qh_findbestnew set if qh_sharpnewfacets returns True (to use qh_findbestnew)
-    qh.bestfacet_notsharp set if qh_sharpnewfacets returns False
-
-  when called by qh_findfacet(), qh_partitionpoint(), qh_partitioncoplanar(),
-                 qh_check_bestdist(), qh_addpoint()
-    indicated by !qh_ISnewfacets
-    returns best facet in neighborhood of given facet
-      this is best facet overall if dist > -   qh.MAXcoplanar
-        or hull has at least a "spherical" curvature
-
-  design:
-    initialize and test for early exit
-    repeat while there are better facets
-      for each neighbor of facet
-        exit if outside facet found
-        test for better facet
-    if point is inside and partitioning
-      test for new facets with a "sharp" intersection
-      if so, future calls go to qh_findbestnew()
-    test horizon facets
-*/
-facetT *qh_findbest(pointT *point, facetT *startfacet,
-                     boolT bestoutside, boolT isnewfacets, boolT noupper,
-                     realT *dist, boolT *isoutside, int *numpart) {
-  realT bestdist= -REALmax/2 /* avoid underflow */;
-  facetT *facet, *neighbor, **neighborp;
-  facetT *bestfacet= NULL, *lastfacet= NULL;
-  int oldtrace= qh IStracing;
-  unsigned int visitid= ++qh visit_id;
-  int numpartnew=0;
-  boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
-
-  zinc_(Zfindbest);
-  if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid(point))) {
-    if (qh TRACElevel > qh IStracing)
-      qh IStracing= qh TRACElevel;
-    qh_fprintf(qh ferr, 8004, "qh_findbest: point p%d starting at f%d isnewfacets? %d, unless %d exit if > %2.2g\n",
-             qh_pointid(point), startfacet->id, isnewfacets, bestoutside, qh MINoutside);
-    qh_fprintf(qh ferr, 8005, "  testhorizon? %d noupper? %d", testhorizon, noupper);
-    qh_fprintf(qh ferr, 8006, "  Last point added was p%d.", qh furthest_id);
-    qh_fprintf(qh ferr, 8007, "  Last merge was #%d.  max_outside %2.2g\n", zzval_(Ztotmerge), qh max_outside);
-  }
-  if (isoutside)
-    *isoutside= True;
-  if (!startfacet->flipped) {  /* test startfacet */
-    *numpart= 1;
-    qh_distplane(point, startfacet, dist);  /* this code is duplicated below */
-    if (!bestoutside && *dist >= qh MINoutside
-    && (!startfacet->upperdelaunay || !noupper)) {
-      bestfacet= startfacet;
-      goto LABELreturn_best;
-    }
-    bestdist= *dist;
-    if (!startfacet->upperdelaunay) {
-      bestfacet= startfacet;
-    }
-  }else
-    *numpart= 0;
-  startfacet->visitid= visitid;
-  facet= startfacet;
-  while (facet) {
-    trace4((qh ferr, 4001, "qh_findbest: neighbors of f%d, bestdist %2.2g f%d\n",
-                facet->id, bestdist, getid_(bestfacet)));
-    lastfacet= facet;
-    FOREACHneighbor_(facet) {
-      if (!neighbor->newfacet && isnewfacets)
-        continue;
-      if (neighbor->visitid == visitid)
-        continue;
-      neighbor->visitid= visitid;
-      if (!neighbor->flipped) {  /* code duplicated above */
-        (*numpart)++;
-        qh_distplane(point, neighbor, dist);
-        if (*dist > bestdist) {
-          if (!bestoutside && *dist >= qh MINoutside
-          && (!neighbor->upperdelaunay || !noupper)) {
-            bestfacet= neighbor;
-            goto LABELreturn_best;
-          }
-          if (!neighbor->upperdelaunay) {
-            bestfacet= neighbor;
-            bestdist= *dist;
-            break; /* switch to neighbor */
-          }else if (!bestfacet) {
-            bestdist= *dist;
-            break; /* switch to neighbor */
-          }
-        } /* end of *dist>bestdist */
-      } /* end of !flipped */
-    } /* end of FOREACHneighbor */
-    facet= neighbor;  /* non-NULL only if *dist>bestdist */
-  } /* end of while facet (directed search) */
-  if (isnewfacets) {
-    if (!bestfacet) {
-      bestdist= -REALmax/2;
-      bestfacet= qh_findbestnew(point, startfacet->next, &bestdist, bestoutside, isoutside, &numpartnew);
-      testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
-    }else if (!qh findbest_notsharp && bestdist < - qh DISTround) {
-      if (qh_sharpnewfacets()) {
-        /* seldom used, qh_findbestnew will retest all facets */
-        zinc_(Zfindnewsharp);
-        bestfacet= qh_findbestnew(point, bestfacet, &bestdist, bestoutside, isoutside, &numpartnew);
-        testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
-        qh findbestnew= True;
-      }else
-        qh findbest_notsharp= True;
-    }
-  }
-  if (!bestfacet)
-    bestfacet= qh_findbestlower(lastfacet, point, &bestdist, numpart);
-  if (testhorizon)
-    bestfacet= qh_findbesthorizon(!qh_IScheckmax, point, bestfacet, noupper, &bestdist, &numpartnew);
-  *dist= bestdist;
-  if (isoutside && bestdist < qh MINoutside)
-    *isoutside= False;
-LABELreturn_best:
-  zadd_(Zfindbesttot, *numpart);
-  zmax_(Zfindbestmax, *numpart);
-  (*numpart) += numpartnew;
-  qh IStracing= oldtrace;
-  return bestfacet;
-}  /* findbest */
-
-
-/*---------------------------------
-
-  qh_findbesthorizon( qh_IScheckmax, point, startfacet, qh_NOupper, &bestdist, &numpart )
-    search coplanar and better horizon facets from startfacet/bestdist
-    ischeckmax turns off statistics and minsearch update
-    all arguments must be initialized
-  returns(ischeckmax):
-    best facet
-  returns(!ischeckmax):
-    best facet that is not upperdelaunay
-    allows upperdelaunay that is clearly outside
-  returns:
-    bestdist is distance to bestfacet
-    numpart -- updates number of distance tests
-
-  notes:
-    no early out -- use qh_findbest() or qh_findbestnew()
-    Searches coplanar or better horizon facets
-
-  when called by qh_check_maxout() (qh_IScheckmax)
-    startfacet must be closest to the point
-      Otherwise, if point is beyond and below startfacet, startfacet may be a local minimum
-      even though other facets are below the point.
-    updates facet->maxoutside for good, visited facets
-    may return NULL
-
-    searchdist is qh.max_outside + 2 * DISTround
-      + max( MINvisible('Vn'), MAXcoplanar('Un'));
-    This setting is a guess.  It must be at least max_outside + 2*DISTround
-    because a facet may have a geometric neighbor across a vertex
-
-  design:
-    for each horizon facet of coplanar best facets
-      continue if clearly inside
-      unless upperdelaunay or clearly outside
-         update best facet
-*/
-facetT *qh_findbesthorizon(boolT ischeckmax, pointT* point, facetT *startfacet, boolT noupper, realT *bestdist, int *numpart) {
-  facetT *bestfacet= startfacet;
-  realT dist;
-  facetT *neighbor, **neighborp, *facet;
-  facetT *nextfacet= NULL; /* optimize last facet of coplanarfacetset */
-  int numpartinit= *numpart, coplanarfacetset_size;
-  unsigned int visitid= ++qh visit_id;
-  boolT newbest= False; /* for tracing */
-  realT minsearch, searchdist;  /* skip facets that are too far from point */
-
-  if (!ischeckmax) {
-    zinc_(Zfindhorizon);
-  }else {
-#if qh_MAXoutside
-    if ((!qh ONLYgood || startfacet->good) && *bestdist > startfacet->maxoutside)
-      startfacet->maxoutside= *bestdist;
-#endif
-  }
-  searchdist= qh_SEARCHdist; /* multiple of qh.max_outside and precision constants */
-  minsearch= *bestdist - searchdist;
-  if (ischeckmax) {
-    /* Always check coplanar facets.  Needed for RBOX 1000 s Z1 G1e-13 t996564279 | QHULL Tv */
-    minimize_(minsearch, -searchdist);
-  }
-  coplanarfacetset_size= 0;
-  facet= startfacet;
-  while (True) {
-    trace4((qh ferr, 4002, "qh_findbesthorizon: neighbors of f%d bestdist %2.2g f%d ischeckmax? %d noupper? %d minsearch %2.2g searchdist %2.2g\n",
-                facet->id, *bestdist, getid_(bestfacet), ischeckmax, noupper,
-                minsearch, searchdist));
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid == visitid)
-        continue;
-      neighbor->visitid= visitid;
-      if (!neighbor->flipped) {
-        qh_distplane(point, neighbor, &dist);
-        (*numpart)++;
-        if (dist > *bestdist) {
-          if (!neighbor->upperdelaunay || ischeckmax || (!noupper && dist >= qh MINoutside)) {
-            bestfacet= neighbor;
-            *bestdist= dist;
-            newbest= True;
-            if (!ischeckmax) {
-              minsearch= dist - searchdist;
-              if (dist > *bestdist + searchdist) {
-                zinc_(Zfindjump);  /* everything in qh.coplanarfacetset at least searchdist below */
-                coplanarfacetset_size= 0;
-              }
-            }
-          }
-        }else if (dist < minsearch)
-          continue;  /* if ischeckmax, dist can't be positive */
-#if qh_MAXoutside
-        if (ischeckmax && dist > neighbor->maxoutside)
-          neighbor->maxoutside= dist;
-#endif
-      } /* end of !flipped */
-      if (nextfacet) {
-        if (!coplanarfacetset_size++) {
-          SETfirst_(qh coplanarfacetset)= nextfacet;
-          SETtruncate_(qh coplanarfacetset, 1);
-        }else
-          qh_setappend(&qh coplanarfacetset, nextfacet); /* Was needed for RBOX 1000 s W1e-13 P0 t996547055 | QHULL d Qbb Qc Tv
-                                                 and RBOX 1000 s Z1 G1e-13 t996564279 | qhull Tv  */
-      }
-      nextfacet= neighbor;
-    } /* end of EACHneighbor */
-    facet= nextfacet;
-    if (facet)
-      nextfacet= NULL;
-    else if (!coplanarfacetset_size)
-      break;
-    else if (!--coplanarfacetset_size) {
-      facet= SETfirstt_(qh coplanarfacetset, facetT);
-      SETtruncate_(qh coplanarfacetset, 0);
-    }else
-      facet= (facetT*)qh_setdellast(qh coplanarfacetset);
-  } /* while True, for each facet in qh.coplanarfacetset */
-  if (!ischeckmax) {
-    zadd_(Zfindhorizontot, *numpart - numpartinit);
-    zmax_(Zfindhorizonmax, *numpart - numpartinit);
-    if (newbest)
-      zinc_(Zparthorizon);
-  }
-  trace4((qh ferr, 4003, "qh_findbesthorizon: newbest? %d bestfacet f%d bestdist %2.2g\n", newbest, getid_(bestfacet), *bestdist));
-  return bestfacet;
-}  /* findbesthorizon */
-
-/*---------------------------------
-
-  qh_findbestnew( point, startfacet, dist, isoutside, numpart )
-    find best newfacet for point
-    searches all of qh.newfacet_list starting at startfacet
-    searches horizon facets of coplanar best newfacets
-    searches all facets if startfacet == qh.facet_list
-  returns:
-    best new or horizon facet that is not upperdelaunay
-    early out if isoutside and not 'Qf'
-    dist is distance to facet
-    isoutside is true if point is outside of facet
-    numpart is number of distance tests
-
-  notes:
-    Always used for merged new facets (see qh_USEfindbestnew)
-    Avoids upperdelaunay facet unless (isoutside and outside)
-
-    Uses qh.visit_id, qh.coplanarfacetset.
-    If share visit_id with qh_findbest, coplanarfacetset is incorrect.
-
-    If merging (testhorizon), searches horizon facets of coplanar best facets because
-    a point maybe coplanar to the bestfacet, below its horizon facet,
-    and above a horizon facet of a coplanar newfacet.  For example,
-      rbox 1000 s Z1 G1e-13 | qhull
-      rbox 1000 s W1e-13 P0 t992110337 | QHULL d Qbb Qc
-
-    qh_findbestnew() used if
-       qh_sharpnewfacets -- newfacets contains a sharp angle
-       if many merges, qh_premerge found a merge, or 'Qf' (qh.findbestnew)
-
-  see also:
-    qh_partitionall() and qh_findbest()
-
-  design:
-    for each new facet starting from startfacet
-      test distance from point to facet
-      return facet if clearly outside
-      unless upperdelaunay and a lowerdelaunay exists
-         update best facet
-    test horizon facets
-*/
-facetT *qh_findbestnew(pointT *point, facetT *startfacet,
-           realT *dist, boolT bestoutside, boolT *isoutside, int *numpart) {
-  realT bestdist= -REALmax/2;
-  facetT *bestfacet= NULL, *facet;
-  int oldtrace= qh IStracing, i;
-  unsigned int visitid= ++qh visit_id;
-  realT distoutside= 0.0;
-  boolT isdistoutside; /* True if distoutside is defined */
-  boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
-
-  if (!startfacet) {
-    if (qh MERGING)
-      qh_fprintf(qh ferr, 6001, "qhull precision error (qh_findbestnew): merging has formed and deleted a cone of new facets.  Can not continue.\n");
-    else
-      qh_fprintf(qh ferr, 6002, "qhull internal error (qh_findbestnew): no new facets for point p%d\n",
-              qh furthest_id);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  zinc_(Zfindnew);
-  if (qh BESToutside || bestoutside)
-    isdistoutside= False;
-  else {
-    isdistoutside= True;
-    distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
-  }
-  if (isoutside)
-    *isoutside= True;
-  *numpart= 0;
-  if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid(point))) {
-    if (qh TRACElevel > qh IStracing)
-      qh IStracing= qh TRACElevel;
-    qh_fprintf(qh ferr, 8008, "qh_findbestnew: point p%d facet f%d. Stop? %d if dist > %2.2g\n",
-             qh_pointid(point), startfacet->id, isdistoutside, distoutside);
-    qh_fprintf(qh ferr, 8009, "  Last point added p%d visitid %d.",  qh furthest_id, visitid);
-    qh_fprintf(qh ferr, 8010, "  Last merge was #%d.\n", zzval_(Ztotmerge));
-  }
-  /* visit all new facets starting with startfacet, maybe qh facet_list */
-  for (i=0, facet=startfacet; i < 2; i++, facet= qh newfacet_list) {
-    FORALLfacet_(facet) {
-      if (facet == startfacet && i)
-        break;
-      facet->visitid= visitid;
-      if (!facet->flipped) {
-        qh_distplane(point, facet, dist);
-        (*numpart)++;
-        if (*dist > bestdist) {
-          if (!facet->upperdelaunay || *dist >= qh MINoutside) {
-            bestfacet= facet;
-            if (isdistoutside && *dist >= distoutside)
-              goto LABELreturn_bestnew;
-            bestdist= *dist;
-          }
-        }
-      } /* end of !flipped */
-    } /* FORALLfacet from startfacet or qh newfacet_list */
-  }
-  if (testhorizon || !bestfacet) /* testhorizon is always True.  Keep the same code as qh_findbest */
-    bestfacet= qh_findbesthorizon(!qh_IScheckmax, point, bestfacet ? bestfacet : startfacet,
-                                        !qh_NOupper, &bestdist, numpart);
-  *dist= bestdist;
-  if (isoutside && *dist < qh MINoutside)
-    *isoutside= False;
-LABELreturn_bestnew:
-  zadd_(Zfindnewtot, *numpart);
-  zmax_(Zfindnewmax, *numpart);
-  trace4((qh ferr, 4004, "qh_findbestnew: bestfacet f%d bestdist %2.2g\n", getid_(bestfacet), *dist));
-  qh IStracing= oldtrace;
-  return bestfacet;
-}  /* findbestnew */
-
-/* ============ hyperplane functions -- keep code together [?] ============ */
-
-/*---------------------------------
-
-  qh_backnormal( rows, numrow, numcol, sign, normal, nearzero )
-    given an upper-triangular rows array and a sign,
-    solve for normal equation x using back substitution over rows U
-
-  returns:
-     normal= x
-
-     if will not be able to divzero() when normalized(qh.MINdenom_2 and qh.MINdenom_1_2),
-       if fails on last row
-         this means that the hyperplane intersects [0,..,1]
-         sets last coordinate of normal to sign
-       otherwise
-         sets tail of normal to [...,sign,0,...], i.e., solves for b= [0...0]
-         sets nearzero
-
-  notes:
-     assumes numrow == numcol-1
-
-     see Golub & van Loan, 1983, Eq. 4.4-9 for "Gaussian elimination with complete pivoting"
-
-     solves Ux=b where Ax=b and PA=LU
-     b= [0,...,0,sign or 0]  (sign is either -1 or +1)
-     last row of A= [0,...,0,1]
-
-     1) Ly=Pb == y=b since P only permutes the 0's of   b
-
-  design:
-    for each row from end
-      perform back substitution
-      if near zero
-        use qh_divzero for division
-        if zero divide and not last row
-          set tail of normal to 0
-*/
-void qh_backnormal(realT **rows, int numrow, int numcol, boolT sign,
-        coordT *normal, boolT *nearzero) {
-  int i, j;
-  coordT *normalp, *normal_tail, *ai, *ak;
-  realT diagonal;
-  boolT waszero;
-  int zerocol= -1;
-
-  normalp= normal + numcol - 1;
-  *normalp--= (sign ? -1.0 : 1.0);
-  for (i=numrow; i--; ) {
-    *normalp= 0.0;
-    ai= rows[i] + i + 1;
-    ak= normalp+1;
-    for (j=i+1; j < numcol; j++)
-      *normalp -= *ai++ * *ak++;
-    diagonal= (rows[i])[i];
-    if (fabs_(diagonal) > qh MINdenom_2)
-      *(normalp--) /= diagonal;
-    else {
-      waszero= False;
-      *normalp= qh_divzero(*normalp, diagonal, qh MINdenom_1_2, &waszero);
-      if (waszero) {
-        zerocol= i;
-        *(normalp--)= (sign ? -1.0 : 1.0);
-        for (normal_tail= normalp+2; normal_tail < normal + numcol; normal_tail++)
-          *normal_tail= 0.0;
-      }else
-        normalp--;
-    }
-  }
-  if (zerocol != -1) {
-    zzinc_(Zback0);
-    *nearzero= True;
-    trace4((qh ferr, 4005, "qh_backnormal: zero diagonal at column %d.\n", i));
-    qh_precision("zero diagonal on back substitution");
-  }
-} /* backnormal */
-
-/*---------------------------------
-
-  qh_gausselim( rows, numrow, numcol, sign )
-    Gaussian elimination with partial pivoting
-
-  returns:
-    rows is upper triangular (includes row exchanges)
-    flips sign for each row exchange
-    sets nearzero if pivot[k] < qh.NEARzero[k], else clears it
-
-  notes:
-    if nearzero, the determinant's sign may be incorrect.
-    assumes numrow <= numcol
-
-  design:
-    for each row
-      determine pivot and exchange rows if necessary
-      test for near zero
-      perform gaussian elimination step
-*/
-void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero) {
-  realT *ai, *ak, *rowp, *pivotrow;
-  realT n, pivot, pivot_abs= 0.0, temp;
-  int i, j, k, pivoti, flip=0;
-
-  *nearzero= False;
-  for (k=0; k < numrow; k++) {
-    pivot_abs= fabs_((rows[k])[k]);
-    pivoti= k;
-    for (i=k+1; i < numrow; i++) {
-      if ((temp= fabs_((rows[i])[k])) > pivot_abs) {
-        pivot_abs= temp;
-        pivoti= i;
-      }
-    }
-    if (pivoti != k) {
-      rowp= rows[pivoti];
-      rows[pivoti]= rows[k];
-      rows[k]= rowp;
-      *sign ^= 1;
-      flip ^= 1;
-    }
-    if (pivot_abs <= qh NEARzero[k]) {
-      *nearzero= True;
-      if (pivot_abs == 0.0) {   /* remainder of column == 0 */
-        if (qh IStracing >= 4) {
-          qh_fprintf(qh ferr, 8011, "qh_gausselim: 0 pivot at column %d. (%2.2g < %2.2g)\n", k, pivot_abs, qh DISTround);
-          qh_printmatrix(qh ferr, "Matrix:", rows, numrow, numcol);
-        }
-        zzinc_(Zgauss0);
-        qh_precision("zero pivot for Gaussian elimination");
-        goto LABELnextcol;
-      }
-    }
-    pivotrow= rows[k] + k;
-    pivot= *pivotrow++;  /* signed value of pivot, and remainder of row */
-    for (i=k+1; i < numrow; i++) {
-      ai= rows[i] + k;
-      ak= pivotrow;
-      n= (*ai++)/pivot;   /* divzero() not needed since |pivot| >= |*ai| */
-      for (j= numcol - (k+1); j--; )
-        *ai++ -= n * *ak++;
-    }
-  LABELnextcol:
-    ;
-  }
-  wmin_(Wmindenom, pivot_abs);  /* last pivot element */
-  if (qh IStracing >= 5)
-    qh_printmatrix(qh ferr, "qh_gausselem: result", rows, numrow, numcol);
-} /* gausselim */
-
-
-/*---------------------------------
-
-  qh_getangle( vect1, vect2 )
-    returns the dot product of two vectors
-    if qh.RANDOMdist, joggles result
-
-  notes:
-    the angle may be > 1.0 or < -1.0 because of roundoff errors
-
-*/
-realT qh_getangle(pointT *vect1, pointT *vect2) {
-  realT angle= 0, randr;
-  int k;
-
-  for (k=qh hull_dim; k--; )
-    angle += *vect1++ * *vect2++;
-  if (qh RANDOMdist) {
-    randr= qh_RANDOMint;
-    angle += (2.0 * randr / qh_RANDOMmax - 1.0) *
-      qh RANDOMfactor;
-  }
-  trace4((qh ferr, 4006, "qh_getangle: %2.2g\n", angle));
-  return(angle);
-} /* getangle */
-
-
-/*---------------------------------
-
-  qh_getcenter( vertices )
-    returns arithmetic center of a set of vertices as a new point
-
-  notes:
-    allocates point array for center
-*/
-pointT *qh_getcenter(setT *vertices) {
-  int k;
-  pointT *center, *coord;
-  vertexT *vertex, **vertexp;
-  int count= qh_setsize(vertices);
-
-  if (count < 2) {
-    qh_fprintf(qh ferr, 6003, "qhull internal error (qh_getcenter): not defined for %d points\n", count);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  center= (pointT *)qh_memalloc(qh normal_size);
-  for (k=0; k < qh hull_dim; k++) {
-    coord= center+k;
-    *coord= 0.0;
-    FOREACHvertex_(vertices)
-      *coord += vertex->point[k];
-    *coord /= count;  /* count>=2 by QH6003 */
-  }
-  return(center);
-} /* getcenter */
-
-
-/*---------------------------------
-
-  qh_getcentrum( facet )
-    returns the centrum for a facet as a new point
-
-  notes:
-    allocates the centrum
-*/
-pointT *qh_getcentrum(facetT *facet) {
-  realT dist;
-  pointT *centrum, *point;
-
-  point= qh_getcenter(facet->vertices);
-  zzinc_(Zcentrumtests);
-  qh_distplane(point, facet, &dist);
-  centrum= qh_projectpoint(point, facet, dist);
-  qh_memfree(point, qh normal_size);
-  trace4((qh ferr, 4007, "qh_getcentrum: for f%d, %d vertices dist= %2.2g\n",
-          facet->id, qh_setsize(facet->vertices), dist));
-  return centrum;
-} /* getcentrum */
-
-
-/*---------------------------------
-
-  qh_getdistance( facet, neighbor, mindist, maxdist )
-    returns the maxdist and mindist distance of any vertex from neighbor
-
-  returns:
-    the max absolute value
-
-  design:
-    for each vertex of facet that is not in neighbor
-      test the distance from vertex to neighbor
-*/
-realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist) {
-  vertexT *vertex, **vertexp;
-  realT dist, maxd, mind;
-
-  FOREACHvertex_(facet->vertices)
-    vertex->seen= False;
-  FOREACHvertex_(neighbor->vertices)
-    vertex->seen= True;
-  mind= 0.0;
-  maxd= 0.0;
-  FOREACHvertex_(facet->vertices) {
-    if (!vertex->seen) {
-      zzinc_(Zbestdist);
-      qh_distplane(vertex->point, neighbor, &dist);
-      if (dist < mind)
-        mind= dist;
-      else if (dist > maxd)
-        maxd= dist;
-    }
-  }
-  *mindist= mind;
-  *maxdist= maxd;
-  mind= -mind;
-  if (maxd > mind)
-    return maxd;
-  else
-    return mind;
-} /* getdistance */
-
-
-/*---------------------------------
-
-  qh_normalize( normal, dim, toporient )
-    normalize a vector and report if too small
-    does not use min norm
-
-  see:
-    qh_normalize2
-*/
-void qh_normalize(coordT *normal, int dim, boolT toporient) {
-  qh_normalize2( normal, dim, toporient, NULL, NULL);
-} /* normalize */
-
-/*---------------------------------
-
-  qh_normalize2( normal, dim, toporient, minnorm, ismin )
-    normalize a vector and report if too small
-    qh.MINdenom/MINdenom1 are the upper limits for divide overflow
-
-  returns:
-    normalized vector
-    flips sign if !toporient
-    if minnorm non-NULL,
-      sets ismin if normal < minnorm
-
-  notes:
-    if zero norm
-       sets all elements to sqrt(1.0/dim)
-    if divide by zero (divzero())
-       sets largest element to   +/-1
-       bumps Znearlysingular
-
-  design:
-    computes norm
-    test for minnorm
-    if not near zero
-      normalizes normal
-    else if zero norm
-      sets normal to standard value
-    else
-      uses qh_divzero to normalize
-      if nearzero
-        sets norm to direction of maximum value
-*/
-void qh_normalize2(coordT *normal, int dim, boolT toporient,
-            realT *minnorm, boolT *ismin) {
-  int k;
-  realT *colp, *maxp, norm= 0, temp, *norm1, *norm2, *norm3;
-  boolT zerodiv;
-
-  norm1= normal+1;
-  norm2= normal+2;
-  norm3= normal+3;
-  if (dim == 2)
-    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1));
-  else if (dim == 3)
-    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2));
-  else if (dim == 4) {
-    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
-               + (*norm3)*(*norm3));
-  }else if (dim > 4) {
-    norm= (*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
-               + (*norm3)*(*norm3);
-    for (k=dim-4, colp=normal+4; k--; colp++)
-      norm += (*colp) * (*colp);
-    norm= sqrt(norm);
-  }
-  if (minnorm) {
-    if (norm < *minnorm)
-      *ismin= True;
-    else
-      *ismin= False;
-  }
-  wmin_(Wmindenom, norm);
-  if (norm > qh MINdenom) {
-    if (!toporient)
-      norm= -norm;
-    *normal /= norm;
-    *norm1 /= norm;
-    if (dim == 2)
-      ; /* all done */
-    else if (dim == 3)
-      *norm2 /= norm;
-    else if (dim == 4) {
-      *norm2 /= norm;
-      *norm3 /= norm;
-    }else if (dim >4) {
-      *norm2 /= norm;
-      *norm3 /= norm;
-      for (k=dim-4, colp=normal+4; k--; )
-        *colp++ /= norm;
-    }
-  }else if (norm == 0.0) {
-    temp= sqrt(1.0/dim);
-    for (k=dim, colp=normal; k--; )
-      *colp++ = temp;
-  }else {
-    if (!toporient)
-      norm= -norm;
-    for (k=dim, colp=normal; k--; colp++) { /* k used below */
-      temp= qh_divzero(*colp, norm, qh MINdenom_1, &zerodiv);
-      if (!zerodiv)
-        *colp= temp;
-      else {
-        maxp= qh_maxabsval(normal, dim);
-        temp= ((*maxp * norm >= 0.0) ? 1.0 : -1.0);
-        for (k=dim, colp=normal; k--; colp++)
-          *colp= 0.0;
-        *maxp= temp;
-        zzinc_(Znearlysingular);
-        trace0((qh ferr, 1, "qh_normalize: norm=%2.2g too small during p%d\n",
-               norm, qh furthest_id));
-        return;
-      }
-    }
-  }
-} /* normalize */
-
-
-/*---------------------------------
-
-  qh_projectpoint( point, facet, dist )
-    project point onto a facet by dist
-
-  returns:
-    returns a new point
-
-  notes:
-    if dist= distplane(point,facet)
-      this projects point to hyperplane
-    assumes qh_memfree_() is valid for normal_size
-*/
-pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist) {
-  pointT *newpoint, *np, *normal;
-  int normsize= qh normal_size;
-  int k;
-  void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */
-
-  qh_memalloc_(normsize, freelistp, newpoint, pointT);
-  np= newpoint;
-  normal= facet->normal;
-  for (k=qh hull_dim; k--; )
-    *(np++)= *point++ - dist * *normal++;
-  return(newpoint);
-} /* projectpoint */
-
-
-/*---------------------------------
-
-  qh_setfacetplane( facet )
-    sets the hyperplane for a facet
-    if qh.RANDOMdist, joggles hyperplane
-
-  notes:
-    uses global buffers qh.gm_matrix and qh.gm_row
-    overwrites facet->normal if already defined
-    updates Wnewvertex if PRINTstatistics
-    sets facet->upperdelaunay if upper envelope of Delaunay triangulation
-
-  design:
-    copy vertex coordinates to qh.gm_matrix/gm_row
-    compute determinate
-    if nearzero
-      recompute determinate with gaussian elimination
-      if nearzero
-        force outside orientation by testing interior point
-*/
-void qh_setfacetplane(facetT *facet) {
-  pointT *point;
-  vertexT *vertex, **vertexp;
-  int normsize= qh normal_size;
-  int k,i, oldtrace= 0;
-  realT dist;
-  void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */
-  coordT *coord, *gmcoord;
-  pointT *point0= SETfirstt_(facet->vertices, vertexT)->point;
-  boolT nearzero= False;
-
-  zzinc_(Zsetplane);
-  if (!facet->normal)
-    qh_memalloc_(normsize, freelistp, facet->normal, coordT);
-  if (facet == qh tracefacet) {
-    oldtrace= qh IStracing;
-    qh IStracing= 5;
-    qh_fprintf(qh ferr, 8012, "qh_setfacetplane: facet f%d created.\n", facet->id);
-    qh_fprintf(qh ferr, 8013, "  Last point added to hull was p%d.", qh furthest_id);
-    if (zzval_(Ztotmerge))
-      qh_fprintf(qh ferr, 8014, "  Last merge was #%d.", zzval_(Ztotmerge));
-    qh_fprintf(qh ferr, 8015, "\n\nCurrent summary is:\n");
-      qh_printsummary(qh ferr);
-  }
-  if (qh hull_dim <= 4) {
-    i= 0;
-    if (qh RANDOMdist) {
-      gmcoord= qh gm_matrix;
-      FOREACHvertex_(facet->vertices) {
-        qh gm_row[i++]= gmcoord;
-        coord= vertex->point;
-        for (k=qh hull_dim; k--; )
-          *(gmcoord++)= *coord++ * qh_randomfactor(qh RANDOMa, qh RANDOMb);
-      }
-    }else {
-      FOREACHvertex_(facet->vertices)
-       qh gm_row[i++]= vertex->point;
-    }
-    qh_sethyperplane_det(qh hull_dim, qh gm_row, point0, facet->toporient,
-                facet->normal, &facet->offset, &nearzero);
-  }
-  if (qh hull_dim > 4 || nearzero) {
-    i= 0;
-    gmcoord= qh gm_matrix;
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->point != point0) {
-        qh gm_row[i++]= gmcoord;
-        coord= vertex->point;
-        point= point0;
-        for (k=qh hull_dim; k--; )
-          *(gmcoord++)= *coord++ - *point++;
-      }
-    }
-    qh gm_row[i]= gmcoord;  /* for areasimplex */
-    if (qh RANDOMdist) {
-      gmcoord= qh gm_matrix;
-      for (i=qh hull_dim-1; i--; ) {
-        for (k=qh hull_dim; k--; )
-          *(gmcoord++) *= qh_randomfactor(qh RANDOMa, qh RANDOMb);
-      }
-    }
-    qh_sethyperplane_gauss(qh hull_dim, qh gm_row, point0, facet->toporient,
-                facet->normal, &facet->offset, &nearzero);
-    if (nearzero) {
-      if (qh_orientoutside(facet)) {
-        trace0((qh ferr, 2, "qh_setfacetplane: flipped orientation after testing interior_point during p%d\n", qh furthest_id));
-      /* this is part of using Gaussian Elimination.  For example in 5-d
-           1 1 1 1 0
-           1 1 1 1 1
-           0 0 0 1 0
-           0 1 0 0 0
-           1 0 0 0 0
-           norm= 0.38 0.38 -0.76 0.38 0
-         has a determinate of 1, but g.e. after subtracting pt. 0 has
-         0's in the diagonal, even with full pivoting.  It does work
-         if you subtract pt. 4 instead. */
-      }
-    }
-  }
-  facet->upperdelaunay= False;
-  if (qh DELAUNAY) {
-    if (qh UPPERdelaunay) {     /* matches qh_triangulate_facet and qh.lower_threshold in qh_initbuild */
-      if (facet->normal[qh hull_dim -1] >= qh ANGLEround * qh_ZEROdelaunay)
-        facet->upperdelaunay= True;
-    }else {
-      if (facet->normal[qh hull_dim -1] > -qh ANGLEround * qh_ZEROdelaunay)
-        facet->upperdelaunay= True;
-    }
-  }
-  if (qh PRINTstatistics || qh IStracing || qh TRACElevel || qh JOGGLEmax < REALmax) {
-    qh old_randomdist= qh RANDOMdist;
-    qh RANDOMdist= False;
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->point != point0) {
-        boolT istrace= False;
-        zinc_(Zdiststat);
-        qh_distplane(vertex->point, facet, &dist);
-        dist= fabs_(dist);
-        zinc_(Znewvertex);
-        wadd_(Wnewvertex, dist);
-        if (dist > wwval_(Wnewvertexmax)) {
-          wwval_(Wnewvertexmax)= dist;
-          if (dist > qh max_outside) {
-            qh max_outside= dist;  /* used by qh_maxouter() */
-            if (dist > qh TRACEdist)
-              istrace= True;
-          }
-        }else if (-dist > qh TRACEdist)
-          istrace= True;
-        if (istrace) {
-          qh_fprintf(qh ferr, 8016, "qh_setfacetplane: ====== vertex p%d(v%d) increases max_outside to %2.2g for new facet f%d last p%d\n",
-                qh_pointid(vertex->point), vertex->id, dist, facet->id, qh furthest_id);
-          qh_errprint("DISTANT", facet, NULL, NULL, NULL);
-        }
-      }
-    }
-    qh RANDOMdist= qh old_randomdist;
-  }
-  if (qh IStracing >= 3) {
-    qh_fprintf(qh ferr, 8017, "qh_setfacetplane: f%d offset %2.2g normal: ",
-             facet->id, facet->offset);
-    for (k=0; k < qh hull_dim; k++)
-      qh_fprintf(qh ferr, 8018, "%2.2g ", facet->normal[k]);
-    qh_fprintf(qh ferr, 8019, "\n");
-  }
-  if (facet == qh tracefacet)
-    qh IStracing= oldtrace;
-} /* setfacetplane */
-
-
-/*---------------------------------
-
-  qh_sethyperplane_det( dim, rows, point0, toporient, normal, offset, nearzero )
-    given dim X dim array indexed by rows[], one row per point,
-        toporient(flips all signs),
-        and point0 (any row)
-    set normalized hyperplane equation from oriented simplex
-
-  returns:
-    normal (normalized)
-    offset (places point0 on the hyperplane)
-    sets nearzero if hyperplane not through points
-
-  notes:
-    only defined for dim == 2..4
-    rows[] is not modified
-    solves det(P-V_0, V_n-V_0, ..., V_1-V_0)=0, i.e. every point is on hyperplane
-    see Bower & Woodworth, A programmer's geometry, Butterworths 1983.
-
-  derivation of 3-d minnorm
-    Goal: all vertices V_i within qh.one_merge of hyperplane
-    Plan: exactly translate the facet so that V_0 is the origin
-          exactly rotate the facet so that V_1 is on the x-axis and y_2=0.
-          exactly rotate the effective perturbation to only effect n_0
-             this introduces a factor of sqrt(3)
-    n_0 = ((y_2-y_0)*(z_1-z_0) - (z_2-z_0)*(y_1-y_0)) / norm
-    Let M_d be the max coordinate difference
-    Let M_a be the greater of M_d and the max abs. coordinate
-    Let u be machine roundoff and distround be max error for distance computation
-    The max error for n_0 is sqrt(3) u M_a M_d / norm.  n_1 is approx. 1 and n_2 is approx. 0
-    The max error for distance of V_1 is sqrt(3) u M_a M_d M_d / norm.  Offset=0 at origin
-    Then minnorm = 1.8 u M_a M_d M_d / qh.ONEmerge
-    Note that qh.one_merge is approx. 45.5 u M_a and norm is usually about M_d M_d
-
-  derivation of 4-d minnorm
-    same as above except rotate the facet so that V_1 on x-axis and w_2, y_3, w_3=0
-     [if two vertices fixed on x-axis, can rotate the other two in yzw.]
-    n_0 = det3_(...) = y_2 det2_(z_1, w_1, z_3, w_3) = - y_2 w_1 z_3
-     [all other terms contain at least two factors nearly zero.]
-    The max error for n_0 is sqrt(4) u M_a M_d M_d / norm
-    Then minnorm = 2 u M_a M_d M_d M_d / qh.ONEmerge
-    Note that qh.one_merge is approx. 82 u M_a and norm is usually about M_d M_d M_d
-*/
-void qh_sethyperplane_det(int dim, coordT **rows, coordT *point0,
-          boolT toporient, coordT *normal, realT *offset, boolT *nearzero) {
-  realT maxround, dist;
-  int i;
-  pointT *point;
-
-
-  if (dim == 2) {
-    normal[0]= dY(1,0);
-    normal[1]= dX(0,1);
-    qh_normalize2(normal, dim, toporient, NULL, NULL);
-    *offset= -(point0[0]*normal[0]+point0[1]*normal[1]);
-    *nearzero= False;  /* since nearzero norm => incident points */
-  }else if (dim == 3) {
-    normal[0]= det2_(dY(2,0), dZ(2,0),
-                     dY(1,0), dZ(1,0));
-    normal[1]= det2_(dX(1,0), dZ(1,0),
-                     dX(2,0), dZ(2,0));
-    normal[2]= det2_(dX(2,0), dY(2,0),
-                     dX(1,0), dY(1,0));
-    qh_normalize2(normal, dim, toporient, NULL, NULL);
-    *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
-               + point0[2]*normal[2]);
-    maxround= qh DISTround;
-    for (i=dim; i--; ) {
-      point= rows[i];
-      if (point != point0) {
-        dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
-               + point[2]*normal[2]);
-        if (dist > maxround || dist < -maxround) {
-          *nearzero= True;
-          break;
-        }
-      }
-    }
-  }else if (dim == 4) {
-    normal[0]= - det3_(dY(2,0), dZ(2,0), dW(2,0),
-                        dY(1,0), dZ(1,0), dW(1,0),
-                        dY(3,0), dZ(3,0), dW(3,0));
-    normal[1]=   det3_(dX(2,0), dZ(2,0), dW(2,0),
-                        dX(1,0), dZ(1,0), dW(1,0),
-                        dX(3,0), dZ(3,0), dW(3,0));
-    normal[2]= - det3_(dX(2,0), dY(2,0), dW(2,0),
-                        dX(1,0), dY(1,0), dW(1,0),
-                        dX(3,0), dY(3,0), dW(3,0));
-    normal[3]=   det3_(dX(2,0), dY(2,0), dZ(2,0),
-                        dX(1,0), dY(1,0), dZ(1,0),
-                        dX(3,0), dY(3,0), dZ(3,0));
-    qh_normalize2(normal, dim, toporient, NULL, NULL);
-    *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
-               + point0[2]*normal[2] + point0[3]*normal[3]);
-    maxround= qh DISTround;
-    for (i=dim; i--; ) {
-      point= rows[i];
-      if (point != point0) {
-        dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
-               + point[2]*normal[2] + point[3]*normal[3]);
-        if (dist > maxround || dist < -maxround) {
-          *nearzero= True;
-          break;
-        }
-      }
-    }
-  }
-  if (*nearzero) {
-    zzinc_(Zminnorm);
-    trace0((qh ferr, 3, "qh_sethyperplane_det: degenerate norm during p%d.\n", qh furthest_id));
-    zzinc_(Znearlysingular);
-  }
-} /* sethyperplane_det */
-
-
-/*---------------------------------
-
-  qh_sethyperplane_gauss( dim, rows, point0, toporient, normal, offset, nearzero )
-    given(dim-1) X dim array of rows[i]= V_{i+1} - V_0 (point0)
-    set normalized hyperplane equation from oriented simplex
-
-  returns:
-    normal (normalized)
-    offset (places point0 on the hyperplane)
-
-  notes:
-    if nearzero
-      orientation may be incorrect because of incorrect sign flips in gausselim
-    solves [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0 .. 0 1]
-        or [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0]
-    i.e., N is normal to the hyperplane, and the unnormalized
-        distance to [0 .. 1] is either 1 or   0
-
-  design:
-    perform gaussian elimination
-    flip sign for negative values
-    perform back substitution
-    normalize result
-    compute offset
-*/
-void qh_sethyperplane_gauss(int dim, coordT **rows, pointT *point0,
-                boolT toporient, coordT *normal, coordT *offset, boolT *nearzero) {
-  coordT *pointcoord, *normalcoef;
-  int k;
-  boolT sign= toporient, nearzero2= False;
-
-  qh_gausselim(rows, dim-1, dim, &sign, nearzero);
-  for (k=dim-1; k--; ) {
-    if ((rows[k])[k] < 0)
-      sign ^= 1;
-  }
-  if (*nearzero) {
-    zzinc_(Znearlysingular);
-    trace0((qh ferr, 4, "qh_sethyperplane_gauss: nearly singular or axis parallel hyperplane during p%d.\n", qh furthest_id));
-    qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
-  }else {
-    qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
-    if (nearzero2) {
-      zzinc_(Znearlysingular);
-      trace0((qh ferr, 5, "qh_sethyperplane_gauss: singular or axis parallel hyperplane at normalization during p%d.\n", qh furthest_id));
-    }
-  }
-  if (nearzero2)
-    *nearzero= True;
-  qh_normalize2(normal, dim, True, NULL, NULL);
-  pointcoord= point0;
-  normalcoef= normal;
-  *offset= -(*pointcoord++ * *normalcoef++);
-  for (k=dim-1; k--; )
-    *offset -= *pointcoord++ * *normalcoef++;
-} /* sethyperplane_gauss */
-
-
-
diff --git a/extern/libqhull/geom.h b/extern/libqhull/geom.h
deleted file mode 100644
index 16ef48d2d7ae..000000000000
--- a/extern/libqhull/geom.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
  ---------------------------------
-
-  geom.h
-    header file for geometric routines
-
-   see qh-geom.htm and geom.c
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/geom.h#1 $$Change: 1981 $
-   $DateTime: 2015/09/28 20:26:32 $$Author: bbarber $
-*/
-
-#ifndef qhDEFgeom
-#define qhDEFgeom 1
-
-#include "libqhull.h"
-
-/* ============ -macros- ======================== */
-
-/*----------------------------------
-
-  fabs_(a)
-    returns the absolute value of a
-*/
-#define fabs_( a ) ((( a ) < 0 ) ? -( a ):( a ))
-
-/*----------------------------------
-
-  fmax_(a,b)
-    returns the maximum value of a and b
-*/
-#define fmax_( a,b )  ( ( a ) < ( b ) ? ( b ) : ( a ) )
-
-/*----------------------------------
-
-  fmin_(a,b)
-    returns the minimum value of a and b
-*/
-#define fmin_( a,b )  ( ( a ) > ( b ) ? ( b ) : ( a ) )
-
-/*----------------------------------
-
-  maximize_(maxval, val)
-    set maxval to val if val is greater than maxval
-*/
-#define maximize_( maxval, val ) { if (( maxval ) < ( val )) ( maxval )= ( val ); }
-
-/*----------------------------------
-
-  minimize_(minval, val)
-    set minval to val if val is less than minval
-*/
-#define minimize_( minval, val ) { if (( minval ) > ( val )) ( minval )= ( val ); }
-
-/*----------------------------------
-
-  det2_(a1, a2,
-        b1, b2)
-
-    compute a 2-d determinate
-*/
-#define det2_( a1,a2,b1,b2 ) (( a1 )*( b2 ) - ( a2 )*( b1 ))
-
-/*----------------------------------
-
-  det3_(a1, a2, a3,
-       b1, b2, b3,
-       c1, c2, c3)
-
-    compute a 3-d determinate
-*/
-#define det3_( a1,a2,a3,b1,b2,b3,c1,c2,c3 ) ( ( a1 )*det2_( b2,b3,c2,c3 ) \
-                - ( b1 )*det2_( a2,a3,c2,c3 ) + ( c1 )*det2_( a2,a3,b2,b3 ) )
-
-/*----------------------------------
-
-  dX( p1, p2 )
-  dY( p1, p2 )
-  dZ( p1, p2 )
-
-    given two indices into rows[],
-
-    compute the difference between X, Y, or Z coordinates
-*/
-#define dX( p1,p2 )  ( *( rows[p1] ) - *( rows[p2] ))
-#define dY( p1,p2 )  ( *( rows[p1]+1 ) - *( rows[p2]+1 ))
-#define dZ( p1,p2 )  ( *( rows[p1]+2 ) - *( rows[p2]+2 ))
-#define dW( p1,p2 )  ( *( rows[p1]+3 ) - *( rows[p2]+3 ))
-
-/*============= prototypes in alphabetical order, infrequent at end ======= */
-
-void    qh_backnormal(realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero);
-void    qh_distplane(pointT *point, facetT *facet, realT *dist);
-facetT *qh_findbest(pointT *point, facetT *startfacet,
-                     boolT bestoutside, boolT isnewfacets, boolT noupper,
-                     realT *dist, boolT *isoutside, int *numpart);
-facetT *qh_findbesthorizon(boolT ischeckmax, pointT *point,
-                     facetT *startfacet, boolT noupper, realT *bestdist, int *numpart);
-facetT *qh_findbestnew(pointT *point, facetT *startfacet, realT *dist,
-                     boolT bestoutside, boolT *isoutside, int *numpart);
-void    qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero);
-realT   qh_getangle(pointT *vect1, pointT *vect2);
-pointT *qh_getcenter(setT *vertices);
-pointT *qh_getcentrum(facetT *facet);
-realT   qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist);
-void    qh_normalize(coordT *normal, int dim, boolT toporient);
-void    qh_normalize2(coordT *normal, int dim, boolT toporient,
-            realT *minnorm, boolT *ismin);
-pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist);
-
-void    qh_setfacetplane(facetT *newfacets);
-void    qh_sethyperplane_det(int dim, coordT **rows, coordT *point0,
-              boolT toporient, coordT *normal, realT *offset, boolT *nearzero);
-void    qh_sethyperplane_gauss(int dim, coordT **rows, pointT *point0,
-             boolT toporient, coordT *normal, coordT *offset, boolT *nearzero);
-boolT   qh_sharpnewfacets(void);
-
-/*========= infrequently used code in geom2.c =============*/
-
-coordT *qh_copypoints(coordT *points, int numpoints, int dimension);
-void    qh_crossproduct(int dim, realT vecA[3], realT vecB[3], realT vecC[3]);
-realT   qh_determinant(realT **rows, int dim, boolT *nearzero);
-realT   qh_detjoggle(pointT *points, int numpoints, int dimension);
-void    qh_detroundoff(void);
-realT   qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero);
-realT   qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp);
-realT   qh_distround(int dimension, realT maxabs, realT maxsumabs);
-realT   qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv);
-realT   qh_facetarea(facetT *facet);
-realT   qh_facetarea_simplex(int dim, coordT *apex, setT *vertices,
-          vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset);
-pointT *qh_facetcenter(setT *vertices);
-facetT *qh_findgooddist(pointT *point, facetT *facetA, realT *distp, facetT **facetlist);
-void    qh_getarea(facetT *facetlist);
-boolT   qh_gram_schmidt(int dim, realT **rows);
-boolT   qh_inthresholds(coordT *normal, realT *angle);
-void    qh_joggleinput(void);
-realT  *qh_maxabsval(realT *normal, int dim);
-setT   *qh_maxmin(pointT *points, int numpoints, int dimension);
-realT   qh_maxouter(void);
-void    qh_maxsimplex(int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex);
-realT   qh_minabsval(realT *normal, int dim);
-int     qh_mindiff(realT *vecA, realT *vecB, int dim);
-boolT   qh_orientoutside(facetT *facet);
-void    qh_outerinner(facetT *facet, realT *outerplane, realT *innerplane);
-coordT  qh_pointdist(pointT *point1, pointT *point2, int dim);
-void    qh_printmatrix(FILE *fp, const char *string, realT **rows, int numrow, int numcol);
-void    qh_printpoints(FILE *fp, const char *string, setT *points);
-void    qh_projectinput(void);
-void    qh_projectpoints(signed char *project, int n, realT *points,
-             int numpoints, int dim, realT *newpoints, int newdim);
-void    qh_rotateinput(realT **rows);
-void    qh_rotatepoints(realT *points, int numpoints, int dim, realT **rows);
-void    qh_scaleinput(void);
-void    qh_scalelast(coordT *points, int numpoints, int dim, coordT low,
-                   coordT high, coordT newhigh);
-void    qh_scalepoints(pointT *points, int numpoints, int dim,
-                realT *newlows, realT *newhighs);
-boolT   qh_sethalfspace(int dim, coordT *coords, coordT **nextp,
-              coordT *normal, coordT *offset, coordT *feasible);
-coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feasible);
-pointT *qh_voronoi_center(int dim, setT *points);
-
-#endif /* qhDEFgeom */
-
-
-
diff --git a/extern/libqhull/geom2.c b/extern/libqhull/geom2.c
deleted file mode 100644
index c32a97daeadf..000000000000
--- a/extern/libqhull/geom2.c
+++ /dev/null
@@ -1,2094 +0,0 @@
-/*
  ---------------------------------
-
-
-   geom2.c
-   infrequently used geometric routines of qhull
-
-   see qh-geom.htm and geom.h
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/geom2.c#6 $$Change: 2065 $
-   $DateTime: 2016/01/18 13:51:04 $$Author: bbarber $
-
-   frequently used code goes into geom.c
-*/
-
-#include "qhull_a.h"
-
-/*================== functions in alphabetic order ============*/
-
-/*---------------------------------
-
-  qh_copypoints( points, numpoints, dimension)
-    return qh_malloc'd copy of points
-  notes:
-    qh_free the returned points to avoid a memory leak
-*/
-coordT *qh_copypoints(coordT *points, int numpoints, int dimension) {
-  int size;
-  coordT *newpoints;
-
-  size= numpoints * dimension * (int)sizeof(coordT);
-  if (!(newpoints=(coordT*)qh_malloc((size_t)size))) {
-    qh_fprintf(qh ferr, 6004, "qhull error: insufficient memory to copy %d points\n",
-        numpoints);
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  memcpy((char *)newpoints, (char *)points, (size_t)size); /* newpoints!=0 by QH6004 */
-  return newpoints;
-} /* copypoints */
-
-/*---------------------------------
-
-  qh_crossproduct( dim, vecA, vecB, vecC )
-    crossproduct of 2 dim vectors
-    C= A x B
-
-  notes:
-    from Glasner, Graphics Gems I, p. 639
-    only defined for dim==3
-*/
-void qh_crossproduct(int dim, realT vecA[3], realT vecB[3], realT vecC[3]){
-
-  if (dim == 3) {
-    vecC[0]=   det2_(vecA[1], vecA[2],
-                     vecB[1], vecB[2]);
-    vecC[1]= - det2_(vecA[0], vecA[2],
-                     vecB[0], vecB[2]);
-    vecC[2]=   det2_(vecA[0], vecA[1],
-                     vecB[0], vecB[1]);
-  }
-} /* vcross */
-
-/*---------------------------------
-
-  qh_determinant( rows, dim, nearzero )
-    compute signed determinant of a square matrix
-    uses qh.NEARzero to test for degenerate matrices
-
-  returns:
-    determinant
-    overwrites rows and the matrix
-    if dim == 2 or 3
-      nearzero iff determinant < qh NEARzero[dim-1]
-      (!quite correct, not critical)
-    if dim >= 4
-      nearzero iff diagonal[k] < qh NEARzero[k]
-*/
-realT qh_determinant(realT **rows, int dim, boolT *nearzero) {
-  realT det=0;
-  int i;
-  boolT sign= False;
-
-  *nearzero= False;
-  if (dim < 2) {
-    qh_fprintf(qh ferr, 6005, "qhull internal error (qh_determinate): only implemented for dimension >= 2\n");
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }else if (dim == 2) {
-    det= det2_(rows[0][0], rows[0][1],
-                 rows[1][0], rows[1][1]);
-    if (fabs_(det) < 10*qh NEARzero[1])  /* not really correct, what should this be? */
-      *nearzero= True;
-  }else if (dim == 3) {
-    det= det3_(rows[0][0], rows[0][1], rows[0][2],
-                 rows[1][0], rows[1][1], rows[1][2],
-                 rows[2][0], rows[2][1], rows[2][2]);
-    if (fabs_(det) < 10*qh NEARzero[2])  /* what should this be?  det 5.5e-12 was flat for qh_maxsimplex of qdelaunay 0,0 27,27 -36,36 -9,63  */
-      *nearzero= True;
-  }else {
-    qh_gausselim(rows, dim, dim, &sign, nearzero);  /* if nearzero, diagonal still ok*/
-    det= 1.0;
-    for (i=dim; i--; )
-      det *= (rows[i])[i];
-    if (sign)
-      det= -det;
-  }
-  return det;
-} /* determinant */
-
-/*---------------------------------
-
-  qh_detjoggle( points, numpoints, dimension )
-    determine default max joggle for point array
-      as qh_distround * qh_JOGGLEdefault
-
-  returns:
-    initial value for JOGGLEmax from points and REALepsilon
-
-  notes:
-    computes DISTround since qh_maxmin not called yet
-    if qh SCALElast, last dimension will be scaled later to MAXwidth
-
-    loop duplicated from qh_maxmin
-*/
-realT qh_detjoggle(pointT *points, int numpoints, int dimension) {
-  realT abscoord, distround, joggle, maxcoord, mincoord;
-  pointT *point, *pointtemp;
-  realT maxabs= -REALmax;
-  realT sumabs= 0;
-  realT maxwidth= 0;
-  int k;
-
-  for (k=0; k < dimension; k++) {
-    if (qh SCALElast && k == dimension-1)
-      abscoord= maxwidth;
-    else if (qh DELAUNAY && k == dimension-1) /* will qh_setdelaunay() */
-      abscoord= 2 * maxabs * maxabs;  /* may be low by qh hull_dim/2 */
-    else {
-      maxcoord= -REALmax;
-      mincoord= REALmax;
-      FORALLpoint_(points, numpoints) {
-        maximize_(maxcoord, point[k]);
-        minimize_(mincoord, point[k]);
-      }
-      maximize_(maxwidth, maxcoord-mincoord);
-      abscoord= fmax_(maxcoord, -mincoord);
-    }
-    sumabs += abscoord;
-    maximize_(maxabs, abscoord);
-  } /* for k */
-  distround= qh_distround(qh hull_dim, maxabs, sumabs);
-  joggle= distround * qh_JOGGLEdefault;
-  maximize_(joggle, REALepsilon * qh_JOGGLEdefault);
-  trace2((qh ferr, 2001, "qh_detjoggle: joggle=%2.2g maxwidth=%2.2g\n", joggle, maxwidth));
-  return joggle;
-} /* detjoggle */
-
-/*---------------------------------
-
-  qh_detroundoff()
-    determine maximum roundoff errors from
-      REALepsilon, REALmax, REALmin, qh.hull_dim, qh.MAXabs_coord,
-      qh.MAXsumcoord, qh.MAXwidth, qh.MINdenom_1
-
-    accounts for qh.SETroundoff, qh.RANDOMdist, qh MERGEexact
-      qh.premerge_cos, qh.postmerge_cos, qh.premerge_centrum,
-      qh.postmerge_centrum, qh.MINoutside,
-      qh_RATIOnearinside, qh_COPLANARratio, qh_WIDEcoplanar
-
-  returns:
-    sets qh.DISTround, etc. (see below)
-    appends precision constants to qh.qhull_options
-
-  see:
-    qh_maxmin() for qh.NEARzero
-
-  design:
-    determine qh.DISTround for distance computations
-    determine minimum denominators for qh_divzero
-    determine qh.ANGLEround for angle computations
-    adjust qh.premerge_cos,... for roundoff error
-    determine qh.ONEmerge for maximum error due to a single merge
-    determine qh.NEARinside, qh.MAXcoplanar, qh.MINvisible,
-      qh.MINoutside, qh.WIDEfacet
-    initialize qh.max_vertex and qh.minvertex
-*/
-void qh_detroundoff(void) {
-
-  qh_option("_max-width", NULL, &qh MAXwidth);
-  if (!qh SETroundoff) {
-    qh DISTround= qh_distround(qh hull_dim, qh MAXabs_coord, qh MAXsumcoord);
-    if (qh RANDOMdist)
-      qh DISTround += qh RANDOMfactor * qh MAXabs_coord;
-    qh_option("Error-roundoff", NULL, &qh DISTround);
-  }
-  qh MINdenom= qh MINdenom_1 * qh MAXabs_coord;
-  qh MINdenom_1_2= sqrt(qh MINdenom_1 * qh hull_dim) ;  /* if will be normalized */
-  qh MINdenom_2= qh MINdenom_1_2 * qh MAXabs_coord;
-                                              /* for inner product */
-  qh ANGLEround= 1.01 * qh hull_dim * REALepsilon;
-  if (qh RANDOMdist)
-    qh ANGLEround += qh RANDOMfactor;
-  if (qh premerge_cos < REALmax/2) {
-    qh premerge_cos -= qh ANGLEround;
-    if (qh RANDOMdist)
-      qh_option("Angle-premerge-with-random", NULL, &qh premerge_cos);
-  }
-  if (qh postmerge_cos < REALmax/2) {
-    qh postmerge_cos -= qh ANGLEround;
-    if (qh RANDOMdist)
-      qh_option("Angle-postmerge-with-random", NULL, &qh postmerge_cos);
-  }
-  qh premerge_centrum += 2 * qh DISTround;    /*2 for centrum and distplane()*/
-  qh postmerge_centrum += 2 * qh DISTround;
-  if (qh RANDOMdist && (qh MERGEexact || qh PREmerge))
-    qh_option("Centrum-premerge-with-random", NULL, &qh premerge_centrum);
-  if (qh RANDOMdist && qh POSTmerge)
-    qh_option("Centrum-postmerge-with-random", NULL, &qh postmerge_centrum);
-  { /* compute ONEmerge, max vertex offset for merging simplicial facets */
-    realT maxangle= 1.0, maxrho;
-
-    minimize_(maxangle, qh premerge_cos);
-    minimize_(maxangle, qh postmerge_cos);
-    /* max diameter * sin theta + DISTround for vertex to its hyperplane */
-    qh ONEmerge= sqrt((realT)qh hull_dim) * qh MAXwidth *
-      sqrt(1.0 - maxangle * maxangle) + qh DISTround;
-    maxrho= qh hull_dim * qh premerge_centrum + qh DISTround;
-    maximize_(qh ONEmerge, maxrho);
-    maxrho= qh hull_dim * qh postmerge_centrum + qh DISTround;
-    maximize_(qh ONEmerge, maxrho);
-    if (qh MERGING)
-      qh_option("_one-merge", NULL, &qh ONEmerge);
-  }
-  qh NEARinside= qh ONEmerge * qh_RATIOnearinside; /* only used if qh KEEPnearinside */
-  if (qh JOGGLEmax < REALmax/2 && (qh KEEPcoplanar || qh KEEPinside)) {
-    realT maxdist;             /* adjust qh.NEARinside for joggle */
-    qh KEEPnearinside= True;
-    maxdist= sqrt((realT)qh hull_dim) * qh JOGGLEmax + qh DISTround;
-    maxdist= 2*maxdist;        /* vertex and coplanar point can joggle in opposite directions */
-    maximize_(qh NEARinside, maxdist);  /* must agree with qh_nearcoplanar() */
-  }
-  if (qh KEEPnearinside)
-    qh_option("_near-inside", NULL, &qh NEARinside);
-  if (qh JOGGLEmax < qh DISTround) {
-    qh_fprintf(qh ferr, 6006, "qhull error: the joggle for 'QJn', %.2g, is below roundoff for distance computations, %.2g\n",
-         qh JOGGLEmax, qh DISTround);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (qh MINvisible > REALmax/2) {
-    if (!qh MERGING)
-      qh MINvisible= qh DISTround;
-    else if (qh hull_dim <= 3)
-      qh MINvisible= qh premerge_centrum;
-    else
-      qh MINvisible= qh_COPLANARratio * qh premerge_centrum;
-    if (qh APPROXhull && qh MINvisible > qh MINoutside)
-      qh MINvisible= qh MINoutside;
-    qh_option("Visible-distance", NULL, &qh MINvisible);
-  }
-  if (qh MAXcoplanar > REALmax/2) {
-    qh MAXcoplanar= qh MINvisible;
-    qh_option("U-coplanar-distance", NULL, &qh MAXcoplanar);
-  }
-  if (!qh APPROXhull) {             /* user may specify qh MINoutside */
-    qh MINoutside= 2 * qh MINvisible;
-    if (qh premerge_cos < REALmax/2)
-      maximize_(qh MINoutside, (1- qh premerge_cos) * qh MAXabs_coord);
-    qh_option("Width-outside", NULL, &qh MINoutside);
-  }
-  qh WIDEfacet= qh MINoutside;
-  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MAXcoplanar);
-  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MINvisible);
-  qh_option("_wide-facet", NULL, &qh WIDEfacet);
-  if (qh MINvisible > qh MINoutside + 3 * REALepsilon
-  && !qh BESToutside && !qh FORCEoutput)
-    qh_fprintf(qh ferr, 7001, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g.  Flipped facets are likely.\n",
-             qh MINvisible, qh MINoutside);
-  qh max_vertex= qh DISTround;
-  qh min_vertex= -qh DISTround;
-  /* numeric constants reported in printsummary */
-} /* detroundoff */
-
-/*---------------------------------
-
-  qh_detsimplex( apex, points, dim, nearzero )
-    compute determinant of a simplex with point apex and base points
-
-  returns:
-     signed determinant and nearzero from qh_determinant
-
-  notes:
-     uses qh.gm_matrix/qh.gm_row (assumes they're big enough)
-
-  design:
-    construct qm_matrix by subtracting apex from points
-    compute determinate
-*/
-realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero) {
-  pointT *coorda, *coordp, *gmcoord, *point, **pointp;
-  coordT **rows;
-  int k,  i=0;
-  realT det;
-
-  zinc_(Zdetsimplex);
-  gmcoord= qh gm_matrix;
-  rows= qh gm_row;
-  FOREACHpoint_(points) {
-    if (i == dim)
-      break;
-    rows[i++]= gmcoord;
-    coordp= point;
-    coorda= apex;
-    for (k=dim; k--; )
-      *(gmcoord++)= *coordp++ - *coorda++;
-  }
-  if (i < dim) {
-    qh_fprintf(qh ferr, 6007, "qhull internal error (qh_detsimplex): #points %d < dimension %d\n",
-               i, dim);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  det= qh_determinant(rows, dim, nearzero);
-  trace2((qh ferr, 2002, "qh_detsimplex: det=%2.2g for point p%d, dim %d, nearzero? %d\n",
-          det, qh_pointid(apex), dim, *nearzero));
-  return det;
-} /* detsimplex */
-
-/*---------------------------------
-
-  qh_distnorm( dim, point, normal, offset )
-    return distance from point to hyperplane at normal/offset
-
-  returns:
-    dist
-
-  notes:
-    dist > 0 if point is outside of hyperplane
-
-  see:
-    qh_distplane in geom.c
-*/
-realT qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp) {
-  coordT *normalp= normal, *coordp= point;
-  realT dist;
-  int k;
-
-  dist= *offsetp;
-  for (k=dim; k--; )
-    dist += *(coordp++) * *(normalp++);
-  return dist;
-} /* distnorm */
-
-/*---------------------------------
-
-  qh_distround(dimension, maxabs, maxsumabs )
-    compute maximum round-off error for a distance computation
-      to a normalized hyperplane
-    maxabs is the maximum absolute value of a coordinate
-    maxsumabs is the maximum possible sum of absolute coordinate values
-
-  returns:
-    max dist round for REALepsilon
-
-  notes:
-    calculate roundoff error according to Golub & van Loan, 1983, Lemma 3.2-1, "Rounding Errors"
-    use sqrt(dim) since one vector is normalized
-      or use maxsumabs since one vector is < 1
-*/
-realT qh_distround(int dimension, realT maxabs, realT maxsumabs) {
-  realT maxdistsum, maxround;
-
-  maxdistsum= sqrt((realT)dimension) * maxabs;
-  minimize_( maxdistsum, maxsumabs);
-  maxround= REALepsilon * (dimension * maxdistsum * 1.01 + maxabs);
-              /* adds maxabs for offset */
-  trace4((qh ferr, 4008, "qh_distround: %2.2g maxabs %2.2g maxsumabs %2.2g maxdistsum %2.2g\n",
-                 maxround, maxabs, maxsumabs, maxdistsum));
-  return maxround;
-} /* distround */
-
-/*---------------------------------
-
-  qh_divzero( numer, denom, mindenom1, zerodiv )
-    divide by a number that's nearly zero
-    mindenom1= minimum denominator for dividing into 1.0
-
-  returns:
-    quotient
-    sets zerodiv and returns 0.0 if it would overflow
-
-  design:
-    if numer is nearly zero and abs(numer) < abs(denom)
-      return numer/denom
-    else if numer is nearly zero
-      return 0 and zerodiv
-    else if denom/numer non-zero
-      return numer/denom
-    else
-      return 0 and zerodiv
-*/
-realT qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv) {
-  realT temp, numerx, denomx;
-
-
-  if (numer < mindenom1 && numer > -mindenom1) {
-    numerx= fabs_(numer);
-    denomx= fabs_(denom);
-    if (numerx < denomx) {
-      *zerodiv= False;
-      return numer/denom;
-    }else {
-      *zerodiv= True;
-      return 0.0;
-    }
-  }
-  temp= denom/numer;
-  if (temp > mindenom1 || temp < -mindenom1) {
-    *zerodiv= False;
-    return numer/denom;
-  }else {
-    *zerodiv= True;
-    return 0.0;
-  }
-} /* divzero */
-
-
-/*---------------------------------
-
-  qh_facetarea( facet )
-    return area for a facet
-
-  notes:
-    if non-simplicial,
-      uses centrum to triangulate facet and sums the projected areas.
-    if (qh DELAUNAY),
-      computes projected area instead for last coordinate
-    assumes facet->normal exists
-    projecting tricoplanar facets to the hyperplane does not appear to make a difference
-
-  design:
-    if simplicial
-      compute area
-    else
-      for each ridge
-        compute area from centrum to ridge
-    negate area if upper Delaunay facet
-*/
-realT qh_facetarea(facetT *facet) {
-  vertexT *apex;
-  pointT *centrum;
-  realT area= 0.0;
-  ridgeT *ridge, **ridgep;
-
-  if (facet->simplicial) {
-    apex= SETfirstt_(facet->vertices, vertexT);
-    area= qh_facetarea_simplex(qh hull_dim, apex->point, facet->vertices,
-                    apex, facet->toporient, facet->normal, &facet->offset);
-  }else {
-    if (qh CENTERtype == qh_AScentrum)
-      centrum= facet->center;
-    else
-      centrum= qh_getcentrum(facet);
-    FOREACHridge_(facet->ridges)
-      area += qh_facetarea_simplex(qh hull_dim, centrum, ridge->vertices,
-                 NULL, (boolT)(ridge->top == facet),  facet->normal, &facet->offset);
-    if (qh CENTERtype != qh_AScentrum)
-      qh_memfree(centrum, qh normal_size);
-  }
-  if (facet->upperdelaunay && qh DELAUNAY)
-    area= -area;  /* the normal should be [0,...,1] */
-  trace4((qh ferr, 4009, "qh_facetarea: f%d area %2.2g\n", facet->id, area));
-  return area;
-} /* facetarea */
-
-/*---------------------------------
-
-  qh_facetarea_simplex( dim, apex, vertices, notvertex, toporient, normal, offset )
-    return area for a simplex defined by
-      an apex, a base of vertices, an orientation, and a unit normal
-    if simplicial or tricoplanar facet,
-      notvertex is defined and it is skipped in vertices
-
-  returns:
-    computes area of simplex projected to plane [normal,offset]
-    returns 0 if vertex too far below plane (qh WIDEfacet)
-      vertex can't be apex of tricoplanar facet
-
-  notes:
-    if (qh DELAUNAY),
-      computes projected area instead for last coordinate
-    uses qh gm_matrix/gm_row and qh hull_dim
-    helper function for qh_facetarea
-
-  design:
-    if Notvertex
-      translate simplex to apex
-    else
-      project simplex to normal/offset
-      translate simplex to apex
-    if Delaunay
-      set last row/column to 0 with -1 on diagonal
-    else
-      set last row to Normal
-    compute determinate
-    scale and flip sign for area
-*/
-realT qh_facetarea_simplex(int dim, coordT *apex, setT *vertices,
-        vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset) {
-  pointT *coorda, *coordp, *gmcoord;
-  coordT **rows, *normalp;
-  int k,  i=0;
-  realT area, dist;
-  vertexT *vertex, **vertexp;
-  boolT nearzero;
-
-  gmcoord= qh gm_matrix;
-  rows= qh gm_row;
-  FOREACHvertex_(vertices) {
-    if (vertex == notvertex)
-      continue;
-    rows[i++]= gmcoord;
-    coorda= apex;
-    coordp= vertex->point;
-    normalp= normal;
-    if (notvertex) {
-      for (k=dim; k--; )
-        *(gmcoord++)= *coordp++ - *coorda++;
-    }else {
-      dist= *offset;
-      for (k=dim; k--; )
-        dist += *coordp++ * *normalp++;
-      if (dist < -qh WIDEfacet) {
-        zinc_(Znoarea);
-        return 0.0;
-      }
-      coordp= vertex->point;
-      normalp= normal;
-      for (k=dim; k--; )
-        *(gmcoord++)= (*coordp++ - dist * *normalp++) - *coorda++;
-    }
-  }
-  if (i != dim-1) {
-    qh_fprintf(qh ferr, 6008, "qhull internal error (qh_facetarea_simplex): #points %d != dim %d -1\n",
-               i, dim);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  rows[i]= gmcoord;
-  if (qh DELAUNAY) {
-    for (i=0; i < dim-1; i++)
-      rows[i][dim-1]= 0.0;
-    for (k=dim; k--; )
-      *(gmcoord++)= 0.0;
-    rows[dim-1][dim-1]= -1.0;
-  }else {
-    normalp= normal;
-    for (k=dim; k--; )
-      *(gmcoord++)= *normalp++;
-  }
-  zinc_(Zdetsimplex);
-  area= qh_determinant(rows, dim, &nearzero);
-  if (toporient)
-    area= -area;
-  area *= qh AREAfactor;
-  trace4((qh ferr, 4010, "qh_facetarea_simplex: area=%2.2g for point p%d, toporient %d, nearzero? %d\n",
-          area, qh_pointid(apex), toporient, nearzero));
-  return area;
-} /* facetarea_simplex */
-
-/*---------------------------------
-
-  qh_facetcenter( vertices )
-    return Voronoi center (Voronoi vertex) for a facet's vertices
-
-  returns:
-    return temporary point equal to the center
-
-  see:
-    qh_voronoi_center()
-*/
-pointT *qh_facetcenter(setT *vertices) {
-  setT *points= qh_settemp(qh_setsize(vertices));
-  vertexT *vertex, **vertexp;
-  pointT *center;
-
-  FOREACHvertex_(vertices)
-    qh_setappend(&points, vertex->point);
-  center= qh_voronoi_center(qh hull_dim-1, points);
-  qh_settempfree(&points);
-  return center;
-} /* facetcenter */
-
-/*---------------------------------
-
-  qh_findgooddist( point, facetA, dist, facetlist )
-    find best good facet visible for point from facetA
-    assumes facetA is visible from point
-
-  returns:
-    best facet, i.e., good facet that is furthest from point
-      distance to best facet
-      NULL if none
-
-    moves good, visible facets (and some other visible facets)
-      to end of qh facet_list
-
-  notes:
-    uses qh visit_id
-
-  design:
-    initialize bestfacet if facetA is good
-    move facetA to end of facetlist
-    for each facet on facetlist
-      for each unvisited neighbor of facet
-        move visible neighbors to end of facetlist
-        update best good neighbor
-        if no good neighbors, update best facet
-*/
-facetT *qh_findgooddist(pointT *point, facetT *facetA, realT *distp,
-               facetT **facetlist) {
-  realT bestdist= -REALmax, dist;
-  facetT *neighbor, **neighborp, *bestfacet=NULL, *facet;
-  boolT goodseen= False;
-
-  if (facetA->good) {
-    zzinc_(Zcheckpart);  /* calls from check_bestdist occur after print stats */
-    qh_distplane(point, facetA, &bestdist);
-    bestfacet= facetA;
-    goodseen= True;
-  }
-  qh_removefacet(facetA);
-  qh_appendfacet(facetA);
-  *facetlist= facetA;
-  facetA->visitid= ++qh visit_id;
-  FORALLfacet_(*facetlist) {
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid == qh visit_id)
-        continue;
-      neighbor->visitid= qh visit_id;
-      if (goodseen && !neighbor->good)
-        continue;
-      zzinc_(Zcheckpart);
-      qh_distplane(point, neighbor, &dist);
-      if (dist > 0) {
-        qh_removefacet(neighbor);
-        qh_appendfacet(neighbor);
-        if (neighbor->good) {
-          goodseen= True;
-          if (dist > bestdist) {
-            bestdist= dist;
-            bestfacet= neighbor;
-          }
-        }
-      }
-    }
-  }
-  if (bestfacet) {
-    *distp= bestdist;
-    trace2((qh ferr, 2003, "qh_findgooddist: p%d is %2.2g above good facet f%d\n",
-      qh_pointid(point), bestdist, bestfacet->id));
-    return bestfacet;
-  }
-  trace4((qh ferr, 4011, "qh_findgooddist: no good facet for p%d above f%d\n",
-      qh_pointid(point), facetA->id));
-  return NULL;
-}  /* findgooddist */
-
-/*---------------------------------
-
-  qh_getarea( facetlist )
-    set area of all facets in facetlist
-    collect statistics
-    nop if hasAreaVolume
-
-  returns:
-    sets qh totarea/totvol to total area and volume of convex hull
-    for Delaunay triangulation, computes projected area of the lower or upper hull
-      ignores upper hull if qh ATinfinity
-
-  notes:
-    could compute outer volume by expanding facet area by rays from interior
-    the following attempt at perpendicular projection underestimated badly:
-      qh.totoutvol += (-dist + facet->maxoutside + qh DISTround)
-                            * area/ qh hull_dim;
-  design:
-    for each facet on facetlist
-      compute facet->area
-      update qh.totarea and qh.totvol
-*/
-void qh_getarea(facetT *facetlist) {
-  realT area;
-  realT dist;
-  facetT *facet;
-
-  if (qh hasAreaVolume)
-    return;
-  if (qh REPORTfreq)
-    qh_fprintf(qh ferr, 8020, "computing area of each facet and volume of the convex hull\n");
-  else
-    trace1((qh ferr, 1001, "qh_getarea: computing volume and area for each facet\n"));
-  qh totarea= qh totvol= 0.0;
-  FORALLfacet_(facetlist) {
-    if (!facet->normal)
-      continue;
-    if (facet->upperdelaunay && qh ATinfinity)
-      continue;
-    if (!facet->isarea) {
-      facet->f.area= qh_facetarea(facet);
-      facet->isarea= True;
-    }
-    area= facet->f.area;
-    if (qh DELAUNAY) {
-      if (facet->upperdelaunay == qh UPPERdelaunay)
-        qh totarea += area;
-    }else {
-      qh totarea += area;
-      qh_distplane(qh interior_point, facet, &dist);
-      qh totvol += -dist * area/ qh hull_dim;
-    }
-    if (qh PRINTstatistics) {
-      wadd_(Wareatot, area);
-      wmax_(Wareamax, area);
-      wmin_(Wareamin, area);
-    }
-  }
-  qh hasAreaVolume= True;
-} /* getarea */
-
-/*---------------------------------
-
-  qh_gram_schmidt( dim, row )
-    implements Gram-Schmidt orthogonalization by rows
-
-  returns:
-    false if zero norm
-    overwrites rows[dim][dim]
-
-  notes:
-    see Golub & van Loan, 1983, Algorithm 6.2-2, "Modified Gram-Schmidt"
-    overflow due to small divisors not handled
-
-  design:
-    for each row
-      compute norm for row
-      if non-zero, normalize row
-      for each remaining rowA
-        compute inner product of row and rowA
-        reduce rowA by row * inner product
-*/
-boolT qh_gram_schmidt(int dim, realT **row) {
-  realT *rowi, *rowj, norm;
-  int i, j, k;
-
-  for (i=0; i < dim; i++) {
-    rowi= row[i];
-    for (norm= 0.0, k= dim; k--; rowi++)
-      norm += *rowi * *rowi;
-    norm= sqrt(norm);
-    wmin_(Wmindenom, norm);
-    if (norm == 0.0)  /* either 0 or overflow due to sqrt */
-      return False;
-    for (k=dim; k--; )
-      *(--rowi) /= norm;
-    for (j=i+1; j < dim; j++) {
-      rowj= row[j];
-      for (norm= 0.0, k=dim; k--; )
-        norm += *rowi++ * *rowj++;
-      for (k=dim; k--; )
-        *(--rowj) -= *(--rowi) * norm;
-    }
-  }
-  return True;
-} /* gram_schmidt */
-
-
-/*---------------------------------
-
-  qh_inthresholds( normal, angle )
-    return True if normal within qh.lower_/upper_threshold
-
-  returns:
-    estimate of angle by summing of threshold diffs
-      angle may be NULL
-      smaller "angle" is better
-
-  notes:
-    invalid if qh.SPLITthresholds
-
-  see:
-    qh.lower_threshold in qh_initbuild()
-    qh_initthresholds()
-
-  design:
-    for each dimension
-      test threshold
-*/
-boolT qh_inthresholds(coordT *normal, realT *angle) {
-  boolT within= True;
-  int k;
-  realT threshold;
-
-  if (angle)
-    *angle= 0.0;
-  for (k=0; k < qh hull_dim; k++) {
-    threshold= qh lower_threshold[k];
-    if (threshold > -REALmax/2) {
-      if (normal[k] < threshold)
-        within= False;
-      if (angle) {
-        threshold -= normal[k];
-        *angle += fabs_(threshold);
-      }
-    }
-    if (qh upper_threshold[k] < REALmax/2) {
-      threshold= qh upper_threshold[k];
-      if (normal[k] > threshold)
-        within= False;
-      if (angle) {
-        threshold -= normal[k];
-        *angle += fabs_(threshold);
-      }
-    }
-  }
-  return within;
-} /* inthresholds */
-
-
-/*---------------------------------
-
-  qh_joggleinput()
-    randomly joggle input to Qhull by qh.JOGGLEmax
-    initial input is qh.first_point/qh.num_points of qh.hull_dim
-      repeated calls use qh.input_points/qh.num_points
-
-  returns:
-    joggles points at qh.first_point/qh.num_points
-    copies data to qh.input_points/qh.input_malloc if first time
-    determines qh.JOGGLEmax if it was zero
-    if qh.DELAUNAY
-      computes the Delaunay projection of the joggled points
-
-  notes:
-    if qh.DELAUNAY, unnecessarily joggles the last coordinate
-    the initial 'QJn' may be set larger than qh_JOGGLEmaxincrease
-
-  design:
-    if qh.DELAUNAY
-      set qh.SCALElast for reduced precision errors
-    if first call
-      initialize qh.input_points to the original input points
-      if qh.JOGGLEmax == 0
-        determine default qh.JOGGLEmax
-    else
-      increase qh.JOGGLEmax according to qh.build_cnt
-    joggle the input by adding a random number in [-qh.JOGGLEmax,qh.JOGGLEmax]
-    if qh.DELAUNAY
-      sets the Delaunay projection
-*/
-void qh_joggleinput(void) {
-  int i, seed, size;
-  coordT *coordp, *inputp;
-  realT randr, randa, randb;
-
-  if (!qh input_points) { /* first call */
-    qh input_points= qh first_point;
-    qh input_malloc= qh POINTSmalloc;
-    size= qh num_points * qh hull_dim * sizeof(coordT);
-    if (!(qh first_point=(coordT*)qh_malloc((size_t)size))) {
-      qh_fprintf(qh ferr, 6009, "qhull error: insufficient memory to joggle %d points\n",
-          qh num_points);
-      qh_errexit(qh_ERRmem, NULL, NULL);
-    }
-    qh POINTSmalloc= True;
-    if (qh JOGGLEmax == 0.0) {
-      qh JOGGLEmax= qh_detjoggle(qh input_points, qh num_points, qh hull_dim);
-      qh_option("QJoggle", NULL, &qh JOGGLEmax);
-    }
-  }else {                 /* repeated call */
-    if (!qh RERUN && qh build_cnt > qh_JOGGLEretry) {
-      if (((qh build_cnt-qh_JOGGLEretry-1) % qh_JOGGLEagain) == 0) {
-        realT maxjoggle= qh MAXwidth * qh_JOGGLEmaxincrease;
-        if (qh JOGGLEmax < maxjoggle) {
-          qh JOGGLEmax *= qh_JOGGLEincrease;
-          minimize_(qh JOGGLEmax, maxjoggle);
-        }
-      }
-    }
-    qh_option("QJoggle", NULL, &qh JOGGLEmax);
-  }
-  if (qh build_cnt > 1 && qh JOGGLEmax > fmax_(qh MAXwidth/4, 0.1)) {
-      qh_fprintf(qh ferr, 6010, "qhull error: the current joggle for 'QJn', %.2g, is too large for the width\nof the input.  If possible, recompile Qhull with higher-precision reals.\n",
-                qh JOGGLEmax);
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  /* for some reason, using qh ROTATErandom and qh_RANDOMseed does not repeat the run. Use 'TRn' instead */
-  seed= qh_RANDOMint;
-  qh_option("_joggle-seed", &seed, NULL);
-  trace0((qh ferr, 6, "qh_joggleinput: joggle input by %2.2g with seed %d\n",
-    qh JOGGLEmax, seed));
-  inputp= qh input_points;
-  coordp= qh first_point;
-  randa= 2.0 * qh JOGGLEmax/qh_RANDOMmax;
-  randb= -qh JOGGLEmax;
-  size= qh num_points * qh hull_dim;
-  for (i=size; i--; ) {
-    randr= qh_RANDOMint;
-    *(coordp++)= *(inputp++) + (randr * randa + randb);
-  }
-  if (qh DELAUNAY) {
-    qh last_low= qh last_high= qh last_newhigh= REALmax;
-    qh_setdelaunay(qh hull_dim, qh num_points, qh first_point);
-  }
-} /* joggleinput */
-
-/*---------------------------------
-
-  qh_maxabsval( normal, dim )
-    return pointer to maximum absolute value of a dim vector
-    returns NULL if dim=0
-*/
-realT *qh_maxabsval(realT *normal, int dim) {
-  realT maxval= -REALmax;
-  realT *maxp= NULL, *colp, absval;
-  int k;
-
-  for (k=dim, colp= normal; k--; colp++) {
-    absval= fabs_(*colp);
-    if (absval > maxval) {
-      maxval= absval;
-      maxp= colp;
-    }
-  }
-  return maxp;
-} /* maxabsval */
-
-
-/*---------------------------------
-
-  qh_maxmin( points, numpoints, dimension )
-    return max/min points for each dimension
-    determine max and min coordinates
-
-  returns:
-    returns a temporary set of max and min points
-      may include duplicate points. Does not include qh.GOODpoint
-    sets qh.NEARzero, qh.MAXabs_coord, qh.MAXsumcoord, qh.MAXwidth
-         qh.MAXlastcoord, qh.MINlastcoord
-    initializes qh.max_outside, qh.min_vertex, qh.WAScoplanar, qh.ZEROall_ok
-
-  notes:
-    loop duplicated in qh_detjoggle()
-
-  design:
-    initialize global precision variables
-    checks definition of REAL...
-    for each dimension
-      for each point
-        collect maximum and minimum point
-      collect maximum of maximums and minimum of minimums
-      determine qh.NEARzero for Gaussian Elimination
-*/
-setT *qh_maxmin(pointT *points, int numpoints, int dimension) {
-  int k;
-  realT maxcoord, temp;
-  pointT *minimum, *maximum, *point, *pointtemp;
-  setT *set;
-
-  qh max_outside= 0.0;
-  qh MAXabs_coord= 0.0;
-  qh MAXwidth= -REALmax;
-  qh MAXsumcoord= 0.0;
-  qh min_vertex= 0.0;
-  qh WAScoplanar= False;
-  if (qh ZEROcentrum)
-    qh ZEROall_ok= True;
-  if (REALmin < REALepsilon && REALmin < REALmax && REALmin > -REALmax
-  && REALmax > 0.0 && -REALmax < 0.0)
-    ; /* all ok */
-  else {
-    qh_fprintf(qh ferr, 6011, "qhull error: floating point constants in user.h are wrong\n\
-REALepsilon %g REALmin %g REALmax %g -REALmax %g\n",
-             REALepsilon, REALmin, REALmax, -REALmax);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  set= qh_settemp(2*dimension);
-  for (k=0; k < dimension; k++) {
-    if (points == qh GOODpointp)
-      minimum= maximum= points + dimension;
-    else
-      minimum= maximum= points;
-    FORALLpoint_(points, numpoints) {
-      if (point == qh GOODpointp)
-        continue;
-      if (maximum[k] < point[k])
-        maximum= point;
-      else if (minimum[k] > point[k])
-        minimum= point;
-    }
-    if (k == dimension-1) {
-      qh MINlastcoord= minimum[k];
-      qh MAXlastcoord= maximum[k];
-    }
-    if (qh SCALElast && k == dimension-1)
-      maxcoord= qh MAXwidth;
-    else {
-      maxcoord= fmax_(maximum[k], -minimum[k]);
-      if (qh GOODpointp) {
-        temp= fmax_(qh GOODpointp[k], -qh GOODpointp[k]);
-        maximize_(maxcoord, temp);
-      }
-      temp= maximum[k] - minimum[k];
-      maximize_(qh MAXwidth, temp);
-    }
-    maximize_(qh MAXabs_coord, maxcoord);
-    qh MAXsumcoord += maxcoord;
-    qh_setappend(&set, maximum);
-    qh_setappend(&set, minimum);
-    /* calculation of qh NEARzero is based on Golub & van Loan, 1983,
-       Eq. 4.4-13 for "Gaussian elimination with complete pivoting".
-       Golub & van Loan say that n^3 can be ignored and 10 be used in
-       place of rho */
-    qh NEARzero[k]= 80 * qh MAXsumcoord * REALepsilon;
-  }
-  if (qh IStracing >=1)
-    qh_printpoints(qh ferr, "qh_maxmin: found the max and min points(by dim):", set);
-  return(set);
-} /* maxmin */
-
-/*---------------------------------
-
-  qh_maxouter()
-    return maximum distance from facet to outer plane
-    normally this is qh.max_outside+qh.DISTround
-    does not include qh.JOGGLEmax
-
-  see:
-    qh_outerinner()
-
-  notes:
-    need to add another qh.DISTround if testing actual point with computation
-
-  for joggle:
-    qh_setfacetplane() updated qh.max_outer for Wnewvertexmax (max distance to vertex)
-    need to use Wnewvertexmax since could have a coplanar point for a high
-      facet that is replaced by a low facet
-    need to add qh.JOGGLEmax if testing input points
-*/
-realT qh_maxouter(void) {
-  realT dist;
-
-  dist= fmax_(qh max_outside, qh DISTround);
-  dist += qh DISTround;
-  trace4((qh ferr, 4012, "qh_maxouter: max distance from facet to outer plane is %2.2g max_outside is %2.2g\n", dist, qh max_outside));
-  return dist;
-} /* maxouter */
-
-/*---------------------------------
-
-  qh_maxsimplex( dim, maxpoints, points, numpoints, simplex )
-    determines maximum simplex for a set of points
-    starts from points already in simplex
-    skips qh.GOODpointp (assumes that it isn't in maxpoints)
-
-  returns:
-    simplex with dim+1 points
-
-  notes:
-    assumes at least pointsneeded points in points
-    maximizes determinate for x,y,z,w, etc.
-    uses maxpoints as long as determinate is clearly non-zero
-
-  design:
-    initialize simplex with at least two points
-      (find points with max or min x coordinate)
-    for each remaining dimension
-      add point that maximizes the determinate
-        (use points from maxpoints first)
-*/
-void qh_maxsimplex(int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) {
-  pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL;
-  boolT nearzero, maxnearzero= False;
-  int k, sizinit;
-  realT maxdet= -REALmax, det, mincoord= REALmax, maxcoord= -REALmax;
-
-  sizinit= qh_setsize(*simplex);
-  if (sizinit < 2) {
-    if (qh_setsize(maxpoints) >= 2) {
-      FOREACHpoint_(maxpoints) {
-        if (maxcoord < point[0]) {
-          maxcoord= point[0];
-          maxx= point;
-        }
-        if (mincoord > point[0]) {
-          mincoord= point[0];
-          minx= point;
-        }
-      }
-    }else {
-      FORALLpoint_(points, numpoints) {
-        if (point == qh GOODpointp)
-          continue;
-        if (maxcoord < point[0]) {
-          maxcoord= point[0];
-          maxx= point;
-        }
-        if (mincoord > point[0]) {
-          mincoord= point[0];
-          minx= point;
-        }
-      }
-    }
-    qh_setunique(simplex, minx);
-    if (qh_setsize(*simplex) < 2)
-      qh_setunique(simplex, maxx);
-    sizinit= qh_setsize(*simplex);
-    if (sizinit < 2) {
-      qh_precision("input has same x coordinate");
-      if (zzval_(Zsetplane) > qh hull_dim+1) {
-        qh_fprintf(qh ferr, 6012, "qhull precision error (qh_maxsimplex for voronoi_center):\n%d points with the same x coordinate.\n",
-                 qh_setsize(maxpoints)+numpoints);
-        qh_errexit(qh_ERRprec, NULL, NULL);
-      }else {
-        qh_fprintf(qh ferr, 6013, "qhull input error: input is less than %d-dimensional since it has the same x coordinate\n", qh hull_dim);
-        qh_errexit(qh_ERRinput, NULL, NULL);
-      }
-    }
-  }
-  for (k=sizinit; k < dim+1; k++) {
-    maxpoint= NULL;
-    maxdet= -REALmax;
-    FOREACHpoint_(maxpoints) {
-      if (!qh_setin(*simplex, point)) {
-        det= qh_detsimplex(point, *simplex, k, &nearzero);
-        if ((det= fabs_(det)) > maxdet) {
-          maxdet= det;
-          maxpoint= point;
-          maxnearzero= nearzero;
-        }
-      }
-    }
-    if (!maxpoint || maxnearzero) {
-      zinc_(Zsearchpoints);
-      if (!maxpoint) {
-        trace0((qh ferr, 7, "qh_maxsimplex: searching all points for %d-th initial vertex.\n", k+1));
-      }else {
-        trace0((qh ferr, 8, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g\n",
-                k+1, qh_pointid(maxpoint), maxdet));
-      }
-      FORALLpoint_(points, numpoints) {
-        if (point == qh GOODpointp)
-          continue;
-        if (!qh_setin(*simplex, point)) {
-          det= qh_detsimplex(point, *simplex, k, &nearzero);
-          if ((det= fabs_(det)) > maxdet) {
-            maxdet= det;
-            maxpoint= point;
-            maxnearzero= nearzero;
-          }
-        }
-      }
-    } /* !maxpoint */
-    if (!maxpoint) {
-      qh_fprintf(qh ferr, 6014, "qhull internal error (qh_maxsimplex): not enough points available\n");
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-    }
-    qh_setappend(simplex, maxpoint);
-    trace1((qh ferr, 1002, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%2.2g\n",
-            qh_pointid(maxpoint), k+1, maxdet));
-  } /* k */
-} /* maxsimplex */
-
-/*---------------------------------
-
-  qh_minabsval( normal, dim )
-    return minimum absolute value of a dim vector
-*/
-realT qh_minabsval(realT *normal, int dim) {
-  realT minval= 0;
-  realT maxval= 0;
-  realT *colp;
-  int k;
-
-  for (k=dim, colp=normal; k--; colp++) {
-    maximize_(maxval, *colp);
-    minimize_(minval, *colp);
-  }
-  return fmax_(maxval, -minval);
-} /* minabsval */
-
-
-/*---------------------------------
-
-  qh_mindif( vecA, vecB, dim )
-    return index of min abs. difference of two vectors
-*/
-int qh_mindiff(realT *vecA, realT *vecB, int dim) {
-  realT mindiff= REALmax, diff;
-  realT *vecAp= vecA, *vecBp= vecB;
-  int k, mink= 0;
-
-  for (k=0; k < dim; k++) {
-    diff= *vecAp++ - *vecBp++;
-    diff= fabs_(diff);
-    if (diff < mindiff) {
-      mindiff= diff;
-      mink= k;
-    }
-  }
-  return mink;
-} /* mindiff */
-
-
-
-/*---------------------------------
-
-  qh_orientoutside( facet  )
-    make facet outside oriented via qh.interior_point
-
-  returns:
-    True if facet reversed orientation.
-*/
-boolT qh_orientoutside(facetT *facet) {
-  int k;
-  realT dist;
-
-  qh_distplane(qh interior_point, facet, &dist);
-  if (dist > 0) {
-    for (k=qh hull_dim; k--; )
-      facet->normal[k]= -facet->normal[k];
-    facet->offset= -facet->offset;
-    return True;
-  }
-  return False;
-} /* orientoutside */
-
-/*---------------------------------
-
-  qh_outerinner( facet, outerplane, innerplane  )
-    if facet and qh.maxoutdone (i.e., qh_check_maxout)
-      returns outer and inner plane for facet
-    else
-      returns maximum outer and inner plane
-    accounts for qh.JOGGLEmax
-
-  see:
-    qh_maxouter(), qh_check_bestdist(), qh_check_points()
-
-  notes:
-    outerplaner or innerplane may be NULL
-    facet is const
-    Does not error (QhullFacet)
-
-    includes qh.DISTround for actual points
-    adds another qh.DISTround if testing with floating point arithmetic
-*/
-void qh_outerinner(facetT *facet, realT *outerplane, realT *innerplane) {
-  realT dist, mindist;
-  vertexT *vertex, **vertexp;
-
-  if (outerplane) {
-    if (!qh_MAXoutside || !facet || !qh maxoutdone) {
-      *outerplane= qh_maxouter();       /* includes qh.DISTround */
-    }else { /* qh_MAXoutside ... */
-#if qh_MAXoutside
-      *outerplane= facet->maxoutside + qh DISTround;
-#endif
-
-    }
-    if (qh JOGGLEmax < REALmax/2)
-      *outerplane += qh JOGGLEmax * sqrt((realT)qh hull_dim);
-  }
-  if (innerplane) {
-    if (facet) {
-      mindist= REALmax;
-      FOREACHvertex_(facet->vertices) {
-        zinc_(Zdistio);
-        qh_distplane(vertex->point, facet, &dist);
-        minimize_(mindist, dist);
-      }
-      *innerplane= mindist - qh DISTround;
-    }else
-      *innerplane= qh min_vertex - qh DISTround;
-    if (qh JOGGLEmax < REALmax/2)
-      *innerplane -= qh JOGGLEmax * sqrt((realT)qh hull_dim);
-  }
-} /* outerinner */
-
-/*---------------------------------
-
-  qh_pointdist( point1, point2, dim )
-    return distance between two points
-
-  notes:
-    returns distance squared if 'dim' is negative
-*/
-coordT qh_pointdist(pointT *point1, pointT *point2, int dim) {
-  coordT dist, diff;
-  int k;
-
-  dist= 0.0;
-  for (k= (dim > 0 ? dim : -dim); k--; ) {
-    diff= *point1++ - *point2++;
-    dist += diff * diff;
-  }
-  if (dim > 0)
-    return(sqrt(dist));
-  return dist;
-} /* pointdist */
-
-
-/*---------------------------------
-
-  qh_printmatrix( fp, string, rows, numrow, numcol )
-    print matrix to fp given by row vectors
-    print string as header
-
-  notes:
-    print a vector by qh_printmatrix(fp, "", &vect, 1, len)
-*/
-void qh_printmatrix(FILE *fp, const char *string, realT **rows, int numrow, int numcol) {
-  realT *rowp;
-  realT r; /*bug fix*/
-  int i,k;
-
-  qh_fprintf(fp, 9001, "%s\n", string);
-  for (i=0; i < numrow; i++) {
-    rowp= rows[i];
-    for (k=0; k < numcol; k++) {
-      r= *rowp++;
-      qh_fprintf(fp, 9002, "%6.3g ", r);
-    }
-    qh_fprintf(fp, 9003, "\n");
-  }
-} /* printmatrix */
-
-
-/*---------------------------------
-
-  qh_printpoints( fp, string, points )
-    print pointids to fp for a set of points
-    if string, prints string and 'p' point ids
-*/
-void qh_printpoints(FILE *fp, const char *string, setT *points) {
-  pointT *point, **pointp;
-
-  if (string) {
-    qh_fprintf(fp, 9004, "%s", string);
-    FOREACHpoint_(points)
-      qh_fprintf(fp, 9005, " p%d", qh_pointid(point));
-    qh_fprintf(fp, 9006, "\n");
-  }else {
-    FOREACHpoint_(points)
-      qh_fprintf(fp, 9007, " %d", qh_pointid(point));
-    qh_fprintf(fp, 9008, "\n");
-  }
-} /* printpoints */
-
-
-/*---------------------------------
-
-  qh_projectinput()
-    project input points using qh.lower_bound/upper_bound and qh DELAUNAY
-    if qh.lower_bound[k]=qh.upper_bound[k]= 0,
-      removes dimension k
-    if halfspace intersection
-      removes dimension k from qh.feasible_point
-    input points in qh first_point, num_points, input_dim
-
-  returns:
-    new point array in qh first_point of qh hull_dim coordinates
-    sets qh POINTSmalloc
-    if qh DELAUNAY
-      projects points to paraboloid
-      lowbound/highbound is also projected
-    if qh ATinfinity
-      adds point "at-infinity"
-    if qh POINTSmalloc
-      frees old point array
-
-  notes:
-    checks that qh.hull_dim agrees with qh.input_dim, PROJECTinput, and DELAUNAY
-
-
-  design:
-    sets project[k] to -1 (delete), 0 (keep), 1 (add for Delaunay)
-    determines newdim and newnum for qh hull_dim and qh num_points
-    projects points to newpoints
-    projects qh.lower_bound to itself
-    projects qh.upper_bound to itself
-    if qh DELAUNAY
-      if qh ATINFINITY
-        projects points to paraboloid
-        computes "infinity" point as vertex average and 10% above all points
-      else
-        uses qh_setdelaunay to project points to paraboloid
-*/
-void qh_projectinput(void) {
-  int k,i;
-  int newdim= qh input_dim, newnum= qh num_points;
-  signed char *project;
-  int projectsize= (qh input_dim+1)*sizeof(*project);
-  pointT *newpoints, *coord, *infinity;
-  realT paraboloid, maxboloid= 0;
-
-  project= (signed char*)qh_memalloc(projectsize);
-  memset((char*)project, 0, (size_t)projectsize);
-  for (k=0; k < qh input_dim; k++) {   /* skip Delaunay bound */
-    if (qh lower_bound[k] == 0 && qh upper_bound[k] == 0) {
-      project[k]= -1;
-      newdim--;
-    }
-  }
-  if (qh DELAUNAY) {
-    project[k]= 1;
-    newdim++;
-    if (qh ATinfinity)
-      newnum++;
-  }
-  if (newdim != qh hull_dim) {
-    qh_memfree(project, projectsize);
-    qh_fprintf(qh ferr, 6015, "qhull internal error (qh_projectinput): dimension after projection %d != hull_dim %d\n", newdim, qh hull_dim);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  if (!(newpoints= qh temp_malloc= (coordT*)qh_malloc(newnum*newdim*sizeof(coordT)))){
-    qh_memfree(project, projectsize);
-    qh_fprintf(qh ferr, 6016, "qhull error: insufficient memory to project %d points\n",
-           qh num_points);
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  /* qh_projectpoints throws error if mismatched dimensions */
-  qh_projectpoints(project, qh input_dim+1, qh first_point,
-                    qh num_points, qh input_dim, newpoints, newdim);
-  trace1((qh ferr, 1003, "qh_projectinput: updating lower and upper_bound\n"));
-  qh_projectpoints(project, qh input_dim+1, qh lower_bound,
-                    1, qh input_dim+1, qh lower_bound, newdim+1);
-  qh_projectpoints(project, qh input_dim+1, qh upper_bound,
-                    1, qh input_dim+1, qh upper_bound, newdim+1);
-  if (qh HALFspace) {
-    if (!qh feasible_point) {
-      qh_memfree(project, projectsize);
-      qh_fprintf(qh ferr, 6017, "qhull internal error (qh_projectinput): HALFspace defined without qh.feasible_point\n");
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-    }
-    qh_projectpoints(project, qh input_dim, qh feasible_point,
-                      1, qh input_dim, qh feasible_point, newdim);
-  }
-  qh_memfree(project, projectsize);
-  if (qh POINTSmalloc)
-    qh_free(qh first_point);
-  qh first_point= newpoints;
-  qh POINTSmalloc= True;
-  qh temp_malloc= NULL;
-  if (qh DELAUNAY && qh ATinfinity) {
-    coord= qh first_point;
-    infinity= qh first_point + qh hull_dim * qh num_points;
-    for (k=qh hull_dim-1; k--; )
-      infinity[k]= 0.0;
-    for (i=qh num_points; i--; ) {
-      paraboloid= 0.0;
-      for (k=0; k < qh hull_dim-1; k++) {
-        paraboloid += *coord * *coord;
-        infinity[k] += *coord;
-        coord++;
-      }
-      *(coord++)= paraboloid;
-      maximize_(maxboloid, paraboloid);
-    }
-    /* coord == infinity */
-    for (k=qh hull_dim-1; k--; )
-      *(coord++) /= qh num_points;
-    *(coord++)= maxboloid * 1.1;
-    qh num_points++;
-    trace0((qh ferr, 9, "qh_projectinput: projected points to paraboloid for Delaunay\n"));
-  }else if (qh DELAUNAY)  /* !qh ATinfinity */
-    qh_setdelaunay( qh hull_dim, qh num_points, qh first_point);
-} /* projectinput */
-
-
-/*---------------------------------
-
-  qh_projectpoints( project, n, points, numpoints, dim, newpoints, newdim )
-    project points/numpoints/dim to newpoints/newdim
-    if project[k] == -1
-      delete dimension k
-    if project[k] == 1
-      add dimension k by duplicating previous column
-    n is size of project
-
-  notes:
-    newpoints may be points if only adding dimension at end
-
-  design:
-    check that 'project' and 'newdim' agree
-    for each dimension
-      if project == -1
-        skip dimension
-      else
-        determine start of column in newpoints
-        determine start of column in points
-          if project == +1, duplicate previous column
-        copy dimension (column) from points to newpoints
-*/
-void qh_projectpoints(signed char *project, int n, realT *points,
-        int numpoints, int dim, realT *newpoints, int newdim) {
-  int testdim= dim, oldk=0, newk=0, i,j=0,k;
-  realT *newp, *oldp;
-
-  for (k=0; k < n; k++)
-    testdim += project[k];
-  if (testdim != newdim) {
-    qh_fprintf(qh ferr, 6018, "qhull internal error (qh_projectpoints): newdim %d should be %d after projection\n",
-      newdim, testdim);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  for (j=0; j= dim)
-          continue;
-        oldp= points+oldk;
-      }else
-        oldp= points+oldk++;
-      for (i=numpoints; i--; ) {
-        *newp= *oldp;
-        newp += newdim;
-        oldp += dim;
-      }
-    }
-    if (oldk >= dim)
-      break;
-  }
-  trace1((qh ferr, 1004, "qh_projectpoints: projected %d points from dim %d to dim %d\n",
-    numpoints, dim, newdim));
-} /* projectpoints */
-
-
-/*---------------------------------
-
-  qh_rotateinput( rows )
-    rotate input using row matrix
-    input points given by qh first_point, num_points, hull_dim
-    assumes rows[dim] is a scratch buffer
-    if qh POINTSmalloc, overwrites input points, else mallocs a new array
-
-  returns:
-    rotated input
-    sets qh POINTSmalloc
-
-  design:
-    see qh_rotatepoints
-*/
-void qh_rotateinput(realT **rows) {
-
-  if (!qh POINTSmalloc) {
-    qh first_point= qh_copypoints(qh first_point, qh num_points, qh hull_dim);
-    qh POINTSmalloc= True;
-  }
-  qh_rotatepoints(qh first_point, qh num_points, qh hull_dim, rows);
-}  /* rotateinput */
-
-/*---------------------------------
-
-  qh_rotatepoints( points, numpoints, dim, row )
-    rotate numpoints points by a d-dim row matrix
-    assumes rows[dim] is a scratch buffer
-
-  returns:
-    rotated points in place
-
-  design:
-    for each point
-      for each coordinate
-        use row[dim] to compute partial inner product
-      for each coordinate
-        rotate by partial inner product
-*/
-void qh_rotatepoints(realT *points, int numpoints, int dim, realT **row) {
-  realT *point, *rowi, *coord= NULL, sum, *newval;
-  int i,j,k;
-
-  if (qh IStracing >= 1)
-    qh_printmatrix(qh ferr, "qh_rotatepoints: rotate points by", row, dim, dim);
-  for (point= points, j= numpoints; j--; point += dim) {
-    newval= row[dim];
-    for (i=0; i < dim; i++) {
-      rowi= row[i];
-      coord= point;
-      for (sum= 0.0, k= dim; k--; )
-        sum += *rowi++ * *coord++;
-      *(newval++)= sum;
-    }
-    for (k=dim; k--; )
-      *(--coord)= *(--newval);
-  }
-} /* rotatepoints */
-
-
-/*---------------------------------
-
-  qh_scaleinput()
-    scale input points using qh low_bound/high_bound
-    input points given by qh first_point, num_points, hull_dim
-    if qh POINTSmalloc, overwrites input points, else mallocs a new array
-
-  returns:
-    scales coordinates of points to low_bound[k], high_bound[k]
-    sets qh POINTSmalloc
-
-  design:
-    see qh_scalepoints
-*/
-void qh_scaleinput(void) {
-
-  if (!qh POINTSmalloc) {
-    qh first_point= qh_copypoints(qh first_point, qh num_points, qh hull_dim);
-    qh POINTSmalloc= True;
-  }
-  qh_scalepoints(qh first_point, qh num_points, qh hull_dim,
-       qh lower_bound, qh upper_bound);
-}  /* scaleinput */
-
-/*---------------------------------
-
-  qh_scalelast( points, numpoints, dim, low, high, newhigh )
-    scale last coordinate to [0,m] for Delaunay triangulations
-    input points given by points, numpoints, dim
-
-  returns:
-    changes scale of last coordinate from [low, high] to [0, newhigh]
-    overwrites last coordinate of each point
-    saves low/high/newhigh in qh.last_low, etc. for qh_setdelaunay()
-
-  notes:
-    when called by qh_setdelaunay, low/high may not match actual data
-
-  design:
-    compute scale and shift factors
-    apply to last coordinate of each point
-*/
-void qh_scalelast(coordT *points, int numpoints, int dim, coordT low,
-                   coordT high, coordT newhigh) {
-  realT scale, shift;
-  coordT *coord;
-  int i;
-  boolT nearzero= False;
-
-  trace4((qh ferr, 4013, "qh_scalelast: scale last coordinate from [%2.2g, %2.2g] to [0,%2.2g]\n",
-    low, high, newhigh));
-  qh last_low= low;
-  qh last_high= high;
-  qh last_newhigh= newhigh;
-  scale= qh_divzero(newhigh, high - low,
-                  qh MINdenom_1, &nearzero);
-  if (nearzero) {
-    if (qh DELAUNAY)
-      qh_fprintf(qh ferr, 6019, "qhull input error: can not scale last coordinate.  Input is cocircular\n   or cospherical.   Use option 'Qz' to add a point at infinity.\n");
-    else
-      qh_fprintf(qh ferr, 6020, "qhull input error: can not scale last coordinate.  New bounds [0, %2.2g] are too wide for\nexisting bounds [%2.2g, %2.2g] (width %2.2g)\n",
-                newhigh, low, high, high-low);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  shift= - low * newhigh / (high-low);
-  coord= points + dim - 1;
-  for (i=numpoints; i--; coord += dim)
-    *coord= *coord * scale + shift;
-} /* scalelast */
-
-/*---------------------------------
-
-  qh_scalepoints( points, numpoints, dim, newlows, newhighs )
-    scale points to new lowbound and highbound
-    retains old bound when newlow= -REALmax or newhigh= +REALmax
-
-  returns:
-    scaled points
-    overwrites old points
-
-  design:
-    for each coordinate
-      compute current low and high bound
-      compute scale and shift factors
-      scale all points
-      enforce new low and high bound for all points
-*/
-void qh_scalepoints(pointT *points, int numpoints, int dim,
-        realT *newlows, realT *newhighs) {
-  int i,k;
-  realT shift, scale, *coord, low, high, newlow, newhigh, mincoord, maxcoord;
-  boolT nearzero= False;
-
-  for (k=0; k < dim; k++) {
-    newhigh= newhighs[k];
-    newlow= newlows[k];
-    if (newhigh > REALmax/2 && newlow < -REALmax/2)
-      continue;
-    low= REALmax;
-    high= -REALmax;
-    for (i=numpoints, coord=points+k; i--; coord += dim) {
-      minimize_(low, *coord);
-      maximize_(high, *coord);
-    }
-    if (newhigh > REALmax/2)
-      newhigh= high;
-    if (newlow < -REALmax/2)
-      newlow= low;
-    if (qh DELAUNAY && k == dim-1 && newhigh < newlow) {
-      qh_fprintf(qh ferr, 6021, "qhull input error: 'Qb%d' or 'QB%d' inverts paraboloid since high bound %.2g < low bound %.2g\n",
-               k, k, newhigh, newlow);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    scale= qh_divzero(newhigh - newlow, high - low,
-                  qh MINdenom_1, &nearzero);
-    if (nearzero) {
-      qh_fprintf(qh ferr, 6022, "qhull input error: %d'th dimension's new bounds [%2.2g, %2.2g] too wide for\nexisting bounds [%2.2g, %2.2g]\n",
-              k, newlow, newhigh, low, high);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    shift= (newlow * high - low * newhigh)/(high-low);
-    coord= points+k;
-    for (i=numpoints; i--; coord += dim)
-      *coord= *coord * scale + shift;
-    coord= points+k;
-    if (newlow < newhigh) {
-      mincoord= newlow;
-      maxcoord= newhigh;
-    }else {
-      mincoord= newhigh;
-      maxcoord= newlow;
-    }
-    for (i=numpoints; i--; coord += dim) {
-      minimize_(*coord, maxcoord);  /* because of roundoff error */
-      maximize_(*coord, mincoord);
-    }
-    trace0((qh ferr, 10, "qh_scalepoints: scaled %d'th coordinate [%2.2g, %2.2g] to [%.2g, %.2g] for %d points by %2.2g and shifted %2.2g\n",
-      k, low, high, newlow, newhigh, numpoints, scale, shift));
-  }
-} /* scalepoints */
-
-
-/*---------------------------------
-
-  qh_setdelaunay( dim, count, points )
-    project count points to dim-d paraboloid for Delaunay triangulation
-
-    dim is one more than the dimension of the input set
-    assumes dim is at least 3 (i.e., at least a 2-d Delaunay triangulation)
-
-    points is a dim*count realT array.  The first dim-1 coordinates
-    are the coordinates of the first input point.  array[dim] is
-    the first coordinate of the second input point.  array[2*dim] is
-    the first coordinate of the third input point.
-
-    if qh.last_low defined (i.e., 'Qbb' called qh_scalelast)
-      calls qh_scalelast to scale the last coordinate the same as the other points
-
-  returns:
-    for each point
-      sets point[dim-1] to sum of squares of coordinates
-    scale points to 'Qbb' if needed
-
-  notes:
-    to project one point, use
-      qh_setdelaunay(qh hull_dim, 1, point)
-
-    Do not use options 'Qbk', 'QBk', or 'QbB' since they scale
-    the coordinates after the original projection.
-
-*/
-void qh_setdelaunay(int dim, int count, pointT *points) {
-  int i, k;
-  coordT *coordp, coord;
-  realT paraboloid;
-
-  trace0((qh ferr, 11, "qh_setdelaunay: project %d points to paraboloid for Delaunay triangulation\n", count));
-  coordp= points;
-  for (i=0; i < count; i++) {
-    coord= *coordp++;
-    paraboloid= coord*coord;
-    for (k=dim-2; k--; ) {
-      coord= *coordp++;
-      paraboloid += coord*coord;
-    }
-    *coordp++ = paraboloid;
-  }
-  if (qh last_low < REALmax/2)
-    qh_scalelast(points, count, dim, qh last_low, qh last_high, qh last_newhigh);
-} /* setdelaunay */
-
-
-/*---------------------------------
-
-  qh_sethalfspace( dim, coords, nextp, normal, offset, feasible )
-    set point to dual of halfspace relative to feasible point
-    halfspace is normal coefficients and offset.
-
-  returns:
-    false and prints error if feasible point is outside of hull
-    overwrites coordinates for point at dim coords
-    nextp= next point (coords)
-    does not call qh_errexit
-
-  design:
-    compute distance from feasible point to halfspace
-    divide each normal coefficient by -dist
-*/
-boolT qh_sethalfspace(int dim, coordT *coords, coordT **nextp,
-         coordT *normal, coordT *offset, coordT *feasible) {
-  coordT *normp= normal, *feasiblep= feasible, *coordp= coords;
-  realT dist;
-  realT r; /*bug fix*/
-  int k;
-  boolT zerodiv;
-
-  dist= *offset;
-  for (k=dim; k--; )
-    dist += *(normp++) * *(feasiblep++);
-  if (dist > 0)
-    goto LABELerroroutside;
-  normp= normal;
-  if (dist < -qh MINdenom) {
-    for (k=dim; k--; )
-      *(coordp++)= *(normp++) / -dist;
-  }else {
-    for (k=dim; k--; ) {
-      *(coordp++)= qh_divzero(*(normp++), -dist, qh MINdenom_1, &zerodiv);
-      if (zerodiv)
-        goto LABELerroroutside;
-    }
-  }
-  *nextp= coordp;
-  if (qh IStracing >= 4) {
-    qh_fprintf(qh ferr, 8021, "qh_sethalfspace: halfspace at offset %6.2g to point: ", *offset);
-    for (k=dim, coordp=coords; k--; ) {
-      r= *coordp++;
-      qh_fprintf(qh ferr, 8022, " %6.2g", r);
-    }
-    qh_fprintf(qh ferr, 8023, "\n");
-  }
-  return True;
-LABELerroroutside:
-  feasiblep= feasible;
-  normp= normal;
-  qh_fprintf(qh ferr, 6023, "qhull input error: feasible point is not clearly inside halfspace\nfeasible point: ");
-  for (k=dim; k--; )
-    qh_fprintf(qh ferr, 8024, qh_REAL_1, r=*(feasiblep++));
-  qh_fprintf(qh ferr, 8025, "\n     halfspace: ");
-  for (k=dim; k--; )
-    qh_fprintf(qh ferr, 8026, qh_REAL_1, r=*(normp++));
-  qh_fprintf(qh ferr, 8027, "\n     at offset: ");
-  qh_fprintf(qh ferr, 8028, qh_REAL_1, *offset);
-  qh_fprintf(qh ferr, 8029, " and distance: ");
-  qh_fprintf(qh ferr, 8030, qh_REAL_1, dist);
-  qh_fprintf(qh ferr, 8031, "\n");
-  return False;
-} /* sethalfspace */
-
-/*---------------------------------
-
-  qh_sethalfspace_all( dim, count, halfspaces, feasible )
-    generate dual for halfspace intersection with feasible point
-    array of count halfspaces
-      each halfspace is normal coefficients followed by offset
-      the origin is inside the halfspace if the offset is negative
-    feasible is a point inside all halfspaces (http://www.qhull.org/html/qhalf.htm#notes)
-
-  returns:
-    malloc'd array of count X dim-1 points
-
-  notes:
-    call before qh_init_B or qh_initqhull_globals
-    free memory when done
-    unused/untested code: please email bradb@shore.net if this works ok for you
-    if using option 'Fp', qh->feasible_point must be set (e.g., to 'feasible')
-    qh->feasible_point is a malloc'd array that is freed by qh_freebuffers.
-
-  design:
-    see qh_sethalfspace
-*/
-coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feasible) {
-  int i, newdim;
-  pointT *newpoints;
-  coordT *coordp, *normalp, *offsetp;
-
-  trace0((qh ferr, 12, "qh_sethalfspace_all: compute dual for halfspace intersection\n"));
-  newdim= dim - 1;
-  if (!(newpoints=(coordT*)qh_malloc(count*newdim*sizeof(coordT)))){
-    qh_fprintf(qh ferr, 6024, "qhull error: insufficient memory to compute dual of %d halfspaces\n",
-          count);
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  coordp= newpoints;
-  normalp= halfspaces;
-  for (i=0; i < count; i++) {
-    offsetp= normalp + newdim;
-    if (!qh_sethalfspace(newdim, coordp, &coordp, normalp, offsetp, feasible)) {
-      qh_free(newpoints);  /* feasible is not inside halfspace as reported by qh_sethalfspace */
-      qh_fprintf(qh ferr, 8032, "The halfspace was at index %d\n", i);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    normalp= offsetp + 1;
-  }
-  return newpoints;
-} /* sethalfspace_all */
-
-
-/*---------------------------------
-
-  qh_sharpnewfacets()
-
-  returns:
-    true if could be an acute angle (facets in different quadrants)
-
-  notes:
-    for qh_findbest
-
-  design:
-    for all facets on qh.newfacet_list
-      if two facets are in different quadrants
-        set issharp
-*/
-boolT qh_sharpnewfacets(void) {
-  facetT *facet;
-  boolT issharp = False;
-  int *quadrant, k;
-
-  quadrant= (int*)qh_memalloc(qh hull_dim * sizeof(int));
-  FORALLfacet_(qh newfacet_list) {
-    if (facet == qh newfacet_list) {
-      for (k=qh hull_dim; k--; )
-        quadrant[ k]= (facet->normal[ k] > 0);
-    }else {
-      for (k=qh hull_dim; k--; ) {
-        if (quadrant[ k] != (facet->normal[ k] > 0)) {
-          issharp= True;
-          break;
-        }
-      }
-    }
-    if (issharp)
-      break;
-  }
-  qh_memfree( quadrant, qh hull_dim * sizeof(int));
-  trace3((qh ferr, 3001, "qh_sharpnewfacets: %d\n", issharp));
-  return issharp;
-} /* sharpnewfacets */
-
-/*---------------------------------
-
-  qh_voronoi_center( dim, points )
-    return Voronoi center for a set of points
-    dim is the original dimension of the points
-    gh.gm_matrix/qh.gm_row are scratch buffers
-
-  returns:
-    center as a temporary point (qh_memalloc)
-    if non-simplicial,
-      returns center for max simplex of points
-
-  notes:
-    only called by qh_facetcenter
-    from Bowyer & Woodwark, A Programmer's Geometry, 1983, p. 65
-
-  design:
-    if non-simplicial
-      determine max simplex for points
-    translate point0 of simplex to origin
-    compute sum of squares of diagonal
-    compute determinate
-    compute Voronoi center (see Bowyer & Woodwark)
-*/
-pointT *qh_voronoi_center(int dim, setT *points) {
-  pointT *point, **pointp, *point0;
-  pointT *center= (pointT*)qh_memalloc(qh center_size);
-  setT *simplex;
-  int i, j, k, size= qh_setsize(points);
-  coordT *gmcoord;
-  realT *diffp, sum2, *sum2row, *sum2p, det, factor;
-  boolT nearzero, infinite;
-
-  if (size == dim+1)
-    simplex= points;
-  else if (size < dim+1) {
-    qh_memfree(center, qh center_size);
-    qh_fprintf(qh ferr, 6025, "qhull internal error (qh_voronoi_center):\n  need at least %d points to construct a Voronoi center\n",
-             dim+1);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-    simplex= points;  /* never executed -- avoids warning */
-  }else {
-    simplex= qh_settemp(dim+1);
-    qh_maxsimplex(dim, points, NULL, 0, &simplex);
-  }
-  point0= SETfirstt_(simplex, pointT);
-  gmcoord= qh gm_matrix;
-  for (k=0; k < dim; k++) {
-    qh gm_row[k]= gmcoord;
-    FOREACHpoint_(simplex) {
-      if (point != point0)
-        *(gmcoord++)= point[k] - point0[k];
-    }
-  }
-  sum2row= gmcoord;
-  for (i=0; i < dim; i++) {
-    sum2= 0.0;
-    for (k=0; k < dim; k++) {
-      diffp= qh gm_row[k] + i;
-      sum2 += *diffp * *diffp;
-    }
-    *(gmcoord++)= sum2;
-  }
-  det= qh_determinant(qh gm_row, dim, &nearzero);
-  factor= qh_divzero(0.5, det, qh MINdenom, &infinite);
-  if (infinite) {
-    for (k=dim; k--; )
-      center[k]= qh_INFINITE;
-    if (qh IStracing)
-      qh_printpoints(qh ferr, "qh_voronoi_center: at infinity for ", simplex);
-  }else {
-    for (i=0; i < dim; i++) {
-      gmcoord= qh gm_matrix;
-      sum2p= sum2row;
-      for (k=0; k < dim; k++) {
-        qh gm_row[k]= gmcoord;
-        if (k == i) {
-          for (j=dim; j--; )
-            *(gmcoord++)= *sum2p++;
-        }else {
-          FOREACHpoint_(simplex) {
-            if (point != point0)
-              *(gmcoord++)= point[k] - point0[k];
-          }
-        }
-      }
-      center[i]= qh_determinant(qh gm_row, dim, &nearzero)*factor + point0[i];
-    }
-#ifndef qh_NOtrace
-    if (qh IStracing >= 3) {
-      qh_fprintf(qh ferr, 8033, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor);
-      qh_printmatrix(qh ferr, "center:", ¢er, 1, dim);
-      if (qh IStracing >= 5) {
-        qh_printpoints(qh ferr, "points", simplex);
-        FOREACHpoint_(simplex)
-          qh_fprintf(qh ferr, 8034, "p%d dist %.2g, ", qh_pointid(point),
-                   qh_pointdist(point, center, dim));
-        qh_fprintf(qh ferr, 8035, "\n");
-      }
-    }
-#endif
-  }
-  if (simplex != points)
-    qh_settempfree(&simplex);
-  return center;
-} /* voronoi_center */
-
diff --git a/extern/libqhull/global.c b/extern/libqhull/global.c
deleted file mode 100644
index 0328fea7b91b..000000000000
--- a/extern/libqhull/global.c
+++ /dev/null
@@ -1,2217 +0,0 @@
-
-/*
  ---------------------------------
-
-   global.c
-   initializes all the globals of the qhull application
-
-   see README
-
-   see libqhull.h for qh.globals and function prototypes
-
-   see qhull_a.h for internal functions
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/global.c#17 $$Change: 2066 $
-   $DateTime: 2016/01/18 19:29:17 $$Author: bbarber $
- */
-
-#include "qhull_a.h"
-
-/*========= qh definition -- globals defined in libqhull.h =======================*/
-
-#if qh_QHpointer
-qhT *qh_qh= NULL;       /* pointer to all global variables */
-#else
-qhT qh_qh;              /* all global variables.
-                           Add "= {0}" if this causes a compiler error.
-                           Also qh_qhstat in stat.c and qhmem in mem.c.  */
-#endif
-
-/*----------------------------------
-
-  qh_version
-    version string by year and date
-    qh_version2 for Unix users and -V
-
-    the revision increases on code changes only
-
-  notes:
-    change date:    Changes.txt, Announce.txt, index.htm, README.txt,
-                    qhull-news.html, Eudora signatures, CMakeLists.txt
-    change version: README.txt, qh-get.htm, File_id.diz, Makefile.txt, CMakeLists.txt
-    check that CmakeLists @version is the same as qh_version2
-    change year:    Copying.txt
-    check download size
-    recompile user_eg.c, rbox.c, libqhull.c, qconvex.c, qdelaun.c qvoronoi.c, qhalf.c, testqset.c
-*/
-
-const char qh_version[]= "2015.2 2016/01/18";
-const char qh_version2[]= "qhull 7.2.0 (2015.2 2016/01/18)";
-
-/*---------------------------------
-
-  qh_appendprint( printFormat )
-    append printFormat to qh.PRINTout unless already defined
-*/
-void qh_appendprint(qh_PRINT format) {
-  int i;
-
-  for (i=0; i < qh_PRINTEND; i++) {
-    if (qh PRINTout[i] == format && format != qh_PRINTqhull)
-      break;
-    if (!qh PRINTout[i]) {
-      qh PRINTout[i]= format;
-      break;
-    }
-  }
-} /* appendprint */
-
-/*---------------------------------
-
-  qh_checkflags( commandStr, hiddenFlags )
-    errors if commandStr contains hiddenFlags
-    hiddenFlags starts and ends with a space and is space delimited (checked)
-
-  notes:
-    ignores first word (e.g., "qconvex i")
-    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
-
-  see:
-    qh_initflags() initializes Qhull according to commandStr
-*/
-void qh_checkflags(char *command, char *hiddenflags) {
-  char *s= command, *t, *chkerr; /* qh_skipfilename is non-const */
-  char key, opt, prevopt;
-  char chkkey[]= "   ";
-  char chkopt[]=  "    ";
-  char chkopt2[]= "     ";
-  boolT waserr= False;
-
-  if (*hiddenflags != ' ' || hiddenflags[strlen(hiddenflags)-1] != ' ') {
-    qh_fprintf(qh ferr, 6026, "qhull error (qh_checkflags): hiddenflags must start and end with a space: \"%s\"", hiddenflags);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (strpbrk(hiddenflags, ",\n\r\t")) {
-    qh_fprintf(qh ferr, 6027, "qhull error (qh_checkflags): hiddenflags contains commas, newlines, or tabs: \"%s\"", hiddenflags);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  while (*s && !isspace(*s))  /* skip program name */
-    s++;
-  while (*s) {
-    while (*s && isspace(*s))
-      s++;
-    if (*s == '-')
-      s++;
-    if (!*s)
-      break;
-    key = *s++;
-    chkerr = NULL;
-    if (key == 'T' && (*s == 'I' || *s == 'O')) {  /* TI or TO 'file name' */
-      s= qh_skipfilename(++s);
-      continue;
-    }
-    chkkey[1]= key;
-    if (strstr(hiddenflags, chkkey)) {
-      chkerr= chkkey;
-    }else if (isupper(key)) {
-      opt= ' ';
-      prevopt= ' ';
-      chkopt[1]= key;
-      chkopt2[1]= key;
-      while (!chkerr && *s && !isspace(*s)) {
-        opt= *s++;
-        if (isalpha(opt)) {
-          chkopt[2]= opt;
-          if (strstr(hiddenflags, chkopt))
-            chkerr= chkopt;
-          if (prevopt != ' ') {
-            chkopt2[2]= prevopt;
-            chkopt2[3]= opt;
-            if (strstr(hiddenflags, chkopt2))
-              chkerr= chkopt2;
-          }
-        }else if (key == 'Q' && isdigit(opt) && prevopt != 'b'
-              && (prevopt == ' ' || islower(prevopt))) {
-            chkopt[2]= opt;
-            if (strstr(hiddenflags, chkopt))
-              chkerr= chkopt;
-        }else {
-          qh_strtod(s-1, &t);
-          if (s < t)
-            s= t;
-        }
-        prevopt= opt;
-      }
-    }
-    if (chkerr) {
-      *chkerr= '\'';
-      chkerr[strlen(chkerr)-1]=  '\'';
-      qh_fprintf(qh ferr, 6029, "qhull error: option %s is not used with this program.\n             It may be used with qhull.\n", chkerr);
-      waserr= True;
-    }
-  }
-  if (waserr)
-    qh_errexit(qh_ERRinput, NULL, NULL);
-} /* checkflags */
-
-/*---------------------------------
-
-  qh_clear_outputflags()
-    Clear output flags for QhullPoints
-*/
-void qh_clear_outputflags(void) {
-  int i,k;
-
-  qh ANNOTATEoutput= False;
-  qh DOintersections= False;
-  qh DROPdim= -1;
-  qh FORCEoutput= False;
-  qh GETarea= False;
-  qh GOODpoint= 0;
-  qh GOODpointp= NULL;
-  qh GOODthreshold= False;
-  qh GOODvertex= 0;
-  qh GOODvertexp= NULL;
-  qh IStracing= 0;
-  qh KEEParea= False;
-  qh KEEPmerge= False;
-  qh KEEPminArea= REALmax;
-  qh PRINTcentrums= False;
-  qh PRINTcoplanar= False;
-  qh PRINTdots= False;
-  qh PRINTgood= False;
-  qh PRINTinner= False;
-  qh PRINTneighbors= False;
-  qh PRINTnoplanes= False;
-  qh PRINToptions1st= False;
-  qh PRINTouter= False;
-  qh PRINTprecision= True;
-  qh PRINTridges= False;
-  qh PRINTspheres= False;
-  qh PRINTstatistics= False;
-  qh PRINTsummary= False;
-  qh PRINTtransparent= False;
-  qh SPLITthresholds= False;
-  qh TRACElevel= 0;
-  qh TRInormals= False;
-  qh USEstdout= False;
-  qh VERIFYoutput= False;
-  for (k=qh input_dim+1; k--; ) {  /* duplicated in qh_initqhull_buffers and qh_clear_outputflags */
-    qh lower_threshold[k]= -REALmax;
-    qh upper_threshold[k]= REALmax;
-    qh lower_bound[k]= -REALmax;
-    qh upper_bound[k]= REALmax;
-  }
-
-  for (i=0; i < qh_PRINTEND; i++) {
-    qh PRINTout[i]= qh_PRINTnone;
-  }
-
-  if (!qh qhull_commandsiz2)
-      qh qhull_commandsiz2= (int)strlen(qh qhull_command); /* WARN64 */
-  else {
-      qh qhull_command[qh qhull_commandsiz2]= '\0';
-  }
-  if (!qh qhull_optionsiz2)
-    qh qhull_optionsiz2= (int)strlen(qh qhull_options);  /* WARN64 */
-  else {
-    qh qhull_options[qh qhull_optionsiz2]= '\0';
-    qh qhull_optionlen= qh_OPTIONline;  /* start a new line */
-  }
-} /* clear_outputflags */
-
-/*---------------------------------
-
-  qh_clock()
-    return user CPU time in 100ths (qh_SECtick)
-    only defined for qh_CLOCKtype == 2
-
-  notes:
-    use first value to determine time 0
-    from Stevens '92 8.15
-*/
-unsigned long qh_clock(void) {
-
-#if (qh_CLOCKtype == 2)
-  struct tms time;
-  static long clktck;  /* initialized first call and never updated */
-  double ratio, cpu;
-  unsigned long ticks;
-
-  if (!clktck) {
-    if ((clktck= sysconf(_SC_CLK_TCK)) < 0) {
-      qh_fprintf(qh ferr, 6030, "qhull internal error (qh_clock): sysconf() failed.  Use qh_CLOCKtype 1 in user.h\n");
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-    }
-  }
-  if (times(&time) == -1) {
-    qh_fprintf(qh ferr, 6031, "qhull internal error (qh_clock): times() failed.  Use qh_CLOCKtype 1 in user.h\n");
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  ratio= qh_SECticks / (double)clktck;
-  ticks= time.tms_utime * ratio;
-  return ticks;
-#else
-  qh_fprintf(qh ferr, 6032, "qhull internal error (qh_clock): use qh_CLOCKtype 2 in user.h\n");
-  qh_errexit(qh_ERRqhull, NULL, NULL); /* never returns */
-  return 0;
-#endif
-} /* clock */
-
-/*---------------------------------
-
-  qh_freebuffers()
-    free up global memory buffers
-
-  notes:
-    must match qh_initbuffers()
-*/
-void qh_freebuffers(void) {
-
-  trace5((qh ferr, 5001, "qh_freebuffers: freeing up global memory buffers\n"));
-  /* allocated by qh_initqhull_buffers */
-  qh_memfree(qh NEARzero, qh hull_dim * sizeof(realT));
-  qh_memfree(qh lower_threshold, (qh input_dim+1) * sizeof(realT));
-  qh_memfree(qh upper_threshold, (qh input_dim+1) * sizeof(realT));
-  qh_memfree(qh lower_bound, (qh input_dim+1) * sizeof(realT));
-  qh_memfree(qh upper_bound, (qh input_dim+1) * sizeof(realT));
-  qh_memfree(qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT));
-  qh_memfree(qh gm_row, (qh hull_dim+1) * sizeof(coordT *));
-  qh NEARzero= qh lower_threshold= qh upper_threshold= NULL;
-  qh lower_bound= qh upper_bound= NULL;
-  qh gm_matrix= NULL;
-  qh gm_row= NULL;
-  qh_setfree(&qh other_points);
-  qh_setfree(&qh del_vertices);
-  qh_setfree(&qh coplanarfacetset);
-  if (qh line)                /* allocated by qh_readinput, freed if no error */
-    qh_free(qh line);
-  if (qh half_space)
-    qh_free(qh half_space);
-  if (qh temp_malloc)
-    qh_free(qh temp_malloc);
-  if (qh feasible_point)      /* allocated by qh_readfeasible */
-    qh_free(qh feasible_point);
-  if (qh feasible_string)     /* allocated by qh_initflags */
-    qh_free(qh feasible_string);
-  qh line= qh feasible_string= NULL;
-  qh half_space= qh feasible_point= qh temp_malloc= NULL;
-  /* usually allocated by qh_readinput */
-  if (qh first_point && qh POINTSmalloc) {
-    qh_free(qh first_point);
-    qh first_point= NULL;
-  }
-  if (qh input_points && qh input_malloc) { /* set by qh_joggleinput */
-    qh_free(qh input_points);
-    qh input_points= NULL;
-  }
-  trace5((qh ferr, 5002, "qh_freebuffers: finished\n"));
-} /* freebuffers */
-
-
-/*---------------------------------
-
-  qh_freebuild( allmem )
-    free global memory used by qh_initbuild and qh_buildhull
-    if !allmem,
-      does not free short memory (e.g., facetT, freed by qh_memfreeshort)
-
-  design:
-    free centrums
-    free each vertex
-    mark unattached ridges
-    for each facet
-      free ridges
-      free outside set, coplanar set, neighbor set, ridge set, vertex set
-      free facet
-    free hash table
-    free interior point
-    free merge set
-    free temporary sets
-*/
-void qh_freebuild(boolT allmem) {
-  facetT *facet;
-  vertexT *vertex;
-  ridgeT *ridge, **ridgep;
-  mergeT *merge, **mergep;
-
-  trace1((qh ferr, 1005, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
-  if (qh del_vertices)
-    qh_settruncate(qh del_vertices, 0);
-  if (allmem) {
-    while ((vertex= qh vertex_list)) {
-      if (vertex->next)
-        qh_delvertex(vertex);
-      else {
-        qh_memfree(vertex, (int)sizeof(vertexT));
-        qh newvertex_list= qh vertex_list= NULL;
-      }
-    }
-  }else if (qh VERTEXneighbors) {
-    FORALLvertices
-      qh_setfreelong(&(vertex->neighbors));
-  }
-  qh VERTEXneighbors= False;
-  qh GOODclosest= NULL;
-  if (allmem) {
-    FORALLfacets {
-      FOREACHridge_(facet->ridges)
-        ridge->seen= False;
-    }
-    FORALLfacets {
-      if (facet->visible) {
-        FOREACHridge_(facet->ridges) {
-          if (!otherfacet_(ridge, facet)->visible)
-            ridge->seen= True;  /* an unattached ridge */
-        }
-      }
-    }
-    while ((facet= qh facet_list)) {
-      FOREACHridge_(facet->ridges) {
-        if (ridge->seen) {
-          qh_setfree(&(ridge->vertices));
-          qh_memfree(ridge, (int)sizeof(ridgeT));
-        }else
-          ridge->seen= True;
-      }
-      qh_setfree(&(facet->outsideset));
-      qh_setfree(&(facet->coplanarset));
-      qh_setfree(&(facet->neighbors));
-      qh_setfree(&(facet->ridges));
-      qh_setfree(&(facet->vertices));
-      if (facet->next)
-        qh_delfacet(facet);
-      else {
-        qh_memfree(facet, (int)sizeof(facetT));
-        qh visible_list= qh newfacet_list= qh facet_list= NULL;
-      }
-    }
-  }else {
-    FORALLfacets {
-      qh_setfreelong(&(facet->outsideset));
-      qh_setfreelong(&(facet->coplanarset));
-      if (!facet->simplicial) {
-        qh_setfreelong(&(facet->neighbors));
-        qh_setfreelong(&(facet->ridges));
-        qh_setfreelong(&(facet->vertices));
-      }
-    }
-  }
-  qh_setfree(&(qh hash_table));
-  qh_memfree(qh interior_point, qh normal_size);
-  qh interior_point= NULL;
-  FOREACHmerge_(qh facet_mergeset)  /* usually empty */
-    qh_memfree(merge, (int)sizeof(mergeT));
-  qh facet_mergeset= NULL;  /* temp set */
-  qh degen_mergeset= NULL;  /* temp set */
-  qh_settempfree_all();
-} /* freebuild */
-
-/*---------------------------------
-
-  qh_freeqhull( allmem )
-    see qh_freeqhull2
-    if qh_QHpointer, frees qh_qh
-*/
-void qh_freeqhull(boolT allmem) {
-    qh_freeqhull2(allmem);
-#if qh_QHpointer
-    qh_free(qh_qh);
-    qh_qh= NULL;
-#endif
-}
-
-/*---------------------------------
-
-qh_freeqhull2( allmem )
-  free global memory and set qhT to 0
-  if !allmem,
-    does not free short memory (freed by qh_memfreeshort unless qh_NOmem)
-
-notes:
-  sets qh.NOerrexit in case caller forgets to
-  Does not throw errors
-
-see:
-  see qh_initqhull_start2()
-
-design:
-  free global and temporary memory from qh_initbuild and qh_buildhull
-  free buffers
-  free statistics
-*/
-void qh_freeqhull2(boolT allmem) {
-
-  qh NOerrexit= True;  /* no more setjmp since called at exit and ~QhullQh */
-  trace1((qh ferr, 1006, "qh_freeqhull: free global memory\n"));
-  qh_freebuild(allmem);
-  qh_freebuffers();
-  qh_freestatistics();
-#if qh_QHpointer
-  memset((char *)qh_qh, 0, sizeof(qhT));
-  /* qh_qh freed by caller, qh_freeqhull() */
-#else
-  memset((char *)&qh_qh, 0, sizeof(qhT));
-#endif
-  qh NOerrexit= True;
-} /* freeqhull2 */
-
-/*---------------------------------
-
-  qh_init_A( infile, outfile, errfile, argc, argv )
-    initialize memory and stdio files
-    convert input options to option string (qh.qhull_command)
-
-  notes:
-    infile may be NULL if qh_readpoints() is not called
-
-    errfile should always be defined.  It is used for reporting
-    errors.  outfile is used for output and format options.
-
-    argc/argv may be 0/NULL
-
-    called before error handling initialized
-    qh_errexit() may not be used
-*/
-void qh_init_A(FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
-  qh_meminit(errfile);
-  qh_initqhull_start(infile, outfile, errfile);
-  qh_init_qhull_command(argc, argv);
-} /* init_A */
-
-/*---------------------------------
-
-  qh_init_B( points, numpoints, dim, ismalloc )
-    initialize globals for points array
-
-    points has numpoints dim-dimensional points
-      points[0] is the first coordinate of the first point
-      points[1] is the second coordinate of the first point
-      points[dim] is the first coordinate of the second point
-
-    ismalloc=True
-      Qhull will call qh_free(points) on exit or input transformation
-    ismalloc=False
-      Qhull will allocate a new point array if needed for input transformation
-
-    qh.qhull_command
-      is the option string.
-      It is defined by qh_init_B(), qh_qhull_command(), or qh_initflags
-
-  returns:
-    if qh.PROJECTinput or (qh.DELAUNAY and qh.PROJECTdelaunay)
-      projects the input to a new point array
-
-        if qh.DELAUNAY,
-          qh.hull_dim is increased by one
-        if qh.ATinfinity,
-          qh_projectinput adds point-at-infinity for Delaunay tri.
-
-    if qh.SCALEinput
-      changes the upper and lower bounds of the input, see qh_scaleinput()
-
-    if qh.ROTATEinput
-      rotates the input by a random rotation, see qh_rotateinput()
-      if qh.DELAUNAY
-        rotates about the last coordinate
-
-  notes:
-    called after points are defined
-    qh_errexit() may be used
-*/
-void qh_init_B(coordT *points, int numpoints, int dim, boolT ismalloc) {
-  qh_initqhull_globals(points, numpoints, dim, ismalloc);
-  if (qhmem.LASTsize == 0)
-    qh_initqhull_mem();
-  /* mem.c and qset.c are initialized */
-  qh_initqhull_buffers();
-  qh_initthresholds(qh qhull_command);
-  if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay))
-    qh_projectinput();
-  if (qh SCALEinput)
-    qh_scaleinput();
-  if (qh ROTATErandom >= 0) {
-    qh_randommatrix(qh gm_matrix, qh hull_dim, qh gm_row);
-    if (qh DELAUNAY) {
-      int k, lastk= qh hull_dim-1;
-      for (k=0; k < lastk; k++) {
-        qh gm_row[k][lastk]= 0.0;
-        qh gm_row[lastk][k]= 0.0;
-      }
-      qh gm_row[lastk][lastk]= 1.0;
-    }
-    qh_gram_schmidt(qh hull_dim, qh gm_row);
-    qh_rotateinput(qh gm_row);
-  }
-} /* init_B */
-
-/*---------------------------------
-
-  qh_init_qhull_command( argc, argv )
-    build qh.qhull_command from argc/argv
-    Calls qh_exit if qhull_command is too short
-
-  returns:
-    a space-delimited string of options (just as typed)
-
-  notes:
-    makes option string easy to input and output
-
-    argc/argv may be 0/NULL
-*/
-void qh_init_qhull_command(int argc, char *argv[]) {
-
-  if (!qh_argv_to_command(argc, argv, qh qhull_command, (int)sizeof(qh qhull_command))){
-    /* Assumes qh.ferr is defined. */
-    qh_fprintf(qh ferr, 6033, "qhull input error: more than %d characters in command line\n",
-          (int)sizeof(qh qhull_command));
-    qh_exit(qh_ERRinput);  /* error reported, can not use qh_errexit */
-  }
-} /* init_qhull_command */
-
-/*---------------------------------
-
-  qh_initflags( commandStr )
-    set flags and initialized constants from commandStr
-    calls qh_exit() if qh->NOerrexit
-
-  returns:
-    sets qh.qhull_command to command if needed
-
-  notes:
-    ignores first word (e.g., "qhull d")
-    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
-
-  see:
-    qh_initthresholds() continues processing of 'Pdn' and 'PDn'
-    'prompt' in unix.c for documentation
-
-  design:
-    for each space-delimited option group
-      if top-level option
-        check syntax
-        append appropriate option to option string
-        set appropriate global variable or append printFormat to print options
-      else
-        for each sub-option
-          check syntax
-          append appropriate option to option string
-          set appropriate global variable or append printFormat to print options
-*/
-void qh_initflags(char *command) {
-  int k, i, lastproject;
-  char *s= command, *t, *prev_s, *start, key;
-  boolT isgeom= False, wasproject;
-  realT r;
-
-  if(qh NOerrexit){/* without this comment, segfault in gcc 4.4.0 mingw32 */
-    qh_fprintf(qh ferr, 6245, "qhull initflags error: qh.NOerrexit was not cleared before calling qh_initflags().  It should be cleared after setjmp().  Exit qhull.");
-    qh_exit(6245);
-  }
-  if (command <= &qh qhull_command[0] || command > &qh qhull_command[0] + sizeof(qh qhull_command)) {
-    if (command != &qh qhull_command[0]) {
-      *qh qhull_command= '\0';
-      strncat(qh qhull_command, command, sizeof(qh qhull_command)-strlen(qh qhull_command)-1);
-    }
-    while (*s && !isspace(*s))  /* skip program name */
-      s++;
-  }
-  while (*s) {
-    while (*s && isspace(*s))
-      s++;
-    if (*s == '-')
-      s++;
-    if (!*s)
-      break;
-    prev_s= s;
-    switch (*s++) {
-    case 'd':
-      qh_option("delaunay", NULL, NULL);
-      qh DELAUNAY= True;
-      break;
-    case 'f':
-      qh_option("facets", NULL, NULL);
-      qh_appendprint(qh_PRINTfacets);
-      break;
-    case 'i':
-      qh_option("incidence", NULL, NULL);
-      qh_appendprint(qh_PRINTincidences);
-      break;
-    case 'm':
-      qh_option("mathematica", NULL, NULL);
-      qh_appendprint(qh_PRINTmathematica);
-      break;
-    case 'n':
-      qh_option("normals", NULL, NULL);
-      qh_appendprint(qh_PRINTnormals);
-      break;
-    case 'o':
-      qh_option("offFile", NULL, NULL);
-      qh_appendprint(qh_PRINToff);
-      break;
-    case 'p':
-      qh_option("points", NULL, NULL);
-      qh_appendprint(qh_PRINTpoints);
-      break;
-    case 's':
-      qh_option("summary", NULL, NULL);
-      qh PRINTsummary= True;
-      break;
-    case 'v':
-      qh_option("voronoi", NULL, NULL);
-      qh VORONOI= True;
-      qh DELAUNAY= True;
-      break;
-    case 'A':
-      if (!isdigit(*s) && *s != '.' && *s != '-')
-        qh_fprintf(qh ferr, 7002, "qhull warning: no maximum cosine angle given for option 'An'.  Ignored.\n");
-      else {
-        if (*s == '-') {
-          qh premerge_cos= -qh_strtod(s, &s);
-          qh_option("Angle-premerge-", NULL, &qh premerge_cos);
-          qh PREmerge= True;
-        }else {
-          qh postmerge_cos= qh_strtod(s, &s);
-          qh_option("Angle-postmerge", NULL, &qh postmerge_cos);
-          qh POSTmerge= True;
-        }
-        qh MERGING= True;
-      }
-      break;
-    case 'C':
-      if (!isdigit(*s) && *s != '.' && *s != '-')
-        qh_fprintf(qh ferr, 7003, "qhull warning: no centrum radius given for option 'Cn'.  Ignored.\n");
-      else {
-        if (*s == '-') {
-          qh premerge_centrum= -qh_strtod(s, &s);
-          qh_option("Centrum-premerge-", NULL, &qh premerge_centrum);
-          qh PREmerge= True;
-        }else {
-          qh postmerge_centrum= qh_strtod(s, &s);
-          qh_option("Centrum-postmerge", NULL, &qh postmerge_centrum);
-          qh POSTmerge= True;
-        }
-        qh MERGING= True;
-      }
-      break;
-    case 'E':
-      if (*s == '-')
-        qh_fprintf(qh ferr, 7004, "qhull warning: negative maximum roundoff given for option 'An'.  Ignored.\n");
-      else if (!isdigit(*s))
-        qh_fprintf(qh ferr, 7005, "qhull warning: no maximum roundoff given for option 'En'.  Ignored.\n");
-      else {
-        qh DISTround= qh_strtod(s, &s);
-        qh_option("Distance-roundoff", NULL, &qh DISTround);
-        qh SETroundoff= True;
-      }
-      break;
-    case 'H':
-      start= s;
-      qh HALFspace= True;
-      qh_strtod(s, &t);
-      while (t > s)  {
-        if (*t && !isspace(*t)) {
-          if (*t == ',')
-            t++;
-          else
-            qh_fprintf(qh ferr, 7006, "qhull warning: origin for Halfspace intersection should be 'Hn,n,n,...'\n");
-        }
-        s= t;
-        qh_strtod(s, &t);
-      }
-      if (start < t) {
-        if (!(qh feasible_string= (char*)calloc((size_t)(t-start+1), (size_t)1))) {
-          qh_fprintf(qh ferr, 6034, "qhull error: insufficient memory for 'Hn,n,n'\n");
-          qh_errexit(qh_ERRmem, NULL, NULL);
-        }
-        strncpy(qh feasible_string, start, (size_t)(t-start));
-        qh_option("Halfspace-about", NULL, NULL);
-        qh_option(qh feasible_string, NULL, NULL);
-      }else
-        qh_option("Halfspace", NULL, NULL);
-      break;
-    case 'R':
-      if (!isdigit(*s))
-        qh_fprintf(qh ferr, 7007, "qhull warning: missing random perturbation for option 'Rn'.  Ignored\n");
-      else {
-        qh RANDOMfactor= qh_strtod(s, &s);
-        qh_option("Random_perturb", NULL, &qh RANDOMfactor);
-        qh RANDOMdist= True;
-      }
-      break;
-    case 'V':
-      if (!isdigit(*s) && *s != '-')
-        qh_fprintf(qh ferr, 7008, "qhull warning: missing visible distance for option 'Vn'.  Ignored\n");
-      else {
-        qh MINvisible= qh_strtod(s, &s);
-        qh_option("Visible", NULL, &qh MINvisible);
-      }
-      break;
-    case 'U':
-      if (!isdigit(*s) && *s != '-')
-        qh_fprintf(qh ferr, 7009, "qhull warning: missing coplanar distance for option 'Un'.  Ignored\n");
-      else {
-        qh MAXcoplanar= qh_strtod(s, &s);
-        qh_option("U-coplanar", NULL, &qh MAXcoplanar);
-      }
-      break;
-    case 'W':
-      if (*s == '-')
-        qh_fprintf(qh ferr, 7010, "qhull warning: negative outside width for option 'Wn'.  Ignored.\n");
-      else if (!isdigit(*s))
-        qh_fprintf(qh ferr, 7011, "qhull warning: missing outside width for option 'Wn'.  Ignored\n");
-      else {
-        qh MINoutside= qh_strtod(s, &s);
-        qh_option("W-outside", NULL, &qh MINoutside);
-        qh APPROXhull= True;
-      }
-      break;
-    /************  sub menus ***************/
-    case 'F':
-      while (*s && !isspace(*s)) {
-        switch (*s++) {
-        case 'a':
-          qh_option("Farea", NULL, NULL);
-          qh_appendprint(qh_PRINTarea);
-          qh GETarea= True;
-          break;
-        case 'A':
-          qh_option("FArea-total", NULL, NULL);
-          qh GETarea= True;
-          break;
-        case 'c':
-          qh_option("Fcoplanars", NULL, NULL);
-          qh_appendprint(qh_PRINTcoplanars);
-          break;
-        case 'C':
-          qh_option("FCentrums", NULL, NULL);
-          qh_appendprint(qh_PRINTcentrums);
-          break;
-        case 'd':
-          qh_option("Fd-cdd-in", NULL, NULL);
-          qh CDDinput= True;
-          break;
-        case 'D':
-          qh_option("FD-cdd-out", NULL, NULL);
-          qh CDDoutput= True;
-          break;
-        case 'F':
-          qh_option("FFacets-xridge", NULL, NULL);
-          qh_appendprint(qh_PRINTfacets_xridge);
-          break;
-        case 'i':
-          qh_option("Finner", NULL, NULL);
-          qh_appendprint(qh_PRINTinner);
-          break;
-        case 'I':
-          qh_option("FIDs", NULL, NULL);
-          qh_appendprint(qh_PRINTids);
-          break;
-        case 'm':
-          qh_option("Fmerges", NULL, NULL);
-          qh_appendprint(qh_PRINTmerges);
-          break;
-        case 'M':
-          qh_option("FMaple", NULL, NULL);
-          qh_appendprint(qh_PRINTmaple);
-          break;
-        case 'n':
-          qh_option("Fneighbors", NULL, NULL);
-          qh_appendprint(qh_PRINTneighbors);
-          break;
-        case 'N':
-          qh_option("FNeighbors-vertex", NULL, NULL);
-          qh_appendprint(qh_PRINTvneighbors);
-          break;
-        case 'o':
-          qh_option("Fouter", NULL, NULL);
-          qh_appendprint(qh_PRINTouter);
-          break;
-        case 'O':
-          if (qh PRINToptions1st) {
-            qh_option("FOptions", NULL, NULL);
-            qh_appendprint(qh_PRINToptions);
-          }else
-            qh PRINToptions1st= True;
-          break;
-        case 'p':
-          qh_option("Fpoint-intersect", NULL, NULL);
-          qh_appendprint(qh_PRINTpointintersect);
-          break;
-        case 'P':
-          qh_option("FPoint-nearest", NULL, NULL);
-          qh_appendprint(qh_PRINTpointnearest);
-          break;
-        case 'Q':
-          qh_option("FQhull", NULL, NULL);
-          qh_appendprint(qh_PRINTqhull);
-          break;
-        case 's':
-          qh_option("Fsummary", NULL, NULL);
-          qh_appendprint(qh_PRINTsummary);
-          break;
-        case 'S':
-          qh_option("FSize", NULL, NULL);
-          qh_appendprint(qh_PRINTsize);
-          qh GETarea= True;
-          break;
-        case 't':
-          qh_option("Ftriangles", NULL, NULL);
-          qh_appendprint(qh_PRINTtriangles);
-          break;
-        case 'v':
-          /* option set in qh_initqhull_globals */
-          qh_appendprint(qh_PRINTvertices);
-          break;
-        case 'V':
-          qh_option("FVertex-average", NULL, NULL);
-          qh_appendprint(qh_PRINTaverage);
-          break;
-        case 'x':
-          qh_option("Fxtremes", NULL, NULL);
-          qh_appendprint(qh_PRINTextremes);
-          break;
-        default:
-          s--;
-          qh_fprintf(qh ferr, 7012, "qhull warning: unknown 'F' output option %c, rest ignored\n", (int)s[0]);
-          while (*++s && !isspace(*s));
-          break;
-        }
-      }
-      break;
-    case 'G':
-      isgeom= True;
-      qh_appendprint(qh_PRINTgeom);
-      while (*s && !isspace(*s)) {
-        switch (*s++) {
-        case 'a':
-          qh_option("Gall-points", NULL, NULL);
-          qh PRINTdots= True;
-          break;
-        case 'c':
-          qh_option("Gcentrums", NULL, NULL);
-          qh PRINTcentrums= True;
-          break;
-        case 'h':
-          qh_option("Gintersections", NULL, NULL);
-          qh DOintersections= True;
-          break;
-        case 'i':
-          qh_option("Ginner", NULL, NULL);
-          qh PRINTinner= True;
-          break;
-        case 'n':
-          qh_option("Gno-planes", NULL, NULL);
-          qh PRINTnoplanes= True;
-          break;
-        case 'o':
-          qh_option("Gouter", NULL, NULL);
-          qh PRINTouter= True;
-          break;
-        case 'p':
-          qh_option("Gpoints", NULL, NULL);
-          qh PRINTcoplanar= True;
-          break;
-        case 'r':
-          qh_option("Gridges", NULL, NULL);
-          qh PRINTridges= True;
-          break;
-        case 't':
-          qh_option("Gtransparent", NULL, NULL);
-          qh PRINTtransparent= True;
-          break;
-        case 'v':
-          qh_option("Gvertices", NULL, NULL);
-          qh PRINTspheres= True;
-          break;
-        case 'D':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 6035, "qhull input error: missing dimension for option 'GDn'\n");
-          else {
-            if (qh DROPdim >= 0)
-              qh_fprintf(qh ferr, 7013, "qhull warning: can only drop one dimension.  Previous 'GD%d' ignored\n",
-                   qh DROPdim);
-            qh DROPdim= qh_strtol(s, &s);
-            qh_option("GDrop-dim", &qh DROPdim, NULL);
-          }
-          break;
-        default:
-          s--;
-          qh_fprintf(qh ferr, 7014, "qhull warning: unknown 'G' print option %c, rest ignored\n", (int)s[0]);
-          while (*++s && !isspace(*s));
-          break;
-        }
-      }
-      break;
-    case 'P':
-      while (*s && !isspace(*s)) {
-        switch (*s++) {
-        case 'd': case 'D':  /* see qh_initthresholds() */
-          key= s[-1];
-          i= qh_strtol(s, &s);
-          r= 0;
-          if (*s == ':') {
-            s++;
-            r= qh_strtod(s, &s);
-          }
-          if (key == 'd')
-            qh_option("Pdrop-facets-dim-less", &i, &r);
-          else
-            qh_option("PDrop-facets-dim-more", &i, &r);
-          break;
-        case 'g':
-          qh_option("Pgood-facets", NULL, NULL);
-          qh PRINTgood= True;
-          break;
-        case 'G':
-          qh_option("PGood-facet-neighbors", NULL, NULL);
-          qh PRINTneighbors= True;
-          break;
-        case 'o':
-          qh_option("Poutput-forced", NULL, NULL);
-          qh FORCEoutput= True;
-          break;
-        case 'p':
-          qh_option("Pprecision-ignore", NULL, NULL);
-          qh PRINTprecision= False;
-          break;
-        case 'A':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 6036, "qhull input error: missing facet count for keep area option 'PAn'\n");
-          else {
-            qh KEEParea= qh_strtol(s, &s);
-            qh_option("PArea-keep", &qh KEEParea, NULL);
-            qh GETarea= True;
-          }
-          break;
-        case 'F':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 6037, "qhull input error: missing facet area for option 'PFn'\n");
-          else {
-            qh KEEPminArea= qh_strtod(s, &s);
-            qh_option("PFacet-area-keep", NULL, &qh KEEPminArea);
-            qh GETarea= True;
-          }
-          break;
-        case 'M':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 6038, "qhull input error: missing merge count for option 'PMn'\n");
-          else {
-            qh KEEPmerge= qh_strtol(s, &s);
-            qh_option("PMerge-keep", &qh KEEPmerge, NULL);
-          }
-          break;
-        default:
-          s--;
-          qh_fprintf(qh ferr, 7015, "qhull warning: unknown 'P' print option %c, rest ignored\n", (int)s[0]);
-          while (*++s && !isspace(*s));
-          break;
-        }
-      }
-      break;
-    case 'Q':
-      lastproject= -1;
-      while (*s && !isspace(*s)) {
-        switch (*s++) {
-        case 'b': case 'B':  /* handled by qh_initthresholds */
-          key= s[-1];
-          if (key == 'b' && *s == 'B') {
-            s++;
-            r= qh_DEFAULTbox;
-            qh SCALEinput= True;
-            qh_option("QbBound-unit-box", NULL, &r);
-            break;
-          }
-          if (key == 'b' && *s == 'b') {
-            s++;
-            qh SCALElast= True;
-            qh_option("Qbbound-last", NULL, NULL);
-            break;
-          }
-          k= qh_strtol(s, &s);
-          r= 0.0;
-          wasproject= False;
-          if (*s == ':') {
-            s++;
-            if ((r= qh_strtod(s, &s)) == 0.0) {
-              t= s;            /* need true dimension for memory allocation */
-              while (*t && !isspace(*t)) {
-                if (toupper(*t++) == 'B'
-                 && k == qh_strtol(t, &t)
-                 && *t++ == ':'
-                 && qh_strtod(t, &t) == 0.0) {
-                  qh PROJECTinput++;
-                  trace2((qh ferr, 2004, "qh_initflags: project dimension %d\n", k));
-                  qh_option("Qb-project-dim", &k, NULL);
-                  wasproject= True;
-                  lastproject= k;
-                  break;
-                }
-              }
-            }
-          }
-          if (!wasproject) {
-            if (lastproject == k && r == 0.0)
-              lastproject= -1;  /* doesn't catch all possible sequences */
-            else if (key == 'b') {
-              qh SCALEinput= True;
-              if (r == 0.0)
-                r= -qh_DEFAULTbox;
-              qh_option("Qbound-dim-low", &k, &r);
-            }else {
-              qh SCALEinput= True;
-              if (r == 0.0)
-                r= qh_DEFAULTbox;
-              qh_option("QBound-dim-high", &k, &r);
-            }
-          }
-          break;
-        case 'c':
-          qh_option("Qcoplanar-keep", NULL, NULL);
-          qh KEEPcoplanar= True;
-          break;
-        case 'f':
-          qh_option("Qfurthest-outside", NULL, NULL);
-          qh BESToutside= True;
-          break;
-        case 'g':
-          qh_option("Qgood-facets-only", NULL, NULL);
-          qh ONLYgood= True;
-          break;
-        case 'i':
-          qh_option("Qinterior-keep", NULL, NULL);
-          qh KEEPinside= True;
-          break;
-        case 'm':
-          qh_option("Qmax-outside-only", NULL, NULL);
-          qh ONLYmax= True;
-          break;
-        case 'r':
-          qh_option("Qrandom-outside", NULL, NULL);
-          qh RANDOMoutside= True;
-          break;
-        case 's':
-          qh_option("Qsearch-initial-simplex", NULL, NULL);
-          qh ALLpoints= True;
-          break;
-        case 't':
-          qh_option("Qtriangulate", NULL, NULL);
-          qh TRIangulate= True;
-          break;
-        case 'T':
-          qh_option("QTestPoints", NULL, NULL);
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 6039, "qhull input error: missing number of test points for option 'QTn'\n");
-          else {
-            qh TESTpoints= qh_strtol(s, &s);
-            qh_option("QTestPoints", &qh TESTpoints, NULL);
-          }
-          break;
-        case 'u':
-          qh_option("QupperDelaunay", NULL, NULL);
-          qh UPPERdelaunay= True;
-          break;
-        case 'v':
-          qh_option("Qvertex-neighbors-convex", NULL, NULL);
-          qh TESTvneighbors= True;
-          break;
-        case 'x':
-          qh_option("Qxact-merge", NULL, NULL);
-          qh MERGEexact= True;
-          break;
-        case 'z':
-          qh_option("Qz-infinity-point", NULL, NULL);
-          qh ATinfinity= True;
-          break;
-        case '0':
-          qh_option("Q0-no-premerge", NULL, NULL);
-          qh NOpremerge= True;
-          break;
-        case '1':
-          if (!isdigit(*s)) {
-            qh_option("Q1-no-angle-sort", NULL, NULL);
-            qh ANGLEmerge= False;
-            break;
-          }
-          switch (*s++) {
-          case '0':
-            qh_option("Q10-no-narrow", NULL, NULL);
-            qh NOnarrow= True;
-            break;
-          case '1':
-            qh_option("Q11-trinormals Qtriangulate", NULL, NULL);
-            qh TRInormals= True;
-            qh TRIangulate= True;
-            break;
-          case '2':
-            qh_option("Q12-no-wide-dup", NULL, NULL);
-            qh NOwide= True;
-            break;
-          default:
-            s--;
-            qh_fprintf(qh ferr, 7016, "qhull warning: unknown 'Q' qhull option 1%c, rest ignored\n", (int)s[0]);
-            while (*++s && !isspace(*s));
-            break;
-          }
-          break;
-        case '2':
-          qh_option("Q2-no-merge-independent", NULL, NULL);
-          qh MERGEindependent= False;
-          goto LABELcheckdigit;
-          break; /* no warnings */
-        case '3':
-          qh_option("Q3-no-merge-vertices", NULL, NULL);
-          qh MERGEvertices= False;
-        LABELcheckdigit:
-          if (isdigit(*s))
-            qh_fprintf(qh ferr, 7017, "qhull warning: can not follow '1', '2', or '3' with a digit.  '%c' skipped.\n",
-                     *s++);
-          break;
-        case '4':
-          qh_option("Q4-avoid-old-into-new", NULL, NULL);
-          qh AVOIDold= True;
-          break;
-        case '5':
-          qh_option("Q5-no-check-outer", NULL, NULL);
-          qh SKIPcheckmax= True;
-          break;
-        case '6':
-          qh_option("Q6-no-concave-merge", NULL, NULL);
-          qh SKIPconvex= True;
-          break;
-        case '7':
-          qh_option("Q7-no-breadth-first", NULL, NULL);
-          qh VIRTUALmemory= True;
-          break;
-        case '8':
-          qh_option("Q8-no-near-inside", NULL, NULL);
-          qh NOnearinside= True;
-          break;
-        case '9':
-          qh_option("Q9-pick-furthest", NULL, NULL);
-          qh PICKfurthest= True;
-          break;
-        case 'G':
-          i= qh_strtol(s, &t);
-          if (qh GOODpoint)
-            qh_fprintf(qh ferr, 7018, "qhull warning: good point already defined for option 'QGn'.  Ignored\n");
-          else if (s == t)
-            qh_fprintf(qh ferr, 7019, "qhull warning: missing good point id for option 'QGn'.  Ignored\n");
-          else if (i < 0 || *s == '-') {
-            qh GOODpoint= i-1;
-            qh_option("QGood-if-dont-see-point", &i, NULL);
-          }else {
-            qh GOODpoint= i+1;
-            qh_option("QGood-if-see-point", &i, NULL);
-          }
-          s= t;
-          break;
-        case 'J':
-          if (!isdigit(*s) && *s != '-')
-            qh JOGGLEmax= 0.0;
-          else {
-            qh JOGGLEmax= (realT) qh_strtod(s, &s);
-            qh_option("QJoggle", NULL, &qh JOGGLEmax);
-          }
-          break;
-        case 'R':
-          if (!isdigit(*s) && *s != '-')
-            qh_fprintf(qh ferr, 7020, "qhull warning: missing random seed for option 'QRn'.  Ignored\n");
-          else {
-            qh ROTATErandom= i= qh_strtol(s, &s);
-            if (i > 0)
-              qh_option("QRotate-id", &i, NULL );
-            else if (i < -1)
-              qh_option("QRandom-seed", &i, NULL );
-          }
-          break;
-        case 'V':
-          i= qh_strtol(s, &t);
-          if (qh GOODvertex)
-            qh_fprintf(qh ferr, 7021, "qhull warning: good vertex already defined for option 'QVn'.  Ignored\n");
-          else if (s == t)
-            qh_fprintf(qh ferr, 7022, "qhull warning: no good point id given for option 'QVn'.  Ignored\n");
-          else if (i < 0) {
-            qh GOODvertex= i - 1;
-            qh_option("QV-good-facets-not-point", &i, NULL);
-          }else {
-            qh_option("QV-good-facets-point", &i, NULL);
-            qh GOODvertex= i + 1;
-          }
-          s= t;
-          break;
-        default:
-          s--;
-          qh_fprintf(qh ferr, 7023, "qhull warning: unknown 'Q' qhull option %c, rest ignored\n", (int)s[0]);
-          while (*++s && !isspace(*s));
-          break;
-        }
-      }
-      break;
-    case 'T':
-      while (*s && !isspace(*s)) {
-        if (isdigit(*s) || *s == '-')
-          qh IStracing= qh_strtol(s, &s);
-        else switch (*s++) {
-        case 'a':
-          qh_option("Tannotate-output", NULL, NULL);
-          qh ANNOTATEoutput= True;
-          break;
-        case 'c':
-          qh_option("Tcheck-frequently", NULL, NULL);
-          qh CHECKfrequently= True;
-          break;
-        case 's':
-          qh_option("Tstatistics", NULL, NULL);
-          qh PRINTstatistics= True;
-          break;
-        case 'v':
-          qh_option("Tverify", NULL, NULL);
-          qh VERIFYoutput= True;
-          break;
-        case 'z':
-          if (qh ferr == qh_FILEstderr) {
-            /* The C++ interface captures the output in qh_fprint_qhull() */
-            qh_option("Tz-stdout", NULL, NULL);
-            qh USEstdout= True;
-          }else if (!qh fout)
-            qh_fprintf(qh ferr, 7024, "qhull warning: output file undefined(stdout).  Option 'Tz' ignored.\n");
-          else {
-            qh_option("Tz-stdout", NULL, NULL);
-            qh USEstdout= True;
-            qh ferr= qh fout;
-            qhmem.ferr= qh fout;
-          }
-          break;
-        case 'C':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 7025, "qhull warning: missing point id for cone for trace option 'TCn'.  Ignored\n");
-          else {
-            i= qh_strtol(s, &s);
-            qh_option("TCone-stop", &i, NULL);
-            qh STOPcone= i + 1;
-          }
-          break;
-        case 'F':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 7026, "qhull warning: missing frequency count for trace option 'TFn'.  Ignored\n");
-          else {
-            qh REPORTfreq= qh_strtol(s, &s);
-            qh_option("TFacet-log", &qh REPORTfreq, NULL);
-            qh REPORTfreq2= qh REPORTfreq/2;  /* for tracemerging() */
-          }
-          break;
-        case 'I':
-          if (!isspace(*s))
-            qh_fprintf(qh ferr, 7027, "qhull warning: missing space between 'TI' and filename, %s\n", s);
-          while (isspace(*s))
-            s++;
-          t= qh_skipfilename(s);
-          {
-            char filename[qh_FILENAMElen];
-
-            qh_copyfilename(filename, (int)sizeof(filename), s, (int)(t-s));   /* WARN64 */
-            s= t;
-            if (!freopen(filename, "r", stdin)) {
-              qh_fprintf(qh ferr, 6041, "qhull error: could not open file \"%s\".", filename);
-              qh_errexit(qh_ERRinput, NULL, NULL);
-            }else {
-              qh_option("TInput-file", NULL, NULL);
-              qh_option(filename, NULL, NULL);
-            }
-          }
-          break;
-        case 'O':
-            if (!isspace(*s))
-                qh_fprintf(qh ferr, 7028, "qhull warning: missing space between 'TO' and filename, %s\n", s);
-            while (isspace(*s))
-                s++;
-            t= qh_skipfilename(s);
-            {
-              char filename[qh_FILENAMElen];
-
-              qh_copyfilename(filename, (int)sizeof(filename), s, (int)(t-s));  /* WARN64 */
-              s= t;
-              if (!qh fout) {
-                qh_fprintf(qh ferr, 6266, "qhull input warning: qh.fout was not set by caller.  Cannot use option 'TO' to redirect output.  Ignoring option 'TO'\n");
-              }else if (!freopen(filename, "w", qh fout)) {
-                qh_fprintf(qh ferr, 6044, "qhull error: could not open file \"%s\".", filename);
-                qh_errexit(qh_ERRinput, NULL, NULL);
-              }else {
-                qh_option("TOutput-file", NULL, NULL);
-              qh_option(filename, NULL, NULL);
-            }
-          }
-          break;
-        case 'P':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 7029, "qhull warning: missing point id for trace option 'TPn'.  Ignored\n");
-          else {
-            qh TRACEpoint= qh_strtol(s, &s);
-            qh_option("Trace-point", &qh TRACEpoint, NULL);
-          }
-          break;
-        case 'M':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 7030, "qhull warning: missing merge id for trace option 'TMn'.  Ignored\n");
-          else {
-            qh TRACEmerge= qh_strtol(s, &s);
-            qh_option("Trace-merge", &qh TRACEmerge, NULL);
-          }
-          break;
-        case 'R':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 7031, "qhull warning: missing rerun count for trace option 'TRn'.  Ignored\n");
-          else {
-            qh RERUN= qh_strtol(s, &s);
-            qh_option("TRerun", &qh RERUN, NULL);
-          }
-          break;
-        case 'V':
-          i= qh_strtol(s, &t);
-          if (s == t)
-            qh_fprintf(qh ferr, 7032, "qhull warning: missing furthest point id for trace option 'TVn'.  Ignored\n");
-          else if (i < 0) {
-            qh STOPpoint= i - 1;
-            qh_option("TV-stop-before-point", &i, NULL);
-          }else {
-            qh STOPpoint= i + 1;
-            qh_option("TV-stop-after-point", &i, NULL);
-          }
-          s= t;
-          break;
-        case 'W':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 7033, "qhull warning: missing max width for trace option 'TWn'.  Ignored\n");
-          else {
-            qh TRACEdist= (realT) qh_strtod(s, &s);
-            qh_option("TWide-trace", NULL, &qh TRACEdist);
-          }
-          break;
-        default:
-          s--;
-          qh_fprintf(qh ferr, 7034, "qhull warning: unknown 'T' trace option %c, rest ignored\n", (int)s[0]);
-          while (*++s && !isspace(*s));
-          break;
-        }
-      }
-      break;
-    default:
-      qh_fprintf(qh ferr, 7035, "qhull warning: unknown flag %c(%x)\n", (int)s[-1],
-               (int)s[-1]);
-      break;
-    }
-    if (s-1 == prev_s && *s && !isspace(*s)) {
-      qh_fprintf(qh ferr, 7036, "qhull warning: missing space after flag %c(%x); reserved for menu. Skipped.\n",
-               (int)*prev_s, (int)*prev_s);
-      while (*s && !isspace(*s))
-        s++;
-    }
-  }
-  if (qh STOPcone && qh JOGGLEmax < REALmax/2)
-    qh_fprintf(qh ferr, 7078, "qhull warning: 'TCn' (stopCone) ignored when used with 'QJn' (joggle)\n");
-  if (isgeom && !qh FORCEoutput && qh PRINTout[1])
-    qh_fprintf(qh ferr, 7037, "qhull warning: additional output formats are not compatible with Geomview\n");
-  /* set derived values in qh_initqhull_globals */
-} /* initflags */
-
-
-/*---------------------------------
-
-  qh_initqhull_buffers()
-    initialize global memory buffers
-
-  notes:
-    must match qh_freebuffers()
-*/
-void qh_initqhull_buffers(void) {
-  int k;
-
-  qh TEMPsize= (qhmem.LASTsize - sizeof(setT))/SETelemsize;
-  if (qh TEMPsize <= 0 || qh TEMPsize > qhmem.LASTsize)
-    qh TEMPsize= 8;  /* e.g., if qh_NOmem */
-  qh other_points= qh_setnew(qh TEMPsize);
-  qh del_vertices= qh_setnew(qh TEMPsize);
-  qh coplanarfacetset= qh_setnew(qh TEMPsize);
-  qh NEARzero= (realT *)qh_memalloc(qh hull_dim * sizeof(realT));
-  qh lower_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
-  qh upper_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
-  qh lower_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
-  qh upper_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
-  for (k=qh input_dim+1; k--; ) {  /* duplicated in qh_initqhull_buffers and qh_clear_outputflags */
-    qh lower_threshold[k]= -REALmax;
-    qh upper_threshold[k]= REALmax;
-    qh lower_bound[k]= -REALmax;
-    qh upper_bound[k]= REALmax;
-  }
-  qh gm_matrix= (coordT *)qh_memalloc((qh hull_dim+1) * qh hull_dim * sizeof(coordT));
-  qh gm_row= (coordT **)qh_memalloc((qh hull_dim+1) * sizeof(coordT *));
-} /* initqhull_buffers */
-
-/*---------------------------------
-
-  qh_initqhull_globals( points, numpoints, dim, ismalloc )
-    initialize globals
-    if ismalloc
-      points were malloc'd and qhull should free at end
-
-  returns:
-    sets qh.first_point, num_points, input_dim, hull_dim and others
-    seeds random number generator (seed=1 if tracing)
-    modifies qh.hull_dim if ((qh.DELAUNAY and qh.PROJECTdelaunay) or qh.PROJECTinput)
-    adjust user flags as needed
-    also checks DIM3 dependencies and constants
-
-  notes:
-    do not use qh_point() since an input transformation may move them elsewhere
-
-  see:
-    qh_initqhull_start() sets default values for non-zero globals
-
-  design:
-    initialize points array from input arguments
-    test for qh.ZEROcentrum
-      (i.e., use opposite vertex instead of cetrum for convexity testing)
-    initialize qh.CENTERtype, qh.normal_size,
-      qh.center_size, qh.TRACEpoint/level,
-    initialize and test random numbers
-    qh_initqhull_outputflags() -- adjust and test output flags
-*/
-void qh_initqhull_globals(coordT *points, int numpoints, int dim, boolT ismalloc) {
-  int seed, pointsneeded, extra= 0, i, randi, k;
-  realT randr;
-  realT factorial;
-
-  time_t timedata;
-
-  trace0((qh ferr, 13, "qh_initqhull_globals: for %s | %s\n", qh rbox_command,
-      qh qhull_command));
-  qh POINTSmalloc= ismalloc;
-  qh first_point= points;
-  qh num_points= numpoints;
-  qh hull_dim= qh input_dim= dim;
-  if (!qh NOpremerge && !qh MERGEexact && !qh PREmerge && qh JOGGLEmax > REALmax/2) {
-    qh MERGING= True;
-    if (qh hull_dim <= 4) {
-      qh PREmerge= True;
-      qh_option("_pre-merge", NULL, NULL);
-    }else {
-      qh MERGEexact= True;
-      qh_option("Qxact_merge", NULL, NULL);
-    }
-  }else if (qh MERGEexact)
-    qh MERGING= True;
-  if (!qh NOpremerge && qh JOGGLEmax > REALmax/2) {
-#ifdef qh_NOmerge
-    qh JOGGLEmax= 0.0;
-#endif
-  }
-  if (qh TRIangulate && qh JOGGLEmax < REALmax/2 && qh PRINTprecision)
-    qh_fprintf(qh ferr, 7038, "qhull warning: joggle('QJ') always produces simplicial output.  Triangulated output('Qt') does nothing.\n");
-  if (qh JOGGLEmax < REALmax/2 && qh DELAUNAY && !qh SCALEinput && !qh SCALElast) {
-    qh SCALElast= True;
-    qh_option("Qbbound-last-qj", NULL, NULL);
-  }
-  if (qh MERGING && !qh POSTmerge && qh premerge_cos > REALmax/2
-  && qh premerge_centrum == 0) {
-    qh ZEROcentrum= True;
-    qh ZEROall_ok= True;
-    qh_option("_zero-centrum", NULL, NULL);
-  }
-  if (qh JOGGLEmax < REALmax/2 && REALepsilon > 2e-8 && qh PRINTprecision)
-    qh_fprintf(qh ferr, 7039, "qhull warning: real epsilon, %2.2g, is probably too large for joggle('QJn')\nRecompile with double precision reals(see user.h).\n",
-          REALepsilon);
-#ifdef qh_NOmerge
-  if (qh MERGING) {
-    qh_fprintf(qh ferr, 6045, "qhull input error: merging not installed(qh_NOmerge + 'Qx', 'Cn' or 'An')\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-#endif
-  if (qh DELAUNAY && qh KEEPcoplanar && !qh KEEPinside) {
-    qh KEEPinside= True;
-    qh_option("Qinterior-keep", NULL, NULL);
-  }
-  if (qh DELAUNAY && qh HALFspace) {
-    qh_fprintf(qh ferr, 6046, "qhull input error: can not use Delaunay('d') or Voronoi('v') with halfspace intersection('H')\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (!qh DELAUNAY && (qh UPPERdelaunay || qh ATinfinity)) {
-    qh_fprintf(qh ferr, 6047, "qhull input error: use upper-Delaunay('Qu') or infinity-point('Qz') with Delaunay('d') or Voronoi('v')\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (qh UPPERdelaunay && qh ATinfinity) {
-    qh_fprintf(qh ferr, 6048, "qhull input error: can not use infinity-point('Qz') with upper-Delaunay('Qu')\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (qh SCALElast && !qh DELAUNAY && qh PRINTprecision)
-    qh_fprintf(qh ferr, 7040, "qhull input warning: option 'Qbb' (scale-last-coordinate) is normally used with 'd' or 'v'\n");
-  qh DOcheckmax= (!qh SKIPcheckmax && qh MERGING );
-  qh KEEPnearinside= (qh DOcheckmax && !(qh KEEPinside && qh KEEPcoplanar)
-                          && !qh NOnearinside);
-  if (qh MERGING)
-    qh CENTERtype= qh_AScentrum;
-  else if (qh VORONOI)
-    qh CENTERtype= qh_ASvoronoi;
-  if (qh TESTvneighbors && !qh MERGING) {
-    qh_fprintf(qh ferr, 6049, "qhull input error: test vertex neighbors('Qv') needs a merge option\n");
-    qh_errexit(qh_ERRinput, NULL ,NULL);
-  }
-  if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay)) {
-    qh hull_dim -= qh PROJECTinput;
-    if (qh DELAUNAY) {
-      qh hull_dim++;
-      if (qh ATinfinity)
-        extra= 1;
-    }
-  }
-  if (qh hull_dim <= 1) {
-    qh_fprintf(qh ferr, 6050, "qhull error: dimension %d must be > 1\n", qh hull_dim);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  for (k=2, factorial=1.0; k < qh hull_dim; k++)
-    factorial *= k;
-  qh AREAfactor= 1.0 / factorial;
-  trace2((qh ferr, 2005, "qh_initqhull_globals: initialize globals.  dim %d numpoints %d malloc? %d projected %d to hull_dim %d\n",
-        dim, numpoints, ismalloc, qh PROJECTinput, qh hull_dim));
-  qh normal_size= qh hull_dim * sizeof(coordT);
-  qh center_size= qh normal_size - sizeof(coordT);
-  pointsneeded= qh hull_dim+1;
-  if (qh hull_dim > qh_DIMmergeVertex) {
-    qh MERGEvertices= False;
-    qh_option("Q3-no-merge-vertices-dim-high", NULL, NULL);
-  }
-  if (qh GOODpoint)
-    pointsneeded++;
-#ifdef qh_NOtrace
-  if (qh IStracing) {
-    qh_fprintf(qh ferr, 6051, "qhull input error: tracing is not installed(qh_NOtrace in user.h)");
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-#endif
-  if (qh RERUN > 1) {
-    qh TRACElastrun= qh IStracing; /* qh_build_withrestart duplicates next conditional */
-    if (qh IStracing != -1)
-      qh IStracing= 0;
-  }else if (qh TRACEpoint != qh_IDunknown || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
-    qh TRACElevel= (qh IStracing? qh IStracing : 3);
-    qh IStracing= 0;
-  }
-  if (qh ROTATErandom == 0 || qh ROTATErandom == -1) {
-    seed= (int)time(&timedata);
-    if (qh ROTATErandom  == -1) {
-      seed= -seed;
-      qh_option("QRandom-seed", &seed, NULL );
-    }else
-      qh_option("QRotate-random", &seed, NULL);
-    qh ROTATErandom= seed;
-  }
-  seed= qh ROTATErandom;
-  if (seed == INT_MIN)    /* default value */
-    seed= 1;
-  else if (seed < 0)
-    seed= -seed;
-  qh_RANDOMseed_(seed);
-  randr= 0.0;
-  for (i=1000; i--; ) {
-    randi= qh_RANDOMint;
-    randr += randi;
-    if (randi > qh_RANDOMmax) {
-      qh_fprintf(qh ferr, 8036, "\
-qhull configuration error (qh_RANDOMmax in user.h):\n\
-   random integer %d > qh_RANDOMmax(%.8g)\n",
-               randi, qh_RANDOMmax);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-  }
-  qh_RANDOMseed_(seed);
-  randr = randr/1000;
-  if (randr < qh_RANDOMmax * 0.1
-  || randr > qh_RANDOMmax * 0.9)
-    qh_fprintf(qh ferr, 8037, "\
-qhull configuration warning (qh_RANDOMmax in user.h):\n\
-   average of 1000 random integers (%.2g) is much different than expected (%.2g).\n\
-   Is qh_RANDOMmax (%.2g) wrong?\n",
-             randr, qh_RANDOMmax * 0.5, qh_RANDOMmax);
-  qh RANDOMa= 2.0 * qh RANDOMfactor/qh_RANDOMmax;
-  qh RANDOMb= 1.0 - qh RANDOMfactor;
-  if (qh_HASHfactor < 1.1) {
-    qh_fprintf(qh ferr, 6052, "qhull internal error (qh_initqhull_globals): qh_HASHfactor %d must be at least 1.1.  Qhull uses linear hash probing\n",
-      qh_HASHfactor);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  if (numpoints+extra < pointsneeded) {
-    qh_fprintf(qh ferr, 6214, "qhull input error: not enough points(%d) to construct initial simplex (need %d)\n",
-            numpoints, pointsneeded);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  qh_initqhull_outputflags();
-} /* initqhull_globals */
-
-/*---------------------------------
-
-  qh_initqhull_mem(  )
-    initialize mem.c for qhull
-    qh.hull_dim and qh.normal_size determine some of the allocation sizes
-    if qh.MERGING,
-      includes ridgeT
-    calls qh_user_memsizes() to add up to 10 additional sizes for quick allocation
-      (see numsizes below)
-
-  returns:
-    mem.c already for qh_memalloc/qh_memfree (errors if called beforehand)
-
-  notes:
-    qh_produceoutput() prints memsizes
-
-*/
-void qh_initqhull_mem(void) {
-  int numsizes;
-  int i;
-
-  numsizes= 8+10;
-  qh_meminitbuffers(qh IStracing, qh_MEMalign, numsizes,
-                     qh_MEMbufsize,qh_MEMinitbuf);
-  qh_memsize((int)sizeof(vertexT));
-  if (qh MERGING) {
-    qh_memsize((int)sizeof(ridgeT));
-    qh_memsize((int)sizeof(mergeT));
-  }
-  qh_memsize((int)sizeof(facetT));
-  i= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;  /* ridge.vertices */
-  qh_memsize(i);
-  qh_memsize(qh normal_size);        /* normal */
-  i += SETelemsize;                 /* facet.vertices, .ridges, .neighbors */
-  qh_memsize(i);
-  qh_user_memsizes();
-  qh_memsetup();
-} /* initqhull_mem */
-
-/*---------------------------------
-
-  qh_initqhull_outputflags
-    initialize flags concerned with output
-
-  returns:
-    adjust user flags as needed
-
-  see:
-    qh_clear_outputflags() resets the flags
-
-  design:
-    test for qh.PRINTgood (i.e., only print 'good' facets)
-    check for conflicting print output options
-*/
-void qh_initqhull_outputflags(void) {
-  boolT printgeom= False, printmath= False, printcoplanar= False;
-  int i;
-
-  trace3((qh ferr, 3024, "qh_initqhull_outputflags: %s\n", qh qhull_command));
-  if (!(qh PRINTgood || qh PRINTneighbors)) {
-    if (qh KEEParea || qh KEEPminArea < REALmax/2 || qh KEEPmerge || qh DELAUNAY
-        || (!qh ONLYgood && (qh GOODvertex || qh GOODpoint))) {
-      qh PRINTgood= True;
-      qh_option("Pgood", NULL, NULL);
-    }
-  }
-  if (qh PRINTtransparent) {
-    if (qh hull_dim != 4 || !qh DELAUNAY || qh VORONOI || qh DROPdim >= 0) {
-      qh_fprintf(qh ferr, 6215, "qhull input error: transparent Delaunay('Gt') needs 3-d Delaunay('d') w/o 'GDn'\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    qh DROPdim = 3;
-    qh PRINTridges = True;
-  }
-  for (i=qh_PRINTEND; i--; ) {
-    if (qh PRINTout[i] == qh_PRINTgeom)
-      printgeom= True;
-    else if (qh PRINTout[i] == qh_PRINTmathematica || qh PRINTout[i] == qh_PRINTmaple)
-      printmath= True;
-    else if (qh PRINTout[i] == qh_PRINTcoplanars)
-      printcoplanar= True;
-    else if (qh PRINTout[i] == qh_PRINTpointnearest)
-      printcoplanar= True;
-    else if (qh PRINTout[i] == qh_PRINTpointintersect && !qh HALFspace) {
-      qh_fprintf(qh ferr, 6053, "qhull input error: option 'Fp' is only used for \nhalfspace intersection('Hn,n,n').\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }else if (qh PRINTout[i] == qh_PRINTtriangles && (qh HALFspace || qh VORONOI)) {
-      qh_fprintf(qh ferr, 6054, "qhull input error: option 'Ft' is not available for Voronoi vertices or halfspace intersection\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }else if (qh PRINTout[i] == qh_PRINTcentrums && qh VORONOI) {
-      qh_fprintf(qh ferr, 6055, "qhull input error: option 'FC' is not available for Voronoi vertices('v')\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }else if (qh PRINTout[i] == qh_PRINTvertices) {
-      if (qh VORONOI)
-        qh_option("Fvoronoi", NULL, NULL);
-      else
-        qh_option("Fvertices", NULL, NULL);
-    }
-  }
-  if (printcoplanar && qh DELAUNAY && qh JOGGLEmax < REALmax/2) {
-    if (qh PRINTprecision)
-      qh_fprintf(qh ferr, 7041, "qhull input warning: 'QJ' (joggle) will usually prevent coincident input sites for options 'Fc' and 'FP'\n");
-  }
-  if (printmath && (qh hull_dim > 3 || qh VORONOI)) {
-    qh_fprintf(qh ferr, 6056, "qhull input error: Mathematica and Maple output is only available for 2-d and 3-d convex hulls and 2-d Delaunay triangulations\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (printgeom) {
-    if (qh hull_dim > 4) {
-      qh_fprintf(qh ferr, 6057, "qhull input error: Geomview output is only available for 2-d, 3-d and 4-d\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    if (qh PRINTnoplanes && !(qh PRINTcoplanar + qh PRINTcentrums
-     + qh PRINTdots + qh PRINTspheres + qh DOintersections + qh PRINTridges)) {
-      qh_fprintf(qh ferr, 6058, "qhull input error: no output specified for Geomview\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    if (qh VORONOI && (qh hull_dim > 3 || qh DROPdim >= 0)) {
-      qh_fprintf(qh ferr, 6059, "qhull input error: Geomview output for Voronoi diagrams only for 2-d\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    /* can not warn about furthest-site Geomview output: no lower_threshold */
-    if (qh hull_dim == 4 && qh DROPdim == -1 &&
-        (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
-      qh_fprintf(qh ferr, 7042, "qhull input warning: coplanars, vertices, and centrums output not\n\
-available for 4-d output(ignored).  Could use 'GDn' instead.\n");
-      qh PRINTcoplanar= qh PRINTspheres= qh PRINTcentrums= False;
-    }
-  }
-  if (!qh KEEPcoplanar && !qh KEEPinside && !qh ONLYgood) {
-    if ((qh PRINTcoplanar && qh PRINTspheres) || printcoplanar) {
-      if (qh QHULLfinished) {
-        qh_fprintf(qh ferr, 7072, "qhull output warning: ignoring coplanar points, option 'Qc' was not set for the first run of qhull.\n");
-      }else {
-        qh KEEPcoplanar = True;
-        qh_option("Qcoplanar", NULL, NULL);
-      }
-    }
-  }
-  qh PRINTdim= qh hull_dim;
-  if (qh DROPdim >=0) {    /* after Geomview checks */
-    if (qh DROPdim < qh hull_dim) {
-      qh PRINTdim--;
-      if (!printgeom || qh hull_dim < 3)
-        qh_fprintf(qh ferr, 7043, "qhull input warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh DROPdim);
-    }else
-      qh DROPdim= -1;
-  }else if (qh VORONOI) {
-    qh DROPdim= qh hull_dim-1;
-    qh PRINTdim= qh hull_dim-1;
-  }
-} /* qh_initqhull_outputflags */
-
-/*---------------------------------
-
-  qh_initqhull_start( infile, outfile, errfile )
-    allocate memory if needed and call qh_initqhull_start2()
-*/
-void qh_initqhull_start(FILE *infile, FILE *outfile, FILE *errfile) {
-
-#if qh_QHpointer
-  if (qh_qh) {
-    qh_fprintf(errfile, 6205, "qhull error (qh_initqhull_start): qh_qh already defined.  Call qh_save_qhull() first\n");
-    qh_exit(qh_ERRqhull);  /* no error handler */
-  }
-  if (!(qh_qh= (qhT *)qh_malloc(sizeof(qhT)))) {
-    qh_fprintf(errfile, 6060, "qhull error (qh_initqhull_start): insufficient memory\n");
-    qh_exit(qh_ERRmem);  /* no error handler */
-  }
-#endif
-  qh_initstatistics();
-  qh_initqhull_start2(infile, outfile, errfile);
-} /* initqhull_start */
-
-/*---------------------------------
-
-  qh_initqhull_start2( infile, outfile, errfile )
-    start initialization of qhull
-    initialize statistics, stdio, default values for global variables
-    assumes qh_qh is defined
-  notes:
-    report errors elsewhere, error handling and g_qhull_output [Qhull.cpp, QhullQh()] not in initialized
-  see:
-    qh_maxmin() determines the precision constants
-    qh_freeqhull2()
-*/
-void qh_initqhull_start2(FILE *infile, FILE *outfile, FILE *errfile) {
-  time_t timedata;
-  int seed;
-
-  qh_CPUclock; /* start the clock(for qh_clock).  One-shot. */
-#if qh_QHpointer
-  memset((char *)qh_qh, 0, sizeof(qhT));   /* every field is 0, FALSE, NULL */
-#else
-  memset((char *)&qh_qh, 0, sizeof(qhT));
-#endif
-  qh ANGLEmerge= True;
-  qh DROPdim= -1;
-  qh ferr= errfile;
-  qh fin= infile;
-  qh fout= outfile;
-  qh furthest_id= qh_IDunknown;
-  qh JOGGLEmax= REALmax;
-  qh KEEPminArea = REALmax;
-  qh last_low= REALmax;
-  qh last_high= REALmax;
-  qh last_newhigh= REALmax;
-  qh max_outside= 0.0;
-  qh max_vertex= 0.0;
-  qh MAXabs_coord= 0.0;
-  qh MAXsumcoord= 0.0;
-  qh MAXwidth= -REALmax;
-  qh MERGEindependent= True;
-  qh MINdenom_1= fmax_(1.0/REALmax, REALmin); /* used by qh_scalepoints */
-  qh MINoutside= 0.0;
-  qh MINvisible= REALmax;
-  qh MAXcoplanar= REALmax;
-  qh outside_err= REALmax;
-  qh premerge_centrum= 0.0;
-  qh premerge_cos= REALmax;
-  qh PRINTprecision= True;
-  qh PRINTradius= 0.0;
-  qh postmerge_cos= REALmax;
-  qh postmerge_centrum= 0.0;
-  qh ROTATErandom= INT_MIN;
-  qh MERGEvertices= True;
-  qh totarea= 0.0;
-  qh totvol= 0.0;
-  qh TRACEdist= REALmax;
-  qh TRACEpoint= qh_IDunknown; /* recompile or use 'TPn' */
-  qh tracefacet_id= UINT_MAX;  /* recompile to trace a facet */
-  qh tracevertex_id= UINT_MAX; /* recompile to trace a vertex */
-  seed= (int)time(&timedata);
-  qh_RANDOMseed_(seed);
-  qh run_id= qh_RANDOMint;
-  if(!qh run_id)
-      qh run_id++;  /* guarantee non-zero */
-  qh_option("run-id", &qh run_id, NULL);
-  strcat(qh qhull, "qhull");
-} /* initqhull_start2 */
-
-/*---------------------------------
-
-  qh_initthresholds( commandString )
-    set thresholds for printing and scaling from commandString
-
-  returns:
-    sets qh.GOODthreshold or qh.SPLITthreshold if 'Pd0D1' used
-
-  see:
-    qh_initflags(), 'Qbk' 'QBk' 'Pdk' and 'PDk'
-    qh_inthresholds()
-
-  design:
-    for each 'Pdn' or 'PDn' option
-      check syntax
-      set qh.lower_threshold or qh.upper_threshold
-    set qh.GOODthreshold if an unbounded threshold is used
-    set qh.SPLITthreshold if a bounded threshold is used
-*/
-void qh_initthresholds(char *command) {
-  realT value;
-  int idx, maxdim, k;
-  char *s= command; /* non-const due to strtol */
-  char key;
-
-  maxdim= qh input_dim;
-  if (qh DELAUNAY && (qh PROJECTdelaunay || qh PROJECTinput))
-    maxdim++;
-  while (*s) {
-    if (*s == '-')
-      s++;
-    if (*s == 'P') {
-      s++;
-      while (*s && !isspace(key= *s++)) {
-        if (key == 'd' || key == 'D') {
-          if (!isdigit(*s)) {
-            qh_fprintf(qh ferr, 7044, "qhull warning: no dimension given for Print option '%c' at: %s.  Ignored\n",
-                    key, s-1);
-            continue;
-          }
-          idx= qh_strtol(s, &s);
-          if (idx >= qh hull_dim) {
-            qh_fprintf(qh ferr, 7045, "qhull warning: dimension %d for Print option '%c' is >= %d.  Ignored\n",
-                idx, key, qh hull_dim);
-            continue;
-          }
-          if (*s == ':') {
-            s++;
-            value= qh_strtod(s, &s);
-            if (fabs((double)value) > 1.0) {
-              qh_fprintf(qh ferr, 7046, "qhull warning: value %2.4g for Print option %c is > +1 or < -1.  Ignored\n",
-                      value, key);
-              continue;
-            }
-          }else
-            value= 0.0;
-          if (key == 'd')
-            qh lower_threshold[idx]= value;
-          else
-            qh upper_threshold[idx]= value;
-        }
-      }
-    }else if (*s == 'Q') {
-      s++;
-      while (*s && !isspace(key= *s++)) {
-        if (key == 'b' && *s == 'B') {
-          s++;
-          for (k=maxdim; k--; ) {
-            qh lower_bound[k]= -qh_DEFAULTbox;
-            qh upper_bound[k]= qh_DEFAULTbox;
-          }
-        }else if (key == 'b' && *s == 'b')
-          s++;
-        else if (key == 'b' || key == 'B') {
-          if (!isdigit(*s)) {
-            qh_fprintf(qh ferr, 7047, "qhull warning: no dimension given for Qhull option %c.  Ignored\n",
-                    key);
-            continue;
-          }
-          idx= qh_strtol(s, &s);
-          if (idx >= maxdim) {
-            qh_fprintf(qh ferr, 7048, "qhull warning: dimension %d for Qhull option %c is >= %d.  Ignored\n",
-                idx, key, maxdim);
-            continue;
-          }
-          if (*s == ':') {
-            s++;
-            value= qh_strtod(s, &s);
-          }else if (key == 'b')
-            value= -qh_DEFAULTbox;
-          else
-            value= qh_DEFAULTbox;
-          if (key == 'b')
-            qh lower_bound[idx]= value;
-          else
-            qh upper_bound[idx]= value;
-        }
-      }
-    }else {
-      while (*s && !isspace(*s))
-        s++;
-    }
-    while (isspace(*s))
-      s++;
-  }
-  for (k=qh hull_dim; k--; ) {
-    if (qh lower_threshold[k] > -REALmax/2) {
-      qh GOODthreshold= True;
-      if (qh upper_threshold[k] < REALmax/2) {
-        qh SPLITthresholds= True;
-        qh GOODthreshold= False;
-        break;
-      }
-    }else if (qh upper_threshold[k] < REALmax/2)
-      qh GOODthreshold= True;
-  }
-} /* initthresholds */
-
-/*---------------------------------
-
-  qh_lib_check( qhullLibraryType, qhTsize, vertexTsize, ridgeTsize, facetTsize, setTsize, qhmemTsize )
-    Report error if library does not agree with caller
-
-  notes:
-    NOerrors -- qh_lib_check can not call qh_errexit()
-*/
-void qh_lib_check(int qhullLibraryType, int qhTsize, int vertexTsize, int ridgeTsize, int facetTsize, int setTsize, int qhmemTsize) {
-    boolT iserror= False;
-
-#if defined(_MSC_VER) && defined(_DEBUG) && defined(QHULL_CRTDBG)  /* user_r.h */
-    // _CrtSetBreakAlloc(744);  /* Break at memalloc {744}, or 'watch' _crtBreakAlloc */
-    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) );
-    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG );
-    _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR );
-    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG );
-    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );
-    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG );
-    _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR );
-#endif
-
-    if (qhullLibraryType==QHULL_NON_REENTRANT) { /* 0 */
-        if (qh_QHpointer) {
-            qh_fprintf_stderr(6246, "qh_lib_check: Incorrect qhull library called.  Caller uses a static qhT while library uses a dynamic qhT via qh_QHpointer.  Both caller and library are non-reentrant.\n");
-            iserror= True;
-        }
-    }else if (qhullLibraryType==QHULL_QH_POINTER) { /* 1 */
-        if (!qh_QHpointer) {
-            qh_fprintf_stderr(6247, "qh_lib_check: Incorrect qhull library called.  Caller uses a dynamic qhT via qh_QHpointer while library uses a static qhT.  Both caller and library are non-reentrant.\n");
-            iserror= True;
-        }
-    }else if (qhullLibraryType==QHULL_REENTRANT) { /* 2 */
-        qh_fprintf_stderr(6248, "qh_lib_check: Incorrect qhull library called.  Caller uses reentrant Qhull while library is non-reentrant\n");
-        iserror= True;
-    }else{
-        qh_fprintf_stderr(6262, "qh_lib_check: Expecting qhullLibraryType QHULL_NON_REENTRANT(0), QHULL_QH_POINTER(1), or QHULL_REENTRANT(2).  Got %d\n", qhullLibraryType);
-        iserror= True;
-    }
-    if (qhTsize != sizeof(qhT)) {
-        qh_fprintf_stderr(6249, "qh_lib_check: Incorrect qhull library called.  Size of qhT for caller is %d, but for library is %d.\n", qhTsize, sizeof(qhT));
-        iserror= True;
-    }
-    if (vertexTsize != sizeof(vertexT)) {
-        qh_fprintf_stderr(6250, "qh_lib_check: Incorrect qhull library called.  Size of vertexT for caller is %d, but for library is %d.\n", vertexTsize, sizeof(vertexT));
-        iserror= True;
-    }
-    if (ridgeTsize != sizeof(ridgeT)) {
-        qh_fprintf_stderr(6251, "qh_lib_check: Incorrect qhull library called.  Size of ridgeT for caller is %d, but for library is %d.\n", ridgeTsize, sizeof(ridgeT));
-        iserror= True;
-    }
-    if (facetTsize != sizeof(facetT)) {
-        qh_fprintf_stderr(6252, "qh_lib_check: Incorrect qhull library called.  Size of facetT for caller is %d, but for library is %d.\n", facetTsize, sizeof(facetT));
-        iserror= True;
-    }
-    if (setTsize && setTsize != sizeof(setT)) {
-        qh_fprintf_stderr(6253, "qh_lib_check: Incorrect qhull library called.  Size of setT for caller is %d, but for library is %d.\n", setTsize, sizeof(setT));
-        iserror= True;
-    }
-    if (qhmemTsize && qhmemTsize != sizeof(qhmemT)) {
-        qh_fprintf_stderr(6254, "qh_lib_check: Incorrect qhull library called.  Size of qhmemT for caller is %d, but for library is %d.\n", qhmemTsize, sizeof(qhmemT));
-        iserror= True;
-    }
-    if (iserror) {
-        if(qh_QHpointer){
-            qh_fprintf_stderr(6255, "qh_lib_check: Cannot continue.  Library '%s' uses a dynamic qhT via qh_QHpointer (e.g., qhull_p.so)\n", qh_version2);
-        }else{
-            qh_fprintf_stderr(6256, "qh_lib_check: Cannot continue.  Library '%s' uses a static qhT (e.g., libqhull.so)\n", qh_version2);
-        }
-        qh_exit(qh_ERRqhull);  /* can not use qh_errexit() */
-    }
-} /* lib_check */
-
-/*---------------------------------
-
-  qh_option( option, intVal, realVal )
-    add an option description to qh.qhull_options
-
-  notes:
-    NOerrors -- qh_option can not call qh_errexit() [qh_initqhull_start2]
-    will be printed with statistics ('Ts') and errors
-    strlen(option) < 40
-*/
-void qh_option(const char *option, int *i, realT *r) {
-  char buf[200];
-  int len, maxlen;
-
-  sprintf(buf, "  %s", option);
-  if (i)
-    sprintf(buf+strlen(buf), " %d", *i);
-  if (r)
-    sprintf(buf+strlen(buf), " %2.2g", *r);
-  len= (int)strlen(buf);  /* WARN64 */
-  qh qhull_optionlen += len;
-  maxlen= sizeof(qh qhull_options) - len -1;
-  maximize_(maxlen, 0);
-  if (qh qhull_optionlen >= qh_OPTIONline && maxlen > 0) {
-    qh qhull_optionlen= len;
-    strncat(qh qhull_options, "\n", (size_t)(maxlen--));
-  }
-  strncat(qh qhull_options, buf, (size_t)maxlen);
-} /* option */
-
-#if qh_QHpointer
-/*---------------------------------
-
-  qh_restore_qhull( oldqh )
-    restores a previously saved qhull
-    also restores qh_qhstat and qhmem.tempstack
-    Sets *oldqh to NULL
-  notes:
-    errors if current qhull hasn't been saved or freed
-    uses qhmem for error reporting
-
-  NOTE 1998/5/11:
-    Freeing memory after qh_save_qhull and qh_restore_qhull
-    is complicated.  The procedures will be redesigned.
-
-  see:
-    qh_save_qhull(), UsingLibQhull
-*/
-void qh_restore_qhull(qhT **oldqh) {
-
-  if (*oldqh && strcmp((*oldqh)->qhull, "qhull")) {
-    qh_fprintf(qhmem.ferr, 6061, "qhull internal error (qh_restore_qhull): %p is not a qhull data structure\n",
-                  *oldqh);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  if (qh_qh) {
-    qh_fprintf(qhmem.ferr, 6062, "qhull internal error (qh_restore_qhull): did not save or free existing qhull\n");
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  if (!*oldqh || !(*oldqh)->old_qhstat) {
-    qh_fprintf(qhmem.ferr, 6063, "qhull internal error (qh_restore_qhull): did not previously save qhull %p\n",
-                  *oldqh);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  qh_qh= *oldqh;
-  *oldqh= NULL;
-  qh_qhstat= qh old_qhstat;
-  qhmem.tempstack= qh old_tempstack;
-  qh old_qhstat= 0;
-  qh old_tempstack= 0;
-  trace1((qh ferr, 1007, "qh_restore_qhull: restored qhull from %p\n", *oldqh));
-} /* restore_qhull */
-
-/*---------------------------------
-
-  qh_save_qhull(  )
-    saves qhull for a later qh_restore_qhull
-    also saves qh_qhstat and qhmem.tempstack
-
-  returns:
-    qh_qh=NULL
-
-  notes:
-    need to initialize qhull or call qh_restore_qhull before continuing
-
-  NOTE 1998/5/11:
-    Freeing memory after qh_save_qhull and qh_restore_qhull
-    is complicated.  The procedures will be redesigned.
-
-  see:
-    qh_restore_qhull()
-*/
-qhT *qh_save_qhull(void) {
-  qhT *oldqh;
-
-  trace1((qhmem.ferr, 1045, "qh_save_qhull: save qhull %p\n", qh_qh));
-  if (!qh_qh) {
-    qh_fprintf(qhmem.ferr, 6064, "qhull internal error (qh_save_qhull): qhull not initialized\n");
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  qh old_qhstat= qh_qhstat;
-  qh_qhstat= NULL;
-  qh old_tempstack= qhmem.tempstack;
-  qhmem.tempstack= NULL;
-  oldqh= qh_qh;
-  qh_qh= NULL;
-  return oldqh;
-} /* save_qhull */
-
-#endif
-
diff --git a/extern/libqhull/io.c b/extern/libqhull/io.c
deleted file mode 100644
index ad666089222f..000000000000
--- a/extern/libqhull/io.c
+++ /dev/null
@@ -1,4062 +0,0 @@
-/*
  ---------------------------------
-
-   io.c
-   Input/Output routines of qhull application
-
-   see qh-io.htm and io.h
-
-   see user.c for qh_errprint and qh_printfacetlist
-
-   unix.c calls qh_readpoints and qh_produce_output
-
-   unix.c and user.c are the only callers of io.c functions
-   This allows the user to avoid loading io.o from qhull.a
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/io.c#5 $$Change: 2064 $
-   $DateTime: 2016/01/18 12:36:08 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-/*========= -functions in alphabetical order after qh_produce_output()  =====*/
-
-/*---------------------------------
-
-  qh_produce_output()
-  qh_produce_output2()
-    prints out the result of qhull in desired format
-    qh_produce_output2() does not call qh_prepare_output()
-    if qh.GETarea
-      computes and prints area and volume
-    qh.PRINTout[] is an array of output formats
-
-  notes:
-    prints output in qh.PRINTout order
-*/
-void qh_produce_output(void) {
-    int tempsize= qh_setsize(qhmem.tempstack);
-
-    qh_prepare_output();
-    qh_produce_output2();
-    if (qh_setsize(qhmem.tempstack) != tempsize) {
-        qh_fprintf(qh ferr, 6206, "qhull internal error (qh_produce_output): temporary sets not empty(%d)\n",
-            qh_setsize(qhmem.tempstack));
-        qh_errexit(qh_ERRqhull, NULL, NULL);
-    }
-} /* produce_output */
-
-
-void qh_produce_output2(void) {
-  int i, tempsize= qh_setsize(qhmem.tempstack), d_1;
-
-  if (qh PRINTsummary)
-    qh_printsummary(qh ferr);
-  else if (qh PRINTout[0] == qh_PRINTnone)
-    qh_printsummary(qh fout);
-  for (i=0; i < qh_PRINTEND; i++)
-    qh_printfacets(qh fout, qh PRINTout[i], qh facet_list, NULL, !qh_ALL);
-  qh_allstatistics();
-  if (qh PRINTprecision && !qh MERGING && (qh JOGGLEmax > REALmax/2 || qh RERUN))
-    qh_printstats(qh ferr, qhstat precision, NULL);
-  if (qh VERIFYoutput && (zzval_(Zridge) > 0 || zzval_(Zridgemid) > 0))
-    qh_printstats(qh ferr, qhstat vridges, NULL);
-  if (qh PRINTstatistics) {
-    qh_printstatistics(qh ferr, "");
-    qh_memstatistics(qh ferr);
-    d_1= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;
-    qh_fprintf(qh ferr, 8040, "\
-    size in bytes: merge %d ridge %d vertex %d facet %d\n\
-         normal %d ridge vertices %d facet vertices or neighbors %d\n",
-            (int)sizeof(mergeT), (int)sizeof(ridgeT),
-            (int)sizeof(vertexT), (int)sizeof(facetT),
-            qh normal_size, d_1, d_1 + SETelemsize);
-  }
-  if (qh_setsize(qhmem.tempstack) != tempsize) {
-    qh_fprintf(qh ferr, 6065, "qhull internal error (qh_produce_output2): temporary sets not empty(%d)\n",
-             qh_setsize(qhmem.tempstack));
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-} /* produce_output2 */
-
-/*---------------------------------
-
-  qh_dfacet( id )
-    print facet by id, for debugging
-
-*/
-void qh_dfacet(unsigned id) {
-  facetT *facet;
-
-  FORALLfacets {
-    if (facet->id == id) {
-      qh_printfacet(qh fout, facet);
-      break;
-    }
-  }
-} /* dfacet */
-
-
-/*---------------------------------
-
-  qh_dvertex( id )
-    print vertex by id, for debugging
-*/
-void qh_dvertex(unsigned id) {
-  vertexT *vertex;
-
-  FORALLvertices {
-    if (vertex->id == id) {
-      qh_printvertex(qh fout, vertex);
-      break;
-    }
-  }
-} /* dvertex */
-
-
-/*---------------------------------
-
-  qh_compare_facetarea( p1, p2 )
-    used by qsort() to order facets by area
-*/
-int qh_compare_facetarea(const void *p1, const void *p2) {
-  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
-
-  if (!a->isarea)
-    return -1;
-  if (!b->isarea)
-    return 1;
-  if (a->f.area > b->f.area)
-    return 1;
-  else if (a->f.area == b->f.area)
-    return 0;
-  return -1;
-} /* compare_facetarea */
-
-/*---------------------------------
-
-  qh_compare_facetmerge( p1, p2 )
-    used by qsort() to order facets by number of merges
-*/
-int qh_compare_facetmerge(const void *p1, const void *p2) {
-  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
-
-  return(a->nummerge - b->nummerge);
-} /* compare_facetvisit */
-
-/*---------------------------------
-
-  qh_compare_facetvisit( p1, p2 )
-    used by qsort() to order facets by visit id or id
-*/
-int qh_compare_facetvisit(const void *p1, const void *p2) {
-  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
-  int i,j;
-
-  if (!(i= a->visitid))
-    i= 0 - a->id; /* do not convert to int, sign distinguishes id from visitid */
-  if (!(j= b->visitid))
-    j= 0 - b->id;
-  return(i - j);
-} /* compare_facetvisit */
-
-/*---------------------------------
-
-  qh_compare_vertexpoint( p1, p2 )
-    used by qsort() to order vertices by point id
-
-  Not used.  Not available in libqhull_r.h since qh_pointid depends on qh
-*/
-int qh_compare_vertexpoint(const void *p1, const void *p2) {
-  const vertexT *a= *((vertexT *const*)p1), *b= *((vertexT *const*)p2);
-
-  return((qh_pointid(a->point) > qh_pointid(b->point)?1:-1));
-} /* compare_vertexpoint */
-
-/*---------------------------------
-
-  qh_copyfilename( dest, size, source, length )
-    copy filename identified by qh_skipfilename()
-
-  notes:
-    see qh_skipfilename() for syntax
-*/
-void qh_copyfilename(char *filename, int size, const char* source, int length) {
-  char c= *source;
-
-  if (length > size + 1) {
-      qh_fprintf(qh ferr, 6040, "qhull error: filename is more than %d characters, %s\n",  size-1, source);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  strncpy(filename, source, length);
-  filename[length]= '\0';
-  if (c == '\'' || c == '"') {
-    char *s= filename + 1;
-    char *t= filename;
-    while (*s) {
-      if (*s == c) {
-          if (s[-1] == '\\')
-              t[-1]= c;
-      }else
-          *t++= *s;
-      s++;
-    }
-    *t= '\0';
-  }
-} /* copyfilename */
-
-/*---------------------------------
-
-  qh_countfacets( facetlist, facets, printall,
-          numfacets, numsimplicial, totneighbors, numridges, numcoplanar, numtricoplanars  )
-    count good facets for printing and set visitid
-    if allfacets, ignores qh_skipfacet()
-
-  notes:
-    qh_printsummary and qh_countfacets must match counts
-
-  returns:
-    numfacets, numsimplicial, total neighbors, numridges, coplanars
-    each facet with ->visitid indicating 1-relative position
-      ->visitid==0 indicates not good
-
-  notes
-    numfacets >= numsimplicial
-    if qh.NEWfacets,
-      does not count visible facets (matches qh_printafacet)
-
-  design:
-    for all facets on facetlist and in facets set
-      unless facet is skipped or visible (i.e., will be deleted)
-        mark facet->visitid
-        update counts
-*/
-void qh_countfacets(facetT *facetlist, setT *facets, boolT printall,
-    int *numfacetsp, int *numsimplicialp, int *totneighborsp, int *numridgesp, int *numcoplanarsp, int *numtricoplanarsp) {
-  facetT *facet, **facetp;
-  int numfacets= 0, numsimplicial= 0, numridges= 0, totneighbors= 0, numcoplanars= 0, numtricoplanars= 0;
-
-  FORALLfacet_(facetlist) {
-    if ((facet->visible && qh NEWfacets)
-    || (!printall && qh_skipfacet(facet)))
-      facet->visitid= 0;
-    else {
-      facet->visitid= ++numfacets;
-      totneighbors += qh_setsize(facet->neighbors);
-      if (facet->simplicial) {
-        numsimplicial++;
-        if (facet->keepcentrum && facet->tricoplanar)
-          numtricoplanars++;
-      }else
-        numridges += qh_setsize(facet->ridges);
-      if (facet->coplanarset)
-        numcoplanars += qh_setsize(facet->coplanarset);
-    }
-  }
-
-  FOREACHfacet_(facets) {
-    if ((facet->visible && qh NEWfacets)
-    || (!printall && qh_skipfacet(facet)))
-      facet->visitid= 0;
-    else {
-      facet->visitid= ++numfacets;
-      totneighbors += qh_setsize(facet->neighbors);
-      if (facet->simplicial){
-        numsimplicial++;
-        if (facet->keepcentrum && facet->tricoplanar)
-          numtricoplanars++;
-      }else
-        numridges += qh_setsize(facet->ridges);
-      if (facet->coplanarset)
-        numcoplanars += qh_setsize(facet->coplanarset);
-    }
-  }
-  qh visit_id += numfacets+1;
-  *numfacetsp= numfacets;
-  *numsimplicialp= numsimplicial;
-  *totneighborsp= totneighbors;
-  *numridgesp= numridges;
-  *numcoplanarsp= numcoplanars;
-  *numtricoplanarsp= numtricoplanars;
-} /* countfacets */
-
-/*---------------------------------
-
-  qh_detvnorm( vertex, vertexA, centers, offset )
-    compute separating plane of the Voronoi diagram for a pair of input sites
-    centers= set of facets (i.e., Voronoi vertices)
-      facet->visitid= 0 iff vertex-at-infinity (i.e., unbounded)
-
-  assumes:
-    qh_ASvoronoi and qh_vertexneighbors() already set
-
-  returns:
-    norm
-      a pointer into qh.gm_matrix to qh.hull_dim-1 reals
-      copy the data before reusing qh.gm_matrix
-    offset
-      if 'QVn'
-        sign adjusted so that qh.GOODvertexp is inside
-      else
-        sign adjusted so that vertex is inside
-
-    qh.gm_matrix= simplex of points from centers relative to first center
-
-  notes:
-    in io.c so that code for 'v Tv' can be removed by removing io.c
-    returns pointer into qh.gm_matrix to avoid tracking of temporary memory
-
-  design:
-    determine midpoint of input sites
-    build points as the set of Voronoi vertices
-    select a simplex from points (if necessary)
-      include midpoint if the Voronoi region is unbounded
-    relocate the first vertex of the simplex to the origin
-    compute the normalized hyperplane through the simplex
-    orient the hyperplane toward 'QVn' or 'vertex'
-    if 'Tv' or 'Ts'
-      if bounded
-        test that hyperplane is the perpendicular bisector of the input sites
-      test that Voronoi vertices not in the simplex are still on the hyperplane
-    free up temporary memory
-*/
-pointT *qh_detvnorm(vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp) {
-  facetT *facet, **facetp;
-  int  i, k, pointid, pointidA, point_i, point_n;
-  setT *simplex= NULL;
-  pointT *point, **pointp, *point0, *midpoint, *normal, *inpoint;
-  coordT *coord, *gmcoord, *normalp;
-  setT *points= qh_settemp(qh TEMPsize);
-  boolT nearzero= False;
-  boolT unbounded= False;
-  int numcenters= 0;
-  int dim= qh hull_dim - 1;
-  realT dist, offset, angle, zero= 0.0;
-
-  midpoint= qh gm_matrix + qh hull_dim * qh hull_dim;  /* last row */
-  for (k=0; k < dim; k++)
-    midpoint[k]= (vertex->point[k] + vertexA->point[k])/2;
-  FOREACHfacet_(centers) {
-    numcenters++;
-    if (!facet->visitid)
-      unbounded= True;
-    else {
-      if (!facet->center)
-        facet->center= qh_facetcenter(facet->vertices);
-      qh_setappend(&points, facet->center);
-    }
-  }
-  if (numcenters > dim) {
-    simplex= qh_settemp(qh TEMPsize);
-    qh_setappend(&simplex, vertex->point);
-    if (unbounded)
-      qh_setappend(&simplex, midpoint);
-    qh_maxsimplex(dim, points, NULL, 0, &simplex);
-    qh_setdelnth(simplex, 0);
-  }else if (numcenters == dim) {
-    if (unbounded)
-      qh_setappend(&points, midpoint);
-    simplex= points;
-  }else {
-    qh_fprintf(qh ferr, 6216, "qhull internal error (qh_detvnorm): too few points(%d) to compute separating plane\n", numcenters);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  i= 0;
-  gmcoord= qh gm_matrix;
-  point0= SETfirstt_(simplex, pointT);
-  FOREACHpoint_(simplex) {
-    if (qh IStracing >= 4)
-      qh_printmatrix(qh ferr, "qh_detvnorm: Voronoi vertex or midpoint",
-                              &point, 1, dim);
-    if (point != point0) {
-      qh gm_row[i++]= gmcoord;
-      coord= point0;
-      for (k=dim; k--; )
-        *(gmcoord++)= *point++ - *coord++;
-    }
-  }
-  qh gm_row[i]= gmcoord;  /* does not overlap midpoint, may be used later for qh_areasimplex */
-  normal= gmcoord;
-  qh_sethyperplane_gauss(dim, qh gm_row, point0, True,
-                normal, &offset, &nearzero);
-  if (qh GOODvertexp == vertexA->point)
-    inpoint= vertexA->point;
-  else
-    inpoint= vertex->point;
-  zinc_(Zdistio);
-  dist= qh_distnorm(dim, inpoint, normal, &offset);
-  if (dist > 0) {
-    offset= -offset;
-    normalp= normal;
-    for (k=dim; k--; ) {
-      *normalp= -(*normalp);
-      normalp++;
-    }
-  }
-  if (qh VERIFYoutput || qh PRINTstatistics) {
-    pointid= qh_pointid(vertex->point);
-    pointidA= qh_pointid(vertexA->point);
-    if (!unbounded) {
-      zinc_(Zdiststat);
-      dist= qh_distnorm(dim, midpoint, normal, &offset);
-      if (dist < 0)
-        dist= -dist;
-      zzinc_(Zridgemid);
-      wwmax_(Wridgemidmax, dist);
-      wwadd_(Wridgemid, dist);
-      trace4((qh ferr, 4014, "qh_detvnorm: points %d %d midpoint dist %2.2g\n",
-                 pointid, pointidA, dist));
-      for (k=0; k < dim; k++)
-        midpoint[k]= vertexA->point[k] - vertex->point[k];  /* overwrites midpoint! */
-      qh_normalize(midpoint, dim, False);
-      angle= qh_distnorm(dim, midpoint, normal, &zero); /* qh_detangle uses dim+1 */
-      if (angle < 0.0)
-        angle= angle + 1.0;
-      else
-        angle= angle - 1.0;
-      if (angle < 0.0)
-        angle -= angle;
-      trace4((qh ferr, 4015, "qh_detvnorm: points %d %d angle %2.2g nearzero %d\n",
-                 pointid, pointidA, angle, nearzero));
-      if (nearzero) {
-        zzinc_(Zridge0);
-        wwmax_(Wridge0max, angle);
-        wwadd_(Wridge0, angle);
-      }else {
-        zzinc_(Zridgeok)
-        wwmax_(Wridgeokmax, angle);
-        wwadd_(Wridgeok, angle);
-      }
-    }
-    if (simplex != points) {
-      FOREACHpoint_i_(points) {
-        if (!qh_setin(simplex, point)) {
-          facet= SETelemt_(centers, point_i, facetT);
-          zinc_(Zdiststat);
-          dist= qh_distnorm(dim, point, normal, &offset);
-          if (dist < 0)
-            dist= -dist;
-          zzinc_(Zridge);
-          wwmax_(Wridgemax, dist);
-          wwadd_(Wridge, dist);
-          trace4((qh ferr, 4016, "qh_detvnorm: points %d %d Voronoi vertex %d dist %2.2g\n",
-                             pointid, pointidA, facet->visitid, dist));
-        }
-      }
-    }
-  }
-  *offsetp= offset;
-  if (simplex != points)
-    qh_settempfree(&simplex);
-  qh_settempfree(&points);
-  return normal;
-} /* detvnorm */
-
-/*---------------------------------
-
-  qh_detvridge( vertexA )
-    determine Voronoi ridge from 'seen' neighbors of vertexA
-    include one vertex-at-infinite if an !neighbor->visitid
-
-  returns:
-    temporary set of centers (facets, i.e., Voronoi vertices)
-    sorted by center id
-*/
-setT *qh_detvridge(vertexT *vertex) {
-  setT *centers= qh_settemp(qh TEMPsize);
-  setT *tricenters= qh_settemp(qh TEMPsize);
-  facetT *neighbor, **neighborp;
-  boolT firstinf= True;
-
-  FOREACHneighbor_(vertex) {
-    if (neighbor->seen) {
-      if (neighbor->visitid) {
-        if (!neighbor->tricoplanar || qh_setunique(&tricenters, neighbor->center))
-          qh_setappend(¢ers, neighbor);
-      }else if (firstinf) {
-        firstinf= False;
-        qh_setappend(¢ers, neighbor);
-      }
-    }
-  }
-  qsort(SETaddr_(centers, facetT), (size_t)qh_setsize(centers),
-             sizeof(facetT *), qh_compare_facetvisit);
-  qh_settempfree(&tricenters);
-  return centers;
-} /* detvridge */
-
-/*---------------------------------
-
-  qh_detvridge3( atvertex, vertex )
-    determine 3-d Voronoi ridge from 'seen' neighbors of atvertex and vertex
-    include one vertex-at-infinite for !neighbor->visitid
-    assumes all facet->seen2= True
-
-  returns:
-    temporary set of centers (facets, i.e., Voronoi vertices)
-    listed in adjacency order (!oriented)
-    all facet->seen2= True
-
-  design:
-    mark all neighbors of atvertex
-    for each adjacent neighbor of both atvertex and vertex
-      if neighbor selected
-        add neighbor to set of Voronoi vertices
-*/
-setT *qh_detvridge3(vertexT *atvertex, vertexT *vertex) {
-  setT *centers= qh_settemp(qh TEMPsize);
-  setT *tricenters= qh_settemp(qh TEMPsize);
-  facetT *neighbor, **neighborp, *facet= NULL;
-  boolT firstinf= True;
-
-  FOREACHneighbor_(atvertex)
-    neighbor->seen2= False;
-  FOREACHneighbor_(vertex) {
-    if (!neighbor->seen2) {
-      facet= neighbor;
-      break;
-    }
-  }
-  while (facet) {
-    facet->seen2= True;
-    if (neighbor->seen) {
-      if (facet->visitid) {
-        if (!facet->tricoplanar || qh_setunique(&tricenters, facet->center))
-          qh_setappend(¢ers, facet);
-      }else if (firstinf) {
-        firstinf= False;
-        qh_setappend(¢ers, facet);
-      }
-    }
-    FOREACHneighbor_(facet) {
-      if (!neighbor->seen2) {
-        if (qh_setin(vertex->neighbors, neighbor))
-          break;
-        else
-          neighbor->seen2= True;
-      }
-    }
-    facet= neighbor;
-  }
-  if (qh CHECKfrequently) {
-    FOREACHneighbor_(vertex) {
-      if (!neighbor->seen2) {
-          qh_fprintf(qh ferr, 6217, "qhull internal error (qh_detvridge3): neighbors of vertex p%d are not connected at facet %d\n",
-                 qh_pointid(vertex->point), neighbor->id);
-        qh_errexit(qh_ERRqhull, neighbor, NULL);
-      }
-    }
-  }
-  FOREACHneighbor_(atvertex)
-    neighbor->seen2= True;
-  qh_settempfree(&tricenters);
-  return centers;
-} /* detvridge3 */
-
-/*---------------------------------
-
-  qh_eachvoronoi( fp, printvridge, vertex, visitall, innerouter, inorder )
-    if visitall,
-      visit all Voronoi ridges for vertex (i.e., an input site)
-    else
-      visit all unvisited Voronoi ridges for vertex
-      all vertex->seen= False if unvisited
-    assumes
-      all facet->seen= False
-      all facet->seen2= True (for qh_detvridge3)
-      all facet->visitid == 0 if vertex_at_infinity
-                         == index of Voronoi vertex
-                         >= qh.num_facets if ignored
-    innerouter:
-      qh_RIDGEall--  both inner (bounded) and outer(unbounded) ridges
-      qh_RIDGEinner- only inner
-      qh_RIDGEouter- only outer
-
-    if inorder
-      orders vertices for 3-d Voronoi diagrams
-
-  returns:
-    number of visited ridges (does not include previously visited ridges)
-
-    if printvridge,
-      calls printvridge( fp, vertex, vertexA, centers)
-        fp== any pointer (assumes FILE*)
-        vertex,vertexA= pair of input sites that define a Voronoi ridge
-        centers= set of facets (i.e., Voronoi vertices)
-                 ->visitid == index or 0 if vertex_at_infinity
-                 ordered for 3-d Voronoi diagram
-  notes:
-    uses qh.vertex_visit
-
-  see:
-    qh_eachvoronoi_all()
-
-  design:
-    mark selected neighbors of atvertex
-    for each selected neighbor (either Voronoi vertex or vertex-at-infinity)
-      for each unvisited vertex
-        if atvertex and vertex share more than d-1 neighbors
-          bump totalcount
-          if printvridge defined
-            build the set of shared neighbors (i.e., Voronoi vertices)
-            call printvridge
-*/
-int qh_eachvoronoi(FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder) {
-  boolT unbounded;
-  int count;
-  facetT *neighbor, **neighborp, *neighborA, **neighborAp;
-  setT *centers;
-  setT *tricenters= qh_settemp(qh TEMPsize);
-
-  vertexT *vertex, **vertexp;
-  boolT firstinf;
-  unsigned int numfacets= (unsigned int)qh num_facets;
-  int totridges= 0;
-
-  qh vertex_visit++;
-  atvertex->seen= True;
-  if (visitall) {
-    FORALLvertices
-      vertex->seen= False;
-  }
-  FOREACHneighbor_(atvertex) {
-    if (neighbor->visitid < numfacets)
-      neighbor->seen= True;
-  }
-  FOREACHneighbor_(atvertex) {
-    if (neighbor->seen) {
-      FOREACHvertex_(neighbor->vertices) {
-        if (vertex->visitid != qh vertex_visit && !vertex->seen) {
-          vertex->visitid= qh vertex_visit;
-          count= 0;
-          firstinf= True;
-          qh_settruncate(tricenters, 0);
-          FOREACHneighborA_(vertex) {
-            if (neighborA->seen) {
-              if (neighborA->visitid) {
-                if (!neighborA->tricoplanar || qh_setunique(&tricenters, neighborA->center))
-                  count++;
-              }else if (firstinf) {
-                count++;
-                firstinf= False;
-              }
-            }
-          }
-          if (count >= qh hull_dim - 1) {  /* e.g., 3 for 3-d Voronoi */
-            if (firstinf) {
-              if (innerouter == qh_RIDGEouter)
-                continue;
-              unbounded= False;
-            }else {
-              if (innerouter == qh_RIDGEinner)
-                continue;
-              unbounded= True;
-            }
-            totridges++;
-            trace4((qh ferr, 4017, "qh_eachvoronoi: Voronoi ridge of %d vertices between sites %d and %d\n",
-                  count, qh_pointid(atvertex->point), qh_pointid(vertex->point)));
-            if (printvridge && fp) {
-              if (inorder && qh hull_dim == 3+1) /* 3-d Voronoi diagram */
-                centers= qh_detvridge3(atvertex, vertex);
-              else
-                centers= qh_detvridge(vertex);
-              (*printvridge)(fp, atvertex, vertex, centers, unbounded);
-              qh_settempfree(¢ers);
-            }
-          }
-        }
-      }
-    }
-  }
-  FOREACHneighbor_(atvertex)
-    neighbor->seen= False;
-  qh_settempfree(&tricenters);
-  return totridges;
-} /* eachvoronoi */
-
-
-/*---------------------------------
-
-  qh_eachvoronoi_all( fp, printvridge, isUpper, innerouter, inorder )
-    visit all Voronoi ridges
-
-    innerouter:
-      see qh_eachvoronoi()
-
-    if inorder
-      orders vertices for 3-d Voronoi diagrams
-
-  returns
-    total number of ridges
-
-    if isUpper == facet->upperdelaunay  (i.e., a Vornoi vertex)
-      facet->visitid= Voronoi vertex index(same as 'o' format)
-    else
-      facet->visitid= 0
-
-    if printvridge,
-      calls printvridge( fp, vertex, vertexA, centers)
-      [see qh_eachvoronoi]
-
-  notes:
-    Not used for qhull.exe
-    same effect as qh_printvdiagram but ridges not sorted by point id
-*/
-int qh_eachvoronoi_all(FILE *fp, printvridgeT printvridge, boolT isUpper, qh_RIDGE innerouter, boolT inorder) {
-  facetT *facet;
-  vertexT *vertex;
-  int numcenters= 1;  /* vertex 0 is vertex-at-infinity */
-  int totridges= 0;
-
-  qh_clearcenters(qh_ASvoronoi);
-  qh_vertexneighbors();
-  maximize_(qh visit_id, (unsigned) qh num_facets);
-  FORALLfacets {
-    facet->visitid= 0;
-    facet->seen= False;
-    facet->seen2= True;
-  }
-  FORALLfacets {
-    if (facet->upperdelaunay == isUpper)
-      facet->visitid= numcenters++;
-  }
-  FORALLvertices
-    vertex->seen= False;
-  FORALLvertices {
-    if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
-      continue;
-    totridges += qh_eachvoronoi(fp, printvridge, vertex,
-                   !qh_ALL, innerouter, inorder);
-  }
-  return totridges;
-} /* eachvoronoi_all */
-
-/*---------------------------------
-
-  qh_facet2point( facet, point0, point1, mindist )
-    return two projected temporary vertices for a 2-d facet
-    may be non-simplicial
-
-  returns:
-    point0 and point1 oriented and projected to the facet
-    returns mindist (maximum distance below plane)
-*/
-void qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist) {
-  vertexT *vertex0, *vertex1;
-  realT dist;
-
-  if (facet->toporient ^ qh_ORIENTclock) {
-    vertex0= SETfirstt_(facet->vertices, vertexT);
-    vertex1= SETsecondt_(facet->vertices, vertexT);
-  }else {
-    vertex1= SETfirstt_(facet->vertices, vertexT);
-    vertex0= SETsecondt_(facet->vertices, vertexT);
-  }
-  zadd_(Zdistio, 2);
-  qh_distplane(vertex0->point, facet, &dist);
-  *mindist= dist;
-  *point0= qh_projectpoint(vertex0->point, facet, dist);
-  qh_distplane(vertex1->point, facet, &dist);
-  minimize_(*mindist, dist);
-  *point1= qh_projectpoint(vertex1->point, facet, dist);
-} /* facet2point */
-
-
-/*---------------------------------
-
-  qh_facetvertices( facetlist, facets, allfacets )
-    returns temporary set of vertices in a set and/or list of facets
-    if allfacets, ignores qh_skipfacet()
-
-  returns:
-    vertices with qh.vertex_visit
-
-  notes:
-    optimized for allfacets of facet_list
-
-  design:
-    if allfacets of facet_list
-      create vertex set from vertex_list
-    else
-      for each selected facet in facets or facetlist
-        append unvisited vertices to vertex set
-*/
-setT *qh_facetvertices(facetT *facetlist, setT *facets, boolT allfacets) {
-  setT *vertices;
-  facetT *facet, **facetp;
-  vertexT *vertex, **vertexp;
-
-  qh vertex_visit++;
-  if (facetlist == qh facet_list && allfacets && !facets) {
-    vertices= qh_settemp(qh num_vertices);
-    FORALLvertices {
-      vertex->visitid= qh vertex_visit;
-      qh_setappend(&vertices, vertex);
-    }
-  }else {
-    vertices= qh_settemp(qh TEMPsize);
-    FORALLfacet_(facetlist) {
-      if (!allfacets && qh_skipfacet(facet))
-        continue;
-      FOREACHvertex_(facet->vertices) {
-        if (vertex->visitid != qh vertex_visit) {
-          vertex->visitid= qh vertex_visit;
-          qh_setappend(&vertices, vertex);
-        }
-      }
-    }
-  }
-  FOREACHfacet_(facets) {
-    if (!allfacets && qh_skipfacet(facet))
-      continue;
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->visitid != qh vertex_visit) {
-        vertex->visitid= qh vertex_visit;
-        qh_setappend(&vertices, vertex);
-      }
-    }
-  }
-  return vertices;
-} /* facetvertices */
-
-/*---------------------------------
-
-  qh_geomplanes( facet, outerplane, innerplane )
-    return outer and inner planes for Geomview
-    qh.PRINTradius is size of vertices and points (includes qh.JOGGLEmax)
-
-  notes:
-    assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
-*/
-void qh_geomplanes(facetT *facet, realT *outerplane, realT *innerplane) {
-  realT radius;
-
-  if (qh MERGING || qh JOGGLEmax < REALmax/2) {
-    qh_outerinner(facet, outerplane, innerplane);
-    radius= qh PRINTradius;
-    if (qh JOGGLEmax < REALmax/2)
-      radius -= qh JOGGLEmax * sqrt((realT)qh hull_dim);  /* already accounted for in qh_outerinner() */
-    *outerplane += radius;
-    *innerplane -= radius;
-    if (qh PRINTcoplanar || qh PRINTspheres) {
-      *outerplane += qh MAXabs_coord * qh_GEOMepsilon;
-      *innerplane -= qh MAXabs_coord * qh_GEOMepsilon;
-    }
-  }else
-    *innerplane= *outerplane= 0;
-} /* geomplanes */
-
-
-/*---------------------------------
-
-  qh_markkeep( facetlist )
-    mark good facets that meet qh.KEEParea, qh.KEEPmerge, and qh.KEEPminArea
-    ignores visible facets (!part of convex hull)
-
-  returns:
-    may clear facet->good
-    recomputes qh.num_good
-
-  design:
-    get set of good facets
-    if qh.KEEParea
-      sort facets by area
-      clear facet->good for all but n largest facets
-    if qh.KEEPmerge
-      sort facets by merge count
-      clear facet->good for all but n most merged facets
-    if qh.KEEPminarea
-      clear facet->good if area too small
-    update qh.num_good
-*/
-void qh_markkeep(facetT *facetlist) {
-  facetT *facet, **facetp;
-  setT *facets= qh_settemp(qh num_facets);
-  int size, count;
-
-  trace2((qh ferr, 2006, "qh_markkeep: only keep %d largest and/or %d most merged facets and/or min area %.2g\n",
-          qh KEEParea, qh KEEPmerge, qh KEEPminArea));
-  FORALLfacet_(facetlist) {
-    if (!facet->visible && facet->good)
-      qh_setappend(&facets, facet);
-  }
-  size= qh_setsize(facets);
-  if (qh KEEParea) {
-    qsort(SETaddr_(facets, facetT), (size_t)size,
-             sizeof(facetT *), qh_compare_facetarea);
-    if ((count= size - qh KEEParea) > 0) {
-      FOREACHfacet_(facets) {
-        facet->good= False;
-        if (--count == 0)
-          break;
-      }
-    }
-  }
-  if (qh KEEPmerge) {
-    qsort(SETaddr_(facets, facetT), (size_t)size,
-             sizeof(facetT *), qh_compare_facetmerge);
-    if ((count= size - qh KEEPmerge) > 0) {
-      FOREACHfacet_(facets) {
-        facet->good= False;
-        if (--count == 0)
-          break;
-      }
-    }
-  }
-  if (qh KEEPminArea < REALmax/2) {
-    FOREACHfacet_(facets) {
-      if (!facet->isarea || facet->f.area < qh KEEPminArea)
-        facet->good= False;
-    }
-  }
-  qh_settempfree(&facets);
-  count= 0;
-  FORALLfacet_(facetlist) {
-    if (facet->good)
-      count++;
-  }
-  qh num_good= count;
-} /* markkeep */
-
-
-/*---------------------------------
-
-  qh_markvoronoi( facetlist, facets, printall, isLower, numcenters )
-    mark voronoi vertices for printing by site pairs
-
-  returns:
-    temporary set of vertices indexed by pointid
-    isLower set if printing lower hull (i.e., at least one facet is lower hull)
-    numcenters= total number of Voronoi vertices
-    bumps qh.printoutnum for vertex-at-infinity
-    clears all facet->seen and sets facet->seen2
-
-    if selected
-      facet->visitid= Voronoi vertex id
-    else if upper hull (or 'Qu' and lower hull)
-      facet->visitid= 0
-    else
-      facet->visitid >= qh num_facets
-
-  notes:
-    ignores qh.ATinfinity, if defined
-*/
-setT *qh_markvoronoi(facetT *facetlist, setT *facets, boolT printall, boolT *isLowerp, int *numcentersp) {
-  int numcenters=0;
-  facetT *facet, **facetp;
-  setT *vertices;
-  boolT isLower= False;
-
-  qh printoutnum++;
-  qh_clearcenters(qh_ASvoronoi);  /* in case, qh_printvdiagram2 called by user */
-  qh_vertexneighbors();
-  vertices= qh_pointvertex();
-  if (qh ATinfinity)
-    SETelem_(vertices, qh num_points-1)= NULL;
-  qh visit_id++;
-  maximize_(qh visit_id, (unsigned) qh num_facets);
-  FORALLfacet_(facetlist) {
-    if (printall || !qh_skipfacet(facet)) {
-      if (!facet->upperdelaunay) {
-        isLower= True;
-        break;
-      }
-    }
-  }
-  FOREACHfacet_(facets) {
-    if (printall || !qh_skipfacet(facet)) {
-      if (!facet->upperdelaunay) {
-        isLower= True;
-        break;
-      }
-    }
-  }
-  FORALLfacets {
-    if (facet->normal && (facet->upperdelaunay == isLower))
-      facet->visitid= 0;  /* facetlist or facets may overwrite */
-    else
-      facet->visitid= qh visit_id;
-    facet->seen= False;
-    facet->seen2= True;
-  }
-  numcenters++;  /* qh_INFINITE */
-  FORALLfacet_(facetlist) {
-    if (printall || !qh_skipfacet(facet))
-      facet->visitid= numcenters++;
-  }
-  FOREACHfacet_(facets) {
-    if (printall || !qh_skipfacet(facet))
-      facet->visitid= numcenters++;
-  }
-  *isLowerp= isLower;
-  *numcentersp= numcenters;
-  trace2((qh ferr, 2007, "qh_markvoronoi: isLower %d numcenters %d\n", isLower, numcenters));
-  return vertices;
-} /* markvoronoi */
-
-/*---------------------------------
-
-  qh_order_vertexneighbors( vertex )
-    order facet neighbors of a 2-d or 3-d vertex by adjacency
-
-  notes:
-    does not orient the neighbors
-
-  design:
-    initialize a new neighbor set with the first facet in vertex->neighbors
-    while vertex->neighbors non-empty
-      select next neighbor in the previous facet's neighbor set
-    set vertex->neighbors to the new neighbor set
-*/
-void qh_order_vertexneighbors(vertexT *vertex) {
-  setT *newset;
-  facetT *facet, *neighbor, **neighborp;
-
-  trace4((qh ferr, 4018, "qh_order_vertexneighbors: order neighbors of v%d for 3-d\n", vertex->id));
-  newset= qh_settemp(qh_setsize(vertex->neighbors));
-  facet= (facetT*)qh_setdellast(vertex->neighbors);
-  qh_setappend(&newset, facet);
-  while (qh_setsize(vertex->neighbors)) {
-    FOREACHneighbor_(vertex) {
-      if (qh_setin(facet->neighbors, neighbor)) {
-        qh_setdel(vertex->neighbors, neighbor);
-        qh_setappend(&newset, neighbor);
-        facet= neighbor;
-        break;
-      }
-    }
-    if (!neighbor) {
-      qh_fprintf(qh ferr, 6066, "qhull internal error (qh_order_vertexneighbors): no neighbor of v%d for f%d\n",
-        vertex->id, facet->id);
-      qh_errexit(qh_ERRqhull, facet, NULL);
-    }
-  }
-  qh_setfree(&vertex->neighbors);
-  qh_settemppop();
-  vertex->neighbors= newset;
-} /* order_vertexneighbors */
-
-/*---------------------------------
-
-  qh_prepare_output( )
-    prepare for qh_produce_output2() according to
-      qh.KEEPminArea, KEEParea, KEEPmerge, GOODvertex, GOODthreshold, GOODpoint, ONLYgood, SPLITthresholds
-    does not reset facet->good
-
-  notes
-    except for PRINTstatistics, no-op if previously called with same options
-*/
-void qh_prepare_output(void) {
-  if (qh VORONOI) {
-    qh_clearcenters(qh_ASvoronoi);  /* must be before qh_triangulate */
-    qh_vertexneighbors();
-  }
-  if (qh TRIangulate && !qh hasTriangulation) {
-    qh_triangulate();
-    if (qh VERIFYoutput && !qh CHECKfrequently)
-      qh_checkpolygon(qh facet_list);
-  }
-  qh_findgood_all(qh facet_list);
-  if (qh GETarea)
-    qh_getarea(qh facet_list);
-  if (qh KEEParea || qh KEEPmerge || qh KEEPminArea < REALmax/2)
-    qh_markkeep(qh facet_list);
-  if (qh PRINTstatistics)
-    qh_collectstatistics();
-}
-
-/*---------------------------------
-
-  qh_printafacet( fp, format, facet, printall )
-    print facet to fp in given output format (see qh.PRINTout)
-
-  returns:
-    nop if !printall and qh_skipfacet()
-    nop if visible facet and NEWfacets and format != PRINTfacets
-    must match qh_countfacets
-
-  notes
-    preserves qh.visit_id
-    facet->normal may be null if PREmerge/MERGEexact and STOPcone before merge
-
-  see
-    qh_printbegin() and qh_printend()
-
-  design:
-    test for printing facet
-    call appropriate routine for format
-    or output results directly
-*/
-void qh_printafacet(FILE *fp, qh_PRINT format, facetT *facet, boolT printall) {
-  realT color[4], offset, dist, outerplane, innerplane;
-  boolT zerodiv;
-  coordT *point, *normp, *coordp, **pointp, *feasiblep;
-  int k;
-  vertexT *vertex, **vertexp;
-  facetT *neighbor, **neighborp;
-
-  if (!printall && qh_skipfacet(facet))
-    return;
-  if (facet->visible && qh NEWfacets && format != qh_PRINTfacets)
-    return;
-  qh printoutnum++;
-  switch (format) {
-  case qh_PRINTarea:
-    if (facet->isarea) {
-      qh_fprintf(fp, 9009, qh_REAL_1, facet->f.area);
-      qh_fprintf(fp, 9010, "\n");
-    }else
-      qh_fprintf(fp, 9011, "0\n");
-    break;
-  case qh_PRINTcoplanars:
-    qh_fprintf(fp, 9012, "%d", qh_setsize(facet->coplanarset));
-    FOREACHpoint_(facet->coplanarset)
-      qh_fprintf(fp, 9013, " %d", qh_pointid(point));
-    qh_fprintf(fp, 9014, "\n");
-    break;
-  case qh_PRINTcentrums:
-    qh_printcenter(fp, format, NULL, facet);
-    break;
-  case qh_PRINTfacets:
-    qh_printfacet(fp, facet);
-    break;
-  case qh_PRINTfacets_xridge:
-    qh_printfacetheader(fp, facet);
-    break;
-  case qh_PRINTgeom:  /* either 2 , 3, or 4-d by qh_printbegin */
-    if (!facet->normal)
-      break;
-    for (k=qh hull_dim; k--; ) {
-      color[k]= (facet->normal[k]+1.0)/2.0;
-      maximize_(color[k], -1.0);
-      minimize_(color[k], +1.0);
-    }
-    qh_projectdim3(color, color);
-    if (qh PRINTdim != qh hull_dim)
-      qh_normalize2(color, 3, True, NULL, NULL);
-    if (qh hull_dim <= 2)
-      qh_printfacet2geom(fp, facet, color);
-    else if (qh hull_dim == 3) {
-      if (facet->simplicial)
-        qh_printfacet3geom_simplicial(fp, facet, color);
-      else
-        qh_printfacet3geom_nonsimplicial(fp, facet, color);
-    }else {
-      if (facet->simplicial)
-        qh_printfacet4geom_simplicial(fp, facet, color);
-      else
-        qh_printfacet4geom_nonsimplicial(fp, facet, color);
-    }
-    break;
-  case qh_PRINTids:
-    qh_fprintf(fp, 9015, "%d\n", facet->id);
-    break;
-  case qh_PRINTincidences:
-  case qh_PRINToff:
-  case qh_PRINTtriangles:
-    if (qh hull_dim == 3 && format != qh_PRINTtriangles)
-      qh_printfacet3vertex(fp, facet, format);
-    else if (facet->simplicial || qh hull_dim == 2 || format == qh_PRINToff)
-      qh_printfacetNvertex_simplicial(fp, facet, format);
-    else
-      qh_printfacetNvertex_nonsimplicial(fp, facet, qh printoutvar++, format);
-    break;
-  case qh_PRINTinner:
-    qh_outerinner(facet, NULL, &innerplane);
-    offset= facet->offset - innerplane;
-    goto LABELprintnorm;
-    break; /* prevent warning */
-  case qh_PRINTmerges:
-    qh_fprintf(fp, 9016, "%d\n", facet->nummerge);
-    break;
-  case qh_PRINTnormals:
-    offset= facet->offset;
-    goto LABELprintnorm;
-    break; /* prevent warning */
-  case qh_PRINTouter:
-    qh_outerinner(facet, &outerplane, NULL);
-    offset= facet->offset - outerplane;
-  LABELprintnorm:
-    if (!facet->normal) {
-      qh_fprintf(fp, 9017, "no normal for facet f%d\n", facet->id);
-      break;
-    }
-    if (qh CDDoutput) {
-      qh_fprintf(fp, 9018, qh_REAL_1, -offset);
-      for (k=0; k < qh hull_dim; k++)
-        qh_fprintf(fp, 9019, qh_REAL_1, -facet->normal[k]);
-    }else {
-      for (k=0; k < qh hull_dim; k++)
-        qh_fprintf(fp, 9020, qh_REAL_1, facet->normal[k]);
-      qh_fprintf(fp, 9021, qh_REAL_1, offset);
-    }
-    qh_fprintf(fp, 9022, "\n");
-    break;
-  case qh_PRINTmathematica:  /* either 2 or 3-d by qh_printbegin */
-  case qh_PRINTmaple:
-    if (qh hull_dim == 2)
-      qh_printfacet2math(fp, facet, format, qh printoutvar++);
-    else
-      qh_printfacet3math(fp, facet, format, qh printoutvar++);
-    break;
-  case qh_PRINTneighbors:
-    qh_fprintf(fp, 9023, "%d", qh_setsize(facet->neighbors));
-    FOREACHneighbor_(facet)
-      qh_fprintf(fp, 9024, " %d",
-               neighbor->visitid ? neighbor->visitid - 1: 0 - neighbor->id);
-    qh_fprintf(fp, 9025, "\n");
-    break;
-  case qh_PRINTpointintersect:
-    if (!qh feasible_point) {
-      qh_fprintf(qh ferr, 6067, "qhull input error (qh_printafacet): option 'Fp' needs qh feasible_point\n");
-      qh_errexit( qh_ERRinput, NULL, NULL);
-    }
-    if (facet->offset > 0)
-      goto LABELprintinfinite;
-    point= coordp= (coordT*)qh_memalloc(qh normal_size);
-    normp= facet->normal;
-    feasiblep= qh feasible_point;
-    if (facet->offset < -qh MINdenom) {
-      for (k=qh hull_dim; k--; )
-        *(coordp++)= (*(normp++) / - facet->offset) + *(feasiblep++);
-    }else {
-      for (k=qh hull_dim; k--; ) {
-        *(coordp++)= qh_divzero(*(normp++), facet->offset, qh MINdenom_1,
-                                 &zerodiv) + *(feasiblep++);
-        if (zerodiv) {
-          qh_memfree(point, qh normal_size);
-          goto LABELprintinfinite;
-        }
-      }
-    }
-    qh_printpoint(fp, NULL, point);
-    qh_memfree(point, qh normal_size);
-    break;
-  LABELprintinfinite:
-    for (k=qh hull_dim; k--; )
-      qh_fprintf(fp, 9026, qh_REAL_1, qh_INFINITE);
-    qh_fprintf(fp, 9027, "\n");
-    break;
-  case qh_PRINTpointnearest:
-    FOREACHpoint_(facet->coplanarset) {
-      int id, id2;
-      vertex= qh_nearvertex(facet, point, &dist);
-      id= qh_pointid(vertex->point);
-      id2= qh_pointid(point);
-      qh_fprintf(fp, 9028, "%d %d %d " qh_REAL_1 "\n", id, id2, facet->id, dist);
-    }
-    break;
-  case qh_PRINTpoints:  /* VORONOI only by qh_printbegin */
-    if (qh CDDoutput)
-      qh_fprintf(fp, 9029, "1 ");
-    qh_printcenter(fp, format, NULL, facet);
-    break;
-  case qh_PRINTvertices:
-    qh_fprintf(fp, 9030, "%d", qh_setsize(facet->vertices));
-    FOREACHvertex_(facet->vertices)
-      qh_fprintf(fp, 9031, " %d", qh_pointid(vertex->point));
-    qh_fprintf(fp, 9032, "\n");
-    break;
-  default:
-    break;
-  }
-} /* printafacet */
-
-/*---------------------------------
-
-  qh_printbegin(  )
-    prints header for all output formats
-
-  returns:
-    checks for valid format
-
-  notes:
-    uses qh.visit_id for 3/4off
-    changes qh.interior_point if printing centrums
-    qh_countfacets clears facet->visitid for non-good facets
-
-  see
-    qh_printend() and qh_printafacet()
-
-  design:
-    count facets and related statistics
-    print header for format
-*/
-void qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
-  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
-  int i, num;
-  facetT *facet, **facetp;
-  vertexT *vertex, **vertexp;
-  setT *vertices;
-  pointT *point, **pointp, *pointtemp;
-
-  qh printoutnum= 0;
-  qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
-      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
-  switch (format) {
-  case qh_PRINTnone:
-    break;
-  case qh_PRINTarea:
-    qh_fprintf(fp, 9033, "%d\n", numfacets);
-    break;
-  case qh_PRINTcoplanars:
-    qh_fprintf(fp, 9034, "%d\n", numfacets);
-    break;
-  case qh_PRINTcentrums:
-    if (qh CENTERtype == qh_ASnone)
-      qh_clearcenters(qh_AScentrum);
-    qh_fprintf(fp, 9035, "%d\n%d\n", qh hull_dim, numfacets);
-    break;
-  case qh_PRINTfacets:
-  case qh_PRINTfacets_xridge:
-    if (facetlist)
-      qh_printvertexlist(fp, "Vertices and facets:\n", facetlist, facets, printall);
-    break;
-  case qh_PRINTgeom:
-    if (qh hull_dim > 4)  /* qh_initqhull_globals also checks */
-      goto LABELnoformat;
-    if (qh VORONOI && qh hull_dim > 3)  /* PRINTdim == DROPdim == hull_dim-1 */
-      goto LABELnoformat;
-    if (qh hull_dim == 2 && (qh PRINTridges || qh DOintersections))
-      qh_fprintf(qh ferr, 7049, "qhull warning: output for ridges and intersections not implemented in 2-d\n");
-    if (qh hull_dim == 4 && (qh PRINTinner || qh PRINTouter ||
-                             (qh PRINTdim == 4 && qh PRINTcentrums)))
-      qh_fprintf(qh ferr, 7050, "qhull warning: output for outer/inner planes and centrums not implemented in 4-d\n");
-    if (qh PRINTdim == 4 && (qh PRINTspheres))
-      qh_fprintf(qh ferr, 7051, "qhull warning: output for vertices not implemented in 4-d\n");
-    if (qh PRINTdim == 4 && qh DOintersections && qh PRINTnoplanes)
-      qh_fprintf(qh ferr, 7052, "qhull warning: 'Gnh' generates no output in 4-d\n");
-    if (qh PRINTdim == 2) {
-      qh_fprintf(fp, 9036, "{appearance {linewidth 3} LIST # %s | %s\n",
-              qh rbox_command, qh qhull_command);
-    }else if (qh PRINTdim == 3) {
-      qh_fprintf(fp, 9037, "{appearance {+edge -evert linewidth 2} LIST # %s | %s\n",
-              qh rbox_command, qh qhull_command);
-    }else if (qh PRINTdim == 4) {
-      qh visit_id++;
-      num= 0;
-      FORALLfacet_(facetlist)    /* get number of ridges to be printed */
-        qh_printend4geom(NULL, facet, &num, printall);
-      FOREACHfacet_(facets)
-        qh_printend4geom(NULL, facet, &num, printall);
-      qh ridgeoutnum= num;
-      qh printoutvar= 0;  /* counts number of ridges in output */
-      qh_fprintf(fp, 9038, "LIST # %s | %s\n", qh rbox_command, qh qhull_command);
-    }
-
-    if (qh PRINTdots) {
-      qh printoutnum++;
-      num= qh num_points + qh_setsize(qh other_points);
-      if (qh DELAUNAY && qh ATinfinity)
-        num--;
-      if (qh PRINTdim == 4)
-        qh_fprintf(fp, 9039, "4VECT %d %d 1\n", num, num);
-      else
-        qh_fprintf(fp, 9040, "VECT %d %d 1\n", num, num);
-
-      for (i=num; i--; ) {
-        if (i % 20 == 0)
-          qh_fprintf(fp, 9041, "\n");
-        qh_fprintf(fp, 9042, "1 ");
-      }
-      qh_fprintf(fp, 9043, "# 1 point per line\n1 ");
-      for (i=num-1; i--; ) { /* num at least 3 for D2 */
-        if (i % 20 == 0)
-          qh_fprintf(fp, 9044, "\n");
-        qh_fprintf(fp, 9045, "0 ");
-      }
-      qh_fprintf(fp, 9046, "# 1 color for all\n");
-      FORALLpoints {
-        if (!qh DELAUNAY || !qh ATinfinity || qh_pointid(point) != qh num_points-1) {
-          if (qh PRINTdim == 4)
-            qh_printpoint(fp, NULL, point);
-            else
-              qh_printpoint3(fp, point);
-        }
-      }
-      FOREACHpoint_(qh other_points) {
-        if (qh PRINTdim == 4)
-          qh_printpoint(fp, NULL, point);
-        else
-          qh_printpoint3(fp, point);
-      }
-      qh_fprintf(fp, 9047, "0 1 1 1  # color of points\n");
-    }
-
-    if (qh PRINTdim == 4  && !qh PRINTnoplanes)
-      /* 4dview loads up multiple 4OFF objects slowly */
-      qh_fprintf(fp, 9048, "4OFF %d %d 1\n", 3*qh ridgeoutnum, qh ridgeoutnum);
-    qh PRINTcradius= 2 * qh DISTround;  /* include test DISTround */
-    if (qh PREmerge) {
-      maximize_(qh PRINTcradius, qh premerge_centrum + qh DISTround);
-    }else if (qh POSTmerge)
-      maximize_(qh PRINTcradius, qh postmerge_centrum + qh DISTround);
-    qh PRINTradius= qh PRINTcradius;
-    if (qh PRINTspheres + qh PRINTcoplanar)
-      maximize_(qh PRINTradius, qh MAXabs_coord * qh_MINradius);
-    if (qh premerge_cos < REALmax/2) {
-      maximize_(qh PRINTradius, (1- qh premerge_cos) * qh MAXabs_coord);
-    }else if (!qh PREmerge && qh POSTmerge && qh postmerge_cos < REALmax/2) {
-      maximize_(qh PRINTradius, (1- qh postmerge_cos) * qh MAXabs_coord);
-    }
-    maximize_(qh PRINTradius, qh MINvisible);
-    if (qh JOGGLEmax < REALmax/2)
-      qh PRINTradius += qh JOGGLEmax * sqrt((realT)qh hull_dim);
-    if (qh PRINTdim != 4 &&
-        (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
-      vertices= qh_facetvertices(facetlist, facets, printall);
-      if (qh PRINTspheres && qh PRINTdim <= 3)
-        qh_printspheres(fp, vertices, qh PRINTradius);
-      if (qh PRINTcoplanar || qh PRINTcentrums) {
-        qh firstcentrum= True;
-        if (qh PRINTcoplanar&& !qh PRINTspheres) {
-          FOREACHvertex_(vertices)
-            qh_printpointvect2(fp, vertex->point, NULL, qh interior_point, qh PRINTradius);
-        }
-        FORALLfacet_(facetlist) {
-          if (!printall && qh_skipfacet(facet))
-            continue;
-          if (!facet->normal)
-            continue;
-          if (qh PRINTcentrums && qh PRINTdim <= 3)
-            qh_printcentrum(fp, facet, qh PRINTcradius);
-          if (!qh PRINTcoplanar)
-            continue;
-          FOREACHpoint_(facet->coplanarset)
-            qh_printpointvect2(fp, point, facet->normal, NULL, qh PRINTradius);
-          FOREACHpoint_(facet->outsideset)
-            qh_printpointvect2(fp, point, facet->normal, NULL, qh PRINTradius);
-        }
-        FOREACHfacet_(facets) {
-          if (!printall && qh_skipfacet(facet))
-            continue;
-          if (!facet->normal)
-            continue;
-          if (qh PRINTcentrums && qh PRINTdim <= 3)
-            qh_printcentrum(fp, facet, qh PRINTcradius);
-          if (!qh PRINTcoplanar)
-            continue;
-          FOREACHpoint_(facet->coplanarset)
-            qh_printpointvect2(fp, point, facet->normal, NULL, qh PRINTradius);
-          FOREACHpoint_(facet->outsideset)
-            qh_printpointvect2(fp, point, facet->normal, NULL, qh PRINTradius);
-        }
-      }
-      qh_settempfree(&vertices);
-    }
-    qh visit_id++; /* for printing hyperplane intersections */
-    break;
-  case qh_PRINTids:
-    qh_fprintf(fp, 9049, "%d\n", numfacets);
-    break;
-  case qh_PRINTincidences:
-    if (qh VORONOI && qh PRINTprecision)
-      qh_fprintf(qh ferr, 7053, "qhull warning: writing Delaunay.  Use 'p' or 'o' for Voronoi centers\n");
-    qh printoutvar= qh vertex_id;  /* centrum id for non-simplicial facets */
-    if (qh hull_dim <= 3)
-      qh_fprintf(fp, 9050, "%d\n", numfacets);
-    else
-      qh_fprintf(fp, 9051, "%d\n", numsimplicial+numridges);
-    break;
-  case qh_PRINTinner:
-  case qh_PRINTnormals:
-  case qh_PRINTouter:
-    if (qh CDDoutput)
-      qh_fprintf(fp, 9052, "%s | %s\nbegin\n    %d %d real\n", qh rbox_command,
-            qh qhull_command, numfacets, qh hull_dim+1);
-    else
-      qh_fprintf(fp, 9053, "%d\n%d\n", qh hull_dim+1, numfacets);
-    break;
-  case qh_PRINTmathematica:
-  case qh_PRINTmaple:
-    if (qh hull_dim > 3)  /* qh_initbuffers also checks */
-      goto LABELnoformat;
-    if (qh VORONOI)
-      qh_fprintf(qh ferr, 7054, "qhull warning: output is the Delaunay triangulation\n");
-    if (format == qh_PRINTmaple) {
-      if (qh hull_dim == 2)
-        qh_fprintf(fp, 9054, "PLOT(CURVES(\n");
-      else
-        qh_fprintf(fp, 9055, "PLOT3D(POLYGONS(\n");
-    }else
-      qh_fprintf(fp, 9056, "{\n");
-    qh printoutvar= 0;   /* counts number of facets for notfirst */
-    break;
-  case qh_PRINTmerges:
-    qh_fprintf(fp, 9057, "%d\n", numfacets);
-    break;
-  case qh_PRINTpointintersect:
-    qh_fprintf(fp, 9058, "%d\n%d\n", qh hull_dim, numfacets);
-    break;
-  case qh_PRINTneighbors:
-    qh_fprintf(fp, 9059, "%d\n", numfacets);
-    break;
-  case qh_PRINToff:
-  case qh_PRINTtriangles:
-    if (qh VORONOI)
-      goto LABELnoformat;
-    num = qh hull_dim;
-    if (format == qh_PRINToff || qh hull_dim == 2)
-      qh_fprintf(fp, 9060, "%d\n%d %d %d\n", num,
-        qh num_points+qh_setsize(qh other_points), numfacets, totneighbors/2);
-    else { /* qh_PRINTtriangles */
-      qh printoutvar= qh num_points+qh_setsize(qh other_points); /* first centrum */
-      if (qh DELAUNAY)
-        num--;  /* drop last dimension */
-      qh_fprintf(fp, 9061, "%d\n%d %d %d\n", num, qh printoutvar
-        + numfacets - numsimplicial, numsimplicial + numridges, totneighbors/2);
-    }
-    FORALLpoints
-      qh_printpointid(qh fout, NULL, num, point, qh_IDunknown);
-    FOREACHpoint_(qh other_points)
-      qh_printpointid(qh fout, NULL, num, point, qh_IDunknown);
-    if (format == qh_PRINTtriangles && qh hull_dim > 2) {
-      FORALLfacets {
-        if (!facet->simplicial && facet->visitid)
-          qh_printcenter(qh fout, format, NULL, facet);
-      }
-    }
-    break;
-  case qh_PRINTpointnearest:
-    qh_fprintf(fp, 9062, "%d\n", numcoplanars);
-    break;
-  case qh_PRINTpoints:
-    if (!qh VORONOI)
-      goto LABELnoformat;
-    if (qh CDDoutput)
-      qh_fprintf(fp, 9063, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
-           qh qhull_command, numfacets, qh hull_dim);
-    else
-      qh_fprintf(fp, 9064, "%d\n%d\n", qh hull_dim-1, numfacets);
-    break;
-  case qh_PRINTvertices:
-    qh_fprintf(fp, 9065, "%d\n", numfacets);
-    break;
-  case qh_PRINTsummary:
-  default:
-  LABELnoformat:
-    qh_fprintf(qh ferr, 6068, "qhull internal error (qh_printbegin): can not use this format for dimension %d\n",
-         qh hull_dim);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-} /* printbegin */
-
-/*---------------------------------
-
-  qh_printcenter( fp, string, facet )
-    print facet->center as centrum or Voronoi center
-    string may be NULL.  Don't include '%' codes.
-    nop if qh CENTERtype neither CENTERvoronoi nor CENTERcentrum
-    if upper envelope of Delaunay triangulation and point at-infinity
-      prints qh_INFINITE instead;
-
-  notes:
-    defines facet->center if needed
-    if format=PRINTgeom, adds a 0 if would otherwise be 2-d
-    Same as QhullFacet::printCenter
-*/
-void qh_printcenter(FILE *fp, qh_PRINT format, const char *string, facetT *facet) {
-  int k, num;
-
-  if (qh CENTERtype != qh_ASvoronoi && qh CENTERtype != qh_AScentrum)
-    return;
-  if (string)
-    qh_fprintf(fp, 9066, string);
-  if (qh CENTERtype == qh_ASvoronoi) {
-    num= qh hull_dim-1;
-    if (!facet->normal || !facet->upperdelaunay || !qh ATinfinity) {
-      if (!facet->center)
-        facet->center= qh_facetcenter(facet->vertices);
-      for (k=0; k < num; k++)
-        qh_fprintf(fp, 9067, qh_REAL_1, facet->center[k]);
-    }else {
-      for (k=0; k < num; k++)
-        qh_fprintf(fp, 9068, qh_REAL_1, qh_INFINITE);
-    }
-  }else /* qh.CENTERtype == qh_AScentrum */ {
-    num= qh hull_dim;
-    if (format == qh_PRINTtriangles && qh DELAUNAY)
-      num--;
-    if (!facet->center)
-      facet->center= qh_getcentrum(facet);
-    for (k=0; k < num; k++)
-      qh_fprintf(fp, 9069, qh_REAL_1, facet->center[k]);
-  }
-  if (format == qh_PRINTgeom && num == 2)
-    qh_fprintf(fp, 9070, " 0\n");
-  else
-    qh_fprintf(fp, 9071, "\n");
-} /* printcenter */
-
-/*---------------------------------
-
-  qh_printcentrum( fp, facet, radius )
-    print centrum for a facet in OOGL format
-    radius defines size of centrum
-    2-d or 3-d only
-
-  returns:
-    defines facet->center if needed
-*/
-void qh_printcentrum(FILE *fp, facetT *facet, realT radius) {
-  pointT *centrum, *projpt;
-  boolT tempcentrum= False;
-  realT xaxis[4], yaxis[4], normal[4], dist;
-  realT green[3]={0, 1, 0};
-  vertexT *apex;
-  int k;
-
-  if (qh CENTERtype == qh_AScentrum) {
-    if (!facet->center)
-      facet->center= qh_getcentrum(facet);
-    centrum= facet->center;
-  }else {
-    centrum= qh_getcentrum(facet);
-    tempcentrum= True;
-  }
-  qh_fprintf(fp, 9072, "{appearance {-normal -edge normscale 0} ");
-  if (qh firstcentrum) {
-    qh firstcentrum= False;
-    qh_fprintf(fp, 9073, "{INST geom { define centrum CQUAD  # f%d\n\
--0.3 -0.3 0.0001     0 0 1 1\n\
- 0.3 -0.3 0.0001     0 0 1 1\n\
- 0.3  0.3 0.0001     0 0 1 1\n\
--0.3  0.3 0.0001     0 0 1 1 } transform { \n", facet->id);
-  }else
-    qh_fprintf(fp, 9074, "{INST geom { : centrum } transform { # f%d\n", facet->id);
-  apex= SETfirstt_(facet->vertices, vertexT);
-  qh_distplane(apex->point, facet, &dist);
-  projpt= qh_projectpoint(apex->point, facet, dist);
-  for (k=qh hull_dim; k--; ) {
-    xaxis[k]= projpt[k] - centrum[k];
-    normal[k]= facet->normal[k];
-  }
-  if (qh hull_dim == 2) {
-    xaxis[2]= 0;
-    normal[2]= 0;
-  }else if (qh hull_dim == 4) {
-    qh_projectdim3(xaxis, xaxis);
-    qh_projectdim3(normal, normal);
-    qh_normalize2(normal, qh PRINTdim, True, NULL, NULL);
-  }
-  qh_crossproduct(3, xaxis, normal, yaxis);
-  qh_fprintf(fp, 9075, "%8.4g %8.4g %8.4g 0\n", xaxis[0], xaxis[1], xaxis[2]);
-  qh_fprintf(fp, 9076, "%8.4g %8.4g %8.4g 0\n", yaxis[0], yaxis[1], yaxis[2]);
-  qh_fprintf(fp, 9077, "%8.4g %8.4g %8.4g 0\n", normal[0], normal[1], normal[2]);
-  qh_printpoint3(fp, centrum);
-  qh_fprintf(fp, 9078, "1 }}}\n");
-  qh_memfree(projpt, qh normal_size);
-  qh_printpointvect(fp, centrum, facet->normal, NULL, radius, green);
-  if (tempcentrum)
-    qh_memfree(centrum, qh normal_size);
-} /* printcentrum */
-
-/*---------------------------------
-
-  qh_printend( fp, format )
-    prints trailer for all output formats
-
-  see:
-    qh_printbegin() and qh_printafacet()
-
-*/
-void qh_printend(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
-  int num;
-  facetT *facet, **facetp;
-
-  if (!qh printoutnum)
-    qh_fprintf(qh ferr, 7055, "qhull warning: no facets printed\n");
-  switch (format) {
-  case qh_PRINTgeom:
-    if (qh hull_dim == 4 && qh DROPdim < 0  && !qh PRINTnoplanes) {
-      qh visit_id++;
-      num= 0;
-      FORALLfacet_(facetlist)
-        qh_printend4geom(fp, facet,&num, printall);
-      FOREACHfacet_(facets)
-        qh_printend4geom(fp, facet, &num, printall);
-      if (num != qh ridgeoutnum || qh printoutvar != qh ridgeoutnum) {
-        qh_fprintf(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);
-        qh_errexit(qh_ERRqhull, NULL, NULL);
-      }
-    }else
-      qh_fprintf(fp, 9079, "}\n");
-    break;
-  case qh_PRINTinner:
-  case qh_PRINTnormals:
-  case qh_PRINTouter:
-    if (qh CDDoutput)
-      qh_fprintf(fp, 9080, "end\n");
-    break;
-  case qh_PRINTmaple:
-    qh_fprintf(fp, 9081, "));\n");
-    break;
-  case qh_PRINTmathematica:
-    qh_fprintf(fp, 9082, "}\n");
-    break;
-  case qh_PRINTpoints:
-    if (qh CDDoutput)
-      qh_fprintf(fp, 9083, "end\n");
-    break;
-  default:
-    break;
-  }
-} /* printend */
-
-/*---------------------------------
-
-  qh_printend4geom( fp, facet, numridges, printall )
-    helper function for qh_printbegin/printend
-
-  returns:
-    number of printed ridges
-
-  notes:
-    just counts printed ridges if fp=NULL
-    uses facet->visitid
-    must agree with qh_printfacet4geom...
-
-  design:
-    computes color for facet from its normal
-    prints each ridge of facet
-*/
-void qh_printend4geom(FILE *fp, facetT *facet, int *nump, boolT printall) {
-  realT color[3];
-  int i, num= *nump;
-  facetT *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-
-  if (!printall && qh_skipfacet(facet))
-    return;
-  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
-    return;
-  if (!facet->normal)
-    return;
-  if (fp) {
-    for (i=0; i < 3; i++) {
-      color[i]= (facet->normal[i]+1.0)/2.0;
-      maximize_(color[i], -1.0);
-      minimize_(color[i], +1.0);
-    }
-  }
-  facet->visitid= qh visit_id;
-  if (facet->simplicial) {
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid != qh visit_id) {
-        if (fp)
-          qh_fprintf(fp, 9084, "3 %d %d %d %8.4g %8.4g %8.4g 1 # f%d f%d\n",
-                 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
-                 facet->id, neighbor->id);
-        num++;
-      }
-    }
-  }else {
-    FOREACHridge_(facet->ridges) {
-      neighbor= otherfacet_(ridge, facet);
-      if (neighbor->visitid != qh visit_id) {
-        if (fp)
-          qh_fprintf(fp, 9085, "3 %d %d %d %8.4g %8.4g %8.4g 1 #r%d f%d f%d\n",
-                 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
-                 ridge->id, facet->id, neighbor->id);
-        num++;
-      }
-    }
-  }
-  *nump= num;
-} /* printend4geom */
-
-/*---------------------------------
-
-  qh_printextremes( fp, facetlist, facets, printall )
-    print extreme points for convex hulls or halfspace intersections
-
-  notes:
-    #points, followed by ids, one per line
-
-    sorted by id
-    same order as qh_printpoints_out if no coplanar/interior points
-*/
-void qh_printextremes(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
-  setT *vertices, *points;
-  pointT *point;
-  vertexT *vertex, **vertexp;
-  int id;
-  int numpoints=0, point_i, point_n;
-  int allpoints= qh num_points + qh_setsize(qh other_points);
-
-  points= qh_settemp(allpoints);
-  qh_setzero(points, 0, allpoints);
-  vertices= qh_facetvertices(facetlist, facets, printall);
-  FOREACHvertex_(vertices) {
-    id= qh_pointid(vertex->point);
-    if (id >= 0) {
-      SETelem_(points, id)= vertex->point;
-      numpoints++;
-    }
-  }
-  qh_settempfree(&vertices);
-  qh_fprintf(fp, 9086, "%d\n", numpoints);
-  FOREACHpoint_i_(points) {
-    if (point)
-      qh_fprintf(fp, 9087, "%d\n", point_i);
-  }
-  qh_settempfree(&points);
-} /* printextremes */
-
-/*---------------------------------
-
-  qh_printextremes_2d( fp, facetlist, facets, printall )
-    prints point ids for facets in qh_ORIENTclock order
-
-  notes:
-    #points, followed by ids, one per line
-    if facetlist/facets are disjoint than the output includes skips
-    errors if facets form a loop
-    does not print coplanar points
-*/
-void qh_printextremes_2d(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
-  int numfacets, numridges, totneighbors, numcoplanars, numsimplicial, numtricoplanars;
-  setT *vertices;
-  facetT *facet, *startfacet, *nextfacet;
-  vertexT *vertexA, *vertexB;
-
-  qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
-      &totneighbors, &numridges, &numcoplanars, &numtricoplanars); /* marks qh visit_id */
-  vertices= qh_facetvertices(facetlist, facets, printall);
-  qh_fprintf(fp, 9088, "%d\n", qh_setsize(vertices));
-  qh_settempfree(&vertices);
-  if (!numfacets)
-    return;
-  facet= startfacet= facetlist ? facetlist : SETfirstt_(facets, facetT);
-  qh vertex_visit++;
-  qh visit_id++;
-  do {
-    if (facet->toporient ^ qh_ORIENTclock) {
-      vertexA= SETfirstt_(facet->vertices, vertexT);
-      vertexB= SETsecondt_(facet->vertices, vertexT);
-      nextfacet= SETfirstt_(facet->neighbors, facetT);
-    }else {
-      vertexA= SETsecondt_(facet->vertices, vertexT);
-      vertexB= SETfirstt_(facet->vertices, vertexT);
-      nextfacet= SETsecondt_(facet->neighbors, facetT);
-    }
-    if (facet->visitid == qh visit_id) {
-      qh_fprintf(qh ferr, 6218, "Qhull internal error (qh_printextremes_2d): loop in facet list.  facet %d nextfacet %d\n",
-                 facet->id, nextfacet->id);
-      qh_errexit2(qh_ERRqhull, facet, nextfacet);
-    }
-    if (facet->visitid) {
-      if (vertexA->visitid != qh vertex_visit) {
-        vertexA->visitid= qh vertex_visit;
-        qh_fprintf(fp, 9089, "%d\n", qh_pointid(vertexA->point));
-      }
-      if (vertexB->visitid != qh vertex_visit) {
-        vertexB->visitid= qh vertex_visit;
-        qh_fprintf(fp, 9090, "%d\n", qh_pointid(vertexB->point));
-      }
-    }
-    facet->visitid= qh visit_id;
-    facet= nextfacet;
-  }while (facet && facet != startfacet);
-} /* printextremes_2d */
-
-/*---------------------------------
-
-  qh_printextremes_d( fp, facetlist, facets, printall )
-    print extreme points of input sites for Delaunay triangulations
-
-  notes:
-    #points, followed by ids, one per line
-
-    unordered
-*/
-void qh_printextremes_d(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
-  setT *vertices;
-  vertexT *vertex, **vertexp;
-  boolT upperseen, lowerseen;
-  facetT *neighbor, **neighborp;
-  int numpoints=0;
-
-  vertices= qh_facetvertices(facetlist, facets, printall);
-  qh_vertexneighbors();
-  FOREACHvertex_(vertices) {
-    upperseen= lowerseen= False;
-    FOREACHneighbor_(vertex) {
-      if (neighbor->upperdelaunay)
-        upperseen= True;
-      else
-        lowerseen= True;
-    }
-    if (upperseen && lowerseen) {
-      vertex->seen= True;
-      numpoints++;
-    }else
-      vertex->seen= False;
-  }
-  qh_fprintf(fp, 9091, "%d\n", numpoints);
-  FOREACHvertex_(vertices) {
-    if (vertex->seen)
-      qh_fprintf(fp, 9092, "%d\n", qh_pointid(vertex->point));
-  }
-  qh_settempfree(&vertices);
-} /* printextremes_d */
-
-/*---------------------------------
-
-  qh_printfacet( fp, facet )
-    prints all fields of a facet to fp
-
-  notes:
-    ridges printed in neighbor order
-*/
-void qh_printfacet(FILE *fp, facetT *facet) {
-
-  qh_printfacetheader(fp, facet);
-  if (facet->ridges)
-    qh_printfacetridges(fp, facet);
-} /* printfacet */
-
-
-/*---------------------------------
-
-  qh_printfacet2geom( fp, facet, color )
-    print facet as part of a 2-d VECT for Geomview
-
-    notes:
-      assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
-      mindist is calculated within io.c.  maxoutside is calculated elsewhere
-      so a DISTround error may have occurred.
-*/
-void qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]) {
-  pointT *point0, *point1;
-  realT mindist, innerplane, outerplane;
-  int k;
-
-  qh_facet2point(facet, &point0, &point1, &mindist);
-  qh_geomplanes(facet, &outerplane, &innerplane);
-  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
-    qh_printfacet2geom_points(fp, point0, point1, facet, outerplane, color);
-  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
-                outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
-    for (k=3; k--; )
-      color[k]= 1.0 - color[k];
-    qh_printfacet2geom_points(fp, point0, point1, facet, innerplane, color);
-  }
-  qh_memfree(point1, qh normal_size);
-  qh_memfree(point0, qh normal_size);
-} /* printfacet2geom */
-
-/*---------------------------------
-
-  qh_printfacet2geom_points( fp, point1, point2, facet, offset, color )
-    prints a 2-d facet as a VECT with 2 points at some offset.
-    The points are on the facet's plane.
-*/
-void qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
-                               facetT *facet, realT offset, realT color[3]) {
-  pointT *p1= point1, *p2= point2;
-
-  qh_fprintf(fp, 9093, "VECT 1 2 1 2 1 # f%d\n", facet->id);
-  if (offset != 0.0) {
-    p1= qh_projectpoint(p1, facet, -offset);
-    p2= qh_projectpoint(p2, facet, -offset);
-  }
-  qh_fprintf(fp, 9094, "%8.4g %8.4g %8.4g\n%8.4g %8.4g %8.4g\n",
-           p1[0], p1[1], 0.0, p2[0], p2[1], 0.0);
-  if (offset != 0.0) {
-    qh_memfree(p1, qh normal_size);
-    qh_memfree(p2, qh normal_size);
-  }
-  qh_fprintf(fp, 9095, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
-} /* printfacet2geom_points */
-
-
-/*---------------------------------
-
-  qh_printfacet2math( fp, facet, format, notfirst )
-    print 2-d Maple or Mathematica output for a facet
-    may be non-simplicial
-
-  notes:
-    use %16.8f since Mathematica 2.2 does not handle exponential format
-    see qh_printfacet3math
-*/
-void qh_printfacet2math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
-  pointT *point0, *point1;
-  realT mindist;
-  const char *pointfmt;
-
-  qh_facet2point(facet, &point0, &point1, &mindist);
-  if (notfirst)
-    qh_fprintf(fp, 9096, ",");
-  if (format == qh_PRINTmaple)
-    pointfmt= "[[%16.8f, %16.8f], [%16.8f, %16.8f]]\n";
-  else
-    pointfmt= "Line[{{%16.8f, %16.8f}, {%16.8f, %16.8f}}]\n";
-  qh_fprintf(fp, 9097, pointfmt, point0[0], point0[1], point1[0], point1[1]);
-  qh_memfree(point1, qh normal_size);
-  qh_memfree(point0, qh normal_size);
-} /* printfacet2math */
-
-
-/*---------------------------------
-
-  qh_printfacet3geom_nonsimplicial( fp, facet, color )
-    print Geomview OFF for a 3-d nonsimplicial facet.
-    if DOintersections, prints ridges to unvisited neighbors(qh visit_id)
-
-  notes
-    uses facet->visitid for intersections and ridges
-*/
-void qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
-  ridgeT *ridge, **ridgep;
-  setT *projectedpoints, *vertices;
-  vertexT *vertex, **vertexp, *vertexA, *vertexB;
-  pointT *projpt, *point, **pointp;
-  facetT *neighbor;
-  realT dist, outerplane, innerplane;
-  int cntvertices, k;
-  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
-
-  qh_geomplanes(facet, &outerplane, &innerplane);
-  vertices= qh_facet3vertex(facet); /* oriented */
-  cntvertices= qh_setsize(vertices);
-  projectedpoints= qh_settemp(cntvertices);
-  FOREACHvertex_(vertices) {
-    zinc_(Zdistio);
-    qh_distplane(vertex->point, facet, &dist);
-    projpt= qh_projectpoint(vertex->point, facet, dist);
-    qh_setappend(&projectedpoints, projpt);
-  }
-  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
-    qh_printfacet3geom_points(fp, projectedpoints, facet, outerplane, color);
-  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
-                outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
-    for (k=3; k--; )
-      color[k]= 1.0 - color[k];
-    qh_printfacet3geom_points(fp, projectedpoints, facet, innerplane, color);
-  }
-  FOREACHpoint_(projectedpoints)
-    qh_memfree(point, qh normal_size);
-  qh_settempfree(&projectedpoints);
-  qh_settempfree(&vertices);
-  if ((qh DOintersections || qh PRINTridges)
-  && (!facet->visible || !qh NEWfacets)) {
-    facet->visitid= qh visit_id;
-    FOREACHridge_(facet->ridges) {
-      neighbor= otherfacet_(ridge, facet);
-      if (neighbor->visitid != qh visit_id) {
-        if (qh DOintersections)
-          qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, black);
-        if (qh PRINTridges) {
-          vertexA= SETfirstt_(ridge->vertices, vertexT);
-          vertexB= SETsecondt_(ridge->vertices, vertexT);
-          qh_printline3geom(fp, vertexA->point, vertexB->point, green);
-        }
-      }
-    }
-  }
-} /* printfacet3geom_nonsimplicial */
-
-/*---------------------------------
-
-  qh_printfacet3geom_points( fp, points, facet, offset )
-    prints a 3-d facet as OFF Geomview object.
-    offset is relative to the facet's hyperplane
-    Facet is determined as a list of points
-*/
-void qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]) {
-  int k, n= qh_setsize(points), i;
-  pointT *point, **pointp;
-  setT *printpoints;
-
-  qh_fprintf(fp, 9098, "{ OFF %d 1 1 # f%d\n", n, facet->id);
-  if (offset != 0.0) {
-    printpoints= qh_settemp(n);
-    FOREACHpoint_(points)
-      qh_setappend(&printpoints, qh_projectpoint(point, facet, -offset));
-  }else
-    printpoints= points;
-  FOREACHpoint_(printpoints) {
-    for (k=0; k < qh hull_dim; k++) {
-      if (k == qh DROPdim)
-        qh_fprintf(fp, 9099, "0 ");
-      else
-        qh_fprintf(fp, 9100, "%8.4g ", point[k]);
-    }
-    if (printpoints != points)
-      qh_memfree(point, qh normal_size);
-    qh_fprintf(fp, 9101, "\n");
-  }
-  if (printpoints != points)
-    qh_settempfree(&printpoints);
-  qh_fprintf(fp, 9102, "%d ", n);
-  for (i=0; i < n; i++)
-    qh_fprintf(fp, 9103, "%d ", i);
-  qh_fprintf(fp, 9104, "%8.4g %8.4g %8.4g 1.0 }\n", color[0], color[1], color[2]);
-} /* printfacet3geom_points */
-
-
-/*---------------------------------
-
-  qh_printfacet3geom_simplicial(  )
-    print Geomview OFF for a 3-d simplicial facet.
-
-  notes:
-    may flip color
-    uses facet->visitid for intersections and ridges
-
-    assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
-    innerplane may be off by qh DISTround.  Maxoutside is calculated elsewhere
-    so a DISTround error may have occurred.
-*/
-void qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
-  setT *points, *vertices;
-  vertexT *vertex, **vertexp, *vertexA, *vertexB;
-  facetT *neighbor, **neighborp;
-  realT outerplane, innerplane;
-  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
-  int k;
-
-  qh_geomplanes(facet, &outerplane, &innerplane);
-  vertices= qh_facet3vertex(facet);
-  points= qh_settemp(qh TEMPsize);
-  FOREACHvertex_(vertices)
-    qh_setappend(&points, vertex->point);
-  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
-    qh_printfacet3geom_points(fp, points, facet, outerplane, color);
-  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
-              outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
-    for (k=3; k--; )
-      color[k]= 1.0 - color[k];
-    qh_printfacet3geom_points(fp, points, facet, innerplane, color);
-  }
-  qh_settempfree(&points);
-  qh_settempfree(&vertices);
-  if ((qh DOintersections || qh PRINTridges)
-  && (!facet->visible || !qh NEWfacets)) {
-    facet->visitid= qh visit_id;
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid != qh visit_id) {
-        vertices= qh_setnew_delnthsorted(facet->vertices, qh hull_dim,
-                          SETindex_(facet->neighbors, neighbor), 0);
-        if (qh DOintersections)
-           qh_printhyperplaneintersection(fp, facet, neighbor, vertices, black);
-        if (qh PRINTridges) {
-          vertexA= SETfirstt_(vertices, vertexT);
-          vertexB= SETsecondt_(vertices, vertexT);
-          qh_printline3geom(fp, vertexA->point, vertexB->point, green);
-        }
-        qh_setfree(&vertices);
-      }
-    }
-  }
-} /* printfacet3geom_simplicial */
-
-/*---------------------------------
-
-  qh_printfacet3math( fp, facet, notfirst )
-    print 3-d Maple or Mathematica output for a facet
-
-  notes:
-    may be non-simplicial
-    use %16.8f since Mathematica 2.2 does not handle exponential format
-    see qh_printfacet2math
-*/
-void qh_printfacet3math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
-  vertexT *vertex, **vertexp;
-  setT *points, *vertices;
-  pointT *point, **pointp;
-  boolT firstpoint= True;
-  realT dist;
-  const char *pointfmt, *endfmt;
-
-  if (notfirst)
-    qh_fprintf(fp, 9105, ",\n");
-  vertices= qh_facet3vertex(facet);
-  points= qh_settemp(qh_setsize(vertices));
-  FOREACHvertex_(vertices) {
-    zinc_(Zdistio);
-    qh_distplane(vertex->point, facet, &dist);
-    point= qh_projectpoint(vertex->point, facet, dist);
-    qh_setappend(&points, point);
-  }
-  if (format == qh_PRINTmaple) {
-    qh_fprintf(fp, 9106, "[");
-    pointfmt= "[%16.8f, %16.8f, %16.8f]";
-    endfmt= "]";
-  }else {
-    qh_fprintf(fp, 9107, "Polygon[{");
-    pointfmt= "{%16.8f, %16.8f, %16.8f}";
-    endfmt= "}]";
-  }
-  FOREACHpoint_(points) {
-    if (firstpoint)
-      firstpoint= False;
-    else
-      qh_fprintf(fp, 9108, ",\n");
-    qh_fprintf(fp, 9109, pointfmt, point[0], point[1], point[2]);
-  }
-  FOREACHpoint_(points)
-    qh_memfree(point, qh normal_size);
-  qh_settempfree(&points);
-  qh_settempfree(&vertices);
-  qh_fprintf(fp, 9110, "%s", endfmt);
-} /* printfacet3math */
-
-
-/*---------------------------------
-
-  qh_printfacet3vertex( fp, facet, format )
-    print vertices in a 3-d facet as point ids
-
-  notes:
-    prints number of vertices first if format == qh_PRINToff
-    the facet may be non-simplicial
-*/
-void qh_printfacet3vertex(FILE *fp, facetT *facet, qh_PRINT format) {
-  vertexT *vertex, **vertexp;
-  setT *vertices;
-
-  vertices= qh_facet3vertex(facet);
-  if (format == qh_PRINToff)
-    qh_fprintf(fp, 9111, "%d ", qh_setsize(vertices));
-  FOREACHvertex_(vertices)
-    qh_fprintf(fp, 9112, "%d ", qh_pointid(vertex->point));
-  qh_fprintf(fp, 9113, "\n");
-  qh_settempfree(&vertices);
-} /* printfacet3vertex */
-
-
-/*---------------------------------
-
-  qh_printfacet4geom_nonsimplicial(  )
-    print Geomview 4OFF file for a 4d nonsimplicial facet
-    prints all ridges to unvisited neighbors (qh.visit_id)
-    if qh.DROPdim
-      prints in OFF format
-
-  notes:
-    must agree with printend4geom()
-*/
-void qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
-  facetT *neighbor;
-  ridgeT *ridge, **ridgep;
-  vertexT *vertex, **vertexp;
-  pointT *point;
-  int k;
-  realT dist;
-
-  facet->visitid= qh visit_id;
-  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
-    return;
-  FOREACHridge_(facet->ridges) {
-    neighbor= otherfacet_(ridge, facet);
-    if (neighbor->visitid == qh visit_id)
-      continue;
-    if (qh PRINTtransparent && !neighbor->good)
-      continue;
-    if (qh DOintersections)
-      qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, color);
-    else {
-      if (qh DROPdim >= 0)
-        qh_fprintf(fp, 9114, "OFF 3 1 1 # f%d\n", facet->id);
-      else {
-        qh printoutvar++;
-        qh_fprintf(fp, 9115, "# r%d between f%d f%d\n", ridge->id, facet->id, neighbor->id);
-      }
-      FOREACHvertex_(ridge->vertices) {
-        zinc_(Zdistio);
-        qh_distplane(vertex->point,facet, &dist);
-        point=qh_projectpoint(vertex->point,facet, dist);
-        for (k=0; k < qh hull_dim; k++) {
-          if (k != qh DROPdim)
-            qh_fprintf(fp, 9116, "%8.4g ", point[k]);
-        }
-        qh_fprintf(fp, 9117, "\n");
-        qh_memfree(point, qh normal_size);
-      }
-      if (qh DROPdim >= 0)
-        qh_fprintf(fp, 9118, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
-    }
-  }
-} /* printfacet4geom_nonsimplicial */
-
-
-/*---------------------------------
-
-  qh_printfacet4geom_simplicial( fp, facet, color )
-    print Geomview 4OFF file for a 4d simplicial facet
-    prints triangles for unvisited neighbors (qh.visit_id)
-
-  notes:
-    must agree with printend4geom()
-*/
-void qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
-  setT *vertices;
-  facetT *neighbor, **neighborp;
-  vertexT *vertex, **vertexp;
-  int k;
-
-  facet->visitid= qh visit_id;
-  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
-    return;
-  FOREACHneighbor_(facet) {
-    if (neighbor->visitid == qh visit_id)
-      continue;
-    if (qh PRINTtransparent && !neighbor->good)
-      continue;
-    vertices= qh_setnew_delnthsorted(facet->vertices, qh hull_dim,
-                          SETindex_(facet->neighbors, neighbor), 0);
-    if (qh DOintersections)
-      qh_printhyperplaneintersection(fp, facet, neighbor, vertices, color);
-    else {
-      if (qh DROPdim >= 0)
-        qh_fprintf(fp, 9119, "OFF 3 1 1 # ridge between f%d f%d\n",
-                facet->id, neighbor->id);
-      else {
-        qh printoutvar++;
-        qh_fprintf(fp, 9120, "# ridge between f%d f%d\n", facet->id, neighbor->id);
-      }
-      FOREACHvertex_(vertices) {
-        for (k=0; k < qh hull_dim; k++) {
-          if (k != qh DROPdim)
-            qh_fprintf(fp, 9121, "%8.4g ", vertex->point[k]);
-        }
-        qh_fprintf(fp, 9122, "\n");
-      }
-      if (qh DROPdim >= 0)
-        qh_fprintf(fp, 9123, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
-    }
-    qh_setfree(&vertices);
-  }
-} /* printfacet4geom_simplicial */
-
-
-/*---------------------------------
-
-  qh_printfacetNvertex_nonsimplicial( fp, facet, id, format )
-    print vertices for an N-d non-simplicial facet
-    triangulates each ridge to the id
-*/
-void qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, qh_PRINT format) {
-  vertexT *vertex, **vertexp;
-  ridgeT *ridge, **ridgep;
-
-  if (facet->visible && qh NEWfacets)
-    return;
-  FOREACHridge_(facet->ridges) {
-    if (format == qh_PRINTtriangles)
-      qh_fprintf(fp, 9124, "%d ", qh hull_dim);
-    qh_fprintf(fp, 9125, "%d ", id);
-    if ((ridge->top == facet) ^ qh_ORIENTclock) {
-      FOREACHvertex_(ridge->vertices)
-        qh_fprintf(fp, 9126, "%d ", qh_pointid(vertex->point));
-    }else {
-      FOREACHvertexreverse12_(ridge->vertices)
-        qh_fprintf(fp, 9127, "%d ", qh_pointid(vertex->point));
-    }
-    qh_fprintf(fp, 9128, "\n");
-  }
-} /* printfacetNvertex_nonsimplicial */
-
-
-/*---------------------------------
-
-  qh_printfacetNvertex_simplicial( fp, facet, format )
-    print vertices for an N-d simplicial facet
-    prints vertices for non-simplicial facets
-      2-d facets (orientation preserved by qh_mergefacet2d)
-      PRINToff ('o') for 4-d and higher
-*/
-void qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, qh_PRINT format) {
-  vertexT *vertex, **vertexp;
-
-  if (format == qh_PRINToff || format == qh_PRINTtriangles)
-    qh_fprintf(fp, 9129, "%d ", qh_setsize(facet->vertices));
-  if ((facet->toporient ^ qh_ORIENTclock)
-  || (qh hull_dim > 2 && !facet->simplicial)) {
-    FOREACHvertex_(facet->vertices)
-      qh_fprintf(fp, 9130, "%d ", qh_pointid(vertex->point));
-  }else {
-    FOREACHvertexreverse12_(facet->vertices)
-      qh_fprintf(fp, 9131, "%d ", qh_pointid(vertex->point));
-  }
-  qh_fprintf(fp, 9132, "\n");
-} /* printfacetNvertex_simplicial */
-
-
-/*---------------------------------
-
-  qh_printfacetheader( fp, facet )
-    prints header fields of a facet to fp
-
-  notes:
-    for 'f' output and debugging
-    Same as QhullFacet::printHeader()
-*/
-void qh_printfacetheader(FILE *fp, facetT *facet) {
-  pointT *point, **pointp, *furthest;
-  facetT *neighbor, **neighborp;
-  realT dist;
-
-  if (facet == qh_MERGEridge) {
-    qh_fprintf(fp, 9133, " MERGEridge\n");
-    return;
-  }else if (facet == qh_DUPLICATEridge) {
-    qh_fprintf(fp, 9134, " DUPLICATEridge\n");
-    return;
-  }else if (!facet) {
-    qh_fprintf(fp, 9135, " NULLfacet\n");
-    return;
-  }
-  qh old_randomdist= qh RANDOMdist;
-  qh RANDOMdist= False;
-  qh_fprintf(fp, 9136, "- f%d\n", facet->id);
-  qh_fprintf(fp, 9137, "    - flags:");
-  if (facet->toporient)
-    qh_fprintf(fp, 9138, " top");
-  else
-    qh_fprintf(fp, 9139, " bottom");
-  if (facet->simplicial)
-    qh_fprintf(fp, 9140, " simplicial");
-  if (facet->tricoplanar)
-    qh_fprintf(fp, 9141, " tricoplanar");
-  if (facet->upperdelaunay)
-    qh_fprintf(fp, 9142, " upperDelaunay");
-  if (facet->visible)
-    qh_fprintf(fp, 9143, " visible");
-  if (facet->newfacet)
-    qh_fprintf(fp, 9144, " new");
-  if (facet->tested)
-    qh_fprintf(fp, 9145, " tested");
-  if (!facet->good)
-    qh_fprintf(fp, 9146, " notG");
-  if (facet->seen)
-    qh_fprintf(fp, 9147, " seen");
-  if (facet->coplanar)
-    qh_fprintf(fp, 9148, " coplanar");
-  if (facet->mergehorizon)
-    qh_fprintf(fp, 9149, " mergehorizon");
-  if (facet->keepcentrum)
-    qh_fprintf(fp, 9150, " keepcentrum");
-  if (facet->dupridge)
-    qh_fprintf(fp, 9151, " dupridge");
-  if (facet->mergeridge && !facet->mergeridge2)
-    qh_fprintf(fp, 9152, " mergeridge1");
-  if (facet->mergeridge2)
-    qh_fprintf(fp, 9153, " mergeridge2");
-  if (facet->newmerge)
-    qh_fprintf(fp, 9154, " newmerge");
-  if (facet->flipped)
-    qh_fprintf(fp, 9155, " flipped");
-  if (facet->notfurthest)
-    qh_fprintf(fp, 9156, " notfurthest");
-  if (facet->degenerate)
-    qh_fprintf(fp, 9157, " degenerate");
-  if (facet->redundant)
-    qh_fprintf(fp, 9158, " redundant");
-  qh_fprintf(fp, 9159, "\n");
-  if (facet->isarea)
-    qh_fprintf(fp, 9160, "    - area: %2.2g\n", facet->f.area);
-  else if (qh NEWfacets && facet->visible && facet->f.replace)
-    qh_fprintf(fp, 9161, "    - replacement: f%d\n", facet->f.replace->id);
-  else if (facet->newfacet) {
-    if (facet->f.samecycle && facet->f.samecycle != facet)
-      qh_fprintf(fp, 9162, "    - shares same visible/horizon as f%d\n", facet->f.samecycle->id);
-  }else if (facet->tricoplanar /* !isarea */) {
-    if (facet->f.triowner)
-      qh_fprintf(fp, 9163, "    - owner of normal & centrum is facet f%d\n", facet->f.triowner->id);
-  }else if (facet->f.newcycle)
-    qh_fprintf(fp, 9164, "    - was horizon to f%d\n", facet->f.newcycle->id);
-  if (facet->nummerge)
-    qh_fprintf(fp, 9165, "    - merges: %d\n", facet->nummerge);
-  qh_printpointid(fp, "    - normal: ", qh hull_dim, facet->normal, qh_IDunknown);
-  qh_fprintf(fp, 9166, "    - offset: %10.7g\n", facet->offset);
-  if (qh CENTERtype == qh_ASvoronoi || facet->center)
-    qh_printcenter(fp, qh_PRINTfacets, "    - center: ", facet);
-#if qh_MAXoutside
-  if (facet->maxoutside > qh DISTround)
-    qh_fprintf(fp, 9167, "    - maxoutside: %10.7g\n", facet->maxoutside);
-#endif
-  if (!SETempty_(facet->outsideset)) {
-    furthest= (pointT*)qh_setlast(facet->outsideset);
-    if (qh_setsize(facet->outsideset) < 6) {
-      qh_fprintf(fp, 9168, "    - outside set(furthest p%d):\n", qh_pointid(furthest));
-      FOREACHpoint_(facet->outsideset)
-        qh_printpoint(fp, "     ", point);
-    }else if (qh_setsize(facet->outsideset) < 21) {
-      qh_printpoints(fp, "    - outside set:", facet->outsideset);
-    }else {
-      qh_fprintf(fp, 9169, "    - outside set:  %d points.", qh_setsize(facet->outsideset));
-      qh_printpoint(fp, "  Furthest", furthest);
-    }
-#if !qh_COMPUTEfurthest
-    qh_fprintf(fp, 9170, "    - furthest distance= %2.2g\n", facet->furthestdist);
-#endif
-  }
-  if (!SETempty_(facet->coplanarset)) {
-    furthest= (pointT*)qh_setlast(facet->coplanarset);
-    if (qh_setsize(facet->coplanarset) < 6) {
-      qh_fprintf(fp, 9171, "    - coplanar set(furthest p%d):\n", qh_pointid(furthest));
-      FOREACHpoint_(facet->coplanarset)
-        qh_printpoint(fp, "     ", point);
-    }else if (qh_setsize(facet->coplanarset) < 21) {
-      qh_printpoints(fp, "    - coplanar set:", facet->coplanarset);
-    }else {
-      qh_fprintf(fp, 9172, "    - coplanar set:  %d points.", qh_setsize(facet->coplanarset));
-      qh_printpoint(fp, "  Furthest", furthest);
-    }
-    zinc_(Zdistio);
-    qh_distplane(furthest, facet, &dist);
-    qh_fprintf(fp, 9173, "      furthest distance= %2.2g\n", dist);
-  }
-  qh_printvertices(fp, "    - vertices:", facet->vertices);
-  qh_fprintf(fp, 9174, "    - neighboring facets:");
-  FOREACHneighbor_(facet) {
-    if (neighbor == qh_MERGEridge)
-      qh_fprintf(fp, 9175, " MERGE");
-    else if (neighbor == qh_DUPLICATEridge)
-      qh_fprintf(fp, 9176, " DUP");
-    else
-      qh_fprintf(fp, 9177, " f%d", neighbor->id);
-  }
-  qh_fprintf(fp, 9178, "\n");
-  qh RANDOMdist= qh old_randomdist;
-} /* printfacetheader */
-
-
-/*---------------------------------
-
-  qh_printfacetridges( fp, facet )
-    prints ridges of a facet to fp
-
-  notes:
-    ridges printed in neighbor order
-    assumes the ridges exist
-    for 'f' output
-    same as QhullFacet::printRidges
-*/
-void qh_printfacetridges(FILE *fp, facetT *facet) {
-  facetT *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-  int numridges= 0;
-
-
-  if (facet->visible && qh NEWfacets) {
-    qh_fprintf(fp, 9179, "    - ridges(ids may be garbage):");
-    FOREACHridge_(facet->ridges)
-      qh_fprintf(fp, 9180, " r%d", ridge->id);
-    qh_fprintf(fp, 9181, "\n");
-  }else {
-    qh_fprintf(fp, 9182, "    - ridges:\n");
-    FOREACHridge_(facet->ridges)
-      ridge->seen= False;
-    if (qh hull_dim == 3) {
-      ridge= SETfirstt_(facet->ridges, ridgeT);
-      while (ridge && !ridge->seen) {
-        ridge->seen= True;
-        qh_printridge(fp, ridge);
-        numridges++;
-        ridge= qh_nextridge3d(ridge, facet, NULL);
-        }
-    }else {
-      FOREACHneighbor_(facet) {
-        FOREACHridge_(facet->ridges) {
-          if (otherfacet_(ridge,facet) == neighbor) {
-            ridge->seen= True;
-            qh_printridge(fp, ridge);
-            numridges++;
-          }
-        }
-      }
-    }
-    if (numridges != qh_setsize(facet->ridges)) {
-      qh_fprintf(fp, 9183, "     - all ridges:");
-      FOREACHridge_(facet->ridges)
-        qh_fprintf(fp, 9184, " r%d", ridge->id);
-        qh_fprintf(fp, 9185, "\n");
-    }
-    FOREACHridge_(facet->ridges) {
-      if (!ridge->seen)
-        qh_printridge(fp, ridge);
-    }
-  }
-} /* printfacetridges */
-
-/*---------------------------------
-
-  qh_printfacets( fp, format, facetlist, facets, printall )
-    prints facetlist and/or facet set in output format
-
-  notes:
-    also used for specialized formats ('FO' and summary)
-    turns off 'Rn' option since want actual numbers
-*/
-void qh_printfacets(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
-  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
-  facetT *facet, **facetp;
-  setT *vertices;
-  coordT *center;
-  realT outerplane, innerplane;
-
-  qh old_randomdist= qh RANDOMdist;
-  qh RANDOMdist= False;
-  if (qh CDDoutput && (format == qh_PRINTcentrums || format == qh_PRINTpointintersect || format == qh_PRINToff))
-    qh_fprintf(qh ferr, 7056, "qhull warning: CDD format is not available for centrums, halfspace\nintersections, and OFF file format.\n");
-  if (format == qh_PRINTnone)
-    ; /* print nothing */
-  else if (format == qh_PRINTaverage) {
-    vertices= qh_facetvertices(facetlist, facets, printall);
-    center= qh_getcenter(vertices);
-    qh_fprintf(fp, 9186, "%d 1\n", qh hull_dim);
-    qh_printpointid(fp, NULL, qh hull_dim, center, qh_IDunknown);
-    qh_memfree(center, qh normal_size);
-    qh_settempfree(&vertices);
-  }else if (format == qh_PRINTextremes) {
-    if (qh DELAUNAY)
-      qh_printextremes_d(fp, facetlist, facets, printall);
-    else if (qh hull_dim == 2)
-      qh_printextremes_2d(fp, facetlist, facets, printall);
-    else
-      qh_printextremes(fp, facetlist, facets, printall);
-  }else if (format == qh_PRINToptions)
-    qh_fprintf(fp, 9187, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
-  else if (format == qh_PRINTpoints && !qh VORONOI)
-    qh_printpoints_out(fp, facetlist, facets, printall);
-  else if (format == qh_PRINTqhull)
-    qh_fprintf(fp, 9188, "%s | %s\n", qh rbox_command, qh qhull_command);
-  else if (format == qh_PRINTsize) {
-    qh_fprintf(fp, 9189, "0\n2 ");
-    qh_fprintf(fp, 9190, qh_REAL_1, qh totarea);
-    qh_fprintf(fp, 9191, qh_REAL_1, qh totvol);
-    qh_fprintf(fp, 9192, "\n");
-  }else if (format == qh_PRINTsummary) {
-    qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
-      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
-    vertices= qh_facetvertices(facetlist, facets, printall);
-    qh_fprintf(fp, 9193, "10 %d %d %d %d %d %d %d %d %d %d\n2 ", qh hull_dim,
-                qh num_points + qh_setsize(qh other_points),
-                qh num_vertices, qh num_facets - qh num_visible,
-                qh_setsize(vertices), numfacets, numcoplanars,
-                numfacets - numsimplicial, zzval_(Zdelvertextot),
-                numtricoplanars);
-    qh_settempfree(&vertices);
-    qh_outerinner(NULL, &outerplane, &innerplane);
-    qh_fprintf(fp, 9194, qh_REAL_2n, outerplane, innerplane);
-  }else if (format == qh_PRINTvneighbors)
-    qh_printvneighbors(fp, facetlist, facets, printall);
-  else if (qh VORONOI && format == qh_PRINToff)
-    qh_printvoronoi(fp, format, facetlist, facets, printall);
-  else if (qh VORONOI && format == qh_PRINTgeom) {
-    qh_printbegin(fp, format, facetlist, facets, printall);
-    qh_printvoronoi(fp, format, facetlist, facets, printall);
-    qh_printend(fp, format, facetlist, facets, printall);
-  }else if (qh VORONOI
-  && (format == qh_PRINTvertices || format == qh_PRINTinner || format == qh_PRINTouter))
-    qh_printvdiagram(fp, format, facetlist, facets, printall);
-  else {
-    qh_printbegin(fp, format, facetlist, facets, printall);
-    FORALLfacet_(facetlist)
-      qh_printafacet(fp, format, facet, printall);
-    FOREACHfacet_(facets)
-      qh_printafacet(fp, format, facet, printall);
-    qh_printend(fp, format, facetlist, facets, printall);
-  }
-  qh RANDOMdist= qh old_randomdist;
-} /* printfacets */
-
-
-/*---------------------------------
-
-  qh_printhyperplaneintersection( fp, facet1, facet2, vertices, color )
-    print Geomview OFF or 4OFF for the intersection of two hyperplanes in 3-d or 4-d
-*/
-void qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
-                   setT *vertices, realT color[3]) {
-  realT costheta, denominator, dist1, dist2, s, t, mindenom, p[4];
-  vertexT *vertex, **vertexp;
-  int i, k;
-  boolT nearzero1, nearzero2;
-
-  costheta= qh_getangle(facet1->normal, facet2->normal);
-  denominator= 1 - costheta * costheta;
-  i= qh_setsize(vertices);
-  if (qh hull_dim == 3)
-    qh_fprintf(fp, 9195, "VECT 1 %d 1 %d 1 ", i, i);
-  else if (qh hull_dim == 4 && qh DROPdim >= 0)
-    qh_fprintf(fp, 9196, "OFF 3 1 1 ");
-  else
-    qh printoutvar++;
-  qh_fprintf(fp, 9197, "# intersect f%d f%d\n", facet1->id, facet2->id);
-  mindenom= 1 / (10.0 * qh MAXabs_coord);
-  FOREACHvertex_(vertices) {
-    zadd_(Zdistio, 2);
-    qh_distplane(vertex->point, facet1, &dist1);
-    qh_distplane(vertex->point, facet2, &dist2);
-    s= qh_divzero(-dist1 + costheta * dist2, denominator,mindenom,&nearzero1);
-    t= qh_divzero(-dist2 + costheta * dist1, denominator,mindenom,&nearzero2);
-    if (nearzero1 || nearzero2)
-      s= t= 0.0;
-    for (k=qh hull_dim; k--; )
-      p[k]= vertex->point[k] + facet1->normal[k] * s + facet2->normal[k] * t;
-    if (qh PRINTdim <= 3) {
-      qh_projectdim3(p, p);
-      qh_fprintf(fp, 9198, "%8.4g %8.4g %8.4g # ", p[0], p[1], p[2]);
-    }else
-      qh_fprintf(fp, 9199, "%8.4g %8.4g %8.4g %8.4g # ", p[0], p[1], p[2], p[3]);
-    if (nearzero1+nearzero2)
-      qh_fprintf(fp, 9200, "p%d(coplanar facets)\n", qh_pointid(vertex->point));
-    else
-      qh_fprintf(fp, 9201, "projected p%d\n", qh_pointid(vertex->point));
-  }
-  if (qh hull_dim == 3)
-    qh_fprintf(fp, 9202, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
-  else if (qh hull_dim == 4 && qh DROPdim >= 0)
-    qh_fprintf(fp, 9203, "3 0 1 2 %8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
-} /* printhyperplaneintersection */
-
-/*---------------------------------
-
-  qh_printline3geom( fp, pointA, pointB, color )
-    prints a line as a VECT
-    prints 0's for qh.DROPdim
-
-  notes:
-    if pointA == pointB,
-      it's a 1 point VECT
-*/
-void qh_printline3geom(FILE *fp, pointT *pointA, pointT *pointB, realT color[3]) {
-  int k;
-  realT pA[4], pB[4];
-
-  qh_projectdim3(pointA, pA);
-  qh_projectdim3(pointB, pB);
-  if ((fabs(pA[0] - pB[0]) > 1e-3) ||
-      (fabs(pA[1] - pB[1]) > 1e-3) ||
-      (fabs(pA[2] - pB[2]) > 1e-3)) {
-    qh_fprintf(fp, 9204, "VECT 1 2 1 2 1\n");
-    for (k=0; k < 3; k++)
-       qh_fprintf(fp, 9205, "%8.4g ", pB[k]);
-    qh_fprintf(fp, 9206, " # p%d\n", qh_pointid(pointB));
-  }else
-    qh_fprintf(fp, 9207, "VECT 1 1 1 1 1\n");
-  for (k=0; k < 3; k++)
-    qh_fprintf(fp, 9208, "%8.4g ", pA[k]);
-  qh_fprintf(fp, 9209, " # p%d\n", qh_pointid(pointA));
-  qh_fprintf(fp, 9210, "%8.4g %8.4g %8.4g 1\n", color[0], color[1], color[2]);
-}
-
-/*---------------------------------
-
-  qh_printneighborhood( fp, format, facetA, facetB, printall )
-    print neighborhood of one or two facets
-
-  notes:
-    calls qh_findgood_all()
-    bumps qh.visit_id
-*/
-void qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall) {
-  facetT *neighbor, **neighborp, *facet;
-  setT *facets;
-
-  if (format == qh_PRINTnone)
-    return;
-  qh_findgood_all(qh facet_list);
-  if (facetA == facetB)
-    facetB= NULL;
-  facets= qh_settemp(2*(qh_setsize(facetA->neighbors)+1));
-  qh visit_id++;
-  for (facet= facetA; facet; facet= ((facet == facetA) ? facetB : NULL)) {
-    if (facet->visitid != qh visit_id) {
-      facet->visitid= qh visit_id;
-      qh_setappend(&facets, facet);
-    }
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid == qh visit_id)
-        continue;
-      neighbor->visitid= qh visit_id;
-      if (printall || !qh_skipfacet(neighbor))
-        qh_setappend(&facets, neighbor);
-    }
-  }
-  qh_printfacets(fp, format, NULL, facets, printall);
-  qh_settempfree(&facets);
-} /* printneighborhood */
-
-/*---------------------------------
-
-  qh_printpoint( fp, string, point )
-  qh_printpointid( fp, string, dim, point, id )
-    prints the coordinates of a point
-
-  returns:
-    if string is defined
-      prints 'string p%d'.  Skips p%d if id=qh_IDunknown(-1) or qh_IDnone(-3)
-
-  notes:
-    nop if point is NULL
-    Same as QhullPoint's printPoint
-*/
-void qh_printpoint(FILE *fp, const char *string, pointT *point) {
-  int id= qh_pointid( point);
-
-  qh_printpointid( fp, string, qh hull_dim, point, id);
-} /* printpoint */
-
-void qh_printpointid(FILE *fp, const char *string, int dim, pointT *point, int id) {
-  int k;
-  realT r; /*bug fix*/
-
-  if (!point)
-    return;
-  if (string) {
-    qh_fprintf(fp, 9211, "%s", string);
-    if (id != qh_IDunknown && id != qh_IDnone)
-      qh_fprintf(fp, 9212, " p%d: ", id);
-  }
-  for (k=dim; k--; ) {
-    r= *point++;
-    if (string)
-      qh_fprintf(fp, 9213, " %8.4g", r);
-    else
-      qh_fprintf(fp, 9214, qh_REAL_1, r);
-  }
-  qh_fprintf(fp, 9215, "\n");
-} /* printpointid */
-
-/*---------------------------------
-
-  qh_printpoint3( fp, point )
-    prints 2-d, 3-d, or 4-d point as Geomview 3-d coordinates
-*/
-void qh_printpoint3(FILE *fp, pointT *point) {
-  int k;
-  realT p[4];
-
-  qh_projectdim3(point, p);
-  for (k=0; k < 3; k++)
-    qh_fprintf(fp, 9216, "%8.4g ", p[k]);
-  qh_fprintf(fp, 9217, " # p%d\n", qh_pointid(point));
-} /* printpoint3 */
-
-/*----------------------------------------
--printpoints- print pointids for a set of points starting at index
-   see geom.c
-*/
-
-/*---------------------------------
-
-  qh_printpoints_out( fp, facetlist, facets, printall )
-    prints vertices, coplanar/inside points, for facets by their point coordinates
-    allows qh.CDDoutput
-
-  notes:
-    same format as qhull input
-    if no coplanar/interior points,
-      same order as qh_printextremes
-*/
-void qh_printpoints_out(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
-  int allpoints= qh num_points + qh_setsize(qh other_points);
-  int numpoints=0, point_i, point_n;
-  setT *vertices, *points;
-  facetT *facet, **facetp;
-  pointT *point, **pointp;
-  vertexT *vertex, **vertexp;
-  int id;
-
-  points= qh_settemp(allpoints);
-  qh_setzero(points, 0, allpoints);
-  vertices= qh_facetvertices(facetlist, facets, printall);
-  FOREACHvertex_(vertices) {
-    id= qh_pointid(vertex->point);
-    if (id >= 0)
-      SETelem_(points, id)= vertex->point;
-  }
-  if (qh KEEPinside || qh KEEPcoplanar || qh KEEPnearinside) {
-    FORALLfacet_(facetlist) {
-      if (!printall && qh_skipfacet(facet))
-        continue;
-      FOREACHpoint_(facet->coplanarset) {
-        id= qh_pointid(point);
-        if (id >= 0)
-          SETelem_(points, id)= point;
-      }
-    }
-    FOREACHfacet_(facets) {
-      if (!printall && qh_skipfacet(facet))
-        continue;
-      FOREACHpoint_(facet->coplanarset) {
-        id= qh_pointid(point);
-        if (id >= 0)
-          SETelem_(points, id)= point;
-      }
-    }
-  }
-  qh_settempfree(&vertices);
-  FOREACHpoint_i_(points) {
-    if (point)
-      numpoints++;
-  }
-  if (qh CDDoutput)
-    qh_fprintf(fp, 9218, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
-             qh qhull_command, numpoints, qh hull_dim + 1);
-  else
-    qh_fprintf(fp, 9219, "%d\n%d\n", qh hull_dim, numpoints);
-  FOREACHpoint_i_(points) {
-    if (point) {
-      if (qh CDDoutput)
-        qh_fprintf(fp, 9220, "1 ");
-      qh_printpoint(fp, NULL, point);
-    }
-  }
-  if (qh CDDoutput)
-    qh_fprintf(fp, 9221, "end\n");
-  qh_settempfree(&points);
-} /* printpoints_out */
-
-
-/*---------------------------------
-
-  qh_printpointvect( fp, point, normal, center, radius, color )
-    prints a 2-d, 3-d, or 4-d point as 3-d VECT's relative to normal or to center point
-*/
-void qh_printpointvect(FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]) {
-  realT diff[4], pointA[4];
-  int k;
-
-  for (k=qh hull_dim; k--; ) {
-    if (center)
-      diff[k]= point[k]-center[k];
-    else if (normal)
-      diff[k]= normal[k];
-    else
-      diff[k]= 0;
-  }
-  if (center)
-    qh_normalize2(diff, qh hull_dim, True, NULL, NULL);
-  for (k=qh hull_dim; k--; )
-    pointA[k]= point[k]+diff[k] * radius;
-  qh_printline3geom(fp, point, pointA, color);
-} /* printpointvect */
-
-/*---------------------------------
-
-  qh_printpointvect2( fp, point, normal, center, radius )
-    prints a 2-d, 3-d, or 4-d point as 2 3-d VECT's for an imprecise point
-*/
-void qh_printpointvect2(FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius) {
-  realT red[3]={1, 0, 0}, yellow[3]={1, 1, 0};
-
-  qh_printpointvect(fp, point, normal, center, radius, red);
-  qh_printpointvect(fp, point, normal, center, -radius, yellow);
-} /* printpointvect2 */
-
-/*---------------------------------
-
-  qh_printridge( fp, ridge )
-    prints the information in a ridge
-
-  notes:
-    for qh_printfacetridges()
-    same as operator<< [QhullRidge.cpp]
-*/
-void qh_printridge(FILE *fp, ridgeT *ridge) {
-
-  qh_fprintf(fp, 9222, "     - r%d", ridge->id);
-  if (ridge->tested)
-    qh_fprintf(fp, 9223, " tested");
-  if (ridge->nonconvex)
-    qh_fprintf(fp, 9224, " nonconvex");
-  qh_fprintf(fp, 9225, "\n");
-  qh_printvertices(fp, "           vertices:", ridge->vertices);
-  if (ridge->top && ridge->bottom)
-    qh_fprintf(fp, 9226, "           between f%d and f%d\n",
-            ridge->top->id, ridge->bottom->id);
-} /* printridge */
-
-/*---------------------------------
-
-  qh_printspheres( fp, vertices, radius )
-    prints 3-d vertices as OFF spheres
-
-  notes:
-    inflated octahedron from Stuart Levy earth/mksphere2
-*/
-void qh_printspheres(FILE *fp, setT *vertices, realT radius) {
-  vertexT *vertex, **vertexp;
-
-  qh printoutnum++;
-  qh_fprintf(fp, 9227, "{appearance {-edge -normal normscale 0} {\n\
-INST geom {define vsphere OFF\n\
-18 32 48\n\
-\n\
-0 0 1\n\
-1 0 0\n\
-0 1 0\n\
--1 0 0\n\
-0 -1 0\n\
-0 0 -1\n\
-0.707107 0 0.707107\n\
-0 -0.707107 0.707107\n\
-0.707107 -0.707107 0\n\
--0.707107 0 0.707107\n\
--0.707107 -0.707107 0\n\
-0 0.707107 0.707107\n\
--0.707107 0.707107 0\n\
-0.707107 0.707107 0\n\
-0.707107 0 -0.707107\n\
-0 0.707107 -0.707107\n\
--0.707107 0 -0.707107\n\
-0 -0.707107 -0.707107\n\
-\n\
-3 0 6 11\n\
-3 0 7 6 \n\
-3 0 9 7 \n\
-3 0 11 9\n\
-3 1 6 8 \n\
-3 1 8 14\n\
-3 1 13 6\n\
-3 1 14 13\n\
-3 2 11 13\n\
-3 2 12 11\n\
-3 2 13 15\n\
-3 2 15 12\n\
-3 3 9 12\n\
-3 3 10 9\n\
-3 3 12 16\n\
-3 3 16 10\n\
-3 4 7 10\n\
-3 4 8 7\n\
-3 4 10 17\n\
-3 4 17 8\n\
-3 5 14 17\n\
-3 5 15 14\n\
-3 5 16 15\n\
-3 5 17 16\n\
-3 6 13 11\n\
-3 7 8 6\n\
-3 9 10 7\n\
-3 11 12 9\n\
-3 14 8 17\n\
-3 15 13 14\n\
-3 16 12 15\n\
-3 17 10 16\n} transforms { TLIST\n");
-  FOREACHvertex_(vertices) {
-    qh_fprintf(fp, 9228, "%8.4g 0 0 0 # v%d\n 0 %8.4g 0 0\n0 0 %8.4g 0\n",
-      radius, vertex->id, radius, radius);
-    qh_printpoint3(fp, vertex->point);
-    qh_fprintf(fp, 9229, "1\n");
-  }
-  qh_fprintf(fp, 9230, "}}}\n");
-} /* printspheres */
-
-
-/*----------------------------------------------
--printsummary-
-                see libqhull.c
-*/
-
-/*---------------------------------
-
-  qh_printvdiagram( fp, format, facetlist, facets, printall )
-    print voronoi diagram
-      # of pairs of input sites
-      #indices site1 site2 vertex1 ...
-
-    sites indexed by input point id
-      point 0 is the first input point
-    vertices indexed by 'o' and 'p' order
-      vertex 0 is the 'vertex-at-infinity'
-      vertex 1 is the first Voronoi vertex
-
-  see:
-    qh_printvoronoi()
-    qh_eachvoronoi_all()
-
-  notes:
-    if all facets are upperdelaunay,
-      prints upper hull (furthest-site Voronoi diagram)
-*/
-void qh_printvdiagram(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
-  setT *vertices;
-  int totcount, numcenters;
-  boolT isLower;
-  qh_RIDGE innerouter= qh_RIDGEall;
-  printvridgeT printvridge= NULL;
-
-  if (format == qh_PRINTvertices) {
-    innerouter= qh_RIDGEall;
-    printvridge= qh_printvridge;
-  }else if (format == qh_PRINTinner) {
-    innerouter= qh_RIDGEinner;
-    printvridge= qh_printvnorm;
-  }else if (format == qh_PRINTouter) {
-    innerouter= qh_RIDGEouter;
-    printvridge= qh_printvnorm;
-  }else {
-    qh_fprintf(qh ferr, 6219, "Qhull internal error (qh_printvdiagram): unknown print format %d.\n", format);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  vertices= qh_markvoronoi(facetlist, facets, printall, &isLower, &numcenters);
-  totcount= qh_printvdiagram2(NULL, NULL, vertices, innerouter, False);
-  qh_fprintf(fp, 9231, "%d\n", totcount);
-  totcount= qh_printvdiagram2(fp, printvridge, vertices, innerouter, True /* inorder*/);
-  qh_settempfree(&vertices);
-#if 0  /* for testing qh_eachvoronoi_all */
-  qh_fprintf(fp, 9232, "\n");
-  totcount= qh_eachvoronoi_all(fp, printvridge, qh UPPERdelaunay, innerouter, True /* inorder*/);
-  qh_fprintf(fp, 9233, "%d\n", totcount);
-#endif
-} /* printvdiagram */
-
-/*---------------------------------
-
-  qh_printvdiagram2( fp, printvridge, vertices, innerouter, inorder )
-    visit all pairs of input sites (vertices) for selected Voronoi vertices
-    vertices may include NULLs
-
-  innerouter:
-    qh_RIDGEall   print inner ridges(bounded) and outer ridges(unbounded)
-    qh_RIDGEinner print only inner ridges
-    qh_RIDGEouter print only outer ridges
-
-  inorder:
-    print 3-d Voronoi vertices in order
-
-  assumes:
-    qh_markvoronoi marked facet->visitid for Voronoi vertices
-    all facet->seen= False
-    all facet->seen2= True
-
-  returns:
-    total number of Voronoi ridges
-    if printvridge,
-      calls printvridge( fp, vertex, vertexA, centers) for each ridge
-      [see qh_eachvoronoi()]
-
-  see:
-    qh_eachvoronoi_all()
-*/
-int qh_printvdiagram2(FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder) {
-  int totcount= 0;
-  int vertex_i, vertex_n;
-  vertexT *vertex;
-
-  FORALLvertices
-    vertex->seen= False;
-  FOREACHvertex_i_(vertices) {
-    if (vertex) {
-      if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
-        continue;
-      totcount += qh_eachvoronoi(fp, printvridge, vertex, !qh_ALL, innerouter, inorder);
-    }
-  }
-  return totcount;
-} /* printvdiagram2 */
-
-/*---------------------------------
-
-  qh_printvertex( fp, vertex )
-    prints the information in a vertex
-    Duplicated as operator<< [QhullVertex.cpp]
-*/
-void qh_printvertex(FILE *fp, vertexT *vertex) {
-  pointT *point;
-  int k, count= 0;
-  facetT *neighbor, **neighborp;
-  realT r; /*bug fix*/
-
-  if (!vertex) {
-    qh_fprintf(fp, 9234, "  NULLvertex\n");
-    return;
-  }
-  qh_fprintf(fp, 9235, "- p%d(v%d):", qh_pointid(vertex->point), vertex->id);
-  point= vertex->point;
-  if (point) {
-    for (k=qh hull_dim; k--; ) {
-      r= *point++;
-      qh_fprintf(fp, 9236, " %5.2g", r);
-    }
-  }
-  if (vertex->deleted)
-    qh_fprintf(fp, 9237, " deleted");
-  if (vertex->delridge)
-    qh_fprintf(fp, 9238, " ridgedeleted");
-  qh_fprintf(fp, 9239, "\n");
-  if (vertex->neighbors) {
-    qh_fprintf(fp, 9240, "  neighbors:");
-    FOREACHneighbor_(vertex) {
-      if (++count % 100 == 0)
-        qh_fprintf(fp, 9241, "\n     ");
-      qh_fprintf(fp, 9242, " f%d", neighbor->id);
-    }
-    qh_fprintf(fp, 9243, "\n");
-  }
-} /* printvertex */
-
-
-/*---------------------------------
-
-  qh_printvertexlist( fp, string, facetlist, facets, printall )
-    prints vertices used by a facetlist or facet set
-    tests qh_skipfacet() if !printall
-*/
-void qh_printvertexlist(FILE *fp, const char* string, facetT *facetlist,
-                         setT *facets, boolT printall) {
-  vertexT *vertex, **vertexp;
-  setT *vertices;
-
-  vertices= qh_facetvertices(facetlist, facets, printall);
-  qh_fprintf(fp, 9244, "%s", string);
-  FOREACHvertex_(vertices)
-    qh_printvertex(fp, vertex);
-  qh_settempfree(&vertices);
-} /* printvertexlist */
-
-
-/*---------------------------------
-
-  qh_printvertices( fp, string, vertices )
-    prints vertices in a set
-    duplicated as printVertexSet [QhullVertex.cpp]
-*/
-void qh_printvertices(FILE *fp, const char* string, setT *vertices) {
-  vertexT *vertex, **vertexp;
-
-  qh_fprintf(fp, 9245, "%s", string);
-  FOREACHvertex_(vertices)
-    qh_fprintf(fp, 9246, " p%d(v%d)", qh_pointid(vertex->point), vertex->id);
-  qh_fprintf(fp, 9247, "\n");
-} /* printvertices */
-
-/*---------------------------------
-
-  qh_printvneighbors( fp, facetlist, facets, printall )
-    print vertex neighbors of vertices in facetlist and facets ('FN')
-
-  notes:
-    qh_countfacets clears facet->visitid for non-printed facets
-
-  design:
-    collect facet count and related statistics
-    if necessary, build neighbor sets for each vertex
-    collect vertices in facetlist and facets
-    build a point array for point->vertex and point->coplanar facet
-    for each point
-      list vertex neighbors or coplanar facet
-*/
-void qh_printvneighbors(FILE *fp, facetT* facetlist, setT *facets, boolT printall) {
-  int numfacets, numsimplicial, numridges, totneighbors, numneighbors, numcoplanars, numtricoplanars;
-  setT *vertices, *vertex_points, *coplanar_points;
-  int numpoints= qh num_points + qh_setsize(qh other_points);
-  vertexT *vertex, **vertexp;
-  int vertex_i, vertex_n;
-  facetT *facet, **facetp, *neighbor, **neighborp;
-  pointT *point, **pointp;
-
-  qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
-      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);  /* sets facet->visitid */
-  qh_fprintf(fp, 9248, "%d\n", numpoints);
-  qh_vertexneighbors();
-  vertices= qh_facetvertices(facetlist, facets, printall);
-  vertex_points= qh_settemp(numpoints);
-  coplanar_points= qh_settemp(numpoints);
-  qh_setzero(vertex_points, 0, numpoints);
-  qh_setzero(coplanar_points, 0, numpoints);
-  FOREACHvertex_(vertices)
-    qh_point_add(vertex_points, vertex->point, vertex);
-  FORALLfacet_(facetlist) {
-    FOREACHpoint_(facet->coplanarset)
-      qh_point_add(coplanar_points, point, facet);
-  }
-  FOREACHfacet_(facets) {
-    FOREACHpoint_(facet->coplanarset)
-      qh_point_add(coplanar_points, point, facet);
-  }
-  FOREACHvertex_i_(vertex_points) {
-    if (vertex) {
-      numneighbors= qh_setsize(vertex->neighbors);
-      qh_fprintf(fp, 9249, "%d", numneighbors);
-      if (qh hull_dim == 3)
-        qh_order_vertexneighbors(vertex);
-      else if (qh hull_dim >= 4)
-        qsort(SETaddr_(vertex->neighbors, facetT), (size_t)numneighbors,
-             sizeof(facetT *), qh_compare_facetvisit);
-      FOREACHneighbor_(vertex)
-        qh_fprintf(fp, 9250, " %d",
-                 neighbor->visitid ? neighbor->visitid - 1 : 0 - neighbor->id);
-      qh_fprintf(fp, 9251, "\n");
-    }else if ((facet= SETelemt_(coplanar_points, vertex_i, facetT)))
-      qh_fprintf(fp, 9252, "1 %d\n",
-                  facet->visitid ? facet->visitid - 1 : 0 - facet->id);
-    else
-      qh_fprintf(fp, 9253, "0\n");
-  }
-  qh_settempfree(&coplanar_points);
-  qh_settempfree(&vertex_points);
-  qh_settempfree(&vertices);
-} /* printvneighbors */
-
-/*---------------------------------
-
-  qh_printvoronoi( fp, format, facetlist, facets, printall )
-    print voronoi diagram in 'o' or 'G' format
-    for 'o' format
-      prints voronoi centers for each facet and for infinity
-      for each vertex, lists ids of printed facets or infinity
-      assumes facetlist and facets are disjoint
-    for 'G' format
-      prints an OFF object
-      adds a 0 coordinate to center
-      prints infinity but does not list in vertices
-
-  see:
-    qh_printvdiagram()
-
-  notes:
-    if 'o',
-      prints a line for each point except "at-infinity"
-    if all facets are upperdelaunay,
-      reverses lower and upper hull
-*/
-void qh_printvoronoi(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
-  int k, numcenters, numvertices= 0, numneighbors, numinf, vid=1, vertex_i, vertex_n;
-  facetT *facet, **facetp, *neighbor, **neighborp;
-  setT *vertices;
-  vertexT *vertex;
-  boolT isLower;
-  unsigned int numfacets= (unsigned int) qh num_facets;
-
-  vertices= qh_markvoronoi(facetlist, facets, printall, &isLower, &numcenters);
-  FOREACHvertex_i_(vertices) {
-    if (vertex) {
-      numvertices++;
-      numneighbors = numinf = 0;
-      FOREACHneighbor_(vertex) {
-        if (neighbor->visitid == 0)
-          numinf= 1;
-        else if (neighbor->visitid < numfacets)
-          numneighbors++;
-      }
-      if (numinf && !numneighbors) {
-        SETelem_(vertices, vertex_i)= NULL;
-        numvertices--;
-      }
-    }
-  }
-  if (format == qh_PRINTgeom)
-    qh_fprintf(fp, 9254, "{appearance {+edge -face} OFF %d %d 1 # Voronoi centers and cells\n",
-                numcenters, numvertices);
-  else
-    qh_fprintf(fp, 9255, "%d\n%d %d 1\n", qh hull_dim-1, numcenters, qh_setsize(vertices));
-  if (format == qh_PRINTgeom) {
-    for (k=qh hull_dim-1; k--; )
-      qh_fprintf(fp, 9256, qh_REAL_1, 0.0);
-    qh_fprintf(fp, 9257, " 0 # infinity not used\n");
-  }else {
-    for (k=qh hull_dim-1; k--; )
-      qh_fprintf(fp, 9258, qh_REAL_1, qh_INFINITE);
-    qh_fprintf(fp, 9259, "\n");
-  }
-  FORALLfacet_(facetlist) {
-    if (facet->visitid && facet->visitid < numfacets) {
-      if (format == qh_PRINTgeom)
-        qh_fprintf(fp, 9260, "# %d f%d\n", vid++, facet->id);
-      qh_printcenter(fp, format, NULL, facet);
-    }
-  }
-  FOREACHfacet_(facets) {
-    if (facet->visitid && facet->visitid < numfacets) {
-      if (format == qh_PRINTgeom)
-        qh_fprintf(fp, 9261, "# %d f%d\n", vid++, facet->id);
-      qh_printcenter(fp, format, NULL, facet);
-    }
-  }
-  FOREACHvertex_i_(vertices) {
-    numneighbors= 0;
-    numinf=0;
-    if (vertex) {
-      if (qh hull_dim == 3)
-        qh_order_vertexneighbors(vertex);
-      else if (qh hull_dim >= 4)
-        qsort(SETaddr_(vertex->neighbors, facetT),
-             (size_t)qh_setsize(vertex->neighbors),
-             sizeof(facetT *), qh_compare_facetvisit);
-      FOREACHneighbor_(vertex) {
-        if (neighbor->visitid == 0)
-          numinf= 1;
-        else if (neighbor->visitid < numfacets)
-          numneighbors++;
-      }
-    }
-    if (format == qh_PRINTgeom) {
-      if (vertex) {
-        qh_fprintf(fp, 9262, "%d", numneighbors);
-        FOREACHneighbor_(vertex) {
-          if (neighbor->visitid && neighbor->visitid < numfacets)
-            qh_fprintf(fp, 9263, " %d", neighbor->visitid);
-        }
-        qh_fprintf(fp, 9264, " # p%d(v%d)\n", vertex_i, vertex->id);
-      }else
-        qh_fprintf(fp, 9265, " # p%d is coplanar or isolated\n", vertex_i);
-    }else {
-      if (numinf)
-        numneighbors++;
-      qh_fprintf(fp, 9266, "%d", numneighbors);
-      if (vertex) {
-        FOREACHneighbor_(vertex) {
-          if (neighbor->visitid == 0) {
-            if (numinf) {
-              numinf= 0;
-              qh_fprintf(fp, 9267, " %d", neighbor->visitid);
-            }
-          }else if (neighbor->visitid < numfacets)
-            qh_fprintf(fp, 9268, " %d", neighbor->visitid);
-        }
-      }
-      qh_fprintf(fp, 9269, "\n");
-    }
-  }
-  if (format == qh_PRINTgeom)
-    qh_fprintf(fp, 9270, "}\n");
-  qh_settempfree(&vertices);
-} /* printvoronoi */
-
-/*---------------------------------
-
-  qh_printvnorm( fp, vertex, vertexA, centers, unbounded )
-    print one separating plane of the Voronoi diagram for a pair of input sites
-    unbounded==True if centers includes vertex-at-infinity
-
-  assumes:
-    qh_ASvoronoi and qh_vertexneighbors() already set
-
-  note:
-    parameter unbounded is UNUSED by this callback
-
-  see:
-    qh_printvdiagram()
-    qh_eachvoronoi()
-*/
-void qh_printvnorm(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
-  pointT *normal;
-  realT offset;
-  int k;
-  QHULL_UNUSED(unbounded);
-
-  normal= qh_detvnorm(vertex, vertexA, centers, &offset);
-  qh_fprintf(fp, 9271, "%d %d %d ",
-      2+qh hull_dim, qh_pointid(vertex->point), qh_pointid(vertexA->point));
-  for (k=0; k< qh hull_dim-1; k++)
-    qh_fprintf(fp, 9272, qh_REAL_1, normal[k]);
-  qh_fprintf(fp, 9273, qh_REAL_1, offset);
-  qh_fprintf(fp, 9274, "\n");
-} /* printvnorm */
-
-/*---------------------------------
-
-  qh_printvridge( fp, vertex, vertexA, centers, unbounded )
-    print one ridge of the Voronoi diagram for a pair of input sites
-    unbounded==True if centers includes vertex-at-infinity
-
-  see:
-    qh_printvdiagram()
-
-  notes:
-    the user may use a different function
-    parameter unbounded is UNUSED
-*/
-void qh_printvridge(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
-  facetT *facet, **facetp;
-  QHULL_UNUSED(unbounded);
-
-  qh_fprintf(fp, 9275, "%d %d %d", qh_setsize(centers)+2,
-       qh_pointid(vertex->point), qh_pointid(vertexA->point));
-  FOREACHfacet_(centers)
-    qh_fprintf(fp, 9276, " %d", facet->visitid);
-  qh_fprintf(fp, 9277, "\n");
-} /* printvridge */
-
-/*---------------------------------
-
-  qh_projectdim3( source, destination )
-    project 2-d 3-d or 4-d point to a 3-d point
-    uses qh.DROPdim and qh.hull_dim
-    source and destination may be the same
-
-  notes:
-    allocate 4 elements to destination just in case
-*/
-void qh_projectdim3(pointT *source, pointT *destination) {
-  int i,k;
-
-  for (k=0, i=0; k < qh hull_dim; k++) {
-    if (qh hull_dim == 4) {
-      if (k != qh DROPdim)
-        destination[i++]= source[k];
-    }else if (k == qh DROPdim)
-      destination[i++]= 0;
-    else
-      destination[i++]= source[k];
-  }
-  while (i < 3)
-    destination[i++]= 0.0;
-} /* projectdim3 */
-
-/*---------------------------------
-
-  qh_readfeasible( dim, curline )
-    read feasible point from current line and qh.fin
-
-  returns:
-    number of lines read from qh.fin
-    sets qh.feasible_point with malloc'd coordinates
-
-  notes:
-    checks for qh.HALFspace
-    assumes dim > 1
-
-  see:
-    qh_setfeasible
-*/
-int qh_readfeasible(int dim, const char *curline) {
-  boolT isfirst= True;
-  int linecount= 0, tokcount= 0;
-  const char *s;
-  char *t, firstline[qh_MAXfirst+1];
-  coordT *coords, value;
-
-  if (!qh HALFspace) {
-    qh_fprintf(qh ferr, 6070, "qhull input error: feasible point(dim 1 coords) is only valid for halfspace intersection\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (qh feasible_string)
-    qh_fprintf(qh ferr, 7057, "qhull input warning: feasible point(dim 1 coords) overrides 'Hn,n,n' feasible point for halfspace intersection\n");
-  if (!(qh feasible_point= (coordT*)qh_malloc(dim* sizeof(coordT)))) {
-    qh_fprintf(qh ferr, 6071, "qhull error: insufficient memory for feasible point\n");
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  coords= qh feasible_point;
-  while ((s= (isfirst ?  curline : fgets(firstline, qh_MAXfirst, qh fin)))) {
-    if (isfirst)
-      isfirst= False;
-    else
-      linecount++;
-    while (*s) {
-      while (isspace(*s))
-        s++;
-      value= qh_strtod(s, &t);
-      if (s == t)
-        break;
-      s= t;
-      *(coords++)= value;
-      if (++tokcount == dim) {
-        while (isspace(*s))
-          s++;
-        qh_strtod(s, &t);
-        if (s != t) {
-          qh_fprintf(qh ferr, 6072, "qhull input error: coordinates for feasible point do not finish out the line: %s\n",
-               s);
-          qh_errexit(qh_ERRinput, NULL, NULL);
-        }
-        return linecount;
-      }
-    }
-  }
-  qh_fprintf(qh ferr, 6073, "qhull input error: only %d coordinates.  Could not read %d-d feasible point.\n",
-           tokcount, dim);
-  qh_errexit(qh_ERRinput, NULL, NULL);
-  return 0;
-} /* readfeasible */
-
-/*---------------------------------
-
-  qh_readpoints( numpoints, dimension, ismalloc )
-    read points from qh.fin into qh.first_point, qh.num_points
-    qh.fin is lines of coordinates, one per vertex, first line number of points
-    if 'rbox D4',
-      gives message
-    if qh.ATinfinity,
-      adds point-at-infinity for Delaunay triangulations
-
-  returns:
-    number of points, array of point coordinates, dimension, ismalloc True
-    if qh.DELAUNAY & !qh.PROJECTinput, projects points to paraboloid
-        and clears qh.PROJECTdelaunay
-    if qh.HALFspace, reads optional feasible point, reads halfspaces,
-        converts to dual.
-
-  for feasible point in "cdd format" in 3-d:
-    3 1
-    coordinates
-    comments
-    begin
-    n 4 real/integer
-    ...
-    end
-
-  notes:
-    dimension will change in qh_initqhull_globals if qh.PROJECTinput
-    uses malloc() since qh_mem not initialized
-    FIXUP QH11012: qh_readpoints needs rewriting, too long
-*/
-coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc) {
-  coordT *points, *coords, *infinity= NULL;
-  realT paraboloid, maxboloid= -REALmax, value;
-  realT *coordp= NULL, *offsetp= NULL, *normalp= NULL;
-  char *s= 0, *t, firstline[qh_MAXfirst+1];
-  int diminput=0, numinput=0, dimfeasible= 0, newnum, k, tempi;
-  int firsttext=0, firstshort=0, firstlong=0, firstpoint=0;
-  int tokcount= 0, linecount=0, maxcount, coordcount=0;
-  boolT islong, isfirst= True, wasbegin= False;
-  boolT isdelaunay= qh DELAUNAY && !qh PROJECTinput;
-
-  if (qh CDDinput) {
-    while ((s= fgets(firstline, qh_MAXfirst, qh fin))) {
-      linecount++;
-      if (qh HALFspace && linecount == 1 && isdigit(*s)) {
-        dimfeasible= qh_strtol(s, &s);
-        while (isspace(*s))
-          s++;
-        if (qh_strtol(s, &s) == 1)
-          linecount += qh_readfeasible(dimfeasible, s);
-        else
-          dimfeasible= 0;
-      }else if (!memcmp(firstline, "begin", (size_t)5) || !memcmp(firstline, "BEGIN", (size_t)5))
-        break;
-      else if (!*qh rbox_command)
-        strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
-    }
-    if (!s) {
-      qh_fprintf(qh ferr, 6074, "qhull input error: missing \"begin\" for cdd-formatted input\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-  }
-  while (!numinput && (s= fgets(firstline, qh_MAXfirst, qh fin))) {
-    linecount++;
-    if (!memcmp(s, "begin", (size_t)5) || !memcmp(s, "BEGIN", (size_t)5))
-      wasbegin= True;
-    while (*s) {
-      while (isspace(*s))
-        s++;
-      if (!*s)
-        break;
-      if (!isdigit(*s)) {
-        if (!*qh rbox_command) {
-          strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
-          firsttext= linecount;
-        }
-        break;
-      }
-      if (!diminput)
-        diminput= qh_strtol(s, &s);
-      else {
-        numinput= qh_strtol(s, &s);
-        if (numinput == 1 && diminput >= 2 && qh HALFspace && !qh CDDinput) {
-          linecount += qh_readfeasible(diminput, s); /* checks if ok */
-          dimfeasible= diminput;
-          diminput= numinput= 0;
-        }else
-          break;
-      }
-    }
-  }
-  if (!s) {
-    qh_fprintf(qh ferr, 6075, "qhull input error: short input file.  Did not find dimension and number of points\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (diminput > numinput) {
-    tempi= diminput;    /* exchange dim and n, e.g., for cdd input format */
-    diminput= numinput;
-    numinput= tempi;
-  }
-  if (diminput < 2) {
-    qh_fprintf(qh ferr, 6220,"qhull input error: dimension %d(first number) should be at least 2\n",
-            diminput);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (isdelaunay) {
-    qh PROJECTdelaunay= False;
-    if (qh CDDinput)
-      *dimension= diminput;
-    else
-      *dimension= diminput+1;
-    *numpoints= numinput;
-    if (qh ATinfinity)
-      (*numpoints)++;
-  }else if (qh HALFspace) {
-    *dimension= diminput - 1;
-    *numpoints= numinput;
-    if (diminput < 3) {
-      qh_fprintf(qh ferr, 6221,"qhull input error: dimension %d(first number, includes offset) should be at least 3 for halfspaces\n",
-            diminput);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    if (dimfeasible) {
-      if (dimfeasible != *dimension) {
-        qh_fprintf(qh ferr, 6222,"qhull input error: dimension %d of feasible point is not one less than dimension %d for halfspaces\n",
-          dimfeasible, diminput);
-        qh_errexit(qh_ERRinput, NULL, NULL);
-      }
-    }else
-      qh_setfeasible(*dimension);
-  }else {
-    if (qh CDDinput)
-      *dimension= diminput-1;
-    else
-      *dimension= diminput;
-    *numpoints= numinput;
-  }
-  qh normal_size= *dimension * sizeof(coordT); /* for tracing with qh_printpoint */
-  if (qh HALFspace) {
-    qh half_space= coordp= (coordT*)qh_malloc(qh normal_size + sizeof(coordT));
-    if (qh CDDinput) {
-      offsetp= qh half_space;
-      normalp= offsetp + 1;
-    }else {
-      normalp= qh half_space;
-      offsetp= normalp + *dimension;
-    }
-  }
-  qh maxline= diminput * (qh_REALdigits + 5);
-  maximize_(qh maxline, 500);
-  qh line= (char*)qh_malloc((qh maxline+1) * sizeof(char));
-  *ismalloc= True;  /* use malloc since memory not setup */
-  coords= points= qh temp_malloc=  /* numinput and diminput >=2 by QH6220 */
-        (coordT*)qh_malloc((*numpoints)*(*dimension)*sizeof(coordT));
-  if (!coords || !qh line || (qh HALFspace && !qh half_space)) {
-    qh_fprintf(qh ferr, 6076, "qhull error: insufficient memory to read %d points\n",
-            numinput);
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  if (isdelaunay && qh ATinfinity) {
-    infinity= points + numinput * (*dimension);
-    for (k= (*dimension) - 1; k--; )
-      infinity[k]= 0.0;
-  }
-  maxcount= numinput * diminput;
-  paraboloid= 0.0;
-  while ((s= (isfirst ?  s : fgets(qh line, qh maxline, qh fin)))) {
-    if (!isfirst) {
-      linecount++;
-      if (*s == 'e' || *s == 'E') {
-        if (!memcmp(s, "end", (size_t)3) || !memcmp(s, "END", (size_t)3)) {
-          if (qh CDDinput )
-            break;
-          else if (wasbegin)
-            qh_fprintf(qh ferr, 7058, "qhull input warning: the input appears to be in cdd format.  If so, use 'Fd'\n");
-        }
-      }
-    }
-    islong= False;
-    while (*s) {
-      while (isspace(*s))
-        s++;
-      value= qh_strtod(s, &t);
-      if (s == t) {
-        if (!*qh rbox_command)
-         strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
-        if (*s && !firsttext)
-          firsttext= linecount;
-        if (!islong && !firstshort && coordcount)
-          firstshort= linecount;
-        break;
-      }
-      if (!firstpoint)
-        firstpoint= linecount;
-      s= t;
-      if (++tokcount > maxcount)
-        continue;
-      if (qh HALFspace) {
-        if (qh CDDinput)
-          *(coordp++)= -value; /* both coefficients and offset */
-        else
-          *(coordp++)= value;
-      }else {
-        *(coords++)= value;
-        if (qh CDDinput && !coordcount) {
-          if (value != 1.0) {
-            qh_fprintf(qh ferr, 6077, "qhull input error: for cdd format, point at line %d does not start with '1'\n",
-                   linecount);
-            qh_errexit(qh_ERRinput, NULL, NULL);
-          }
-          coords--;
-        }else if (isdelaunay) {
-          paraboloid += value * value;
-          if (qh ATinfinity) {
-            if (qh CDDinput)
-              infinity[coordcount-1] += value;
-            else
-              infinity[coordcount] += value;
-          }
-        }
-      }
-      if (++coordcount == diminput) {
-        coordcount= 0;
-        if (isdelaunay) {
-          *(coords++)= paraboloid;
-          maximize_(maxboloid, paraboloid);
-          paraboloid= 0.0;
-        }else if (qh HALFspace) {
-          if (!qh_sethalfspace(*dimension, coords, &coords, normalp, offsetp, qh feasible_point)) {
-            qh_fprintf(qh ferr, 8048, "The halfspace was on line %d\n", linecount);
-            if (wasbegin)
-              qh_fprintf(qh ferr, 8049, "The input appears to be in cdd format.  If so, you should use option 'Fd'\n");
-            qh_errexit(qh_ERRinput, NULL, NULL);
-          }
-          coordp= qh half_space;
-        }
-        while (isspace(*s))
-          s++;
-        if (*s) {
-          islong= True;
-          if (!firstlong)
-            firstlong= linecount;
-        }
-      }
-    }
-    if (!islong && !firstshort && coordcount)
-      firstshort= linecount;
-    if (!isfirst && s - qh line >= qh maxline) {
-      qh_fprintf(qh ferr, 6078, "qhull input error: line %d contained more than %d characters\n",
-              linecount, (int) (s - qh line));   /* WARN64 */
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    isfirst= False;
-  }
-  if (tokcount != maxcount) {
-    newnum= fmin_(numinput, tokcount/diminput);
-    qh_fprintf(qh ferr, 7073,"\
-qhull warning: instead of %d %d-dimensional points, input contains\n\
-%d points and %d extra coordinates.  Line %d is the first\npoint",
-       numinput, diminput, tokcount/diminput, tokcount % diminput, firstpoint);
-    if (firsttext)
-      qh_fprintf(qh ferr, 8051, ", line %d is the first comment", firsttext);
-    if (firstshort)
-      qh_fprintf(qh ferr, 8052, ", line %d is the first short\nline", firstshort);
-    if (firstlong)
-      qh_fprintf(qh ferr, 8053, ", line %d is the first long line", firstlong);
-    qh_fprintf(qh ferr, 8054, ".  Continue with %d points.\n", newnum);
-    numinput= newnum;
-    if (isdelaunay && qh ATinfinity) {
-      for (k= tokcount % diminput; k--; )
-        infinity[k] -= *(--coords);
-      *numpoints= newnum+1;
-    }else {
-      coords -= tokcount % diminput;
-      *numpoints= newnum;
-    }
-  }
-  if (isdelaunay && qh ATinfinity) {
-    for (k= (*dimension) -1; k--; )
-      infinity[k] /= numinput;
-    if (coords == infinity)
-      coords += (*dimension) -1;
-    else {
-      for (k=0; k < (*dimension) -1; k++)
-        *(coords++)= infinity[k];
-    }
-    *(coords++)= maxboloid * 1.1;
-  }
-  if (qh rbox_command[0]) {
-    qh rbox_command[strlen(qh rbox_command)-1]= '\0';
-    if (!strcmp(qh rbox_command, "./rbox D4"))
-      qh_fprintf(qh ferr, 8055, "\n\
-This is the qhull test case.  If any errors or core dumps occur,\n\
-recompile qhull with 'make new'.  If errors still occur, there is\n\
-an incompatibility.  You should try a different compiler.  You can also\n\
-change the choices in user.h.  If you discover the source of the problem,\n\
-please send mail to qhull_bug@qhull.org.\n\
-\n\
-Type 'qhull' for a short list of options.\n");
-  }
-  qh_free(qh line);
-  qh line= NULL;
-  if (qh half_space) {
-    qh_free(qh half_space);
-    qh half_space= NULL;
-  }
-  qh temp_malloc= NULL;
-  trace1((qh ferr, 1008,"qh_readpoints: read in %d %d-dimensional points\n",
-          numinput, diminput));
-  return(points);
-} /* readpoints */
-
-
-/*---------------------------------
-
-  qh_setfeasible( dim )
-    set qh.feasible_point from qh.feasible_string in "n,n,n" or "n n n" format
-
-  notes:
-    "n,n,n" already checked by qh_initflags()
-    see qh_readfeasible()
-    called only once from qh_new_qhull, otherwise leaks memory
-*/
-void qh_setfeasible(int dim) {
-  int tokcount= 0;
-  char *s;
-  coordT *coords, value;
-
-  if (!(s= qh feasible_string)) {
-    qh_fprintf(qh ferr, 6223, "\
-qhull input error: halfspace intersection needs a feasible point.\n\
-Either prepend the input with 1 point or use 'Hn,n,n'.  See manual.\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (!(qh feasible_point= (pointT*)qh_malloc(dim * sizeof(coordT)))) {
-    qh_fprintf(qh ferr, 6079, "qhull error: insufficient memory for 'Hn,n,n'\n");
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  coords= qh feasible_point;
-  while (*s) {
-    value= qh_strtod(s, &s);
-    if (++tokcount > dim) {
-      qh_fprintf(qh ferr, 7059, "qhull input warning: more coordinates for 'H%s' than dimension %d\n",
-          qh feasible_string, dim);
-      break;
-    }
-    *(coords++)= value;
-    if (*s)
-      s++;
-  }
-  while (++tokcount <= dim)
-    *(coords++)= 0.0;
-} /* setfeasible */
-
-/*---------------------------------
-
-  qh_skipfacet( facet )
-    returns 'True' if this facet is not to be printed
-
-  notes:
-    based on the user provided slice thresholds and 'good' specifications
-*/
-boolT qh_skipfacet(facetT *facet) {
-  facetT *neighbor, **neighborp;
-
-  if (qh PRINTneighbors) {
-    if (facet->good)
-      return !qh PRINTgood;
-    FOREACHneighbor_(facet) {
-      if (neighbor->good)
-        return False;
-    }
-    return True;
-  }else if (qh PRINTgood)
-    return !facet->good;
-  else if (!facet->normal)
-    return True;
-  return(!qh_inthresholds(facet->normal, NULL));
-} /* skipfacet */
-
-/*---------------------------------
-
-  qh_skipfilename( string )
-    returns pointer to character after filename
-
-  notes:
-    skips leading spaces
-    ends with spacing or eol
-    if starts with ' or " ends with the same, skipping \' or \"
-    For qhull, qh_argv_to_command() only uses double quotes
-*/
-char *qh_skipfilename(char *filename) {
-  char *s= filename;  /* non-const due to return */
-  char c;
-
-  while (*s && isspace(*s))
-    s++;
-  c= *s++;
-  if (c == '\0') {
-    qh_fprintf(qh ferr, 6204, "qhull input error: filename expected, none found.\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (c == '\'' || c == '"') {
-    while (*s !=c || s[-1] == '\\') {
-      if (!*s) {
-        qh_fprintf(qh ferr, 6203, "qhull input error: missing quote after filename -- %s\n", filename);
-        qh_errexit(qh_ERRinput, NULL, NULL);
-      }
-      s++;
-    }
-    s++;
-  }
-  else while (*s && !isspace(*s))
-      s++;
-  return s;
-} /* skipfilename */
-
diff --git a/extern/libqhull/io.h b/extern/libqhull/io.h
deleted file mode 100644
index eca0369d30e9..000000000000
--- a/extern/libqhull/io.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
  ---------------------------------
-
-   io.h
-   declarations of Input/Output functions
-
-   see README, libqhull.h and io.c
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/io.h#1 $$Change: 1981 $
-   $DateTime: 2015/09/28 20:26:32 $$Author: bbarber $
-*/
-
-#ifndef qhDEFio
-#define qhDEFio 1
-
-#include "libqhull.h"
-
-/*============ constants and flags ==================*/
-
-/*----------------------------------
-
-  qh_MAXfirst
-    maximum length of first two lines of stdin
-*/
-#define qh_MAXfirst  200
-
-/*----------------------------------
-
-  qh_MINradius
-    min radius for Gp and Gv, fraction of maxcoord
-*/
-#define qh_MINradius 0.02
-
-/*----------------------------------
-
-  qh_GEOMepsilon
-    adjust outer planes for 'lines closer' and geomview roundoff.
-    This prevents bleed through.
-*/
-#define qh_GEOMepsilon 2e-3
-
-/*----------------------------------
-
-  qh_WHITESPACE
-    possible values of white space
-*/
-#define qh_WHITESPACE " \n\t\v\r\f"
-
-
-/*----------------------------------
-
-  qh_RIDGE
-    to select which ridges to print in qh_eachvoronoi
-*/
-typedef enum
-{
-    qh_RIDGEall = 0, qh_RIDGEinner, qh_RIDGEouter
-}
-qh_RIDGE;
-
-/*----------------------------------
-
-  printvridgeT
-    prints results of qh_printvdiagram
-
-  see:
-    qh_printvridge for an example
-*/
-typedef void (*printvridgeT)(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
-
-/*============== -prototypes in alphabetical order =========*/
-
-void    qh_dfacet(unsigned id);
-void    qh_dvertex(unsigned id);
-int     qh_compare_facetarea(const void *p1, const void *p2);
-int     qh_compare_facetmerge(const void *p1, const void *p2);
-int     qh_compare_facetvisit(const void *p1, const void *p2);
-int     qh_compare_vertexpoint(const void *p1, const void *p2); /* not used, not in libqhull_r.h */
-void    qh_copyfilename(char *filename, int size, const char* source, int length);
-void    qh_countfacets(facetT *facetlist, setT *facets, boolT printall,
-              int *numfacetsp, int *numsimplicialp, int *totneighborsp,
-              int *numridgesp, int *numcoplanarsp, int *numnumtricoplanarsp);
-pointT *qh_detvnorm(vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp);
-setT   *qh_detvridge(vertexT *vertex);
-setT   *qh_detvridge3(vertexT *atvertex, vertexT *vertex);
-int     qh_eachvoronoi(FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder);
-int     qh_eachvoronoi_all(FILE *fp, printvridgeT printvridge, boolT isUpper, qh_RIDGE innerouter, boolT inorder);
-void    qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist);
-setT   *qh_facetvertices(facetT *facetlist, setT *facets, boolT allfacets);
-void    qh_geomplanes(facetT *facet, realT *outerplane, realT *innerplane);
-void    qh_markkeep(facetT *facetlist);
-setT   *qh_markvoronoi(facetT *facetlist, setT *facets, boolT printall, boolT *isLowerp, int *numcentersp);
-void    qh_order_vertexneighbors(vertexT *vertex);
-void    qh_prepare_output(void);
-void    qh_printafacet(FILE *fp, qh_PRINT format, facetT *facet, boolT printall);
-void    qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
-void    qh_printcenter(FILE *fp, qh_PRINT format, const char *string, facetT *facet);
-void    qh_printcentrum(FILE *fp, facetT *facet, realT radius);
-void    qh_printend(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
-void    qh_printend4geom(FILE *fp, facetT *facet, int *num, boolT printall);
-void    qh_printextremes(FILE *fp, facetT *facetlist, setT *facets, boolT printall);
-void    qh_printextremes_2d(FILE *fp, facetT *facetlist, setT *facets, boolT printall);
-void    qh_printextremes_d(FILE *fp, facetT *facetlist, setT *facets, boolT printall);
-void    qh_printfacet(FILE *fp, facetT *facet);
-void    qh_printfacet2math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst);
-void    qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]);
-void    qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
-                               facetT *facet, realT offset, realT color[3]);
-void    qh_printfacet3math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst);
-void    qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
-void    qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]);
-void    qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
-void    qh_printfacet3vertex(FILE *fp, facetT *facet, qh_PRINT format);
-void    qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
-void    qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
-void    qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, qh_PRINT format);
-void    qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, qh_PRINT format);
-void    qh_printfacetheader(FILE *fp, facetT *facet);
-void    qh_printfacetridges(FILE *fp, facetT *facet);
-void    qh_printfacets(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
-void    qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
-                   setT *vertices, realT color[3]);
-void    qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall);
-void    qh_printline3geom(FILE *fp, pointT *pointA, pointT *pointB, realT color[3]);
-void    qh_printpoint(FILE *fp, const char *string, pointT *point);
-void    qh_printpointid(FILE *fp, const char *string, int dim, pointT *point, int id);
-void    qh_printpoint3(FILE *fp, pointT *point);
-void    qh_printpoints_out(FILE *fp, facetT *facetlist, setT *facets, boolT printall);
-void    qh_printpointvect(FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]);
-void    qh_printpointvect2(FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius);
-void    qh_printridge(FILE *fp, ridgeT *ridge);
-void    qh_printspheres(FILE *fp, setT *vertices, realT radius);
-void    qh_printvdiagram(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
-int     qh_printvdiagram2(FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder);
-void    qh_printvertex(FILE *fp, vertexT *vertex);
-void    qh_printvertexlist(FILE *fp, const char* string, facetT *facetlist,
-                         setT *facets, boolT printall);
-void    qh_printvertices(FILE *fp, const char* string, setT *vertices);
-void    qh_printvneighbors(FILE *fp, facetT* facetlist, setT *facets, boolT printall);
-void    qh_printvoronoi(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
-void    qh_printvnorm(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
-void    qh_printvridge(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
-void    qh_produce_output(void);
-void    qh_produce_output2(void);
-void    qh_projectdim3(pointT *source, pointT *destination);
-int     qh_readfeasible(int dim, const char *curline);
-coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
-void    qh_setfeasible(int dim);
-boolT   qh_skipfacet(facetT *facet);
-char   *qh_skipfilename(char *filename);
-
-#endif /* qhDEFio */
diff --git a/extern/libqhull/libqhull.c b/extern/libqhull/libqhull.c
deleted file mode 100644
index 7696a8a9fee8..000000000000
--- a/extern/libqhull/libqhull.c
+++ /dev/null
@@ -1,1403 +0,0 @@
-/*
  ---------------------------------
-
-   libqhull.c
-   Quickhull algorithm for convex hulls
-
-   qhull() and top-level routines
-
-   see qh-qhull.htm, libqhull.h, unix.c
-
-   see qhull_a.h for internal functions
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/libqhull.c#3 $$Change: 2047 $
-   $DateTime: 2016/01/04 22:03:18 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-/*============= functions in alphabetic order after qhull() =======*/
-
-/*---------------------------------
-
-  qh_qhull()
-    compute DIM3 convex hull of qh.num_points starting at qh.first_point
-    qh contains all global options and variables
-
-  returns:
-    returns polyhedron
-      qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices,
-
-    returns global variables
-      qh.hulltime, qh.max_outside, qh.interior_point, qh.max_vertex, qh.min_vertex
-
-    returns precision constants
-      qh.ANGLEround, centrum_radius, cos_max, DISTround, MAXabs_coord, ONEmerge
-
-  notes:
-    unless needed for output
-      qh.max_vertex and qh.min_vertex are max/min due to merges
-
-  see:
-    to add individual points to either qh.num_points
-      use qh_addpoint()
-
-    if qh.GETarea
-      qh_produceoutput() returns qh.totarea and qh.totvol via qh_getarea()
-
-  design:
-    record starting time
-    initialize hull and partition points
-    build convex hull
-    unless early termination
-      update facet->maxoutside for vertices, coplanar, and near-inside points
-    error if temporary sets exist
-    record end time
-*/
-
-void qh_qhull(void) {
-  int numoutside;
-
-  qh hulltime= qh_CPUclock;
-  if (qh RERUN || qh JOGGLEmax < REALmax/2)
-    qh_build_withrestart();
-  else {
-    qh_initbuild();
-    qh_buildhull();
-  }
-  if (!qh STOPpoint && !qh STOPcone) {
-    if (qh ZEROall_ok && !qh TESTvneighbors && qh MERGEexact)
-      qh_checkzero( qh_ALL);
-    if (qh ZEROall_ok && !qh TESTvneighbors && !qh WAScoplanar) {
-      trace2((qh ferr, 2055, "qh_qhull: all facets are clearly convex and no coplanar points.  Post-merging and check of maxout not needed.\n"));
-      qh DOcheckmax= False;
-    }else {
-      if (qh MERGEexact || (qh hull_dim > qh_DIMreduceBuild && qh PREmerge))
-        qh_postmerge("First post-merge", qh premerge_centrum, qh premerge_cos,
-             (qh POSTmerge ? False : qh TESTvneighbors));
-      else if (!qh POSTmerge && qh TESTvneighbors)
-        qh_postmerge("For testing vertex neighbors", qh premerge_centrum,
-             qh premerge_cos, True);
-      if (qh POSTmerge)
-        qh_postmerge("For post-merging", qh postmerge_centrum,
-             qh postmerge_cos, qh TESTvneighbors);
-      if (qh visible_list == qh facet_list) { /* i.e., merging done */
-        qh findbestnew= True;
-        qh_partitionvisible(/*qh.visible_list*/ !qh_ALL, &numoutside);
-        qh findbestnew= False;
-        qh_deletevisible(/*qh.visible_list*/);
-        qh_resetlists(False, qh_RESETvisible /*qh.visible_list newvertex_list newfacet_list */);
-      }
-    }
-    if (qh DOcheckmax){
-      if (qh REPORTfreq) {
-        qh_buildtracing(NULL, NULL);
-        qh_fprintf(qh ferr, 8115, "\nTesting all coplanar points.\n");
-      }
-      qh_check_maxout();
-    }
-    if (qh KEEPnearinside && !qh maxoutdone)
-      qh_nearcoplanar();
-  }
-  if (qh_setsize(qhmem.tempstack) != 0) {
-    qh_fprintf(qh ferr, 6164, "qhull internal error (qh_qhull): temporary sets not empty(%d)\n",
-             qh_setsize(qhmem.tempstack));
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  qh hulltime= qh_CPUclock - qh hulltime;
-  qh QHULLfinished= True;
-  trace1((qh ferr, 1036, "Qhull: algorithm completed\n"));
-} /* qhull */
-
-/*---------------------------------
-
-  qh_addpoint( furthest, facet, checkdist )
-    add point (usually furthest point) above facet to hull
-    if checkdist,
-      check that point is above facet.
-      if point is not outside of the hull, uses qh_partitioncoplanar()
-      assumes that facet is defined by qh_findbestfacet()
-    else if facet specified,
-      assumes that point is above facet (major damage if below)
-    for Delaunay triangulations,
-      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
-      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
-
-  returns:
-    returns False if user requested an early termination
-     qh.visible_list, newfacet_list, delvertex_list, NEWfacets may be defined
-    updates qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices
-    clear qh.maxoutdone (will need to call qh_check_maxout() for facet->maxoutside)
-    if unknown point, adds a pointer to qh.other_points
-      do not deallocate the point's coordinates
-
-  notes:
-    assumes point is near its best facet and not at a local minimum of a lens
-      distributions.  Use qh_findbestfacet to avoid this case.
-    uses qh.visible_list, qh.newfacet_list, qh.delvertex_list, qh.NEWfacets
-
-  see also:
-    qh_triangulate() -- triangulate non-simplicial facets
-
-  design:
-    add point to other_points if needed
-    if checkdist
-      if point not above facet
-        partition coplanar point
-        exit
-    exit if pre STOPpoint requested
-    find horizon and visible facets for point
-    make new facets for point to horizon
-    make hyperplanes for point
-    compute balance statistics
-    match neighboring new facets
-    update vertex neighbors and delete interior vertices
-    exit if STOPcone requested
-    merge non-convex new facets
-    if merge found, many merges, or 'Qf'
-       use qh_findbestnew() instead of qh_findbest()
-    partition outside points from visible facets
-    delete visible facets
-    check polyhedron if requested
-    exit if post STOPpoint requested
-    reset working lists of facets and vertices
-*/
-boolT qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist) {
-  int goodvisible, goodhorizon;
-  vertexT *vertex;
-  facetT *newfacet;
-  realT dist, newbalance, pbalance;
-  boolT isoutside= False;
-  int numpart, numpoints, numnew, firstnew;
-
-  qh maxoutdone= False;
-  if (qh_pointid(furthest) == qh_IDunknown)
-    qh_setappend(&qh other_points, furthest);
-  if (!facet) {
-    qh_fprintf(qh ferr, 6213, "qhull internal error (qh_addpoint): NULL facet.  Need to call qh_findbestfacet first\n");
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  if (checkdist) {
-    facet= qh_findbest(furthest, facet, !qh_ALL, !qh_ISnewfacets, !qh_NOupper,
-                        &dist, &isoutside, &numpart);
-    zzadd_(Zpartition, numpart);
-    if (!isoutside) {
-      zinc_(Znotmax);  /* last point of outsideset is no longer furthest. */
-      facet->notfurthest= True;
-      qh_partitioncoplanar(furthest, facet, &dist);
-      return True;
-    }
-  }
-  qh_buildtracing(furthest, facet);
-  if (qh STOPpoint < 0 && qh furthest_id == -qh STOPpoint-1) {
-    facet->notfurthest= True;
-    return False;
-  }
-  qh_findhorizon(furthest, facet, &goodvisible, &goodhorizon);
-  if (qh ONLYgood && !(goodvisible+goodhorizon) && !qh GOODclosest) {
-    zinc_(Znotgood);
-    facet->notfurthest= True;
-    /* last point of outsideset is no longer furthest.  This is ok
-       since all points of the outside are likely to be bad */
-    qh_resetlists(False, qh_RESETvisible /*qh.visible_list newvertex_list newfacet_list */);
-    return True;
-  }
-  zzinc_(Zprocessed);
-  firstnew= qh facet_id;
-  vertex= qh_makenewfacets(furthest /*visible_list, attaches if !ONLYgood */);
-  qh_makenewplanes(/* newfacet_list */);
-  numnew= qh facet_id - firstnew;
-  newbalance= numnew - (realT) (qh num_facets-qh num_visible)
-                         * qh hull_dim/qh num_vertices;
-  wadd_(Wnewbalance, newbalance);
-  wadd_(Wnewbalance2, newbalance * newbalance);
-  if (qh ONLYgood
-  && !qh_findgood(qh newfacet_list, goodhorizon) && !qh GOODclosest) {
-    FORALLnew_facets
-      qh_delfacet(newfacet);
-    qh_delvertex(vertex);
-    qh_resetlists(True, qh_RESETvisible /*qh.visible_list newvertex_list newfacet_list */);
-    zinc_(Znotgoodnew);
-    facet->notfurthest= True;
-    return True;
-  }
-  if (qh ONLYgood)
-    qh_attachnewfacets(/*visible_list*/);
-  qh_matchnewfacets();
-  qh_updatevertices();
-  if (qh STOPcone && qh furthest_id == qh STOPcone-1) {
-    facet->notfurthest= True;
-    return False;  /* visible_list etc. still defined */
-  }
-  qh findbestnew= False;
-  if (qh PREmerge || qh MERGEexact) {
-    qh_premerge(vertex, qh premerge_centrum, qh premerge_cos);
-    if (qh_USEfindbestnew)
-      qh findbestnew= True;
-    else {
-      FORALLnew_facets {
-        if (!newfacet->simplicial) {
-          qh findbestnew= True;  /* use qh_findbestnew instead of qh_findbest*/
-          break;
-        }
-      }
-    }
-  }else if (qh BESToutside)
-    qh findbestnew= True;
-  qh_partitionvisible(/*qh.visible_list*/ !qh_ALL, &numpoints);
-  qh findbestnew= False;
-  qh findbest_notsharp= False;
-  zinc_(Zpbalance);
-  pbalance= numpoints - (realT) qh hull_dim /* assumes all points extreme */
-                * (qh num_points - qh num_vertices)/qh num_vertices;
-  wadd_(Wpbalance, pbalance);
-  wadd_(Wpbalance2, pbalance * pbalance);
-  qh_deletevisible(/*qh.visible_list*/);
-  zmax_(Zmaxvertex, qh num_vertices);
-  qh NEWfacets= False;
-  if (qh IStracing >= 4) {
-    if (qh num_facets < 2000)
-      qh_printlists();
-    qh_printfacetlist(qh newfacet_list, NULL, True);
-    qh_checkpolygon(qh facet_list);
-  }else if (qh CHECKfrequently) {
-    if (qh num_facets < 50)
-      qh_checkpolygon(qh facet_list);
-    else
-      qh_checkpolygon(qh newfacet_list);
-  }
-  if (qh STOPpoint > 0 && qh furthest_id == qh STOPpoint-1)
-    return False;
-  qh_resetlists(True, qh_RESETvisible /*qh.visible_list newvertex_list newfacet_list */);
-  /* qh_triangulate(); to test qh.TRInormals */
-  trace2((qh ferr, 2056, "qh_addpoint: added p%d new facets %d new balance %2.2g point balance %2.2g\n",
-    qh_pointid(furthest), numnew, newbalance, pbalance));
-  return True;
-} /* addpoint */
-
-/*---------------------------------
-
-  qh_build_withrestart()
-    allow restarts due to qh.JOGGLEmax while calling qh_buildhull()
-       qh_errexit always undoes qh_build_withrestart()
-    qh.FIRSTpoint/qh.NUMpoints is point array
-        it may be moved by qh_joggleinput()
-*/
-void qh_build_withrestart(void) {
-  int restart;
-
-  qh ALLOWrestart= True;
-  while (True) {
-    restart= setjmp(qh restartexit); /* simple statement for CRAY J916 */
-    if (restart) {       /* only from qh_precision() */
-      zzinc_(Zretry);
-      wmax_(Wretrymax, qh JOGGLEmax);
-      /* QH7078 warns about using 'TCn' with 'QJn' */
-      qh STOPcone= qh_IDunknown; /* if break from joggle, prevents normal output */
-    }
-    if (!qh RERUN && qh JOGGLEmax < REALmax/2) {
-      if (qh build_cnt > qh_JOGGLEmaxretry) {
-        qh_fprintf(qh ferr, 6229, "qhull precision error: %d attempts to construct a convex hull\n\
-        with joggled input.  Increase joggle above 'QJ%2.2g'\n\
-        or modify qh_JOGGLE... parameters in user.h\n",
-           qh build_cnt, qh JOGGLEmax);
-        qh_errexit(qh_ERRqhull, NULL, NULL);
-      }
-      if (qh build_cnt && !restart)
-        break;
-    }else if (qh build_cnt && qh build_cnt >= qh RERUN)
-      break;
-    qh STOPcone= 0;
-    qh_freebuild(True);  /* first call is a nop */
-    qh build_cnt++;
-    if (!qh qhull_optionsiz)
-      qh qhull_optionsiz= (int)strlen(qh qhull_options);   /* WARN64 */
-    else {
-      qh qhull_options [qh qhull_optionsiz]= '\0';
-      qh qhull_optionlen= qh_OPTIONline;  /* starts a new line */
-    }
-    qh_option("_run", &qh build_cnt, NULL);
-    if (qh build_cnt == qh RERUN) {
-      qh IStracing= qh TRACElastrun;  /* duplicated from qh_initqhull_globals */
-      if (qh TRACEpoint != qh_IDunknown || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
-        qh TRACElevel= (qh IStracing? qh IStracing : 3);
-        qh IStracing= 0;
-      }
-      qhmem.IStracing= qh IStracing;
-    }
-    if (qh JOGGLEmax < REALmax/2)
-      qh_joggleinput();
-    qh_initbuild();
-    qh_buildhull();
-    if (qh JOGGLEmax < REALmax/2 && !qh MERGING)
-      qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
-  }
-  qh ALLOWrestart= False;
-} /* qh_build_withrestart */
-
-/*---------------------------------
-
-  qh_buildhull()
-    construct a convex hull by adding outside points one at a time
-
-  returns:
-
-  notes:
-    may be called multiple times
-    checks facet and vertex lists for incorrect flags
-    to recover from STOPcone, call qh_deletevisible and qh_resetlists
-
-  design:
-    check visible facet and newfacet flags
-    check newlist vertex flags and qh.STOPcone/STOPpoint
-    for each facet with a furthest outside point
-      add point to facet
-      exit if qh.STOPcone or qh.STOPpoint requested
-    if qh.NARROWhull for initial simplex
-      partition remaining outside points to coplanar sets
-*/
-void qh_buildhull(void) {
-  facetT *facet;
-  pointT *furthest;
-  vertexT *vertex;
-  int id;
-
-  trace1((qh ferr, 1037, "qh_buildhull: start build hull\n"));
-  FORALLfacets {
-    if (facet->visible || facet->newfacet) {
-      qh_fprintf(qh ferr, 6165, "qhull internal error (qh_buildhull): visible or new facet f%d in facet list\n",
-                   facet->id);
-      qh_errexit(qh_ERRqhull, facet, NULL);
-    }
-  }
-  FORALLvertices {
-    if (vertex->newlist) {
-      qh_fprintf(qh ferr, 6166, "qhull internal error (qh_buildhull): new vertex f%d in vertex list\n",
-                   vertex->id);
-      qh_errprint("ERRONEOUS", NULL, NULL, NULL, vertex);
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-    }
-    id= qh_pointid(vertex->point);
-    if ((qh STOPpoint>0 && id == qh STOPpoint-1) ||
-        (qh STOPpoint<0 && id == -qh STOPpoint-1) ||
-        (qh STOPcone>0 && id == qh STOPcone-1)) {
-      trace1((qh ferr, 1038,"qh_buildhull: stop point or cone P%d in initial hull\n", id));
-      return;
-    }
-  }
-  qh facet_next= qh facet_list;      /* advance facet when processed */
-  while ((furthest= qh_nextfurthest(&facet))) {
-    qh num_outside--;  /* if ONLYmax, furthest may not be outside */
-    if (!qh_addpoint(furthest, facet, qh ONLYmax))
-      break;
-  }
-  if (qh NARROWhull) /* move points from outsideset to coplanarset */
-    qh_outcoplanar( /* facet_list */ );
-  if (qh num_outside && !furthest) {
-    qh_fprintf(qh ferr, 6167, "qhull internal error (qh_buildhull): %d outside points were never processed.\n", qh num_outside);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  trace1((qh ferr, 1039, "qh_buildhull: completed the hull construction\n"));
-} /* buildhull */
-
-
-/*---------------------------------
-
-  qh_buildtracing( furthest, facet )
-    trace an iteration of qh_buildhull() for furthest point and facet
-    if !furthest, prints progress message
-
-  returns:
-    tracks progress with qh.lastreport
-    updates qh.furthest_id (-3 if furthest is NULL)
-    also resets visit_id, vertext_visit on wrap around
-
-  see:
-    qh_tracemerging()
-
-  design:
-    if !furthest
-      print progress message
-      exit
-    if 'TFn' iteration
-      print progress message
-    else if tracing
-      trace furthest point and facet
-    reset qh.visit_id and qh.vertex_visit if overflow may occur
-    set qh.furthest_id for tracing
-*/
-void qh_buildtracing(pointT *furthest, facetT *facet) {
-  realT dist= 0;
-  float cpu;
-  int total, furthestid;
-  time_t timedata;
-  struct tm *tp;
-  vertexT *vertex;
-
-  qh old_randomdist= qh RANDOMdist;
-  qh RANDOMdist= False;
-  if (!furthest) {
-    time(&timedata);
-    tp= localtime(&timedata);
-    cpu= (float)qh_CPUclock - (float)qh hulltime;
-    cpu /= (float)qh_SECticks;
-    total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
-    qh_fprintf(qh ferr, 8118, "\n\
-At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
- The current hull contains %d facets and %d vertices.  Last point was p%d\n",
-      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh facet_id -1,
-      total, qh num_facets, qh num_vertices, qh furthest_id);
-    return;
-  }
-  furthestid= qh_pointid(furthest);
-  if (qh TRACEpoint == furthestid) {
-    qh IStracing= qh TRACElevel;
-    qhmem.IStracing= qh TRACElevel;
-  }else if (qh TRACEpoint != qh_IDunknown && qh TRACEdist < REALmax/2) {
-    qh IStracing= 0;
-    qhmem.IStracing= 0;
-  }
-  if (qh REPORTfreq && (qh facet_id-1 > qh lastreport+qh REPORTfreq)) {
-    qh lastreport= qh facet_id-1;
-    time(&timedata);
-    tp= localtime(&timedata);
-    cpu= (float)qh_CPUclock - (float)qh hulltime;
-    cpu /= (float)qh_SECticks;
-    total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
-    zinc_(Zdistio);
-    qh_distplane(furthest, facet, &dist);
-    qh_fprintf(qh ferr, 8119, "\n\
-At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
- The current hull contains %d facets and %d vertices.  There are %d\n\
- outside points.  Next is point p%d(v%d), %2.2g above f%d.\n",
-      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh facet_id -1,
-      total, qh num_facets, qh num_vertices, qh num_outside+1,
-      furthestid, qh vertex_id, dist, getid_(facet));
-  }else if (qh IStracing >=1) {
-    cpu= (float)qh_CPUclock - (float)qh hulltime;
-    cpu /= (float)qh_SECticks;
-    qh_distplane(furthest, facet, &dist);
-    qh_fprintf(qh ferr, 8120, "qh_addpoint: add p%d(v%d) to hull of %d facets(%2.2g above f%d) and %d outside at %4.4g CPU secs.  Previous was p%d.\n",
-      furthestid, qh vertex_id, qh num_facets, dist,
-      getid_(facet), qh num_outside+1, cpu, qh furthest_id);
-  }
-  zmax_(Zvisit2max, (int)qh visit_id/2);
-  if (qh visit_id > (unsigned) INT_MAX) { /* 31 bits */
-    zinc_(Zvisit);
-    qh visit_id= 0;
-    FORALLfacets
-      facet->visitid= 0;
-  }
-  zmax_(Zvvisit2max, (int)qh vertex_visit/2);
-  if (qh vertex_visit > (unsigned) INT_MAX) { /* 31 bits */
-    zinc_(Zvvisit);
-    qh vertex_visit= 0;
-    FORALLvertices
-      vertex->visitid= 0;
-  }
-  qh furthest_id= furthestid;
-  qh RANDOMdist= qh old_randomdist;
-} /* buildtracing */
-
-/*---------------------------------
-
-  qh_errexit2( exitcode, facet, otherfacet )
-    return exitcode to system after an error
-    report two facets
-
-  returns:
-    assumes exitcode non-zero
-
-  see:
-    normally use qh_errexit() in user.c(reports a facet and a ridge)
-*/
-void qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet) {
-
-  qh_errprint("ERRONEOUS", facet, otherfacet, NULL, NULL);
-  qh_errexit(exitcode, NULL, NULL);
-} /* errexit2 */
-
-
-/*---------------------------------
-
-  qh_findhorizon( point, facet, goodvisible, goodhorizon )
-    given a visible facet, find the point's horizon and visible facets
-    for all facets, !facet-visible
-
-  returns:
-    returns qh.visible_list/num_visible with all visible facets
-      marks visible facets with ->visible
-    updates count of good visible and good horizon facets
-    updates qh.max_outside, qh.max_vertex, facet->maxoutside
-
-  see:
-    similar to qh_delpoint()
-
-  design:
-    move facet to qh.visible_list at end of qh.facet_list
-    for all visible facets
-     for each unvisited neighbor of a visible facet
-       compute distance of point to neighbor
-       if point above neighbor
-         move neighbor to end of qh.visible_list
-       else if point is coplanar with neighbor
-         update qh.max_outside, qh.max_vertex, neighbor->maxoutside
-         mark neighbor coplanar (will create a samecycle later)
-         update horizon statistics
-*/
-void qh_findhorizon(pointT *point, facetT *facet, int *goodvisible, int *goodhorizon) {
-  facetT *neighbor, **neighborp, *visible;
-  int numhorizon= 0, coplanar= 0;
-  realT dist;
-
-  trace1((qh ferr, 1040,"qh_findhorizon: find horizon for point p%d facet f%d\n",qh_pointid(point),facet->id));
-  *goodvisible= *goodhorizon= 0;
-  zinc_(Ztotvisible);
-  qh_removefacet(facet);  /* visible_list at end of qh facet_list */
-  qh_appendfacet(facet);
-  qh num_visible= 1;
-  if (facet->good)
-    (*goodvisible)++;
-  qh visible_list= facet;
-  facet->visible= True;
-  facet->f.replace= NULL;
-  if (qh IStracing >=4)
-    qh_errprint("visible", facet, NULL, NULL, NULL);
-  qh visit_id++;
-  FORALLvisible_facets {
-    if (visible->tricoplanar && !qh TRInormals) {
-      qh_fprintf(qh ferr, 6230, "Qhull internal error (qh_findhorizon): does not work for tricoplanar facets.  Use option 'Q11'\n");
-      qh_errexit(qh_ERRqhull, visible, NULL);
-    }
-    visible->visitid= qh visit_id;
-    FOREACHneighbor_(visible) {
-      if (neighbor->visitid == qh visit_id)
-        continue;
-      neighbor->visitid= qh visit_id;
-      zzinc_(Znumvisibility);
-      qh_distplane(point, neighbor, &dist);
-      if (dist > qh MINvisible) {
-        zinc_(Ztotvisible);
-        qh_removefacet(neighbor);  /* append to end of qh visible_list */
-        qh_appendfacet(neighbor);
-        neighbor->visible= True;
-        neighbor->f.replace= NULL;
-        qh num_visible++;
-        if (neighbor->good)
-          (*goodvisible)++;
-        if (qh IStracing >=4)
-          qh_errprint("visible", neighbor, NULL, NULL, NULL);
-      }else {
-        if (dist > - qh MAXcoplanar) {
-          neighbor->coplanar= True;
-          zzinc_(Zcoplanarhorizon);
-          qh_precision("coplanar horizon");
-          coplanar++;
-          if (qh MERGING) {
-            if (dist > 0) {
-              maximize_(qh max_outside, dist);
-              maximize_(qh max_vertex, dist);
-#if qh_MAXoutside
-              maximize_(neighbor->maxoutside, dist);
-#endif
-            }else
-              minimize_(qh min_vertex, dist);  /* due to merge later */
-          }
-          trace2((qh ferr, 2057, "qh_findhorizon: point p%d is coplanar to horizon f%d, dist=%2.7g < qh MINvisible(%2.7g)\n",
-              qh_pointid(point), neighbor->id, dist, qh MINvisible));
-        }else
-          neighbor->coplanar= False;
-        zinc_(Ztothorizon);
-        numhorizon++;
-        if (neighbor->good)
-          (*goodhorizon)++;
-        if (qh IStracing >=4)
-          qh_errprint("horizon", neighbor, NULL, NULL, NULL);
-      }
-    }
-  }
-  if (!numhorizon) {
-    qh_precision("empty horizon");
-    qh_fprintf(qh ferr, 6168, "qhull precision error (qh_findhorizon): empty horizon\n\
-QhullPoint p%d was above all facets.\n", qh_pointid(point));
-    qh_printfacetlist(qh facet_list, NULL, True);
-    qh_errexit(qh_ERRprec, NULL, NULL);
-  }
-  trace1((qh ferr, 1041, "qh_findhorizon: %d horizon facets(good %d), %d visible(good %d), %d coplanar\n",
-       numhorizon, *goodhorizon, qh num_visible, *goodvisible, coplanar));
-  if (qh IStracing >= 4 && qh num_facets < 50)
-    qh_printlists();
-} /* findhorizon */
-
-/*---------------------------------
-
-  qh_nextfurthest( visible )
-    returns next furthest point and visible facet for qh_addpoint()
-    starts search at qh.facet_next
-
-  returns:
-    removes furthest point from outside set
-    NULL if none available
-    advances qh.facet_next over facets with empty outside sets
-
-  design:
-    for each facet from qh.facet_next
-      if empty outside set
-        advance qh.facet_next
-      else if qh.NARROWhull
-        determine furthest outside point
-        if furthest point is not outside
-          advance qh.facet_next(point will be coplanar)
-    remove furthest point from outside set
-*/
-pointT *qh_nextfurthest(facetT **visible) {
-  facetT *facet;
-  int size, idx;
-  realT randr, dist;
-  pointT *furthest;
-
-  while ((facet= qh facet_next) != qh facet_tail) {
-    if (!facet->outsideset) {
-      qh facet_next= facet->next;
-      continue;
-    }
-    SETreturnsize_(facet->outsideset, size);
-    if (!size) {
-      qh_setfree(&facet->outsideset);
-      qh facet_next= facet->next;
-      continue;
-    }
-    if (qh NARROWhull) {
-      if (facet->notfurthest)
-        qh_furthestout(facet);
-      furthest= (pointT*)qh_setlast(facet->outsideset);
-#if qh_COMPUTEfurthest
-      qh_distplane(furthest, facet, &dist);
-      zinc_(Zcomputefurthest);
-#else
-      dist= facet->furthestdist;
-#endif
-      if (dist < qh MINoutside) { /* remainder of outside set is coplanar for qh_outcoplanar */
-        qh facet_next= facet->next;
-        continue;
-      }
-    }
-    if (!qh RANDOMoutside && !qh VIRTUALmemory) {
-      if (qh PICKfurthest) {
-        qh_furthestnext(/* qh.facet_list */);
-        facet= qh facet_next;
-      }
-      *visible= facet;
-      return((pointT*)qh_setdellast(facet->outsideset));
-    }
-    if (qh RANDOMoutside) {
-      int outcoplanar = 0;
-      if (qh NARROWhull) {
-        FORALLfacets {
-          if (facet == qh facet_next)
-            break;
-          if (facet->outsideset)
-            outcoplanar += qh_setsize( facet->outsideset);
-        }
-      }
-      randr= qh_RANDOMint;
-      randr= randr/(qh_RANDOMmax+1);
-      idx= (int)floor((qh num_outside - outcoplanar) * randr);
-      FORALLfacet_(qh facet_next) {
-        if (facet->outsideset) {
-          SETreturnsize_(facet->outsideset, size);
-          if (!size)
-            qh_setfree(&facet->outsideset);
-          else if (size > idx) {
-            *visible= facet;
-            return((pointT*)qh_setdelnth(facet->outsideset, idx));
-          }else
-            idx -= size;
-        }
-      }
-      qh_fprintf(qh ferr, 6169, "qhull internal error (qh_nextfurthest): num_outside %d is too low\nby at least %d, or a random real %g >= 1.0\n",
-              qh num_outside, idx+1, randr);
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-    }else { /* VIRTUALmemory */
-      facet= qh facet_tail->previous;
-      if (!(furthest= (pointT*)qh_setdellast(facet->outsideset))) {
-        if (facet->outsideset)
-          qh_setfree(&facet->outsideset);
-        qh_removefacet(facet);
-        qh_prependfacet(facet, &qh facet_list);
-        continue;
-      }
-      *visible= facet;
-      return furthest;
-    }
-  }
-  return NULL;
-} /* nextfurthest */
-
-/*---------------------------------
-
-  qh_partitionall( vertices, points, numpoints )
-    partitions all points in points/numpoints to the outsidesets of facets
-    vertices= vertices in qh.facet_list(!partitioned)
-
-  returns:
-    builds facet->outsideset
-    does not partition qh.GOODpoint
-    if qh.ONLYgood && !qh.MERGING,
-      does not partition qh.GOODvertex
-
-  notes:
-    faster if qh.facet_list sorted by anticipated size of outside set
-
-  design:
-    initialize pointset with all points
-    remove vertices from pointset
-    remove qh.GOODpointp from pointset (unless it's qh.STOPcone or qh.STOPpoint)
-    for all facets
-      for all remaining points in pointset
-        compute distance from point to facet
-        if point is outside facet
-          remove point from pointset (by not reappending)
-          update bestpoint
-          append point or old bestpoint to facet's outside set
-      append bestpoint to facet's outside set (furthest)
-    for all points remaining in pointset
-      partition point into facets' outside sets and coplanar sets
-*/
-void qh_partitionall(setT *vertices, pointT *points, int numpoints){
-  setT *pointset;
-  vertexT *vertex, **vertexp;
-  pointT *point, **pointp, *bestpoint;
-  int size, point_i, point_n, point_end, remaining, i, id;
-  facetT *facet;
-  realT bestdist= -REALmax, dist, distoutside;
-
-  trace1((qh ferr, 1042, "qh_partitionall: partition all points into outside sets\n"));
-  pointset= qh_settemp(numpoints);
-  qh num_outside= 0;
-  pointp= SETaddr_(pointset, pointT);
-  for (i=numpoints, point= points; i--; point += qh hull_dim)
-    *(pointp++)= point;
-  qh_settruncate(pointset, numpoints);
-  FOREACHvertex_(vertices) {
-    if ((id= qh_pointid(vertex->point)) >= 0)
-      SETelem_(pointset, id)= NULL;
-  }
-  id= qh_pointid(qh GOODpointp);
-  if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id)
-    SETelem_(pointset, id)= NULL;
-  if (qh GOODvertexp && qh ONLYgood && !qh MERGING) { /* matches qhull()*/
-    if ((id= qh_pointid(qh GOODvertexp)) >= 0)
-      SETelem_(pointset, id)= NULL;
-  }
-  if (!qh BESToutside) {  /* matches conditional for qh_partitionpoint below */
-    distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
-    zval_(Ztotpartition)= qh num_points - qh hull_dim - 1; /*misses GOOD... */
-    remaining= qh num_facets;
-    point_end= numpoints;
-    FORALLfacets {
-      size= point_end/(remaining--) + 100;
-      facet->outsideset= qh_setnew(size);
-      bestpoint= NULL;
-      point_end= 0;
-      FOREACHpoint_i_(pointset) {
-        if (point) {
-          zzinc_(Zpartitionall);
-          qh_distplane(point, facet, &dist);
-          if (dist < distoutside)
-            SETelem_(pointset, point_end++)= point;
-          else {
-            qh num_outside++;
-            if (!bestpoint) {
-              bestpoint= point;
-              bestdist= dist;
-            }else if (dist > bestdist) {
-              qh_setappend(&facet->outsideset, bestpoint);
-              bestpoint= point;
-              bestdist= dist;
-            }else
-              qh_setappend(&facet->outsideset, point);
-          }
-        }
-      }
-      if (bestpoint) {
-        qh_setappend(&facet->outsideset, bestpoint);
-#if !qh_COMPUTEfurthest
-        facet->furthestdist= bestdist;
-#endif
-      }else
-        qh_setfree(&facet->outsideset);
-      qh_settruncate(pointset, point_end);
-    }
-  }
-  /* if !qh BESToutside, pointset contains points not assigned to outsideset */
-  if (qh BESToutside || qh MERGING || qh KEEPcoplanar || qh KEEPinside) {
-    qh findbestnew= True;
-    FOREACHpoint_i_(pointset) {
-      if (point)
-        qh_partitionpoint(point, qh facet_list);
-    }
-    qh findbestnew= False;
-  }
-  zzadd_(Zpartitionall, zzval_(Zpartition));
-  zzval_(Zpartition)= 0;
-  qh_settempfree(&pointset);
-  if (qh IStracing >= 4)
-    qh_printfacetlist(qh facet_list, NULL, True);
-} /* partitionall */
-
-
-/*---------------------------------
-
-  qh_partitioncoplanar( point, facet, dist )
-    partition coplanar point to a facet
-    dist is distance from point to facet
-    if dist NULL,
-      searches for bestfacet and does nothing if inside
-    if qh.findbestnew set,
-      searches new facets instead of using qh_findbest()
-
-  returns:
-    qh.max_ouside updated
-    if qh.KEEPcoplanar or qh.KEEPinside
-      point assigned to best coplanarset
-
-  notes:
-    facet->maxoutside is updated at end by qh_check_maxout
-
-  design:
-    if dist undefined
-      find best facet for point
-      if point sufficiently below facet (depends on qh.NEARinside and qh.KEEPinside)
-        exit
-    if keeping coplanar/nearinside/inside points
-      if point is above furthest coplanar point
-        append point to coplanar set (it is the new furthest)
-        update qh.max_outside
-      else
-        append point one before end of coplanar set
-    else if point is clearly outside of qh.max_outside and bestfacet->coplanarset
-    and bestfacet is more than perpendicular to facet
-      repartition the point using qh_findbest() -- it may be put on an outsideset
-    else
-      update qh.max_outside
-*/
-void qh_partitioncoplanar(pointT *point, facetT *facet, realT *dist) {
-  facetT *bestfacet;
-  pointT *oldfurthest;
-  realT bestdist, dist2= 0, angle;
-  int numpart= 0, oldfindbest;
-  boolT isoutside;
-
-  qh WAScoplanar= True;
-  if (!dist) {
-    if (qh findbestnew)
-      bestfacet= qh_findbestnew(point, facet, &bestdist, qh_ALL, &isoutside, &numpart);
-    else
-      bestfacet= qh_findbest(point, facet, qh_ALL, !qh_ISnewfacets, qh DELAUNAY,
-                          &bestdist, &isoutside, &numpart);
-    zinc_(Ztotpartcoplanar);
-    zzadd_(Zpartcoplanar, numpart);
-    if (!qh DELAUNAY && !qh KEEPinside) { /*  for 'd', bestdist skips upperDelaunay facets */
-      if (qh KEEPnearinside) {
-        if (bestdist < -qh NEARinside) {
-          zinc_(Zcoplanarinside);
-          trace4((qh ferr, 4062, "qh_partitioncoplanar: point p%d is more than near-inside facet f%d dist %2.2g findbestnew %d\n",
-                  qh_pointid(point), bestfacet->id, bestdist, qh findbestnew));
-          return;
-        }
-      }else if (bestdist < -qh MAXcoplanar) {
-          trace4((qh ferr, 4063, "qh_partitioncoplanar: point p%d is inside facet f%d dist %2.2g findbestnew %d\n",
-                  qh_pointid(point), bestfacet->id, bestdist, qh findbestnew));
-        zinc_(Zcoplanarinside);
-        return;
-      }
-    }
-  }else {
-    bestfacet= facet;
-    bestdist= *dist;
-  }
-  if (bestdist > qh max_outside) {
-    if (!dist && facet != bestfacet) {
-      zinc_(Zpartangle);
-      angle= qh_getangle(facet->normal, bestfacet->normal);
-      if (angle < 0) {
-        /* typically due to deleted vertex and coplanar facets, e.g.,
-             RBOX 1000 s Z1 G1e-13 t1001185205 | QHULL Tv */
-        zinc_(Zpartflip);
-        trace2((qh ferr, 2058, "qh_partitioncoplanar: repartition point p%d from f%d.  It is above flipped facet f%d dist %2.2g\n",
-                qh_pointid(point), facet->id, bestfacet->id, bestdist));
-        oldfindbest= qh findbestnew;
-        qh findbestnew= False;
-        qh_partitionpoint(point, bestfacet);
-        qh findbestnew= oldfindbest;
-        return;
-      }
-    }
-    qh max_outside= bestdist;
-    if (bestdist > qh TRACEdist) {
-      qh_fprintf(qh ferr, 8122, "qh_partitioncoplanar: ====== p%d from f%d increases max_outside to %2.2g of f%d last p%d\n",
-                     qh_pointid(point), facet->id, bestdist, bestfacet->id, qh furthest_id);
-      qh_errprint("DISTANT", facet, bestfacet, NULL, NULL);
-    }
-  }
-  if (qh KEEPcoplanar + qh KEEPinside + qh KEEPnearinside) {
-    oldfurthest= (pointT*)qh_setlast(bestfacet->coplanarset);
-    if (oldfurthest) {
-      zinc_(Zcomputefurthest);
-      qh_distplane(oldfurthest, bestfacet, &dist2);
-    }
-    if (!oldfurthest || dist2 < bestdist)
-      qh_setappend(&bestfacet->coplanarset, point);
-    else
-      qh_setappend2ndlast(&bestfacet->coplanarset, point);
-  }
-  trace4((qh ferr, 4064, "qh_partitioncoplanar: point p%d is coplanar with facet f%d(or inside) dist %2.2g\n",
-          qh_pointid(point), bestfacet->id, bestdist));
-} /* partitioncoplanar */
-
-/*---------------------------------
-
-  qh_partitionpoint( point, facet )
-    assigns point to an outside set, coplanar set, or inside set (i.e., dropt)
-    if qh.findbestnew
-      uses qh_findbestnew() to search all new facets
-    else
-      uses qh_findbest()
-
-  notes:
-    after qh_distplane(), this and qh_findbest() are most expensive in 3-d
-
-  design:
-    find best facet for point
-      (either exhaustive search of new facets or directed search from facet)
-    if qh.NARROWhull
-      retain coplanar and nearinside points as outside points
-    if point is outside bestfacet
-      if point above furthest point for bestfacet
-        append point to outside set (it becomes the new furthest)
-        if outside set was empty
-          move bestfacet to end of qh.facet_list (i.e., after qh.facet_next)
-        update bestfacet->furthestdist
-      else
-        append point one before end of outside set
-    else if point is coplanar to bestfacet
-      if keeping coplanar points or need to update qh.max_outside
-        partition coplanar point into bestfacet
-    else if near-inside point
-      partition as coplanar point into bestfacet
-    else is an inside point
-      if keeping inside points
-        partition as coplanar point into bestfacet
-*/
-void qh_partitionpoint(pointT *point, facetT *facet) {
-  realT bestdist;
-  boolT isoutside;
-  facetT *bestfacet;
-  int numpart;
-#if qh_COMPUTEfurthest
-  realT dist;
-#endif
-
-  if (qh findbestnew)
-    bestfacet= qh_findbestnew(point, facet, &bestdist, qh BESToutside, &isoutside, &numpart);
-  else
-    bestfacet= qh_findbest(point, facet, qh BESToutside, qh_ISnewfacets, !qh_NOupper,
-                          &bestdist, &isoutside, &numpart);
-  zinc_(Ztotpartition);
-  zzadd_(Zpartition, numpart);
-  if (qh NARROWhull) {
-    if (qh DELAUNAY && !isoutside && bestdist >= -qh MAXcoplanar)
-      qh_precision("nearly incident point(narrow hull)");
-    if (qh KEEPnearinside) {
-      if (bestdist >= -qh NEARinside)
-        isoutside= True;
-    }else if (bestdist >= -qh MAXcoplanar)
-      isoutside= True;
-  }
-
-  if (isoutside) {
-    if (!bestfacet->outsideset
-    || !qh_setlast(bestfacet->outsideset)) {
-      qh_setappend(&(bestfacet->outsideset), point);
-      if (!bestfacet->newfacet) {
-        qh_removefacet(bestfacet);  /* make sure it's after qh facet_next */
-        qh_appendfacet(bestfacet);
-      }
-#if !qh_COMPUTEfurthest
-      bestfacet->furthestdist= bestdist;
-#endif
-    }else {
-#if qh_COMPUTEfurthest
-      zinc_(Zcomputefurthest);
-      qh_distplane(oldfurthest, bestfacet, &dist);
-      if (dist < bestdist)
-        qh_setappend(&(bestfacet->outsideset), point);
-      else
-        qh_setappend2ndlast(&(bestfacet->outsideset), point);
-#else
-      if (bestfacet->furthestdist < bestdist) {
-        qh_setappend(&(bestfacet->outsideset), point);
-        bestfacet->furthestdist= bestdist;
-      }else
-        qh_setappend2ndlast(&(bestfacet->outsideset), point);
-#endif
-    }
-    qh num_outside++;
-    trace4((qh ferr, 4065, "qh_partitionpoint: point p%d is outside facet f%d new? %d (or narrowhull)\n",
-          qh_pointid(point), bestfacet->id, bestfacet->newfacet));
-  }else if (qh DELAUNAY || bestdist >= -qh MAXcoplanar) { /* for 'd', bestdist skips upperDelaunay facets */
-    zzinc_(Zcoplanarpart);
-    if (qh DELAUNAY)
-      qh_precision("nearly incident point");
-    if ((qh KEEPcoplanar + qh KEEPnearinside) || bestdist > qh max_outside)
-      qh_partitioncoplanar(point, bestfacet, &bestdist);
-    else {
-      trace4((qh ferr, 4066, "qh_partitionpoint: point p%d is coplanar to facet f%d (dropped)\n",
-          qh_pointid(point), bestfacet->id));
-    }
-  }else if (qh KEEPnearinside && bestdist > -qh NEARinside) {
-    zinc_(Zpartnear);
-    qh_partitioncoplanar(point, bestfacet, &bestdist);
-  }else {
-    zinc_(Zpartinside);
-    trace4((qh ferr, 4067, "qh_partitionpoint: point p%d is inside all facets, closest to f%d dist %2.2g\n",
-          qh_pointid(point), bestfacet->id, bestdist));
-    if (qh KEEPinside)
-      qh_partitioncoplanar(point, bestfacet, &bestdist);
-  }
-} /* partitionpoint */
-
-/*---------------------------------
-
-  qh_partitionvisible( allpoints, numoutside )
-    partitions points in visible facets to qh.newfacet_list
-    qh.visible_list= visible facets
-    for visible facets
-      1st neighbor (if any) points to a horizon facet or a new facet
-    if allpoints(!used),
-      repartitions coplanar points
-
-  returns:
-    updates outside sets and coplanar sets of qh.newfacet_list
-    updates qh.num_outside (count of outside points)
-
-  notes:
-    qh.findbest_notsharp should be clear (extra work if set)
-
-  design:
-    for all visible facets with outside set or coplanar set
-      select a newfacet for visible facet
-      if outside set
-        partition outside set into new facets
-      if coplanar set and keeping coplanar/near-inside/inside points
-        if allpoints
-          partition coplanar set into new facets, may be assigned outside
-        else
-          partition coplanar set into coplanar sets of new facets
-    for each deleted vertex
-      if allpoints
-        partition vertex into new facets, may be assigned outside
-      else
-        partition vertex into coplanar sets of new facets
-*/
-void qh_partitionvisible(/*qh.visible_list*/ boolT allpoints, int *numoutside) {
-  facetT *visible, *newfacet;
-  pointT *point, **pointp;
-  int coplanar=0, size;
-  unsigned count;
-  vertexT *vertex, **vertexp;
-
-  if (qh ONLYmax)
-    maximize_(qh MINoutside, qh max_vertex);
-  *numoutside= 0;
-  FORALLvisible_facets {
-    if (!visible->outsideset && !visible->coplanarset)
-      continue;
-    newfacet= visible->f.replace;
-    count= 0;
-    while (newfacet && newfacet->visible) {
-      newfacet= newfacet->f.replace;
-      if (count++ > qh facet_id)
-        qh_infiniteloop(visible);
-    }
-    if (!newfacet)
-      newfacet= qh newfacet_list;
-    if (newfacet == qh facet_tail) {
-      qh_fprintf(qh ferr, 6170, "qhull precision error (qh_partitionvisible): all new facets deleted as\n        degenerate facets. Can not continue.\n");
-      qh_errexit(qh_ERRprec, NULL, NULL);
-    }
-    if (visible->outsideset) {
-      size= qh_setsize(visible->outsideset);
-      *numoutside += size;
-      qh num_outside -= size;
-      FOREACHpoint_(visible->outsideset)
-        qh_partitionpoint(point, newfacet);
-    }
-    if (visible->coplanarset && (qh KEEPcoplanar + qh KEEPinside + qh KEEPnearinside)) {
-      size= qh_setsize(visible->coplanarset);
-      coplanar += size;
-      FOREACHpoint_(visible->coplanarset) {
-        if (allpoints) /* not used */
-          qh_partitionpoint(point, newfacet);
-        else
-          qh_partitioncoplanar(point, newfacet, NULL);
-      }
-    }
-  }
-  FOREACHvertex_(qh del_vertices) {
-    if (vertex->point) {
-      if (allpoints) /* not used */
-        qh_partitionpoint(vertex->point, qh newfacet_list);
-      else
-        qh_partitioncoplanar(vertex->point, qh newfacet_list, NULL);
-    }
-  }
-  trace1((qh ferr, 1043,"qh_partitionvisible: partitioned %d points from outsidesets and %d points from coplanarsets\n", *numoutside, coplanar));
-} /* partitionvisible */
-
-
-
-/*---------------------------------
-
-  qh_precision( reason )
-    restart on precision errors if not merging and if 'QJn'
-*/
-void qh_precision(const char *reason) {
-
-  if (qh ALLOWrestart && !qh PREmerge && !qh MERGEexact) {
-    if (qh JOGGLEmax < REALmax/2) {
-      trace0((qh ferr, 26, "qh_precision: qhull restart because of %s\n", reason));
-      /* May be called repeatedly if qh->ALLOWrestart */
-      longjmp(qh restartexit, qh_ERRprec);
-    }
-  }
-} /* qh_precision */
-
-/*---------------------------------
-
-  qh_printsummary( fp )
-    prints summary to fp
-
-  notes:
-    not in io.c so that user_eg.c can prevent io.c from loading
-    qh_printsummary and qh_countfacets must match counts
-
-  design:
-    determine number of points, vertices, and coplanar points
-    print summary
-*/
-void qh_printsummary(FILE *fp) {
-  realT ratio, outerplane, innerplane;
-  float cpu;
-  int size, id, nummerged, numvertices, numcoplanars= 0, nonsimplicial=0;
-  int goodused;
-  facetT *facet;
-  const char *s;
-  int numdel= zzval_(Zdelvertextot);
-  int numtricoplanars= 0;
-
-  size= qh num_points + qh_setsize(qh other_points);
-  numvertices= qh num_vertices - qh_setsize(qh del_vertices);
-  id= qh_pointid(qh GOODpointp);
-  FORALLfacets {
-    if (facet->coplanarset)
-      numcoplanars += qh_setsize( facet->coplanarset);
-    if (facet->good) {
-      if (facet->simplicial) {
-        if (facet->keepcentrum && facet->tricoplanar)
-          numtricoplanars++;
-      }else if (qh_setsize(facet->vertices) != qh hull_dim)
-        nonsimplicial++;
-    }
-  }
-  if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id)
-    size--;
-  if (qh STOPcone || qh STOPpoint)
-      qh_fprintf(fp, 9288, "\nAt a premature exit due to 'TVn', 'TCn', 'TRn', or precision error with 'QJn'.");
-  if (qh UPPERdelaunay)
-    goodused= qh GOODvertex + qh GOODpoint + qh SPLITthresholds;
-  else if (qh DELAUNAY)
-    goodused= qh GOODvertex + qh GOODpoint + qh GOODthreshold;
-  else
-    goodused= qh num_good;
-  nummerged= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
-  if (qh VORONOI) {
-    if (qh UPPERdelaunay)
-      qh_fprintf(fp, 9289, "\n\
-Furthest-site Voronoi vertices by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
-    else
-      qh_fprintf(fp, 9290, "\n\
-Voronoi diagram by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
-    qh_fprintf(fp, 9291, "  Number of Voronoi regions%s: %d\n",
-              qh ATinfinity ? " and at-infinity" : "", numvertices);
-    if (numdel)
-      qh_fprintf(fp, 9292, "  Total number of deleted points due to merging: %d\n", numdel);
-    if (numcoplanars - numdel > 0)
-      qh_fprintf(fp, 9293, "  Number of nearly incident points: %d\n", numcoplanars - numdel);
-    else if (size - numvertices - numdel > 0)
-      qh_fprintf(fp, 9294, "  Total number of nearly incident points: %d\n", size - numvertices - numdel);
-    qh_fprintf(fp, 9295, "  Number of%s Voronoi vertices: %d\n",
-              goodused ? " 'good'" : "", qh num_good);
-    if (nonsimplicial)
-      qh_fprintf(fp, 9296, "  Number of%s non-simplicial Voronoi vertices: %d\n",
-              goodused ? " 'good'" : "", nonsimplicial);
-  }else if (qh DELAUNAY) {
-    if (qh UPPERdelaunay)
-      qh_fprintf(fp, 9297, "\n\
-Furthest-site Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
-    else
-      qh_fprintf(fp, 9298, "\n\
-Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
-    qh_fprintf(fp, 9299, "  Number of input sites%s: %d\n",
-              qh ATinfinity ? " and at-infinity" : "", numvertices);
-    if (numdel)
-      qh_fprintf(fp, 9300, "  Total number of deleted points due to merging: %d\n", numdel);
-    if (numcoplanars - numdel > 0)
-      qh_fprintf(fp, 9301, "  Number of nearly incident points: %d\n", numcoplanars - numdel);
-    else if (size - numvertices - numdel > 0)
-      qh_fprintf(fp, 9302, "  Total number of nearly incident points: %d\n", size - numvertices - numdel);
-    qh_fprintf(fp, 9303, "  Number of%s Delaunay regions: %d\n",
-              goodused ? " 'good'" : "", qh num_good);
-    if (nonsimplicial)
-      qh_fprintf(fp, 9304, "  Number of%s non-simplicial Delaunay regions: %d\n",
-              goodused ? " 'good'" : "", nonsimplicial);
-  }else if (qh HALFspace) {
-    qh_fprintf(fp, 9305, "\n\
-Halfspace intersection by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
-    qh_fprintf(fp, 9306, "  Number of halfspaces: %d\n", size);
-    qh_fprintf(fp, 9307, "  Number of non-redundant halfspaces: %d\n", numvertices);
-    if (numcoplanars) {
-      if (qh KEEPinside && qh KEEPcoplanar)
-        s= "similar and redundant";
-      else if (qh KEEPinside)
-        s= "redundant";
-      else
-        s= "similar";
-      qh_fprintf(fp, 9308, "  Number of %s halfspaces: %d\n", s, numcoplanars);
-    }
-    qh_fprintf(fp, 9309, "  Number of intersection points: %d\n", qh num_facets - qh num_visible);
-    if (goodused)
-      qh_fprintf(fp, 9310, "  Number of 'good' intersection points: %d\n", qh num_good);
-    if (nonsimplicial)
-      qh_fprintf(fp, 9311, "  Number of%s non-simplicial intersection points: %d\n",
-              goodused ? " 'good'" : "", nonsimplicial);
-  }else {
-    qh_fprintf(fp, 9312, "\n\
-Convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
-    qh_fprintf(fp, 9313, "  Number of vertices: %d\n", numvertices);
-    if (numcoplanars) {
-      if (qh KEEPinside && qh KEEPcoplanar)
-        s= "coplanar and interior";
-      else if (qh KEEPinside)
-        s= "interior";
-      else
-        s= "coplanar";
-      qh_fprintf(fp, 9314, "  Number of %s points: %d\n", s, numcoplanars);
-    }
-    qh_fprintf(fp, 9315, "  Number of facets: %d\n", qh num_facets - qh num_visible);
-    if (goodused)
-      qh_fprintf(fp, 9316, "  Number of 'good' facets: %d\n", qh num_good);
-    if (nonsimplicial)
-      qh_fprintf(fp, 9317, "  Number of%s non-simplicial facets: %d\n",
-              goodused ? " 'good'" : "", nonsimplicial);
-  }
-  if (numtricoplanars)
-      qh_fprintf(fp, 9318, "  Number of triangulated facets: %d\n", numtricoplanars);
-  qh_fprintf(fp, 9319, "\nStatistics for: %s | %s",
-                      qh rbox_command, qh qhull_command);
-  if (qh ROTATErandom != INT_MIN)
-    qh_fprintf(fp, 9320, " QR%d\n\n", qh ROTATErandom);
-  else
-    qh_fprintf(fp, 9321, "\n\n");
-  qh_fprintf(fp, 9322, "  Number of points processed: %d\n", zzval_(Zprocessed));
-  qh_fprintf(fp, 9323, "  Number of hyperplanes created: %d\n", zzval_(Zsetplane));
-  if (qh DELAUNAY)
-    qh_fprintf(fp, 9324, "  Number of facets in hull: %d\n", qh num_facets - qh num_visible);
-  qh_fprintf(fp, 9325, "  Number of distance tests for qhull: %d\n", zzval_(Zpartition)+
-      zzval_(Zpartitionall)+zzval_(Znumvisibility)+zzval_(Zpartcoplanar));
-#if 0  /* NOTE: must print before printstatistics() */
-  {realT stddev, ave;
-  qh_fprintf(fp, 9326, "  average new facet balance: %2.2g\n",
-          wval_(Wnewbalance)/zval_(Zprocessed));
-  stddev= qh_stddev(zval_(Zprocessed), wval_(Wnewbalance),
-                                 wval_(Wnewbalance2), &ave);
-  qh_fprintf(fp, 9327, "  new facet standard deviation: %2.2g\n", stddev);
-  qh_fprintf(fp, 9328, "  average partition balance: %2.2g\n",
-          wval_(Wpbalance)/zval_(Zpbalance));
-  stddev= qh_stddev(zval_(Zpbalance), wval_(Wpbalance),
-                                 wval_(Wpbalance2), &ave);
-  qh_fprintf(fp, 9329, "  partition standard deviation: %2.2g\n", stddev);
-  }
-#endif
-  if (nummerged) {
-    qh_fprintf(fp, 9330,"  Number of distance tests for merging: %d\n",zzval_(Zbestdist)+
-          zzval_(Zcentrumtests)+zzval_(Zdistconvex)+zzval_(Zdistcheck)+
-          zzval_(Zdistzero));
-    qh_fprintf(fp, 9331,"  Number of distance tests for checking: %d\n",zzval_(Zcheckpart));
-    qh_fprintf(fp, 9332,"  Number of merged facets: %d\n", nummerged);
-  }
-  if (!qh RANDOMoutside && qh QHULLfinished) {
-    cpu= (float)qh hulltime;
-    cpu /= (float)qh_SECticks;
-    wval_(Wcpu)= cpu;
-    qh_fprintf(fp, 9333, "  CPU seconds to compute hull (after input): %2.4g\n", cpu);
-  }
-  if (qh RERUN) {
-    if (!qh PREmerge && !qh MERGEexact)
-      qh_fprintf(fp, 9334, "  Percentage of runs with precision errors: %4.1f\n",
-           zzval_(Zretry)*100.0/qh build_cnt);  /* careful of order */
-  }else if (qh JOGGLEmax < REALmax/2) {
-    if (zzval_(Zretry))
-      qh_fprintf(fp, 9335, "  After %d retries, input joggled by: %2.2g\n",
-         zzval_(Zretry), qh JOGGLEmax);
-    else
-      qh_fprintf(fp, 9336, "  Input joggled by: %2.2g\n", qh JOGGLEmax);
-  }
-  if (qh totarea != 0.0)
-    qh_fprintf(fp, 9337, "  %s facet area:   %2.8g\n",
-            zzval_(Ztotmerge) ? "Approximate" : "Total", qh totarea);
-  if (qh totvol != 0.0)
-    qh_fprintf(fp, 9338, "  %s volume:       %2.8g\n",
-            zzval_(Ztotmerge) ? "Approximate" : "Total", qh totvol);
-  if (qh MERGING) {
-    qh_outerinner(NULL, &outerplane, &innerplane);
-    if (outerplane > 2 * qh DISTround) {
-      qh_fprintf(fp, 9339, "  Maximum distance of %spoint above facet: %2.2g",
-            (qh QHULLfinished ? "" : "merged "), outerplane);
-      ratio= outerplane/(qh ONEmerge + qh DISTround);
-      /* don't report ratio if MINoutside is large */
-      if (ratio > 0.05 && 2* qh ONEmerge > qh MINoutside && qh JOGGLEmax > REALmax/2)
-        qh_fprintf(fp, 9340, " (%.1fx)\n", ratio);
-      else
-        qh_fprintf(fp, 9341, "\n");
-    }
-    if (innerplane < -2 * qh DISTround) {
-      qh_fprintf(fp, 9342, "  Maximum distance of %svertex below facet: %2.2g",
-            (qh QHULLfinished ? "" : "merged "), innerplane);
-      ratio= -innerplane/(qh ONEmerge+qh DISTround);
-      if (ratio > 0.05 && qh JOGGLEmax > REALmax/2)
-        qh_fprintf(fp, 9343, " (%.1fx)\n", ratio);
-      else
-        qh_fprintf(fp, 9344, "\n");
-    }
-  }
-  qh_fprintf(fp, 9345, "\n");
-} /* printsummary */
-
-
diff --git a/extern/libqhull/libqhull.h b/extern/libqhull/libqhull.h
deleted file mode 100644
index 677085808d54..000000000000
--- a/extern/libqhull/libqhull.h
+++ /dev/null
@@ -1,1140 +0,0 @@
-/*
  ---------------------------------
-
-   libqhull.h
-   user-level header file for using qhull.a library
-
-   see qh-qhull.htm, qhull_a.h
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/libqhull.h#7 $$Change: 2066 $
-   $DateTime: 2016/01/18 19:29:17 $$Author: bbarber $
-
-   NOTE: access to qh_qh is via the 'qh' macro.  This allows
-   qh_qh to be either a pointer or a structure.  An example
-   of using qh is "qh.DROPdim" which accesses the DROPdim
-   field of qh_qh.  Similarly, access to qh_qhstat is via
-   the 'qhstat' macro.
-
-   includes function prototypes for libqhull.c, geom.c, global.c, io.c, user.c
-
-   use mem.h for mem.c
-   use qset.h for qset.c
-
-   see unix.c for an example of using libqhull.h
-
-   recompile qhull if you change this file
-*/
-
-#ifndef qhDEFlibqhull
-#define qhDEFlibqhull 1
-
-/*=========================== -included files ==============*/
-
-/* user_r.h first for QHULL_CRTDBG */
-#include "user.h"      /* user definable constants (e.g., qh_QHpointer) */
-
-#include "mem.h"   /* Needed qhT in libqhull_r.h.  Here for compatibility */
-#include "qset.h"   /* Needed for QHULL_LIB_CHECK */
-/* include stat_r.h after defining boolT.  Needed for qhT in libqhull_r.h.  Here for compatibility and statT */
-
-#include 
-#include 
-#include 
-#include 
-
-#if __MWERKS__ && __POWERPC__
-#include  
-#include  
-#include        
-#endif
-
-#ifndef __STDC__
-#ifndef __cplusplus
-#if     !_MSC_VER
-#error  Neither __STDC__ nor __cplusplus is defined.  Please use strict ANSI C or C++ to compile
-#error  Qhull.  You may need to turn off compiler extensions in your project configuration.  If
-#error  your compiler is a standard C compiler, you can delete this warning from libqhull.h
-#endif
-#endif
-#endif
-
-/*============ constants and basic types ====================*/
-
-extern const char qh_version[]; /* defined in global.c */
-extern const char qh_version2[]; /* defined in global.c */
-
-/*----------------------------------
-
-  coordT
-    coordinates and coefficients are stored as realT (i.e., double)
-
-  notes:
-    Qhull works well if realT is 'float'.  If so joggle (QJ) is not effective.
-
-    Could use 'float' for data and 'double' for calculations (realT vs. coordT)
-      This requires many type casts, and adjusted error bounds.
-      Also C compilers may do expressions in double anyway.
-*/
-#define coordT realT
-
-/*----------------------------------
-
-  pointT
-    a point is an array of coordinates, usually qh.hull_dim
-    qh_pointid returns
-      qh_IDnone if point==0 or qh is undefined
-      qh_IDinterior for qh.interior_point
-      qh_IDunknown if point is neither in qh.first_point... nor qh.other_points
-
-  notes:
-    qh.STOPcone and qh.STOPpoint assume that qh_IDunknown==-1 (other negative numbers indicate points)
-    qh_IDunknown is also returned by getid_() for unknown facet, ridge, or vertex
-*/
-#define pointT coordT
-typedef enum
-{
-    qh_IDnone = -3, qh_IDinterior = -2, qh_IDunknown = -1
-}
-qh_pointT;
-
-/*----------------------------------
-
-  flagT
-    Boolean flag as a bit
-*/
-#define flagT unsigned int
-
-/*----------------------------------
-
-  boolT
-    boolean value, either True or False
-
-  notes:
-    needed for portability
-    Use qh_False/qh_True as synonyms
-*/
-#define boolT unsigned int
-#ifdef False
-#undef False
-#endif
-#ifdef True
-#undef True
-#endif
-#define False 0
-#define True 1
-#define qh_False 0
-#define qh_True 1
-
-#include "stat.h"  /* after define of boolT */
-
-/*----------------------------------
-
-  qh_CENTER
-    to distinguish facet->center
-*/
-typedef enum
-{
-    qh_ASnone = 0,   /* If not MERGING and not VORONOI */
-    qh_ASvoronoi,    /* Set by qh_clearcenters on qh_prepare_output, or if not MERGING and VORONOI */
-    qh_AScentrum     /* If MERGING (assumed during merging) */
-}
-qh_CENTER;
-
-/*----------------------------------
-
-  qh_PRINT
-    output formats for printing (qh.PRINTout).
-    'Fa' 'FV' 'Fc' 'FC'
-
-
-   notes:
-   some of these names are similar to qhT names.  The similar names are only
-   used in switch statements in qh_printbegin() etc.
-*/
-typedef enum {qh_PRINTnone= 0,
-  qh_PRINTarea, qh_PRINTaverage,           /* 'Fa' 'FV' 'Fc' 'FC' */
-  qh_PRINTcoplanars, qh_PRINTcentrums,
-  qh_PRINTfacets, qh_PRINTfacets_xridge,   /* 'f' 'FF' 'G' 'FI' 'Fi' 'Fn' */
-  qh_PRINTgeom, qh_PRINTids, qh_PRINTinner, qh_PRINTneighbors,
-  qh_PRINTnormals, qh_PRINTouter, qh_PRINTmaple, /* 'n' 'Fo' 'i' 'm' 'Fm' 'FM', 'o' */
-  qh_PRINTincidences, qh_PRINTmathematica, qh_PRINTmerges, qh_PRINToff,
-  qh_PRINToptions, qh_PRINTpointintersect, /* 'FO' 'Fp' 'FP' 'p' 'FQ' 'FS' */
-  qh_PRINTpointnearest, qh_PRINTpoints, qh_PRINTqhull, qh_PRINTsize,
-  qh_PRINTsummary, qh_PRINTtriangles,      /* 'Fs' 'Ft' 'Fv' 'FN' 'Fx' */
-  qh_PRINTvertices, qh_PRINTvneighbors, qh_PRINTextremes,
-  qh_PRINTEND} qh_PRINT;
-
-/*----------------------------------
-
-  qh_ALL
-    argument flag for selecting everything
-*/
-#define qh_ALL      True
-#define qh_NOupper  True     /* argument for qh_findbest */
-#define qh_IScheckmax  True     /* argument for qh_findbesthorizon */
-#define qh_ISnewfacets  True     /* argument for qh_findbest */
-#define qh_RESETvisible  True     /* argument for qh_resetlists */
-
-/*----------------------------------
-
-  qh_ERR
-    Qhull exit codes, for indicating errors
-    See: MSG_ERROR and MSG_WARNING [user.h]
-*/
-#define qh_ERRnone  0    /* no error occurred during qhull */
-#define qh_ERRinput 1    /* input inconsistency */
-#define qh_ERRsingular 2 /* singular input data */
-#define qh_ERRprec  3    /* precision error */
-#define qh_ERRmem   4    /* insufficient memory, matches mem.h */
-#define qh_ERRqhull 5    /* internal error detected, matches mem.h */
-
-/*----------------------------------
-
-qh_FILEstderr
-Fake stderr to distinguish error output from normal output
-For C++ interface.  Must redefine qh_fprintf_qhull
-*/
-#define qh_FILEstderr ((FILE*)1)
-
-/* ============ -structures- ====================
-   each of the following structures is defined by a typedef
-   all realT and coordT fields occur at the beginning of a structure
-        (otherwise space may be wasted due to alignment)
-   define all flags together and pack into 32-bit number
-   DEFsetT is likewise defined in
-   mem.h and qset.h
-*/
-
-typedef struct vertexT vertexT;
-typedef struct ridgeT ridgeT;
-typedef struct facetT facetT;
-#ifndef DEFsetT
-#define DEFsetT 1
-typedef struct setT setT;          /* defined in qset.h */
-#endif
-
-/*----------------------------------
-
-  facetT
-    defines a facet
-
-  notes:
-   qhull() generates the hull as a list of facets.
-
-  topological information:
-    f.previous,next     doubly-linked list of facets
-    f.vertices          set of vertices
-    f.ridges            set of ridges
-    f.neighbors         set of neighbors
-    f.toporient         True if facet has top-orientation (else bottom)
-
-  geometric information:
-    f.offset,normal     hyperplane equation
-    f.maxoutside        offset to outer plane -- all points inside
-    f.center            centrum for testing convexity
-    f.simplicial        True if facet is simplicial
-    f.flipped           True if facet does not include qh.interior_point
-
-  for constructing hull:
-    f.visible           True if facet on list of visible facets (will be deleted)
-    f.newfacet          True if facet on list of newly created facets
-    f.coplanarset       set of points coplanar with this facet
-                        (includes near-inside points for later testing)
-    f.outsideset        set of points outside of this facet
-    f.furthestdist      distance to furthest point of outside set
-    f.visitid           marks visited facets during a loop
-    f.replace           replacement facet for to-be-deleted, visible facets
-    f.samecycle,newcycle cycle of facets for merging into horizon facet
-
-  see below for other flags and fields
-*/
-struct facetT {
-#if !qh_COMPUTEfurthest
-  coordT   furthestdist;/* distance to furthest point of outsideset */
-#endif
-#if qh_MAXoutside
-  coordT   maxoutside;  /* max computed distance of point to facet
-                        Before QHULLfinished this is an approximation
-                        since maxdist not always set for mergefacet
-                        Actual outer plane is +DISTround and
-                        computed outer plane is +2*DISTround */
-#endif
-  coordT   offset;      /* exact offset of hyperplane from origin */
-  coordT  *normal;      /* normal of hyperplane, hull_dim coefficients */
-                        /*   if tricoplanar, shared with a neighbor */
-  union {               /* in order of testing */
-   realT   area;        /* area of facet, only in io.c if  ->isarea */
-   facetT *replace;     /*  replacement facet if ->visible and NEWfacets
-                             is NULL only if qh_mergedegen_redundant or interior */
-   facetT *samecycle;   /*  cycle of facets from the same visible/horizon intersection,
-                             if ->newfacet */
-   facetT *newcycle;    /*  in horizon facet, current samecycle of new facets */
-   facetT *trivisible;  /* visible facet for ->tricoplanar facets during qh_triangulate() */
-   facetT *triowner;    /* owner facet for ->tricoplanar, !isarea facets w/ ->keepcentrum */
-  }f;
-  coordT  *center;      /* set according to qh.CENTERtype */
-                        /*   qh_ASnone:    no center (not MERGING) */
-                        /*   qh_AScentrum: centrum for testing convexity (qh_getcentrum) */
-                        /*                 assumed qh_AScentrum while merging */
-                        /*   qh_ASvoronoi: Voronoi center (qh_facetcenter) */
-                        /* after constructing the hull, it may be changed (qh_clearcenter) */
-                        /* if tricoplanar and !keepcentrum, shared with a neighbor */
-  facetT  *previous;    /* previous facet in the facet_list */
-  facetT  *next;        /* next facet in the facet_list */
-  setT    *vertices;    /* vertices for this facet, inverse sorted by ID
-                           if simplicial, 1st vertex was apex/furthest */
-  setT    *ridges;      /* explicit ridges for nonsimplicial facets.
-                           for simplicial facets, neighbors define the ridges */
-  setT    *neighbors;   /* neighbors of the facet.  If simplicial, the kth
-                           neighbor is opposite the kth vertex, and the first
-                           neighbor is the horizon facet for the first vertex*/
-  setT    *outsideset;  /* set of points outside this facet
-                           if non-empty, last point is furthest
-                           if NARROWhull, includes coplanars for partitioning*/
-  setT    *coplanarset; /* set of points coplanar with this facet
-                           > qh.min_vertex and <= facet->max_outside
-                           a point is assigned to the furthest facet
-                           if non-empty, last point is furthest away */
-  unsigned visitid;     /* visit_id, for visiting all neighbors,
-                           all uses are independent */
-  unsigned id;          /* unique identifier from qh.facet_id */
-  unsigned nummerge:9;  /* number of merges */
-#define qh_MAXnummerge 511 /*     2^9-1, 32 flags total, see "flags:" in io.c */
-  flagT    tricoplanar:1; /* True if TRIangulate and simplicial and coplanar with a neighbor */
-                          /*   all tricoplanars share the same apex */
-                          /*   all tricoplanars share the same ->center, ->normal, ->offset, ->maxoutside */
-                          /*     ->keepcentrum is true for the owner.  It has the ->coplanareset */
-                          /*   if ->degenerate, does not span facet (one logical ridge) */
-                          /*   during qh_triangulate, f.trivisible points to original facet */
-  flagT    newfacet:1;  /* True if facet on qh.newfacet_list (new or merged) */
-  flagT    visible:1;   /* True if visible facet (will be deleted) */
-  flagT    toporient:1; /* True if created with top orientation
-                           after merging, use ridge orientation */
-  flagT    simplicial:1;/* True if simplicial facet, ->ridges may be implicit */
-  flagT    seen:1;      /* used to perform operations only once, like visitid */
-  flagT    seen2:1;     /* used to perform operations only once, like visitid */
-  flagT    flipped:1;   /* True if facet is flipped */
-  flagT    upperdelaunay:1; /* True if facet is upper envelope of Delaunay triangulation */
-  flagT    notfurthest:1; /* True if last point of outsideset is not furthest*/
-
-/*-------- flags primarily for output ---------*/
-  flagT    good:1;      /* True if a facet marked good for output */
-  flagT    isarea:1;    /* True if facet->f.area is defined */
-
-/*-------- flags for merging ------------------*/
-  flagT    dupridge:1;  /* True if duplicate ridge in facet */
-  flagT    mergeridge:1; /* True if facet or neighbor contains a qh_MERGEridge
-                            ->normal defined (also defined for mergeridge2) */
-  flagT    mergeridge2:1; /* True if neighbor contains a qh_MERGEridge (mark_dupridges */
-  flagT    coplanar:1;  /* True if horizon facet is coplanar at last use */
-  flagT     mergehorizon:1; /* True if will merge into horizon (->coplanar) */
-  flagT     cycledone:1;/* True if mergecycle_all already done */
-  flagT    tested:1;    /* True if facet convexity has been tested (false after merge */
-  flagT    keepcentrum:1; /* True if keep old centrum after a merge, or marks owner for ->tricoplanar */
-  flagT    newmerge:1;  /* True if facet is newly merged for reducevertices */
-  flagT    degenerate:1; /* True if facet is degenerate (degen_mergeset or ->tricoplanar) */
-  flagT    redundant:1;  /* True if facet is redundant (degen_mergeset) */
-};
-
-
-/*----------------------------------
-
-  ridgeT
-    defines a ridge
-
-  notes:
-  a ridge is hull_dim-1 simplex between two neighboring facets.  If the
-  facets are non-simplicial, there may be more than one ridge between
-  two facets.  E.G. a 4-d hypercube has two triangles between each pair
-  of neighboring facets.
-
-  topological information:
-    vertices            a set of vertices
-    top,bottom          neighboring facets with orientation
-
-  geometric information:
-    tested              True if ridge is clearly convex
-    nonconvex           True if ridge is non-convex
-*/
-struct ridgeT {
-  setT    *vertices;    /* vertices belonging to this ridge, inverse sorted by ID
-                           NULL if a degen ridge (matchsame) */
-  facetT  *top;         /* top facet this ridge is part of */
-  facetT  *bottom;      /* bottom facet this ridge is part of */
-  unsigned id;          /* unique identifier.  Same size as vertex_id and ridge_id */
-  flagT    seen:1;      /* used to perform operations only once */
-  flagT    tested:1;    /* True when ridge is tested for convexity */
-  flagT    nonconvex:1; /* True if getmergeset detected a non-convex neighbor
-                           only one ridge between neighbors may have nonconvex */
-};
-
-/*----------------------------------
-
-  vertexT
-     defines a vertex
-
-  topological information:
-    next,previous       doubly-linked list of all vertices
-    neighbors           set of adjacent facets (only if qh.VERTEXneighbors)
-
-  geometric information:
-    point               array of DIM3 coordinates
-*/
-struct vertexT {
-  vertexT *next;        /* next vertex in vertex_list */
-  vertexT *previous;    /* previous vertex in vertex_list */
-  pointT  *point;       /* hull_dim coordinates (coordT) */
-  setT    *neighbors;   /* neighboring facets of vertex, qh_vertexneighbors()
-                           inits in io.c or after first merge */
-  unsigned id;          /* unique identifier.  Same size as qh.vertex_id and qh.ridge_id */
-  unsigned visitid;     /* for use with qh.vertex_visit, size must match */
-  flagT    seen:1;      /* used to perform operations only once */
-  flagT    seen2:1;     /* another seen flag */
-  flagT    delridge:1;  /* vertex was part of a deleted ridge */
-  flagT    deleted:1;   /* true if vertex on qh.del_vertices */
-  flagT    newlist:1;   /* true if vertex on qh.newvertex_list */
-};
-
-/*======= -global variables -qh ============================*/
-
-/*----------------------------------
-
-  qh
-   all global variables for qhull are in qh, qhmem, and qhstat
-
-  notes:
-   qhmem is defined in mem.h, qhstat is defined in stat.h, qhrbox is defined in rboxpoints.h
-   Access to qh_qh is via the "qh" macro.  See qh_QHpointer in user.h
-
-   All global variables for qhull are in qh, qhmem, and qhstat
-   qh must be unique for each instance of qhull
-   qhstat may be shared between qhull instances.
-   qhmem may be shared across multiple instances of Qhull.
-   Rbox uses global variables rbox_inuse and rbox, but does not persist data across calls.
-
-   Qhull is not multi-threaded.  Global state could be stored in thread-local storage.
-
-   QHULL_LIB_CHECK checks that a program and the corresponding
-   qhull library were built with the same type of header files.
-*/
-
-typedef struct qhT qhT;
-
-#define QHULL_NON_REENTRANT 0
-#define QHULL_QH_POINTER 1
-#define QHULL_REENTRANT 2
-
-#if qh_QHpointer_dllimport
-#define qh qh_qh->
-__declspec(dllimport) extern qhT *qh_qh;     /* allocated in global.c */
-#define QHULL_LIB_TYPE QHULL_QH_POINTER
-
-#elif qh_QHpointer
-#define qh qh_qh->
-extern qhT *qh_qh;     /* allocated in global.c */
-#define QHULL_LIB_TYPE QHULL_QH_POINTER
-
-#elif qh_dllimport
-#define qh qh_qh.
-__declspec(dllimport) extern qhT qh_qh;      /* allocated in global.c */
-#define QHULL_LIB_TYPE QHULL_NON_REENTRANT
-
-#else
-#define qh qh_qh.
-extern qhT qh_qh;
-#define QHULL_LIB_TYPE QHULL_NON_REENTRANT
-#endif
-
-#define QHULL_LIB_CHECK qh_lib_check(QHULL_LIB_TYPE, sizeof(qhT), sizeof(vertexT), sizeof(ridgeT), sizeof(facetT), sizeof(setT), sizeof(qhmemT));
-#define QHULL_LIB_CHECK_RBOX qh_lib_check(QHULL_LIB_TYPE, sizeof(qhT), sizeof(vertexT), sizeof(ridgeT), sizeof(facetT), 0, 0);
-
-struct qhT {
-
-/*----------------------------------
-
-  qh constants
-    configuration flags and constants for Qhull
-
-  notes:
-    The user configures Qhull by defining flags.  They are
-    copied into qh by qh_setflags().  qh-quick.htm#options defines the flags.
-*/
-  boolT ALLpoints;        /* true 'Qs' if search all points for initial simplex */
-  boolT ANGLEmerge;       /* true 'Qa' if sort potential merges by angle */
-  boolT APPROXhull;       /* true 'Wn' if MINoutside set */
-  realT   MINoutside;     /*   'Wn' min. distance for an outside point */
-  boolT ANNOTATEoutput;   /* true 'Ta' if annotate output with message codes */
-  boolT ATinfinity;       /* true 'Qz' if point num_points-1 is "at-infinity"
-                             for improving precision in Delaunay triangulations */
-  boolT AVOIDold;         /* true 'Q4' if avoid old->new merges */
-  boolT BESToutside;      /* true 'Qf' if partition points into best outsideset */
-  boolT CDDinput;         /* true 'Pc' if input uses CDD format (1.0/offset first) */
-  boolT CDDoutput;        /* true 'PC' if print normals in CDD format (offset first) */
-  boolT CHECKfrequently;  /* true 'Tc' if checking frequently */
-  realT premerge_cos;     /*   'A-n'   cos_max when pre merging */
-  realT postmerge_cos;    /*   'An'    cos_max when post merging */
-  boolT DELAUNAY;         /* true 'd' if computing DELAUNAY triangulation */
-  boolT DOintersections;  /* true 'Gh' if print hyperplane intersections */
-  int   DROPdim;          /* drops dim 'GDn' for 4-d -> 3-d output */
-  boolT FORCEoutput;      /* true 'Po' if forcing output despite degeneracies */
-  int   GOODpoint;        /* 1+n for 'QGn', good facet if visible/not(-) from point n*/
-  pointT *GOODpointp;     /*   the actual point */
-  boolT GOODthreshold;    /* true if qh.lower_threshold/upper_threshold defined
-                             false if qh.SPLITthreshold */
-  int   GOODvertex;       /* 1+n, good facet if vertex for point n */
-  pointT *GOODvertexp;     /*   the actual point */
-  boolT HALFspace;        /* true 'Hn,n,n' if halfspace intersection */
-  boolT ISqhullQh;        /* Set by Qhull.cpp on initialization */
-  int   IStracing;        /* trace execution, 0=none, 1=least, 4=most, -1=events */
-  int   KEEParea;         /* 'PAn' number of largest facets to keep */
-  boolT KEEPcoplanar;     /* true 'Qc' if keeping nearest facet for coplanar points */
-  boolT KEEPinside;       /* true 'Qi' if keeping nearest facet for inside points
-                              set automatically if 'd Qc' */
-  int   KEEPmerge;        /* 'PMn' number of facets to keep with most merges */
-  realT KEEPminArea;      /* 'PFn' minimum facet area to keep */
-  realT MAXcoplanar;      /* 'Un' max distance below a facet to be coplanar*/
-  boolT MERGEexact;       /* true 'Qx' if exact merges (coplanar, degen, dupridge, flipped) */
-  boolT MERGEindependent; /* true 'Q2' if merging independent sets */
-  boolT MERGING;          /* true if exact-, pre- or post-merging, with angle and centrum tests */
-  realT   premerge_centrum;  /*   'C-n' centrum_radius when pre merging.  Default is round-off */
-  realT   postmerge_centrum; /*   'Cn' centrum_radius when post merging.  Default is round-off */
-  boolT MERGEvertices;    /* true 'Q3' if merging redundant vertices */
-  realT MINvisible;       /* 'Vn' min. distance for a facet to be visible */
-  boolT NOnarrow;         /* true 'Q10' if no special processing for narrow distributions */
-  boolT NOnearinside;     /* true 'Q8' if ignore near-inside points when partitioning */
-  boolT NOpremerge;       /* true 'Q0' if no defaults for C-0 or Qx */
-  boolT NOwide;           /* true 'Q12' if no error on wide merge due to duplicate ridge */
-  boolT ONLYgood;         /* true 'Qg' if process points with good visible or horizon facets */
-  boolT ONLYmax;          /* true 'Qm' if only process points that increase max_outside */
-  boolT PICKfurthest;     /* true 'Q9' if process furthest of furthest points*/
-  boolT POSTmerge;        /* true if merging after buildhull (Cn or An) */
-  boolT PREmerge;         /* true if merging during buildhull (C-n or A-n) */
-                        /* NOTE: some of these names are similar to qh_PRINT names */
-  boolT PRINTcentrums;    /* true 'Gc' if printing centrums */
-  boolT PRINTcoplanar;    /* true 'Gp' if printing coplanar points */
-  int   PRINTdim;         /* print dimension for Geomview output */
-  boolT PRINTdots;        /* true 'Ga' if printing all points as dots */
-  boolT PRINTgood;        /* true 'Pg' if printing good facets */
-  boolT PRINTinner;       /* true 'Gi' if printing inner planes */
-  boolT PRINTneighbors;   /* true 'PG' if printing neighbors of good facets */
-  boolT PRINTnoplanes;    /* true 'Gn' if printing no planes */
-  boolT PRINToptions1st;  /* true 'FO' if printing options to stderr */
-  boolT PRINTouter;       /* true 'Go' if printing outer planes */
-  boolT PRINTprecision;   /* false 'Pp' if not reporting precision problems */
-  qh_PRINT PRINTout[qh_PRINTEND]; /* list of output formats to print */
-  boolT PRINTridges;      /* true 'Gr' if print ridges */
-  boolT PRINTspheres;     /* true 'Gv' if print vertices as spheres */
-  boolT PRINTstatistics;  /* true 'Ts' if printing statistics to stderr */
-  boolT PRINTsummary;     /* true 's' if printing summary to stderr */
-  boolT PRINTtransparent; /* true 'Gt' if print transparent outer ridges */
-  boolT PROJECTdelaunay;  /* true if DELAUNAY, no readpoints() and
-                             need projectinput() for Delaunay in qh_init_B */
-  int   PROJECTinput;     /* number of projected dimensions 'bn:0Bn:0' */
-  boolT QUICKhelp;        /* true if quick help message for degen input */
-  boolT RANDOMdist;       /* true if randomly change distplane and setfacetplane */
-  realT RANDOMfactor;     /*    maximum random perturbation */
-  realT RANDOMa;          /*    qh_randomfactor is randr * RANDOMa + RANDOMb */
-  realT RANDOMb;
-  boolT RANDOMoutside;    /* true if select a random outside point */
-  int   REPORTfreq;       /* buildtracing reports every n facets */
-  int   REPORTfreq2;      /* tracemerging reports every REPORTfreq/2 facets */
-  int   RERUN;            /* 'TRn' rerun qhull n times (qh.build_cnt) */
-  int   ROTATErandom;     /* 'QRn' seed, 0 time, >= rotate input */
-  boolT SCALEinput;       /* true 'Qbk' if scaling input */
-  boolT SCALElast;        /* true 'Qbb' if scale last coord to max prev coord */
-  boolT SETroundoff;      /* true 'E' if qh.DISTround is predefined */
-  boolT SKIPcheckmax;     /* true 'Q5' if skip qh_check_maxout */
-  boolT SKIPconvex;       /* true 'Q6' if skip convexity testing during pre-merge */
-  boolT SPLITthresholds;  /* true if upper_/lower_threshold defines a region
-                               used only for printing (!for qh.ONLYgood) */
-  int   STOPcone;         /* 'TCn' 1+n for stopping after cone for point n */
-                          /*       also used by qh_build_withresart for err exit*/
-  int   STOPpoint;        /* 'TVn' 'TV-n' 1+n for stopping after/before(-)
-                                        adding point n */
-  int   TESTpoints;       /* 'QTn' num of test points after qh.num_points.  Test points always coplanar. */
-  boolT TESTvneighbors;   /*  true 'Qv' if test vertex neighbors at end */
-  int   TRACElevel;       /* 'Tn' conditional IStracing level */
-  int   TRACElastrun;     /*  qh.TRACElevel applies to last qh.RERUN */
-  int   TRACEpoint;       /* 'TPn' start tracing when point n is a vertex */
-  realT TRACEdist;        /* 'TWn' start tracing when merge distance too big */
-  int   TRACEmerge;       /* 'TMn' start tracing before this merge */
-  boolT TRIangulate;      /* true 'Qt' if triangulate non-simplicial facets */
-  boolT TRInormals;       /* true 'Q11' if triangulate duplicates ->normal and ->center (sets Qt) */
-  boolT UPPERdelaunay;    /* true 'Qu' if computing furthest-site Delaunay */
-  boolT USEstdout;        /* true 'Tz' if using stdout instead of stderr */
-  boolT VERIFYoutput;     /* true 'Tv' if verify output at end of qhull */
-  boolT VIRTUALmemory;    /* true 'Q7' if depth-first processing in buildhull */
-  boolT VORONOI;          /* true 'v' if computing Voronoi diagram */
-
-  /*--------input constants ---------*/
-  realT AREAfactor;       /* 1/(hull_dim-1)! for converting det's to area */
-  boolT DOcheckmax;       /* true if calling qh_check_maxout (qh_initqhull_globals) */
-  char  *feasible_string;  /* feasible point 'Hn,n,n' for halfspace intersection */
-  coordT *feasible_point;  /*    as coordinates, both malloc'd */
-  boolT GETarea;          /* true 'Fa', 'FA', 'FS', 'PAn', 'PFn' if compute facet area/Voronoi volume in io.c */
-  boolT KEEPnearinside;   /* true if near-inside points in coplanarset */
-  int   hull_dim;         /* dimension of hull, set by initbuffers */
-  int   input_dim;        /* dimension of input, set by initbuffers */
-  int   num_points;       /* number of input points */
-  pointT *first_point;    /* array of input points, see POINTSmalloc */
-  boolT POINTSmalloc;     /*   true if qh.first_point/num_points allocated */
-  pointT *input_points;   /* copy of original qh.first_point for input points for qh_joggleinput */
-  boolT input_malloc;     /* true if qh.input_points malloc'd */
-  char  qhull_command[256];/* command line that invoked this program */
-  int   qhull_commandsiz2; /*    size of qhull_command at qh_clear_outputflags */
-  char  rbox_command[256]; /* command line that produced the input points */
-  char  qhull_options[512];/* descriptive list of options */
-  int   qhull_optionlen;  /*    length of last line */
-  int   qhull_optionsiz;  /*    size of qhull_options at qh_build_withrestart */
-  int   qhull_optionsiz2; /*    size of qhull_options at qh_clear_outputflags */
-  int   run_id;           /* non-zero, random identifier for this instance of qhull */
-  boolT VERTEXneighbors;  /* true if maintaining vertex neighbors */
-  boolT ZEROcentrum;      /* true if 'C-0' or 'C-0 Qx'.  sets ZEROall_ok */
-  realT *upper_threshold; /* don't print if facet->normal[k]>=upper_threshold[k]
-                             must set either GOODthreshold or SPLITthreshold
-                             if Delaunay, default is 0.0 for upper envelope */
-  realT *lower_threshold; /* don't print if facet->normal[k] <=lower_threshold[k] */
-  realT *upper_bound;     /* scale point[k] to new upper bound */
-  realT *lower_bound;     /* scale point[k] to new lower bound
-                             project if both upper_ and lower_bound == 0 */
-
-/*----------------------------------
-
-  qh precision constants
-    precision constants for Qhull
-
-  notes:
-    qh_detroundoff() computes the maximum roundoff error for distance
-    and other computations.  It also sets default values for the
-    qh constants above.
-*/
-  realT ANGLEround;       /* max round off error for angles */
-  realT centrum_radius;   /* max centrum radius for convexity (roundoff added) */
-  realT cos_max;          /* max cosine for convexity (roundoff added) */
-  realT DISTround;        /* max round off error for distances, 'E' overrides qh_distround() */
-  realT MAXabs_coord;     /* max absolute coordinate */
-  realT MAXlastcoord;     /* max last coordinate for qh_scalelast */
-  realT MAXsumcoord;      /* max sum of coordinates */
-  realT MAXwidth;         /* max rectilinear width of point coordinates */
-  realT MINdenom_1;       /* min. abs. value for 1/x */
-  realT MINdenom;         /*    use divzero if denominator < MINdenom */
-  realT MINdenom_1_2;     /* min. abs. val for 1/x that allows normalization */
-  realT MINdenom_2;       /*    use divzero if denominator < MINdenom_2 */
-  realT MINlastcoord;     /* min. last coordinate for qh_scalelast */
-  boolT NARROWhull;       /* set in qh_initialhull if angle < qh_MAXnarrow */
-  realT *NEARzero;        /* hull_dim array for near zero in gausselim */
-  realT NEARinside;       /* keep points for qh_check_maxout if close to facet */
-  realT ONEmerge;         /* max distance for merging simplicial facets */
-  realT outside_err;      /* application's epsilon for coplanar points
-                             qh_check_bestdist() qh_check_points() reports error if point outside */
-  realT WIDEfacet;        /* size of wide facet for skipping ridge in
-                             area computation and locking centrum */
-
-/*----------------------------------
-
-  qh internal constants
-    internal constants for Qhull
-*/
-  char qhull[sizeof("qhull")]; /* "qhull" for checking ownership while debugging */
-  jmp_buf errexit;        /* exit label for qh_errexit, defined by setjmp() and NOerrexit */
-  char jmpXtra[40];       /* extra bytes in case jmp_buf is defined wrong by compiler */
-  jmp_buf restartexit;    /* restart label for qh_errexit, defined by setjmp() and ALLOWrestart */
-  char jmpXtra2[40];      /* extra bytes in case jmp_buf is defined wrong by compiler*/
-  FILE *fin;              /* pointer to input file, init by qh_initqhull_start2 */
-  FILE *fout;             /* pointer to output file */
-  FILE *ferr;             /* pointer to error file */
-  pointT *interior_point; /* center point of the initial simplex*/
-  int normal_size;     /* size in bytes for facet normals and point coords*/
-  int center_size;     /* size in bytes for Voronoi centers */
-  int   TEMPsize;         /* size for small, temporary sets (in quick mem) */
-
-/*----------------------------------
-
-  qh facet and vertex lists
-    defines lists of facets, new facets, visible facets, vertices, and
-    new vertices.  Includes counts, next ids, and trace ids.
-  see:
-    qh_resetlists()
-*/
-  facetT *facet_list;     /* first facet */
-  facetT  *facet_tail;     /* end of facet_list (dummy facet) */
-  facetT *facet_next;     /* next facet for buildhull()
-                             previous facets do not have outside sets
-                             NARROWhull: previous facets may have coplanar outside sets for qh_outcoplanar */
-  facetT *newfacet_list;  /* list of new facets to end of facet_list */
-  facetT *visible_list;   /* list of visible facets preceding newfacet_list,
-                             facet->visible set */
-  int       num_visible;  /* current number of visible facets */
-  unsigned tracefacet_id;  /* set at init, then can print whenever */
-  facetT *tracefacet;     /*   set in newfacet/mergefacet, undone in delfacet*/
-  unsigned tracevertex_id;  /* set at buildtracing, can print whenever */
-  vertexT *tracevertex;     /*   set in newvertex, undone in delvertex*/
-  vertexT *vertex_list;     /* list of all vertices, to vertex_tail */
-  vertexT  *vertex_tail;    /*      end of vertex_list (dummy vertex) */
-  vertexT *newvertex_list; /* list of vertices in newfacet_list, to vertex_tail
-                             all vertices have 'newlist' set */
-  int   num_facets;       /* number of facets in facet_list
-                             includes visible faces (num_visible) */
-  int   num_vertices;     /* number of vertices in facet_list */
-  int   num_outside;      /* number of points in outsidesets (for tracing and RANDOMoutside)
-                               includes coplanar outsideset points for NARROWhull/qh_outcoplanar() */
-  int   num_good;         /* number of good facets (after findgood_all) */
-  unsigned facet_id;      /* ID of next, new facet from newfacet() */
-  unsigned ridge_id;      /* ID of next, new ridge from newridge() */
-  unsigned vertex_id;     /* ID of next, new vertex from newvertex() */
-
-/*----------------------------------
-
-  qh global variables
-    defines minimum and maximum distances, next visit ids, several flags,
-    and other global variables.
-    initialize in qh_initbuild or qh_maxmin if used in qh_buildhull
-*/
-  unsigned long hulltime; /* ignore time to set up input and randomize */
-                          /*   use unsigned to avoid wrap-around errors */
-  boolT ALLOWrestart;     /* true if qh_precision can use qh.restartexit */
-  int   build_cnt;        /* number of calls to qh_initbuild */
-  qh_CENTER CENTERtype;   /* current type of facet->center, qh_CENTER */
-  int   furthest_id;      /* pointid of furthest point, for tracing */
-  facetT *GOODclosest;    /* closest facet to GOODthreshold in qh_findgood */
-  boolT hasAreaVolume;    /* true if totarea, totvol was defined by qh_getarea */
-  boolT hasTriangulation; /* true if triangulation created by qh_triangulate */
-  realT JOGGLEmax;        /* set 'QJn' if randomly joggle input */
-  boolT maxoutdone;       /* set qh_check_maxout(), cleared by qh_addpoint() */
-  realT max_outside;      /* maximum distance from a point to a facet,
-                               before roundoff, not simplicial vertices
-                               actual outer plane is +DISTround and
-                               computed outer plane is +2*DISTround */
-  realT max_vertex;       /* maximum distance (>0) from vertex to a facet,
-                               before roundoff, due to a merge */
-  realT min_vertex;       /* minimum distance (<0) from vertex to a facet,
-                               before roundoff, due to a merge
-                               if qh.JOGGLEmax, qh_makenewplanes sets it
-                               recomputed if qh.DOcheckmax, default -qh.DISTround */
-  boolT NEWfacets;        /* true while visible facets invalid due to new or merge
-                              from makecone/attachnewfacets to deletevisible */
-  boolT findbestnew;      /* true if partitioning calls qh_findbestnew */
-  boolT findbest_notsharp; /* true if new facets are at least 90 degrees */
-  boolT NOerrexit;        /* true if qh.errexit is not available, cleared after setjmp */
-  realT PRINTcradius;     /* radius for printing centrums */
-  realT PRINTradius;      /* radius for printing vertex spheres and points */
-  boolT POSTmerging;      /* true when post merging */
-  int   printoutvar;      /* temporary variable for qh_printbegin, etc. */
-  int   printoutnum;      /* number of facets printed */
-  boolT QHULLfinished;    /* True after qhull() is finished */
-  realT totarea;          /* 'FA': total facet area computed by qh_getarea, hasAreaVolume */
-  realT totvol;           /* 'FA': total volume computed by qh_getarea, hasAreaVolume */
-  unsigned int visit_id;  /* unique ID for searching neighborhoods, */
-  unsigned int vertex_visit; /* unique ID for searching vertices, reset with qh_buildtracing */
-  boolT ZEROall_ok;       /* True if qh_checkzero always succeeds */
-  boolT WAScoplanar;      /* True if qh_partitioncoplanar (qh_check_maxout) */
-
-/*----------------------------------
-
-  qh global sets
-    defines sets for merging, initial simplex, hashing, extra input points,
-    and deleted vertices
-*/
-  setT *facet_mergeset;   /* temporary set of merges to be done */
-  setT *degen_mergeset;   /* temporary set of degenerate and redundant merges */
-  setT *hash_table;       /* hash table for matching ridges in qh_matchfacets
-                             size is setsize() */
-  setT *other_points;     /* additional points */
-  setT *del_vertices;     /* vertices to partition and delete with visible
-                             facets.  Have deleted set for checkfacet */
-
-/*----------------------------------
-
-  qh global buffers
-    defines buffers for maxtrix operations, input, and error messages
-*/
-  coordT *gm_matrix;      /* (dim+1)Xdim matrix for geom.c */
-  coordT **gm_row;        /* array of gm_matrix rows */
-  char* line;             /* malloc'd input line of maxline+1 chars */
-  int maxline;
-  coordT *half_space;     /* malloc'd input array for halfspace (qh normal_size+coordT) */
-  coordT *temp_malloc;    /* malloc'd input array for points */
-
-/*----------------------------------
-
-  qh static variables
-    defines static variables for individual functions
-
-  notes:
-    do not use 'static' within a function.  Multiple instances of qhull
-    may exist.
-
-    do not assume zero initialization, 'QPn' may cause a restart
-*/
-  boolT ERREXITcalled;    /* true during qh_errexit (prevents duplicate calls */
-  boolT firstcentrum;     /* for qh_printcentrum */
-  boolT old_randomdist;   /* save RANDOMdist flag during io, tracing, or statistics */
-  setT *coplanarfacetset;  /* set of coplanar facets for searching qh_findbesthorizon() */
-  realT last_low;         /* qh_scalelast parameters for qh_setdelaunay */
-  realT last_high;
-  realT last_newhigh;
-  unsigned lastreport;    /* for qh_buildtracing */
-  int mergereport;        /* for qh_tracemerging */
-  qhstatT *old_qhstat;    /* for saving qh_qhstat in save_qhull() and UsingLibQhull.  Free with qh_free() */
-  setT *old_tempstack;    /* for saving qhmem.tempstack in save_qhull */
-  int   ridgeoutnum;      /* number of ridges for 4OFF output (qh_printbegin,etc) */
-};
-
-/*=========== -macros- =========================*/
-
-/*----------------------------------
-
-  otherfacet_(ridge, facet)
-    return neighboring facet for a ridge in facet
-*/
-#define otherfacet_(ridge, facet) \
-                        (((ridge)->top == (facet)) ? (ridge)->bottom : (ridge)->top)
-
-/*----------------------------------
-
-  getid_(p)
-    return int ID for facet, ridge, or vertex
-    return qh_IDunknown(-1) if NULL
-*/
-#define getid_(p)       ((p) ? (int)((p)->id) : qh_IDunknown)
-
-/*============== FORALL macros ===================*/
-
-/*----------------------------------
-
-  FORALLfacets { ... }
-    assign 'facet' to each facet in qh.facet_list
-
-  notes:
-    uses 'facetT *facet;'
-    assumes last facet is a sentinel
-
-  see:
-    FORALLfacet_( facetlist )
-*/
-#define FORALLfacets for (facet=qh facet_list;facet && facet->next;facet=facet->next)
-
-/*----------------------------------
-
-  FORALLpoints { ... }
-    assign 'point' to each point in qh.first_point, qh.num_points
-
-  declare:
-    coordT *point, *pointtemp;
-*/
-#define FORALLpoints FORALLpoint_(qh first_point, qh num_points)
-
-/*----------------------------------
-
-  FORALLpoint_( points, num) { ... }
-    assign 'point' to each point in points array of num points
-
-  declare:
-    coordT *point, *pointtemp;
-*/
-#define FORALLpoint_(points, num) for (point= (points), \
-      pointtemp= (points)+qh hull_dim*(num); point < pointtemp; point += qh hull_dim)
-
-/*----------------------------------
-
-  FORALLvertices { ... }
-    assign 'vertex' to each vertex in qh.vertex_list
-
-  declare:
-    vertexT *vertex;
-
-  notes:
-    assumes qh.vertex_list terminated with a sentinel
-*/
-#define FORALLvertices for (vertex=qh vertex_list;vertex && vertex->next;vertex= vertex->next)
-
-/*----------------------------------
-
-  FOREACHfacet_( facets ) { ... }
-    assign 'facet' to each facet in facets
-
-  declare:
-    facetT *facet, **facetp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHfacet_(facets)    FOREACHsetelement_(facetT, facets, facet)
-
-/*----------------------------------
-
-  FOREACHneighbor_( facet ) { ... }
-    assign 'neighbor' to each neighbor in facet->neighbors
-
-  FOREACHneighbor_( vertex ) { ... }
-    assign 'neighbor' to each neighbor in vertex->neighbors
-
-  declare:
-    facetT *neighbor, **neighborp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHneighbor_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighbor)
-
-/*----------------------------------
-
-  FOREACHpoint_( points ) { ... }
-    assign 'point' to each point in points set
-
-  declare:
-    pointT *point, **pointp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHpoint_(points)    FOREACHsetelement_(pointT, points, point)
-
-/*----------------------------------
-
-  FOREACHridge_( ridges ) { ... }
-    assign 'ridge' to each ridge in ridges set
-
-  declare:
-    ridgeT *ridge, **ridgep;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHridge_(ridges)    FOREACHsetelement_(ridgeT, ridges, ridge)
-
-/*----------------------------------
-
-  FOREACHvertex_( vertices ) { ... }
-    assign 'vertex' to each vertex in vertices set
-
-  declare:
-    vertexT *vertex, **vertexp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHvertex_(vertices) FOREACHsetelement_(vertexT, vertices,vertex)
-
-/*----------------------------------
-
-  FOREACHfacet_i_( facets ) { ... }
-    assign 'facet' and 'facet_i' for each facet in facets set
-
-  declare:
-    facetT *facet;
-    int     facet_n, facet_i;
-
-  see:
-    FOREACHsetelement_i_
-*/
-#define FOREACHfacet_i_(facets)    FOREACHsetelement_i_(facetT, facets, facet)
-
-/*----------------------------------
-
-  FOREACHneighbor_i_( facet ) { ... }
-    assign 'neighbor' and 'neighbor_i' for each neighbor in facet->neighbors
-
-  FOREACHneighbor_i_( vertex ) { ... }
-    assign 'neighbor' and 'neighbor_i' for each neighbor in vertex->neighbors
-
-  declare:
-    facetT *neighbor;
-    int     neighbor_n, neighbor_i;
-
-  see:
-    FOREACHsetelement_i_
-*/
-#define FOREACHneighbor_i_(facet)  FOREACHsetelement_i_(facetT, facet->neighbors, neighbor)
-
-/*----------------------------------
-
-  FOREACHpoint_i_( points ) { ... }
-    assign 'point' and 'point_i' for each point in points set
-
-  declare:
-    pointT *point;
-    int     point_n, point_i;
-
-  see:
-    FOREACHsetelement_i_
-*/
-#define FOREACHpoint_i_(points)    FOREACHsetelement_i_(pointT, points, point)
-
-/*----------------------------------
-
-  FOREACHridge_i_( ridges ) { ... }
-    assign 'ridge' and 'ridge_i' for each ridge in ridges set
-
-  declare:
-    ridgeT *ridge;
-    int     ridge_n, ridge_i;
-
-  see:
-    FOREACHsetelement_i_
-*/
-#define FOREACHridge_i_(ridges)    FOREACHsetelement_i_(ridgeT, ridges, ridge)
-
-/*----------------------------------
-
-  FOREACHvertex_i_( vertices ) { ... }
-    assign 'vertex' and 'vertex_i' for each vertex in vertices set
-
-  declare:
-    vertexT *vertex;
-    int     vertex_n, vertex_i;
-
-  see:
-    FOREACHsetelement_i_
-*/
-#define FOREACHvertex_i_(vertices) FOREACHsetelement_i_(vertexT, vertices,vertex)
-
-/********* -libqhull.c prototypes (duplicated from qhull_a.h) **********************/
-
-void    qh_qhull(void);
-boolT   qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist);
-void    qh_printsummary(FILE *fp);
-
-/********* -user.c prototypes (alphabetical) **********************/
-
-void    qh_errexit(int exitcode, facetT *facet, ridgeT *ridge);
-void    qh_errprint(const char* string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex);
-int     qh_new_qhull(int dim, int numpoints, coordT *points, boolT ismalloc,
-                char *qhull_cmd, FILE *outfile, FILE *errfile);
-void    qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall);
-void    qh_printhelp_degenerate(FILE *fp);
-void    qh_printhelp_narrowhull(FILE *fp, realT minangle);
-void    qh_printhelp_singular(FILE *fp);
-void    qh_user_memsizes(void);
-
-/********* -usermem.c prototypes (alphabetical) **********************/
-void    qh_exit(int exitcode);
-void    qh_fprintf_stderr(int msgcode, const char *fmt, ... );
-void    qh_free(void *mem);
-void   *qh_malloc(size_t size);
-
-/********* -userprintf.c and userprintf_rbox.c prototypes **********************/
-void    qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... );
-void    qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... );
-
-/***** -geom.c/geom2.c/random.c prototypes (duplicated from geom.h, random.h) ****************/
-
-facetT *qh_findbest(pointT *point, facetT *startfacet,
-                     boolT bestoutside, boolT newfacets, boolT noupper,
-                     realT *dist, boolT *isoutside, int *numpart);
-facetT *qh_findbestnew(pointT *point, facetT *startfacet,
-                     realT *dist, boolT bestoutside, boolT *isoutside, int *numpart);
-boolT   qh_gram_schmidt(int dim, realT **rows);
-void    qh_outerinner(facetT *facet, realT *outerplane, realT *innerplane);
-void    qh_printsummary(FILE *fp);
-void    qh_projectinput(void);
-void    qh_randommatrix(realT *buffer, int dim, realT **row);
-void    qh_rotateinput(realT **rows);
-void    qh_scaleinput(void);
-void    qh_setdelaunay(int dim, int count, pointT *points);
-coordT  *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feasible);
-
-/***** -global.c prototypes (alphabetical) ***********************/
-
-unsigned long qh_clock(void);
-void    qh_checkflags(char *command, char *hiddenflags);
-void    qh_clear_outputflags(void);
-void    qh_freebuffers(void);
-void    qh_freeqhull(boolT allmem);
-void    qh_freeqhull2(boolT allmem);
-void    qh_init_A(FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]);
-void    qh_init_B(coordT *points, int numpoints, int dim, boolT ismalloc);
-void    qh_init_qhull_command(int argc, char *argv[]);
-void    qh_initbuffers(coordT *points, int numpoints, int dim, boolT ismalloc);
-void    qh_initflags(char *command);
-void    qh_initqhull_buffers(void);
-void    qh_initqhull_globals(coordT *points, int numpoints, int dim, boolT ismalloc);
-void    qh_initqhull_mem(void);
-void    qh_initqhull_outputflags(void);
-void    qh_initqhull_start(FILE *infile, FILE *outfile, FILE *errfile);
-void    qh_initqhull_start2(FILE *infile, FILE *outfile, FILE *errfile);
-void    qh_initthresholds(char *command);
-void    qh_lib_check(int qhullLibraryType, int qhTsize, int vertexTsize, int ridgeTsize, int facetTsize, int setTsize, int qhmemTsize);
-void    qh_option(const char *option, int *i, realT *r);
-#if qh_QHpointer
-void    qh_restore_qhull(qhT **oldqh);
-qhT    *qh_save_qhull(void);
-#endif
-
-/***** -io.c prototypes (duplicated from io.h) ***********************/
-
-void    qh_dfacet(unsigned id);
-void    qh_dvertex(unsigned id);
-void    qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall);
-void    qh_produce_output(void);
-coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
-
-
-/********* -mem.c prototypes (duplicated from mem.h) **********************/
-
-void qh_meminit(FILE *ferr);
-void qh_memfreeshort(int *curlong, int *totlong);
-
-/********* -poly.c/poly2.c prototypes (duplicated from poly.h) **********************/
-
-void    qh_check_output(void);
-void    qh_check_points(void);
-setT   *qh_facetvertices(facetT *facetlist, setT *facets, boolT allfacets);
-facetT *qh_findbestfacet(pointT *point, boolT bestoutside,
-           realT *bestdist, boolT *isoutside);
-vertexT *qh_nearvertex(facetT *facet, pointT *point, realT *bestdistp);
-pointT *qh_point(int id);
-setT   *qh_pointfacet(void /*qh.facet_list*/);
-int     qh_pointid(pointT *point);
-setT   *qh_pointvertex(void /*qh.facet_list*/);
-void    qh_setvoronoi_all(void);
-void    qh_triangulate(void /*qh.facet_list*/);
-
-/********* -rboxlib.c prototypes **********************/
-int     qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command);
-void    qh_errexit_rbox(int exitcode);
-
-/********* -stat.c prototypes (duplicated from stat.h) **********************/
-
-void    qh_collectstatistics(void);
-void    qh_printallstatistics(FILE *fp, const char *string);
-
-#endif /* qhDEFlibqhull */
diff --git a/extern/libqhull/mem.c b/extern/libqhull/mem.c
deleted file mode 100644
index db72bb4e19d9..000000000000
--- a/extern/libqhull/mem.c
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
  ---------------------------------
-
-  mem.c
-    memory management routines for qhull
-
-  This is a standalone program.
-
-  To initialize memory:
-
-    qh_meminit(stderr);
-    qh_meminitbuffers(qh IStracing, qh_MEMalign, 7, qh_MEMbufsize,qh_MEMinitbuf);
-    qh_memsize((int)sizeof(facetT));
-    qh_memsize((int)sizeof(facetT));
-    ...
-    qh_memsetup();
-
-  To free up all memory buffers:
-    qh_memfreeshort(&curlong, &totlong);
-
-  if qh_NOmem,
-    malloc/free is used instead of mem.c
-
-  notes:
-    uses Quickfit algorithm (freelists for commonly allocated sizes)
-    assumes small sizes for freelists (it discards the tail of memory buffers)
-
-  see:
-    qh-mem.htm and mem.h
-    global.c (qh_initbuffers) for an example of using mem.c
-
-  Copyright (c) 1993-2015 The Geometry Center.
-  $Id: //main/2015/qhull/src/libqhull/mem.c#7 $$Change: 2065 $
-  $DateTime: 2016/01/18 13:51:04 $$Author: bbarber $
-*/
-
-#include "user.h"  /* for QHULL_CRTDBG */
-#include "mem.h"
-#include 
-#include 
-#include 
-
-#ifndef qhDEFlibqhull
-typedef struct ridgeT ridgeT;
-typedef struct facetT facetT;
-#ifdef _MSC_VER  /* Microsoft Visual C++ -- warning level 4 */
-#pragma warning( disable : 4127)  /* conditional expression is constant */
-#pragma warning( disable : 4706)  /* assignment within conditional function */
-#endif
-void    qh_errexit(int exitcode, facetT *, ridgeT *);
-void    qh_exit(int exitcode);
-void    qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... );
-void    qh_fprintf_stderr(int msgcode, const char *fmt, ... );
-void    qh_free(void *mem);
-void   *qh_malloc(size_t size);
-#endif
-
-/*============ -global data structure ==============
-    see mem.h for definition
-*/
-
-qhmemT qhmem= {0,0,0,0,0,0,0,0,0,0,0,
-               0,0,0,0,0,0,0,0,0,0,0,
-               0,0,0,0,0,0,0};     /* remove "= {0}" if this causes a compiler error */
-
-#ifndef qh_NOmem
-
-/*============= internal functions ==============*/
-
-static int qh_intcompare(const void *i, const void *j);
-
-/*========== functions in alphabetical order ======== */
-
-/*---------------------------------
-
-  qh_intcompare( i, j )
-    used by qsort and bsearch to compare two integers
-*/
-static int qh_intcompare(const void *i, const void *j) {
-  return(*((const int *)i) - *((const int *)j));
-} /* intcompare */
-
-
-/*----------------------------------
-
-  qh_memalloc( insize )
-    returns object of insize bytes
-    qhmem is the global memory structure
-
-  returns:
-    pointer to allocated memory
-    errors if insufficient memory
-
-  notes:
-    use explicit type conversion to avoid type warnings on some compilers
-    actual object may be larger than insize
-    use qh_memalloc_() for inline code for quick allocations
-    logs allocations if 'T5'
-    caller is responsible for freeing the memory.
-    short memory is freed on shutdown by qh_memfreeshort unless qh_NOmem
-
-  design:
-    if size < qhmem.LASTsize
-      if qhmem.freelists[size] non-empty
-        return first object on freelist
-      else
-        round up request to size of qhmem.freelists[size]
-        allocate new allocation buffer if necessary
-        allocate object from allocation buffer
-    else
-      allocate object with qh_malloc() in user.c
-*/
-void *qh_memalloc(int insize) {
-  void **freelistp, *newbuffer;
-  int idx, size, n;
-  int outsize, bufsize;
-  void *object;
-
-  if (insize<0) {
-      qh_fprintf(qhmem.ferr, 6235, "qhull error (qh_memalloc): negative request size (%d).  Did int overflow due to high-D?\n", insize); /* WARN64 */
-      qh_errexit(qhmem_ERRmem, NULL, NULL);
-  }
-  if (insize>=0 && insize <= qhmem.LASTsize) {
-    idx= qhmem.indextable[insize];
-    outsize= qhmem.sizetable[idx];
-    qhmem.totshort += outsize;
-    freelistp= qhmem.freelists+idx;
-    if ((object= *freelistp)) {
-      qhmem.cntquick++;
-      qhmem.totfree -= outsize;
-      *freelistp= *((void **)*freelistp);  /* replace freelist with next object */
-#ifdef qh_TRACEshort
-      n= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort;
-      if (qhmem.IStracing >= 5)
-          qh_fprintf(qhmem.ferr, 8141, "qh_mem %p n %8d alloc quick: %d bytes (tot %d cnt %d)\n", object, n, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort);
-#endif
-      return(object);
-    }else {
-      qhmem.cntshort++;
-      if (outsize > qhmem.freesize) {
-        qhmem.totdropped += qhmem.freesize;
-        if (!qhmem.curbuffer)
-          bufsize= qhmem.BUFinit;
-        else
-          bufsize= qhmem.BUFsize;
-        if (!(newbuffer= qh_malloc((size_t)bufsize))) {
-          qh_fprintf(qhmem.ferr, 6080, "qhull error (qh_memalloc): insufficient memory to allocate short memory buffer (%d bytes)\n", bufsize);
-          qh_errexit(qhmem_ERRmem, NULL, NULL);
-        }
-        *((void **)newbuffer)= qhmem.curbuffer;  /* prepend newbuffer to curbuffer
-                                                    list.  newbuffer!=0 by QH6080 */
-        qhmem.curbuffer= newbuffer;
-        size= (sizeof(void **) + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
-        qhmem.freemem= (void *)((char *)newbuffer+size);
-        qhmem.freesize= bufsize - size;
-        qhmem.totbuffer += bufsize - size; /* easier to check */
-        /* Periodically test totbuffer.  It matches at beginning and exit of every call */
-        n = qhmem.totshort + qhmem.totfree + qhmem.totdropped + qhmem.freesize - outsize;
-        if (qhmem.totbuffer != n) {
-            qh_fprintf(qhmem.ferr, 6212, "qh_memalloc internal error: short totbuffer %d != totshort+totfree... %d\n", qhmem.totbuffer, n);
-            qh_errexit(qhmem_ERRmem, NULL, NULL);
-        }
-      }
-      object= qhmem.freemem;
-      qhmem.freemem= (void *)((char *)qhmem.freemem + outsize);
-      qhmem.freesize -= outsize;
-      qhmem.totunused += outsize - insize;
-#ifdef qh_TRACEshort
-      n= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort;
-      if (qhmem.IStracing >= 5)
-          qh_fprintf(qhmem.ferr, 8140, "qh_mem %p n %8d alloc short: %d bytes (tot %d cnt %d)\n", object, n, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort);
-#endif
-      return object;
-    }
-  }else {                     /* long allocation */
-    if (!qhmem.indextable) {
-      qh_fprintf(qhmem.ferr, 6081, "qhull internal error (qh_memalloc): qhmem has not been initialized.\n");
-      qh_errexit(qhmem_ERRqhull, NULL, NULL);
-    }
-    outsize= insize;
-    qhmem.cntlong++;
-    qhmem.totlong += outsize;
-    if (qhmem.maxlong < qhmem.totlong)
-      qhmem.maxlong= qhmem.totlong;
-    if (!(object= qh_malloc((size_t)outsize))) {
-      qh_fprintf(qhmem.ferr, 6082, "qhull error (qh_memalloc): insufficient memory to allocate %d bytes\n", outsize);
-      qh_errexit(qhmem_ERRmem, NULL, NULL);
-    }
-    if (qhmem.IStracing >= 5)
-      qh_fprintf(qhmem.ferr, 8057, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, outsize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
-  }
-  return(object);
-} /* memalloc */
-
-
-/*----------------------------------
-
-  qh_memcheck( )
-*/
-void qh_memcheck(void) {
-  int i, count, totfree= 0;
-  void *object;
-
-  if (qhmem.ferr == 0 || qhmem.IStracing < 0 || qhmem.IStracing > 10 || (((qhmem.ALIGNmask+1) & qhmem.ALIGNmask) != 0)) {
-    qh_fprintf_stderr(6244, "qh_memcheck error: either qhmem is overwritten or qhmem is not initialized.  Call qh_meminit() or qh_new_qhull() before calling qh_mem routines.  ferr 0x%x IsTracing %d ALIGNmask 0x%x", qhmem.ferr, qhmem.IStracing, qhmem.ALIGNmask);
-    qh_exit(qhmem_ERRqhull);  /* can not use qh_errexit() */
-  }
-  if (qhmem.IStracing != 0)
-    qh_fprintf(qhmem.ferr, 8143, "qh_memcheck: check size of freelists on qhmem\nqh_memcheck: A segmentation fault indicates an overwrite of qhmem\n");
-  for (i=0; i < qhmem.TABLEsize; i++) {
-    count=0;
-    for (object= qhmem.freelists[i]; object; object= *((void **)object))
-      count++;
-    totfree += qhmem.sizetable[i] * count;
-  }
-  if (totfree != qhmem.totfree) {
-    qh_fprintf(qhmem.ferr, 6211, "Qhull internal error (qh_memcheck): totfree %d not equal to freelist total %d\n", qhmem.totfree, totfree);
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-  if (qhmem.IStracing != 0)
-    qh_fprintf(qhmem.ferr, 8144, "qh_memcheck: total size of freelists totfree is the same as qhmem.totfree\n", totfree);
-} /* memcheck */
-
-/*----------------------------------
-
-  qh_memfree( object, insize )
-    free up an object of size bytes
-    size is insize from qh_memalloc
-
-  notes:
-    object may be NULL
-    type checking warns if using (void **)object
-    use qh_memfree_() for quick free's of small objects
-
-  design:
-    if size <= qhmem.LASTsize
-      append object to corresponding freelist
-    else
-      call qh_free(object)
-*/
-void qh_memfree(void *object, int insize) {
-  void **freelistp;
-  int idx, outsize;
-
-  if (!object)
-    return;
-  if (insize <= qhmem.LASTsize) {
-    qhmem.freeshort++;
-    idx= qhmem.indextable[insize];
-    outsize= qhmem.sizetable[idx];
-    qhmem.totfree += outsize;
-    qhmem.totshort -= outsize;
-    freelistp= qhmem.freelists + idx;
-    *((void **)object)= *freelistp;
-    *freelistp= object;
-#ifdef qh_TRACEshort
-    idx= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort;
-    if (qhmem.IStracing >= 5)
-        qh_fprintf(qhmem.ferr, 8142, "qh_mem %p n %8d free short: %d bytes (tot %d cnt %d)\n", object, idx, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort);
-#endif
-  }else {
-    qhmem.freelong++;
-    qhmem.totlong -= insize;
-    if (qhmem.IStracing >= 5)
-      qh_fprintf(qhmem.ferr, 8058, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, insize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
-    qh_free(object);
-  }
-} /* memfree */
-
-
-/*---------------------------------
-
-  qh_memfreeshort( curlong, totlong )
-    frees up all short and qhmem memory allocations
-
-  returns:
-    number and size of current long allocations
-
-  see:
-    qh_freeqhull(allMem)
-    qh_memtotal(curlong, totlong, curshort, totshort, maxlong, totbuffer);
-*/
-void qh_memfreeshort(int *curlong, int *totlong) {
-  void *buffer, *nextbuffer;
-  FILE *ferr;
-
-  *curlong= qhmem.cntlong - qhmem.freelong;
-  *totlong= qhmem.totlong;
-  for (buffer= qhmem.curbuffer; buffer; buffer= nextbuffer) {
-    nextbuffer= *((void **) buffer);
-    qh_free(buffer);
-  }
-  qhmem.curbuffer= NULL;
-  if (qhmem.LASTsize) {
-    qh_free(qhmem.indextable);
-    qh_free(qhmem.freelists);
-    qh_free(qhmem.sizetable);
-  }
-  ferr= qhmem.ferr;
-  memset((char *)&qhmem, 0, sizeof(qhmem));  /* every field is 0, FALSE, NULL */
-  qhmem.ferr= ferr;
-} /* memfreeshort */
-
-
-/*----------------------------------
-
-  qh_meminit( ferr )
-    initialize qhmem and test sizeof( void*)
-    Does not throw errors.  qh_exit on failure
-*/
-void qh_meminit(FILE *ferr) {
-
-  memset((char *)&qhmem, 0, sizeof(qhmem));  /* every field is 0, FALSE, NULL */
-  if (ferr)
-    qhmem.ferr= ferr;
-  else
-    qhmem.ferr= stderr;
-  if (sizeof(void*) < sizeof(int)) {
-    qh_fprintf(qhmem.ferr, 6083, "qhull internal error (qh_meminit): sizeof(void*) %d < sizeof(int) %d.  qset.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
-    qh_exit(qhmem_ERRqhull);  /* can not use qh_errexit() */
-  }
-  if (sizeof(void*) > sizeof(ptr_intT)) {
-      qh_fprintf(qhmem.ferr, 6084, "qhull internal error (qh_meminit): sizeof(void*) %d > sizeof(ptr_intT) %d. Change ptr_intT in mem.h to 'long long'\n", (int)sizeof(void*), (int)sizeof(ptr_intT));
-      qh_exit(qhmem_ERRqhull);  /* can not use qh_errexit() */
-  }
-  qh_memcheck();
-} /* meminit */
-
-/*---------------------------------
-
-  qh_meminitbuffers( tracelevel, alignment, numsizes, bufsize, bufinit )
-    initialize qhmem
-    if tracelevel >= 5, trace memory allocations
-    alignment= desired address alignment for memory allocations
-    numsizes= number of freelists
-    bufsize=  size of additional memory buffers for short allocations
-    bufinit=  size of initial memory buffer for short allocations
-*/
-void qh_meminitbuffers(int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
-
-  qhmem.IStracing= tracelevel;
-  qhmem.NUMsizes= numsizes;
-  qhmem.BUFsize= bufsize;
-  qhmem.BUFinit= bufinit;
-  qhmem.ALIGNmask= alignment-1;
-  if (qhmem.ALIGNmask & ~qhmem.ALIGNmask) {
-    qh_fprintf(qhmem.ferr, 6085, "qhull internal error (qh_meminit): memory alignment %d is not a power of 2\n", alignment);
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-  qhmem.sizetable= (int *) calloc((size_t)numsizes, sizeof(int));
-  qhmem.freelists= (void **) calloc((size_t)numsizes, sizeof(void *));
-  if (!qhmem.sizetable || !qhmem.freelists) {
-    qh_fprintf(qhmem.ferr, 6086, "qhull error (qh_meminit): insufficient memory\n");
-    qh_errexit(qhmem_ERRmem, NULL, NULL);
-  }
-  if (qhmem.IStracing >= 1)
-    qh_fprintf(qhmem.ferr, 8059, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment);
-} /* meminitbuffers */
-
-/*---------------------------------
-
-  qh_memsetup()
-    set up memory after running memsize()
-*/
-void qh_memsetup(void) {
-  int k,i;
-
-  qsort(qhmem.sizetable, (size_t)qhmem.TABLEsize, sizeof(int), qh_intcompare);
-  qhmem.LASTsize= qhmem.sizetable[qhmem.TABLEsize-1];
-  if (qhmem.LASTsize >= qhmem.BUFsize || qhmem.LASTsize >= qhmem.BUFinit) {
-    qh_fprintf(qhmem.ferr, 6087, "qhull error (qh_memsetup): largest mem size %d is >= buffer size %d or initial buffer size %d\n",
-            qhmem.LASTsize, qhmem.BUFsize, qhmem.BUFinit);
-    qh_errexit(qhmem_ERRmem, NULL, NULL);
-  }
-  if (!(qhmem.indextable= (int *)qh_malloc((qhmem.LASTsize+1) * sizeof(int)))) {
-    qh_fprintf(qhmem.ferr, 6088, "qhull error (qh_memsetup): insufficient memory\n");
-    qh_errexit(qhmem_ERRmem, NULL, NULL);
-  }
-  for (k=qhmem.LASTsize+1; k--; )
-    qhmem.indextable[k]= k;
-  i= 0;
-  for (k=0; k <= qhmem.LASTsize; k++) {
-    if (qhmem.indextable[k] <= qhmem.sizetable[i])
-      qhmem.indextable[k]= i;
-    else
-      qhmem.indextable[k]= ++i;
-  }
-} /* memsetup */
-
-/*---------------------------------
-
-  qh_memsize( size )
-    define a free list for this size
-*/
-void qh_memsize(int size) {
-  int k;
-
-  if (qhmem.LASTsize) {
-    qh_fprintf(qhmem.ferr, 6089, "qhull error (qh_memsize): called after qhmem_setup\n");
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-  size= (size + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
-  for (k=qhmem.TABLEsize; k--; ) {
-    if (qhmem.sizetable[k] == size)
-      return;
-  }
-  if (qhmem.TABLEsize < qhmem.NUMsizes)
-    qhmem.sizetable[qhmem.TABLEsize++]= size;
-  else
-    qh_fprintf(qhmem.ferr, 7060, "qhull warning (memsize): free list table has room for only %d sizes\n", qhmem.NUMsizes);
-} /* memsize */
-
-
-/*---------------------------------
-
-  qh_memstatistics( fp )
-    print out memory statistics
-
-    Verifies that qhmem.totfree == sum of freelists
-*/
-void qh_memstatistics(FILE *fp) {
-  int i;
-  int count;
-  void *object;
-
-  qh_memcheck();
-  qh_fprintf(fp, 9278, "\nmemory statistics:\n\
-%7d quick allocations\n\
-%7d short allocations\n\
-%7d long allocations\n\
-%7d short frees\n\
-%7d long frees\n\
-%7d bytes of short memory in use\n\
-%7d bytes of short memory in freelists\n\
-%7d bytes of dropped short memory\n\
-%7d bytes of unused short memory (estimated)\n\
-%7d bytes of long memory allocated (max, except for input)\n\
-%7d bytes of long memory in use (in %d pieces)\n\
-%7d bytes of short memory buffers (minus links)\n\
-%7d bytes per short memory buffer (initially %d bytes)\n",
-           qhmem.cntquick, qhmem.cntshort, qhmem.cntlong,
-           qhmem.freeshort, qhmem.freelong,
-           qhmem.totshort, qhmem.totfree,
-           qhmem.totdropped + qhmem.freesize, qhmem.totunused,
-           qhmem.maxlong, qhmem.totlong, qhmem.cntlong - qhmem.freelong,
-           qhmem.totbuffer, qhmem.BUFsize, qhmem.BUFinit);
-  if (qhmem.cntlarger) {
-    qh_fprintf(fp, 9279, "%7d calls to qh_setlarger\n%7.2g     average copy size\n",
-           qhmem.cntlarger, ((float)qhmem.totlarger)/(float)qhmem.cntlarger);
-    qh_fprintf(fp, 9280, "  freelists(bytes->count):");
-  }
-  for (i=0; i < qhmem.TABLEsize; i++) {
-    count=0;
-    for (object= qhmem.freelists[i]; object; object= *((void **)object))
-      count++;
-    qh_fprintf(fp, 9281, " %d->%d", qhmem.sizetable[i], count);
-  }
-  qh_fprintf(fp, 9282, "\n\n");
-} /* memstatistics */
-
-
-/*---------------------------------
-
-  qh_NOmem
-    turn off quick-fit memory allocation
-
-  notes:
-    uses qh_malloc() and qh_free() instead
-*/
-#else /* qh_NOmem */
-
-void *qh_memalloc(int insize) {
-  void *object;
-
-  if (!(object= qh_malloc((size_t)insize))) {
-    qh_fprintf(qhmem.ferr, 6090, "qhull error (qh_memalloc): insufficient memory\n");
-    qh_errexit(qhmem_ERRmem, NULL, NULL);
-  }
-  qhmem.cntlong++;
-  qhmem.totlong += insize;
-  if (qhmem.maxlong < qhmem.totlong)
-      qhmem.maxlong= qhmem.totlong;
-  if (qhmem.IStracing >= 5)
-    qh_fprintf(qhmem.ferr, 8060, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, insize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
-  return object;
-}
-
-void qh_memfree(void *object, int insize) {
-
-  if (!object)
-    return;
-  qh_free(object);
-  qhmem.freelong++;
-  qhmem.totlong -= insize;
-  if (qhmem.IStracing >= 5)
-    qh_fprintf(qhmem.ferr, 8061, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, insize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
-}
-
-void qh_memfreeshort(int *curlong, int *totlong) {
-  *totlong= qhmem.totlong;
-  *curlong= qhmem.cntlong - qhmem.freelong;
-  memset((char *)&qhmem, 0, sizeof(qhmem));  /* every field is 0, FALSE, NULL */
-}
-
-void qh_meminit(FILE *ferr) {
-
-  memset((char *)&qhmem, 0, sizeof(qhmem));  /* every field is 0, FALSE, NULL */
-  if (ferr)
-      qhmem.ferr= ferr;
-  else
-      qhmem.ferr= stderr;
-  if (sizeof(void*) < sizeof(int)) {
-    qh_fprintf(qhmem.ferr, 6091, "qhull internal error (qh_meminit): sizeof(void*) %d < sizeof(int) %d.  qset.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-}
-
-void qh_meminitbuffers(int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
-
-  qhmem.IStracing= tracelevel;
-}
-
-void qh_memsetup(void) {
-
-}
-
-void qh_memsize(int size) {
-
-}
-
-void qh_memstatistics(FILE *fp) {
-
-  qh_fprintf(fp, 9409, "\nmemory statistics:\n\
-%7d long allocations\n\
-%7d long frees\n\
-%7d bytes of long memory allocated (max, except for input)\n\
-%7d bytes of long memory in use (in %d pieces)\n",
-           qhmem.cntlong,
-           qhmem.freelong,
-           qhmem.maxlong, qhmem.totlong, qhmem.cntlong - qhmem.freelong);
-}
-
-#endif /* qh_NOmem */
-
-/*---------------------------------
-
-  qh_memtotal( totlong, curlong, totshort, curshort, maxlong, totbuffer )
-    Return the total, allocated long and short memory
-
-  returns:
-    Returns the total current bytes of long and short allocations
-    Returns the current count of long and short allocations
-    Returns the maximum long memory and total short buffer (minus one link per buffer)
-    Does not error (UsingLibQhull.cpp)
-*/
-void qh_memtotal(int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer) {
-    *totlong= qhmem.totlong;
-    *curlong= qhmem.cntlong - qhmem.freelong;
-    *totshort= qhmem.totshort;
-    *curshort= qhmem.cntshort + qhmem.cntquick - qhmem.freeshort;
-    *maxlong= qhmem.maxlong;
-    *totbuffer= qhmem.totbuffer;
-} /* memtotlong */
-
diff --git a/extern/libqhull/mem.h b/extern/libqhull/mem.h
deleted file mode 100644
index 453f319df3ac..000000000000
--- a/extern/libqhull/mem.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
  ---------------------------------
-
-   mem.h
-     prototypes for memory management functions
-
-   see qh-mem.htm, mem.c and qset.h
-
-   for error handling, writes message and calls
-     qh_errexit(qhmem_ERRmem, NULL, NULL) if insufficient memory
-       and
-     qh_errexit(qhmem_ERRqhull, NULL, NULL) otherwise
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/mem.h#2 $$Change: 2062 $
-   $DateTime: 2016/01/17 13:13:18 $$Author: bbarber $
-*/
-
-#ifndef qhDEFmem
-#define qhDEFmem 1
-
-#include 
-
-/*---------------------------------
-
-  qh_NOmem
-    turn off quick-fit memory allocation
-
-  notes:
-    mem.c implements Quickfit memory allocation for about 20% time
-    savings.  If it fails on your machine, try to locate the
-    problem, and send the answer to qhull@qhull.org.  If this can
-    not be done, define qh_NOmem to use malloc/free instead.
-
-   #define qh_NOmem
-*/
-
-/*---------------------------------
-
-qh_TRACEshort
-Trace short and quick memory allocations at T5
-
-*/
-#define qh_TRACEshort
-
-/*-------------------------------------------
-    to avoid bus errors, memory allocation must consider alignment requirements.
-    malloc() automatically takes care of alignment.   Since mem.c manages
-    its own memory, we need to explicitly specify alignment in
-    qh_meminitbuffers().
-
-    A safe choice is sizeof(double).  sizeof(float) may be used if doubles
-    do not occur in data structures and pointers are the same size.  Be careful
-    of machines (e.g., DEC Alpha) with large pointers.  If gcc is available,
-    use __alignof__(double) or fmax_(__alignof__(float), __alignof__(void *)).
-
-   see qh_MEMalign in user.h for qhull's alignment
-*/
-
-#define qhmem_ERRmem 4    /* matches qh_ERRmem in libqhull.h */
-#define qhmem_ERRqhull 5  /* matches qh_ERRqhull in libqhull.h */
-
-/*----------------------------------
-
-  ptr_intT
-    for casting a void * to an integer-type that holds a pointer
-    Used for integer expressions (e.g., computing qh_gethash() in poly.c)
-
-  notes:
-    WARN64 -- these notes indicate 64-bit issues
-    On 64-bit machines, a pointer may be larger than an 'int'.
-    qh_meminit()/mem.c checks that 'ptr_intT' holds a 'void*'
-    ptr_intT is typically a signed value, but not necessarily so
-    size_t is typically unsigned, but should match the parameter type
-    Qhull uses int instead of size_t except for system calls such as malloc, qsort, qh_malloc, etc.
-    This matches Qt convention and is easier to work with.
-*/
-#if (defined(__MINGW64__)) && defined(_WIN64)
-typedef long long ptr_intT;
-#elif (_MSC_VER) && defined(_WIN64)
-typedef long long ptr_intT;
-#else
-typedef long ptr_intT;
-#endif
-
-/*----------------------------------
-
-  qhmemT
-    global memory structure for mem.c
-
- notes:
-   users should ignore qhmem except for writing extensions
-   qhmem is allocated in mem.c
-
-   qhmem could be swapable like qh and qhstat, but then
-   multiple qh's and qhmem's would need to keep in synch.
-   A swapable qhmem would also waste memory buffers.  As long
-   as memory operations are atomic, there is no problem with
-   multiple qh structures being active at the same time.
-   If you need separate address spaces, you can swap the
-   contents of qhmem.
-*/
-typedef struct qhmemT qhmemT;
-extern qhmemT qhmem;
-
-#ifndef DEFsetT
-#define DEFsetT 1
-typedef struct setT setT;          /* defined in qset.h */
-#endif
-
-/* Update qhmem in mem.c if add or remove fields */
-struct qhmemT {               /* global memory management variables */
-  int      BUFsize;           /* size of memory allocation buffer */
-  int      BUFinit;           /* initial size of memory allocation buffer */
-  int      TABLEsize;         /* actual number of sizes in free list table */
-  int      NUMsizes;          /* maximum number of sizes in free list table */
-  int      LASTsize;          /* last size in free list table */
-  int      ALIGNmask;         /* worst-case alignment, must be 2^n-1 */
-  void   **freelists;          /* free list table, linked by offset 0 */
-  int     *sizetable;         /* size of each freelist */
-  int     *indextable;        /* size->index table */
-  void    *curbuffer;         /* current buffer, linked by offset 0 */
-  void    *freemem;           /*   free memory in curbuffer */
-  int      freesize;          /*   size of freemem in bytes */
-  setT    *tempstack;         /* stack of temporary memory, managed by users */
-  FILE    *ferr;              /* file for reporting errors when 'qh' may be undefined */
-  int      IStracing;         /* =5 if tracing memory allocations */
-  int      cntquick;          /* count of quick allocations */
-                              /* Note: removing statistics doesn't effect speed */
-  int      cntshort;          /* count of short allocations */
-  int      cntlong;           /* count of long allocations */
-  int      freeshort;         /* count of short memfrees */
-  int      freelong;          /* count of long memfrees */
-  int      totbuffer;         /* total short memory buffers minus buffer links */
-  int      totdropped;        /* total dropped memory at end of short memory buffers (e.g., freesize) */
-  int      totfree;           /* total size of free, short memory on freelists */
-  int      totlong;           /* total size of long memory in use */
-  int      maxlong;           /*   maximum totlong */
-  int      totshort;          /* total size of short memory in use */
-  int      totunused;         /* total unused short memory (estimated, short size - request size of first allocations) */
-  int      cntlarger;         /* count of setlarger's */
-  int      totlarger;         /* total copied by setlarger */
-};
-
-
-/*==================== -macros ====================*/
-
-/*----------------------------------
-
-  qh_memalloc_(insize, freelistp, object, type)
-    returns object of size bytes
-        assumes size<=qhmem.LASTsize and void **freelistp is a temp
-*/
-
-#if defined qh_NOmem
-#define qh_memalloc_(insize, freelistp, object, type) {\
-  object= (type*)qh_memalloc(insize); }
-#elif defined qh_TRACEshort
-#define qh_memalloc_(insize, freelistp, object, type) {\
-    freelistp= NULL; /* Avoid warnings */ \
-    object= (type*)qh_memalloc(insize); }
-#else /* !qh_NOmem */
-
-#define qh_memalloc_(insize, freelistp, object, type) {\
-  freelistp= qhmem.freelists + qhmem.indextable[insize];\
-  if ((object= (type*)*freelistp)) {\
-    qhmem.totshort += qhmem.sizetable[qhmem.indextable[insize]]; \
-    qhmem.totfree -= qhmem.sizetable[qhmem.indextable[insize]]; \
-    qhmem.cntquick++;  \
-    *freelistp= *((void **)*freelistp);\
-  }else object= (type*)qh_memalloc(insize);}
-#endif
-
-/*----------------------------------
-
-  qh_memfree_(object, insize, freelistp)
-    free up an object
-
-  notes:
-    object may be NULL
-    assumes size<=qhmem.LASTsize and void **freelistp is a temp
-*/
-#if defined qh_NOmem
-#define qh_memfree_(object, insize, freelistp) {\
-  qh_memfree(object, insize); }
-#elif defined qh_TRACEshort
-#define qh_memfree_(object, insize, freelistp) {\
-    freelistp= NULL; /* Avoid warnings */ \
-    qh_memfree(object, insize); }
-#else /* !qh_NOmem */
-
-#define qh_memfree_(object, insize, freelistp) {\
-  if (object) { \
-    qhmem.freeshort++;\
-    freelistp= qhmem.freelists + qhmem.indextable[insize];\
-    qhmem.totshort -= qhmem.sizetable[qhmem.indextable[insize]]; \
-    qhmem.totfree += qhmem.sizetable[qhmem.indextable[insize]]; \
-    *((void **)object)= *freelistp;\
-    *freelistp= object;}}
-#endif
-
-/*=============== prototypes in alphabetical order ============*/
-
-void *qh_memalloc(int insize);
-void qh_memcheck(void);
-void qh_memfree(void *object, int insize);
-void qh_memfreeshort(int *curlong, int *totlong);
-void qh_meminit(FILE *ferr);
-void qh_meminitbuffers(int tracelevel, int alignment, int numsizes,
-                        int bufsize, int bufinit);
-void qh_memsetup(void);
-void qh_memsize(int size);
-void qh_memstatistics(FILE *fp);
-void qh_memtotal(int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer);
-
-#endif /* qhDEFmem */
diff --git a/extern/libqhull/merge.c b/extern/libqhull/merge.c
deleted file mode 100644
index 22104dc0313d..000000000000
--- a/extern/libqhull/merge.c
+++ /dev/null
@@ -1,3628 +0,0 @@
-/*
  ---------------------------------
-
-   merge.c
-   merges non-convex facets
-
-   see qh-merge.htm and merge.h
-
-   other modules call qh_premerge() and qh_postmerge()
-
-   the user may call qh_postmerge() to perform additional merges.
-
-   To remove deleted facets and vertices (qhull() in libqhull.c):
-     qh_partitionvisible(!qh_ALL, &numoutside);  // visible_list, newfacet_list
-     qh_deletevisible();         // qh.visible_list
-     qh_resetlists(False, qh_RESETvisible);       // qh.visible_list newvertex_list newfacet_list
-
-   assumes qh.CENTERtype= centrum
-
-   merges occur in qh_mergefacet and in qh_mergecycle
-   vertex->neighbors not set until the first merge occurs
-
-   Copyright (c) 1993-2015 C.B. Barber.
-   $Id: //main/2015/qhull/src/libqhull/merge.c#4 $$Change: 2064 $
-   $DateTime: 2016/01/18 12:36:08 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-#ifndef qh_NOmerge
-
-/*===== functions(alphabetical after premerge and postmerge) ======*/
-
-/*---------------------------------
-
-  qh_premerge( apex, maxcentrum )
-    pre-merge nonconvex facets in qh.newfacet_list for apex
-    maxcentrum defines coplanar and concave (qh_test_appendmerge)
-
-  returns:
-    deleted facets added to qh.visible_list with facet->visible set
-
-  notes:
-    uses globals, qh.MERGEexact, qh.PREmerge
-
-  design:
-    mark duplicate ridges in qh.newfacet_list
-    merge facet cycles in qh.newfacet_list
-    merge duplicate ridges and concave facets in qh.newfacet_list
-    check merged facet cycles for degenerate and redundant facets
-    merge degenerate and redundant facets
-    collect coplanar and concave facets
-    merge concave, coplanar, degenerate, and redundant facets
-*/
-void qh_premerge(vertexT *apex, realT maxcentrum, realT maxangle) {
-  boolT othermerge= False;
-  facetT *newfacet;
-
-  if (qh ZEROcentrum && qh_checkzero(!qh_ALL))
-    return;
-  trace2((qh ferr, 2008, "qh_premerge: premerge centrum %2.2g angle %2.2g for apex v%d facetlist f%d\n",
-            maxcentrum, maxangle, apex->id, getid_(qh newfacet_list)));
-  if (qh IStracing >= 4 && qh num_facets < 50)
-    qh_printlists();
-  qh centrum_radius= maxcentrum;
-  qh cos_max= maxangle;
-  qh degen_mergeset= qh_settemp(qh TEMPsize);
-  qh facet_mergeset= qh_settemp(qh TEMPsize);
-  if (qh hull_dim >=3) {
-    qh_mark_dupridges(qh newfacet_list); /* facet_mergeset */
-    qh_mergecycle_all(qh newfacet_list, &othermerge);
-    qh_forcedmerges(&othermerge /* qh.facet_mergeset */);
-    FORALLnew_facets {  /* test samecycle merges */
-      if (!newfacet->simplicial && !newfacet->mergeridge)
-        qh_degen_redundant_neighbors(newfacet, NULL);
-    }
-    if (qh_merge_degenredundant())
-      othermerge= True;
-  }else /* qh.hull_dim == 2 */
-    qh_mergecycle_all(qh newfacet_list, &othermerge);
-  qh_flippedmerges(qh newfacet_list, &othermerge);
-  if (!qh MERGEexact || zzval_(Ztotmerge)) {
-    zinc_(Zpremergetot);
-    qh POSTmerging= False;
-    qh_getmergeset_initial(qh newfacet_list);
-    qh_all_merges(othermerge, False);
-  }
-  qh_settempfree(&qh facet_mergeset);
-  qh_settempfree(&qh degen_mergeset);
-} /* premerge */
-
-/*---------------------------------
-
-  qh_postmerge( reason, maxcentrum, maxangle, vneighbors )
-    post-merge nonconvex facets as defined by maxcentrum and maxangle
-    'reason' is for reporting progress
-    if vneighbors,
-      calls qh_test_vneighbors at end of qh_all_merge
-    if firstmerge,
-      calls qh_reducevertices before qh_getmergeset
-
-  returns:
-    if first call (qh.visible_list != qh.facet_list),
-      builds qh.facet_newlist, qh.newvertex_list
-    deleted facets added to qh.visible_list with facet->visible
-    qh.visible_list == qh.facet_list
-
-  notes:
-
-
-  design:
-    if first call
-      set qh.visible_list and qh.newfacet_list to qh.facet_list
-      add all facets to qh.newfacet_list
-      mark non-simplicial facets, facet->newmerge
-      set qh.newvertext_list to qh.vertex_list
-      add all vertices to qh.newvertex_list
-      if a pre-merge occured
-        set vertex->delridge {will retest the ridge}
-        if qh.MERGEexact
-          call qh_reducevertices()
-      if no pre-merging
-        merge flipped facets
-    determine non-convex facets
-    merge all non-convex facets
-*/
-void qh_postmerge(const char *reason, realT maxcentrum, realT maxangle,
-                      boolT vneighbors) {
-  facetT *newfacet;
-  boolT othermerges= False;
-  vertexT *vertex;
-
-  if (qh REPORTfreq || qh IStracing) {
-    qh_buildtracing(NULL, NULL);
-    qh_printsummary(qh ferr);
-    if (qh PRINTstatistics)
-      qh_printallstatistics(qh ferr, "reason");
-    qh_fprintf(qh ferr, 8062, "\n%s with 'C%.2g' and 'A%.2g'\n",
-        reason, maxcentrum, maxangle);
-  }
-  trace2((qh ferr, 2009, "qh_postmerge: postmerge.  test vneighbors? %d\n",
-            vneighbors));
-  qh centrum_radius= maxcentrum;
-  qh cos_max= maxangle;
-  qh POSTmerging= True;
-  qh degen_mergeset= qh_settemp(qh TEMPsize);
-  qh facet_mergeset= qh_settemp(qh TEMPsize);
-  if (qh visible_list != qh facet_list) {  /* first call */
-    qh NEWfacets= True;
-    qh visible_list= qh newfacet_list= qh facet_list;
-    FORALLnew_facets {
-      newfacet->newfacet= True;
-       if (!newfacet->simplicial)
-        newfacet->newmerge= True;
-     zinc_(Zpostfacets);
-    }
-    qh newvertex_list= qh vertex_list;
-    FORALLvertices
-      vertex->newlist= True;
-    if (qh VERTEXneighbors) { /* a merge has occurred */
-      FORALLvertices
-        vertex->delridge= True; /* test for redundant, needed? */
-      if (qh MERGEexact) {
-        if (qh hull_dim <= qh_DIMreduceBuild)
-          qh_reducevertices(); /* was skipped during pre-merging */
-      }
-    }
-    if (!qh PREmerge && !qh MERGEexact)
-      qh_flippedmerges(qh newfacet_list, &othermerges);
-  }
-  qh_getmergeset_initial(qh newfacet_list);
-  qh_all_merges(False, vneighbors);
-  qh_settempfree(&qh facet_mergeset);
-  qh_settempfree(&qh degen_mergeset);
-} /* post_merge */
-
-/*---------------------------------
-
-  qh_all_merges( othermerge, vneighbors )
-    merge all non-convex facets
-
-    set othermerge if already merged facets (for qh_reducevertices)
-    if vneighbors
-      tests vertex neighbors for convexity at end
-    qh.facet_mergeset lists the non-convex ridges in qh_newfacet_list
-    qh.degen_mergeset is defined
-    if qh.MERGEexact && !qh.POSTmerging,
-      does not merge coplanar facets
-
-  returns:
-    deleted facets added to qh.visible_list with facet->visible
-    deleted vertices added qh.delvertex_list with vertex->delvertex
-
-  notes:
-    unless !qh.MERGEindependent,
-      merges facets in independent sets
-    uses qh.newfacet_list as argument since merges call qh_removefacet()
-
-  design:
-    while merges occur
-      for each merge in qh.facet_mergeset
-        unless one of the facets was already merged in this pass
-          merge the facets
-        test merged facets for additional merges
-        add merges to qh.facet_mergeset
-      if vertices record neighboring facets
-        rename redundant vertices
-          update qh.facet_mergeset
-    if vneighbors ??
-      tests vertex neighbors for convexity at end
-*/
-void qh_all_merges(boolT othermerge, boolT vneighbors) {
-  facetT *facet1, *facet2;
-  mergeT *merge;
-  boolT wasmerge= True, isreduce;
-  void **freelistp;  /* used if !qh_NOmem by qh_memfree_() */
-  vertexT *vertex;
-  mergeType mergetype;
-  int numcoplanar=0, numconcave=0, numdegenredun= 0, numnewmerges= 0;
-
-  trace2((qh ferr, 2010, "qh_all_merges: starting to merge facets beginning from f%d\n",
-            getid_(qh newfacet_list)));
-  while (True) {
-    wasmerge= False;
-    while (qh_setsize(qh facet_mergeset)) {
-      while ((merge= (mergeT*)qh_setdellast(qh facet_mergeset))) {
-        facet1= merge->facet1;
-        facet2= merge->facet2;
-        mergetype= merge->type;
-        qh_memfree_(merge, (int)sizeof(mergeT), freelistp);
-        if (facet1->visible || facet2->visible) /*deleted facet*/
-          continue;
-        if ((facet1->newfacet && !facet1->tested)
-                || (facet2->newfacet && !facet2->tested)) {
-          if (qh MERGEindependent && mergetype <= MRGanglecoplanar)
-            continue;      /* perform independent sets of merges */
-        }
-        qh_merge_nonconvex(facet1, facet2, mergetype);
-        numdegenredun += qh_merge_degenredundant();
-        numnewmerges++;
-        wasmerge= True;
-        if (mergetype == MRGconcave)
-          numconcave++;
-        else /* MRGcoplanar or MRGanglecoplanar */
-          numcoplanar++;
-      } /* while setdellast */
-      if (qh POSTmerging && qh hull_dim <= qh_DIMreduceBuild
-      && numnewmerges > qh_MAXnewmerges) {
-        numnewmerges= 0;
-        qh_reducevertices();  /* otherwise large post merges too slow */
-      }
-      qh_getmergeset(qh newfacet_list); /* facet_mergeset */
-    } /* while mergeset */
-    if (qh VERTEXneighbors) {
-      isreduce= False;
-      if (qh hull_dim >=4 && qh POSTmerging) {
-        FORALLvertices
-          vertex->delridge= True;
-        isreduce= True;
-      }
-      if ((wasmerge || othermerge) && (!qh MERGEexact || qh POSTmerging)
-          && qh hull_dim <= qh_DIMreduceBuild) {
-        othermerge= False;
-        isreduce= True;
-      }
-      if (isreduce) {
-        if (qh_reducevertices()) {
-          qh_getmergeset(qh newfacet_list); /* facet_mergeset */
-          continue;
-        }
-      }
-    }
-    if (vneighbors && qh_test_vneighbors(/* qh.newfacet_list */))
-      continue;
-    break;
-  } /* while (True) */
-  if (qh CHECKfrequently && !qh MERGEexact) {
-    qh old_randomdist= qh RANDOMdist;
-    qh RANDOMdist= False;
-    qh_checkconvex(qh newfacet_list, qh_ALGORITHMfault);
-    /* qh_checkconnect(); [this is slow and it changes the facet order] */
-    qh RANDOMdist= qh old_randomdist;
-  }
-  trace1((qh ferr, 1009, "qh_all_merges: merged %d coplanar facets %d concave facets and %d degen or redundant facets.\n",
-    numcoplanar, numconcave, numdegenredun));
-  if (qh IStracing >= 4 && qh num_facets < 50)
-    qh_printlists();
-} /* all_merges */
-
-
-/*---------------------------------
-
-  qh_appendmergeset( facet, neighbor, mergetype, angle )
-    appends an entry to qh.facet_mergeset or qh.degen_mergeset
-
-    angle ignored if NULL or !qh.ANGLEmerge
-
-  returns:
-    merge appended to facet_mergeset or degen_mergeset
-      sets ->degenerate or ->redundant if degen_mergeset
-
-  see:
-    qh_test_appendmerge()
-
-  design:
-    allocate merge entry
-    if regular merge
-      append to qh.facet_mergeset
-    else if degenerate merge and qh.facet_mergeset is all degenerate
-      append to qh.degen_mergeset
-    else if degenerate merge
-      prepend to qh.degen_mergeset
-    else if redundant merge
-      append to qh.degen_mergeset
-*/
-void qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle) {
-  mergeT *merge, *lastmerge;
-  void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */
-
-  if (facet->redundant)
-    return;
-  if (facet->degenerate && mergetype == MRGdegen)
-    return;
-  qh_memalloc_((int)sizeof(mergeT), freelistp, merge, mergeT);
-  merge->facet1= facet;
-  merge->facet2= neighbor;
-  merge->type= mergetype;
-  if (angle && qh ANGLEmerge)
-    merge->angle= *angle;
-  if (mergetype < MRGdegen)
-    qh_setappend(&(qh facet_mergeset), merge);
-  else if (mergetype == MRGdegen) {
-    facet->degenerate= True;
-    if (!(lastmerge= (mergeT*)qh_setlast(qh degen_mergeset))
-    || lastmerge->type == MRGdegen)
-      qh_setappend(&(qh degen_mergeset), merge);
-    else
-      qh_setaddnth(&(qh degen_mergeset), 0, merge);
-  }else if (mergetype == MRGredundant) {
-    facet->redundant= True;
-    qh_setappend(&(qh degen_mergeset), merge);
-  }else /* mergetype == MRGmirror */ {
-    if (facet->redundant || neighbor->redundant) {
-      qh_fprintf(qh ferr, 6092, "qhull error (qh_appendmergeset): facet f%d or f%d is already a mirrored facet\n",
-           facet->id, neighbor->id);
-      qh_errexit2(qh_ERRqhull, facet, neighbor);
-    }
-    if (!qh_setequal(facet->vertices, neighbor->vertices)) {
-      qh_fprintf(qh ferr, 6093, "qhull error (qh_appendmergeset): mirrored facets f%d and f%d do not have the same vertices\n",
-           facet->id, neighbor->id);
-      qh_errexit2(qh_ERRqhull, facet, neighbor);
-    }
-    facet->redundant= True;
-    neighbor->redundant= True;
-    qh_setappend(&(qh degen_mergeset), merge);
-  }
-} /* appendmergeset */
-
-
-/*---------------------------------
-
-  qh_basevertices( samecycle )
-    return temporary set of base vertices for samecycle
-    samecycle is first facet in the cycle
-    assumes apex is SETfirst_( samecycle->vertices )
-
-  returns:
-    vertices(settemp)
-    all ->seen are cleared
-
-  notes:
-    uses qh_vertex_visit;
-
-  design:
-    for each facet in samecycle
-      for each unseen vertex in facet->vertices
-        append to result
-*/
-setT *qh_basevertices(facetT *samecycle) {
-  facetT *same;
-  vertexT *apex, *vertex, **vertexp;
-  setT *vertices= qh_settemp(qh TEMPsize);
-
-  apex= SETfirstt_(samecycle->vertices, vertexT);
-  apex->visitid= ++qh vertex_visit;
-  FORALLsame_cycle_(samecycle) {
-    if (same->mergeridge)
-      continue;
-    FOREACHvertex_(same->vertices) {
-      if (vertex->visitid != qh vertex_visit) {
-        qh_setappend(&vertices, vertex);
-        vertex->visitid= qh vertex_visit;
-        vertex->seen= False;
-      }
-    }
-  }
-  trace4((qh ferr, 4019, "qh_basevertices: found %d vertices\n",
-         qh_setsize(vertices)));
-  return vertices;
-} /* basevertices */
-
-/*---------------------------------
-
-  qh_checkconnect()
-    check that new facets are connected
-    new facets are on qh.newfacet_list
-
-  notes:
-    this is slow and it changes the order of the facets
-    uses qh.visit_id
-
-  design:
-    move first new facet to end of qh.facet_list
-    for all newly appended facets
-      append unvisited neighbors to end of qh.facet_list
-    for all new facets
-      report error if unvisited
-*/
-void qh_checkconnect(void /* qh.newfacet_list */) {
-  facetT *facet, *newfacet, *errfacet= NULL, *neighbor, **neighborp;
-
-  facet= qh newfacet_list;
-  qh_removefacet(facet);
-  qh_appendfacet(facet);
-  facet->visitid= ++qh visit_id;
-  FORALLfacet_(facet) {
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid != qh visit_id) {
-        qh_removefacet(neighbor);
-        qh_appendfacet(neighbor);
-        neighbor->visitid= qh visit_id;
-      }
-    }
-  }
-  FORALLnew_facets {
-    if (newfacet->visitid == qh visit_id)
-      break;
-    qh_fprintf(qh ferr, 6094, "qhull error: f%d is not attached to the new facets\n",
-         newfacet->id);
-    errfacet= newfacet;
-  }
-  if (errfacet)
-    qh_errexit(qh_ERRqhull, errfacet, NULL);
-} /* checkconnect */
-
-/*---------------------------------
-
-  qh_checkzero( testall )
-    check that facets are clearly convex for qh.DISTround with qh.MERGEexact
-
-    if testall,
-      test all facets for qh.MERGEexact post-merging
-    else
-      test qh.newfacet_list
-
-    if qh.MERGEexact,
-      allows coplanar ridges
-      skips convexity test while qh.ZEROall_ok
-
-  returns:
-    True if all facets !flipped, !dupridge, normal
-         if all horizon facets are simplicial
-         if all vertices are clearly below neighbor
-         if all opposite vertices of horizon are below
-    clears qh.ZEROall_ok if any problems or coplanar facets
-
-  notes:
-    uses qh.vertex_visit
-    horizon facets may define multiple new facets
-
-  design:
-    for all facets in qh.newfacet_list or qh.facet_list
-      check for flagged faults (flipped, etc.)
-    for all facets in qh.newfacet_list or qh.facet_list
-      for each neighbor of facet
-        skip horizon facets for qh.newfacet_list
-        test the opposite vertex
-      if qh.newfacet_list
-        test the other vertices in the facet's horizon facet
-*/
-boolT qh_checkzero(boolT testall) {
-  facetT *facet, *neighbor, **neighborp;
-  facetT *horizon, *facetlist;
-  int neighbor_i;
-  vertexT *vertex, **vertexp;
-  realT dist;
-
-  if (testall)
-    facetlist= qh facet_list;
-  else {
-    facetlist= qh newfacet_list;
-    FORALLfacet_(facetlist) {
-      horizon= SETfirstt_(facet->neighbors, facetT);
-      if (!horizon->simplicial)
-        goto LABELproblem;
-      if (facet->flipped || facet->dupridge || !facet->normal)
-        goto LABELproblem;
-    }
-    if (qh MERGEexact && qh ZEROall_ok) {
-      trace2((qh ferr, 2011, "qh_checkzero: skip convexity check until first pre-merge\n"));
-      return True;
-    }
-  }
-  FORALLfacet_(facetlist) {
-    qh vertex_visit++;
-    neighbor_i= 0;
-    horizon= NULL;
-    FOREACHneighbor_(facet) {
-      if (!neighbor_i && !testall) {
-        horizon= neighbor;
-        neighbor_i++;
-        continue; /* horizon facet tested in qh_findhorizon */
-      }
-      vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
-      vertex->visitid= qh vertex_visit;
-      zzinc_(Zdistzero);
-      qh_distplane(vertex->point, neighbor, &dist);
-      if (dist >= -qh DISTround) {
-        qh ZEROall_ok= False;
-        if (!qh MERGEexact || testall || dist > qh DISTround)
-          goto LABELnonconvex;
-      }
-    }
-    if (!testall && horizon) {
-      FOREACHvertex_(horizon->vertices) {
-        if (vertex->visitid != qh vertex_visit) {
-          zzinc_(Zdistzero);
-          qh_distplane(vertex->point, facet, &dist);
-          if (dist >= -qh DISTround) {
-            qh ZEROall_ok= False;
-            if (!qh MERGEexact || dist > qh DISTround)
-              goto LABELnonconvex;
-          }
-          break;
-        }
-      }
-    }
-  }
-  trace2((qh ferr, 2012, "qh_checkzero: testall %d, facets are %s\n", testall,
-        (qh MERGEexact && !testall) ?
-           "not concave, flipped, or duplicate ridged" : "clearly convex"));
-  return True;
-
- LABELproblem:
-  qh ZEROall_ok= False;
-  trace2((qh ferr, 2013, "qh_checkzero: facet f%d needs pre-merging\n",
-       facet->id));
-  return False;
-
- LABELnonconvex:
-  trace2((qh ferr, 2014, "qh_checkzero: facet f%d and f%d are not clearly convex.  v%d dist %.2g\n",
-         facet->id, neighbor->id, vertex->id, dist));
-  return False;
-} /* checkzero */
-
-/*---------------------------------
-
-  qh_compareangle( angle1, angle2 )
-    used by qsort() to order merges by angle
-*/
-int qh_compareangle(const void *p1, const void *p2) {
-  const mergeT *a= *((mergeT *const*)p1), *b= *((mergeT *const*)p2);
-
-  return((a->angle > b->angle) ? 1 : -1);
-} /* compareangle */
-
-/*---------------------------------
-
-  qh_comparemerge( merge1, merge2 )
-    used by qsort() to order merges
-*/
-int qh_comparemerge(const void *p1, const void *p2) {
-  const mergeT *a= *((mergeT *const*)p1), *b= *((mergeT *const*)p2);
-
-  return(a->type - b->type);
-} /* comparemerge */
-
-/*---------------------------------
-
-  qh_comparevisit( vertex1, vertex2 )
-    used by qsort() to order vertices by their visitid
-*/
-int qh_comparevisit(const void *p1, const void *p2) {
-  const vertexT *a= *((vertexT *const*)p1), *b= *((vertexT *const*)p2);
-
-  return(a->visitid - b->visitid);
-} /* comparevisit */
-
-/*---------------------------------
-
-  qh_copynonconvex( atridge )
-    set non-convex flag on other ridges (if any) between same neighbors
-
-  notes:
-    may be faster if use smaller ridge set
-
-  design:
-    for each ridge of atridge's top facet
-      if ridge shares the same neighbor
-        set nonconvex flag
-*/
-void qh_copynonconvex(ridgeT *atridge) {
-  facetT *facet, *otherfacet;
-  ridgeT *ridge, **ridgep;
-
-  facet= atridge->top;
-  otherfacet= atridge->bottom;
-  FOREACHridge_(facet->ridges) {
-    if (otherfacet == otherfacet_(ridge, facet) && ridge != atridge) {
-      ridge->nonconvex= True;
-      trace4((qh ferr, 4020, "qh_copynonconvex: moved nonconvex flag from r%d to r%d\n",
-              atridge->id, ridge->id));
-      break;
-    }
-  }
-} /* copynonconvex */
-
-/*---------------------------------
-
-  qh_degen_redundant_facet( facet )
-    check facet for degen. or redundancy
-
-  notes:
-    bumps vertex_visit
-    called if a facet was redundant but no longer is (qh_merge_degenredundant)
-    qh_appendmergeset() only appends first reference to facet (i.e., redundant)
-
-  see:
-    qh_degen_redundant_neighbors()
-
-  design:
-    test for redundant neighbor
-    test for degenerate facet
-*/
-void qh_degen_redundant_facet(facetT *facet) {
-  vertexT *vertex, **vertexp;
-  facetT *neighbor, **neighborp;
-
-  trace4((qh ferr, 4021, "qh_degen_redundant_facet: test facet f%d for degen/redundant\n",
-          facet->id));
-  FOREACHneighbor_(facet) {
-    qh vertex_visit++;
-    FOREACHvertex_(neighbor->vertices)
-      vertex->visitid= qh vertex_visit;
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->visitid != qh vertex_visit)
-        break;
-    }
-    if (!vertex) {
-      qh_appendmergeset(facet, neighbor, MRGredundant, NULL);
-      trace2((qh ferr, 2015, "qh_degen_redundant_facet: f%d is contained in f%d.  merge\n", facet->id, neighbor->id));
-      return;
-    }
-  }
-  if (qh_setsize(facet->neighbors) < qh hull_dim) {
-    qh_appendmergeset(facet, facet, MRGdegen, NULL);
-    trace2((qh ferr, 2016, "qh_degen_redundant_neighbors: f%d is degenerate.\n", facet->id));
-  }
-} /* degen_redundant_facet */
-
-
-/*---------------------------------
-
-  qh_degen_redundant_neighbors( facet, delfacet,  )
-    append degenerate and redundant neighbors to facet_mergeset
-    if delfacet,
-      only checks neighbors of both delfacet and facet
-    also checks current facet for degeneracy
-
-  notes:
-    bumps vertex_visit
-    called for each qh_mergefacet() and qh_mergecycle()
-    merge and statistics occur in merge_nonconvex
-    qh_appendmergeset() only appends first reference to facet (i.e., redundant)
-      it appends redundant facets after degenerate ones
-
-    a degenerate facet has fewer than hull_dim neighbors
-    a redundant facet's vertices is a subset of its neighbor's vertices
-    tests for redundant merges first (appendmergeset is nop for others)
-    in a merge, only needs to test neighbors of merged facet
-
-  see:
-    qh_merge_degenredundant() and qh_degen_redundant_facet()
-
-  design:
-    test for degenerate facet
-    test for redundant neighbor
-    test for degenerate neighbor
-*/
-void qh_degen_redundant_neighbors(facetT *facet, facetT *delfacet) {
-  vertexT *vertex, **vertexp;
-  facetT *neighbor, **neighborp;
-  int size;
-
-  trace4((qh ferr, 4022, "qh_degen_redundant_neighbors: test neighbors of f%d with delfacet f%d\n",
-          facet->id, getid_(delfacet)));
-  if ((size= qh_setsize(facet->neighbors)) < qh hull_dim) {
-    qh_appendmergeset(facet, facet, MRGdegen, NULL);
-    trace2((qh ferr, 2017, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors.\n", facet->id, size));
-  }
-  if (!delfacet)
-    delfacet= facet;
-  qh vertex_visit++;
-  FOREACHvertex_(facet->vertices)
-    vertex->visitid= qh vertex_visit;
-  FOREACHneighbor_(delfacet) {
-    /* uses early out instead of checking vertex count */
-    if (neighbor == facet)
-      continue;
-    FOREACHvertex_(neighbor->vertices) {
-      if (vertex->visitid != qh vertex_visit)
-        break;
-    }
-    if (!vertex) {
-      qh_appendmergeset(neighbor, facet, MRGredundant, NULL);
-      trace2((qh ferr, 2018, "qh_degen_redundant_neighbors: f%d is contained in f%d.  merge\n", neighbor->id, facet->id));
-    }
-  }
-  FOREACHneighbor_(delfacet) {   /* redundant merges occur first */
-    if (neighbor == facet)
-      continue;
-    if ((size= qh_setsize(neighbor->neighbors)) < qh hull_dim) {
-      qh_appendmergeset(neighbor, neighbor, MRGdegen, NULL);
-      trace2((qh ferr, 2019, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors.  Neighbor of f%d.\n", neighbor->id, size, facet->id));
-    }
-  }
-} /* degen_redundant_neighbors */
-
-
-/*---------------------------------
-
-  qh_find_newvertex( oldvertex, vertices, ridges )
-    locate new vertex for renaming old vertex
-    vertices is a set of possible new vertices
-      vertices sorted by number of deleted ridges
-
-  returns:
-    newvertex or NULL
-      each ridge includes both vertex and oldvertex
-    vertices sorted by number of deleted ridges
-
-  notes:
-    modifies vertex->visitid
-    new vertex is in one of the ridges
-    renaming will not cause a duplicate ridge
-    renaming will minimize the number of deleted ridges
-    newvertex may not be adjacent in the dual (though unlikely)
-
-  design:
-    for each vertex in vertices
-      set vertex->visitid to number of references in ridges
-    remove unvisited vertices
-    set qh.vertex_visit above all possible values
-    sort vertices by number of references in ridges
-    add each ridge to qh.hash_table
-    for each vertex in vertices
-      look for a vertex that would not cause a duplicate ridge after a rename
-*/
-vertexT *qh_find_newvertex(vertexT *oldvertex, setT *vertices, setT *ridges) {
-  vertexT *vertex, **vertexp;
-  setT *newridges;
-  ridgeT *ridge, **ridgep;
-  int size, hashsize;
-  int hash;
-
-#ifndef qh_NOtrace
-  if (qh IStracing >= 4) {
-    qh_fprintf(qh ferr, 8063, "qh_find_newvertex: find new vertex for v%d from ",
-             oldvertex->id);
-    FOREACHvertex_(vertices)
-      qh_fprintf(qh ferr, 8064, "v%d ", vertex->id);
-    FOREACHridge_(ridges)
-      qh_fprintf(qh ferr, 8065, "r%d ", ridge->id);
-    qh_fprintf(qh ferr, 8066, "\n");
-  }
-#endif
-  FOREACHvertex_(vertices)
-    vertex->visitid= 0;
-  FOREACHridge_(ridges) {
-    FOREACHvertex_(ridge->vertices)
-      vertex->visitid++;
-  }
-  FOREACHvertex_(vertices) {
-    if (!vertex->visitid) {
-      qh_setdelnth(vertices, SETindex_(vertices,vertex));
-      vertexp--; /* repeat since deleted this vertex */
-    }
-  }
-  qh vertex_visit += (unsigned int)qh_setsize(ridges);
-  if (!qh_setsize(vertices)) {
-    trace4((qh ferr, 4023, "qh_find_newvertex: vertices not in ridges for v%d\n",
-            oldvertex->id));
-    return NULL;
-  }
-  qsort(SETaddr_(vertices, vertexT), (size_t)qh_setsize(vertices),
-                sizeof(vertexT *), qh_comparevisit);
-  /* can now use qh vertex_visit */
-  if (qh PRINTstatistics) {
-    size= qh_setsize(vertices);
-    zinc_(Zintersect);
-    zadd_(Zintersecttot, size);
-    zmax_(Zintersectmax, size);
-  }
-  hashsize= qh_newhashtable(qh_setsize(ridges));
-  FOREACHridge_(ridges)
-    qh_hashridge(qh hash_table, hashsize, ridge, oldvertex);
-  FOREACHvertex_(vertices) {
-    newridges= qh_vertexridges(vertex);
-    FOREACHridge_(newridges) {
-      if (qh_hashridge_find(qh hash_table, hashsize, ridge, vertex, oldvertex, &hash)) {
-        zinc_(Zdupridge);
-        break;
-      }
-    }
-    qh_settempfree(&newridges);
-    if (!ridge)
-      break;  /* found a rename */
-  }
-  if (vertex) {
-    /* counted in qh_renamevertex */
-    trace2((qh ferr, 2020, "qh_find_newvertex: found v%d for old v%d from %d vertices and %d ridges.\n",
-      vertex->id, oldvertex->id, qh_setsize(vertices), qh_setsize(ridges)));
-  }else {
-    zinc_(Zfindfail);
-    trace0((qh ferr, 14, "qh_find_newvertex: no vertex for renaming v%d(all duplicated ridges) during p%d\n",
-      oldvertex->id, qh furthest_id));
-  }
-  qh_setfree(&qh hash_table);
-  return vertex;
-} /* find_newvertex */
-
-/*---------------------------------
-
-  qh_findbest_test( testcentrum, facet, neighbor, bestfacet, dist, mindist, maxdist )
-    test neighbor of facet for qh_findbestneighbor()
-    if testcentrum,
-      tests centrum (assumes it is defined)
-    else
-      tests vertices
-
-  returns:
-    if a better facet (i.e., vertices/centrum of facet closer to neighbor)
-      updates bestfacet, dist, mindist, and maxdist
-*/
-void qh_findbest_test(boolT testcentrum, facetT *facet, facetT *neighbor,
-      facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp) {
-  realT dist, mindist, maxdist;
-
-  if (testcentrum) {
-    zzinc_(Zbestdist);
-    qh_distplane(facet->center, neighbor, &dist);
-    dist *= qh hull_dim; /* estimate furthest vertex */
-    if (dist < 0) {
-      maxdist= 0;
-      mindist= dist;
-      dist= -dist;
-    }else {
-      mindist= 0;
-      maxdist= dist;
-    }
-  }else
-    dist= qh_getdistance(facet, neighbor, &mindist, &maxdist);
-  if (dist < *distp) {
-    *bestfacet= neighbor;
-    *mindistp= mindist;
-    *maxdistp= maxdist;
-    *distp= dist;
-  }
-} /* findbest_test */
-
-/*---------------------------------
-
-  qh_findbestneighbor( facet, dist, mindist, maxdist )
-    finds best neighbor (least dist) of a facet for merging
-
-  returns:
-    returns min and max distances and their max absolute value
-
-  notes:
-    error if qh_ASvoronoi
-    avoids merging old into new
-    assumes ridge->nonconvex only set on one ridge between a pair of facets
-    could use an early out predicate but not worth it
-
-  design:
-    if a large facet
-      will test centrum
-    else
-      will test vertices
-    if a large facet
-      test nonconvex neighbors for best merge
-    else
-      test all neighbors for the best merge
-    if testing centrum
-      get distance information
-*/
-facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp) {
-  facetT *neighbor, **neighborp, *bestfacet= NULL;
-  ridgeT *ridge, **ridgep;
-  boolT nonconvex= True, testcentrum= False;
-  int size= qh_setsize(facet->vertices);
-
-  if(qh CENTERtype==qh_ASvoronoi){
-    qh_fprintf(qh ferr, 6272, "qhull error: cannot call qh_findbestneighor for f%d while qh.CENTERtype is qh_ASvoronoi\n", facet->id);
-    qh_errexit(qh_ERRqhull, facet, NULL);
-  }
-  *distp= REALmax;
-  if (size > qh_BESTcentrum2 * qh hull_dim + qh_BESTcentrum) {
-    testcentrum= True;
-    zinc_(Zbestcentrum);
-    if (!facet->center)
-       facet->center= qh_getcentrum(facet);
-  }
-  if (size > qh hull_dim + qh_BESTnonconvex) {
-    FOREACHridge_(facet->ridges) {
-      if (ridge->nonconvex) {
-        neighbor= otherfacet_(ridge, facet);
-        qh_findbest_test(testcentrum, facet, neighbor,
-                          &bestfacet, distp, mindistp, maxdistp);
-      }
-    }
-  }
-  if (!bestfacet) {
-    nonconvex= False;
-    FOREACHneighbor_(facet)
-      qh_findbest_test(testcentrum, facet, neighbor,
-                        &bestfacet, distp, mindistp, maxdistp);
-  }
-  if (!bestfacet) {
-    qh_fprintf(qh ferr, 6095, "qhull internal error (qh_findbestneighbor): no neighbors for f%d\n", facet->id);
-
-    qh_errexit(qh_ERRqhull, facet, NULL);
-  }
-  if (testcentrum)
-    qh_getdistance(facet, bestfacet, mindistp, maxdistp);
-  trace3((qh ferr, 3002, "qh_findbestneighbor: f%d is best neighbor for f%d testcentrum? %d nonconvex? %d dist %2.2g min %2.2g max %2.2g\n",
-     bestfacet->id, facet->id, testcentrum, nonconvex, *distp, *mindistp, *maxdistp));
-  return(bestfacet);
-} /* findbestneighbor */
-
-
-/*---------------------------------
-
-  qh_flippedmerges( facetlist, wasmerge )
-    merge flipped facets into best neighbor
-    assumes qh.facet_mergeset at top of temporary stack
-
-  returns:
-    no flipped facets on facetlist
-    sets wasmerge if merge occurred
-    degen/redundant merges passed through
-
-  notes:
-    othermerges not needed since qh.facet_mergeset is empty before & after
-      keep it in case of change
-
-  design:
-    append flipped facets to qh.facetmergeset
-    for each flipped merge
-      find best neighbor
-      merge facet into neighbor
-      merge degenerate and redundant facets
-    remove flipped merges from qh.facet_mergeset
-*/
-void qh_flippedmerges(facetT *facetlist, boolT *wasmerge) {
-  facetT *facet, *neighbor, *facet1;
-  realT dist, mindist, maxdist;
-  mergeT *merge, **mergep;
-  setT *othermerges;
-  int nummerge=0;
-
-  trace4((qh ferr, 4024, "qh_flippedmerges: begin\n"));
-  FORALLfacet_(facetlist) {
-    if (facet->flipped && !facet->visible)
-      qh_appendmergeset(facet, facet, MRGflip, NULL);
-  }
-  othermerges= qh_settemppop(); /* was facet_mergeset */
-  qh facet_mergeset= qh_settemp(qh TEMPsize);
-  qh_settemppush(othermerges);
-  FOREACHmerge_(othermerges) {
-    facet1= merge->facet1;
-    if (merge->type != MRGflip || facet1->visible)
-      continue;
-    if (qh TRACEmerge-1 == zzval_(Ztotmerge))
-      qhmem.IStracing= qh IStracing= qh TRACElevel;
-    neighbor= qh_findbestneighbor(facet1, &dist, &mindist, &maxdist);
-    trace0((qh ferr, 15, "qh_flippedmerges: merge flipped f%d into f%d dist %2.2g during p%d\n",
-      facet1->id, neighbor->id, dist, qh furthest_id));
-    qh_mergefacet(facet1, neighbor, &mindist, &maxdist, !qh_MERGEapex);
-    nummerge++;
-    if (qh PRINTstatistics) {
-      zinc_(Zflipped);
-      wadd_(Wflippedtot, dist);
-      wmax_(Wflippedmax, dist);
-    }
-    qh_merge_degenredundant();
-  }
-  FOREACHmerge_(othermerges) {
-    if (merge->facet1->visible || merge->facet2->visible)
-      qh_memfree(merge, (int)sizeof(mergeT));
-    else
-      qh_setappend(&qh facet_mergeset, merge);
-  }
-  qh_settempfree(&othermerges);
-  if (nummerge)
-    *wasmerge= True;
-  trace1((qh ferr, 1010, "qh_flippedmerges: merged %d flipped facets into a good neighbor\n", nummerge));
-} /* flippedmerges */
-
-
-/*---------------------------------
-
-  qh_forcedmerges( wasmerge )
-    merge duplicated ridges
-
-  returns:
-    removes all duplicate ridges on facet_mergeset
-    wasmerge set if merge
-    qh.facet_mergeset may include non-forced merges(none for now)
-    qh.degen_mergeset includes degen/redun merges
-
-  notes:
-    duplicate ridges occur when the horizon is pinched,
-        i.e. a subridge occurs in more than two horizon ridges.
-     could rename vertices that pinch the horizon
-    assumes qh_merge_degenredundant() has not be called
-    othermerges isn't needed since facet_mergeset is empty afterwards
-      keep it in case of change
-
-  design:
-    for each duplicate ridge
-      find current facets by chasing f.replace links
-      check for wide merge due to duplicate ridge
-      determine best direction for facet
-      merge one facet into the other
-      remove duplicate ridges from qh.facet_mergeset
-*/
-void qh_forcedmerges(boolT *wasmerge) {
-  facetT *facet1, *facet2;
-  mergeT *merge, **mergep;
-  realT dist1, dist2, mindist1, mindist2, maxdist1, maxdist2;
-  setT *othermerges;
-  int nummerge=0, numflip=0;
-
-  if (qh TRACEmerge-1 == zzval_(Ztotmerge))
-    qhmem.IStracing= qh IStracing= qh TRACElevel;
-  trace4((qh ferr, 4025, "qh_forcedmerges: begin\n"));
-  othermerges= qh_settemppop(); /* was facet_mergeset */
-  qh facet_mergeset= qh_settemp(qh TEMPsize);
-  qh_settemppush(othermerges);
-  FOREACHmerge_(othermerges) {
-    if (merge->type != MRGridge)
-        continue;
-    if (qh TRACEmerge-1 == zzval_(Ztotmerge))
-        qhmem.IStracing= qh IStracing= qh TRACElevel;
-    facet1= merge->facet1;
-    facet2= merge->facet2;
-    while (facet1->visible)      /* must exist, no qh_merge_degenredunant */
-      facet1= facet1->f.replace; /* previously merged facet */
-    while (facet2->visible)
-      facet2= facet2->f.replace; /* previously merged facet */
-    if (facet1 == facet2)
-      continue;
-    if (!qh_setin(facet2->neighbors, facet1)) {
-      qh_fprintf(qh ferr, 6096, "qhull internal error (qh_forcedmerges): f%d and f%d had a duplicate ridge but as f%d and f%d they are no longer neighbors\n",
-               merge->facet1->id, merge->facet2->id, facet1->id, facet2->id);
-      qh_errexit2(qh_ERRqhull, facet1, facet2);
-    }
-    dist1= qh_getdistance(facet1, facet2, &mindist1, &maxdist1);
-    dist2= qh_getdistance(facet2, facet1, &mindist2, &maxdist2);
-    qh_check_dupridge(facet1, dist1, facet2, dist2);
-    if (dist1 < dist2)
-      qh_mergefacet(facet1, facet2, &mindist1, &maxdist1, !qh_MERGEapex);
-    else {
-      qh_mergefacet(facet2, facet1, &mindist2, &maxdist2, !qh_MERGEapex);
-      dist1= dist2;
-      facet1= facet2;
-    }
-    if (facet1->flipped) {
-      zinc_(Zmergeflipdup);
-      numflip++;
-    }else
-      nummerge++;
-    if (qh PRINTstatistics) {
-      zinc_(Zduplicate);
-      wadd_(Wduplicatetot, dist1);
-      wmax_(Wduplicatemax, dist1);
-    }
-  }
-  FOREACHmerge_(othermerges) {
-    if (merge->type == MRGridge)
-      qh_memfree(merge, (int)sizeof(mergeT));
-    else
-      qh_setappend(&qh facet_mergeset, merge);
-  }
-  qh_settempfree(&othermerges);
-  if (nummerge)
-    *wasmerge= True;
-  trace1((qh ferr, 1011, "qh_forcedmerges: merged %d facets and %d flipped facets across duplicated ridges\n",
-                nummerge, numflip));
-} /* forcedmerges */
-
-
-/*---------------------------------
-
-  qh_getmergeset( facetlist )
-    determines nonconvex facets on facetlist
-    tests !tested ridges and nonconvex ridges of !tested facets
-
-  returns:
-    returns sorted qh.facet_mergeset of facet-neighbor pairs to be merged
-    all ridges tested
-
-  notes:
-    assumes no nonconvex ridges with both facets tested
-    uses facet->tested/ridge->tested to prevent duplicate tests
-    can not limit tests to modified ridges since the centrum changed
-    uses qh.visit_id
-
-  see:
-    qh_getmergeset_initial()
-
-  design:
-    for each facet on facetlist
-      for each ridge of facet
-        if untested ridge
-          test ridge for convexity
-          if non-convex
-            append ridge to qh.facet_mergeset
-    sort qh.facet_mergeset by angle
-*/
-void qh_getmergeset(facetT *facetlist) {
-  facetT *facet, *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-  int nummerges;
-
-  nummerges= qh_setsize(qh facet_mergeset);
-  trace4((qh ferr, 4026, "qh_getmergeset: started.\n"));
-  qh visit_id++;
-  FORALLfacet_(facetlist) {
-    if (facet->tested)
-      continue;
-    facet->visitid= qh visit_id;
-    facet->tested= True;  /* must be non-simplicial due to merge */
-    FOREACHneighbor_(facet)
-      neighbor->seen= False;
-    FOREACHridge_(facet->ridges) {
-      if (ridge->tested && !ridge->nonconvex)
-        continue;
-      /* if tested & nonconvex, need to append merge */
-      neighbor= otherfacet_(ridge, facet);
-      if (neighbor->seen) {
-        ridge->tested= True;
-        ridge->nonconvex= False;
-      }else if (neighbor->visitid != qh visit_id) {
-        ridge->tested= True;
-        ridge->nonconvex= False;
-        neighbor->seen= True;      /* only one ridge is marked nonconvex */
-        if (qh_test_appendmerge(facet, neighbor))
-          ridge->nonconvex= True;
-      }
-    }
-  }
-  nummerges= qh_setsize(qh facet_mergeset);
-  if (qh ANGLEmerge)
-    qsort(SETaddr_(qh facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_compareangle);
-  else
-    qsort(SETaddr_(qh facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_comparemerge);
-  if (qh POSTmerging) {
-    zadd_(Zmergesettot2, nummerges);
-  }else {
-    zadd_(Zmergesettot, nummerges);
-    zmax_(Zmergesetmax, nummerges);
-  }
-  trace2((qh ferr, 2021, "qh_getmergeset: %d merges found\n", nummerges));
-} /* getmergeset */
-
-
-/*---------------------------------
-
-  qh_getmergeset_initial( facetlist )
-    determine initial qh.facet_mergeset for facets
-    tests all facet/neighbor pairs on facetlist
-
-  returns:
-    sorted qh.facet_mergeset with nonconvex ridges
-    sets facet->tested, ridge->tested, and ridge->nonconvex
-
-  notes:
-    uses visit_id, assumes ridge->nonconvex is False
-
-  see:
-    qh_getmergeset()
-
-  design:
-    for each facet on facetlist
-      for each untested neighbor of facet
-        test facet and neighbor for convexity
-        if non-convex
-          append merge to qh.facet_mergeset
-          mark one of the ridges as nonconvex
-    sort qh.facet_mergeset by angle
-*/
-void qh_getmergeset_initial(facetT *facetlist) {
-  facetT *facet, *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-  int nummerges;
-
-  qh visit_id++;
-  FORALLfacet_(facetlist) {
-    facet->visitid= qh visit_id;
-    facet->tested= True;
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid != qh visit_id) {
-        if (qh_test_appendmerge(facet, neighbor)) {
-          FOREACHridge_(neighbor->ridges) {
-            if (facet == otherfacet_(ridge, neighbor)) {
-              ridge->nonconvex= True;
-              break;    /* only one ridge is marked nonconvex */
-            }
-          }
-        }
-      }
-    }
-    FOREACHridge_(facet->ridges)
-      ridge->tested= True;
-  }
-  nummerges= qh_setsize(qh facet_mergeset);
-  if (qh ANGLEmerge)
-    qsort(SETaddr_(qh facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_compareangle);
-  else
-    qsort(SETaddr_(qh facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_comparemerge);
-  if (qh POSTmerging) {
-    zadd_(Zmergeinittot2, nummerges);
-  }else {
-    zadd_(Zmergeinittot, nummerges);
-    zmax_(Zmergeinitmax, nummerges);
-  }
-  trace2((qh ferr, 2022, "qh_getmergeset_initial: %d merges found\n", nummerges));
-} /* getmergeset_initial */
-
-
-/*---------------------------------
-
-  qh_hashridge( hashtable, hashsize, ridge, oldvertex )
-    add ridge to hashtable without oldvertex
-
-  notes:
-    assumes hashtable is large enough
-
-  design:
-    determine hash value for ridge without oldvertex
-    find next empty slot for ridge
-*/
-void qh_hashridge(setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex) {
-  int hash;
-  ridgeT *ridgeA;
-
-  hash= qh_gethash(hashsize, ridge->vertices, qh hull_dim-1, 0, oldvertex);
-  while (True) {
-    if (!(ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
-      SETelem_(hashtable, hash)= ridge;
-      break;
-    }else if (ridgeA == ridge)
-      break;
-    if (++hash == hashsize)
-      hash= 0;
-  }
-} /* hashridge */
-
-
-/*---------------------------------
-
-  qh_hashridge_find( hashtable, hashsize, ridge, vertex, oldvertex, hashslot )
-    returns matching ridge without oldvertex in hashtable
-      for ridge without vertex
-    if oldvertex is NULL
-      matches with any one skip
-
-  returns:
-    matching ridge or NULL
-    if no match,
-      if ridge already in   table
-        hashslot= -1
-      else
-        hashslot= next NULL index
-
-  notes:
-    assumes hashtable is large enough
-    can't match ridge to itself
-
-  design:
-    get hash value for ridge without vertex
-    for each hashslot
-      return match if ridge matches ridgeA without oldvertex
-*/
-ridgeT *qh_hashridge_find(setT *hashtable, int hashsize, ridgeT *ridge,
-              vertexT *vertex, vertexT *oldvertex, int *hashslot) {
-  int hash;
-  ridgeT *ridgeA;
-
-  *hashslot= 0;
-  zinc_(Zhashridge);
-  hash= qh_gethash(hashsize, ridge->vertices, qh hull_dim-1, 0, vertex);
-  while ((ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
-    if (ridgeA == ridge)
-      *hashslot= -1;
-    else {
-      zinc_(Zhashridgetest);
-      if (qh_setequal_except(ridge->vertices, vertex, ridgeA->vertices, oldvertex))
-        return ridgeA;
-    }
-    if (++hash == hashsize)
-      hash= 0;
-  }
-  if (!*hashslot)
-    *hashslot= hash;
-  return NULL;
-} /* hashridge_find */
-
-
-/*---------------------------------
-
-  qh_makeridges( facet )
-    creates explicit ridges between simplicial facets
-
-  returns:
-    facet with ridges and without qh_MERGEridge
-    ->simplicial is False
-
-  notes:
-    allows qh_MERGEridge flag
-    uses existing ridges
-    duplicate neighbors ok if ridges already exist (qh_mergecycle_ridges)
-
-  see:
-    qh_mergecycle_ridges()
-
-  design:
-    look for qh_MERGEridge neighbors
-    mark neighbors that already have ridges
-    for each unprocessed neighbor of facet
-      create a ridge for neighbor and facet
-    if any qh_MERGEridge neighbors
-      delete qh_MERGEridge flags (already handled by qh_mark_dupridges)
-*/
-void qh_makeridges(facetT *facet) {
-  facetT *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-  int neighbor_i, neighbor_n;
-  boolT toporient, mergeridge= False;
-
-  if (!facet->simplicial)
-    return;
-  trace4((qh ferr, 4027, "qh_makeridges: make ridges for f%d\n", facet->id));
-  facet->simplicial= False;
-  FOREACHneighbor_(facet) {
-    if (neighbor == qh_MERGEridge)
-      mergeridge= True;
-    else
-      neighbor->seen= False;
-  }
-  FOREACHridge_(facet->ridges)
-    otherfacet_(ridge, facet)->seen= True;
-  FOREACHneighbor_i_(facet) {
-    if (neighbor == qh_MERGEridge)
-      continue;  /* fixed by qh_mark_dupridges */
-    else if (!neighbor->seen) {  /* no current ridges */
-      ridge= qh_newridge();
-      ridge->vertices= qh_setnew_delnthsorted(facet->vertices, qh hull_dim,
-                                                          neighbor_i, 0);
-      toporient= facet->toporient ^ (neighbor_i & 0x1);
-      if (toporient) {
-        ridge->top= facet;
-        ridge->bottom= neighbor;
-      }else {
-        ridge->top= neighbor;
-        ridge->bottom= facet;
-      }
-#if 0 /* this also works */
-      flip= (facet->toporient ^ neighbor->toporient)^(skip1 & 0x1) ^ (skip2 & 0x1);
-      if (facet->toporient ^ (skip1 & 0x1) ^ flip) {
-        ridge->top= neighbor;
-        ridge->bottom= facet;
-      }else {
-        ridge->top= facet;
-        ridge->bottom= neighbor;
-      }
-#endif
-      qh_setappend(&(facet->ridges), ridge);
-      qh_setappend(&(neighbor->ridges), ridge);
-    }
-  }
-  if (mergeridge) {
-    while (qh_setdel(facet->neighbors, qh_MERGEridge))
-      ; /* delete each one */
-  }
-} /* makeridges */
-
-
-/*---------------------------------
-
-  qh_mark_dupridges( facetlist )
-    add duplicated ridges to qh.facet_mergeset
-    facet->dupridge is true
-
-  returns:
-    duplicate ridges on qh.facet_mergeset
-    ->mergeridge/->mergeridge2 set
-    duplicate ridges marked by qh_MERGEridge and both sides facet->dupridge
-    no MERGEridges in neighbor sets
-
-  notes:
-    duplicate ridges occur when the horizon is pinched,
-        i.e. a subridge occurs in more than two horizon ridges.
-    could rename vertices that pinch the horizon (thus removing subridge)
-    uses qh.visit_id
-
-  design:
-    for all facets on facetlist
-      if facet contains a duplicate ridge
-        for each neighbor of facet
-          if neighbor marked qh_MERGEridge (one side of the merge)
-            set facet->mergeridge
-          else
-            if neighbor contains a duplicate ridge
-            and the back link is qh_MERGEridge
-              append duplicate ridge to qh.facet_mergeset
-   for each duplicate ridge
-     make ridge sets in preparation for merging
-     remove qh_MERGEridge from neighbor set
-   for each duplicate ridge
-     restore the missing neighbor from the neighbor set that was qh_MERGEridge
-     add the missing ridge for this neighbor
-*/
-void qh_mark_dupridges(facetT *facetlist) {
-  facetT *facet, *neighbor, **neighborp;
-  int nummerge=0;
-  mergeT *merge, **mergep;
-
-
-  trace4((qh ferr, 4028, "qh_mark_dupridges: identify duplicate ridges\n"));
-  FORALLfacet_(facetlist) {
-    if (facet->dupridge) {
-      FOREACHneighbor_(facet) {
-        if (neighbor == qh_MERGEridge) {
-          facet->mergeridge= True;
-          continue;
-        }
-        if (neighbor->dupridge
-        && !qh_setin(neighbor->neighbors, facet)) { /* qh_MERGEridge */
-          qh_appendmergeset(facet, neighbor, MRGridge, NULL);
-          facet->mergeridge2= True;
-          facet->mergeridge= True;
-          nummerge++;
-        }
-      }
-    }
-  }
-  if (!nummerge)
-    return;
-  FORALLfacet_(facetlist) {            /* gets rid of qh_MERGEridge */
-    if (facet->mergeridge && !facet->mergeridge2)
-      qh_makeridges(facet);
-  }
-  FOREACHmerge_(qh facet_mergeset) {   /* restore the missing neighbors */
-    if (merge->type == MRGridge) {
-      qh_setappend(&merge->facet2->neighbors, merge->facet1);
-      qh_makeridges(merge->facet1);   /* and the missing ridges */
-    }
-  }
-  trace1((qh ferr, 1012, "qh_mark_dupridges: found %d duplicated ridges\n",
-                nummerge));
-} /* mark_dupridges */
-
-/*---------------------------------
-
-  qh_maydropneighbor( facet )
-    drop neighbor relationship if no ridge between facet and neighbor
-
-  returns:
-    neighbor sets updated
-    appends degenerate facets to qh.facet_mergeset
-
-  notes:
-    won't cause redundant facets since vertex inclusion is the same
-    may drop vertex and neighbor if no ridge
-    uses qh.visit_id
-
-  design:
-    visit all neighbors with ridges
-    for each unvisited neighbor of facet
-      delete neighbor and facet from the neighbor sets
-      if neighbor becomes degenerate
-        append neighbor to qh.degen_mergeset
-    if facet is degenerate
-      append facet to qh.degen_mergeset
-*/
-void qh_maydropneighbor(facetT *facet) {
-  ridgeT *ridge, **ridgep;
-  realT angledegen= qh_ANGLEdegen;
-  facetT *neighbor, **neighborp;
-
-  qh visit_id++;
-  trace4((qh ferr, 4029, "qh_maydropneighbor: test f%d for no ridges to a neighbor\n",
-          facet->id));
-  FOREACHridge_(facet->ridges) {
-    ridge->top->visitid= qh visit_id;
-    ridge->bottom->visitid= qh visit_id;
-  }
-  FOREACHneighbor_(facet) {
-    if (neighbor->visitid != qh visit_id) {
-      trace0((qh ferr, 17, "qh_maydropneighbor: facets f%d and f%d are no longer neighbors during p%d\n",
-            facet->id, neighbor->id, qh furthest_id));
-      zinc_(Zdropneighbor);
-      qh_setdel(facet->neighbors, neighbor);
-      neighborp--;  /* repeat, deleted a neighbor */
-      qh_setdel(neighbor->neighbors, facet);
-      if (qh_setsize(neighbor->neighbors) < qh hull_dim) {
-        zinc_(Zdropdegen);
-        qh_appendmergeset(neighbor, neighbor, MRGdegen, &angledegen);
-        trace2((qh ferr, 2023, "qh_maydropneighbors: f%d is degenerate.\n", neighbor->id));
-      }
-    }
-  }
-  if (qh_setsize(facet->neighbors) < qh hull_dim) {
-    zinc_(Zdropdegen);
-    qh_appendmergeset(facet, facet, MRGdegen, &angledegen);
-    trace2((qh ferr, 2024, "qh_maydropneighbors: f%d is degenerate.\n", facet->id));
-  }
-} /* maydropneighbor */
-
-
-/*---------------------------------
-
-  qh_merge_degenredundant()
-    merge all degenerate and redundant facets
-    qh.degen_mergeset contains merges from qh_degen_redundant_neighbors()
-
-  returns:
-    number of merges performed
-    resets facet->degenerate/redundant
-    if deleted (visible) facet has no neighbors
-      sets ->f.replace to NULL
-
-  notes:
-    redundant merges happen before degenerate ones
-    merging and renaming vertices can result in degen/redundant facets
-
-  design:
-    for each merge on qh.degen_mergeset
-      if redundant merge
-        if non-redundant facet merged into redundant facet
-          recheck facet for redundancy
-        else
-          merge redundant facet into other facet
-*/
-int qh_merge_degenredundant(void) {
-  int size;
-  mergeT *merge;
-  facetT *bestneighbor, *facet1, *facet2;
-  realT dist, mindist, maxdist;
-  vertexT *vertex, **vertexp;
-  int nummerges= 0;
-  mergeType mergetype;
-
-  while ((merge= (mergeT*)qh_setdellast(qh degen_mergeset))) {
-    facet1= merge->facet1;
-    facet2= merge->facet2;
-    mergetype= merge->type;
-    qh_memfree(merge, (int)sizeof(mergeT));
-    if (facet1->visible)
-      continue;
-    facet1->degenerate= False;
-    facet1->redundant= False;
-    if (qh TRACEmerge-1 == zzval_(Ztotmerge))
-      qhmem.IStracing= qh IStracing= qh TRACElevel;
-    if (mergetype == MRGredundant) {
-      zinc_(Zneighbor);
-      while (facet2->visible) {
-        if (!facet2->f.replace) {
-          qh_fprintf(qh ferr, 6097, "qhull internal error (qh_merge_degenredunant): f%d redundant but f%d has no replacement\n",
-               facet1->id, facet2->id);
-          qh_errexit2(qh_ERRqhull, facet1, facet2);
-        }
-        facet2= facet2->f.replace;
-      }
-      if (facet1 == facet2) {
-        qh_degen_redundant_facet(facet1); /* in case of others */
-        continue;
-      }
-      trace2((qh ferr, 2025, "qh_merge_degenredundant: facet f%d is contained in f%d, will merge\n",
-            facet1->id, facet2->id));
-      qh_mergefacet(facet1, facet2, NULL, NULL, !qh_MERGEapex);
-      /* merge distance is already accounted for */
-      nummerges++;
-    }else {  /* mergetype == MRGdegen, other merges may have fixed */
-      if (!(size= qh_setsize(facet1->neighbors))) {
-        zinc_(Zdelfacetdup);
-        trace2((qh ferr, 2026, "qh_merge_degenredundant: facet f%d has no neighbors.  Deleted\n", facet1->id));
-        qh_willdelete(facet1, NULL);
-        FOREACHvertex_(facet1->vertices) {
-          qh_setdel(vertex->neighbors, facet1);
-          if (!SETfirst_(vertex->neighbors)) {
-            zinc_(Zdegenvertex);
-            trace2((qh ferr, 2027, "qh_merge_degenredundant: deleted v%d because f%d has no neighbors\n",
-                 vertex->id, facet1->id));
-            vertex->deleted= True;
-            qh_setappend(&qh del_vertices, vertex);
-          }
-        }
-        nummerges++;
-      }else if (size < qh hull_dim) {
-        bestneighbor= qh_findbestneighbor(facet1, &dist, &mindist, &maxdist);
-        trace2((qh ferr, 2028, "qh_merge_degenredundant: facet f%d has %d neighbors, merge into f%d dist %2.2g\n",
-              facet1->id, size, bestneighbor->id, dist));
-        qh_mergefacet(facet1, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
-        nummerges++;
-        if (qh PRINTstatistics) {
-          zinc_(Zdegen);
-          wadd_(Wdegentot, dist);
-          wmax_(Wdegenmax, dist);
-        }
-      } /* else, another merge fixed the degeneracy and redundancy tested */
-    }
-  }
-  return nummerges;
-} /* merge_degenredundant */
-
-/*---------------------------------
-
-  qh_merge_nonconvex( facet1, facet2, mergetype )
-    remove non-convex ridge between facet1 into facet2
-    mergetype gives why the facet's are non-convex
-
-  returns:
-    merges one of the facets into the best neighbor
-
-  design:
-    if one of the facets is a new facet
-      prefer merging new facet into old facet
-    find best neighbors for both facets
-    merge the nearest facet into its best neighbor
-    update the statistics
-*/
-void qh_merge_nonconvex(facetT *facet1, facetT *facet2, mergeType mergetype) {
-  facetT *bestfacet, *bestneighbor, *neighbor;
-  realT dist, dist2, mindist, mindist2, maxdist, maxdist2;
-
-  if (qh TRACEmerge-1 == zzval_(Ztotmerge))
-    qhmem.IStracing= qh IStracing= qh TRACElevel;
-  trace3((qh ferr, 3003, "qh_merge_nonconvex: merge #%d for f%d and f%d type %d\n",
-      zzval_(Ztotmerge) + 1, facet1->id, facet2->id, mergetype));
-  /* concave or coplanar */
-  if (!facet1->newfacet) {
-    bestfacet= facet2;   /* avoid merging old facet if new is ok */
-    facet2= facet1;
-    facet1= bestfacet;
-  }else
-    bestfacet= facet1;
-  bestneighbor= qh_findbestneighbor(bestfacet, &dist, &mindist, &maxdist);
-  neighbor= qh_findbestneighbor(facet2, &dist2, &mindist2, &maxdist2);
-  if (dist < dist2) {
-    qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
-  }else if (qh AVOIDold && !facet2->newfacet
-  && ((mindist >= -qh MAXcoplanar && maxdist <= qh max_outside)
-       || dist * 1.5 < dist2)) {
-    zinc_(Zavoidold);
-    wadd_(Wavoidoldtot, dist);
-    wmax_(Wavoidoldmax, dist);
-    trace2((qh ferr, 2029, "qh_merge_nonconvex: avoid merging old facet f%d dist %2.2g.  Use f%d dist %2.2g instead\n",
-           facet2->id, dist2, facet1->id, dist2));
-    qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
-  }else {
-    qh_mergefacet(facet2, neighbor, &mindist2, &maxdist2, !qh_MERGEapex);
-    dist= dist2;
-  }
-  if (qh PRINTstatistics) {
-    if (mergetype == MRGanglecoplanar) {
-      zinc_(Zacoplanar);
-      wadd_(Wacoplanartot, dist);
-      wmax_(Wacoplanarmax, dist);
-    }else if (mergetype == MRGconcave) {
-      zinc_(Zconcave);
-      wadd_(Wconcavetot, dist);
-      wmax_(Wconcavemax, dist);
-    }else { /* MRGcoplanar */
-      zinc_(Zcoplanar);
-      wadd_(Wcoplanartot, dist);
-      wmax_(Wcoplanarmax, dist);
-    }
-  }
-} /* merge_nonconvex */
-
-/*---------------------------------
-
-  qh_mergecycle( samecycle, newfacet )
-    merge a cycle of facets starting at samecycle into a newfacet
-    newfacet is a horizon facet with ->normal
-    samecycle facets are simplicial from an apex
-
-  returns:
-    initializes vertex neighbors on first merge
-    samecycle deleted (placed on qh.visible_list)
-    newfacet at end of qh.facet_list
-    deleted vertices on qh.del_vertices
-
-  see:
-    qh_mergefacet()
-    called by qh_mergecycle_all() for multiple, same cycle facets
-
-  design:
-    make vertex neighbors if necessary
-    make ridges for newfacet
-    merge neighbor sets of samecycle into newfacet
-    merge ridges of samecycle into newfacet
-    merge vertex neighbors of samecycle into newfacet
-    make apex of samecycle the apex of newfacet
-    if newfacet wasn't a new facet
-      add its vertices to qh.newvertex_list
-    delete samecycle facets a make newfacet a newfacet
-*/
-void qh_mergecycle(facetT *samecycle, facetT *newfacet) {
-  int traceonce= False, tracerestore= 0;
-  vertexT *apex;
-#ifndef qh_NOtrace
-  facetT *same;
-#endif
-
-  if (newfacet->tricoplanar) {
-    if (!qh TRInormals) {
-      qh_fprintf(qh ferr, 6224, "Qhull internal error (qh_mergecycle): does not work for tricoplanar facets.  Use option 'Q11'\n");
-      qh_errexit(qh_ERRqhull, newfacet, NULL);
-    }
-    newfacet->tricoplanar= False;
-    newfacet->keepcentrum= False;
-  }
-  if (!qh VERTEXneighbors)
-    qh_vertexneighbors();
-  zzinc_(Ztotmerge);
-  if (qh REPORTfreq2 && qh POSTmerging) {
-    if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
-      qh_tracemerging();
-  }
-#ifndef qh_NOtrace
-  if (qh TRACEmerge == zzval_(Ztotmerge))
-    qhmem.IStracing= qh IStracing= qh TRACElevel;
-  trace2((qh ferr, 2030, "qh_mergecycle: merge #%d for facets from cycle f%d into coplanar horizon f%d\n",
-        zzval_(Ztotmerge), samecycle->id, newfacet->id));
-  if (newfacet == qh tracefacet) {
-    tracerestore= qh IStracing;
-    qh IStracing= 4;
-    qh_fprintf(qh ferr, 8068, "qh_mergecycle: ========= trace merge %d of samecycle %d into trace f%d, furthest is p%d\n",
-               zzval_(Ztotmerge), samecycle->id, newfacet->id,  qh furthest_id);
-    traceonce= True;
-  }
-  if (qh IStracing >=4) {
-    qh_fprintf(qh ferr, 8069, "  same cycle:");
-    FORALLsame_cycle_(samecycle)
-      qh_fprintf(qh ferr, 8070, " f%d", same->id);
-    qh_fprintf(qh ferr, 8071, "\n");
-  }
-  if (qh IStracing >=4)
-    qh_errprint("MERGING CYCLE", samecycle, newfacet, NULL, NULL);
-#endif /* !qh_NOtrace */
-  apex= SETfirstt_(samecycle->vertices, vertexT);
-  qh_makeridges(newfacet);
-  qh_mergecycle_neighbors(samecycle, newfacet);
-  qh_mergecycle_ridges(samecycle, newfacet);
-  qh_mergecycle_vneighbors(samecycle, newfacet);
-  if (SETfirstt_(newfacet->vertices, vertexT) != apex)
-    qh_setaddnth(&newfacet->vertices, 0, apex);  /* apex has last id */
-  if (!newfacet->newfacet)
-    qh_newvertices(newfacet->vertices);
-  qh_mergecycle_facets(samecycle, newfacet);
-  qh_tracemerge(samecycle, newfacet);
-  /* check for degen_redundant_neighbors after qh_forcedmerges() */
-  if (traceonce) {
-    qh_fprintf(qh ferr, 8072, "qh_mergecycle: end of trace facet\n");
-    qh IStracing= tracerestore;
-  }
-} /* mergecycle */
-
-/*---------------------------------
-
-  qh_mergecycle_all( facetlist, wasmerge )
-    merge all samecycles of coplanar facets into horizon
-    don't merge facets with ->mergeridge (these already have ->normal)
-    all facets are simplicial from apex
-    all facet->cycledone == False
-
-  returns:
-    all newfacets merged into coplanar horizon facets
-    deleted vertices on  qh.del_vertices
-    sets wasmerge if any merge
-
-  see:
-    calls qh_mergecycle for multiple, same cycle facets
-
-  design:
-    for each facet on facetlist
-      skip facets with duplicate ridges and normals
-      check that facet is in a samecycle (->mergehorizon)
-      if facet only member of samecycle
-        sets vertex->delridge for all vertices except apex
-        merge facet into horizon
-      else
-        mark all facets in samecycle
-        remove facets with duplicate ridges from samecycle
-        merge samecycle into horizon (deletes facets from facetlist)
-*/
-void qh_mergecycle_all(facetT *facetlist, boolT *wasmerge) {
-  facetT *facet, *same, *prev, *horizon;
-  facetT *samecycle= NULL, *nextfacet, *nextsame;
-  vertexT *apex, *vertex, **vertexp;
-  int cycles=0, total=0, facets, nummerge;
-
-  trace2((qh ferr, 2031, "qh_mergecycle_all: begin\n"));
-  for (facet= facetlist; facet && (nextfacet= facet->next); facet= nextfacet) {
-    if (facet->normal)
-      continue;
-    if (!facet->mergehorizon) {
-      qh_fprintf(qh ferr, 6225, "Qhull internal error (qh_mergecycle_all): f%d without normal\n", facet->id);
-      qh_errexit(qh_ERRqhull, facet, NULL);
-    }
-    horizon= SETfirstt_(facet->neighbors, facetT);
-    if (facet->f.samecycle == facet) {
-      zinc_(Zonehorizon);
-      /* merge distance done in qh_findhorizon */
-      apex= SETfirstt_(facet->vertices, vertexT);
-      FOREACHvertex_(facet->vertices) {
-        if (vertex != apex)
-          vertex->delridge= True;
-      }
-      horizon->f.newcycle= NULL;
-      qh_mergefacet(facet, horizon, NULL, NULL, qh_MERGEapex);
-    }else {
-      samecycle= facet;
-      facets= 0;
-      prev= facet;
-      for (same= facet->f.samecycle; same;  /* FORALLsame_cycle_(facet) */
-           same= (same == facet ? NULL :nextsame)) { /* ends at facet */
-        nextsame= same->f.samecycle;
-        if (same->cycledone || same->visible)
-          qh_infiniteloop(same);
-        same->cycledone= True;
-        if (same->normal) {
-          prev->f.samecycle= same->f.samecycle; /* unlink ->mergeridge */
-          same->f.samecycle= NULL;
-        }else {
-          prev= same;
-          facets++;
-        }
-      }
-      while (nextfacet && nextfacet->cycledone)  /* will delete samecycle */
-        nextfacet= nextfacet->next;
-      horizon->f.newcycle= NULL;
-      qh_mergecycle(samecycle, horizon);
-      nummerge= horizon->nummerge + facets;
-      if (nummerge > qh_MAXnummerge)
-        horizon->nummerge= qh_MAXnummerge;
-      else
-        horizon->nummerge= (short unsigned int)nummerge;
-      zzinc_(Zcyclehorizon);
-      total += facets;
-      zzadd_(Zcyclefacettot, facets);
-      zmax_(Zcyclefacetmax, facets);
-    }
-    cycles++;
-  }
-  if (cycles)
-    *wasmerge= True;
-  trace1((qh ferr, 1013, "qh_mergecycle_all: merged %d same cycles or facets into coplanar horizons\n", cycles));
-} /* mergecycle_all */
-
-/*---------------------------------
-
-  qh_mergecycle_facets( samecycle, newfacet )
-    finish merge of samecycle into newfacet
-
-  returns:
-    samecycle prepended to visible_list for later deletion and partitioning
-      each facet->f.replace == newfacet
-
-    newfacet moved to end of qh.facet_list
-      makes newfacet a newfacet (get's facet1->id if it was old)
-      sets newfacet->newmerge
-      clears newfacet->center (unless merging into a large facet)
-      clears newfacet->tested and ridge->tested for facet1
-
-    adds neighboring facets to facet_mergeset if redundant or degenerate
-
-  design:
-    make newfacet a new facet and set its flags
-    move samecycle facets to qh.visible_list for later deletion
-    unless newfacet is large
-      remove its centrum
-*/
-void qh_mergecycle_facets(facetT *samecycle, facetT *newfacet) {
-  facetT *same, *next;
-
-  trace4((qh ferr, 4030, "qh_mergecycle_facets: make newfacet new and samecycle deleted\n"));
-  qh_removefacet(newfacet);  /* append as a newfacet to end of qh facet_list */
-  qh_appendfacet(newfacet);
-  newfacet->newfacet= True;
-  newfacet->simplicial= False;
-  newfacet->newmerge= True;
-
-  for (same= samecycle->f.samecycle; same; same= (same == samecycle ?  NULL : next)) {
-    next= same->f.samecycle;  /* reused by willdelete */
-    qh_willdelete(same, newfacet);
-  }
-  if (newfacet->center
-      && qh_setsize(newfacet->vertices) <= qh hull_dim + qh_MAXnewcentrum) {
-    qh_memfree(newfacet->center, qh normal_size);
-    newfacet->center= NULL;
-  }
-  trace3((qh ferr, 3004, "qh_mergecycle_facets: merged facets from cycle f%d into f%d\n",
-             samecycle->id, newfacet->id));
-} /* mergecycle_facets */
-
-/*---------------------------------
-
-  qh_mergecycle_neighbors( samecycle, newfacet )
-    add neighbors for samecycle facets to newfacet
-
-  returns:
-    newfacet with updated neighbors and vice-versa
-    newfacet has ridges
-    all neighbors of newfacet marked with qh.visit_id
-    samecycle facets marked with qh.visit_id-1
-    ridges updated for simplicial neighbors of samecycle with a ridge
-
-  notes:
-    assumes newfacet not in samecycle
-    usually, samecycle facets are new, simplicial facets without internal ridges
-      not so if horizon facet is coplanar to two different samecycles
-
-  see:
-    qh_mergeneighbors()
-
-  design:
-    check samecycle
-    delete neighbors from newfacet that are also in samecycle
-    for each neighbor of a facet in samecycle
-      if neighbor is simplicial
-        if first visit
-          move the neighbor relation to newfacet
-          update facet links for its ridges
-        else
-          make ridges for neighbor
-          remove samecycle reference
-      else
-        update neighbor sets
-*/
-void qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet) {
-  facetT *same, *neighbor, **neighborp;
-  int delneighbors= 0, newneighbors= 0;
-  unsigned int samevisitid;
-  ridgeT *ridge, **ridgep;
-
-  samevisitid= ++qh visit_id;
-  FORALLsame_cycle_(samecycle) {
-    if (same->visitid == samevisitid || same->visible)
-      qh_infiniteloop(samecycle);
-    same->visitid= samevisitid;
-  }
-  newfacet->visitid= ++qh visit_id;
-  trace4((qh ferr, 4031, "qh_mergecycle_neighbors: delete shared neighbors from newfacet\n"));
-  FOREACHneighbor_(newfacet) {
-    if (neighbor->visitid == samevisitid) {
-      SETref_(neighbor)= NULL;  /* samecycle neighbors deleted */
-      delneighbors++;
-    }else
-      neighbor->visitid= qh visit_id;
-  }
-  qh_setcompact(newfacet->neighbors);
-
-  trace4((qh ferr, 4032, "qh_mergecycle_neighbors: update neighbors\n"));
-  FORALLsame_cycle_(samecycle) {
-    FOREACHneighbor_(same) {
-      if (neighbor->visitid == samevisitid)
-        continue;
-      if (neighbor->simplicial) {
-        if (neighbor->visitid != qh visit_id) {
-          qh_setappend(&newfacet->neighbors, neighbor);
-          qh_setreplace(neighbor->neighbors, same, newfacet);
-          newneighbors++;
-          neighbor->visitid= qh visit_id;
-          FOREACHridge_(neighbor->ridges) { /* update ridge in case of qh_makeridges */
-            if (ridge->top == same) {
-              ridge->top= newfacet;
-              break;
-            }else if (ridge->bottom == same) {
-              ridge->bottom= newfacet;
-              break;
-            }
-          }
-        }else {
-          qh_makeridges(neighbor);
-          qh_setdel(neighbor->neighbors, same);
-          /* same can't be horizon facet for neighbor */
-        }
-      }else { /* non-simplicial neighbor */
-        qh_setdel(neighbor->neighbors, same);
-        if (neighbor->visitid != qh visit_id) {
-          qh_setappend(&neighbor->neighbors, newfacet);
-          qh_setappend(&newfacet->neighbors, neighbor);
-          neighbor->visitid= qh visit_id;
-          newneighbors++;
-        }
-      }
-    }
-  }
-  trace2((qh ferr, 2032, "qh_mergecycle_neighbors: deleted %d neighbors and added %d\n",
-             delneighbors, newneighbors));
-} /* mergecycle_neighbors */
-
-/*---------------------------------
-
-  qh_mergecycle_ridges( samecycle, newfacet )
-    add ridges/neighbors for facets in samecycle to newfacet
-    all new/old neighbors of newfacet marked with qh.visit_id
-    facets in samecycle marked with qh.visit_id-1
-    newfacet marked with qh.visit_id
-
-  returns:
-    newfacet has merged ridges
-
-  notes:
-    ridge already updated for simplicial neighbors of samecycle with a ridge
-
-  see:
-    qh_mergeridges()
-    qh_makeridges()
-
-  design:
-    remove ridges between newfacet and samecycle
-    for each facet in samecycle
-      for each ridge in facet
-        update facet pointers in ridge
-        skip ridges processed in qh_mergecycle_neighors
-        free ridges between newfacet and samecycle
-        free ridges between facets of samecycle (on 2nd visit)
-        append remaining ridges to newfacet
-      if simpilicial facet
-        for each neighbor of facet
-          if simplicial facet
-          and not samecycle facet or newfacet
-            make ridge between neighbor and newfacet
-*/
-void qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet) {
-  facetT *same, *neighbor= NULL;
-  int numold=0, numnew=0;
-  int neighbor_i, neighbor_n;
-  unsigned int samevisitid;
-  ridgeT *ridge, **ridgep;
-  boolT toporient;
-  void **freelistp; /* used if !qh_NOmem by qh_memfree_() */
-
-  trace4((qh ferr, 4033, "qh_mergecycle_ridges: delete shared ridges from newfacet\n"));
-  samevisitid= qh visit_id -1;
-  FOREACHridge_(newfacet->ridges) {
-    neighbor= otherfacet_(ridge, newfacet);
-    if (neighbor->visitid == samevisitid)
-      SETref_(ridge)= NULL; /* ridge free'd below */
-  }
-  qh_setcompact(newfacet->ridges);
-
-  trace4((qh ferr, 4034, "qh_mergecycle_ridges: add ridges to newfacet\n"));
-  FORALLsame_cycle_(samecycle) {
-    FOREACHridge_(same->ridges) {
-      if (ridge->top == same) {
-        ridge->top= newfacet;
-        neighbor= ridge->bottom;
-      }else if (ridge->bottom == same) {
-        ridge->bottom= newfacet;
-        neighbor= ridge->top;
-      }else if (ridge->top == newfacet || ridge->bottom == newfacet) {
-        qh_setappend(&newfacet->ridges, ridge);
-        numold++;  /* already set by qh_mergecycle_neighbors */
-        continue;
-      }else {
-        qh_fprintf(qh ferr, 6098, "qhull internal error (qh_mergecycle_ridges): bad ridge r%d\n", ridge->id);
-        qh_errexit(qh_ERRqhull, NULL, ridge);
-      }
-      if (neighbor == newfacet) {
-        qh_setfree(&(ridge->vertices));
-        qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
-        numold++;
-      }else if (neighbor->visitid == samevisitid) {
-        qh_setdel(neighbor->ridges, ridge);
-        qh_setfree(&(ridge->vertices));
-        qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
-        numold++;
-      }else {
-        qh_setappend(&newfacet->ridges, ridge);
-        numold++;
-      }
-    }
-    if (same->ridges)
-      qh_settruncate(same->ridges, 0);
-    if (!same->simplicial)
-      continue;
-    FOREACHneighbor_i_(same) {       /* note: !newfact->simplicial */
-      if (neighbor->visitid != samevisitid && neighbor->simplicial) {
-        ridge= qh_newridge();
-        ridge->vertices= qh_setnew_delnthsorted(same->vertices, qh hull_dim,
-                                                          neighbor_i, 0);
-        toporient= same->toporient ^ (neighbor_i & 0x1);
-        if (toporient) {
-          ridge->top= newfacet;
-          ridge->bottom= neighbor;
-        }else {
-          ridge->top= neighbor;
-          ridge->bottom= newfacet;
-        }
-        qh_setappend(&(newfacet->ridges), ridge);
-        qh_setappend(&(neighbor->ridges), ridge);
-        numnew++;
-      }
-    }
-  }
-
-  trace2((qh ferr, 2033, "qh_mergecycle_ridges: found %d old ridges and %d new ones\n",
-             numold, numnew));
-} /* mergecycle_ridges */
-
-/*---------------------------------
-
-  qh_mergecycle_vneighbors( samecycle, newfacet )
-    create vertex neighbors for newfacet from vertices of facets in samecycle
-    samecycle marked with visitid == qh.visit_id - 1
-
-  returns:
-    newfacet vertices with updated neighbors
-    marks newfacet with qh.visit_id-1
-    deletes vertices that are merged away
-    sets delridge on all vertices (faster here than in mergecycle_ridges)
-
-  see:
-    qh_mergevertex_neighbors()
-
-  design:
-    for each vertex of samecycle facet
-      set vertex->delridge
-      delete samecycle facets from vertex neighbors
-      append newfacet to vertex neighbors
-      if vertex only in newfacet
-        delete it from newfacet
-        add it to qh.del_vertices for later deletion
-*/
-void qh_mergecycle_vneighbors(facetT *samecycle, facetT *newfacet) {
-  facetT *neighbor, **neighborp;
-  unsigned int mergeid;
-  vertexT *vertex, **vertexp, *apex;
-  setT *vertices;
-
-  trace4((qh ferr, 4035, "qh_mergecycle_vneighbors: update vertex neighbors for newfacet\n"));
-  mergeid= qh visit_id - 1;
-  newfacet->visitid= mergeid;
-  vertices= qh_basevertices(samecycle); /* temp */
-  apex= SETfirstt_(samecycle->vertices, vertexT);
-  qh_setappend(&vertices, apex);
-  FOREACHvertex_(vertices) {
-    vertex->delridge= True;
-    FOREACHneighbor_(vertex) {
-      if (neighbor->visitid == mergeid)
-        SETref_(neighbor)= NULL;
-    }
-    qh_setcompact(vertex->neighbors);
-    qh_setappend(&vertex->neighbors, newfacet);
-    if (!SETsecond_(vertex->neighbors)) {
-      zinc_(Zcyclevertex);
-      trace2((qh ferr, 2034, "qh_mergecycle_vneighbors: deleted v%d when merging cycle f%d into f%d\n",
-        vertex->id, samecycle->id, newfacet->id));
-      qh_setdelsorted(newfacet->vertices, vertex);
-      vertex->deleted= True;
-      qh_setappend(&qh del_vertices, vertex);
-    }
-  }
-  qh_settempfree(&vertices);
-  trace3((qh ferr, 3005, "qh_mergecycle_vneighbors: merged vertices from cycle f%d into f%d\n",
-             samecycle->id, newfacet->id));
-} /* mergecycle_vneighbors */
-
-/*---------------------------------
-
-  qh_mergefacet( facet1, facet2, mindist, maxdist, mergeapex )
-    merges facet1 into facet2
-    mergeapex==qh_MERGEapex if merging new facet into coplanar horizon
-
-  returns:
-    qh.max_outside and qh.min_vertex updated
-    initializes vertex neighbors on first merge
-
-  returns:
-    facet2 contains facet1's vertices, neighbors, and ridges
-      facet2 moved to end of qh.facet_list
-      makes facet2 a newfacet
-      sets facet2->newmerge set
-      clears facet2->center (unless merging into a large facet)
-      clears facet2->tested and ridge->tested for facet1
-
-    facet1 prepended to visible_list for later deletion and partitioning
-      facet1->f.replace == facet2
-
-    adds neighboring facets to facet_mergeset if redundant or degenerate
-
-  notes:
-    mindist/maxdist may be NULL (only if both NULL)
-    traces merge if fmax_(maxdist,-mindist) > TRACEdist
-
-  see:
-    qh_mergecycle()
-
-  design:
-    trace merge and check for degenerate simplex
-    make ridges for both facets
-    update qh.max_outside, qh.max_vertex, qh.min_vertex
-    update facet2->maxoutside and keepcentrum
-    update facet2->nummerge
-    update tested flags for facet2
-    if facet1 is simplicial
-      merge facet1 into facet2
-    else
-      merge facet1's neighbors into facet2
-      merge facet1's ridges into facet2
-      merge facet1's vertices into facet2
-      merge facet1's vertex neighbors into facet2
-      add facet2's vertices to qh.new_vertexlist
-      unless qh_MERGEapex
-        test facet2 for degenerate or redundant neighbors
-      move facet1 to qh.visible_list for later deletion
-      move facet2 to end of qh.newfacet_list
-*/
-void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex) {
-  boolT traceonce= False;
-  vertexT *vertex, **vertexp;
-  int tracerestore=0, nummerge;
-
-  if (facet1->tricoplanar || facet2->tricoplanar) {
-    if (!qh TRInormals) {
-      qh_fprintf(qh ferr, 6226, "Qhull internal error (qh_mergefacet): does not work for tricoplanar facets.  Use option 'Q11'\n");
-      qh_errexit2(qh_ERRqhull, facet1, facet2);
-    }
-    if (facet2->tricoplanar) {
-      facet2->tricoplanar= False;
-      facet2->keepcentrum= False;
-    }
-  }
-  zzinc_(Ztotmerge);
-  if (qh REPORTfreq2 && qh POSTmerging) {
-    if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
-      qh_tracemerging();
-  }
-#ifndef qh_NOtrace
-  if (qh build_cnt >= qh RERUN) {
-    if (mindist && (-*mindist > qh TRACEdist || *maxdist > qh TRACEdist)) {
-      tracerestore= 0;
-      qh IStracing= qh TRACElevel;
-      traceonce= True;
-      qh_fprintf(qh ferr, 8075, "qh_mergefacet: ========= trace wide merge #%d(%2.2g) for f%d into f%d, last point was p%d\n", zzval_(Ztotmerge),
-             fmax_(-*mindist, *maxdist), facet1->id, facet2->id, qh furthest_id);
-    }else if (facet1 == qh tracefacet || facet2 == qh tracefacet) {
-      tracerestore= qh IStracing;
-      qh IStracing= 4;
-      traceonce= True;
-      qh_fprintf(qh ferr, 8076, "qh_mergefacet: ========= trace merge #%d involving f%d, furthest is p%d\n",
-                 zzval_(Ztotmerge), qh tracefacet_id,  qh furthest_id);
-    }
-  }
-  if (qh IStracing >= 2) {
-    realT mergemin= -2;
-    realT mergemax= -2;
-
-    if (mindist) {
-      mergemin= *mindist;
-      mergemax= *maxdist;
-    }
-    qh_fprintf(qh ferr, 8077, "qh_mergefacet: #%d merge f%d into f%d, mindist= %2.2g, maxdist= %2.2g\n",
-    zzval_(Ztotmerge), facet1->id, facet2->id, mergemin, mergemax);
-  }
-#endif /* !qh_NOtrace */
-  if (facet1 == facet2 || facet1->visible || facet2->visible) {
-    qh_fprintf(qh ferr, 6099, "qhull internal error (qh_mergefacet): either f%d and f%d are the same or one is a visible facet\n",
-             facet1->id, facet2->id);
-    qh_errexit2(qh_ERRqhull, facet1, facet2);
-  }
-  if (qh num_facets - qh num_visible <= qh hull_dim + 1) {
-    qh_fprintf(qh ferr, 6227, "\n\
-qhull precision error: Only %d facets remain.  Can not merge another\n\
-pair.  The input is too degenerate or the convexity constraints are\n\
-too strong.\n", qh hull_dim+1);
-    if (qh hull_dim >= 5 && !qh MERGEexact)
-      qh_fprintf(qh ferr, 8079, "Option 'Qx' may avoid this problem.\n");
-    qh_errexit(qh_ERRprec, NULL, NULL);
-  }
-  if (!qh VERTEXneighbors)
-    qh_vertexneighbors();
-  qh_makeridges(facet1);
-  qh_makeridges(facet2);
-  if (qh IStracing >=4)
-    qh_errprint("MERGING", facet1, facet2, NULL, NULL);
-  if (mindist) {
-    maximize_(qh max_outside, *maxdist);
-    maximize_(qh max_vertex, *maxdist);
-#if qh_MAXoutside
-    maximize_(facet2->maxoutside, *maxdist);
-#endif
-    minimize_(qh min_vertex, *mindist);
-    if (!facet2->keepcentrum
-    && (*maxdist > qh WIDEfacet || *mindist < -qh WIDEfacet)) {
-      facet2->keepcentrum= True;
-      zinc_(Zwidefacet);
-    }
-  }
-  nummerge= facet1->nummerge + facet2->nummerge + 1;
-  if (nummerge >= qh_MAXnummerge)
-    facet2->nummerge= qh_MAXnummerge;
-  else
-    facet2->nummerge= (short unsigned int)nummerge;
-  facet2->newmerge= True;
-  facet2->dupridge= False;
-  qh_updatetested(facet1, facet2);
-  if (qh hull_dim > 2 && qh_setsize(facet1->vertices) == qh hull_dim)
-    qh_mergesimplex(facet1, facet2, mergeapex);
-  else {
-    qh vertex_visit++;
-    FOREACHvertex_(facet2->vertices)
-      vertex->visitid= qh vertex_visit;
-    if (qh hull_dim == 2)
-      qh_mergefacet2d(facet1, facet2);
-    else {
-      qh_mergeneighbors(facet1, facet2);
-      qh_mergevertices(facet1->vertices, &facet2->vertices);
-    }
-    qh_mergeridges(facet1, facet2);
-    qh_mergevertex_neighbors(facet1, facet2);
-    if (!facet2->newfacet)
-      qh_newvertices(facet2->vertices);
-  }
-  if (!mergeapex)
-    qh_degen_redundant_neighbors(facet2, facet1);
-  if (facet2->coplanar || !facet2->newfacet) {
-    zinc_(Zmergeintohorizon);
-  }else if (!facet1->newfacet && facet2->newfacet) {
-    zinc_(Zmergehorizon);
-  }else {
-    zinc_(Zmergenew);
-  }
-  qh_willdelete(facet1, facet2);
-  qh_removefacet(facet2);  /* append as a newfacet to end of qh facet_list */
-  qh_appendfacet(facet2);
-  facet2->newfacet= True;
-  facet2->tested= False;
-  qh_tracemerge(facet1, facet2);
-  if (traceonce) {
-    qh_fprintf(qh ferr, 8080, "qh_mergefacet: end of wide tracing\n");
-    qh IStracing= tracerestore;
-  }
-} /* mergefacet */
-
-
-/*---------------------------------
-
-  qh_mergefacet2d( facet1, facet2 )
-    in 2d, merges neighbors and vertices of facet1 into facet2
-
-  returns:
-    build ridges for neighbors if necessary
-    facet2 looks like a simplicial facet except for centrum, ridges
-      neighbors are opposite the corresponding vertex
-      maintains orientation of facet2
-
-  notes:
-    qh_mergefacet() retains non-simplicial structures
-      they are not needed in 2d, but later routines may use them
-    preserves qh.vertex_visit for qh_mergevertex_neighbors()
-
-  design:
-    get vertices and neighbors
-    determine new vertices and neighbors
-    set new vertices and neighbors and adjust orientation
-    make ridges for new neighbor if needed
-*/
-void qh_mergefacet2d(facetT *facet1, facetT *facet2) {
-  vertexT *vertex1A, *vertex1B, *vertex2A, *vertex2B, *vertexA, *vertexB;
-  facetT *neighbor1A, *neighbor1B, *neighbor2A, *neighbor2B, *neighborA, *neighborB;
-
-  vertex1A= SETfirstt_(facet1->vertices, vertexT);
-  vertex1B= SETsecondt_(facet1->vertices, vertexT);
-  vertex2A= SETfirstt_(facet2->vertices, vertexT);
-  vertex2B= SETsecondt_(facet2->vertices, vertexT);
-  neighbor1A= SETfirstt_(facet1->neighbors, facetT);
-  neighbor1B= SETsecondt_(facet1->neighbors, facetT);
-  neighbor2A= SETfirstt_(facet2->neighbors, facetT);
-  neighbor2B= SETsecondt_(facet2->neighbors, facetT);
-  if (vertex1A == vertex2A) {
-    vertexA= vertex1B;
-    vertexB= vertex2B;
-    neighborA= neighbor2A;
-    neighborB= neighbor1A;
-  }else if (vertex1A == vertex2B) {
-    vertexA= vertex1B;
-    vertexB= vertex2A;
-    neighborA= neighbor2B;
-    neighborB= neighbor1A;
-  }else if (vertex1B == vertex2A) {
-    vertexA= vertex1A;
-    vertexB= vertex2B;
-    neighborA= neighbor2A;
-    neighborB= neighbor1B;
-  }else { /* 1B == 2B */
-    vertexA= vertex1A;
-    vertexB= vertex2A;
-    neighborA= neighbor2B;
-    neighborB= neighbor1B;
-  }
-  /* vertexB always from facet2, neighborB always from facet1 */
-  if (vertexA->id > vertexB->id) {
-    SETfirst_(facet2->vertices)= vertexA;
-    SETsecond_(facet2->vertices)= vertexB;
-    if (vertexB == vertex2A)
-      facet2->toporient= !facet2->toporient;
-    SETfirst_(facet2->neighbors)= neighborA;
-    SETsecond_(facet2->neighbors)= neighborB;
-  }else {
-    SETfirst_(facet2->vertices)= vertexB;
-    SETsecond_(facet2->vertices)= vertexA;
-    if (vertexB == vertex2B)
-      facet2->toporient= !facet2->toporient;
-    SETfirst_(facet2->neighbors)= neighborB;
-    SETsecond_(facet2->neighbors)= neighborA;
-  }
-  qh_makeridges(neighborB);
-  qh_setreplace(neighborB->neighbors, facet1, facet2);
-  trace4((qh ferr, 4036, "qh_mergefacet2d: merged v%d and neighbor f%d of f%d into f%d\n",
-       vertexA->id, neighborB->id, facet1->id, facet2->id));
-} /* mergefacet2d */
-
-
-/*---------------------------------
-
-  qh_mergeneighbors( facet1, facet2 )
-    merges the neighbors of facet1 into facet2
-
-  see:
-    qh_mergecycle_neighbors()
-
-  design:
-    for each neighbor of facet1
-      if neighbor is also a neighbor of facet2
-        if neighbor is simpilicial
-          make ridges for later deletion as a degenerate facet
-        update its neighbor set
-      else
-        move the neighbor relation to facet2
-    remove the neighbor relation for facet1 and facet2
-*/
-void qh_mergeneighbors(facetT *facet1, facetT *facet2) {
-  facetT *neighbor, **neighborp;
-
-  trace4((qh ferr, 4037, "qh_mergeneighbors: merge neighbors of f%d and f%d\n",
-          facet1->id, facet2->id));
-  qh visit_id++;
-  FOREACHneighbor_(facet2) {
-    neighbor->visitid= qh visit_id;
-  }
-  FOREACHneighbor_(facet1) {
-    if (neighbor->visitid == qh visit_id) {
-      if (neighbor->simplicial)    /* is degen, needs ridges */
-        qh_makeridges(neighbor);
-      if (SETfirstt_(neighbor->neighbors, facetT) != facet1) /*keep newfacet->horizon*/
-        qh_setdel(neighbor->neighbors, facet1);
-      else {
-        qh_setdel(neighbor->neighbors, facet2);
-        qh_setreplace(neighbor->neighbors, facet1, facet2);
-      }
-    }else if (neighbor != facet2) {
-      qh_setappend(&(facet2->neighbors), neighbor);
-      qh_setreplace(neighbor->neighbors, facet1, facet2);
-    }
-  }
-  qh_setdel(facet1->neighbors, facet2);  /* here for makeridges */
-  qh_setdel(facet2->neighbors, facet1);
-} /* mergeneighbors */
-
-
-/*---------------------------------
-
-  qh_mergeridges( facet1, facet2 )
-    merges the ridge set of facet1 into facet2
-
-  returns:
-    may delete all ridges for a vertex
-    sets vertex->delridge on deleted ridges
-
-  see:
-    qh_mergecycle_ridges()
-
-  design:
-    delete ridges between facet1 and facet2
-      mark (delridge) vertices on these ridges for later testing
-    for each remaining ridge
-      rename facet1 to facet2
-*/
-void qh_mergeridges(facetT *facet1, facetT *facet2) {
-  ridgeT *ridge, **ridgep;
-  vertexT *vertex, **vertexp;
-
-  trace4((qh ferr, 4038, "qh_mergeridges: merge ridges of f%d and f%d\n",
-          facet1->id, facet2->id));
-  FOREACHridge_(facet2->ridges) {
-    if ((ridge->top == facet1) || (ridge->bottom == facet1)) {
-      FOREACHvertex_(ridge->vertices)
-        vertex->delridge= True;
-      qh_delridge(ridge);  /* expensive in high-d, could rebuild */
-      ridgep--; /*repeat*/
-    }
-  }
-  FOREACHridge_(facet1->ridges) {
-    if (ridge->top == facet1)
-      ridge->top= facet2;
-    else
-      ridge->bottom= facet2;
-    qh_setappend(&(facet2->ridges), ridge);
-  }
-} /* mergeridges */
-
-
-/*---------------------------------
-
-  qh_mergesimplex( facet1, facet2, mergeapex )
-    merge simplicial facet1 into facet2
-    mergeapex==qh_MERGEapex if merging samecycle into horizon facet
-      vertex id is latest (most recently created)
-    facet1 may be contained in facet2
-    ridges exist for both facets
-
-  returns:
-    facet2 with updated vertices, ridges, neighbors
-    updated neighbors for facet1's vertices
-    facet1 not deleted
-    sets vertex->delridge on deleted ridges
-
-  notes:
-    special case code since this is the most common merge
-    called from qh_mergefacet()
-
-  design:
-    if qh_MERGEapex
-      add vertices of facet2 to qh.new_vertexlist if necessary
-      add apex to facet2
-    else
-      for each ridge between facet1 and facet2
-        set vertex->delridge
-      determine the apex for facet1 (i.e., vertex to be merged)
-      unless apex already in facet2
-        insert apex into vertices for facet2
-      add vertices of facet2 to qh.new_vertexlist if necessary
-      add apex to qh.new_vertexlist if necessary
-      for each vertex of facet1
-        if apex
-          rename facet1 to facet2 in its vertex neighbors
-        else
-          delete facet1 from vertex neighors
-          if only in facet2
-            add vertex to qh.del_vertices for later deletion
-      for each ridge of facet1
-        delete ridges between facet1 and facet2
-        append other ridges to facet2 after renaming facet to facet2
-*/
-void qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex) {
-  vertexT *vertex, **vertexp, *apex;
-  ridgeT *ridge, **ridgep;
-  boolT issubset= False;
-  int vertex_i= -1, vertex_n;
-  facetT *neighbor, **neighborp, *otherfacet;
-
-  if (mergeapex) {
-    if (!facet2->newfacet)
-      qh_newvertices(facet2->vertices);  /* apex is new */
-    apex= SETfirstt_(facet1->vertices, vertexT);
-    if (SETfirstt_(facet2->vertices, vertexT) != apex)
-      qh_setaddnth(&facet2->vertices, 0, apex);  /* apex has last id */
-    else
-      issubset= True;
-  }else {
-    zinc_(Zmergesimplex);
-    FOREACHvertex_(facet1->vertices)
-      vertex->seen= False;
-    FOREACHridge_(facet1->ridges) {
-      if (otherfacet_(ridge, facet1) == facet2) {
-        FOREACHvertex_(ridge->vertices) {
-          vertex->seen= True;
-          vertex->delridge= True;
-        }
-        break;
-      }
-    }
-    FOREACHvertex_(facet1->vertices) {
-      if (!vertex->seen)
-        break;  /* must occur */
-    }
-    apex= vertex;
-    trace4((qh ferr, 4039, "qh_mergesimplex: merge apex v%d of f%d into facet f%d\n",
-          apex->id, facet1->id, facet2->id));
-    FOREACHvertex_i_(facet2->vertices) {
-      if (vertex->id < apex->id) {
-        break;
-      }else if (vertex->id == apex->id) {
-        issubset= True;
-        break;
-      }
-    }
-    if (!issubset)
-      qh_setaddnth(&facet2->vertices, vertex_i, apex);
-    if (!facet2->newfacet)
-      qh_newvertices(facet2->vertices);
-    else if (!apex->newlist) {
-      qh_removevertex(apex);
-      qh_appendvertex(apex);
-    }
-  }
-  trace4((qh ferr, 4040, "qh_mergesimplex: update vertex neighbors of f%d\n",
-          facet1->id));
-  FOREACHvertex_(facet1->vertices) {
-    if (vertex == apex && !issubset)
-      qh_setreplace(vertex->neighbors, facet1, facet2);
-    else {
-      qh_setdel(vertex->neighbors, facet1);
-      if (!SETsecond_(vertex->neighbors))
-        qh_mergevertex_del(vertex, facet1, facet2);
-    }
-  }
-  trace4((qh ferr, 4041, "qh_mergesimplex: merge ridges and neighbors of f%d into f%d\n",
-          facet1->id, facet2->id));
-  qh visit_id++;
-  FOREACHneighbor_(facet2)
-    neighbor->visitid= qh visit_id;
-  FOREACHridge_(facet1->ridges) {
-    otherfacet= otherfacet_(ridge, facet1);
-    if (otherfacet == facet2) {
-      qh_setdel(facet2->ridges, ridge);
-      qh_setfree(&(ridge->vertices));
-      qh_memfree(ridge, (int)sizeof(ridgeT));
-      qh_setdel(facet2->neighbors, facet1);
-    }else {
-      qh_setappend(&facet2->ridges, ridge);
-      if (otherfacet->visitid != qh visit_id) {
-        qh_setappend(&facet2->neighbors, otherfacet);
-        qh_setreplace(otherfacet->neighbors, facet1, facet2);
-        otherfacet->visitid= qh visit_id;
-      }else {
-        if (otherfacet->simplicial)    /* is degen, needs ridges */
-          qh_makeridges(otherfacet);
-        if (SETfirstt_(otherfacet->neighbors, facetT) != facet1)
-          qh_setdel(otherfacet->neighbors, facet1);
-        else {   /*keep newfacet->neighbors->horizon*/
-          qh_setdel(otherfacet->neighbors, facet2);
-          qh_setreplace(otherfacet->neighbors, facet1, facet2);
-        }
-      }
-      if (ridge->top == facet1) /* wait until after qh_makeridges */
-        ridge->top= facet2;
-      else
-        ridge->bottom= facet2;
-    }
-  }
-  SETfirst_(facet1->ridges)= NULL; /* it will be deleted */
-  trace3((qh ferr, 3006, "qh_mergesimplex: merged simplex f%d apex v%d into facet f%d\n",
-          facet1->id, getid_(apex), facet2->id));
-} /* mergesimplex */
-
-/*---------------------------------
-
-  qh_mergevertex_del( vertex, facet1, facet2 )
-    delete a vertex because of merging facet1 into facet2
-
-  returns:
-    deletes vertex from facet2
-    adds vertex to qh.del_vertices for later deletion
-*/
-void qh_mergevertex_del(vertexT *vertex, facetT *facet1, facetT *facet2) {
-
-  zinc_(Zmergevertex);
-  trace2((qh ferr, 2035, "qh_mergevertex_del: deleted v%d when merging f%d into f%d\n",
-          vertex->id, facet1->id, facet2->id));
-  qh_setdelsorted(facet2->vertices, vertex);
-  vertex->deleted= True;
-  qh_setappend(&qh del_vertices, vertex);
-} /* mergevertex_del */
-
-/*---------------------------------
-
-  qh_mergevertex_neighbors( facet1, facet2 )
-    merge the vertex neighbors of facet1 to facet2
-
-  returns:
-    if vertex is current qh.vertex_visit
-      deletes facet1 from vertex->neighbors
-    else
-      renames facet1 to facet2 in vertex->neighbors
-    deletes vertices if only one neighbor
-
-  notes:
-    assumes vertex neighbor sets are good
-*/
-void qh_mergevertex_neighbors(facetT *facet1, facetT *facet2) {
-  vertexT *vertex, **vertexp;
-
-  trace4((qh ferr, 4042, "qh_mergevertex_neighbors: merge vertex neighbors of f%d and f%d\n",
-          facet1->id, facet2->id));
-  if (qh tracevertex) {
-    qh_fprintf(qh ferr, 8081, "qh_mergevertex_neighbors: of f%d and f%d at furthest p%d f0= %p\n",
-             facet1->id, facet2->id, qh furthest_id, qh tracevertex->neighbors->e[0].p);
-    qh_errprint("TRACE", NULL, NULL, NULL, qh tracevertex);
-  }
-  FOREACHvertex_(facet1->vertices) {
-    if (vertex->visitid != qh vertex_visit)
-      qh_setreplace(vertex->neighbors, facet1, facet2);
-    else {
-      qh_setdel(vertex->neighbors, facet1);
-      if (!SETsecond_(vertex->neighbors))
-        qh_mergevertex_del(vertex, facet1, facet2);
-    }
-  }
-  if (qh tracevertex)
-    qh_errprint("TRACE", NULL, NULL, NULL, qh tracevertex);
-} /* mergevertex_neighbors */
-
-
-/*---------------------------------
-
-  qh_mergevertices( vertices1, vertices2 )
-    merges the vertex set of facet1 into facet2
-
-  returns:
-    replaces vertices2 with merged set
-    preserves vertex_visit for qh_mergevertex_neighbors
-    updates qh.newvertex_list
-
-  design:
-    create a merged set of both vertices (in inverse id order)
-*/
-void qh_mergevertices(setT *vertices1, setT **vertices2) {
-  int newsize= qh_setsize(vertices1)+qh_setsize(*vertices2) - qh hull_dim + 1;
-  setT *mergedvertices;
-  vertexT *vertex, **vertexp, **vertex2= SETaddr_(*vertices2, vertexT);
-
-  mergedvertices= qh_settemp(newsize);
-  FOREACHvertex_(vertices1) {
-    if (!*vertex2 || vertex->id > (*vertex2)->id)
-      qh_setappend(&mergedvertices, vertex);
-    else {
-      while (*vertex2 && (*vertex2)->id > vertex->id)
-        qh_setappend(&mergedvertices, *vertex2++);
-      if (!*vertex2 || (*vertex2)->id < vertex->id)
-        qh_setappend(&mergedvertices, vertex);
-      else
-        qh_setappend(&mergedvertices, *vertex2++);
-    }
-  }
-  while (*vertex2)
-    qh_setappend(&mergedvertices, *vertex2++);
-  if (newsize < qh_setsize(mergedvertices)) {
-    qh_fprintf(qh ferr, 6100, "qhull internal error (qh_mergevertices): facets did not share a ridge\n");
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  qh_setfree(vertices2);
-  *vertices2= mergedvertices;
-  qh_settemppop();
-} /* mergevertices */
-
-
-/*---------------------------------
-
-  qh_neighbor_intersections( vertex )
-    return intersection of all vertices in vertex->neighbors except for vertex
-
-  returns:
-    returns temporary set of vertices
-    does not include vertex
-    NULL if a neighbor is simplicial
-    NULL if empty set
-
-  notes:
-    used for renaming vertices
-
-  design:
-    initialize the intersection set with vertices of the first two neighbors
-    delete vertex from the intersection
-    for each remaining neighbor
-      intersect its vertex set with the intersection set
-      return NULL if empty
-    return the intersection set
-*/
-setT *qh_neighbor_intersections(vertexT *vertex) {
-  facetT *neighbor, **neighborp, *neighborA, *neighborB;
-  setT *intersect;
-  int neighbor_i, neighbor_n;
-
-  FOREACHneighbor_(vertex) {
-    if (neighbor->simplicial)
-      return NULL;
-  }
-  neighborA= SETfirstt_(vertex->neighbors, facetT);
-  neighborB= SETsecondt_(vertex->neighbors, facetT);
-  zinc_(Zintersectnum);
-  if (!neighborA)
-    return NULL;
-  if (!neighborB)
-    intersect= qh_setcopy(neighborA->vertices, 0);
-  else
-    intersect= qh_vertexintersect_new(neighborA->vertices, neighborB->vertices);
-  qh_settemppush(intersect);
-  qh_setdelsorted(intersect, vertex);
-  FOREACHneighbor_i_(vertex) {
-    if (neighbor_i >= 2) {
-      zinc_(Zintersectnum);
-      qh_vertexintersect(&intersect, neighbor->vertices);
-      if (!SETfirst_(intersect)) {
-        zinc_(Zintersectfail);
-        qh_settempfree(&intersect);
-        return NULL;
-      }
-    }
-  }
-  trace3((qh ferr, 3007, "qh_neighbor_intersections: %d vertices in neighbor intersection of v%d\n",
-          qh_setsize(intersect), vertex->id));
-  return intersect;
-} /* neighbor_intersections */
-
-/*---------------------------------
-
-  qh_newvertices( vertices )
-    add vertices to end of qh.vertex_list (marks as new vertices)
-
-  returns:
-    vertices on qh.newvertex_list
-    vertex->newlist set
-*/
-void qh_newvertices(setT *vertices) {
-  vertexT *vertex, **vertexp;
-
-  FOREACHvertex_(vertices) {
-    if (!vertex->newlist) {
-      qh_removevertex(vertex);
-      qh_appendvertex(vertex);
-    }
-  }
-} /* newvertices */
-
-/*---------------------------------
-
-  qh_reducevertices()
-    reduce extra vertices, shared vertices, and redundant vertices
-    facet->newmerge is set if merged since last call
-    if !qh.MERGEvertices, only removes extra vertices
-
-  returns:
-    True if also merged degen_redundant facets
-    vertices are renamed if possible
-    clears facet->newmerge and vertex->delridge
-
-  notes:
-    ignored if 2-d
-
-  design:
-    merge any degenerate or redundant facets
-    for each newly merged facet
-      remove extra vertices
-    if qh.MERGEvertices
-      for each newly merged facet
-        for each vertex
-          if vertex was on a deleted ridge
-            rename vertex if it is shared
-      remove delridge flag from new vertices
-*/
-boolT qh_reducevertices(void) {
-  int numshare=0, numrename= 0;
-  boolT degenredun= False;
-  facetT *newfacet;
-  vertexT *vertex, **vertexp;
-
-  if (qh hull_dim == 2)
-    return False;
-  if (qh_merge_degenredundant())
-    degenredun= True;
- LABELrestart:
-  FORALLnew_facets {
-    if (newfacet->newmerge) {
-      if (!qh MERGEvertices)
-        newfacet->newmerge= False;
-      qh_remove_extravertices(newfacet);
-    }
-  }
-  if (!qh MERGEvertices)
-    return False;
-  FORALLnew_facets {
-    if (newfacet->newmerge) {
-      newfacet->newmerge= False;
-      FOREACHvertex_(newfacet->vertices) {
-        if (vertex->delridge) {
-          if (qh_rename_sharedvertex(vertex, newfacet)) {
-            numshare++;
-            vertexp--; /* repeat since deleted vertex */
-          }
-        }
-      }
-    }
-  }
-  FORALLvertex_(qh newvertex_list) {
-    if (vertex->delridge && !vertex->deleted) {
-      vertex->delridge= False;
-      if (qh hull_dim >= 4 && qh_redundant_vertex(vertex)) {
-        numrename++;
-        if (qh_merge_degenredundant()) {
-          degenredun= True;
-          goto LABELrestart;
-        }
-      }
-    }
-  }
-  trace1((qh ferr, 1014, "qh_reducevertices: renamed %d shared vertices and %d redundant vertices. Degen? %d\n",
-          numshare, numrename, degenredun));
-  return degenredun;
-} /* reducevertices */
-
-/*---------------------------------
-
-  qh_redundant_vertex( vertex )
-    detect and rename a redundant vertex
-    vertices have full vertex->neighbors
-
-  returns:
-    returns true if find a redundant vertex
-      deletes vertex(vertex->deleted)
-
-  notes:
-    only needed if vertex->delridge and hull_dim >= 4
-    may add degenerate facets to qh.facet_mergeset
-    doesn't change vertex->neighbors or create redundant facets
-
-  design:
-    intersect vertices of all facet neighbors of vertex
-    determine ridges for these vertices
-    if find a new vertex for vertex amoung these ridges and vertices
-      rename vertex to the new vertex
-*/
-vertexT *qh_redundant_vertex(vertexT *vertex) {
-  vertexT *newvertex= NULL;
-  setT *vertices, *ridges;
-
-  trace3((qh ferr, 3008, "qh_redundant_vertex: check if v%d can be renamed\n", vertex->id));
-  if ((vertices= qh_neighbor_intersections(vertex))) {
-    ridges= qh_vertexridges(vertex);
-    if ((newvertex= qh_find_newvertex(vertex, vertices, ridges)))
-      qh_renamevertex(vertex, newvertex, ridges, NULL, NULL);
-    qh_settempfree(&ridges);
-    qh_settempfree(&vertices);
-  }
-  return newvertex;
-} /* redundant_vertex */
-
-/*---------------------------------
-
-  qh_remove_extravertices( facet )
-    remove extra vertices from non-simplicial facets
-
-  returns:
-    returns True if it finds them
-
-  design:
-    for each vertex in facet
-      if vertex not in a ridge (i.e., no longer used)
-        delete vertex from facet
-        delete facet from vertice's neighbors
-        unless vertex in another facet
-          add vertex to qh.del_vertices for later deletion
-*/
-boolT qh_remove_extravertices(facetT *facet) {
-  ridgeT *ridge, **ridgep;
-  vertexT *vertex, **vertexp;
-  boolT foundrem= False;
-
-  trace4((qh ferr, 4043, "qh_remove_extravertices: test f%d for extra vertices\n",
-          facet->id));
-  FOREACHvertex_(facet->vertices)
-    vertex->seen= False;
-  FOREACHridge_(facet->ridges) {
-    FOREACHvertex_(ridge->vertices)
-      vertex->seen= True;
-  }
-  FOREACHvertex_(facet->vertices) {
-    if (!vertex->seen) {
-      foundrem= True;
-      zinc_(Zremvertex);
-      qh_setdelsorted(facet->vertices, vertex);
-      qh_setdel(vertex->neighbors, facet);
-      if (!qh_setsize(vertex->neighbors)) {
-        vertex->deleted= True;
-        qh_setappend(&qh del_vertices, vertex);
-        zinc_(Zremvertexdel);
-        trace2((qh ferr, 2036, "qh_remove_extravertices: v%d deleted because it's lost all ridges\n", vertex->id));
-      }else
-        trace3((qh ferr, 3009, "qh_remove_extravertices: v%d removed from f%d because it's lost all ridges\n", vertex->id, facet->id));
-      vertexp--; /*repeat*/
-    }
-  }
-  return foundrem;
-} /* remove_extravertices */
-
-/*---------------------------------
-
-  qh_rename_sharedvertex( vertex, facet )
-    detect and rename if shared vertex in facet
-    vertices have full ->neighbors
-
-  returns:
-    newvertex or NULL
-    the vertex may still exist in other facets (i.e., a neighbor was pinched)
-    does not change facet->neighbors
-    updates vertex->neighbors
-
-  notes:
-    a shared vertex for a facet is only in ridges to one neighbor
-    this may undo a pinched facet
-
-    it does not catch pinches involving multiple facets.  These appear
-      to be difficult to detect, since an exhaustive search is too expensive.
-
-  design:
-    if vertex only has two neighbors
-      determine the ridges that contain the vertex
-      determine the vertices shared by both neighbors
-      if can find a new vertex in this set
-        rename the vertex to the new vertex
-*/
-vertexT *qh_rename_sharedvertex(vertexT *vertex, facetT *facet) {
-  facetT *neighbor, **neighborp, *neighborA= NULL;
-  setT *vertices, *ridges;
-  vertexT *newvertex;
-
-  if (qh_setsize(vertex->neighbors) == 2) {
-    neighborA= SETfirstt_(vertex->neighbors, facetT);
-    if (neighborA == facet)
-      neighborA= SETsecondt_(vertex->neighbors, facetT);
-  }else if (qh hull_dim == 3)
-    return NULL;
-  else {
-    qh visit_id++;
-    FOREACHneighbor_(facet)
-      neighbor->visitid= qh visit_id;
-    FOREACHneighbor_(vertex) {
-      if (neighbor->visitid == qh visit_id) {
-        if (neighborA)
-          return NULL;
-        neighborA= neighbor;
-      }
-    }
-    if (!neighborA) {
-      qh_fprintf(qh ferr, 6101, "qhull internal error (qh_rename_sharedvertex): v%d's neighbors not in f%d\n",
-        vertex->id, facet->id);
-      qh_errprint("ERRONEOUS", facet, NULL, NULL, vertex);
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-    }
-  }
-  /* the vertex is shared by facet and neighborA */
-  ridges= qh_settemp(qh TEMPsize);
-  neighborA->visitid= ++qh visit_id;
-  qh_vertexridges_facet(vertex, facet, &ridges);
-  trace2((qh ferr, 2037, "qh_rename_sharedvertex: p%d(v%d) is shared by f%d(%d ridges) and f%d\n",
-    qh_pointid(vertex->point), vertex->id, facet->id, qh_setsize(ridges), neighborA->id));
-  zinc_(Zintersectnum);
-  vertices= qh_vertexintersect_new(facet->vertices, neighborA->vertices);
-  qh_setdel(vertices, vertex);
-  qh_settemppush(vertices);
-  if ((newvertex= qh_find_newvertex(vertex, vertices, ridges)))
-    qh_renamevertex(vertex, newvertex, ridges, facet, neighborA);
-  qh_settempfree(&vertices);
-  qh_settempfree(&ridges);
-  return newvertex;
-} /* rename_sharedvertex */
-
-/*---------------------------------
-
-  qh_renameridgevertex( ridge, oldvertex, newvertex )
-    renames oldvertex as newvertex in ridge
-
-  returns:
-
-  design:
-    delete oldvertex from ridge
-    if newvertex already in ridge
-      copy ridge->noconvex to another ridge if possible
-      delete the ridge
-    else
-      insert newvertex into the ridge
-      adjust the ridge's orientation
-*/
-void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex) {
-  int nth= 0, oldnth;
-  facetT *temp;
-  vertexT *vertex, **vertexp;
-
-  oldnth= qh_setindex(ridge->vertices, oldvertex);
-  qh_setdelnthsorted(ridge->vertices, oldnth);
-  FOREACHvertex_(ridge->vertices) {
-    if (vertex == newvertex) {
-      zinc_(Zdelridge);
-      if (ridge->nonconvex) /* only one ridge has nonconvex set */
-        qh_copynonconvex(ridge);
-      trace2((qh ferr, 2038, "qh_renameridgevertex: ridge r%d deleted.  It contained both v%d and v%d\n",
-        ridge->id, oldvertex->id, newvertex->id));
-      qh_delridge(ridge);
-      return;
-    }
-    if (vertex->id < newvertex->id)
-      break;
-    nth++;
-  }
-  qh_setaddnth(&ridge->vertices, nth, newvertex);
-  if (abs(oldnth - nth)%2) {
-    trace3((qh ferr, 3010, "qh_renameridgevertex: swapped the top and bottom of ridge r%d\n",
-            ridge->id));
-    temp= ridge->top;
-    ridge->top= ridge->bottom;
-    ridge->bottom= temp;
-  }
-} /* renameridgevertex */
-
-
-/*---------------------------------
-
-  qh_renamevertex( oldvertex, newvertex, ridges, oldfacet, neighborA )
-    renames oldvertex as newvertex in ridges
-    gives oldfacet/neighborA if oldvertex is shared between two facets
-
-  returns:
-    oldvertex may still exist afterwards
-
-
-  notes:
-    can not change neighbors of newvertex (since it's a subset)
-
-  design:
-    for each ridge in ridges
-      rename oldvertex to newvertex and delete degenerate ridges
-    if oldfacet not defined
-      for each neighbor of oldvertex
-        delete oldvertex from neighbor's vertices
-        remove extra vertices from neighbor
-      add oldvertex to qh.del_vertices
-    else if oldvertex only between oldfacet and neighborA
-      delete oldvertex from oldfacet and neighborA
-      add oldvertex to qh.del_vertices
-    else oldvertex is in oldfacet and neighborA and other facets (i.e., pinched)
-      delete oldvertex from oldfacet
-      delete oldfacet from oldvertice's neighbors
-      remove extra vertices (e.g., oldvertex) from neighborA
-*/
-void qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges, facetT *oldfacet, facetT *neighborA) {
-  facetT *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-  boolT istrace= False;
-
-  if (qh IStracing >= 2 || oldvertex->id == qh tracevertex_id ||
-        newvertex->id == qh tracevertex_id)
-    istrace= True;
-  FOREACHridge_(ridges)
-    qh_renameridgevertex(ridge, oldvertex, newvertex);
-  if (!oldfacet) {
-    zinc_(Zrenameall);
-    if (istrace)
-      qh_fprintf(qh ferr, 8082, "qh_renamevertex: renamed v%d to v%d in several facets\n",
-               oldvertex->id, newvertex->id);
-    FOREACHneighbor_(oldvertex) {
-      qh_maydropneighbor(neighbor);
-      qh_setdelsorted(neighbor->vertices, oldvertex);
-      if (qh_remove_extravertices(neighbor))
-        neighborp--; /* neighbor may be deleted */
-    }
-    if (!oldvertex->deleted) {
-      oldvertex->deleted= True;
-      qh_setappend(&qh del_vertices, oldvertex);
-    }
-  }else if (qh_setsize(oldvertex->neighbors) == 2) {
-    zinc_(Zrenameshare);
-    if (istrace)
-      qh_fprintf(qh ferr, 8083, "qh_renamevertex: renamed v%d to v%d in oldfacet f%d\n",
-               oldvertex->id, newvertex->id, oldfacet->id);
-    FOREACHneighbor_(oldvertex)
-      qh_setdelsorted(neighbor->vertices, oldvertex);
-    oldvertex->deleted= True;
-    qh_setappend(&qh del_vertices, oldvertex);
-  }else {
-    zinc_(Zrenamepinch);
-    if (istrace || qh IStracing)
-      qh_fprintf(qh ferr, 8084, "qh_renamevertex: renamed pinched v%d to v%d between f%d and f%d\n",
-               oldvertex->id, newvertex->id, oldfacet->id, neighborA->id);
-    qh_setdelsorted(oldfacet->vertices, oldvertex);
-    qh_setdel(oldvertex->neighbors, oldfacet);
-    qh_remove_extravertices(neighborA);
-  }
-} /* renamevertex */
-
-
-/*---------------------------------
-
-  qh_test_appendmerge( facet, neighbor )
-    tests facet/neighbor for convexity
-    appends to mergeset if non-convex
-    if pre-merging,
-      nop if qh.SKIPconvex, or qh.MERGEexact and coplanar
-
-  returns:
-    true if appends facet/neighbor to mergeset
-    sets facet->center as needed
-    does not change facet->seen
-
-  design:
-    if qh.cos_max is defined
-      if the angle between facet normals is too shallow
-        append an angle-coplanar merge to qh.mergeset
-        return True
-    make facet's centrum if needed
-    if facet's centrum is above the neighbor
-      set isconcave
-    else
-      if facet's centrum is not below the neighbor
-        set iscoplanar
-      make neighbor's centrum if needed
-      if neighbor's centrum is above the facet
-        set isconcave
-      else if neighbor's centrum is not below the facet
-        set iscoplanar
-   if isconcave or iscoplanar
-     get angle if needed
-     append concave or coplanar merge to qh.mergeset
-*/
-boolT qh_test_appendmerge(facetT *facet, facetT *neighbor) {
-  realT dist, dist2= -REALmax, angle= -REALmax;
-  boolT isconcave= False, iscoplanar= False, okangle= False;
-
-  if (qh SKIPconvex && !qh POSTmerging)
-    return False;
-  if ((!qh MERGEexact || qh POSTmerging) && qh cos_max < REALmax/2) {
-    angle= qh_getangle(facet->normal, neighbor->normal);
-    zinc_(Zangletests);
-    if (angle > qh cos_max) {
-      zinc_(Zcoplanarangle);
-      qh_appendmergeset(facet, neighbor, MRGanglecoplanar, &angle);
-      trace2((qh ferr, 2039, "qh_test_appendmerge: coplanar angle %4.4g between f%d and f%d\n",
-         angle, facet->id, neighbor->id));
-      return True;
-    }else
-      okangle= True;
-  }
-  if (!facet->center)
-    facet->center= qh_getcentrum(facet);
-  zzinc_(Zcentrumtests);
-  qh_distplane(facet->center, neighbor, &dist);
-  if (dist > qh centrum_radius)
-    isconcave= True;
-  else {
-    if (dist > -qh centrum_radius)
-      iscoplanar= True;
-    if (!neighbor->center)
-      neighbor->center= qh_getcentrum(neighbor);
-    zzinc_(Zcentrumtests);
-    qh_distplane(neighbor->center, facet, &dist2);
-    if (dist2 > qh centrum_radius)
-      isconcave= True;
-    else if (!iscoplanar && dist2 > -qh centrum_radius)
-      iscoplanar= True;
-  }
-  if (!isconcave && (!iscoplanar || (qh MERGEexact && !qh POSTmerging)))
-    return False;
-  if (!okangle && qh ANGLEmerge) {
-    angle= qh_getangle(facet->normal, neighbor->normal);
-    zinc_(Zangletests);
-  }
-  if (isconcave) {
-    zinc_(Zconcaveridge);
-    if (qh ANGLEmerge)
-      angle += qh_ANGLEconcave + 0.5;
-    qh_appendmergeset(facet, neighbor, MRGconcave, &angle);
-    trace0((qh ferr, 18, "qh_test_appendmerge: concave f%d to f%d dist %4.4g and reverse dist %4.4g angle %4.4g during p%d\n",
-           facet->id, neighbor->id, dist, dist2, angle, qh furthest_id));
-  }else /* iscoplanar */ {
-    zinc_(Zcoplanarcentrum);
-    qh_appendmergeset(facet, neighbor, MRGcoplanar, &angle);
-    trace2((qh ferr, 2040, "qh_test_appendmerge: coplanar f%d to f%d dist %4.4g, reverse dist %4.4g angle %4.4g\n",
-              facet->id, neighbor->id, dist, dist2, angle));
-  }
-  return True;
-} /* test_appendmerge */
-
-/*---------------------------------
-
-  qh_test_vneighbors()
-    test vertex neighbors for convexity
-    tests all facets on qh.newfacet_list
-
-  returns:
-    true if non-convex vneighbors appended to qh.facet_mergeset
-    initializes vertex neighbors if needed
-
-  notes:
-    assumes all facet neighbors have been tested
-    this can be expensive
-    this does not guarantee that a centrum is below all facets
-      but it is unlikely
-    uses qh.visit_id
-
-  design:
-    build vertex neighbors if necessary
-    for all new facets
-      for all vertices
-        for each unvisited facet neighbor of the vertex
-          test new facet and neighbor for convexity
-*/
-boolT qh_test_vneighbors(void /* qh.newfacet_list */) {
-  facetT *newfacet, *neighbor, **neighborp;
-  vertexT *vertex, **vertexp;
-  int nummerges= 0;
-
-  trace1((qh ferr, 1015, "qh_test_vneighbors: testing vertex neighbors for convexity\n"));
-  if (!qh VERTEXneighbors)
-    qh_vertexneighbors();
-  FORALLnew_facets
-    newfacet->seen= False;
-  FORALLnew_facets {
-    newfacet->seen= True;
-    newfacet->visitid= qh visit_id++;
-    FOREACHneighbor_(newfacet)
-      newfacet->visitid= qh visit_id;
-    FOREACHvertex_(newfacet->vertices) {
-      FOREACHneighbor_(vertex) {
-        if (neighbor->seen || neighbor->visitid == qh visit_id)
-          continue;
-        if (qh_test_appendmerge(newfacet, neighbor))
-          nummerges++;
-      }
-    }
-  }
-  zadd_(Ztestvneighbor, nummerges);
-  trace1((qh ferr, 1016, "qh_test_vneighbors: found %d non-convex, vertex neighbors\n",
-           nummerges));
-  return (nummerges > 0);
-} /* test_vneighbors */
-
-/*---------------------------------
-
-  qh_tracemerge( facet1, facet2 )
-    print trace message after merge
-*/
-void qh_tracemerge(facetT *facet1, facetT *facet2) {
-  boolT waserror= False;
-
-#ifndef qh_NOtrace
-  if (qh IStracing >= 4)
-    qh_errprint("MERGED", facet2, NULL, NULL, NULL);
-  if (facet2 == qh tracefacet || (qh tracevertex && qh tracevertex->newlist)) {
-    qh_fprintf(qh ferr, 8085, "qh_tracemerge: trace facet and vertex after merge of f%d and f%d, furthest p%d\n", facet1->id, facet2->id, qh furthest_id);
-    if (facet2 != qh tracefacet)
-      qh_errprint("TRACE", qh tracefacet,
-        (qh tracevertex && qh tracevertex->neighbors) ?
-           SETfirstt_(qh tracevertex->neighbors, facetT) : NULL,
-        NULL, qh tracevertex);
-  }
-  if (qh tracevertex) {
-    if (qh tracevertex->deleted)
-      qh_fprintf(qh ferr, 8086, "qh_tracemerge: trace vertex deleted at furthest p%d\n",
-            qh furthest_id);
-    else
-      qh_checkvertex(qh tracevertex);
-  }
-  if (qh tracefacet) {
-    qh_checkfacet(qh tracefacet, True, &waserror);
-    if (waserror)
-      qh_errexit(qh_ERRqhull, qh tracefacet, NULL);
-  }
-#endif /* !qh_NOtrace */
-  if (qh CHECKfrequently || qh IStracing >= 4) { /* can't check polygon here */
-    qh_checkfacet(facet2, True, &waserror);
-    if (waserror)
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-} /* tracemerge */
-
-/*---------------------------------
-
-  qh_tracemerging()
-    print trace message during POSTmerging
-
-  returns:
-    updates qh.mergereport
-
-  notes:
-    called from qh_mergecycle() and qh_mergefacet()
-
-  see:
-    qh_buildtracing()
-*/
-void qh_tracemerging(void) {
-  realT cpu;
-  int total;
-  time_t timedata;
-  struct tm *tp;
-
-  qh mergereport= zzval_(Ztotmerge);
-  time(&timedata);
-  tp= localtime(&timedata);
-  cpu= qh_CPUclock;
-  cpu /= qh_SECticks;
-  total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
-  qh_fprintf(qh ferr, 8087, "\n\
-At %d:%d:%d & %2.5g CPU secs, qhull has merged %d facets.  The hull\n\
-  contains %d facets and %d vertices.\n",
-      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu,
-      total, qh num_facets - qh num_visible,
-      qh num_vertices-qh_setsize(qh del_vertices));
-} /* tracemerging */
-
-/*---------------------------------
-
-  qh_updatetested( facet1, facet2 )
-    clear facet2->tested and facet1->ridge->tested for merge
-
-  returns:
-    deletes facet2->center unless it's already large
-      if so, clears facet2->ridge->tested
-
-  design:
-    clear facet2->tested
-    clear ridge->tested for facet1's ridges
-    if facet2 has a centrum
-      if facet2 is large
-        set facet2->keepcentrum
-      else if facet2 has 3 vertices due to many merges, or not large and post merging
-        clear facet2->keepcentrum
-      unless facet2->keepcentrum
-        clear facet2->center to recompute centrum later
-        clear ridge->tested for facet2's ridges
-*/
-void qh_updatetested(facetT *facet1, facetT *facet2) {
-  ridgeT *ridge, **ridgep;
-  int size;
-
-  facet2->tested= False;
-  FOREACHridge_(facet1->ridges)
-    ridge->tested= False;
-  if (!facet2->center)
-    return;
-  size= qh_setsize(facet2->vertices);
-  if (!facet2->keepcentrum) {
-    if (size > qh hull_dim + qh_MAXnewcentrum) {
-      facet2->keepcentrum= True;
-      zinc_(Zwidevertices);
-    }
-  }else if (size <= qh hull_dim + qh_MAXnewcentrum) {
-    /* center and keepcentrum was set */
-    if (size == qh hull_dim || qh POSTmerging)
-      facet2->keepcentrum= False; /* if many merges need to recompute centrum */
-  }
-  if (!facet2->keepcentrum) {
-    qh_memfree(facet2->center, qh normal_size);
-    facet2->center= NULL;
-    FOREACHridge_(facet2->ridges)
-      ridge->tested= False;
-  }
-} /* updatetested */
-
-/*---------------------------------
-
-  qh_vertexridges( vertex )
-    return temporary set of ridges adjacent to a vertex
-    vertex->neighbors defined
-
-  ntoes:
-    uses qh.visit_id
-    does not include implicit ridges for simplicial facets
-
-  design:
-    for each neighbor of vertex
-      add ridges that include the vertex to ridges
-*/
-setT *qh_vertexridges(vertexT *vertex) {
-  facetT *neighbor, **neighborp;
-  setT *ridges= qh_settemp(qh TEMPsize);
-  int size;
-
-  qh visit_id++;
-  FOREACHneighbor_(vertex)
-    neighbor->visitid= qh visit_id;
-  FOREACHneighbor_(vertex) {
-    if (*neighborp)   /* no new ridges in last neighbor */
-      qh_vertexridges_facet(vertex, neighbor, &ridges);
-  }
-  if (qh PRINTstatistics || qh IStracing) {
-    size= qh_setsize(ridges);
-    zinc_(Zvertexridge);
-    zadd_(Zvertexridgetot, size);
-    zmax_(Zvertexridgemax, size);
-    trace3((qh ferr, 3011, "qh_vertexridges: found %d ridges for v%d\n",
-             size, vertex->id));
-  }
-  return ridges;
-} /* vertexridges */
-
-/*---------------------------------
-
-  qh_vertexridges_facet( vertex, facet, ridges )
-    add adjacent ridges for vertex in facet
-    neighbor->visitid==qh.visit_id if it hasn't been visited
-
-  returns:
-    ridges updated
-    sets facet->visitid to qh.visit_id-1
-
-  design:
-    for each ridge of facet
-      if ridge of visited neighbor (i.e., unprocessed)
-        if vertex in ridge
-          append ridge to vertex
-    mark facet processed
-*/
-void qh_vertexridges_facet(vertexT *vertex, facetT *facet, setT **ridges) {
-  ridgeT *ridge, **ridgep;
-  facetT *neighbor;
-
-  FOREACHridge_(facet->ridges) {
-    neighbor= otherfacet_(ridge, facet);
-    if (neighbor->visitid == qh visit_id
-    && qh_setin(ridge->vertices, vertex))
-      qh_setappend(ridges, ridge);
-  }
-  facet->visitid= qh visit_id-1;
-} /* vertexridges_facet */
-
-/*---------------------------------
-
-  qh_willdelete( facet, replace )
-    moves facet to visible list
-    sets facet->f.replace to replace (may be NULL)
-
-  returns:
-    bumps qh.num_visible
-*/
-void qh_willdelete(facetT *facet, facetT *replace) {
-
-  qh_removefacet(facet);
-  qh_prependfacet(facet, &qh visible_list);
-  qh num_visible++;
-  facet->visible= True;
-  facet->f.replace= replace;
-} /* willdelete */
-
-#else /* qh_NOmerge */
-void qh_premerge(vertexT *apex, realT maxcentrum, realT maxangle) {
-}
-void qh_postmerge(const char *reason, realT maxcentrum, realT maxangle,
-                      boolT vneighbors) {
-}
-boolT qh_checkzero(boolT testall) {
-   }
-#endif /* qh_NOmerge */
-
diff --git a/extern/libqhull/merge.h b/extern/libqhull/merge.h
deleted file mode 100644
index 7f5ec3fb6176..000000000000
--- a/extern/libqhull/merge.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
  ---------------------------------
-
-   merge.h
-   header file for merge.c
-
-   see qh-merge.htm and merge.c
-
-   Copyright (c) 1993-2015 C.B. Barber.
-   $Id: //main/2015/qhull/src/libqhull/merge.h#1 $$Change: 1981 $
-   $DateTime: 2015/09/28 20:26:32 $$Author: bbarber $
-*/
-
-#ifndef qhDEFmerge
-#define qhDEFmerge 1
-
-#include "libqhull.h"
-
-
-/*============ -constants- ==============*/
-
-/*----------------------------------
-
-  qh_ANGLEredundant
-    indicates redundant merge in mergeT->angle
-*/
-#define qh_ANGLEredundant 6.0
-
-/*----------------------------------
-
-  qh_ANGLEdegen
-    indicates degenerate facet in mergeT->angle
-*/
-#define qh_ANGLEdegen     5.0
-
-/*----------------------------------
-
-  qh_ANGLEconcave
-    offset to indicate concave facets in mergeT->angle
-
-  notes:
-    concave facets are assigned the range of [2,4] in mergeT->angle
-    roundoff error may make the angle less than 2
-*/
-#define qh_ANGLEconcave  1.5
-
-/*----------------------------------
-
-  MRG... (mergeType)
-    indicates the type of a merge (mergeT->type)
-*/
-typedef enum {  /* in sort order for facet_mergeset */
-  MRGnone= 0,
-  MRGcoplanar,          /* centrum coplanar */
-  MRGanglecoplanar,     /* angle coplanar */
-                        /* could detect half concave ridges */
-  MRGconcave,           /* concave ridge */
-  MRGflip,              /* flipped facet. facet1 == facet2 */
-  MRGridge,             /* duplicate ridge (qh_MERGEridge) */
-                        /* degen and redundant go onto degen_mergeset */
-  MRGdegen,             /* degenerate facet (!enough neighbors) facet1 == facet2 */
-  MRGredundant,         /* redundant facet (vertex subset) */
-                        /* merge_degenredundant assumes degen < redundant */
-  MRGmirror,            /* mirror facet from qh_triangulate */
-  ENDmrg
-} mergeType;
-
-/*----------------------------------
-
-  qh_MERGEapex
-    flag for qh_mergefacet() to indicate an apex merge
-*/
-#define qh_MERGEapex     True
-
-/*============ -structures- ====================*/
-
-/*----------------------------------
-
-  mergeT
-    structure used to merge facets
-*/
-
-typedef struct mergeT mergeT;
-struct mergeT {         /* initialize in qh_appendmergeset */
-  realT   angle;        /* angle between normals of facet1 and facet2 */
-  facetT *facet1;       /* will merge facet1 into facet2 */
-  facetT *facet2;
-  mergeType type;
-};
-
-
-/*=========== -macros- =========================*/
-
-/*----------------------------------
-
-  FOREACHmerge_( merges ) {...}
-    assign 'merge' to each merge in merges
-
-  notes:
-    uses 'mergeT *merge, **mergep;'
-    if qh_mergefacet(),
-      restart since qh.facet_mergeset may change
-    see FOREACHsetelement_
-*/
-#define FOREACHmerge_( merges ) FOREACHsetelement_(mergeT, merges, merge)
-
-/*============ prototypes in alphabetical order after pre/postmerge =======*/
-
-void    qh_premerge(vertexT *apex, realT maxcentrum, realT maxangle);
-void    qh_postmerge(const char *reason, realT maxcentrum, realT maxangle,
-             boolT vneighbors);
-void    qh_all_merges(boolT othermerge, boolT vneighbors);
-void    qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle);
-setT   *qh_basevertices( facetT *samecycle);
-void    qh_checkconnect(void /* qh.new_facets */);
-boolT   qh_checkzero(boolT testall);
-int     qh_compareangle(const void *p1, const void *p2);
-int     qh_comparemerge(const void *p1, const void *p2);
-int     qh_comparevisit(const void *p1, const void *p2);
-void    qh_copynonconvex(ridgeT *atridge);
-void    qh_degen_redundant_facet(facetT *facet);
-void    qh_degen_redundant_neighbors(facetT *facet, facetT *delfacet);
-vertexT *qh_find_newvertex(vertexT *oldvertex, setT *vertices, setT *ridges);
-void    qh_findbest_test(boolT testcentrum, facetT *facet, facetT *neighbor,
-           facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp);
-facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp);
-void    qh_flippedmerges(facetT *facetlist, boolT *wasmerge);
-void    qh_forcedmerges( boolT *wasmerge);
-void    qh_getmergeset(facetT *facetlist);
-void    qh_getmergeset_initial(facetT *facetlist);
-void    qh_hashridge(setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex);
-ridgeT *qh_hashridge_find(setT *hashtable, int hashsize, ridgeT *ridge,
-              vertexT *vertex, vertexT *oldvertex, int *hashslot);
-void    qh_makeridges(facetT *facet);
-void    qh_mark_dupridges(facetT *facetlist);
-void    qh_maydropneighbor(facetT *facet);
-int     qh_merge_degenredundant(void);
-void    qh_merge_nonconvex( facetT *facet1, facetT *facet2, mergeType mergetype);
-void    qh_mergecycle(facetT *samecycle, facetT *newfacet);
-void    qh_mergecycle_all(facetT *facetlist, boolT *wasmerge);
-void    qh_mergecycle_facets( facetT *samecycle, facetT *newfacet);
-void    qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet);
-void    qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet);
-void    qh_mergecycle_vneighbors( facetT *samecycle, facetT *newfacet);
-void    qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex);
-void    qh_mergefacet2d(facetT *facet1, facetT *facet2);
-void    qh_mergeneighbors(facetT *facet1, facetT *facet2);
-void    qh_mergeridges(facetT *facet1, facetT *facet2);
-void    qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex);
-void    qh_mergevertex_del(vertexT *vertex, facetT *facet1, facetT *facet2);
-void    qh_mergevertex_neighbors(facetT *facet1, facetT *facet2);
-void    qh_mergevertices(setT *vertices1, setT **vertices);
-setT   *qh_neighbor_intersections(vertexT *vertex);
-void    qh_newvertices(setT *vertices);
-boolT   qh_reducevertices(void);
-vertexT *qh_redundant_vertex(vertexT *vertex);
-boolT   qh_remove_extravertices(facetT *facet);
-vertexT *qh_rename_sharedvertex(vertexT *vertex, facetT *facet);
-void    qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex);
-void    qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges,
-                        facetT *oldfacet, facetT *neighborA);
-boolT   qh_test_appendmerge(facetT *facet, facetT *neighbor);
-boolT   qh_test_vneighbors(void /* qh.newfacet_list */);
-void    qh_tracemerge(facetT *facet1, facetT *facet2);
-void    qh_tracemerging(void);
-void    qh_updatetested( facetT *facet1, facetT *facet2);
-setT   *qh_vertexridges(vertexT *vertex);
-void    qh_vertexridges_facet(vertexT *vertex, facetT *facet, setT **ridges);
-void    qh_willdelete(facetT *facet, facetT *replace);
-
-#endif /* qhDEFmerge */
diff --git a/extern/libqhull/poly.c b/extern/libqhull/poly.c
deleted file mode 100644
index b8db6a9ef790..000000000000
--- a/extern/libqhull/poly.c
+++ /dev/null
@@ -1,1205 +0,0 @@
-/*
  ---------------------------------
-
-   poly.c
-   implements polygons and simplices
-
-   see qh-poly.htm, poly.h and libqhull.h
-
-   infrequent code is in poly2.c
-   (all but top 50 and their callers 12/3/95)
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/poly.c#3 $$Change: 2064 $
-   $DateTime: 2016/01/18 12:36:08 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-/*======== functions in alphabetical order ==========*/
-
-/*---------------------------------
-
-  qh_appendfacet( facet )
-    appends facet to end of qh.facet_list,
-
-  returns:
-    updates qh.newfacet_list, facet_next, facet_list
-    increments qh.numfacets
-
-  notes:
-    assumes qh.facet_list/facet_tail is defined (createsimplex)
-
-  see:
-    qh_removefacet()
-
-*/
-void qh_appendfacet(facetT *facet) {
-  facetT *tail= qh facet_tail;
-
-  if (tail == qh newfacet_list)
-    qh newfacet_list= facet;
-  if (tail == qh facet_next)
-    qh facet_next= facet;
-  facet->previous= tail->previous;
-  facet->next= tail;
-  if (tail->previous)
-    tail->previous->next= facet;
-  else
-    qh facet_list= facet;
-  tail->previous= facet;
-  qh num_facets++;
-  trace4((qh ferr, 4044, "qh_appendfacet: append f%d to facet_list\n", facet->id));
-} /* appendfacet */
-
-
-/*---------------------------------
-
-  qh_appendvertex( vertex )
-    appends vertex to end of qh.vertex_list,
-
-  returns:
-    sets vertex->newlist
-    updates qh.vertex_list, newvertex_list
-    increments qh.num_vertices
-
-  notes:
-    assumes qh.vertex_list/vertex_tail is defined (createsimplex)
-
-*/
-void qh_appendvertex(vertexT *vertex) {
-  vertexT *tail= qh vertex_tail;
-
-  if (tail == qh newvertex_list)
-    qh newvertex_list= vertex;
-  vertex->newlist= True;
-  vertex->previous= tail->previous;
-  vertex->next= tail;
-  if (tail->previous)
-    tail->previous->next= vertex;
-  else
-    qh vertex_list= vertex;
-  tail->previous= vertex;
-  qh num_vertices++;
-  trace4((qh ferr, 4045, "qh_appendvertex: append v%d to vertex_list\n", vertex->id));
-} /* appendvertex */
-
-
-/*---------------------------------
-
-  qh_attachnewfacets( )
-    attach horizon facets to new facets in qh.newfacet_list
-    newfacets have neighbor and ridge links to horizon but not vice versa
-    only needed for qh.ONLYgood
-
-  returns:
-    set qh.NEWfacets
-    horizon facets linked to new facets
-      ridges changed from visible facets to new facets
-      simplicial ridges deleted
-    qh.visible_list, no ridges valid
-    facet->f.replace is a newfacet (if any)
-
-  design:
-    delete interior ridges and neighbor sets by
-      for each visible, non-simplicial facet
-        for each ridge
-          if last visit or if neighbor is simplicial
-            if horizon neighbor
-              delete ridge for horizon's ridge set
-            delete ridge
-        erase neighbor set
-    attach horizon facets and new facets by
-      for all new facets
-        if corresponding horizon facet is simplicial
-          locate corresponding visible facet {may be more than one}
-          link visible facet to new facet
-          replace visible facet with new facet in horizon
-        else it's non-simplicial
-          for all visible neighbors of the horizon facet
-            link visible neighbor to new facet
-            delete visible neighbor from horizon facet
-          append new facet to horizon's neighbors
-          the first ridge of the new facet is the horizon ridge
-          link the new facet into the horizon ridge
-*/
-void qh_attachnewfacets(void /* qh.visible_list, newfacet_list */) {
-  facetT *newfacet= NULL, *neighbor, **neighborp, *horizon, *visible;
-  ridgeT *ridge, **ridgep;
-
-  qh NEWfacets= True;
-  trace3((qh ferr, 3012, "qh_attachnewfacets: delete interior ridges\n"));
-  qh visit_id++;
-  FORALLvisible_facets {
-    visible->visitid= qh visit_id;
-    if (visible->ridges) {
-      FOREACHridge_(visible->ridges) {
-        neighbor= otherfacet_(ridge, visible);
-        if (neighbor->visitid == qh visit_id
-            || (!neighbor->visible && neighbor->simplicial)) {
-          if (!neighbor->visible)  /* delete ridge for simplicial horizon */
-            qh_setdel(neighbor->ridges, ridge);
-          qh_setfree(&(ridge->vertices)); /* delete on 2nd visit */
-          qh_memfree(ridge, (int)sizeof(ridgeT));
-        }
-      }
-      SETfirst_(visible->ridges)= NULL;
-    }
-    SETfirst_(visible->neighbors)= NULL;
-  }
-  trace1((qh ferr, 1017, "qh_attachnewfacets: attach horizon facets to new facets\n"));
-  FORALLnew_facets {
-    horizon= SETfirstt_(newfacet->neighbors, facetT);
-    if (horizon->simplicial) {
-      visible= NULL;
-      FOREACHneighbor_(horizon) {   /* may have more than one horizon ridge */
-        if (neighbor->visible) {
-          if (visible) {
-            if (qh_setequal_skip(newfacet->vertices, 0, horizon->vertices,
-                                  SETindex_(horizon->neighbors, neighbor))) {
-              visible= neighbor;
-              break;
-            }
-          }else
-            visible= neighbor;
-        }
-      }
-      if (visible) {
-        visible->f.replace= newfacet;
-        qh_setreplace(horizon->neighbors, visible, newfacet);
-      }else {
-        qh_fprintf(qh ferr, 6102, "qhull internal error (qh_attachnewfacets): couldn't find visible facet for horizon f%d of newfacet f%d\n",
-                 horizon->id, newfacet->id);
-        qh_errexit2(qh_ERRqhull, horizon, newfacet);
-      }
-    }else { /* non-simplicial, with a ridge for newfacet */
-      FOREACHneighbor_(horizon) {    /* may hold for many new facets */
-        if (neighbor->visible) {
-          neighbor->f.replace= newfacet;
-          qh_setdelnth(horizon->neighbors,
-                        SETindex_(horizon->neighbors, neighbor));
-          neighborp--; /* repeat */
-        }
-      }
-      qh_setappend(&horizon->neighbors, newfacet);
-      ridge= SETfirstt_(newfacet->ridges, ridgeT);
-      if (ridge->top == horizon)
-        ridge->bottom= newfacet;
-      else
-        ridge->top= newfacet;
-      }
-  } /* newfacets */
-  if (qh PRINTstatistics) {
-    FORALLvisible_facets {
-      if (!visible->f.replace)
-        zinc_(Zinsidevisible);
-    }
-  }
-} /* attachnewfacets */
-
-/*---------------------------------
-
-  qh_checkflipped( facet, dist, allerror )
-    checks facet orientation to interior point
-
-    if allerror set,
-      tests against qh.DISTround
-    else
-      tests against 0 since tested against DISTround before
-
-  returns:
-    False if it flipped orientation (sets facet->flipped)
-    distance if non-NULL
-*/
-boolT qh_checkflipped(facetT *facet, realT *distp, boolT allerror) {
-  realT dist;
-
-  if (facet->flipped && !distp)
-    return False;
-  zzinc_(Zdistcheck);
-  qh_distplane(qh interior_point, facet, &dist);
-  if (distp)
-    *distp= dist;
-  if ((allerror && dist > -qh DISTround)|| (!allerror && dist >= 0.0)) {
-    facet->flipped= True;
-    zzinc_(Zflippedfacets);
-    trace0((qh ferr, 19, "qh_checkflipped: facet f%d is flipped, distance= %6.12g during p%d\n",
-              facet->id, dist, qh furthest_id));
-    qh_precision("flipped facet");
-    return False;
-  }
-  return True;
-} /* checkflipped */
-
-/*---------------------------------
-
-  qh_delfacet( facet )
-    removes facet from facet_list and frees up its memory
-
-  notes:
-    assumes vertices and ridges already freed
-*/
-void qh_delfacet(facetT *facet) {
-  void **freelistp; /* used if !qh_NOmem by qh_memfree_() */
-
-  trace4((qh ferr, 4046, "qh_delfacet: delete f%d\n", facet->id));
-  if (facet == qh tracefacet)
-    qh tracefacet= NULL;
-  if (facet == qh GOODclosest)
-    qh GOODclosest= NULL;
-  qh_removefacet(facet);
-  if (!facet->tricoplanar || facet->keepcentrum) {
-    qh_memfree_(facet->normal, qh normal_size, freelistp);
-    if (qh CENTERtype == qh_ASvoronoi) {   /* braces for macro calls */
-      qh_memfree_(facet->center, qh center_size, freelistp);
-    }else /* AScentrum */ {
-      qh_memfree_(facet->center, qh normal_size, freelistp);
-    }
-  }
-  qh_setfree(&(facet->neighbors));
-  if (facet->ridges)
-    qh_setfree(&(facet->ridges));
-  qh_setfree(&(facet->vertices));
-  if (facet->outsideset)
-    qh_setfree(&(facet->outsideset));
-  if (facet->coplanarset)
-    qh_setfree(&(facet->coplanarset));
-  qh_memfree_(facet, (int)sizeof(facetT), freelistp);
-} /* delfacet */
-
-
-/*---------------------------------
-
-  qh_deletevisible()
-    delete visible facets and vertices
-
-  returns:
-    deletes each facet and removes from facetlist
-    at exit, qh.visible_list empty (== qh.newfacet_list)
-
-  notes:
-    ridges already deleted
-    horizon facets do not reference facets on qh.visible_list
-    new facets in qh.newfacet_list
-    uses   qh.visit_id;
-*/
-void qh_deletevisible(void /*qh.visible_list*/) {
-  facetT *visible, *nextfacet;
-  vertexT *vertex, **vertexp;
-  int numvisible= 0, numdel= qh_setsize(qh del_vertices);
-
-  trace1((qh ferr, 1018, "qh_deletevisible: delete %d visible facets and %d vertices\n",
-         qh num_visible, numdel));
-  for (visible= qh visible_list; visible && visible->visible;
-                visible= nextfacet) { /* deleting current */
-    nextfacet= visible->next;
-    numvisible++;
-    qh_delfacet(visible);
-  }
-  if (numvisible != qh num_visible) {
-    qh_fprintf(qh ferr, 6103, "qhull internal error (qh_deletevisible): qh num_visible %d is not number of visible facets %d\n",
-             qh num_visible, numvisible);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  qh num_visible= 0;
-  zadd_(Zvisfacettot, numvisible);
-  zmax_(Zvisfacetmax, numvisible);
-  zzadd_(Zdelvertextot, numdel);
-  zmax_(Zdelvertexmax, numdel);
-  FOREACHvertex_(qh del_vertices)
-    qh_delvertex(vertex);
-  qh_settruncate(qh del_vertices, 0);
-} /* deletevisible */
-
-/*---------------------------------
-
-  qh_facetintersect( facetA, facetB, skipa, skipB, prepend )
-    return vertices for intersection of two simplicial facets
-    may include 1 prepended entry (if more, need to settemppush)
-
-  returns:
-    returns set of qh.hull_dim-1 + prepend vertices
-    returns skipped index for each test and checks for exactly one
-
-  notes:
-    does not need settemp since set in quick memory
-
-  see also:
-    qh_vertexintersect and qh_vertexintersect_new
-    use qh_setnew_delnthsorted to get nth ridge (no skip information)
-
-  design:
-    locate skipped vertex by scanning facet A's neighbors
-    locate skipped vertex by scanning facet B's neighbors
-    intersect the vertex sets
-*/
-setT *qh_facetintersect(facetT *facetA, facetT *facetB,
-                         int *skipA,int *skipB, int prepend) {
-  setT *intersect;
-  int dim= qh hull_dim, i, j;
-  facetT **neighborsA, **neighborsB;
-
-  neighborsA= SETaddr_(facetA->neighbors, facetT);
-  neighborsB= SETaddr_(facetB->neighbors, facetT);
-  i= j= 0;
-  if (facetB == *neighborsA++)
-    *skipA= 0;
-  else if (facetB == *neighborsA++)
-    *skipA= 1;
-  else if (facetB == *neighborsA++)
-    *skipA= 2;
-  else {
-    for (i=3; i < dim; i++) {
-      if (facetB == *neighborsA++) {
-        *skipA= i;
-        break;
-      }
-    }
-  }
-  if (facetA == *neighborsB++)
-    *skipB= 0;
-  else if (facetA == *neighborsB++)
-    *skipB= 1;
-  else if (facetA == *neighborsB++)
-    *skipB= 2;
-  else {
-    for (j=3; j < dim; j++) {
-      if (facetA == *neighborsB++) {
-        *skipB= j;
-        break;
-      }
-    }
-  }
-  if (i >= dim || j >= dim) {
-    qh_fprintf(qh ferr, 6104, "qhull internal error (qh_facetintersect): f%d or f%d not in others neighbors\n",
-            facetA->id, facetB->id);
-    qh_errexit2(qh_ERRqhull, facetA, facetB);
-  }
-  intersect= qh_setnew_delnthsorted(facetA->vertices, qh hull_dim, *skipA, prepend);
-  trace4((qh ferr, 4047, "qh_facetintersect: f%d skip %d matches f%d skip %d\n",
-          facetA->id, *skipA, facetB->id, *skipB));
-  return(intersect);
-} /* facetintersect */
-
-/*---------------------------------
-
-  qh_gethash( hashsize, set, size, firstindex, skipelem )
-    return hashvalue for a set with firstindex and skipelem
-
-  notes:
-    returned hash is in [0,hashsize)
-    assumes at least firstindex+1 elements
-    assumes skipelem is NULL, in set, or part of hash
-
-    hashes memory addresses which may change over different runs of the same data
-    using sum for hash does badly in high d
-*/
-int qh_gethash(int hashsize, setT *set, int size, int firstindex, void *skipelem) {
-  void **elemp= SETelemaddr_(set, firstindex, void);
-  ptr_intT hash = 0, elem;
-  unsigned result;
-  int i;
-#ifdef _MSC_VER                   /* Microsoft Visual C++ -- warn about 64-bit issues */
-#pragma warning( push)            /* WARN64 -- ptr_intT holds a 64-bit pointer */
-#pragma warning( disable : 4311)  /* 'type cast': pointer truncation from 'void*' to 'ptr_intT' */
-#endif
-
-  switch (size-firstindex) {
-  case 1:
-    hash= (ptr_intT)(*elemp) - (ptr_intT) skipelem;
-    break;
-  case 2:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] - (ptr_intT) skipelem;
-    break;
-  case 3:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
-      - (ptr_intT) skipelem;
-    break;
-  case 4:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
-      + (ptr_intT)elemp[3] - (ptr_intT) skipelem;
-    break;
-  case 5:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
-      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4] - (ptr_intT) skipelem;
-    break;
-  case 6:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
-      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4]+ (ptr_intT)elemp[5]
-      - (ptr_intT) skipelem;
-    break;
-  default:
-    hash= 0;
-    i= 3;
-    do {     /* this is about 10% in 10-d */
-      if ((elem= (ptr_intT)*elemp++) != (ptr_intT)skipelem) {
-        hash ^= (elem << i) + (elem >> (32-i));
-        i += 3;
-        if (i >= 32)
-          i -= 32;
-      }
-    }while (*elemp);
-    break;
-  }
-  if (hashsize<0) {
-    qh_fprintf(qh ferr, 6202, "qhull internal error: negative hashsize %d passed to qh_gethash [poly.c]\n", hashsize);
-    qh_errexit2(qh_ERRqhull, NULL, NULL);
-  }
-  result= (unsigned)hash;
-  result %= (unsigned)hashsize;
-  /* result= 0; for debugging */
-  return result;
-#ifdef _MSC_VER
-#pragma warning( pop)
-#endif
-} /* gethash */
-
-/*---------------------------------
-
-  qh_makenewfacet( vertices, toporient, horizon )
-    creates a toporient? facet from vertices
-
-  returns:
-    returns newfacet
-      adds newfacet to qh.facet_list
-      newfacet->vertices= vertices
-      if horizon
-        newfacet->neighbor= horizon, but not vice versa
-    newvertex_list updated with vertices
-*/
-facetT *qh_makenewfacet(setT *vertices, boolT toporient,facetT *horizon) {
-  facetT *newfacet;
-  vertexT *vertex, **vertexp;
-
-  FOREACHvertex_(vertices) {
-    if (!vertex->newlist) {
-      qh_removevertex(vertex);
-      qh_appendvertex(vertex);
-    }
-  }
-  newfacet= qh_newfacet();
-  newfacet->vertices= vertices;
-  newfacet->toporient= (unsigned char)toporient;
-  if (horizon)
-    qh_setappend(&(newfacet->neighbors), horizon);
-  qh_appendfacet(newfacet);
-  return(newfacet);
-} /* makenewfacet */
-
-
-/*---------------------------------
-
-  qh_makenewplanes()
-    make new hyperplanes for facets on qh.newfacet_list
-
-  returns:
-    all facets have hyperplanes or are marked for   merging
-    doesn't create hyperplane if horizon is coplanar (will merge)
-    updates qh.min_vertex if qh.JOGGLEmax
-
-  notes:
-    facet->f.samecycle is defined for facet->mergehorizon facets
-*/
-void qh_makenewplanes(void /* newfacet_list */) {
-  facetT *newfacet;
-
-  FORALLnew_facets {
-    if (!newfacet->mergehorizon)
-      qh_setfacetplane(newfacet);
-  }
-  if (qh JOGGLEmax < REALmax/2)
-    minimize_(qh min_vertex, -wwval_(Wnewvertexmax));
-} /* makenewplanes */
-
-/*---------------------------------
-
-  qh_makenew_nonsimplicial( visible, apex, numnew )
-    make new facets for ridges of a visible facet
-
-  returns:
-    first newfacet, bumps numnew as needed
-    attaches new facets if !qh.ONLYgood
-    marks ridge neighbors for simplicial visible
-    if (qh.ONLYgood)
-      ridges on newfacet, horizon, and visible
-    else
-      ridge and neighbors between newfacet and   horizon
-      visible facet's ridges are deleted
-
-  notes:
-    qh.visit_id if visible has already been processed
-    sets neighbor->seen for building f.samecycle
-      assumes all 'seen' flags initially false
-
-  design:
-    for each ridge of visible facet
-      get neighbor of visible facet
-      if neighbor was already processed
-        delete the ridge (will delete all visible facets later)
-      if neighbor is a horizon facet
-        create a new facet
-        if neighbor coplanar
-          adds newfacet to f.samecycle for later merging
-        else
-          updates neighbor's neighbor set
-          (checks for non-simplicial facet with multiple ridges to visible facet)
-        updates neighbor's ridge set
-        (checks for simplicial neighbor to non-simplicial visible facet)
-        (deletes ridge if neighbor is simplicial)
-
-*/
-#ifndef qh_NOmerge
-facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew) {
-  void **freelistp; /* used if !qh_NOmem by qh_memfree_() */
-  ridgeT *ridge, **ridgep;
-  facetT *neighbor, *newfacet= NULL, *samecycle;
-  setT *vertices;
-  boolT toporient;
-  int ridgeid;
-
-  FOREACHridge_(visible->ridges) {
-    ridgeid= ridge->id;
-    neighbor= otherfacet_(ridge, visible);
-    if (neighbor->visible) {
-      if (!qh ONLYgood) {
-        if (neighbor->visitid == qh visit_id) {
-          qh_setfree(&(ridge->vertices));  /* delete on 2nd visit */
-          qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
-        }
-      }
-    }else {  /* neighbor is an horizon facet */
-      toporient= (ridge->top == visible);
-      vertices= qh_setnew(qh hull_dim); /* makes sure this is quick */
-      qh_setappend(&vertices, apex);
-      qh_setappend_set(&vertices, ridge->vertices);
-      newfacet= qh_makenewfacet(vertices, toporient, neighbor);
-      (*numnew)++;
-      if (neighbor->coplanar) {
-        newfacet->mergehorizon= True;
-        if (!neighbor->seen) {
-          newfacet->f.samecycle= newfacet;
-          neighbor->f.newcycle= newfacet;
-        }else {
-          samecycle= neighbor->f.newcycle;
-          newfacet->f.samecycle= samecycle->f.samecycle;
-          samecycle->f.samecycle= newfacet;
-        }
-      }
-      if (qh ONLYgood) {
-        if (!neighbor->simplicial)
-          qh_setappend(&(newfacet->ridges), ridge);
-      }else {  /* qh_attachnewfacets */
-        if (neighbor->seen) {
-          if (neighbor->simplicial) {
-            qh_fprintf(qh ferr, 6105, "qhull internal error (qh_makenew_nonsimplicial): simplicial f%d sharing two ridges with f%d\n",
-                   neighbor->id, visible->id);
-            qh_errexit2(qh_ERRqhull, neighbor, visible);
-          }
-          qh_setappend(&(neighbor->neighbors), newfacet);
-        }else
-          qh_setreplace(neighbor->neighbors, visible, newfacet);
-        if (neighbor->simplicial) {
-          qh_setdel(neighbor->ridges, ridge);
-          qh_setfree(&(ridge->vertices));
-          qh_memfree(ridge, (int)sizeof(ridgeT));
-        }else {
-          qh_setappend(&(newfacet->ridges), ridge);
-          if (toporient)
-            ridge->top= newfacet;
-          else
-            ridge->bottom= newfacet;
-        }
-      trace4((qh ferr, 4048, "qh_makenew_nonsimplicial: created facet f%d from v%d and r%d of horizon f%d\n",
-            newfacet->id, apex->id, ridgeid, neighbor->id));
-      }
-    }
-    neighbor->seen= True;
-  } /* for each ridge */
-  if (!qh ONLYgood)
-    SETfirst_(visible->ridges)= NULL;
-  return newfacet;
-} /* makenew_nonsimplicial */
-#else /* qh_NOmerge */
-facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew) {
-  return NULL;
-}
-#endif /* qh_NOmerge */
-
-/*---------------------------------
-
-  qh_makenew_simplicial( visible, apex, numnew )
-    make new facets for simplicial visible facet and apex
-
-  returns:
-    attaches new facets if (!qh.ONLYgood)
-      neighbors between newfacet and horizon
-
-  notes:
-    nop if neighbor->seen or neighbor->visible(see qh_makenew_nonsimplicial)
-
-  design:
-    locate neighboring horizon facet for visible facet
-    determine vertices and orientation
-    create new facet
-    if coplanar,
-      add new facet to f.samecycle
-    update horizon facet's neighbor list
-*/
-facetT *qh_makenew_simplicial(facetT *visible, vertexT *apex, int *numnew) {
-  facetT *neighbor, **neighborp, *newfacet= NULL;
-  setT *vertices;
-  boolT flip, toporient;
-  int horizonskip= 0, visibleskip= 0;
-
-  FOREACHneighbor_(visible) {
-    if (!neighbor->seen && !neighbor->visible) {
-      vertices= qh_facetintersect(neighbor,visible, &horizonskip, &visibleskip, 1);
-      SETfirst_(vertices)= apex;
-      flip= ((horizonskip & 0x1) ^ (visibleskip & 0x1));
-      if (neighbor->toporient)
-        toporient= horizonskip & 0x1;
-      else
-        toporient= (horizonskip & 0x1) ^ 0x1;
-      newfacet= qh_makenewfacet(vertices, toporient, neighbor);
-      (*numnew)++;
-      if (neighbor->coplanar && (qh PREmerge || qh MERGEexact)) {
-#ifndef qh_NOmerge
-        newfacet->f.samecycle= newfacet;
-        newfacet->mergehorizon= True;
-#endif
-      }
-      if (!qh ONLYgood)
-        SETelem_(neighbor->neighbors, horizonskip)= newfacet;
-      trace4((qh ferr, 4049, "qh_makenew_simplicial: create facet f%d top %d from v%d and horizon f%d skip %d top %d and visible f%d skip %d, flip? %d\n",
-            newfacet->id, toporient, apex->id, neighbor->id, horizonskip,
-              neighbor->toporient, visible->id, visibleskip, flip));
-    }
-  }
-  return newfacet;
-} /* makenew_simplicial */
-
-/*---------------------------------
-
-  qh_matchneighbor( newfacet, newskip, hashsize, hashcount )
-    either match subridge of newfacet with neighbor or add to hash_table
-
-  returns:
-    duplicate ridges are unmatched and marked by qh_DUPLICATEridge
-
-  notes:
-    ridge is newfacet->vertices w/o newskip vertex
-    do not allocate memory (need to free hash_table cleanly)
-    uses linear hash chains
-
-  see also:
-    qh_matchduplicates
-
-  design:
-    for each possible matching facet in qh.hash_table
-      if vertices match
-        set ismatch, if facets have opposite orientation
-        if ismatch and matching facet doesn't have a match
-          match the facets by updating their neighbor sets
-        else
-          indicate a duplicate ridge
-          set facet hyperplane for later testing
-          add facet to hashtable
-          unless the other facet was already a duplicate ridge
-            mark both facets with a duplicate ridge
-            add other facet (if defined) to hash table
-*/
-void qh_matchneighbor(facetT *newfacet, int newskip, int hashsize, int *hashcount) {
-  boolT newfound= False;   /* True, if new facet is already in hash chain */
-  boolT same, ismatch;
-  int hash, scan;
-  facetT *facet, *matchfacet;
-  int skip, matchskip;
-
-  hash= qh_gethash(hashsize, newfacet->vertices, qh hull_dim, 1,
-                     SETelem_(newfacet->vertices, newskip));
-  trace4((qh ferr, 4050, "qh_matchneighbor: newfacet f%d skip %d hash %d hashcount %d\n",
-          newfacet->id, newskip, hash, *hashcount));
-  zinc_(Zhashlookup);
-  for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT));
-       scan= (++scan >= hashsize ? 0 : scan)) {
-    if (facet == newfacet) {
-      newfound= True;
-      continue;
-    }
-    zinc_(Zhashtests);
-    if (qh_matchvertices(1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
-      if (SETelem_(newfacet->vertices, newskip) ==
-          SETelem_(facet->vertices, skip)) {
-        qh_precision("two facets with the same vertices");
-        qh_fprintf(qh ferr, 6106, "qhull precision error: Vertex sets are the same for f%d and f%d.  Can not force output.\n",
-          facet->id, newfacet->id);
-        qh_errexit2(qh_ERRprec, facet, newfacet);
-      }
-      ismatch= (same == (boolT)((newfacet->toporient ^ facet->toporient)));
-      matchfacet= SETelemt_(facet->neighbors, skip, facetT);
-      if (ismatch && !matchfacet) {
-        SETelem_(facet->neighbors, skip)= newfacet;
-        SETelem_(newfacet->neighbors, newskip)= facet;
-        (*hashcount)--;
-        trace4((qh ferr, 4051, "qh_matchneighbor: f%d skip %d matched with new f%d skip %d\n",
-           facet->id, skip, newfacet->id, newskip));
-        return;
-      }
-      if (!qh PREmerge && !qh MERGEexact) {
-        qh_precision("a ridge with more than two neighbors");
-        qh_fprintf(qh ferr, 6107, "qhull precision error: facets f%d, f%d and f%d meet at a ridge with more than 2 neighbors.  Can not continue.\n",
-                 facet->id, newfacet->id, getid_(matchfacet));
-        qh_errexit2(qh_ERRprec, facet, newfacet);
-      }
-      SETelem_(newfacet->neighbors, newskip)= qh_DUPLICATEridge;
-      newfacet->dupridge= True;
-      if (!newfacet->normal)
-        qh_setfacetplane(newfacet);
-      qh_addhash(newfacet, qh hash_table, hashsize, hash);
-      (*hashcount)++;
-      if (!facet->normal)
-        qh_setfacetplane(facet);
-      if (matchfacet != qh_DUPLICATEridge) {
-        SETelem_(facet->neighbors, skip)= qh_DUPLICATEridge;
-        facet->dupridge= True;
-        if (!facet->normal)
-          qh_setfacetplane(facet);
-        if (matchfacet) {
-          matchskip= qh_setindex(matchfacet->neighbors, facet);
-          if (matchskip<0) {
-              qh_fprintf(qh ferr, 6260, "qhull internal error (qh_matchneighbor): matchfacet f%d is in f%d neighbors but not vice versa.  Can not continue.\n",
-                  matchfacet->id, facet->id);
-              qh_errexit2(qh_ERRqhull, matchfacet, facet);
-          }
-          SETelem_(matchfacet->neighbors, matchskip)= qh_DUPLICATEridge; /* matchskip>=0 by QH6260 */
-          matchfacet->dupridge= True;
-          if (!matchfacet->normal)
-            qh_setfacetplane(matchfacet);
-          qh_addhash(matchfacet, qh hash_table, hashsize, hash);
-          *hashcount += 2;
-        }
-      }
-      trace4((qh ferr, 4052, "qh_matchneighbor: new f%d skip %d duplicates ridge for f%d skip %d matching f%d ismatch %d at hash %d\n",
-           newfacet->id, newskip, facet->id, skip,
-           (matchfacet == qh_DUPLICATEridge ? -2 : getid_(matchfacet)),
-           ismatch, hash));
-      return; /* end of duplicate ridge */
-    }
-  }
-  if (!newfound)
-    SETelem_(qh hash_table, scan)= newfacet;  /* same as qh_addhash */
-  (*hashcount)++;
-  trace4((qh ferr, 4053, "qh_matchneighbor: no match for f%d skip %d at hash %d\n",
-           newfacet->id, newskip, hash));
-} /* matchneighbor */
-
-
-/*---------------------------------
-
-  qh_matchnewfacets()
-    match newfacets in qh.newfacet_list to their newfacet neighbors
-
-  returns:
-    qh.newfacet_list with full neighbor sets
-      get vertices with nth neighbor by deleting nth vertex
-    if qh.PREmerge/MERGEexact or qh.FORCEoutput
-      sets facet->flippped if flipped normal (also prevents point partitioning)
-    if duplicate ridges and qh.PREmerge/MERGEexact
-      sets facet->dupridge
-      missing neighbor links identifies extra ridges to be merging (qh_MERGEridge)
-
-  notes:
-    newfacets already have neighbor[0] (horizon facet)
-    assumes qh.hash_table is NULL
-    vertex->neighbors has not been updated yet
-    do not allocate memory after qh.hash_table (need to free it cleanly)
-
-  design:
-    delete neighbor sets for all new facets
-    initialize a hash table
-    for all new facets
-      match facet with neighbors
-    if unmatched facets (due to duplicate ridges)
-      for each new facet with a duplicate ridge
-        match it with a facet
-    check for flipped facets
-*/
-void qh_matchnewfacets(void /* qh.newfacet_list */) {
-  int numnew=0, hashcount=0, newskip;
-  facetT *newfacet, *neighbor;
-  int dim= qh hull_dim, hashsize, neighbor_i, neighbor_n;
-  setT *neighbors;
-#ifndef qh_NOtrace
-  int facet_i, facet_n, numfree= 0;
-  facetT *facet;
-#endif
-
-  trace1((qh ferr, 1019, "qh_matchnewfacets: match neighbors for new facets.\n"));
-  FORALLnew_facets {
-    numnew++;
-    {  /* inline qh_setzero(newfacet->neighbors, 1, qh hull_dim); */
-      neighbors= newfacet->neighbors;
-      neighbors->e[neighbors->maxsize].i= dim+1; /*may be overwritten*/
-      memset((char *)SETelemaddr_(neighbors, 1, void), 0, dim * SETelemsize);
-    }
-  }
-
-  qh_newhashtable(numnew*(qh hull_dim-1)); /* twice what is normally needed,
-                                     but every ridge could be DUPLICATEridge */
-  hashsize= qh_setsize(qh hash_table);
-  FORALLnew_facets {
-    for (newskip=1; newskip0 because hull_dim>1 and numnew>0 */
-      qh_matchneighbor(newfacet, newskip, hashsize, &hashcount);
-#if 0   /* use the following to trap hashcount errors */
-    {
-      int count= 0, k;
-      facetT *facet, *neighbor;
-
-      count= 0;
-      FORALLfacet_(qh newfacet_list) {  /* newfacet already in use */
-        for (k=1; k < qh hull_dim; k++) {
-          neighbor= SETelemt_(facet->neighbors, k, facetT);
-          if (!neighbor || neighbor == qh_DUPLICATEridge)
-            count++;
-        }
-        if (facet == newfacet)
-          break;
-      }
-      if (count != hashcount) {
-        qh_fprintf(qh ferr, 8088, "qh_matchnewfacets: after adding facet %d, hashcount %d != count %d\n",
-                 newfacet->id, hashcount, count);
-        qh_errexit(qh_ERRqhull, newfacet, NULL);
-      }
-    }
-#endif  /* end of trap code */
-  }
-  if (hashcount) {
-    FORALLnew_facets {
-      if (newfacet->dupridge) {
-        FOREACHneighbor_i_(newfacet) {
-          if (neighbor == qh_DUPLICATEridge) {
-            qh_matchduplicates(newfacet, neighbor_i, hashsize, &hashcount);
-                    /* this may report MERGEfacet */
-          }
-        }
-      }
-    }
-  }
-  if (hashcount) {
-    qh_fprintf(qh ferr, 6108, "qhull internal error (qh_matchnewfacets): %d neighbors did not match up\n",
-        hashcount);
-    qh_printhashtable(qh ferr);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-#ifndef qh_NOtrace
-  if (qh IStracing >= 2) {
-    FOREACHfacet_i_(qh hash_table) {
-      if (!facet)
-        numfree++;
-    }
-    qh_fprintf(qh ferr, 8089, "qh_matchnewfacets: %d new facets, %d unused hash entries .  hashsize %d\n",
-             numnew, numfree, qh_setsize(qh hash_table));
-  }
-#endif /* !qh_NOtrace */
-  qh_setfree(&qh hash_table);
-  if (qh PREmerge || qh MERGEexact) {
-    if (qh IStracing >= 4)
-      qh_printfacetlist(qh newfacet_list, NULL, qh_ALL);
-    FORALLnew_facets {
-      if (newfacet->normal)
-        qh_checkflipped(newfacet, NULL, qh_ALL);
-    }
-  }else if (qh FORCEoutput)
-    qh_checkflipped_all(qh newfacet_list);  /* prints warnings for flipped */
-} /* matchnewfacets */
-
-
-/*---------------------------------
-
-  qh_matchvertices( firstindex, verticesA, skipA, verticesB, skipB, same )
-    tests whether vertices match with a single skip
-    starts match at firstindex since all new facets have a common vertex
-
-  returns:
-    true if matched vertices
-    skip index for each set
-    sets same iff vertices have the same orientation
-
-  notes:
-    assumes skipA is in A and both sets are the same size
-
-  design:
-    set up pointers
-    scan both sets checking for a match
-    test orientation
-*/
-boolT qh_matchvertices(int firstindex, setT *verticesA, int skipA,
-       setT *verticesB, int *skipB, boolT *same) {
-  vertexT **elemAp, **elemBp, **skipBp=NULL, **skipAp;
-
-  elemAp= SETelemaddr_(verticesA, firstindex, vertexT);
-  elemBp= SETelemaddr_(verticesB, firstindex, vertexT);
-  skipAp= SETelemaddr_(verticesA, skipA, vertexT);
-  do if (elemAp != skipAp) {
-    while (*elemAp != *elemBp++) {
-      if (skipBp)
-        return False;
-      skipBp= elemBp;  /* one extra like FOREACH */
-    }
-  }while (*(++elemAp));
-  if (!skipBp)
-    skipBp= ++elemBp;
-  *skipB= SETindex_(verticesB, skipB); /* i.e., skipBp - verticesB */
-  *same= !((skipA & 0x1) ^ (*skipB & 0x1)); /* result is 0 or 1 */
-  trace4((qh ferr, 4054, "qh_matchvertices: matched by skip %d(v%d) and skip %d(v%d) same? %d\n",
-          skipA, (*skipAp)->id, *skipB, (*(skipBp-1))->id, *same));
-  return(True);
-} /* matchvertices */
-
-/*---------------------------------
-
-  qh_newfacet()
-    return a new facet
-
-  returns:
-    all fields initialized or cleared   (NULL)
-    preallocates neighbors set
-*/
-facetT *qh_newfacet(void) {
-  facetT *facet;
-  void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */
-
-  qh_memalloc_((int)sizeof(facetT), freelistp, facet, facetT);
-  memset((char *)facet, (size_t)0, sizeof(facetT));
-  if (qh facet_id == qh tracefacet_id)
-    qh tracefacet= facet;
-  facet->id= qh facet_id++;
-  facet->neighbors= qh_setnew(qh hull_dim);
-#if !qh_COMPUTEfurthest
-  facet->furthestdist= 0.0;
-#endif
-#if qh_MAXoutside
-  if (qh FORCEoutput && qh APPROXhull)
-    facet->maxoutside= qh MINoutside;
-  else
-    facet->maxoutside= qh DISTround;
-#endif
-  facet->simplicial= True;
-  facet->good= True;
-  facet->newfacet= True;
-  trace4((qh ferr, 4055, "qh_newfacet: created facet f%d\n", facet->id));
-  return(facet);
-} /* newfacet */
-
-
-/*---------------------------------
-
-  qh_newridge()
-    return a new ridge
-*/
-ridgeT *qh_newridge(void) {
-  ridgeT *ridge;
-  void **freelistp;   /* used if !qh_NOmem by qh_memalloc_() */
-
-  qh_memalloc_((int)sizeof(ridgeT), freelistp, ridge, ridgeT);
-  memset((char *)ridge, (size_t)0, sizeof(ridgeT));
-  zinc_(Ztotridges);
-  if (qh ridge_id == UINT_MAX) {
-    qh_fprintf(qh ferr, 7074, "\
-qhull warning: more than 2^32 ridges.  Qhull results are OK.  Since the ridge ID wraps around to 0, two ridges may have the same identifier.\n");
-  }
-  ridge->id= qh ridge_id++;
-  trace4((qh ferr, 4056, "qh_newridge: created ridge r%d\n", ridge->id));
-  return(ridge);
-} /* newridge */
-
-
-/*---------------------------------
-
-  qh_pointid(  point )
-    return id for a point,
-    returns qh_IDnone(-3) if null, qh_IDinterior(-2) if interior, or qh_IDunknown(-1) if not known
-
-  alternative code if point is in qh.first_point...
-    unsigned long id;
-    id= ((unsigned long)point - (unsigned long)qh.first_point)/qh.normal_size;
-
-  notes:
-    Valid points are non-negative
-    WARN64 -- id truncated to 32-bits, at most 2G points
-    NOerrors returned (QhullPoint::id)
-    if point not in point array
-      the code does a comparison of unrelated pointers.
-*/
-int qh_pointid(pointT *point) {
-  ptr_intT offset, id;
-
-  if (!point)
-    return qh_IDnone;
-  else if (point == qh interior_point)
-    return qh_IDinterior;
-  else if (point >= qh first_point
-  && point < qh first_point + qh num_points * qh hull_dim) {
-    offset= (ptr_intT)(point - qh first_point);
-    id= offset / qh hull_dim;
-  }else if ((id= qh_setindex(qh other_points, point)) != -1)
-    id += qh num_points;
-  else
-    return qh_IDunknown;
-  return (int)id;
-} /* pointid */
-
-/*---------------------------------
-
-  qh_removefacet( facet )
-    unlinks facet from qh.facet_list,
-
-  returns:
-    updates qh.facet_list .newfacet_list .facet_next visible_list
-    decrements qh.num_facets
-
-  see:
-    qh_appendfacet
-*/
-void qh_removefacet(facetT *facet) {
-  facetT *next= facet->next, *previous= facet->previous;
-
-  if (facet == qh newfacet_list)
-    qh newfacet_list= next;
-  if (facet == qh facet_next)
-    qh facet_next= next;
-  if (facet == qh visible_list)
-    qh visible_list= next;
-  if (previous) {
-    previous->next= next;
-    next->previous= previous;
-  }else {  /* 1st facet in qh facet_list */
-    qh facet_list= next;
-    qh facet_list->previous= NULL;
-  }
-  qh num_facets--;
-  trace4((qh ferr, 4057, "qh_removefacet: remove f%d from facet_list\n", facet->id));
-} /* removefacet */
-
-
-/*---------------------------------
-
-  qh_removevertex( vertex )
-    unlinks vertex from qh.vertex_list,
-
-  returns:
-    updates qh.vertex_list .newvertex_list
-    decrements qh.num_vertices
-*/
-void qh_removevertex(vertexT *vertex) {
-  vertexT *next= vertex->next, *previous= vertex->previous;
-
-  if (vertex == qh newvertex_list)
-    qh newvertex_list= next;
-  if (previous) {
-    previous->next= next;
-    next->previous= previous;
-  }else {  /* 1st vertex in qh vertex_list */
-    qh vertex_list= vertex->next;
-    qh vertex_list->previous= NULL;
-  }
-  qh num_vertices--;
-  trace4((qh ferr, 4058, "qh_removevertex: remove v%d from vertex_list\n", vertex->id));
-} /* removevertex */
-
-
-/*---------------------------------
-
-  qh_updatevertices()
-    update vertex neighbors and delete interior vertices
-
-  returns:
-    if qh.VERTEXneighbors, updates neighbors for each vertex
-      if qh.newvertex_list,
-         removes visible neighbors  from vertex neighbors
-      if qh.newfacet_list
-         adds new facets to vertex neighbors
-    if qh.visible_list
-       interior vertices added to qh.del_vertices for later partitioning
-
-  design:
-    if qh.VERTEXneighbors
-      deletes references to visible facets from vertex neighbors
-      appends new facets to the neighbor list for each vertex
-      checks all vertices of visible facets
-        removes visible facets from neighbor lists
-        marks unused vertices for deletion
-*/
-void qh_updatevertices(void /*qh.newvertex_list, newfacet_list, visible_list*/) {
-  facetT *newfacet= NULL, *neighbor, **neighborp, *visible;
-  vertexT *vertex, **vertexp;
-
-  trace3((qh ferr, 3013, "qh_updatevertices: delete interior vertices and update vertex->neighbors\n"));
-  if (qh VERTEXneighbors) {
-    FORALLvertex_(qh newvertex_list) {
-      FOREACHneighbor_(vertex) {
-        if (neighbor->visible)
-          SETref_(neighbor)= NULL;
-      }
-      qh_setcompact(vertex->neighbors);
-    }
-    FORALLnew_facets {
-      FOREACHvertex_(newfacet->vertices)
-        qh_setappend(&vertex->neighbors, newfacet);
-    }
-    FORALLvisible_facets {
-      FOREACHvertex_(visible->vertices) {
-        if (!vertex->newlist && !vertex->deleted) {
-          FOREACHneighbor_(vertex) { /* this can happen under merging */
-            if (!neighbor->visible)
-              break;
-          }
-          if (neighbor)
-            qh_setdel(vertex->neighbors, visible);
-          else {
-            vertex->deleted= True;
-            qh_setappend(&qh del_vertices, vertex);
-            trace2((qh ferr, 2041, "qh_updatevertices: delete vertex p%d(v%d) in f%d\n",
-                  qh_pointid(vertex->point), vertex->id, visible->id));
-          }
-        }
-      }
-    }
-  }else {  /* !VERTEXneighbors */
-    FORALLvisible_facets {
-      FOREACHvertex_(visible->vertices) {
-        if (!vertex->newlist && !vertex->deleted) {
-          vertex->deleted= True;
-          qh_setappend(&qh del_vertices, vertex);
-          trace2((qh ferr, 2042, "qh_updatevertices: delete vertex p%d(v%d) in f%d\n",
-                  qh_pointid(vertex->point), vertex->id, visible->id));
-        }
-      }
-    }
-  }
-} /* updatevertices */
-
-
-
diff --git a/extern/libqhull/poly.h b/extern/libqhull/poly.h
deleted file mode 100644
index af8b42077f11..000000000000
--- a/extern/libqhull/poly.h
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
  ---------------------------------
-
-   poly.h
-   header file for poly.c and poly2.c
-
-   see qh-poly.htm, libqhull.h and poly.c
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/poly.h#3 $$Change: 2047 $
-   $DateTime: 2016/01/04 22:03:18 $$Author: bbarber $
-*/
-
-#ifndef qhDEFpoly
-#define qhDEFpoly 1
-
-#include "libqhull.h"
-
-/*===============   constants ========================== */
-
-/*----------------------------------
-
-  ALGORITHMfault
-    use as argument to checkconvex() to report errors during buildhull
-*/
-#define qh_ALGORITHMfault 0
-
-/*----------------------------------
-
-  DATAfault
-    use as argument to checkconvex() to report errors during initialhull
-*/
-#define qh_DATAfault 1
-
-/*----------------------------------
-
-  DUPLICATEridge
-    special value for facet->neighbor to indicate a duplicate ridge
-
-  notes:
-    set by matchneighbor, used by matchmatch and mark_dupridge
-*/
-#define qh_DUPLICATEridge (facetT *)1L
-
-/*----------------------------------
-
-  MERGEridge       flag in facet
-    special value for facet->neighbor to indicate a merged ridge
-
-  notes:
-    set by matchneighbor, used by matchmatch and mark_dupridge
-*/
-#define qh_MERGEridge (facetT *)2L
-
-
-/*============ -structures- ====================*/
-
-/*=========== -macros- =========================*/
-
-/*----------------------------------
-
-  FORALLfacet_( facetlist ) { ... }
-    assign 'facet' to each facet in facetlist
-
-  notes:
-    uses 'facetT *facet;'
-    assumes last facet is a sentinel
-
-  see:
-    FORALLfacets
-*/
-#define FORALLfacet_( facetlist ) if (facetlist ) for ( facet=( facetlist ); facet && facet->next; facet= facet->next )
-
-/*----------------------------------
-
-  FORALLnew_facets { ... }
-    assign 'newfacet' to each facet in qh.newfacet_list
-
-  notes:
-    uses 'facetT *newfacet;'
-    at exit, newfacet==NULL
-*/
-#define FORALLnew_facets for ( newfacet=qh newfacet_list;newfacet && newfacet->next;newfacet=newfacet->next )
-
-/*----------------------------------
-
-  FORALLvertex_( vertexlist ) { ... }
-    assign 'vertex' to each vertex in vertexlist
-
-  notes:
-    uses 'vertexT *vertex;'
-    at exit, vertex==NULL
-*/
-#define FORALLvertex_( vertexlist ) for (vertex=( vertexlist );vertex && vertex->next;vertex= vertex->next )
-
-/*----------------------------------
-
-  FORALLvisible_facets { ... }
-    assign 'visible' to each visible facet in qh.visible_list
-
-  notes:
-    uses 'vacetT *visible;'
-    at exit, visible==NULL
-*/
-#define FORALLvisible_facets for (visible=qh visible_list; visible && visible->visible; visible= visible->next)
-
-/*----------------------------------
-
-  FORALLsame_( newfacet ) { ... }
-    assign 'same' to each facet in newfacet->f.samecycle
-
-  notes:
-    uses 'facetT *same;'
-    stops when it returns to newfacet
-*/
-#define FORALLsame_(newfacet) for (same= newfacet->f.samecycle; same != newfacet; same= same->f.samecycle)
-
-/*----------------------------------
-
-  FORALLsame_cycle_( newfacet ) { ... }
-    assign 'same' to each facet in newfacet->f.samecycle
-
-  notes:
-    uses 'facetT *same;'
-    at exit, same == NULL
-*/
-#define FORALLsame_cycle_(newfacet) \
-     for (same= newfacet->f.samecycle; \
-         same; same= (same == newfacet ?  NULL : same->f.samecycle))
-
-/*----------------------------------
-
-  FOREACHneighborA_( facet ) { ... }
-    assign 'neighborA' to each neighbor in facet->neighbors
-
-  FOREACHneighborA_( vertex ) { ... }
-    assign 'neighborA' to each neighbor in vertex->neighbors
-
-  declare:
-    facetT *neighborA, **neighborAp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHneighborA_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighborA)
-
-/*----------------------------------
-
-  FOREACHvisible_( facets ) { ... }
-    assign 'visible' to each facet in facets
-
-  notes:
-    uses 'facetT *facet, *facetp;'
-    see FOREACHsetelement_
-*/
-#define FOREACHvisible_(facets) FOREACHsetelement_(facetT, facets, visible)
-
-/*----------------------------------
-
-  FOREACHnewfacet_( facets ) { ... }
-    assign 'newfacet' to each facet in facets
-
-  notes:
-    uses 'facetT *newfacet, *newfacetp;'
-    see FOREACHsetelement_
-*/
-#define FOREACHnewfacet_(facets) FOREACHsetelement_(facetT, facets, newfacet)
-
-/*----------------------------------
-
-  FOREACHvertexA_( vertices ) { ... }
-    assign 'vertexA' to each vertex in vertices
-
-  notes:
-    uses 'vertexT *vertexA, *vertexAp;'
-    see FOREACHsetelement_
-*/
-#define FOREACHvertexA_(vertices) FOREACHsetelement_(vertexT, vertices, vertexA)
-
-/*----------------------------------
-
-  FOREACHvertexreverse12_( vertices ) { ... }
-    assign 'vertex' to each vertex in vertices
-    reverse order of first two vertices
-
-  notes:
-    uses 'vertexT *vertex, *vertexp;'
-    see FOREACHsetelement_
-*/
-#define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex)
-
-
-/*=============== prototypes poly.c in alphabetical order ================*/
-
-void    qh_appendfacet(facetT *facet);
-void    qh_appendvertex(vertexT *vertex);
-void    qh_attachnewfacets(void /* qh.visible_list, qh.newfacet_list */);
-boolT   qh_checkflipped(facetT *facet, realT *dist, boolT allerror);
-void    qh_delfacet(facetT *facet);
-void    qh_deletevisible(void /*qh.visible_list, qh.horizon_list*/);
-setT   *qh_facetintersect(facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra);
-int     qh_gethash(int hashsize, setT *set, int size, int firstindex, void *skipelem);
-facetT *qh_makenewfacet(setT *vertices, boolT toporient, facetT *facet);
-void    qh_makenewplanes(void /* newfacet_list */);
-facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew);
-facetT *qh_makenew_simplicial(facetT *visible, vertexT *apex, int *numnew);
-void    qh_matchneighbor(facetT *newfacet, int newskip, int hashsize,
-                          int *hashcount);
-void    qh_matchnewfacets(void);
-boolT   qh_matchvertices(int firstindex, setT *verticesA, int skipA,
-                          setT *verticesB, int *skipB, boolT *same);
-facetT *qh_newfacet(void);
-ridgeT *qh_newridge(void);
-int     qh_pointid(pointT *point);
-void    qh_removefacet(facetT *facet);
-void    qh_removevertex(vertexT *vertex);
-void    qh_updatevertices(void);
-
-
-/*========== -prototypes poly2.c in alphabetical order ===========*/
-
-void    qh_addhash(void* newelem, setT *hashtable, int hashsize, int hash);
-void    qh_check_bestdist(void);
-void    qh_check_dupridge(facetT *facet1, realT dist1, facetT *facet2, realT dist2);
-void    qh_check_maxout(void);
-void    qh_check_output(void);
-void    qh_check_point(pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2);
-void    qh_check_points(void);
-void    qh_checkconvex(facetT *facetlist, int fault);
-void    qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp);
-void    qh_checkflipped_all(facetT *facetlist);
-void    qh_checkpolygon(facetT *facetlist);
-void    qh_checkvertex(vertexT *vertex);
-void    qh_clearcenters(qh_CENTER type);
-void    qh_createsimplex(setT *vertices);
-void    qh_delridge(ridgeT *ridge);
-void    qh_delvertex(vertexT *vertex);
-setT   *qh_facet3vertex(facetT *facet);
-facetT *qh_findbestfacet(pointT *point, boolT bestoutside,
-           realT *bestdist, boolT *isoutside);
-facetT *qh_findbestlower(facetT *upperfacet, pointT *point, realT *bestdistp, int *numpart);
-facetT *qh_findfacet_all(pointT *point, realT *bestdist, boolT *isoutside,
-                          int *numpart);
-int     qh_findgood(facetT *facetlist, int goodhorizon);
-void    qh_findgood_all(facetT *facetlist);
-void    qh_furthestnext(void /* qh.facet_list */);
-void    qh_furthestout(facetT *facet);
-void    qh_infiniteloop(facetT *facet);
-void    qh_initbuild(void);
-void    qh_initialhull(setT *vertices);
-setT   *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints);
-vertexT *qh_isvertex(pointT *point, setT *vertices);
-vertexT *qh_makenewfacets(pointT *point /*horizon_list, visible_list*/);
-void    qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcount);
-void    qh_nearcoplanar(void /* qh.facet_list */);
-vertexT *qh_nearvertex(facetT *facet, pointT *point, realT *bestdistp);
-int     qh_newhashtable(int newsize);
-vertexT *qh_newvertex(pointT *point);
-ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp);
-void    qh_outcoplanar(void /* facet_list */);
-pointT *qh_point(int id);
-void    qh_point_add(setT *set, pointT *point, void *elem);
-setT   *qh_pointfacet(void /*qh.facet_list*/);
-setT   *qh_pointvertex(void /*qh.facet_list*/);
-void    qh_prependfacet(facetT *facet, facetT **facetlist);
-void    qh_printhashtable(FILE *fp);
-void    qh_printlists(void);
-void    qh_resetlists(boolT stats, boolT resetVisible /*qh.newvertex_list qh.newfacet_list qh.visible_list*/);
-void    qh_setvoronoi_all(void);
-void    qh_triangulate(void /*qh.facet_list*/);
-void    qh_triangulate_facet(facetT *facetA, vertexT **first_vertex);
-void    qh_triangulate_link(facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB);
-void    qh_triangulate_mirror(facetT *facetA, facetT *facetB);
-void    qh_triangulate_null(facetT *facetA);
-void    qh_vertexintersect(setT **vertexsetA,setT *vertexsetB);
-setT   *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB);
-void    qh_vertexneighbors(void /*qh.facet_list*/);
-boolT   qh_vertexsubset(setT *vertexsetA, setT *vertexsetB);
-
-
-#endif /* qhDEFpoly */
diff --git a/extern/libqhull/poly2.c b/extern/libqhull/poly2.c
deleted file mode 100644
index f6dc15c20b28..000000000000
--- a/extern/libqhull/poly2.c
+++ /dev/null
@@ -1,3222 +0,0 @@
-/*
  ---------------------------------
-
-   poly2.c
-   implements polygons and simplices
-
-   see qh-poly.htm, poly.h and libqhull.h
-
-   frequently used code is in poly.c
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/poly2.c#11 $$Change: 2069 $
-   $DateTime: 2016/01/18 22:05:03 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-/*======== functions in alphabetical order ==========*/
-
-/*---------------------------------
-
-  qh_addhash( newelem, hashtable, hashsize, hash )
-    add newelem to linear hash table at hash if not already there
-*/
-void qh_addhash(void* newelem, setT *hashtable, int hashsize, int hash) {
-  int scan;
-  void *elem;
-
-  for (scan= (int)hash; (elem= SETelem_(hashtable, scan));
-       scan= (++scan >= hashsize ? 0 : scan)) {
-    if (elem == newelem)
-      break;
-  }
-  /* loop terminates because qh_HASHfactor >= 1.1 by qh_initbuffers */
-  if (!elem)
-    SETelem_(hashtable, scan)= newelem;
-} /* addhash */
-
-/*---------------------------------
-
-  qh_check_bestdist()
-    check that all points are within max_outside of the nearest facet
-    if qh.ONLYgood,
-      ignores !good facets
-
-  see:
-    qh_check_maxout(), qh_outerinner()
-
-  notes:
-    only called from qh_check_points()
-      seldom used since qh.MERGING is almost always set
-    if notverified>0 at end of routine
-      some points were well inside the hull.  If the hull contains
-      a lens-shaped component, these points were not verified.  Use
-      options 'Qi Tv' to verify all points.  (Exhaustive check also verifies)
-
-  design:
-    determine facet for each point (if any)
-    for each point
-      start with the assigned facet or with the first facet
-      find the best facet for the point and check all coplanar facets
-      error if point is outside of facet
-*/
-void qh_check_bestdist(void) {
-  boolT waserror= False, unassigned;
-  facetT *facet, *bestfacet, *errfacet1= NULL, *errfacet2= NULL;
-  facetT *facetlist;
-  realT dist, maxoutside, maxdist= -REALmax;
-  pointT *point;
-  int numpart= 0, facet_i, facet_n, notgood= 0, notverified= 0;
-  setT *facets;
-
-  trace1((qh ferr, 1020, "qh_check_bestdist: check points below nearest facet.  Facet_list f%d\n",
-      qh facet_list->id));
-  maxoutside= qh_maxouter();
-  maxoutside += qh DISTround;
-  /* one more qh.DISTround for check computation */
-  trace1((qh ferr, 1021, "qh_check_bestdist: check that all points are within %2.2g of best facet\n", maxoutside));
-  facets= qh_pointfacet(/*qh.facet_list*/);
-  if (!qh_QUICKhelp && qh PRINTprecision)
-    qh_fprintf(qh ferr, 8091, "\n\
-qhull output completed.  Verifying that %d points are\n\
-below %2.2g of the nearest %sfacet.\n",
-             qh_setsize(facets), maxoutside, (qh ONLYgood ?  "good " : ""));
-  FOREACHfacet_i_(facets) {  /* for each point with facet assignment */
-    if (facet)
-      unassigned= False;
-    else {
-      unassigned= True;
-      facet= qh facet_list;
-    }
-    point= qh_point(facet_i);
-    if (point == qh GOODpointp)
-      continue;
-    qh_distplane(point, facet, &dist);
-    numpart++;
-    bestfacet= qh_findbesthorizon(!qh_IScheckmax, point, facet, qh_NOupper, &dist, &numpart);
-    /* occurs after statistics reported */
-    maximize_(maxdist, dist);
-    if (dist > maxoutside) {
-      if (qh ONLYgood && !bestfacet->good
-          && !((bestfacet= qh_findgooddist(point, bestfacet, &dist, &facetlist))
-               && dist > maxoutside))
-        notgood++;
-      else {
-        waserror= True;
-        qh_fprintf(qh ferr, 6109, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
-                facet_i, bestfacet->id, dist, maxoutside);
-        if (errfacet1 != bestfacet) {
-          errfacet2= errfacet1;
-          errfacet1= bestfacet;
-        }
-      }
-    }else if (unassigned && dist < -qh MAXcoplanar)
-      notverified++;
-  }
-  qh_settempfree(&facets);
-  if (notverified && !qh DELAUNAY && !qh_QUICKhelp && qh PRINTprecision)
-    qh_fprintf(qh ferr, 8092, "\n%d points were well inside the hull.  If the hull contains\n\
-a lens-shaped component, these points were not verified.  Use\n\
-options 'Qci Tv' to verify all points.\n", notverified);
-  if (maxdist > qh outside_err) {
-    qh_fprintf(qh ferr, 6110, "qhull precision error (qh_check_bestdist): a coplanar point is %6.2g from convex hull.  The maximum value(qh.outside_err) is %6.2g\n",
-              maxdist, qh outside_err);
-    qh_errexit2(qh_ERRprec, errfacet1, errfacet2);
-  }else if (waserror && qh outside_err > REALmax/2)
-    qh_errexit2(qh_ERRprec, errfacet1, errfacet2);
-  /* else if waserror, the error was logged to qh.ferr but does not effect the output */
-  trace0((qh ferr, 20, "qh_check_bestdist: max distance outside %2.2g\n", maxdist));
-} /* check_bestdist */
-
-/*---------------------------------
-
-  qh_check_dupridge(facet1, dist1, facet2, dist2)
-    Check duplicate ridge between facet1 and facet2 for wide merge
-    dist1 is the maximum distance of facet1's vertices to facet2
-    dist2 is the maximum distance of facet2's vertices to facet1
-
-  Returns
-    Level 1 log of the duplicate ridge with the minimum distance between vertices
-    Throws error if the merge will increase the maximum facet width by qh_WIDEduplicate (100x)
-
-  called from:
-    qh_forcedmerges()
-*/
-#ifndef qh_NOmerge
-void qh_check_dupridge(facetT *facet1, realT dist1, facetT *facet2, realT dist2) {
-  vertexT *vertex, **vertexp, *vertexA, **vertexAp;
-  realT dist, innerplane, mergedist, outerplane, prevdist, ratio;
-  realT minvertex= REALmax;
-
-  mergedist= fmin_(dist1, dist2);
-  qh_outerinner(NULL, &outerplane, &innerplane);  /* ratio from qh_printsummary */
-  prevdist= fmax_(outerplane, innerplane);
-  maximize_(prevdist, qh ONEmerge + qh DISTround);
-  maximize_(prevdist, qh MINoutside + qh DISTround);
-  ratio= mergedist/prevdist;
-  FOREACHvertex_(facet1->vertices) {     /* The duplicate ridge is between facet1 and facet2, so either facet can be tested */
-    FOREACHvertexA_(facet1->vertices) {
-      if (vertex > vertexA){   /* Test each pair once */
-        dist= qh_pointdist(vertex->point, vertexA->point, qh hull_dim);
-        minimize_(minvertex, dist);
-      }
-    }
-  }
-  trace0((qh ferr, 16, "qh_check_dupridge: duplicate ridge between f%d and f%d due to nearly-coincident vertices (%2.2g), dist %2.2g, reverse dist %2.2g, ratio %2.2g while processing p%d\n",
-        facet1->id, facet2->id, minvertex, dist1, dist2, ratio, qh furthest_id));
-  if (ratio > qh_WIDEduplicate) {
-    qh_fprintf(qh ferr, 6271, "qhull precision error (qh_check_dupridge): wide merge (%.0f times wider) due to duplicate ridge with nearly coincident points (%2.2g) between f%d and f%d, merge dist %2.2g, while processing p%d\n- Ignore error with option 'Q12'\n- To be fixed in a later version of Qhull\n",
-          ratio, minvertex, facet1->id, facet2->id, mergedist, qh furthest_id);
-    if (qh DELAUNAY)
-      qh_fprintf(qh ferr, 8145, "- A bounding box for the input sites may alleviate this error.\n");
-    if(minvertex > qh_WIDEduplicate*prevdist)
-      qh_fprintf(qh ferr, 8146, "- Vertex distance %2.2g is greater than %d times maximum distance %2.2g\n  Please report to bradb@shore.net with steps to reproduce and all output\n",
-          minvertex, qh_WIDEduplicate, prevdist);
-    if (!qh NOwide)
-      qh_errexit2(qh_ERRqhull, facet1, facet2);
-  }
-} /* check_dupridge */
-#endif
-
-/*---------------------------------
-
-  qh_check_maxout()
-    updates qh.max_outside by checking all points against bestfacet
-    if qh.ONLYgood, ignores !good facets
-
-  returns:
-    updates facet->maxoutside via qh_findbesthorizon()
-    sets qh.maxoutdone
-    if printing qh.min_vertex (qh_outerinner),
-      it is updated to the current vertices
-    removes inside/coplanar points from coplanarset as needed
-
-  notes:
-    defines coplanar as min_vertex instead of MAXcoplanar
-    may not need to check near-inside points because of qh.MAXcoplanar
-      and qh.KEEPnearinside (before it was -DISTround)
-
-  see also:
-    qh_check_bestdist()
-
-  design:
-    if qh.min_vertex is needed
-      for all neighbors of all vertices
-        test distance from vertex to neighbor
-    determine facet for each point (if any)
-    for each point with an assigned facet
-      find the best facet for the point and check all coplanar facets
-        (updates outer planes)
-    remove near-inside points from coplanar sets
-*/
-#ifndef qh_NOmerge
-void qh_check_maxout(void) {
-  facetT *facet, *bestfacet, *neighbor, **neighborp, *facetlist;
-  realT dist, maxoutside, minvertex, old_maxoutside;
-  pointT *point;
-  int numpart= 0, facet_i, facet_n, notgood= 0;
-  setT *facets, *vertices;
-  vertexT *vertex;
-
-  trace1((qh ferr, 1022, "qh_check_maxout: check and update maxoutside for each facet.\n"));
-  maxoutside= minvertex= 0;
-  if (qh VERTEXneighbors
-  && (qh PRINTsummary || qh KEEPinside || qh KEEPcoplanar
-        || qh TRACElevel || qh PRINTstatistics
-        || qh PRINTout[0] == qh_PRINTsummary || qh PRINTout[0] == qh_PRINTnone)) {
-    trace1((qh ferr, 1023, "qh_check_maxout: determine actual maxoutside and minvertex\n"));
-    vertices= qh_pointvertex(/*qh.facet_list*/);
-    FORALLvertices {
-      FOREACHneighbor_(vertex) {
-        zinc_(Zdistvertex);  /* distance also computed by main loop below */
-        qh_distplane(vertex->point, neighbor, &dist);
-        minimize_(minvertex, dist);
-        if (-dist > qh TRACEdist || dist > qh TRACEdist
-        || neighbor == qh tracefacet || vertex == qh tracevertex)
-          qh_fprintf(qh ferr, 8093, "qh_check_maxout: p%d(v%d) is %.2g from f%d\n",
-                    qh_pointid(vertex->point), vertex->id, dist, neighbor->id);
-      }
-    }
-    if (qh MERGING) {
-      wmin_(Wminvertex, qh min_vertex);
-    }
-    qh min_vertex= minvertex;
-    qh_settempfree(&vertices);
-  }
-  facets= qh_pointfacet(/*qh.facet_list*/);
-  do {
-    old_maxoutside= fmax_(qh max_outside, maxoutside);
-    FOREACHfacet_i_(facets) {     /* for each point with facet assignment */
-      if (facet) {
-        point= qh_point(facet_i);
-        if (point == qh GOODpointp)
-          continue;
-        zzinc_(Ztotcheck);
-        qh_distplane(point, facet, &dist);
-        numpart++;
-        bestfacet= qh_findbesthorizon(qh_IScheckmax, point, facet, !qh_NOupper, &dist, &numpart);
-        if (bestfacet && dist > maxoutside) {
-          if (qh ONLYgood && !bestfacet->good
-          && !((bestfacet= qh_findgooddist(point, bestfacet, &dist, &facetlist))
-               && dist > maxoutside))
-            notgood++;
-          else
-            maxoutside= dist;
-        }
-        if (dist > qh TRACEdist || (bestfacet && bestfacet == qh tracefacet))
-          qh_fprintf(qh ferr, 8094, "qh_check_maxout: p%d is %.2g above f%d\n",
-                     qh_pointid(point), dist, (bestfacet ? bestfacet->id : UINT_MAX));
-      }
-    }
-  }while
-    (maxoutside > 2*old_maxoutside);
-    /* if qh.maxoutside increases substantially, qh_SEARCHdist is not valid
-          e.g., RBOX 5000 s Z1 G1e-13 t1001200614 | qhull */
-  zzadd_(Zcheckpart, numpart);
-  qh_settempfree(&facets);
-  wval_(Wmaxout)= maxoutside - qh max_outside;
-  wmax_(Wmaxoutside, qh max_outside);
-  qh max_outside= maxoutside;
-  qh_nearcoplanar(/*qh.facet_list*/);
-  qh maxoutdone= True;
-  trace1((qh ferr, 1024, "qh_check_maxout: maxoutside %2.2g, min_vertex %2.2g, outside of not good %d\n",
-       maxoutside, qh min_vertex, notgood));
-} /* check_maxout */
-#else /* qh_NOmerge */
-void qh_check_maxout(void) {
-}
-#endif
-
-/*---------------------------------
-
-  qh_check_output()
-    performs the checks at the end of qhull algorithm
-    Maybe called after voronoi output.  Will recompute otherwise centrums are Voronoi centers instead
-*/
-void qh_check_output(void) {
-  int i;
-
-  if (qh STOPcone)
-    return;
-  if (qh VERIFYoutput | qh IStracing | qh CHECKfrequently) {
-    qh_checkpolygon(qh facet_list);
-    qh_checkflipped_all(qh facet_list);
-    qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
-  }else if (!qh MERGING && qh_newstats(qhstat precision, &i)) {
-    qh_checkflipped_all(qh facet_list);
-    qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
-  }
-} /* check_output */
-
-
-
-/*---------------------------------
-
-  qh_check_point( point, facet, maxoutside, maxdist, errfacet1, errfacet2 )
-    check that point is less than maxoutside from facet
-*/
-void qh_check_point(pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2) {
-  realT dist;
-
-  /* occurs after statistics reported */
-  qh_distplane(point, facet, &dist);
-  if (dist > *maxoutside) {
-    if (*errfacet1 != facet) {
-      *errfacet2= *errfacet1;
-      *errfacet1= facet;
-    }
-    qh_fprintf(qh ferr, 6111, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
-              qh_pointid(point), facet->id, dist, *maxoutside);
-  }
-  maximize_(*maxdist, dist);
-} /* qh_check_point */
-
-
-/*---------------------------------
-
-  qh_check_points()
-    checks that all points are inside all facets
-
-  notes:
-    if many points and qh_check_maxout not called (i.e., !qh.MERGING),
-       calls qh_findbesthorizon (seldom done).
-    ignores flipped facets
-    maxoutside includes 2 qh.DISTrounds
-      one qh.DISTround for the computed distances in qh_check_points
-    qh_printafacet and qh_printsummary needs only one qh.DISTround
-    the computation for qh.VERIFYdirect does not account for qh.other_points
-
-  design:
-    if many points
-      use qh_check_bestdist()
-    else
-      for all facets
-        for all points
-          check that point is inside facet
-*/
-void qh_check_points(void) {
-  facetT *facet, *errfacet1= NULL, *errfacet2= NULL;
-  realT total, maxoutside, maxdist= -REALmax;
-  pointT *point, **pointp, *pointtemp;
-  boolT testouter;
-
-  maxoutside= qh_maxouter();
-  maxoutside += qh DISTround;
-  /* one more qh.DISTround for check computation */
-  trace1((qh ferr, 1025, "qh_check_points: check all points below %2.2g of all facet planes\n",
-          maxoutside));
-  if (qh num_good)   /* miss counts other_points and !good facets */
-     total= (float)qh num_good * (float)qh num_points;
-  else
-     total= (float)qh num_facets * (float)qh num_points;
-  if (total >= qh_VERIFYdirect && !qh maxoutdone) {
-    if (!qh_QUICKhelp && qh SKIPcheckmax && qh MERGING)
-      qh_fprintf(qh ferr, 7075, "qhull input warning: merging without checking outer planes('Q5' or 'Po').\n\
-Verify may report that a point is outside of a facet.\n");
-    qh_check_bestdist();
-  }else {
-    if (qh_MAXoutside && qh maxoutdone)
-      testouter= True;
-    else
-      testouter= False;
-    if (!qh_QUICKhelp) {
-      if (qh MERGEexact)
-        qh_fprintf(qh ferr, 7076, "qhull input warning: exact merge ('Qx').  Verify may report that a point\n\
-is outside of a facet.  See qh-optq.htm#Qx\n");
-      else if (qh SKIPcheckmax || qh NOnearinside)
-        qh_fprintf(qh ferr, 7077, "qhull input warning: no outer plane check ('Q5') or no processing of\n\
-near-inside points ('Q8').  Verify may report that a point is outside\n\
-of a facet.\n");
-    }
-    if (qh PRINTprecision) {
-      if (testouter)
-        qh_fprintf(qh ferr, 8098, "\n\
-Output completed.  Verifying that all points are below outer planes of\n\
-all %sfacets.  Will make %2.0f distance computations.\n",
-              (qh ONLYgood ?  "good " : ""), total);
-      else
-        qh_fprintf(qh ferr, 8099, "\n\
-Output completed.  Verifying that all points are below %2.2g of\n\
-all %sfacets.  Will make %2.0f distance computations.\n",
-              maxoutside, (qh ONLYgood ?  "good " : ""), total);
-    }
-    FORALLfacets {
-      if (!facet->good && qh ONLYgood)
-        continue;
-      if (facet->flipped)
-        continue;
-      if (!facet->normal) {
-        qh_fprintf(qh ferr, 7061, "qhull warning (qh_check_points): missing normal for facet f%d\n", facet->id);
-        continue;
-      }
-      if (testouter) {
-#if qh_MAXoutside
-        maxoutside= facet->maxoutside + 2* qh DISTround;
-        /* one DISTround to actual point and another to computed point */
-#endif
-      }
-      FORALLpoints {
-        if (point != qh GOODpointp)
-          qh_check_point(point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
-      }
-      FOREACHpoint_(qh other_points) {
-        if (point != qh GOODpointp)
-          qh_check_point(point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
-      }
-    }
-    if (maxdist > qh outside_err) {
-      qh_fprintf(qh ferr, 6112, "qhull precision error (qh_check_points): a coplanar point is %6.2g from convex hull.  The maximum value(qh.outside_err) is %6.2g\n",
-                maxdist, qh outside_err );
-      qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
-    }else if (errfacet1 && qh outside_err > REALmax/2)
-        qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
-    /* else if errfacet1, the error was logged to qh.ferr but does not effect the output */
-    trace0((qh ferr, 21, "qh_check_points: max distance outside %2.2g\n", maxdist));
-  }
-} /* check_points */
-
-
-/*---------------------------------
-
-  qh_checkconvex( facetlist, fault )
-    check that each ridge in facetlist is convex
-    fault = qh_DATAfault if reporting errors
-          = qh_ALGORITHMfault otherwise
-
-  returns:
-    counts Zconcaveridges and Zcoplanarridges
-    errors if concaveridge or if merging an coplanar ridge
-
-  note:
-    if not merging,
-      tests vertices for neighboring simplicial facets
-    else if ZEROcentrum,
-      tests vertices for neighboring simplicial   facets
-    else
-      tests centrums of neighboring facets
-
-  design:
-    for all facets
-      report flipped facets
-      if ZEROcentrum and simplicial neighbors
-        test vertices for neighboring simplicial facets
-      else
-        test centrum against all neighbors
-*/
-void qh_checkconvex(facetT *facetlist, int fault) {
-  facetT *facet, *neighbor, **neighborp, *errfacet1=NULL, *errfacet2=NULL;
-  vertexT *vertex;
-  realT dist;
-  pointT *centrum;
-  boolT waserror= False, centrum_warning= False, tempcentrum= False, allsimplicial;
-  int neighbor_i;
-
-  trace1((qh ferr, 1026, "qh_checkconvex: check all ridges are convex\n"));
-  if (!qh RERUN) {
-    zzval_(Zconcaveridges)= 0;
-    zzval_(Zcoplanarridges)= 0;
-  }
-  FORALLfacet_(facetlist) {
-    if (facet->flipped) {
-      qh_precision("flipped facet");
-      qh_fprintf(qh ferr, 6113, "qhull precision error: f%d is flipped(interior point is outside)\n",
-               facet->id);
-      errfacet1= facet;
-      waserror= True;
-      continue;
-    }
-    if (qh MERGING && (!qh ZEROcentrum || !facet->simplicial || facet->tricoplanar))
-      allsimplicial= False;
-    else {
-      allsimplicial= True;
-      neighbor_i= 0;
-      FOREACHneighbor_(facet) {
-        vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
-        if (!neighbor->simplicial || neighbor->tricoplanar) {
-          allsimplicial= False;
-          continue;
-        }
-        qh_distplane(vertex->point, neighbor, &dist);
-        if (dist > -qh DISTround) {
-          if (fault == qh_DATAfault) {
-            qh_precision("coplanar or concave ridge");
-            qh_fprintf(qh ferr, 6114, "qhull precision error: initial simplex is not convex. Distance=%.2g\n", dist);
-            qh_errexit(qh_ERRsingular, NULL, NULL);
-          }
-          if (dist > qh DISTround) {
-            zzinc_(Zconcaveridges);
-            qh_precision("concave ridge");
-            qh_fprintf(qh ferr, 6115, "qhull precision error: f%d is concave to f%d, since p%d(v%d) is %6.4g above\n",
-              facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
-            errfacet1= facet;
-            errfacet2= neighbor;
-            waserror= True;
-          }else if (qh ZEROcentrum) {
-            if (dist > 0) {     /* qh_checkzero checks that dist < - qh DISTround */
-              zzinc_(Zcoplanarridges);
-              qh_precision("coplanar ridge");
-              qh_fprintf(qh ferr, 6116, "qhull precision error: f%d is clearly not convex to f%d, since p%d(v%d) is %6.4g above\n",
-                facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
-              errfacet1= facet;
-              errfacet2= neighbor;
-              waserror= True;
-            }
-          }else {
-            zzinc_(Zcoplanarridges);
-            qh_precision("coplanar ridge");
-            trace0((qh ferr, 22, "qhull precision error: f%d may be coplanar to f%d, since p%d(v%d) is within %6.4g during p%d\n",
-              facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist, qh furthest_id));
-          }
-        }
-      }
-    }
-    if (!allsimplicial) {
-      if (qh CENTERtype == qh_AScentrum) {
-        if (!facet->center)
-          facet->center= qh_getcentrum(facet);
-        centrum= facet->center;
-      }else {
-        if (!centrum_warning && (!facet->simplicial || facet->tricoplanar)) {
-           centrum_warning= True;
-           qh_fprintf(qh ferr, 7062, "qhull warning: recomputing centrums for convexity test.  This may lead to false, precision errors.\n");
-        }
-        centrum= qh_getcentrum(facet);
-        tempcentrum= True;
-      }
-      FOREACHneighbor_(facet) {
-        if (qh ZEROcentrum && facet->simplicial && neighbor->simplicial)
-          continue;
-        if (facet->tricoplanar || neighbor->tricoplanar)
-          continue;
-        zzinc_(Zdistconvex);
-        qh_distplane(centrum, neighbor, &dist);
-        if (dist > qh DISTround) {
-          zzinc_(Zconcaveridges);
-          qh_precision("concave ridge");
-          qh_fprintf(qh ferr, 6117, "qhull precision error: f%d is concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
-            facet->id, neighbor->id, facet->id, dist, neighbor->id);
-          errfacet1= facet;
-          errfacet2= neighbor;
-          waserror= True;
-        }else if (dist >= 0.0) {   /* if arithmetic always rounds the same,
-                                     can test against centrum radius instead */
-          zzinc_(Zcoplanarridges);
-          qh_precision("coplanar ridge");
-          qh_fprintf(qh ferr, 6118, "qhull precision error: f%d is coplanar or concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
-            facet->id, neighbor->id, facet->id, dist, neighbor->id);
-          errfacet1= facet;
-          errfacet2= neighbor;
-          waserror= True;
-        }
-      }
-      if (tempcentrum)
-        qh_memfree(centrum, qh normal_size);
-    }
-  }
-  if (waserror && !qh FORCEoutput)
-    qh_errexit2(qh_ERRprec, errfacet1, errfacet2);
-} /* checkconvex */
-
-
-/*---------------------------------
-
-  qh_checkfacet( facet, newmerge, waserror )
-    checks for consistency errors in facet
-    newmerge set if from merge.c
-
-  returns:
-    sets waserror if any error occurs
-
-  checks:
-    vertex ids are inverse sorted
-    unless newmerge, at least hull_dim neighbors and vertices (exactly if simplicial)
-    if non-simplicial, at least as many ridges as neighbors
-    neighbors are not duplicated
-    ridges are not duplicated
-    in 3-d, ridges=verticies
-    (qh.hull_dim-1) ridge vertices
-    neighbors are reciprocated
-    ridge neighbors are facet neighbors and a ridge for every neighbor
-    simplicial neighbors match facetintersect
-    vertex intersection matches vertices of common ridges
-    vertex neighbors and facet vertices agree
-    all ridges have distinct vertex sets
-
-  notes:
-    uses neighbor->seen
-
-  design:
-    check sets
-    check vertices
-    check sizes of neighbors and vertices
-    check for qh_MERGEridge and qh_DUPLICATEridge flags
-    check neighbor set
-    check ridge set
-    check ridges, neighbors, and vertices
-*/
-void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp) {
-  facetT *neighbor, **neighborp, *errother=NULL;
-  ridgeT *ridge, **ridgep, *errridge= NULL, *ridge2;
-  vertexT *vertex, **vertexp;
-  unsigned previousid= INT_MAX;
-  int numneighbors, numvertices, numridges=0, numRvertices=0;
-  boolT waserror= False;
-  int skipA, skipB, ridge_i, ridge_n, i;
-  setT *intersection;
-
-  if (facet->visible) {
-    qh_fprintf(qh ferr, 6119, "qhull internal error (qh_checkfacet): facet f%d is on the visible_list\n",
-      facet->id);
-    qh_errexit(qh_ERRqhull, facet, NULL);
-  }
-  if (!facet->normal) {
-    qh_fprintf(qh ferr, 6120, "qhull internal error (qh_checkfacet): facet f%d does not have  a normal\n",
-      facet->id);
-    waserror= True;
-  }
-  qh_setcheck(facet->vertices, "vertices for f", facet->id);
-  qh_setcheck(facet->ridges, "ridges for f", facet->id);
-  qh_setcheck(facet->outsideset, "outsideset for f", facet->id);
-  qh_setcheck(facet->coplanarset, "coplanarset for f", facet->id);
-  qh_setcheck(facet->neighbors, "neighbors for f", facet->id);
-  FOREACHvertex_(facet->vertices) {
-    if (vertex->deleted) {
-      qh_fprintf(qh ferr, 6121, "qhull internal error (qh_checkfacet): deleted vertex v%d in f%d\n", vertex->id, facet->id);
-      qh_errprint("ERRONEOUS", NULL, NULL, NULL, vertex);
-      waserror= True;
-    }
-    if (vertex->id >= previousid) {
-      qh_fprintf(qh ferr, 6122, "qhull internal error (qh_checkfacet): vertices of f%d are not in descending id order at v%d\n", facet->id, vertex->id);
-      waserror= True;
-      break;
-    }
-    previousid= vertex->id;
-  }
-  numneighbors= qh_setsize(facet->neighbors);
-  numvertices= qh_setsize(facet->vertices);
-  numridges= qh_setsize(facet->ridges);
-  if (facet->simplicial) {
-    if (numvertices+numneighbors != 2*qh hull_dim
-    && !facet->degenerate && !facet->redundant) {
-      qh_fprintf(qh ferr, 6123, "qhull internal error (qh_checkfacet): for simplicial facet f%d, #vertices %d + #neighbors %d != 2*qh hull_dim\n",
-                facet->id, numvertices, numneighbors);
-      qh_setprint(qh ferr, "", facet->neighbors);
-      waserror= True;
-    }
-  }else { /* non-simplicial */
-    if (!newmerge
-    &&(numvertices < qh hull_dim || numneighbors < qh hull_dim)
-    && !facet->degenerate && !facet->redundant) {
-      qh_fprintf(qh ferr, 6124, "qhull internal error (qh_checkfacet): for facet f%d, #vertices %d or #neighbors %d < qh hull_dim\n",
-         facet->id, numvertices, numneighbors);
-       waserror= True;
-    }
-    /* in 3-d, can get a vertex twice in an edge list, e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv TP624 TW1e-13 T4 */
-    if (numridges < numneighbors
-    ||(qh hull_dim == 3 && numvertices > numridges && !qh NEWfacets)
-    ||(qh hull_dim == 2 && numridges + numvertices + numneighbors != 6)) {
-      if (!facet->degenerate && !facet->redundant) {
-        qh_fprintf(qh ferr, 6125, "qhull internal error (qh_checkfacet): for facet f%d, #ridges %d < #neighbors %d or(3-d) > #vertices %d or(2-d) not all 2\n",
-            facet->id, numridges, numneighbors, numvertices);
-        waserror= True;
-      }
-    }
-  }
-  FOREACHneighbor_(facet) {
-    if (neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) {
-      qh_fprintf(qh ferr, 6126, "qhull internal error (qh_checkfacet): facet f%d still has a MERGE or DUP neighbor\n", facet->id);
-      qh_errexit(qh_ERRqhull, facet, NULL);
-    }
-    neighbor->seen= True;
-  }
-  FOREACHneighbor_(facet) {
-    if (!qh_setin(neighbor->neighbors, facet)) {
-      qh_fprintf(qh ferr, 6127, "qhull internal error (qh_checkfacet): facet f%d has neighbor f%d, but f%d does not have neighbor f%d\n",
-              facet->id, neighbor->id, neighbor->id, facet->id);
-      errother= neighbor;
-      waserror= True;
-    }
-    if (!neighbor->seen) {
-      qh_fprintf(qh ferr, 6128, "qhull internal error (qh_checkfacet): facet f%d has a duplicate neighbor f%d\n",
-              facet->id, neighbor->id);
-      errother= neighbor;
-      waserror= True;
-    }
-    neighbor->seen= False;
-  }
-  FOREACHridge_(facet->ridges) {
-    qh_setcheck(ridge->vertices, "vertices for r", ridge->id);
-    ridge->seen= False;
-  }
-  FOREACHridge_(facet->ridges) {
-    if (ridge->seen) {
-      qh_fprintf(qh ferr, 6129, "qhull internal error (qh_checkfacet): facet f%d has a duplicate ridge r%d\n",
-              facet->id, ridge->id);
-      errridge= ridge;
-      waserror= True;
-    }
-    ridge->seen= True;
-    numRvertices= qh_setsize(ridge->vertices);
-    if (numRvertices != qh hull_dim - 1) {
-      qh_fprintf(qh ferr, 6130, "qhull internal error (qh_checkfacet): ridge between f%d and f%d has %d vertices\n",
-                ridge->top->id, ridge->bottom->id, numRvertices);
-      errridge= ridge;
-      waserror= True;
-    }
-    neighbor= otherfacet_(ridge, facet);
-    neighbor->seen= True;
-    if (!qh_setin(facet->neighbors, neighbor)) {
-      qh_fprintf(qh ferr, 6131, "qhull internal error (qh_checkfacet): for facet f%d, neighbor f%d of ridge r%d not in facet\n",
-           facet->id, neighbor->id, ridge->id);
-      errridge= ridge;
-      waserror= True;
-    }
-  }
-  if (!facet->simplicial) {
-    FOREACHneighbor_(facet) {
-      if (!neighbor->seen) {
-        qh_fprintf(qh ferr, 6132, "qhull internal error (qh_checkfacet): facet f%d does not have a ridge for neighbor f%d\n",
-              facet->id, neighbor->id);
-        errother= neighbor;
-        waserror= True;
-      }
-      intersection= qh_vertexintersect_new(facet->vertices, neighbor->vertices);
-      qh_settemppush(intersection);
-      FOREACHvertex_(facet->vertices) {
-        vertex->seen= False;
-        vertex->seen2= False;
-      }
-      FOREACHvertex_(intersection)
-        vertex->seen= True;
-      FOREACHridge_(facet->ridges) {
-        if (neighbor != otherfacet_(ridge, facet))
-            continue;
-        FOREACHvertex_(ridge->vertices) {
-          if (!vertex->seen) {
-            qh_fprintf(qh ferr, 6133, "qhull internal error (qh_checkfacet): vertex v%d in r%d not in f%d intersect f%d\n",
-                  vertex->id, ridge->id, facet->id, neighbor->id);
-            qh_errexit(qh_ERRqhull, facet, ridge);
-          }
-          vertex->seen2= True;
-        }
-      }
-      if (!newmerge) {
-        FOREACHvertex_(intersection) {
-          if (!vertex->seen2) {
-            if (qh IStracing >=3 || !qh MERGING) {
-              qh_fprintf(qh ferr, 6134, "qhull precision error (qh_checkfacet): vertex v%d in f%d intersect f%d but\n\
- not in a ridge.  This is ok under merging.  Last point was p%d\n",
-                     vertex->id, facet->id, neighbor->id, qh furthest_id);
-              if (!qh FORCEoutput && !qh MERGING) {
-                qh_errprint("ERRONEOUS", facet, neighbor, NULL, vertex);
-                if (!qh MERGING)
-                  qh_errexit(qh_ERRqhull, NULL, NULL);
-              }
-            }
-          }
-        }
-      }
-      qh_settempfree(&intersection);
-    }
-  }else { /* simplicial */
-    FOREACHneighbor_(facet) {
-      if (neighbor->simplicial) {
-        skipA= SETindex_(facet->neighbors, neighbor);
-        skipB= qh_setindex(neighbor->neighbors, facet);
-        if (skipA<0 || skipB<0 || !qh_setequal_skip(facet->vertices, skipA, neighbor->vertices, skipB)) {
-          qh_fprintf(qh ferr, 6135, "qhull internal error (qh_checkfacet): facet f%d skip %d and neighbor f%d skip %d do not match \n",
-                   facet->id, skipA, neighbor->id, skipB);
-          errother= neighbor;
-          waserror= True;
-        }
-      }
-    }
-  }
-  if (qh hull_dim < 5 && (qh IStracing > 2 || qh CHECKfrequently)) {
-    FOREACHridge_i_(facet->ridges) {           /* expensive */
-      for (i=ridge_i+1; i < ridge_n; i++) {
-        ridge2= SETelemt_(facet->ridges, i, ridgeT);
-        if (qh_setequal(ridge->vertices, ridge2->vertices)) {
-          qh_fprintf(qh ferr, 6227, "Qhull internal error (qh_checkfacet): ridges r%d and r%d have the same vertices\n",
-                  ridge->id, ridge2->id);
-          errridge= ridge;
-          waserror= True;
-        }
-      }
-    }
-  }
-  if (waserror) {
-    qh_errprint("ERRONEOUS", facet, errother, errridge, NULL);
-    *waserrorp= True;
-  }
-} /* checkfacet */
-
-
-/*---------------------------------
-
-  qh_checkflipped_all( facetlist )
-    checks orientation of facets in list against interior point
-*/
-void qh_checkflipped_all(facetT *facetlist) {
-  facetT *facet;
-  boolT waserror= False;
-  realT dist;
-
-  if (facetlist == qh facet_list)
-    zzval_(Zflippedfacets)= 0;
-  FORALLfacet_(facetlist) {
-    if (facet->normal && !qh_checkflipped(facet, &dist, !qh_ALL)) {
-      qh_fprintf(qh ferr, 6136, "qhull precision error: facet f%d is flipped, distance= %6.12g\n",
-              facet->id, dist);
-      if (!qh FORCEoutput) {
-        qh_errprint("ERRONEOUS", facet, NULL, NULL, NULL);
-        waserror= True;
-      }
-    }
-  }
-  if (waserror) {
-    qh_fprintf(qh ferr, 8101, "\n\
-A flipped facet occurs when its distance to the interior point is\n\
-greater than %2.2g, the maximum roundoff error.\n", -qh DISTround);
-    qh_errexit(qh_ERRprec, NULL, NULL);
-  }
-} /* checkflipped_all */
-
-/*---------------------------------
-
-  qh_checkpolygon( facetlist )
-    checks the correctness of the structure
-
-  notes:
-    call with either qh.facet_list or qh.newfacet_list
-    checks num_facets and num_vertices if qh.facet_list
-
-  design:
-    for each facet
-      checks facet and outside set
-    initializes vertexlist
-    for each facet
-      checks vertex set
-    if checking all facets(qh.facetlist)
-      check facet count
-      if qh.VERTEXneighbors
-        check vertex neighbors and count
-      check vertex count
-*/
-void qh_checkpolygon(facetT *facetlist) {
-  facetT *facet;
-  vertexT *vertex, **vertexp, *vertexlist;
-  int numfacets= 0, numvertices= 0, numridges= 0;
-  int totvneighbors= 0, totvertices= 0;
-  boolT waserror= False, nextseen= False, visibleseen= False;
-
-  trace1((qh ferr, 1027, "qh_checkpolygon: check all facets from f%d\n", facetlist->id));
-  if (facetlist != qh facet_list || qh ONLYgood)
-    nextseen= True;
-  FORALLfacet_(facetlist) {
-    if (facet == qh visible_list)
-      visibleseen= True;
-    if (!facet->visible) {
-      if (!nextseen) {
-        if (facet == qh facet_next)
-          nextseen= True;
-        else if (qh_setsize(facet->outsideset)) {
-          if (!qh NARROWhull
-#if !qh_COMPUTEfurthest
-               || facet->furthestdist >= qh MINoutside
-#endif
-                        ) {
-            qh_fprintf(qh ferr, 6137, "qhull internal error (qh_checkpolygon): f%d has outside points before qh facet_next\n",
-                     facet->id);
-            qh_errexit(qh_ERRqhull, facet, NULL);
-          }
-        }
-      }
-      numfacets++;
-      qh_checkfacet(facet, False, &waserror);
-    }
-  }
-  if (qh visible_list && !visibleseen && facetlist == qh facet_list) {
-    qh_fprintf(qh ferr, 6138, "qhull internal error (qh_checkpolygon): visible list f%d no longer on facet list\n", qh visible_list->id);
-    qh_printlists();
-    qh_errexit(qh_ERRqhull, qh visible_list, NULL);
-  }
-  if (facetlist == qh facet_list)
-    vertexlist= qh vertex_list;
-  else if (facetlist == qh newfacet_list)
-    vertexlist= qh newvertex_list;
-  else
-    vertexlist= NULL;
-  FORALLvertex_(vertexlist) {
-    vertex->seen= False;
-    vertex->visitid= 0;
-  }
-  FORALLfacet_(facetlist) {
-    if (facet->visible)
-      continue;
-    if (facet->simplicial)
-      numridges += qh hull_dim;
-    else
-      numridges += qh_setsize(facet->ridges);
-    FOREACHvertex_(facet->vertices) {
-      vertex->visitid++;
-      if (!vertex->seen) {
-        vertex->seen= True;
-        numvertices++;
-        if (qh_pointid(vertex->point) == qh_IDunknown) {
-          qh_fprintf(qh ferr, 6139, "qhull internal error (qh_checkpolygon): unknown point %p for vertex v%d first_point %p\n",
-                   vertex->point, vertex->id, qh first_point);
-          waserror= True;
-        }
-      }
-    }
-  }
-  qh vertex_visit += (unsigned int)numfacets;
-  if (facetlist == qh facet_list) {
-    if (numfacets != qh num_facets - qh num_visible) {
-      qh_fprintf(qh ferr, 6140, "qhull internal error (qh_checkpolygon): actual number of facets is %d, cumulative facet count is %d - %d visible facets\n",
-              numfacets, qh num_facets, qh num_visible);
-      waserror= True;
-    }
-    qh vertex_visit++;
-    if (qh VERTEXneighbors) {
-      FORALLvertices {
-        qh_setcheck(vertex->neighbors, "neighbors for v", vertex->id);
-        if (vertex->deleted)
-          continue;
-        totvneighbors += qh_setsize(vertex->neighbors);
-      }
-      FORALLfacet_(facetlist)
-        totvertices += qh_setsize(facet->vertices);
-      if (totvneighbors != totvertices) {
-        qh_fprintf(qh ferr, 6141, "qhull internal error (qh_checkpolygon): vertex neighbors inconsistent.  Totvneighbors %d, totvertices %d\n",
-                totvneighbors, totvertices);
-        waserror= True;
-      }
-    }
-    if (numvertices != qh num_vertices - qh_setsize(qh del_vertices)) {
-      qh_fprintf(qh ferr, 6142, "qhull internal error (qh_checkpolygon): actual number of vertices is %d, cumulative vertex count is %d\n",
-              numvertices, qh num_vertices - qh_setsize(qh del_vertices));
-      waserror= True;
-    }
-    if (qh hull_dim == 2 && numvertices != numfacets) {
-      qh_fprintf(qh ferr, 6143, "qhull internal error (qh_checkpolygon): #vertices %d != #facets %d\n",
-        numvertices, numfacets);
-      waserror= True;
-    }
-    if (qh hull_dim == 3 && numvertices + numfacets - numridges/2 != 2) {
-      qh_fprintf(qh ferr, 7063, "qhull warning: #vertices %d + #facets %d - #edges %d != 2\n\
-        A vertex appears twice in a edge list.  May occur during merging.",
-        numvertices, numfacets, numridges/2);
-      /* occurs if lots of merging and a vertex ends up twice in an edge list.  e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv */
-    }
-  }
-  if (waserror)
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-} /* checkpolygon */
-
-
-/*---------------------------------
-
-  qh_checkvertex( vertex )
-    check vertex for consistency
-    checks vertex->neighbors
-
-  notes:
-    neighbors checked efficiently in checkpolygon
-*/
-void qh_checkvertex(vertexT *vertex) {
-  boolT waserror= False;
-  facetT *neighbor, **neighborp, *errfacet=NULL;
-
-  if (qh_pointid(vertex->point) == qh_IDunknown) {
-    qh_fprintf(qh ferr, 6144, "qhull internal error (qh_checkvertex): unknown point id %p\n", vertex->point);
-    waserror= True;
-  }
-  if (vertex->id >= qh vertex_id) {
-    qh_fprintf(qh ferr, 6145, "qhull internal error (qh_checkvertex): unknown vertex id %d\n", vertex->id);
-    waserror= True;
-  }
-  if (!waserror && !vertex->deleted) {
-    if (qh_setsize(vertex->neighbors)) {
-      FOREACHneighbor_(vertex) {
-        if (!qh_setin(neighbor->vertices, vertex)) {
-          qh_fprintf(qh ferr, 6146, "qhull internal error (qh_checkvertex): neighbor f%d does not contain v%d\n", neighbor->id, vertex->id);
-          errfacet= neighbor;
-          waserror= True;
-        }
-      }
-    }
-  }
-  if (waserror) {
-    qh_errprint("ERRONEOUS", NULL, NULL, NULL, vertex);
-    qh_errexit(qh_ERRqhull, errfacet, NULL);
-  }
-} /* checkvertex */
-
-/*---------------------------------
-
-  qh_clearcenters( type )
-    clear old data from facet->center
-
-  notes:
-    sets new centertype
-    nop if CENTERtype is the same
-*/
-void qh_clearcenters(qh_CENTER type) {
-  facetT *facet;
-
-  if (qh CENTERtype != type) {
-    FORALLfacets {
-      if (facet->tricoplanar && !facet->keepcentrum)
-          facet->center= NULL;  /* center is owned by the ->keepcentrum facet */
-      else if (qh CENTERtype == qh_ASvoronoi){
-        if (facet->center) {
-          qh_memfree(facet->center, qh center_size);
-          facet->center= NULL;
-        }
-      }else /* qh.CENTERtype == qh_AScentrum */ {
-        if (facet->center) {
-          qh_memfree(facet->center, qh normal_size);
-          facet->center= NULL;
-        }
-      }
-    }
-    qh CENTERtype= type;
-  }
-  trace2((qh ferr, 2043, "qh_clearcenters: switched to center type %d\n", type));
-} /* clearcenters */
-
-/*---------------------------------
-
-  qh_createsimplex( vertices )
-    creates a simplex from a set of vertices
-
-  returns:
-    initializes qh.facet_list to the simplex
-    initializes qh.newfacet_list, .facet_tail
-    initializes qh.vertex_list, .newvertex_list, .vertex_tail
-
-  design:
-    initializes lists
-    for each vertex
-      create a new facet
-    for each new facet
-      create its neighbor set
-*/
-void qh_createsimplex(setT *vertices) {
-  facetT *facet= NULL, *newfacet;
-  boolT toporient= True;
-  int vertex_i, vertex_n, nth;
-  setT *newfacets= qh_settemp(qh hull_dim+1);
-  vertexT *vertex;
-
-  qh facet_list= qh newfacet_list= qh facet_tail= qh_newfacet();
-  qh num_facets= qh num_vertices= qh num_visible= 0;
-  qh vertex_list= qh newvertex_list= qh vertex_tail= qh_newvertex(NULL);
-  FOREACHvertex_i_(vertices) {
-    newfacet= qh_newfacet();
-    newfacet->vertices= qh_setnew_delnthsorted(vertices, vertex_n,
-                                                vertex_i, 0);
-    newfacet->toporient= (unsigned char)toporient;
-    qh_appendfacet(newfacet);
-    newfacet->newfacet= True;
-    qh_appendvertex(vertex);
-    qh_setappend(&newfacets, newfacet);
-    toporient ^= True;
-  }
-  FORALLnew_facets {
-    nth= 0;
-    FORALLfacet_(qh newfacet_list) {
-      if (facet != newfacet)
-        SETelem_(newfacet->neighbors, nth++)= facet;
-    }
-    qh_settruncate(newfacet->neighbors, qh hull_dim);
-  }
-  qh_settempfree(&newfacets);
-  trace1((qh ferr, 1028, "qh_createsimplex: created simplex\n"));
-} /* createsimplex */
-
-/*---------------------------------
-
-  qh_delridge( ridge )
-    deletes ridge from data structures it belongs to
-    frees up its memory
-
-  notes:
-    in merge.c, caller sets vertex->delridge for each vertex
-    ridges also freed in qh_freeqhull
-*/
-void qh_delridge(ridgeT *ridge) {
-  void **freelistp; /* used if !qh_NOmem by qh_memfree_() */
-
-  qh_setdel(ridge->top->ridges, ridge);
-  qh_setdel(ridge->bottom->ridges, ridge);
-  qh_setfree(&(ridge->vertices));
-  qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
-} /* delridge */
-
-
-/*---------------------------------
-
-  qh_delvertex( vertex )
-    deletes a vertex and frees its memory
-
-  notes:
-    assumes vertex->adjacencies have been updated if needed
-    unlinks from vertex_list
-*/
-void qh_delvertex(vertexT *vertex) {
-
-  if (vertex == qh tracevertex)
-    qh tracevertex= NULL;
-  qh_removevertex(vertex);
-  qh_setfree(&vertex->neighbors);
-  qh_memfree(vertex, (int)sizeof(vertexT));
-} /* delvertex */
-
-
-/*---------------------------------
-
-  qh_facet3vertex(  )
-    return temporary set of 3-d vertices in qh_ORIENTclock order
-
-  design:
-    if simplicial facet
-      build set from facet->vertices with facet->toporient
-    else
-      for each ridge in order
-        build set from ridge's vertices
-*/
-setT *qh_facet3vertex(facetT *facet) {
-  ridgeT *ridge, *firstridge;
-  vertexT *vertex;
-  int cntvertices, cntprojected=0;
-  setT *vertices;
-
-  cntvertices= qh_setsize(facet->vertices);
-  vertices= qh_settemp(cntvertices);
-  if (facet->simplicial) {
-    if (cntvertices != 3) {
-      qh_fprintf(qh ferr, 6147, "qhull internal error (qh_facet3vertex): only %d vertices for simplicial facet f%d\n",
-                  cntvertices, facet->id);
-      qh_errexit(qh_ERRqhull, facet, NULL);
-    }
-    qh_setappend(&vertices, SETfirst_(facet->vertices));
-    if (facet->toporient ^ qh_ORIENTclock)
-      qh_setappend(&vertices, SETsecond_(facet->vertices));
-    else
-      qh_setaddnth(&vertices, 0, SETsecond_(facet->vertices));
-    qh_setappend(&vertices, SETelem_(facet->vertices, 2));
-  }else {
-    ridge= firstridge= SETfirstt_(facet->ridges, ridgeT);   /* no infinite */
-    while ((ridge= qh_nextridge3d(ridge, facet, &vertex))) {
-      qh_setappend(&vertices, vertex);
-      if (++cntprojected > cntvertices || ridge == firstridge)
-        break;
-    }
-    if (!ridge || cntprojected != cntvertices) {
-      qh_fprintf(qh ferr, 6148, "qhull internal error (qh_facet3vertex): ridges for facet %d don't match up.  got at least %d\n",
-                  facet->id, cntprojected);
-      qh_errexit(qh_ERRqhull, facet, ridge);
-    }
-  }
-  return vertices;
-} /* facet3vertex */
-
-/*---------------------------------
-
-  qh_findbestfacet( point, bestoutside, bestdist, isoutside )
-    find facet that is furthest below a point
-
-    for Delaunay triangulations,
-      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
-      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
-
-  returns:
-    if bestoutside is set (e.g., qh_ALL)
-      returns best facet that is not upperdelaunay
-      if Delaunay and inside, point is outside circumsphere of bestfacet
-    else
-      returns first facet below point
-      if point is inside, returns nearest, !upperdelaunay facet
-    distance to facet
-    isoutside set if outside of facet
-
-  notes:
-    For tricoplanar facets, this finds one of the tricoplanar facets closest
-    to the point.  For Delaunay triangulations, the point may be inside a
-    different tricoplanar facet. See locate a facet with qh_findbestfacet()
-
-    If inside, qh_findbestfacet performs an exhaustive search
-       this may be too conservative.  Sometimes it is clearly required.
-
-    qh_findbestfacet is not used by qhull.
-    uses qh.visit_id and qh.coplanarset
-
-  see:
-    qh_findbest
-*/
-facetT *qh_findbestfacet(pointT *point, boolT bestoutside,
-           realT *bestdist, boolT *isoutside) {
-  facetT *bestfacet= NULL;
-  int numpart, totpart= 0;
-
-  bestfacet= qh_findbest(point, qh facet_list,
-                            bestoutside, !qh_ISnewfacets, bestoutside /* qh_NOupper */,
-                            bestdist, isoutside, &totpart);
-  if (*bestdist < -qh DISTround) {
-    bestfacet= qh_findfacet_all(point, bestdist, isoutside, &numpart);
-    totpart += numpart;
-    if ((isoutside && *isoutside && bestoutside)
-    || (isoutside && !*isoutside && bestfacet->upperdelaunay)) {
-      bestfacet= qh_findbest(point, bestfacet,
-                            bestoutside, False, bestoutside,
-                            bestdist, isoutside, &totpart);
-      totpart += numpart;
-    }
-  }
-  trace3((qh ferr, 3014, "qh_findbestfacet: f%d dist %2.2g isoutside %d totpart %d\n",
-      bestfacet->id, *bestdist, (isoutside ? *isoutside : UINT_MAX), totpart));
-  return bestfacet;
-} /* findbestfacet */
-
-/*---------------------------------
-
-  qh_findbestlower( facet, point, bestdist, numpart )
-    returns best non-upper, non-flipped neighbor of facet for point
-    if needed, searches vertex neighbors
-
-  returns:
-    returns bestdist and updates numpart
-
-  notes:
-    if Delaunay and inside, point is outside of circumsphere of bestfacet
-    called by qh_findbest() for points above an upperdelaunay facet
-
-*/
-facetT *qh_findbestlower(facetT *upperfacet, pointT *point, realT *bestdistp, int *numpart) {
-  facetT *neighbor, **neighborp, *bestfacet= NULL;
-  realT bestdist= -REALmax/2 /* avoid underflow */;
-  realT dist;
-  vertexT *vertex;
-  boolT isoutside= False;  /* not used */
-
-  zinc_(Zbestlower);
-  FOREACHneighbor_(upperfacet) {
-    if (neighbor->upperdelaunay || neighbor->flipped)
-      continue;
-    (*numpart)++;
-    qh_distplane(point, neighbor, &dist);
-    if (dist > bestdist) {
-      bestfacet= neighbor;
-      bestdist= dist;
-    }
-  }
-  if (!bestfacet) {
-    zinc_(Zbestlowerv);
-    /* rarely called, numpart does not count nearvertex computations */
-    vertex= qh_nearvertex(upperfacet, point, &dist);
-    qh_vertexneighbors();
-    FOREACHneighbor_(vertex) {
-      if (neighbor->upperdelaunay || neighbor->flipped)
-        continue;
-      (*numpart)++;
-      qh_distplane(point, neighbor, &dist);
-      if (dist > bestdist) {
-        bestfacet= neighbor;
-        bestdist= dist;
-      }
-    }
-  }
-  if (!bestfacet) {
-    zinc_(Zbestlowerall);  /* invoked once per point in outsideset */
-    zmax_(Zbestloweralln, qh num_facets);
-    /* [dec'15] Previously reported as QH6228 */
-    trace3((qh ferr, 3025, "qh_findbestlower: all neighbors of facet %d are flipped or upper Delaunay.  Search all facets\n",
-        upperfacet->id));
-    /* rarely called */
-    bestfacet= qh_findfacet_all(point, &bestdist, &isoutside, numpart);
-  }
-  *bestdistp= bestdist;
-  trace3((qh ferr, 3015, "qh_findbestlower: f%d dist %2.2g for f%d p%d\n",
-          bestfacet->id, bestdist, upperfacet->id, qh_pointid(point)));
-  return bestfacet;
-} /* findbestlower */
-
-/*---------------------------------
-
-  qh_findfacet_all( point, bestdist, isoutside, numpart )
-    exhaustive search for facet below a point
-
-    for Delaunay triangulations,
-      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
-      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
-
-  returns:
-    returns first facet below point
-    if point is inside,
-      returns nearest facet
-    distance to facet
-    isoutside if point is outside of the hull
-    number of distance tests
-
-  notes:
-    primarily for library users, rarely used by Qhull
-*/
-facetT *qh_findfacet_all(pointT *point, realT *bestdist, boolT *isoutside,
-                          int *numpart) {
-  facetT *bestfacet= NULL, *facet;
-  realT dist;
-  int totpart= 0;
-
-  *bestdist= -REALmax;
-  *isoutside= False;
-  FORALLfacets {
-    if (facet->flipped || !facet->normal)
-      continue;
-    totpart++;
-    qh_distplane(point, facet, &dist);
-    if (dist > *bestdist) {
-      *bestdist= dist;
-      bestfacet= facet;
-      if (dist > qh MINoutside) {
-        *isoutside= True;
-        break;
-      }
-    }
-  }
-  *numpart= totpart;
-  trace3((qh ferr, 3016, "qh_findfacet_all: f%d dist %2.2g isoutside %d totpart %d\n",
-          getid_(bestfacet), *bestdist, *isoutside, totpart));
-  return bestfacet;
-} /* findfacet_all */
-
-/*---------------------------------
-
-  qh_findgood( facetlist, goodhorizon )
-    identify good facets for qh.PRINTgood
-    if qh.GOODvertex>0
-      facet includes point as vertex
-      if !match, returns goodhorizon
-      inactive if qh.MERGING
-    if qh.GOODpoint
-      facet is visible or coplanar (>0) or not visible (<0)
-    if qh.GOODthreshold
-      facet->normal matches threshold
-    if !goodhorizon and !match,
-      selects facet with closest angle
-      sets GOODclosest
-
-  returns:
-    number of new, good facets found
-    determines facet->good
-    may update qh.GOODclosest
-
-  notes:
-    qh_findgood_all further reduces the good region
-
-  design:
-    count good facets
-    mark good facets for qh.GOODpoint
-    mark good facets for qh.GOODthreshold
-    if necessary
-      update qh.GOODclosest
-*/
-int qh_findgood(facetT *facetlist, int goodhorizon) {
-  facetT *facet, *bestfacet= NULL;
-  realT angle, bestangle= REALmax, dist;
-  int  numgood=0;
-
-  FORALLfacet_(facetlist) {
-    if (facet->good)
-      numgood++;
-  }
-  if (qh GOODvertex>0 && !qh MERGING) {
-    FORALLfacet_(facetlist) {
-      if (!qh_isvertex(qh GOODvertexp, facet->vertices)) {
-        facet->good= False;
-        numgood--;
-      }
-    }
-  }
-  if (qh GOODpoint && numgood) {
-    FORALLfacet_(facetlist) {
-      if (facet->good && facet->normal) {
-        zinc_(Zdistgood);
-        qh_distplane(qh GOODpointp, facet, &dist);
-        if ((qh GOODpoint > 0) ^ (dist > 0.0)) {
-          facet->good= False;
-          numgood--;
-        }
-      }
-    }
-  }
-  if (qh GOODthreshold && (numgood || goodhorizon || qh GOODclosest)) {
-    FORALLfacet_(facetlist) {
-      if (facet->good && facet->normal) {
-        if (!qh_inthresholds(facet->normal, &angle)) {
-          facet->good= False;
-          numgood--;
-          if (angle < bestangle) {
-            bestangle= angle;
-            bestfacet= facet;
-          }
-        }
-      }
-    }
-    if (!numgood && (!goodhorizon || qh GOODclosest)) {
-      if (qh GOODclosest) {
-        if (qh GOODclosest->visible)
-          qh GOODclosest= NULL;
-        else {
-          qh_inthresholds(qh GOODclosest->normal, &angle);
-          if (angle < bestangle)
-            bestfacet= qh GOODclosest;
-        }
-      }
-      if (bestfacet && bestfacet != qh GOODclosest) {
-        if (qh GOODclosest)
-          qh GOODclosest->good= False;
-        qh GOODclosest= bestfacet;
-        bestfacet->good= True;
-        numgood++;
-        trace2((qh ferr, 2044, "qh_findgood: f%d is closest(%2.2g) to thresholds\n",
-           bestfacet->id, bestangle));
-        return numgood;
-      }
-    }else if (qh GOODclosest) { /* numgood > 0 */
-      qh GOODclosest->good= False;
-      qh GOODclosest= NULL;
-    }
-  }
-  zadd_(Zgoodfacet, numgood);
-  trace2((qh ferr, 2045, "qh_findgood: found %d good facets with %d good horizon\n",
-               numgood, goodhorizon));
-  if (!numgood && qh GOODvertex>0 && !qh MERGING)
-    return goodhorizon;
-  return numgood;
-} /* findgood */
-
-/*---------------------------------
-
-  qh_findgood_all( facetlist )
-    apply other constraints for good facets (used by qh.PRINTgood)
-    if qh.GOODvertex
-      facet includes (>0) or doesn't include (<0) point as vertex
-      if last good facet and ONLYgood, prints warning and continues
-    if qh.SPLITthresholds
-      facet->normal matches threshold, or if none, the closest one
-    calls qh_findgood
-    nop if good not used
-
-  returns:
-    clears facet->good if not good
-    sets qh.num_good
-
-  notes:
-    this is like qh_findgood but more restrictive
-
-  design:
-    uses qh_findgood to mark good facets
-    marks facets for qh.GOODvertex
-    marks facets for qh.SPLITthreholds
-*/
-void qh_findgood_all(facetT *facetlist) {
-  facetT *facet, *bestfacet=NULL;
-  realT angle, bestangle= REALmax;
-  int  numgood=0, startgood;
-
-  if (!qh GOODvertex && !qh GOODthreshold && !qh GOODpoint
-  && !qh SPLITthresholds)
-    return;
-  if (!qh ONLYgood)
-    qh_findgood(qh facet_list, 0);
-  FORALLfacet_(facetlist) {
-    if (facet->good)
-      numgood++;
-  }
-  if (qh GOODvertex <0 || (qh GOODvertex > 0 && qh MERGING)) {
-    FORALLfacet_(facetlist) {
-      if (facet->good && ((qh GOODvertex > 0) ^ !!qh_isvertex(qh GOODvertexp, facet->vertices))) {
-        if (!--numgood) {
-          if (qh ONLYgood) {
-            qh_fprintf(qh ferr, 7064, "qhull warning: good vertex p%d does not match last good facet f%d.  Ignored.\n",
-               qh_pointid(qh GOODvertexp), facet->id);
-            return;
-          }else if (qh GOODvertex > 0)
-            qh_fprintf(qh ferr, 7065, "qhull warning: point p%d is not a vertex('QV%d').\n",
-                qh GOODvertex-1, qh GOODvertex-1);
-          else
-            qh_fprintf(qh ferr, 7066, "qhull warning: point p%d is a vertex for every facet('QV-%d').\n",
-                -qh GOODvertex - 1, -qh GOODvertex - 1);
-        }
-        facet->good= False;
-      }
-    }
-  }
-  startgood= numgood;
-  if (qh SPLITthresholds) {
-    FORALLfacet_(facetlist) {
-      if (facet->good) {
-        if (!qh_inthresholds(facet->normal, &angle)) {
-          facet->good= False;
-          numgood--;
-          if (angle < bestangle) {
-            bestangle= angle;
-            bestfacet= facet;
-          }
-        }
-      }
-    }
-    if (!numgood && bestfacet) {
-      bestfacet->good= True;
-      numgood++;
-      trace0((qh ferr, 23, "qh_findgood_all: f%d is closest(%2.2g) to thresholds\n",
-           bestfacet->id, bestangle));
-      return;
-    }
-  }
-  qh num_good= numgood;
-  trace0((qh ferr, 24, "qh_findgood_all: %d good facets remain out of %d facets\n",
-        numgood, startgood));
-} /* findgood_all */
-
-/*---------------------------------
-
-  qh_furthestnext()
-    set qh.facet_next to facet with furthest of all furthest points
-    searches all facets on qh.facet_list
-
-  notes:
-    this may help avoid precision problems
-*/
-void qh_furthestnext(void /* qh.facet_list */) {
-  facetT *facet, *bestfacet= NULL;
-  realT dist, bestdist= -REALmax;
-
-  FORALLfacets {
-    if (facet->outsideset) {
-#if qh_COMPUTEfurthest
-      pointT *furthest;
-      furthest= (pointT*)qh_setlast(facet->outsideset);
-      zinc_(Zcomputefurthest);
-      qh_distplane(furthest, facet, &dist);
-#else
-      dist= facet->furthestdist;
-#endif
-      if (dist > bestdist) {
-        bestfacet= facet;
-        bestdist= dist;
-      }
-    }
-  }
-  if (bestfacet) {
-    qh_removefacet(bestfacet);
-    qh_prependfacet(bestfacet, &qh facet_next);
-    trace1((qh ferr, 1029, "qh_furthestnext: made f%d next facet(dist %.2g)\n",
-            bestfacet->id, bestdist));
-  }
-} /* furthestnext */
-
-/*---------------------------------
-
-  qh_furthestout( facet )
-    make furthest outside point the last point of outsideset
-
-  returns:
-    updates facet->outsideset
-    clears facet->notfurthest
-    sets facet->furthestdist
-
-  design:
-    determine best point of outsideset
-    make it the last point of outsideset
-*/
-void qh_furthestout(facetT *facet) {
-  pointT *point, **pointp, *bestpoint= NULL;
-  realT dist, bestdist= -REALmax;
-
-  FOREACHpoint_(facet->outsideset) {
-    qh_distplane(point, facet, &dist);
-    zinc_(Zcomputefurthest);
-    if (dist > bestdist) {
-      bestpoint= point;
-      bestdist= dist;
-    }
-  }
-  if (bestpoint) {
-    qh_setdel(facet->outsideset, point);
-    qh_setappend(&facet->outsideset, point);
-#if !qh_COMPUTEfurthest
-    facet->furthestdist= bestdist;
-#endif
-  }
-  facet->notfurthest= False;
-  trace3((qh ferr, 3017, "qh_furthestout: p%d is furthest outside point of f%d\n",
-          qh_pointid(point), facet->id));
-} /* furthestout */
-
-
-/*---------------------------------
-
-  qh_infiniteloop( facet )
-    report infinite loop error due to facet
-*/
-void qh_infiniteloop(facetT *facet) {
-
-  qh_fprintf(qh ferr, 6149, "qhull internal error (qh_infiniteloop): potential infinite loop detected\n");
-  qh_errexit(qh_ERRqhull, facet, NULL);
-} /* qh_infiniteloop */
-
-/*---------------------------------
-
-  qh_initbuild()
-    initialize hull and outside sets with point array
-    qh.FIRSTpoint/qh.NUMpoints is point array
-    if qh.GOODpoint
-      adds qh.GOODpoint to initial hull
-
-  returns:
-    qh_facetlist with initial hull
-    points partioned into outside sets, coplanar sets, or inside
-    initializes qh.GOODpointp, qh.GOODvertexp,
-
-  design:
-    initialize global variables used during qh_buildhull
-    determine precision constants and points with max/min coordinate values
-      if qh.SCALElast, scale last coordinate(for 'd')
-    build initial simplex
-    partition input points into facets of initial simplex
-    set up lists
-    if qh.ONLYgood
-      check consistency
-      add qh.GOODvertex if defined
-*/
-void qh_initbuild( void) {
-  setT *maxpoints, *vertices;
-  facetT *facet;
-  int i, numpart;
-  realT dist;
-  boolT isoutside;
-
-  qh furthest_id= qh_IDunknown;
-  qh lastreport= 0;
-  qh facet_id= qh vertex_id= qh ridge_id= 0;
-  qh visit_id= qh vertex_visit= 0;
-  qh maxoutdone= False;
-
-  if (qh GOODpoint > 0)
-    qh GOODpointp= qh_point(qh GOODpoint-1);
-  else if (qh GOODpoint < 0)
-    qh GOODpointp= qh_point(-qh GOODpoint-1);
-  if (qh GOODvertex > 0)
-    qh GOODvertexp= qh_point(qh GOODvertex-1);
-  else if (qh GOODvertex < 0)
-    qh GOODvertexp= qh_point(-qh GOODvertex-1);
-  if ((qh GOODpoint
-       && (qh GOODpointp < qh first_point  /* also catches !GOODpointp */
-           || qh GOODpointp > qh_point(qh num_points-1)))
-    || (qh GOODvertex
-        && (qh GOODvertexp < qh first_point  /* also catches !GOODvertexp */
-            || qh GOODvertexp > qh_point(qh num_points-1)))) {
-    qh_fprintf(qh ferr, 6150, "qhull input error: either QGn or QVn point is > p%d\n",
-             qh num_points-1);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  maxpoints= qh_maxmin(qh first_point, qh num_points, qh hull_dim);
-  if (qh SCALElast)
-    qh_scalelast(qh first_point, qh num_points, qh hull_dim,
-               qh MINlastcoord, qh MAXlastcoord, qh MAXwidth);
-  qh_detroundoff();
-  if (qh DELAUNAY && qh upper_threshold[qh hull_dim-1] > REALmax/2
-                  && qh lower_threshold[qh hull_dim-1] < -REALmax/2) {
-    for (i=qh_PRINTEND; i--; ) {
-      if (qh PRINTout[i] == qh_PRINTgeom && qh DROPdim < 0
-          && !qh GOODthreshold && !qh SPLITthresholds)
-        break;  /* in this case, don't set upper_threshold */
-    }
-    if (i < 0) {
-      if (qh UPPERdelaunay) { /* matches qh.upperdelaunay in qh_setfacetplane */
-        qh lower_threshold[qh hull_dim-1]= qh ANGLEround * qh_ZEROdelaunay;
-        qh GOODthreshold= True;
-      }else {
-        qh upper_threshold[qh hull_dim-1]= -qh ANGLEround * qh_ZEROdelaunay;
-        if (!qh GOODthreshold)
-          qh SPLITthresholds= True; /* build upper-convex hull even if Qg */
-          /* qh_initqhull_globals errors if Qg without Pdk/etc. */
-      }
-    }
-  }
-  vertices= qh_initialvertices(qh hull_dim, maxpoints, qh first_point, qh num_points);
-  qh_initialhull(vertices);  /* initial qh facet_list */
-  qh_partitionall(vertices, qh first_point, qh num_points);
-  if (qh PRINToptions1st || qh TRACElevel || qh IStracing) {
-    if (qh TRACElevel || qh IStracing)
-      qh_fprintf(qh ferr, 8103, "\nTrace level %d for %s | %s\n",
-         qh IStracing ? qh IStracing : qh TRACElevel, qh rbox_command, qh qhull_command);
-    qh_fprintf(qh ferr, 8104, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
-  }
-  qh_resetlists(False, qh_RESETvisible /*qh.visible_list newvertex_list newfacet_list */);
-  qh facet_next= qh facet_list;
-  qh_furthestnext(/* qh.facet_list */);
-  if (qh PREmerge) {
-    qh cos_max= qh premerge_cos;
-    qh centrum_radius= qh premerge_centrum;
-  }
-  if (qh ONLYgood) {
-    if (qh GOODvertex > 0 && qh MERGING) {
-      qh_fprintf(qh ferr, 6151, "qhull input error: 'Qg QVn' (only good vertex) does not work with merging.\nUse 'QJ' to joggle the input or 'Q0' to turn off merging.\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    if (!(qh GOODthreshold || qh GOODpoint
-         || (!qh MERGEexact && !qh PREmerge && qh GOODvertexp))) {
-      qh_fprintf(qh ferr, 6152, "qhull input error: 'Qg' (ONLYgood) needs a good threshold('Pd0D0'), a\n\
-good point(QGn or QG-n), or a good vertex with 'QJ' or 'Q0' (QVn).\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    if (qh GOODvertex > 0  && !qh MERGING  /* matches qh_partitionall */
-        && !qh_isvertex(qh GOODvertexp, vertices)) {
-      facet= qh_findbestnew(qh GOODvertexp, qh facet_list,
-                          &dist, !qh_ALL, &isoutside, &numpart);
-      zadd_(Zdistgood, numpart);
-      if (!isoutside) {
-        qh_fprintf(qh ferr, 6153, "qhull input error: point for QV%d is inside initial simplex.  It can not be made a vertex.\n",
-               qh_pointid(qh GOODvertexp));
-        qh_errexit(qh_ERRinput, NULL, NULL);
-      }
-      if (!qh_addpoint(qh GOODvertexp, facet, False)) {
-        qh_settempfree(&vertices);
-        qh_settempfree(&maxpoints);
-        return;
-      }
-    }
-    qh_findgood(qh facet_list, 0);
-  }
-  qh_settempfree(&vertices);
-  qh_settempfree(&maxpoints);
-  trace1((qh ferr, 1030, "qh_initbuild: initial hull created and points partitioned\n"));
-} /* initbuild */
-
-/*---------------------------------
-
-  qh_initialhull( vertices )
-    constructs the initial hull as a DIM3 simplex of vertices
-
-  design:
-    creates a simplex (initializes lists)
-    determines orientation of simplex
-    sets hyperplanes for facets
-    doubles checks orientation (in case of axis-parallel facets with Gaussian elimination)
-    checks for flipped facets and qh.NARROWhull
-    checks the result
-*/
-void qh_initialhull(setT *vertices) {
-  facetT *facet, *firstfacet, *neighbor, **neighborp;
-  realT dist, angle, minangle= REALmax;
-#ifndef qh_NOtrace
-  int k;
-#endif
-
-  qh_createsimplex(vertices);  /* qh.facet_list */
-  qh_resetlists(False, qh_RESETvisible);
-  qh facet_next= qh facet_list;      /* advance facet when processed */
-  qh interior_point= qh_getcenter(vertices);
-  firstfacet= qh facet_list;
-  qh_setfacetplane(firstfacet);
-  zinc_(Znumvisibility); /* needs to be in printsummary */
-  qh_distplane(qh interior_point, firstfacet, &dist);
-  if (dist > 0) {
-    FORALLfacets
-      facet->toporient ^= (unsigned char)True;
-  }
-  FORALLfacets
-    qh_setfacetplane(facet);
-  FORALLfacets {
-    if (!qh_checkflipped(facet, NULL, qh_ALL)) {/* due to axis-parallel facet */
-      trace1((qh ferr, 1031, "qh_initialhull: initial orientation incorrect.  Correct all facets\n"));
-      facet->flipped= False;
-      FORALLfacets {
-        facet->toporient ^= (unsigned char)True;
-        qh_orientoutside(facet);
-      }
-      break;
-    }
-  }
-  FORALLfacets {
-    if (!qh_checkflipped(facet, NULL, !qh_ALL)) {  /* can happen with 'R0.1' */
-      if (qh DELAUNAY && ! qh ATinfinity) {
-        if (qh UPPERdelaunay)
-          qh_fprintf(qh ferr, 6240, "Qhull precision error: Initial simplex is cocircular or cospherical.  Option 'Qs' searches all points.  Can not compute the upper Delaunay triangulation or upper Voronoi diagram of cocircular/cospherical points.\n");
-        else
-          qh_fprintf(qh ferr, 6239, "Qhull precision error: Initial simplex is cocircular or cospherical.  Use option 'Qz' for the Delaunay triangulation or Voronoi diagram of cocircular/cospherical points.  Option 'Qz' adds a point \"at infinity\".    Use option 'Qs' to search all points for the initial simplex.\n");
-        qh_errexit(qh_ERRinput, NULL, NULL);
-      }
-      qh_precision("initial simplex is flat");
-      qh_fprintf(qh ferr, 6154, "Qhull precision error: Initial simplex is flat (facet %d is coplanar with the interior point)\n",
-                 facet->id);
-      qh_errexit(qh_ERRsingular, NULL, NULL);  /* calls qh_printhelp_singular */
-    }
-    FOREACHneighbor_(facet) {
-      angle= qh_getangle(facet->normal, neighbor->normal);
-      minimize_( minangle, angle);
-    }
-  }
-  if (minangle < qh_MAXnarrow && !qh NOnarrow) {
-    realT diff= 1.0 + minangle;
-
-    qh NARROWhull= True;
-    qh_option("_narrow-hull", NULL, &diff);
-    if (minangle < qh_WARNnarrow && !qh RERUN && qh PRINTprecision)
-      qh_printhelp_narrowhull(qh ferr, minangle);
-  }
-  zzval_(Zprocessed)= qh hull_dim+1;
-  qh_checkpolygon(qh facet_list);
-  qh_checkconvex(qh facet_list,   qh_DATAfault);
-#ifndef qh_NOtrace
-  if (qh IStracing >= 1) {
-    qh_fprintf(qh ferr, 8105, "qh_initialhull: simplex constructed, interior point:");
-    for (k=0; k < qh hull_dim; k++)
-      qh_fprintf(qh ferr, 8106, " %6.4g", qh interior_point[k]);
-    qh_fprintf(qh ferr, 8107, "\n");
-  }
-#endif
-} /* initialhull */
-
-/*---------------------------------
-
-  qh_initialvertices( dim, maxpoints, points, numpoints )
-    determines a non-singular set of initial vertices
-    maxpoints may include duplicate points
-
-  returns:
-    temporary set of dim+1 vertices in descending order by vertex id
-    if qh.RANDOMoutside && !qh.ALLpoints
-      picks random points
-    if dim >= qh_INITIALmax,
-      uses min/max x and max points with non-zero determinants
-
-  notes:
-    unless qh.ALLpoints,
-      uses maxpoints as long as determinate is non-zero
-*/
-setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints) {
-  pointT *point, **pointp;
-  setT *vertices, *simplex, *tested;
-  realT randr;
-  int idx, point_i, point_n, k;
-  boolT nearzero= False;
-
-  vertices= qh_settemp(dim + 1);
-  simplex= qh_settemp(dim+1);
-  if (qh ALLpoints)
-    qh_maxsimplex(dim, NULL, points, numpoints, &simplex);
-  else if (qh RANDOMoutside) {
-    while (qh_setsize(simplex) != dim+1) {
-      randr= qh_RANDOMint;
-      randr= randr/(qh_RANDOMmax+1);
-      idx= (int)floor(qh num_points * randr);
-      while (qh_setin(simplex, qh_point(idx))) {
-        idx++; /* in case qh_RANDOMint always returns the same value */
-        idx= idx < qh num_points ? idx : 0;
-      }
-      qh_setappend(&simplex, qh_point(idx));
-    }
-  }else if (qh hull_dim >= qh_INITIALmax) {
-    tested= qh_settemp(dim+1);
-    qh_setappend(&simplex, SETfirst_(maxpoints));   /* max and min X coord */
-    qh_setappend(&simplex, SETsecond_(maxpoints));
-    qh_maxsimplex(fmin_(qh_INITIALsearch, dim), maxpoints, points, numpoints, &simplex);
-    k= qh_setsize(simplex);
-    FOREACHpoint_i_(maxpoints) {
-      if (point_i & 0x1) {     /* first pick up max. coord. points */
-        if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
-          qh_detsimplex(point, simplex, k, &nearzero);
-          if (nearzero)
-            qh_setappend(&tested, point);
-          else {
-            qh_setappend(&simplex, point);
-            if (++k == dim)  /* use search for last point */
-              break;
-          }
-        }
-      }
-    }
-    while (k != dim && (point= (pointT*)qh_setdellast(maxpoints))) {
-      if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
-        qh_detsimplex(point, simplex, k, &nearzero);
-        if (nearzero)
-          qh_setappend(&tested, point);
-        else {
-          qh_setappend(&simplex, point);
-          k++;
-        }
-      }
-    }
-    idx= 0;
-    while (k != dim && (point= qh_point(idx++))) {
-      if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
-        qh_detsimplex(point, simplex, k, &nearzero);
-        if (!nearzero){
-          qh_setappend(&simplex, point);
-          k++;
-        }
-      }
-    }
-    qh_settempfree(&tested);
-    qh_maxsimplex(dim, maxpoints, points, numpoints, &simplex);
-  }else
-    qh_maxsimplex(dim, maxpoints, points, numpoints, &simplex);
-  FOREACHpoint_(simplex)
-    qh_setaddnth(&vertices, 0, qh_newvertex(point)); /* descending order */
-  qh_settempfree(&simplex);
-  return vertices;
-} /* initialvertices */
-
-
-/*---------------------------------
-
-  qh_isvertex( point, vertices )
-    returns vertex if point is in vertex set, else returns NULL
-
-  notes:
-    for qh.GOODvertex
-*/
-vertexT *qh_isvertex(pointT *point, setT *vertices) {
-  vertexT *vertex, **vertexp;
-
-  FOREACHvertex_(vertices) {
-    if (vertex->point == point)
-      return vertex;
-  }
-  return NULL;
-} /* isvertex */
-
-/*---------------------------------
-
-  qh_makenewfacets( point )
-    make new facets from point and qh.visible_list
-
-  returns:
-    qh.newfacet_list= list of new facets with hyperplanes and ->newfacet
-    qh.newvertex_list= list of vertices in new facets with ->newlist set
-
-    if (qh.ONLYgood)
-      newfacets reference horizon facets, but not vice versa
-      ridges reference non-simplicial horizon ridges, but not vice versa
-      does not change existing facets
-    else
-      sets qh.NEWfacets
-      new facets attached to horizon facets and ridges
-      for visible facets,
-        visible->r.replace is corresponding new facet
-
-  see also:
-    qh_makenewplanes() -- make hyperplanes for facets
-    qh_attachnewfacets() -- attachnewfacets if not done here(qh ONLYgood)
-    qh_matchnewfacets() -- match up neighbors
-    qh_updatevertices() -- update vertex neighbors and delvertices
-    qh_deletevisible() -- delete visible facets
-    qh_checkpolygon() --check the result
-    qh_triangulate() -- triangulate a non-simplicial facet
-
-  design:
-    for each visible facet
-      make new facets to its horizon facets
-      update its f.replace
-      clear its neighbor set
-*/
-vertexT *qh_makenewfacets(pointT *point /*visible_list*/) {
-  facetT *visible, *newfacet= NULL, *newfacet2= NULL, *neighbor, **neighborp;
-  vertexT *apex;
-  int numnew=0;
-
-  qh newfacet_list= qh facet_tail;
-  qh newvertex_list= qh vertex_tail;
-  apex= qh_newvertex(point);
-  qh_appendvertex(apex);
-  qh visit_id++;
-  if (!qh ONLYgood)
-    qh NEWfacets= True;
-  FORALLvisible_facets {
-    FOREACHneighbor_(visible)
-      neighbor->seen= False;
-    if (visible->ridges) {
-      visible->visitid= qh visit_id;
-      newfacet2= qh_makenew_nonsimplicial(visible, apex, &numnew);
-    }
-    if (visible->simplicial)
-      newfacet= qh_makenew_simplicial(visible, apex, &numnew);
-    if (!qh ONLYgood) {
-      if (newfacet2)  /* newfacet is null if all ridges defined */
-        newfacet= newfacet2;
-      if (newfacet)
-        visible->f.replace= newfacet;
-      else
-        zinc_(Zinsidevisible);
-      SETfirst_(visible->neighbors)= NULL;
-    }
-  }
-  trace1((qh ferr, 1032, "qh_makenewfacets: created %d new facets from point p%d to horizon\n",
-          numnew, qh_pointid(point)));
-  if (qh IStracing >= 4)
-    qh_printfacetlist(qh newfacet_list, NULL, qh_ALL);
-  return apex;
-} /* makenewfacets */
-
-/*---------------------------------
-
-  qh_matchduplicates( atfacet, atskip, hashsize, hashcount )
-    match duplicate ridges in qh.hash_table for atfacet/atskip
-    duplicates marked with ->dupridge and qh_DUPLICATEridge
-
-  returns:
-    picks match with worst merge (min distance apart)
-    updates hashcount
-
-  see also:
-    qh_matchneighbor
-
-  notes:
-
-  design:
-    compute hash value for atfacet and atskip
-    repeat twice -- once to make best matches, once to match the rest
-      for each possible facet in qh.hash_table
-        if it is a matching facet and pass 2
-          make match
-          unless tricoplanar, mark match for merging (qh_MERGEridge)
-          [e.g., tricoplanar RBOX s 1000 t993602376 | QHULL C-1e-3 d Qbb FA Qt]
-        if it is a matching facet and pass 1
-          test if this is a better match
-      if pass 1,
-        make best match (it will not be merged)
-*/
-#ifndef qh_NOmerge
-void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcount) {
-  boolT same, ismatch;
-  int hash, scan;
-  facetT *facet, *newfacet, *maxmatch= NULL, *maxmatch2= NULL, *nextfacet;
-  int skip, newskip, nextskip= 0, maxskip= 0, maxskip2= 0, makematch;
-  realT maxdist= -REALmax, mindist, dist2, low, high;
-
-  hash= qh_gethash(hashsize, atfacet->vertices, qh hull_dim, 1,
-                     SETelem_(atfacet->vertices, atskip));
-  trace2((qh ferr, 2046, "qh_matchduplicates: find duplicate matches for f%d skip %d hash %d hashcount %d\n",
-          atfacet->id, atskip, hash, *hashcount));
-  for (makematch= 0; makematch < 2; makematch++) {
-    qh visit_id++;
-    for (newfacet= atfacet, newskip= atskip; newfacet; newfacet= nextfacet, newskip= nextskip) {
-      zinc_(Zhashlookup);
-      nextfacet= NULL;
-      newfacet->visitid= qh visit_id;
-      for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT));
-           scan= (++scan >= hashsize ? 0 : scan)) {
-        if (!facet->dupridge || facet->visitid == qh visit_id)
-          continue;
-        zinc_(Zhashtests);
-        if (qh_matchvertices(1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
-          ismatch= (same == (boolT)(newfacet->toporient ^ facet->toporient));
-          if (SETelemt_(facet->neighbors, skip, facetT) != qh_DUPLICATEridge) {
-            if (!makematch) {
-              qh_fprintf(qh ferr, 6155, "qhull internal error (qh_matchduplicates): missing dupridge at f%d skip %d for new f%d skip %d hash %d\n",
-                     facet->id, skip, newfacet->id, newskip, hash);
-              qh_errexit2(qh_ERRqhull, facet, newfacet);
-            }
-          }else if (ismatch && makematch) {
-            if (SETelemt_(newfacet->neighbors, newskip, facetT) == qh_DUPLICATEridge) {
-              SETelem_(facet->neighbors, skip)= newfacet;
-              if (newfacet->tricoplanar)
-                SETelem_(newfacet->neighbors, newskip)= facet;
-              else
-                SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;
-              *hashcount -= 2; /* removed two unmatched facets */
-              trace4((qh ferr, 4059, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d merge\n",
-                    facet->id, skip, newfacet->id, newskip));
-            }
-          }else if (ismatch) {
-            mindist= qh_getdistance(facet, newfacet, &low, &high);
-            dist2= qh_getdistance(newfacet, facet, &low, &high);
-            minimize_(mindist, dist2);
-            if (mindist > maxdist) {
-              maxdist= mindist;
-              maxmatch= facet;
-              maxskip= skip;
-              maxmatch2= newfacet;
-              maxskip2= newskip;
-            }
-            trace3((qh ferr, 3018, "qh_matchduplicates: duplicate f%d skip %d new f%d skip %d at dist %2.2g, max is now f%d f%d\n",
-                    facet->id, skip, newfacet->id, newskip, mindist,
-                    maxmatch->id, maxmatch2->id));
-          }else { /* !ismatch */
-            nextfacet= facet;
-            nextskip= skip;
-          }
-        }
-        if (makematch && !facet
-        && SETelemt_(facet->neighbors, skip, facetT) == qh_DUPLICATEridge) {
-          qh_fprintf(qh ferr, 6156, "qhull internal error (qh_matchduplicates): no MERGEridge match for duplicate f%d skip %d at hash %d\n",
-                     newfacet->id, newskip, hash);
-          qh_errexit(qh_ERRqhull, newfacet, NULL);
-        }
-      }
-    } /* end of for each new facet at hash */
-    if (!makematch) {
-      if (!maxmatch) {
-        qh_fprintf(qh ferr, 6157, "qhull internal error (qh_matchduplicates): no maximum match at duplicate f%d skip %d at hash %d\n",
-                     atfacet->id, atskip, hash);
-        qh_errexit(qh_ERRqhull, atfacet, NULL);
-      }
-      SETelem_(maxmatch->neighbors, maxskip)= maxmatch2; /* maxmatch!=0 by QH6157 */
-      SETelem_(maxmatch2->neighbors, maxskip2)= maxmatch;
-      *hashcount -= 2; /* removed two unmatched facets */
-      zzinc_(Zmultiridge);
-      trace0((qh ferr, 25, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d keep\n",
-              maxmatch->id, maxskip, maxmatch2->id, maxskip2));
-      qh_precision("ridge with multiple neighbors");
-      if (qh IStracing >= 4)
-        qh_errprint("DUPLICATED/MATCH", maxmatch, maxmatch2, NULL, NULL);
-    }
-  }
-} /* matchduplicates */
-
-/*---------------------------------
-
-  qh_nearcoplanar()
-    for all facets, remove near-inside points from facet->coplanarset
-    coplanar points defined by innerplane from qh_outerinner()
-
-  returns:
-    if qh KEEPcoplanar && !qh KEEPinside
-      facet->coplanarset only contains coplanar points
-    if qh.JOGGLEmax
-      drops inner plane by another qh.JOGGLEmax diagonal since a
-        vertex could shift out while a coplanar point shifts in
-
-  notes:
-    used for qh.PREmerge and qh.JOGGLEmax
-    must agree with computation of qh.NEARcoplanar in qh_detroundoff()
-  design:
-    if not keeping coplanar or inside points
-      free all coplanar sets
-    else if not keeping both coplanar and inside points
-      remove !coplanar or !inside points from coplanar sets
-*/
-void qh_nearcoplanar(void /* qh.facet_list */) {
-  facetT *facet;
-  pointT *point, **pointp;
-  int numpart;
-  realT dist, innerplane;
-
-  if (!qh KEEPcoplanar && !qh KEEPinside) {
-    FORALLfacets {
-      if (facet->coplanarset)
-        qh_setfree( &facet->coplanarset);
-    }
-  }else if (!qh KEEPcoplanar || !qh KEEPinside) {
-    qh_outerinner(NULL, NULL, &innerplane);
-    if (qh JOGGLEmax < REALmax/2)
-      innerplane -= qh JOGGLEmax * sqrt((realT)qh hull_dim);
-    numpart= 0;
-    FORALLfacets {
-      if (facet->coplanarset) {
-        FOREACHpoint_(facet->coplanarset) {
-          numpart++;
-          qh_distplane(point, facet, &dist);
-          if (dist < innerplane) {
-            if (!qh KEEPinside)
-              SETref_(point)= NULL;
-          }else if (!qh KEEPcoplanar)
-            SETref_(point)= NULL;
-        }
-        qh_setcompact(facet->coplanarset);
-      }
-    }
-    zzadd_(Zcheckpart, numpart);
-  }
-} /* nearcoplanar */
-
-/*---------------------------------
-
-  qh_nearvertex( facet, point, bestdist )
-    return nearest vertex in facet to point
-
-  returns:
-    vertex and its distance
-
-  notes:
-    if qh.DELAUNAY
-      distance is measured in the input set
-    searches neighboring tricoplanar facets (requires vertexneighbors)
-      Slow implementation.  Recomputes vertex set for each point.
-    The vertex set could be stored in the qh.keepcentrum facet.
-*/
-vertexT *qh_nearvertex(facetT *facet, pointT *point, realT *bestdistp) {
-  realT bestdist= REALmax, dist;
-  vertexT *bestvertex= NULL, *vertex, **vertexp, *apex;
-  coordT *center;
-  facetT *neighbor, **neighborp;
-  setT *vertices;
-  int dim= qh hull_dim;
-
-  if (qh DELAUNAY)
-    dim--;
-  if (facet->tricoplanar) {
-    if (!qh VERTEXneighbors || !facet->center) {
-      qh_fprintf(qh ferr, 6158, "qhull internal error (qh_nearvertex): qh.VERTEXneighbors and facet->center required for tricoplanar facets\n");
-      qh_errexit(qh_ERRqhull, facet, NULL);
-    }
-    vertices= qh_settemp(qh TEMPsize);
-    apex= SETfirstt_(facet->vertices, vertexT);
-    center= facet->center;
-    FOREACHneighbor_(apex) {
-      if (neighbor->center == center) {
-        FOREACHvertex_(neighbor->vertices)
-          qh_setappend(&vertices, vertex);
-      }
-    }
-  }else
-    vertices= facet->vertices;
-  FOREACHvertex_(vertices) {
-    dist= qh_pointdist(vertex->point, point, -dim);
-    if (dist < bestdist) {
-      bestdist= dist;
-      bestvertex= vertex;
-    }
-  }
-  if (facet->tricoplanar)
-    qh_settempfree(&vertices);
-  *bestdistp= sqrt(bestdist);
-  if (!bestvertex) {
-      qh_fprintf(qh ferr, 6261, "qhull internal error (qh_nearvertex): did not find bestvertex for f%d p%d\n", facet->id, qh_pointid(point));
-      qh_errexit(qh_ERRqhull, facet, NULL);
-  }
-  trace3((qh ferr, 3019, "qh_nearvertex: v%d dist %2.2g for f%d p%d\n",
-        bestvertex->id, *bestdistp, facet->id, qh_pointid(point))); /* bestvertex!=0 by QH2161 */
-  return bestvertex;
-} /* nearvertex */
-
-/*---------------------------------
-
-  qh_newhashtable( newsize )
-    returns size of qh.hash_table of at least newsize slots
-
-  notes:
-    assumes qh.hash_table is NULL
-    qh_HASHfactor determines the number of extra slots
-    size is not divisible by 2, 3, or 5
-*/
-int qh_newhashtable(int newsize) {
-  int size;
-
-  size= ((newsize+1)*qh_HASHfactor) | 0x1;  /* odd number */
-  while (True) {
-    if (newsize<0 || size<0) {
-        qh_fprintf(qhmem.ferr, 6236, "qhull error (qh_newhashtable): negative request (%d) or size (%d).  Did int overflow due to high-D?\n", newsize, size); /* WARN64 */
-        qh_errexit(qhmem_ERRmem, NULL, NULL);
-    }
-    if ((size%3) && (size%5))
-      break;
-    size += 2;
-    /* loop terminates because there is an infinite number of primes */
-  }
-  qh hash_table= qh_setnew(size);
-  qh_setzero(qh hash_table, 0, size);
-  return size;
-} /* newhashtable */
-
-/*---------------------------------
-
-  qh_newvertex( point )
-    returns a new vertex for point
-*/
-vertexT *qh_newvertex(pointT *point) {
-  vertexT *vertex;
-
-  zinc_(Ztotvertices);
-  vertex= (vertexT *)qh_memalloc((int)sizeof(vertexT));
-  memset((char *) vertex, (size_t)0, sizeof(vertexT));
-  if (qh vertex_id == UINT_MAX) {
-    qh_memfree(vertex, (int)sizeof(vertexT));
-    qh_fprintf(qh ferr, 6159, "qhull error: more than 2^32 vertices.  vertexT.id field overflows.  Vertices would not be sorted correctly.\n");
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  if (qh vertex_id == qh tracevertex_id)
-    qh tracevertex= vertex;
-  vertex->id= qh vertex_id++;
-  vertex->point= point;
-  trace4((qh ferr, 4060, "qh_newvertex: vertex p%d(v%d) created\n", qh_pointid(vertex->point),
-          vertex->id));
-  return(vertex);
-} /* newvertex */
-
-/*---------------------------------
-
-  qh_nextridge3d( atridge, facet, vertex )
-    return next ridge and vertex for a 3d facet
-    returns NULL on error
-    [for QhullFacet::nextRidge3d] Does not call qh_errexit nor access qh_qh.
-
-  notes:
-    in qh_ORIENTclock order
-    this is a O(n^2) implementation to trace all ridges
-    be sure to stop on any 2nd visit
-    same as QhullRidge::nextRidge3d
-    does not use qh_qh or qh_errexit [QhullFacet.cpp]
-
-  design:
-    for each ridge
-      exit if it is the ridge after atridge
-*/
-ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp) {
-  vertexT *atvertex, *vertex, *othervertex;
-  ridgeT *ridge, **ridgep;
-
-  if ((atridge->top == facet) ^ qh_ORIENTclock)
-    atvertex= SETsecondt_(atridge->vertices, vertexT);
-  else
-    atvertex= SETfirstt_(atridge->vertices, vertexT);
-  FOREACHridge_(facet->ridges) {
-    if (ridge == atridge)
-      continue;
-    if ((ridge->top == facet) ^ qh_ORIENTclock) {
-      othervertex= SETsecondt_(ridge->vertices, vertexT);
-      vertex= SETfirstt_(ridge->vertices, vertexT);
-    }else {
-      vertex= SETsecondt_(ridge->vertices, vertexT);
-      othervertex= SETfirstt_(ridge->vertices, vertexT);
-    }
-    if (vertex == atvertex) {
-      if (vertexp)
-        *vertexp= othervertex;
-      return ridge;
-    }
-  }
-  return NULL;
-} /* nextridge3d */
-#else /* qh_NOmerge */
-void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcount) {
-}
-ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp) {
-
-  return NULL;
-}
-#endif /* qh_NOmerge */
-
-/*---------------------------------
-
-  qh_outcoplanar()
-    move points from all facets' outsidesets to their coplanarsets
-
-  notes:
-    for post-processing under qh.NARROWhull
-
-  design:
-    for each facet
-      for each outside point for facet
-        partition point into coplanar set
-*/
-void qh_outcoplanar(void /* facet_list */) {
-  pointT *point, **pointp;
-  facetT *facet;
-  realT dist;
-
-  trace1((qh ferr, 1033, "qh_outcoplanar: move outsideset to coplanarset for qh NARROWhull\n"));
-  FORALLfacets {
-    FOREACHpoint_(facet->outsideset) {
-      qh num_outside--;
-      if (qh KEEPcoplanar || qh KEEPnearinside) {
-        qh_distplane(point, facet, &dist);
-        zinc_(Zpartition);
-        qh_partitioncoplanar(point, facet, &dist);
-      }
-    }
-    qh_setfree(&facet->outsideset);
-  }
-} /* outcoplanar */
-
-/*---------------------------------
-
-  qh_point( id )
-    return point for a point id, or NULL if unknown
-
-  alternative code:
-    return((pointT *)((unsigned   long)qh.first_point
-           + (unsigned long)((id)*qh.normal_size)));
-*/
-pointT *qh_point(int id) {
-
-  if (id < 0)
-    return NULL;
-  if (id < qh num_points)
-    return qh first_point + id * qh hull_dim;
-  id -= qh num_points;
-  if (id < qh_setsize(qh other_points))
-    return SETelemt_(qh other_points, id, pointT);
-  return NULL;
-} /* point */
-
-/*---------------------------------
-
-  qh_point_add( set, point, elem )
-    stores elem at set[point.id]
-
-  returns:
-    access function for qh_pointfacet and qh_pointvertex
-
-  notes:
-    checks point.id
-*/
-void qh_point_add(setT *set, pointT *point, void *elem) {
-  int id, size;
-
-  SETreturnsize_(set, size);
-  if ((id= qh_pointid(point)) < 0)
-    qh_fprintf(qh ferr, 7067, "qhull internal warning (point_add): unknown point %p id %d\n",
-      point, id);
-  else if (id >= size) {
-    qh_fprintf(qh ferr, 6160, "qhull internal errror(point_add): point p%d is out of bounds(%d)\n",
-             id, size);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }else
-    SETelem_(set, id)= elem;
-} /* point_add */
-
-
-/*---------------------------------
-
-  qh_pointfacet()
-    return temporary set of facet for each point
-    the set is indexed by point id
-
-  notes:
-    vertices assigned to one of the facets
-    coplanarset assigned to the facet
-    outside set assigned to the facet
-    NULL if no facet for point (inside)
-      includes qh.GOODpointp
-
-  access:
-    FOREACHfacet_i_(facets) { ... }
-    SETelem_(facets, i)
-
-  design:
-    for each facet
-      add each vertex
-      add each coplanar point
-      add each outside point
-*/
-setT *qh_pointfacet(void /*qh.facet_list*/) {
-  int numpoints= qh num_points + qh_setsize(qh other_points);
-  setT *facets;
-  facetT *facet;
-  vertexT *vertex, **vertexp;
-  pointT *point, **pointp;
-
-  facets= qh_settemp(numpoints);
-  qh_setzero(facets, 0, numpoints);
-  qh vertex_visit++;
-  FORALLfacets {
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->visitid != qh vertex_visit) {
-        vertex->visitid= qh vertex_visit;
-        qh_point_add(facets, vertex->point, facet);
-      }
-    }
-    FOREACHpoint_(facet->coplanarset)
-      qh_point_add(facets, point, facet);
-    FOREACHpoint_(facet->outsideset)
-      qh_point_add(facets, point, facet);
-  }
-  return facets;
-} /* pointfacet */
-
-/*---------------------------------
-
-  qh_pointvertex(  )
-    return temporary set of vertices indexed by point id
-    entry is NULL if no vertex for a point
-      this will include qh.GOODpointp
-
-  access:
-    FOREACHvertex_i_(vertices) { ... }
-    SETelem_(vertices, i)
-*/
-setT *qh_pointvertex(void /*qh.facet_list*/) {
-  int numpoints= qh num_points + qh_setsize(qh other_points);
-  setT *vertices;
-  vertexT *vertex;
-
-  vertices= qh_settemp(numpoints);
-  qh_setzero(vertices, 0, numpoints);
-  FORALLvertices
-    qh_point_add(vertices, vertex->point, vertex);
-  return vertices;
-} /* pointvertex */
-
-
-/*---------------------------------
-
-  qh_prependfacet( facet, facetlist )
-    prepend facet to the start of a facetlist
-
-  returns:
-    increments qh.numfacets
-    updates facetlist, qh.facet_list, facet_next
-
-  notes:
-    be careful of prepending since it can lose a pointer.
-      e.g., can lose _next by deleting and then prepending before _next
-*/
-void qh_prependfacet(facetT *facet, facetT **facetlist) {
-  facetT *prevfacet, *list;
-
-
-  trace4((qh ferr, 4061, "qh_prependfacet: prepend f%d before f%d\n",
-          facet->id, getid_(*facetlist)));
-  if (!*facetlist)
-    (*facetlist)= qh facet_tail;
-  list= *facetlist;
-  prevfacet= list->previous;
-  facet->previous= prevfacet;
-  if (prevfacet)
-    prevfacet->next= facet;
-  list->previous= facet;
-  facet->next= *facetlist;
-  if (qh facet_list == list)  /* this may change *facetlist */
-    qh facet_list= facet;
-  if (qh facet_next == list)
-    qh facet_next= facet;
-  *facetlist= facet;
-  qh num_facets++;
-} /* prependfacet */
-
-
-/*---------------------------------
-
-  qh_printhashtable( fp )
-    print hash table to fp
-
-  notes:
-    not in I/O to avoid bringing io.c in
-
-  design:
-    for each hash entry
-      if defined
-        if unmatched or will merge (NULL, qh_MERGEridge, qh_DUPLICATEridge)
-          print entry and neighbors
-*/
-void qh_printhashtable(FILE *fp) {
-  facetT *facet, *neighbor;
-  int id, facet_i, facet_n, neighbor_i= 0, neighbor_n= 0;
-  vertexT *vertex, **vertexp;
-
-  FOREACHfacet_i_(qh hash_table) {
-    if (facet) {
-      FOREACHneighbor_i_(facet) {
-        if (!neighbor || neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge)
-          break;
-      }
-      if (neighbor_i == neighbor_n)
-        continue;
-      qh_fprintf(fp, 9283, "hash %d f%d ", facet_i, facet->id);
-      FOREACHvertex_(facet->vertices)
-        qh_fprintf(fp, 9284, "v%d ", vertex->id);
-      qh_fprintf(fp, 9285, "\n neighbors:");
-      FOREACHneighbor_i_(facet) {
-        if (neighbor == qh_MERGEridge)
-          id= -3;
-        else if (neighbor == qh_DUPLICATEridge)
-          id= -2;
-        else
-          id= getid_(neighbor);
-        qh_fprintf(fp, 9286, " %d", id);
-      }
-      qh_fprintf(fp, 9287, "\n");
-    }
-  }
-} /* printhashtable */
-
-
-/*---------------------------------
-
-  qh_printlists( fp )
-    print out facet and vertex list for debugging (without 'f/v' tags)
-*/
-void qh_printlists(void) {
-  facetT *facet;
-  vertexT *vertex;
-  int count= 0;
-
-  qh_fprintf(qh ferr, 8108, "qh_printlists: facets:");
-  FORALLfacets {
-    if (++count % 100 == 0)
-      qh_fprintf(qh ferr, 8109, "\n     ");
-    qh_fprintf(qh ferr, 8110, " %d", facet->id);
-  }
-  qh_fprintf(qh ferr, 8111, "\n  new facets %d visible facets %d next facet for qh_addpoint %d\n  vertices(new %d):",
-     getid_(qh newfacet_list), getid_(qh visible_list), getid_(qh facet_next),
-     getid_(qh newvertex_list));
-  count = 0;
-  FORALLvertices {
-    if (++count % 100 == 0)
-      qh_fprintf(qh ferr, 8112, "\n     ");
-    qh_fprintf(qh ferr, 8113, " %d", vertex->id);
-  }
-  qh_fprintf(qh ferr, 8114, "\n");
-} /* printlists */
-
-/*---------------------------------
-
-  qh_resetlists( stats, qh_RESETvisible )
-    reset newvertex_list, newfacet_list, visible_list
-    if stats,
-      maintains statistics
-
-  returns:
-    visible_list is empty if qh_deletevisible was called
-*/
-void qh_resetlists(boolT stats, boolT resetVisible /*qh.newvertex_list newfacet_list visible_list*/) {
-  vertexT *vertex;
-  facetT *newfacet, *visible;
-  int totnew=0, totver=0;
-
-  if (stats) {
-    FORALLvertex_(qh newvertex_list)
-      totver++;
-    FORALLnew_facets
-      totnew++;
-    zadd_(Zvisvertextot, totver);
-    zmax_(Zvisvertexmax, totver);
-    zadd_(Znewfacettot, totnew);
-    zmax_(Znewfacetmax, totnew);
-  }
-  FORALLvertex_(qh newvertex_list)
-    vertex->newlist= False;
-  qh newvertex_list= NULL;
-  FORALLnew_facets
-    newfacet->newfacet= False;
-  qh newfacet_list= NULL;
-  if (resetVisible) {
-    FORALLvisible_facets {
-      visible->f.replace= NULL;
-      visible->visible= False;
-    }
-    qh num_visible= 0;
-  }
-  qh visible_list= NULL; /* may still have visible facets via qh_triangulate */
-  qh NEWfacets= False;
-} /* resetlists */
-
-/*---------------------------------
-
-  qh_setvoronoi_all()
-    compute Voronoi centers for all facets
-    includes upperDelaunay facets if qh.UPPERdelaunay ('Qu')
-
-  returns:
-    facet->center is the Voronoi center
-
-  notes:
-    this is unused/untested code
-      please email bradb@shore.net if this works ok for you
-
-  use:
-    FORALLvertices {...} to locate the vertex for a point.
-    FOREACHneighbor_(vertex) {...} to visit the Voronoi centers for a Voronoi cell.
-*/
-void qh_setvoronoi_all(void) {
-  facetT *facet;
-
-  qh_clearcenters(qh_ASvoronoi);
-  qh_vertexneighbors();
-
-  FORALLfacets {
-    if (!facet->normal || !facet->upperdelaunay || qh UPPERdelaunay) {
-      if (!facet->center)
-        facet->center= qh_facetcenter(facet->vertices);
-    }
-  }
-} /* setvoronoi_all */
-
-#ifndef qh_NOmerge
-
-/*---------------------------------
-
-  qh_triangulate()
-    triangulate non-simplicial facets on qh.facet_list,
-    if qh VORONOI, sets Voronoi centers of non-simplicial facets
-    nop if hasTriangulation
-
-  returns:
-    all facets simplicial
-    each tricoplanar facet has ->f.triowner == owner of ->center,normal,etc.
-
-  notes:
-    call after qh_check_output since may switch to Voronoi centers
-    Output may overwrite ->f.triowner with ->f.area
-*/
-void qh_triangulate(void /*qh.facet_list*/) {
-  facetT *facet, *nextfacet, *owner;
-  int onlygood= qh ONLYgood;
-  facetT *neighbor, *visible= NULL, *facet1, *facet2, *new_facet_list= NULL;
-  facetT *orig_neighbor= NULL, *otherfacet;
-  vertexT *new_vertex_list= NULL;
-  mergeT *merge;
-  mergeType mergetype;
-  int neighbor_i, neighbor_n;
-
-  if (qh hasTriangulation)
-      return;
-  trace1((qh ferr, 1034, "qh_triangulate: triangulate non-simplicial facets\n"));
-  if (qh hull_dim == 2)
-    return;
-  if (qh VORONOI) {  /* otherwise lose Voronoi centers [could rebuild vertex set from tricoplanar] */
-    qh_clearcenters(qh_ASvoronoi);
-    qh_vertexneighbors();
-  }
-  qh ONLYgood= False; /* for makenew_nonsimplicial */
-  qh visit_id++;
-  qh NEWfacets= True;
-  qh degen_mergeset= qh_settemp(qh TEMPsize);
-  qh newvertex_list= qh vertex_tail;
-  for (facet= qh facet_list; facet && facet->next; facet= nextfacet) { /* non-simplicial facets moved to end */
-    nextfacet= facet->next;
-    if (facet->visible || facet->simplicial)
-      continue;
-    /* triangulate all non-simplicial facets, otherwise merging does not work, e.g., RBOX c P-0.1 P+0.1 P+0.1 D3 | QHULL d Qt Tv */
-    if (!new_facet_list)
-      new_facet_list= facet;  /* will be moved to end */
-    qh_triangulate_facet(facet, &new_vertex_list);
-  }
-  trace2((qh ferr, 2047, "qh_triangulate: delete null facets from f%d -- apex same as second vertex\n", getid_(new_facet_list)));
-  for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* null facets moved to end */
-    nextfacet= facet->next;
-    if (facet->visible)
-      continue;
-    if (facet->ridges) {
-      if (qh_setsize(facet->ridges) > 0) {
-        qh_fprintf(qh ferr, 6161, "qhull error (qh_triangulate): ridges still defined for f%d\n", facet->id);
-        qh_errexit(qh_ERRqhull, facet, NULL);
-      }
-      qh_setfree(&facet->ridges);
-    }
-    if (SETfirst_(facet->vertices) == SETsecond_(facet->vertices)) {
-      zinc_(Ztrinull);
-      qh_triangulate_null(facet);
-    }
-  }
-  trace2((qh ferr, 2048, "qh_triangulate: delete %d or more mirror facets -- same vertices and neighbors\n", qh_setsize(qh degen_mergeset)));
-  qh visible_list= qh facet_tail;
-  while ((merge= (mergeT*)qh_setdellast(qh degen_mergeset))) {
-    facet1= merge->facet1;
-    facet2= merge->facet2;
-    mergetype= merge->type;
-    qh_memfree(merge, (int)sizeof(mergeT));
-    if (mergetype == MRGmirror) {
-      zinc_(Ztrimirror);
-      qh_triangulate_mirror(facet1, facet2);
-    }
-  }
-  qh_settempfree(&qh degen_mergeset);
-  trace2((qh ferr, 2049, "qh_triangulate: update neighbor lists for vertices from v%d\n", getid_(new_vertex_list)));
-  qh newvertex_list= new_vertex_list;  /* all vertices of new facets */
-  qh visible_list= NULL;
-  qh_updatevertices(/*qh.newvertex_list, empty newfacet_list and visible_list*/);
-  qh_resetlists(False, !qh_RESETvisible /*qh.newvertex_list, empty newfacet_list and visible_list*/);
-
-  trace2((qh ferr, 2050, "qh_triangulate: identify degenerate tricoplanar facets from f%d\n", getid_(new_facet_list)));
-  trace2((qh ferr, 2051, "qh_triangulate: and replace facet->f.triowner with tricoplanar facets that own center, normal, etc.\n"));
-  FORALLfacet_(new_facet_list) {
-    if (facet->tricoplanar && !facet->visible) {
-      FOREACHneighbor_i_(facet) {
-        if (neighbor_i == 0) {  /* first iteration */
-          if (neighbor->tricoplanar)
-            orig_neighbor= neighbor->f.triowner;
-          else
-            orig_neighbor= neighbor;
-        }else {
-          if (neighbor->tricoplanar)
-            otherfacet= neighbor->f.triowner;
-          else
-            otherfacet= neighbor;
-          if (orig_neighbor == otherfacet) {
-            zinc_(Ztridegen);
-            facet->degenerate= True;
-            break;
-          }
-        }
-      }
-    }
-  }
-
-  trace2((qh ferr, 2052, "qh_triangulate: delete visible facets -- non-simplicial, null, and mirrored facets\n"));
-  owner= NULL;
-  visible= NULL;
-  for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* may delete facet */
-    nextfacet= facet->next;
-    if (facet->visible) {
-      if (facet->tricoplanar) { /* a null or mirrored facet */
-        qh_delfacet(facet);
-        qh num_visible--;
-      }else {  /* a non-simplicial facet followed by its tricoplanars */
-        if (visible && !owner) {
-          /*  RBOX 200 s D5 t1001471447 | QHULL Qt C-0.01 Qx Qc Tv Qt -- f4483 had 6 vertices/neighbors and 8 ridges */
-          trace2((qh ferr, 2053, "qh_triangulate: all tricoplanar facets degenerate for non-simplicial facet f%d\n",
-                       visible->id));
-          qh_delfacet(visible);
-          qh num_visible--;
-        }
-        visible= facet;
-        owner= NULL;
-      }
-    }else if (facet->tricoplanar) {
-      if (facet->f.triowner != visible || visible==NULL) {
-        qh_fprintf(qh ferr, 6162, "qhull error (qh_triangulate): tricoplanar facet f%d not owned by its visible, non-simplicial facet f%d\n", facet->id, getid_(visible));
-        qh_errexit2(qh_ERRqhull, facet, visible);
-      }
-      if (owner)
-        facet->f.triowner= owner;
-      else if (!facet->degenerate) {
-        owner= facet;
-        nextfacet= visible->next; /* rescan tricoplanar facets with owner, visible!=0 by QH6162 */
-        facet->keepcentrum= True;  /* one facet owns ->normal, etc. */
-        facet->coplanarset= visible->coplanarset;
-        facet->outsideset= visible->outsideset;
-        visible->coplanarset= NULL;
-        visible->outsideset= NULL;
-        if (!qh TRInormals) { /* center and normal copied to tricoplanar facets */
-          visible->center= NULL;
-          visible->normal= NULL;
-        }
-        qh_delfacet(visible);
-        qh num_visible--;
-      }
-    }
-  }
-  if (visible && !owner) {
-    trace2((qh ferr, 2054, "qh_triangulate: all tricoplanar facets degenerate for last non-simplicial facet f%d\n",
-                 visible->id));
-    qh_delfacet(visible);
-    qh num_visible--;
-  }
-  qh NEWfacets= False;
-  qh ONLYgood= onlygood; /* restore value */
-  if (qh CHECKfrequently)
-    qh_checkpolygon(qh facet_list);
-  qh hasTriangulation= True;
-} /* triangulate */
-
-
-/*---------------------------------
-
-  qh_triangulate_facet(qh, facetA, &firstVertex )
-    triangulate a non-simplicial facet
-      if qh.CENTERtype=qh_ASvoronoi, sets its Voronoi center
-  returns:
-    qh.newfacet_list == simplicial facets
-      facet->tricoplanar set and ->keepcentrum false
-      facet->degenerate set if duplicated apex
-      facet->f.trivisible set to facetA
-      facet->center copied from facetA (created if qh_ASvoronoi)
-        qh_eachvoronoi, qh_detvridge, qh_detvridge3 assume centers copied
-      facet->normal,offset,maxoutside copied from facetA
-
-  notes:
-      only called by qh_triangulate
-      qh_makenew_nonsimplicial uses neighbor->seen for the same
-      if qh.TRInormals, newfacet->normal will need qh_free
-        if qh.TRInormals and qh_AScentrum, newfacet->center will need qh_free
-        keepcentrum is also set on Zwidefacet in qh_mergefacet
-        freed by qh_clearcenters
-
-  see also:
-      qh_addpoint() -- add a point
-      qh_makenewfacets() -- construct a cone of facets for a new vertex
-
-  design:
-      if qh_ASvoronoi,
-         compute Voronoi center (facet->center)
-      select first vertex (highest ID to preserve ID ordering of ->vertices)
-      triangulate from vertex to ridges
-      copy facet->center, normal, offset
-      update vertex neighbors
-*/
-void qh_triangulate_facet(facetT *facetA, vertexT **first_vertex) {
-  facetT *newfacet;
-  facetT *neighbor, **neighborp;
-  vertexT *apex;
-  int numnew=0;
-
-  trace3((qh ferr, 3020, "qh_triangulate_facet: triangulate facet f%d\n", facetA->id));
-
-  if (qh IStracing >= 4)
-    qh_printfacet(qh ferr, facetA);
-  FOREACHneighbor_(facetA) {
-    neighbor->seen= False;
-    neighbor->coplanar= False;
-  }
-  if (qh CENTERtype == qh_ASvoronoi && !facetA->center  /* matches upperdelaunay in qh_setfacetplane() */
-        && fabs_(facetA->normal[qh hull_dim -1]) >= qh ANGLEround * qh_ZEROdelaunay) {
-    facetA->center= qh_facetcenter(facetA->vertices);
-  }
-  qh_willdelete(facetA, NULL);
-  qh newfacet_list= qh facet_tail;
-  facetA->visitid= qh visit_id;
-  apex= SETfirstt_(facetA->vertices, vertexT);
-  qh_makenew_nonsimplicial(facetA, apex, &numnew);
-  SETfirst_(facetA->neighbors)= NULL;
-  FORALLnew_facets {
-    newfacet->tricoplanar= True;
-    newfacet->f.trivisible= facetA;
-    newfacet->degenerate= False;
-    newfacet->upperdelaunay= facetA->upperdelaunay;
-    newfacet->good= facetA->good;
-    if (qh TRInormals) { /* 'Q11' triangulate duplicates ->normal and ->center */
-      newfacet->keepcentrum= True;
-      if(facetA->normal){
-        newfacet->normal= qh_memalloc(qh normal_size);
-        memcpy((char *)newfacet->normal, facetA->normal, qh normal_size);
-      }
-      if (qh CENTERtype == qh_AScentrum)
-        newfacet->center= qh_getcentrum(newfacet);
-      else if (qh CENTERtype == qh_ASvoronoi && facetA->center){
-        newfacet->center= qh_memalloc(qh center_size);
-        memcpy((char *)newfacet->center, facetA->center, qh center_size);
-      }
-    }else {
-      newfacet->keepcentrum= False;
-      /* one facet will have keepcentrum=True at end of qh_triangulate */
-      newfacet->normal= facetA->normal;
-      newfacet->center= facetA->center;
-    }
-    newfacet->offset= facetA->offset;
-#if qh_MAXoutside
-    newfacet->maxoutside= facetA->maxoutside;
-#endif
-  }
-  qh_matchnewfacets(/*qh.newfacet_list*/);
-  zinc_(Ztricoplanar);
-  zadd_(Ztricoplanartot, numnew);
-  zmax_(Ztricoplanarmax, numnew);
-  qh visible_list= NULL;
-  if (!(*first_vertex))
-    (*first_vertex)= qh newvertex_list;
-  qh newvertex_list= NULL;
-  qh_updatevertices(/*qh.newfacet_list, qh.empty visible_list and qh.newvertex_list*/);
-  qh_resetlists(False, !qh_RESETvisible /*qh.newfacet_list, qh.empty visible_list and qh.newvertex_list*/);
-} /* triangulate_facet */
-
-/*---------------------------------
-
-  qh_triangulate_link(oldfacetA, facetA, oldfacetB, facetB)
-    relink facetA to facetB via oldfacets
-  returns:
-    adds mirror facets to qh degen_mergeset (4-d and up only)
-  design:
-    if they are already neighbors, the opposing neighbors become MRGmirror facets
-*/
-void qh_triangulate_link(facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB) {
-  int errmirror= False;
-
-  trace3((qh ferr, 3021, "qh_triangulate_link: relink old facets f%d and f%d between neighbors f%d and f%d\n",
-         oldfacetA->id, oldfacetB->id, facetA->id, facetB->id));
-  if (qh_setin(facetA->neighbors, facetB)) {
-    if (!qh_setin(facetB->neighbors, facetA))
-      errmirror= True;
-    else
-      qh_appendmergeset(facetA, facetB, MRGmirror, NULL);
-  }else if (qh_setin(facetB->neighbors, facetA))
-    errmirror= True;
-  if (errmirror) {
-    qh_fprintf(qh ferr, 6163, "qhull error (qh_triangulate_link): mirror facets f%d and f%d do not match for old facets f%d and f%d\n",
-       facetA->id, facetB->id, oldfacetA->id, oldfacetB->id);
-    qh_errexit2(qh_ERRqhull, facetA, facetB);
-  }
-  qh_setreplace(facetB->neighbors, oldfacetB, facetA);
-  qh_setreplace(facetA->neighbors, oldfacetA, facetB);
-} /* triangulate_link */
-
-/*---------------------------------
-
-  qh_triangulate_mirror(facetA, facetB)
-    delete mirrored facets from qh_triangulate_null() and qh_triangulate_mirror
-      a mirrored facet shares the same vertices of a logical ridge
-  design:
-    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
-    if they are already neighbors, the opposing neighbors become MRGmirror facets
-*/
-void qh_triangulate_mirror(facetT *facetA, facetT *facetB) {
-  facetT *neighbor, *neighborB;
-  int neighbor_i, neighbor_n;
-
-  trace3((qh ferr, 3022, "qh_triangulate_mirror: delete mirrored facets f%d and f%d\n",
-         facetA->id, facetB->id));
-  FOREACHneighbor_i_(facetA) {
-    neighborB= SETelemt_(facetB->neighbors, neighbor_i, facetT);
-    if (neighbor == neighborB)
-      continue; /* occurs twice */
-    qh_triangulate_link(facetA, neighbor, facetB, neighborB);
-  }
-  qh_willdelete(facetA, NULL);
-  qh_willdelete(facetB, NULL);
-} /* triangulate_mirror */
-
-/*---------------------------------
-
-  qh_triangulate_null(facetA)
-    remove null facetA from qh_triangulate_facet()
-      a null facet has vertex #1 (apex) == vertex #2
-  returns:
-    adds facetA to ->visible for deletion after qh_updatevertices
-    qh degen_mergeset contains mirror facets (4-d and up only)
-  design:
-    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
-    if they are already neighbors, the opposing neighbors become MRGmirror facets
-*/
-void qh_triangulate_null(facetT *facetA) {
-  facetT *neighbor, *otherfacet;
-
-  trace3((qh ferr, 3023, "qh_triangulate_null: delete null facet f%d\n", facetA->id));
-  neighbor= SETfirstt_(facetA->neighbors, facetT);
-  otherfacet= SETsecondt_(facetA->neighbors, facetT);
-  qh_triangulate_link(facetA, neighbor, facetA, otherfacet);
-  qh_willdelete(facetA, NULL);
-} /* triangulate_null */
-
-#else /* qh_NOmerge */
-void qh_triangulate(void) {
-}
-#endif /* qh_NOmerge */
-
-   /*---------------------------------
-
-  qh_vertexintersect( vertexsetA, vertexsetB )
-    intersects two vertex sets (inverse id ordered)
-    vertexsetA is a temporary set at the top of qhmem.tempstack
-
-  returns:
-    replaces vertexsetA with the intersection
-
-  notes:
-    could overwrite vertexsetA if currently too slow
-*/
-void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB) {
-  setT *intersection;
-
-  intersection= qh_vertexintersect_new(*vertexsetA, vertexsetB);
-  qh_settempfree(vertexsetA);
-  *vertexsetA= intersection;
-  qh_settemppush(intersection);
-} /* vertexintersect */
-
-/*---------------------------------
-
-  qh_vertexintersect_new(  )
-    intersects two vertex sets (inverse id ordered)
-
-  returns:
-    a new set
-*/
-setT *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB) {
-  setT *intersection= qh_setnew(qh hull_dim - 1);
-  vertexT **vertexA= SETaddr_(vertexsetA, vertexT);
-  vertexT **vertexB= SETaddr_(vertexsetB, vertexT);
-
-  while (*vertexA && *vertexB) {
-    if (*vertexA  == *vertexB) {
-      qh_setappend(&intersection, *vertexA);
-      vertexA++; vertexB++;
-    }else {
-      if ((*vertexA)->id > (*vertexB)->id)
-        vertexA++;
-      else
-        vertexB++;
-    }
-  }
-  return intersection;
-} /* vertexintersect_new */
-
-/*---------------------------------
-
-  qh_vertexneighbors()
-    for each vertex in qh.facet_list,
-      determine its neighboring facets
-
-  returns:
-    sets qh.VERTEXneighbors
-      nop if qh.VERTEXneighbors already set
-      qh_addpoint() will maintain them
-
-  notes:
-    assumes all vertex->neighbors are NULL
-
-  design:
-    for each facet
-      for each vertex
-        append facet to vertex->neighbors
-*/
-void qh_vertexneighbors(void /*qh.facet_list*/) {
-  facetT *facet;
-  vertexT *vertex, **vertexp;
-
-  if (qh VERTEXneighbors)
-    return;
-  trace1((qh ferr, 1035, "qh_vertexneighbors: determing neighboring facets for each vertex\n"));
-  qh vertex_visit++;
-  FORALLfacets {
-    if (facet->visible)
-      continue;
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->visitid != qh vertex_visit) {
-        vertex->visitid= qh vertex_visit;
-        vertex->neighbors= qh_setnew(qh hull_dim);
-      }
-      qh_setappend(&vertex->neighbors, facet);
-    }
-  }
-  qh VERTEXneighbors= True;
-} /* vertexneighbors */
-
-/*---------------------------------
-
-  qh_vertexsubset( vertexsetA, vertexsetB )
-    returns True if vertexsetA is a subset of vertexsetB
-    assumes vertexsets are sorted
-
-  note:
-    empty set is a subset of any other set
-*/
-boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB) {
-  vertexT **vertexA= (vertexT **) SETaddr_(vertexsetA, vertexT);
-  vertexT **vertexB= (vertexT **) SETaddr_(vertexsetB, vertexT);
-
-  while (True) {
-    if (!*vertexA)
-      return True;
-    if (!*vertexB)
-      return False;
-    if ((*vertexA)->id > (*vertexB)->id)
-      return False;
-    if (*vertexA  == *vertexB)
-      vertexA++;
-    vertexB++;
-  }
-  return False; /* avoid warnings */
-} /* vertexsubset */
diff --git a/extern/libqhull/qhull_a.h b/extern/libqhull/qhull_a.h
deleted file mode 100644
index 729b7232768b..000000000000
--- a/extern/libqhull/qhull_a.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
  ---------------------------------
-
-   qhull_a.h
-   all header files for compiling qhull with non-reentrant code
-   included before C++ headers for user_r.h:QHULL_CRTDBG
-
-   see qh-qhull.htm
-
-   see libqhull.h for user-level definitions
-
-   see user.h for user-definable constants
-
-   defines internal functions for libqhull.c global.c
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/qhull_a.h#4 $$Change: 2064 $
-   $DateTime: 2016/01/18 12:36:08 $$Author: bbarber $
-
-   Notes:  grep for ((" and (" to catch fprintf("lkasdjf");
-           full parens around (x?y:z)
-           use '#include "libqhull/qhull_a.h"' to avoid name clashes
-*/
-
-#ifndef qhDEFqhulla
-#define qhDEFqhulla 1
-
-#include "libqhull.h"  /* Includes user_r.h and data types */
-
-#include "stat.h"
-#include "random.h"
-#include "mem.h"
-#include "qset.h"
-#include "geom.h"
-#include "merge.h"
-#include "poly.h"
-#include "io.h"
-
-#include 
-#include 
-#include 
-#include     /* some compilers will not need float.h */
-#include 
-#include 
-#include 
-#include 
-#include 
-/*** uncomment here and qset.c
-     if string.h does not define memcpy()
-#include 
-*/
-
-#if qh_CLOCKtype == 2  /* defined in user.h from libqhull.h */
-#include 
-#include 
-#include 
-#endif
-
-#ifdef _MSC_VER  /* Microsoft Visual C++ -- warning level 4 */
-#pragma warning( disable : 4100)  /* unreferenced formal parameter */
-#pragma warning( disable : 4127)  /* conditional expression is constant */
-#pragma warning( disable : 4706)  /* assignment within conditional function */
-#pragma warning( disable : 4996)  /* function was declared deprecated(strcpy, localtime, etc.) */
-#endif
-
-/* ======= -macros- =========== */
-
-/*----------------------------------
-
-  traceN((qh ferr, 0Nnnn, "format\n", vars));
-    calls qh_fprintf if qh.IStracing >= N
-
-    Add debugging traps to the end of qh_fprintf
-
-  notes:
-    removing tracing reduces code size but doesn't change execution speed
-*/
-#ifndef qh_NOtrace
-#define trace0(args) {if (qh IStracing) qh_fprintf args;}
-#define trace1(args) {if (qh IStracing >= 1) qh_fprintf args;}
-#define trace2(args) {if (qh IStracing >= 2) qh_fprintf args;}
-#define trace3(args) {if (qh IStracing >= 3) qh_fprintf args;}
-#define trace4(args) {if (qh IStracing >= 4) qh_fprintf args;}
-#define trace5(args) {if (qh IStracing >= 5) qh_fprintf args;}
-#else /* qh_NOtrace */
-#define trace0(args) {}
-#define trace1(args) {}
-#define trace2(args) {}
-#define trace3(args) {}
-#define trace4(args) {}
-#define trace5(args) {}
-#endif /* qh_NOtrace */
-
-/*----------------------------------
-
-  Define an unused variable to avoid compiler warnings
-
-  Derived from Qt's corelib/global/qglobal.h
-
-*/
-
-#if defined(__cplusplus) && defined(__INTEL_COMPILER) && !defined(QHULL_OS_WIN)
-template 
-inline void qhullUnused(T &x) { (void)x; }
-#  define QHULL_UNUSED(x) qhullUnused(x);
-#else
-#  define QHULL_UNUSED(x) (void)x;
-#endif
-
-/***** -libqhull.c prototypes (alphabetical after qhull) ********************/
-
-void    qh_qhull(void);
-boolT   qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist);
-void    qh_buildhull(void);
-void    qh_buildtracing(pointT *furthest, facetT *facet);
-void    qh_build_withrestart(void);
-void    qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet);
-void    qh_findhorizon(pointT *point, facetT *facet, int *goodvisible,int *goodhorizon);
-pointT *qh_nextfurthest(facetT **visible);
-void    qh_partitionall(setT *vertices, pointT *points,int npoints);
-void    qh_partitioncoplanar(pointT *point, facetT *facet, realT *dist);
-void    qh_partitionpoint(pointT *point, facetT *facet);
-void    qh_partitionvisible(boolT allpoints, int *numpoints);
-void    qh_precision(const char *reason);
-void    qh_printsummary(FILE *fp);
-
-/***** -global.c internal prototypes (alphabetical) ***********************/
-
-void    qh_appendprint(qh_PRINT format);
-void    qh_freebuild(boolT allmem);
-void    qh_freebuffers(void);
-void    qh_initbuffers(coordT *points, int numpoints, int dim, boolT ismalloc);
-
-/***** -stat.c internal prototypes (alphabetical) ***********************/
-
-void    qh_allstatA(void);
-void    qh_allstatB(void);
-void    qh_allstatC(void);
-void    qh_allstatD(void);
-void    qh_allstatE(void);
-void    qh_allstatE2(void);
-void    qh_allstatF(void);
-void    qh_allstatG(void);
-void    qh_allstatH(void);
-void    qh_freebuffers(void);
-void    qh_initbuffers(coordT *points, int numpoints, int dim, boolT ismalloc);
-
-#endif /* qhDEFqhulla */
diff --git a/extern/libqhull/qset.c b/extern/libqhull/qset.c
deleted file mode 100644
index a969252a7590..000000000000
--- a/extern/libqhull/qset.c
+++ /dev/null
@@ -1,1340 +0,0 @@
-/*
  ---------------------------------
-
-   qset.c
-   implements set manipulations needed for quickhull
-
-   see qh-set.htm and qset.h
-
-   Be careful of strict aliasing (two pointers of different types
-   that reference the same location).  The last slot of a set is
-   either the actual size of the set plus 1, or the NULL terminator
-   of the set (i.e., setelemT).
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/qset.c#3 $$Change: 2062 $
-   $DateTime: 2016/01/17 13:13:18 $$Author: bbarber $
-*/
-
-#include "user.h" /* for QHULL_CRTDBG */
-#include "qset.h"
-#include "mem.h"
-#include 
-#include 
-/*** uncomment here and qhull_a.h
-     if string.h does not define memcpy()
-#include 
-*/
-
-#ifndef qhDEFlibqhull
-typedef struct ridgeT ridgeT;
-typedef struct facetT facetT;
-void    qh_errexit(int exitcode, facetT *, ridgeT *);
-void    qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... );
-#  ifdef _MSC_VER  /* Microsoft Visual C++ -- warning level 4 */
-#  pragma warning( disable : 4127)  /* conditional expression is constant */
-#  pragma warning( disable : 4706)  /* assignment within conditional function */
-#  endif
-#endif
-
-/*=============== internal macros ===========================*/
-
-/*============ functions in alphabetical order ===================*/
-
-/*----------------------------------
-
-  qh_setaddnth( setp, nth, newelem)
-    adds newelem as n'th element of sorted or unsorted *setp
-
-  notes:
-    *setp and newelem must be defined
-    *setp may be a temp set
-    nth=0 is first element
-    errors if nth is out of bounds
-
-  design:
-    expand *setp if empty or full
-    move tail of *setp up one
-    insert newelem
-*/
-void qh_setaddnth(setT **setp, int nth, void *newelem) {
-  int oldsize, i;
-  setelemT *sizep;          /* avoid strict aliasing */
-  setelemT *oldp, *newp;
-
-  if (!*setp || (sizep= SETsizeaddr_(*setp))->i==0) {
-    qh_setlarger(setp);
-    sizep= SETsizeaddr_(*setp);
-  }
-  oldsize= sizep->i - 1;
-  if (nth < 0 || nth > oldsize) {
-    qh_fprintf(qhmem.ferr, 6171, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
-    qh_setprint(qhmem.ferr, "", *setp);
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-  sizep->i++;
-  oldp= (setelemT *)SETelemaddr_(*setp, oldsize, void);   /* NULL */
-  newp= oldp+1;
-  for (i=oldsize-nth+1; i--; )  /* move at least NULL  */
-    (newp--)->p= (oldp--)->p;       /* may overwrite *sizep */
-  newp->p= newelem;
-} /* setaddnth */
-
-
-/*----------------------------------
-
-  setaddsorted( setp, newelem )
-    adds an newelem into sorted *setp
-
-  notes:
-    *setp and newelem must be defined
-    *setp may be a temp set
-    nop if newelem already in set
-
-  design:
-    find newelem's position in *setp
-    insert newelem
-*/
-void qh_setaddsorted(setT **setp, void *newelem) {
-  int newindex=0;
-  void *elem, **elemp;
-
-  FOREACHelem_(*setp) {          /* could use binary search instead */
-    if (elem < newelem)
-      newindex++;
-    else if (elem == newelem)
-      return;
-    else
-      break;
-  }
-  qh_setaddnth(setp, newindex, newelem);
-} /* setaddsorted */
-
-
-/*---------------------------------
-
-  qh_setappend( setp, newelem)
-    append newelem to *setp
-
-  notes:
-    *setp may be a temp set
-    *setp and newelem may be NULL
-
-  design:
-    expand *setp if empty or full
-    append newelem to *setp
-
-*/
-void qh_setappend(setT **setp, void *newelem) {
-  setelemT *sizep;  /* Avoid strict aliasing.  Writing to *endp may overwrite *sizep */
-  setelemT *endp;
-  int count;
-
-  if (!newelem)
-    return;
-  if (!*setp || (sizep= SETsizeaddr_(*setp))->i==0) {
-    qh_setlarger(setp);
-    sizep= SETsizeaddr_(*setp);
-  }
-  count= (sizep->i)++ - 1;
-  endp= (setelemT *)SETelemaddr_(*setp, count, void);
-  (endp++)->p= newelem;
-  endp->p= NULL;
-} /* setappend */
-
-/*---------------------------------
-
-  qh_setappend_set( setp, setA)
-    appends setA to *setp
-
-  notes:
-    *setp can not be a temp set
-    *setp and setA may be NULL
-
-  design:
-    setup for copy
-    expand *setp if it is too small
-    append all elements of setA to *setp
-*/
-void qh_setappend_set(setT **setp, setT *setA) {
-  int sizeA, size;
-  setT *oldset;
-  setelemT *sizep;
-
-  if (!setA)
-    return;
-  SETreturnsize_(setA, sizeA);
-  if (!*setp)
-    *setp= qh_setnew(sizeA);
-  sizep= SETsizeaddr_(*setp);
-  if (!(size= sizep->i))
-    size= (*setp)->maxsize;
-  else
-    size--;
-  if (size + sizeA > (*setp)->maxsize) {
-    oldset= *setp;
-    *setp= qh_setcopy(oldset, sizeA);
-    qh_setfree(&oldset);
-    sizep= SETsizeaddr_(*setp);
-  }
-  if (sizeA > 0) {
-    sizep->i= size+sizeA+1;   /* memcpy may overwrite */
-    memcpy((char *)&((*setp)->e[size].p), (char *)&(setA->e[0].p), (size_t)(sizeA+1) * SETelemsize);
-  }
-} /* setappend_set */
-
-
-/*---------------------------------
-
-  qh_setappend2ndlast( setp, newelem )
-    makes newelem the next to the last element in *setp
-
-  notes:
-    *setp must have at least one element
-    newelem must be defined
-    *setp may be a temp set
-
-  design:
-    expand *setp if empty or full
-    move last element of *setp up one
-    insert newelem
-*/
-void qh_setappend2ndlast(setT **setp, void *newelem) {
-    setelemT *sizep;  /* Avoid strict aliasing.  Writing to *endp may overwrite *sizep */
-    setelemT *endp, *lastp;
-    int count;
-
-    if (!*setp || (sizep= SETsizeaddr_(*setp))->i==0) {
-        qh_setlarger(setp);
-        sizep= SETsizeaddr_(*setp);
-    }
-    count= (sizep->i)++ - 1;
-    endp= (setelemT *)SETelemaddr_(*setp, count, void); /* NULL */
-    lastp= endp-1;
-    *(endp++)= *lastp;
-    endp->p= NULL;    /* may overwrite *sizep */
-    lastp->p= newelem;
-} /* setappend2ndlast */
-
-/*---------------------------------
-
-  qh_setcheck( set, typename, id )
-    check set for validity
-    report errors with typename and id
-
-  design:
-    checks that maxsize, actual size, and NULL terminator agree
-*/
-void qh_setcheck(setT *set, const char *tname, unsigned id) {
-  int maxsize, size;
-  int waserr= 0;
-
-  if (!set)
-    return;
-  SETreturnsize_(set, size);
-  maxsize= set->maxsize;
-  if (size > maxsize || !maxsize) {
-    qh_fprintf(qhmem.ferr, 6172, "qhull internal error (qh_setcheck): actual size %d of %s%d is greater than max size %d\n",
-             size, tname, id, maxsize);
-    waserr= 1;
-  }else if (set->e[size].p) {
-    qh_fprintf(qhmem.ferr, 6173, "qhull internal error (qh_setcheck): %s%d(size %d max %d) is not null terminated.\n",
-             tname, id, size-1, maxsize);
-    waserr= 1;
-  }
-  if (waserr) {
-    qh_setprint(qhmem.ferr, "ERRONEOUS", set);
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-} /* setcheck */
-
-
-/*---------------------------------
-
-  qh_setcompact( set )
-    remove internal NULLs from an unsorted set
-
-  returns:
-    updated set
-
-  notes:
-    set may be NULL
-    it would be faster to swap tail of set into holes, like qh_setdel
-
-  design:
-    setup pointers into set
-    skip NULLs while copying elements to start of set
-    update the actual size
-*/
-void qh_setcompact(setT *set) {
-  int size;
-  void **destp, **elemp, **endp, **firstp;
-
-  if (!set)
-    return;
-  SETreturnsize_(set, size);
-  destp= elemp= firstp= SETaddr_(set, void);
-  endp= destp + size;
-  while (1) {
-    if (!(*destp++ = *elemp++)) {
-      destp--;
-      if (elemp > endp)
-        break;
-    }
-  }
-  qh_settruncate(set, (int)(destp-firstp));   /* WARN64 */
-} /* setcompact */
-
-
-/*---------------------------------
-
-  qh_setcopy( set, extra )
-    make a copy of a sorted or unsorted set with extra slots
-
-  returns:
-    new set
-
-  design:
-    create a newset with extra slots
-    copy the elements to the newset
-
-*/
-setT *qh_setcopy(setT *set, int extra) {
-  setT *newset;
-  int size;
-
-  if (extra < 0)
-    extra= 0;
-  SETreturnsize_(set, size);
-  newset= qh_setnew(size+extra);
-  SETsizeaddr_(newset)->i= size+1;    /* memcpy may overwrite */
-  memcpy((char *)&(newset->e[0].p), (char *)&(set->e[0].p), (size_t)(size+1) * SETelemsize);
-  return(newset);
-} /* setcopy */
-
-
-/*---------------------------------
-
-  qh_setdel( set, oldelem )
-    delete oldelem from an unsorted set
-
-  returns:
-    returns oldelem if found
-    returns NULL otherwise
-
-  notes:
-    set may be NULL
-    oldelem must not be NULL;
-    only deletes one copy of oldelem in set
-
-  design:
-    locate oldelem
-    update actual size if it was full
-    move the last element to the oldelem's location
-*/
-void *qh_setdel(setT *set, void *oldelem) {
-  setelemT *sizep;
-  setelemT *elemp;
-  setelemT *lastp;
-
-  if (!set)
-    return NULL;
-  elemp= (setelemT *)SETaddr_(set, void);
-  while (elemp->p != oldelem && elemp->p)
-    elemp++;
-  if (elemp->p) {
-    sizep= SETsizeaddr_(set);
-    if (!(sizep->i)--)         /*  if was a full set */
-      sizep->i= set->maxsize;  /*     *sizep= (maxsize-1)+ 1 */
-    lastp= (setelemT *)SETelemaddr_(set, sizep->i-1, void);
-    elemp->p= lastp->p;      /* may overwrite itself */
-    lastp->p= NULL;
-    return oldelem;
-  }
-  return NULL;
-} /* setdel */
-
-
-/*---------------------------------
-
-  qh_setdellast( set)
-    return last element of set or NULL
-
-  notes:
-    deletes element from set
-    set may be NULL
-
-  design:
-    return NULL if empty
-    if full set
-      delete last element and set actual size
-    else
-      delete last element and update actual size
-*/
-void *qh_setdellast(setT *set) {
-  int setsize;  /* actually, actual_size + 1 */
-  int maxsize;
-  setelemT *sizep;
-  void *returnvalue;
-
-  if (!set || !(set->e[0].p))
-    return NULL;
-  sizep= SETsizeaddr_(set);
-  if ((setsize= sizep->i)) {
-    returnvalue= set->e[setsize - 2].p;
-    set->e[setsize - 2].p= NULL;
-    sizep->i--;
-  }else {
-    maxsize= set->maxsize;
-    returnvalue= set->e[maxsize - 1].p;
-    set->e[maxsize - 1].p= NULL;
-    sizep->i= maxsize;
-  }
-  return returnvalue;
-} /* setdellast */
-
-
-/*---------------------------------
-
-  qh_setdelnth( set, nth )
-    deletes nth element from unsorted set
-    0 is first element
-
-  returns:
-    returns the element (needs type conversion)
-
-  notes:
-    errors if nth invalid
-
-  design:
-    setup points and check nth
-    delete nth element and overwrite with last element
-*/
-void *qh_setdelnth(setT *set, int nth) {
-  void *elem;
-  setelemT *sizep;
-  setelemT *elemp, *lastp;
-
-  sizep= SETsizeaddr_(set);
-  if ((sizep->i--)==0)         /*  if was a full set */
-      sizep->i= set->maxsize;  /*     *sizep= (maxsize-1)+ 1 */
-  if (nth < 0 || nth >= sizep->i) {
-    qh_fprintf(qhmem.ferr, 6174, "qhull internal error (qh_setdelnth): nth %d is out-of-bounds for set:\n", nth);
-    qh_setprint(qhmem.ferr, "", set);
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-  elemp= (setelemT *)SETelemaddr_(set, nth, void); /* nth valid by QH6174 */
-  lastp= (setelemT *)SETelemaddr_(set, sizep->i-1, void);
-  elem= elemp->p;
-  elemp->p= lastp->p;      /* may overwrite itself */
-  lastp->p= NULL;
-  return elem;
-} /* setdelnth */
-
-/*---------------------------------
-
-  qh_setdelnthsorted( set, nth )
-    deletes nth element from sorted set
-
-  returns:
-    returns the element (use type conversion)
-
-  notes:
-    errors if nth invalid
-
-  see also:
-    setnew_delnthsorted
-
-  design:
-    setup points and check nth
-    copy remaining elements down one
-    update actual size
-*/
-void *qh_setdelnthsorted(setT *set, int nth) {
-  void *elem;
-  setelemT *sizep;
-  setelemT *newp, *oldp;
-
-  sizep= SETsizeaddr_(set);
-  if (nth < 0 || (sizep->i && nth >= sizep->i-1) || nth >= set->maxsize) {
-    qh_fprintf(qhmem.ferr, 6175, "qhull internal error (qh_setdelnthsorted): nth %d is out-of-bounds for set:\n", nth);
-    qh_setprint(qhmem.ferr, "", set);
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-  newp= (setelemT *)SETelemaddr_(set, nth, void);
-  elem= newp->p;
-  oldp= newp+1;
-  while (((newp++)->p= (oldp++)->p))
-    ; /* copy remaining elements and NULL */
-  if ((sizep->i--)==0)         /*  if was a full set */
-    sizep->i= set->maxsize;  /*     *sizep= (max size-1)+ 1 */
-  return elem;
-} /* setdelnthsorted */
-
-
-/*---------------------------------
-
-  qh_setdelsorted( set, oldelem )
-    deletes oldelem from sorted set
-
-  returns:
-    returns oldelem if it was deleted
-
-  notes:
-    set may be NULL
-
-  design:
-    locate oldelem in set
-    copy remaining elements down one
-    update actual size
-*/
-void *qh_setdelsorted(setT *set, void *oldelem) {
-  setelemT *sizep;
-  setelemT *newp, *oldp;
-
-  if (!set)
-    return NULL;
-  newp= (setelemT *)SETaddr_(set, void);
-  while(newp->p != oldelem && newp->p)
-    newp++;
-  if (newp->p) {
-    oldp= newp+1;
-    while (((newp++)->p= (oldp++)->p))
-      ; /* copy remaining elements */
-    sizep= SETsizeaddr_(set);
-    if ((sizep->i--)==0)    /*  if was a full set */
-      sizep->i= set->maxsize;  /*     *sizep= (max size-1)+ 1 */
-    return oldelem;
-  }
-  return NULL;
-} /* setdelsorted */
-
-
-/*---------------------------------
-
-  qh_setduplicate( set, elemsize )
-    duplicate a set of elemsize elements
-
-  notes:
-    use setcopy if retaining old elements
-
-  design:
-    create a new set
-    for each elem of the old set
-      create a newelem
-      append newelem to newset
-*/
-setT *qh_setduplicate(setT *set, int elemsize) {
-  void          *elem, **elemp, *newElem;
-  setT          *newSet;
-  int           size;
-
-  if (!(size= qh_setsize(set)))
-    return NULL;
-  newSet= qh_setnew(size);
-  FOREACHelem_(set) {
-    newElem= qh_memalloc(elemsize);
-    memcpy(newElem, elem, (size_t)elemsize);
-    qh_setappend(&newSet, newElem);
-  }
-  return newSet;
-} /* setduplicate */
-
-
-/*---------------------------------
-
-  qh_setendpointer( set )
-    Returns pointer to NULL terminator of a set's elements
-    set can not be NULL
-
-*/
-void **qh_setendpointer(setT *set) {
-
-  setelemT *sizep= SETsizeaddr_(set);
-  int n= sizep->i;
-  return (n ? &set->e[n-1].p : &sizep->p);
-} /* qh_setendpointer */
-
-/*---------------------------------
-
-  qh_setequal( setA, setB )
-    returns 1 if two sorted sets are equal, otherwise returns 0
-
-  notes:
-    either set may be NULL
-
-  design:
-    check size of each set
-    setup pointers
-    compare elements of each set
-*/
-int qh_setequal(setT *setA, setT *setB) {
-  void **elemAp, **elemBp;
-  int sizeA= 0, sizeB= 0;
-
-  if (setA) {
-    SETreturnsize_(setA, sizeA);
-  }
-  if (setB) {
-    SETreturnsize_(setB, sizeB);
-  }
-  if (sizeA != sizeB)
-    return 0;
-  if (!sizeA)
-    return 1;
-  elemAp= SETaddr_(setA, void);
-  elemBp= SETaddr_(setB, void);
-  if (!memcmp((char *)elemAp, (char *)elemBp, sizeA*SETelemsize))
-    return 1;
-  return 0;
-} /* setequal */
-
-
-/*---------------------------------
-
-  qh_setequal_except( setA, skipelemA, setB, skipelemB )
-    returns 1 if sorted setA and setB are equal except for skipelemA & B
-
-  returns:
-    false if either skipelemA or skipelemB are missing
-
-  notes:
-    neither set may be NULL
-
-    if skipelemB is NULL,
-      can skip any one element of setB
-
-  design:
-    setup pointers
-    search for skipelemA, skipelemB, and mismatches
-    check results
-*/
-int qh_setequal_except(setT *setA, void *skipelemA, setT *setB, void *skipelemB) {
-  void **elemA, **elemB;
-  int skip=0;
-
-  elemA= SETaddr_(setA, void);
-  elemB= SETaddr_(setB, void);
-  while (1) {
-    if (*elemA == skipelemA) {
-      skip++;
-      elemA++;
-    }
-    if (skipelemB) {
-      if (*elemB == skipelemB) {
-        skip++;
-        elemB++;
-      }
-    }else if (*elemA != *elemB) {
-      skip++;
-      if (!(skipelemB= *elemB++))
-        return 0;
-    }
-    if (!*elemA)
-      break;
-    if (*elemA++ != *elemB++)
-      return 0;
-  }
-  if (skip != 2 || *elemB)
-    return 0;
-  return 1;
-} /* setequal_except */
-
-
-/*---------------------------------
-
-  qh_setequal_skip( setA, skipA, setB, skipB )
-    returns 1 if sorted setA and setB are equal except for elements skipA & B
-
-  returns:
-    false if different size
-
-  notes:
-    neither set may be NULL
-
-  design:
-    setup pointers
-    search for mismatches while skipping skipA and skipB
-*/
-int qh_setequal_skip(setT *setA, int skipA, setT *setB, int skipB) {
-  void **elemA, **elemB, **skipAp, **skipBp;
-
-  elemA= SETaddr_(setA, void);
-  elemB= SETaddr_(setB, void);
-  skipAp= SETelemaddr_(setA, skipA, void);
-  skipBp= SETelemaddr_(setB, skipB, void);
-  while (1) {
-    if (elemA == skipAp)
-      elemA++;
-    if (elemB == skipBp)
-      elemB++;
-    if (!*elemA)
-      break;
-    if (*elemA++ != *elemB++)
-      return 0;
-  }
-  if (*elemB)
-    return 0;
-  return 1;
-} /* setequal_skip */
-
-
-/*---------------------------------
-
-  qh_setfree( setp )
-    frees the space occupied by a sorted or unsorted set
-
-  returns:
-    sets setp to NULL
-
-  notes:
-    set may be NULL
-
-  design:
-    free array
-    free set
-*/
-void qh_setfree(setT **setp) {
-  int size;
-  void **freelistp;  /* used if !qh_NOmem by qh_memfree_() */
-
-  if (*setp) {
-    size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize;
-    if (size <= qhmem.LASTsize) {
-      qh_memfree_(*setp, size, freelistp);
-    }else
-      qh_memfree(*setp, size);
-    *setp= NULL;
-  }
-} /* setfree */
-
-
-/*---------------------------------
-
-  qh_setfree2( setp, elemsize )
-    frees the space occupied by a set and its elements
-
-  notes:
-    set may be NULL
-
-  design:
-    free each element
-    free set
-*/
-void qh_setfree2(setT **setp, int elemsize) {
-  void          *elem, **elemp;
-
-  FOREACHelem_(*setp)
-    qh_memfree(elem, elemsize);
-  qh_setfree(setp);
-} /* setfree2 */
-
-
-
-/*---------------------------------
-
-  qh_setfreelong( setp )
-    frees a set only if it's in long memory
-
-  returns:
-    sets setp to NULL if it is freed
-
-  notes:
-    set may be NULL
-
-  design:
-    if set is large
-      free it
-*/
-void qh_setfreelong(setT **setp) {
-  int size;
-
-  if (*setp) {
-    size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize;
-    if (size > qhmem.LASTsize) {
-      qh_memfree(*setp, size);
-      *setp= NULL;
-    }
-  }
-} /* setfreelong */
-
-
-/*---------------------------------
-
-  qh_setin( set, setelem )
-    returns 1 if setelem is in a set, 0 otherwise
-
-  notes:
-    set may be NULL or unsorted
-
-  design:
-    scans set for setelem
-*/
-int qh_setin(setT *set, void *setelem) {
-  void *elem, **elemp;
-
-  FOREACHelem_(set) {
-    if (elem == setelem)
-      return 1;
-  }
-  return 0;
-} /* setin */
-
-
-/*---------------------------------
-
-  qh_setindex( set, atelem )
-    returns the index of atelem in set.
-    returns -1, if not in set or maxsize wrong
-
-  notes:
-    set may be NULL and may contain nulls.
-    NOerrors returned (qh_pointid, QhullPoint::id)
-
-  design:
-    checks maxsize
-    scans set for atelem
-*/
-int qh_setindex(setT *set, void *atelem) {
-  void **elem;
-  int size, i;
-
-  if (!set)
-    return -1;
-  SETreturnsize_(set, size);
-  if (size > set->maxsize)
-    return -1;
-  elem= SETaddr_(set, void);
-  for (i=0; i < size; i++) {
-    if (*elem++ == atelem)
-      return i;
-  }
-  return -1;
-} /* setindex */
-
-
-/*---------------------------------
-
-  qh_setlarger( oldsetp )
-    returns a larger set that contains all elements of *oldsetp
-
-  notes:
-    the set is at least twice as large
-    if temp set, updates qhmem.tempstack
-
-  design:
-    creates a new set
-    copies the old set to the new set
-    updates pointers in tempstack
-    deletes the old set
-*/
-void qh_setlarger(setT **oldsetp) {
-  int size= 1;
-  setT *newset, *set, **setp, *oldset;
-  setelemT *sizep;
-  setelemT *newp, *oldp;
-
-  if (*oldsetp) {
-    oldset= *oldsetp;
-    SETreturnsize_(oldset, size);
-    qhmem.cntlarger++;
-    qhmem.totlarger += size+1;
-    newset= qh_setnew(2 * size);
-    oldp= (setelemT *)SETaddr_(oldset, void);
-    newp= (setelemT *)SETaddr_(newset, void);
-    memcpy((char *)newp, (char *)oldp, (size_t)(size+1) * SETelemsize);
-    sizep= SETsizeaddr_(newset);
-    sizep->i= size+1;
-    FOREACHset_((setT *)qhmem.tempstack) {
-      if (set == oldset)
-        *(setp-1)= newset;
-    }
-    qh_setfree(oldsetp);
-  }else
-    newset= qh_setnew(3);
-  *oldsetp= newset;
-} /* setlarger */
-
-
-/*---------------------------------
-
-  qh_setlast( set )
-    return last element of set or NULL (use type conversion)
-
-  notes:
-    set may be NULL
-
-  design:
-    return last element
-*/
-void *qh_setlast(setT *set) {
-  int size;
-
-  if (set) {
-    size= SETsizeaddr_(set)->i;
-    if (!size)
-      return SETelem_(set, set->maxsize - 1);
-    else if (size > 1)
-      return SETelem_(set, size - 2);
-  }
-  return NULL;
-} /* setlast */
-
-
-/*---------------------------------
-
-  qh_setnew( setsize )
-    creates and allocates space for a set
-
-  notes:
-    setsize means the number of elements (!including the NULL terminator)
-    use qh_settemp/qh_setfreetemp if set is temporary
-
-  design:
-    allocate memory for set
-    roundup memory if small set
-    initialize as empty set
-*/
-setT *qh_setnew(int setsize) {
-  setT *set;
-  int sizereceived; /* used if !qh_NOmem */
-  int size;
-  void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */
-
-  if (!setsize)
-    setsize++;
-  size= sizeof(setT) + setsize * SETelemsize;
-  if (size>0 && size <= qhmem.LASTsize) {
-    qh_memalloc_(size, freelistp, set, setT);
-#ifndef qh_NOmem
-    sizereceived= qhmem.sizetable[ qhmem.indextable[size]];
-    if (sizereceived > size)
-      setsize += (sizereceived - size)/SETelemsize;
-#endif
-  }else
-    set= (setT*)qh_memalloc(size);
-  set->maxsize= setsize;
-  set->e[setsize].i= 1;
-  set->e[0].p= NULL;
-  return(set);
-} /* setnew */
-
-
-/*---------------------------------
-
-  qh_setnew_delnthsorted( set, size, nth, prepend )
-    creates a sorted set not containing nth element
-    if prepend, the first prepend elements are undefined
-
-  notes:
-    set must be defined
-    checks nth
-    see also: setdelnthsorted
-
-  design:
-    create new set
-    setup pointers and allocate room for prepend'ed entries
-    append head of old set to new set
-    append tail of old set to new set
-*/
-setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend) {
-  setT *newset;
-  void **oldp, **newp;
-  int tailsize= size - nth -1, newsize;
-
-  if (tailsize < 0) {
-    qh_fprintf(qhmem.ferr, 6176, "qhull internal error (qh_setnew_delnthsorted): nth %d is out-of-bounds for set:\n", nth);
-    qh_setprint(qhmem.ferr, "", set);
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-  newsize= size-1 + prepend;
-  newset= qh_setnew(newsize);
-  newset->e[newset->maxsize].i= newsize+1;  /* may be overwritten */
-  oldp= SETaddr_(set, void);
-  newp= SETaddr_(newset, void) + prepend;
-  switch (nth) {
-  case 0:
-    break;
-  case 1:
-    *(newp++)= *oldp++;
-    break;
-  case 2:
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    break;
-  case 3:
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    break;
-  case 4:
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    break;
-  default:
-    memcpy((char *)newp, (char *)oldp, (size_t)nth * SETelemsize);
-    newp += nth;
-    oldp += nth;
-    break;
-  }
-  oldp++;
-  switch (tailsize) {
-  case 0:
-    break;
-  case 1:
-    *(newp++)= *oldp++;
-    break;
-  case 2:
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    break;
-  case 3:
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    break;
-  case 4:
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    break;
-  default:
-    memcpy((char *)newp, (char *)oldp, (size_t)tailsize * SETelemsize);
-    newp += tailsize;
-  }
-  *newp= NULL;
-  return(newset);
-} /* setnew_delnthsorted */
-
-
-/*---------------------------------
-
-  qh_setprint( fp, string, set )
-    print set elements to fp with identifying string
-
-  notes:
-    never errors
-*/
-void qh_setprint(FILE *fp, const char* string, setT *set) {
-  int size, k;
-
-  if (!set)
-    qh_fprintf(fp, 9346, "%s set is null\n", string);
-  else {
-    SETreturnsize_(set, size);
-    qh_fprintf(fp, 9347, "%s set=%p maxsize=%d size=%d elems=",
-             string, set, set->maxsize, size);
-    if (size > set->maxsize)
-      size= set->maxsize+1;
-    for (k=0; k < size; k++)
-      qh_fprintf(fp, 9348, " %p", set->e[k].p);
-    qh_fprintf(fp, 9349, "\n");
-  }
-} /* setprint */
-
-/*---------------------------------
-
-  qh_setreplace( set, oldelem, newelem )
-    replaces oldelem in set with newelem
-
-  notes:
-    errors if oldelem not in the set
-    newelem may be NULL, but it turns the set into an indexed set (no FOREACH)
-
-  design:
-    find oldelem
-    replace with newelem
-*/
-void qh_setreplace(setT *set, void *oldelem, void *newelem) {
-  void **elemp;
-
-  elemp= SETaddr_(set, void);
-  while (*elemp != oldelem && *elemp)
-    elemp++;
-  if (*elemp)
-    *elemp= newelem;
-  else {
-    qh_fprintf(qhmem.ferr, 6177, "qhull internal error (qh_setreplace): elem %p not found in set\n",
-       oldelem);
-    qh_setprint(qhmem.ferr, "", set);
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-} /* setreplace */
-
-
-/*---------------------------------
-
-  qh_setsize( set )
-    returns the size of a set
-
-  notes:
-    errors if set's maxsize is incorrect
-    same as SETreturnsize_(set)
-    same code for qh_setsize [qset.c] and QhullSetBase::count
-
-  design:
-    determine actual size of set from maxsize
-*/
-int qh_setsize(setT *set) {
-  int size;
-  setelemT *sizep;
-
-  if (!set)
-    return(0);
-  sizep= SETsizeaddr_(set);
-  if ((size= sizep->i)) {
-    size--;
-    if (size > set->maxsize) {
-      qh_fprintf(qhmem.ferr, 6178, "qhull internal error (qh_setsize): current set size %d is greater than maximum size %d\n",
-               size, set->maxsize);
-      qh_setprint(qhmem.ferr, "set: ", set);
-      qh_errexit(qhmem_ERRqhull, NULL, NULL);
-    }
-  }else
-    size= set->maxsize;
-  return size;
-} /* setsize */
-
-/*---------------------------------
-
-  qh_settemp( setsize )
-    return a stacked, temporary set of upto setsize elements
-
-  notes:
-    use settempfree or settempfree_all to release from qhmem.tempstack
-    see also qh_setnew
-
-  design:
-    allocate set
-    append to qhmem.tempstack
-
-*/
-setT *qh_settemp(int setsize) {
-  setT *newset;
-
-  newset= qh_setnew(setsize);
-  qh_setappend(&qhmem.tempstack, newset);
-  if (qhmem.IStracing >= 5)
-    qh_fprintf(qhmem.ferr, 8123, "qh_settemp: temp set %p of %d elements, depth %d\n",
-       newset, newset->maxsize, qh_setsize(qhmem.tempstack));
-  return newset;
-} /* settemp */
-
-/*---------------------------------
-
-  qh_settempfree( set )
-    free temporary set at top of qhmem.tempstack
-
-  notes:
-    nop if set is NULL
-    errors if set not from previous   qh_settemp
-
-  to locate errors:
-    use 'T2' to find source and then find mis-matching qh_settemp
-
-  design:
-    check top of qhmem.tempstack
-    free it
-*/
-void qh_settempfree(setT **set) {
-  setT *stackedset;
-
-  if (!*set)
-    return;
-  stackedset= qh_settemppop();
-  if (stackedset != *set) {
-    qh_settemppush(stackedset);
-    qh_fprintf(qhmem.ferr, 6179, "qhull internal error (qh_settempfree): set %p(size %d) was not last temporary allocated(depth %d, set %p, size %d)\n",
-             *set, qh_setsize(*set), qh_setsize(qhmem.tempstack)+1,
-             stackedset, qh_setsize(stackedset));
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-  qh_setfree(set);
-} /* settempfree */
-
-/*---------------------------------
-
-  qh_settempfree_all(  )
-    free all temporary sets in qhmem.tempstack
-
-  design:
-    for each set in tempstack
-      free set
-    free qhmem.tempstack
-*/
-void qh_settempfree_all(void) {
-  setT *set, **setp;
-
-  FOREACHset_(qhmem.tempstack)
-    qh_setfree(&set);
-  qh_setfree(&qhmem.tempstack);
-} /* settempfree_all */
-
-/*---------------------------------
-
-  qh_settemppop(  )
-    pop and return temporary set from qhmem.tempstack
-
-  notes:
-    the returned set is permanent
-
-  design:
-    pop and check top of qhmem.tempstack
-*/
-setT *qh_settemppop(void) {
-  setT *stackedset;
-
-  stackedset= (setT*)qh_setdellast(qhmem.tempstack);
-  if (!stackedset) {
-    qh_fprintf(qhmem.ferr, 6180, "qhull internal error (qh_settemppop): pop from empty temporary stack\n");
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-  if (qhmem.IStracing >= 5)
-    qh_fprintf(qhmem.ferr, 8124, "qh_settemppop: depth %d temp set %p of %d elements\n",
-       qh_setsize(qhmem.tempstack)+1, stackedset, qh_setsize(stackedset));
-  return stackedset;
-} /* settemppop */
-
-/*---------------------------------
-
-  qh_settemppush( set )
-    push temporary set unto qhmem.tempstack (makes it temporary)
-
-  notes:
-    duplicates settemp() for tracing
-
-  design:
-    append set to tempstack
-*/
-void qh_settemppush(setT *set) {
-  if (!set) {
-    qh_fprintf(qhmem.ferr, 6267, "qhull error (qh_settemppush): can not push a NULL temp\n");
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-  qh_setappend(&qhmem.tempstack, set);
-  if (qhmem.IStracing >= 5)
-    qh_fprintf(qhmem.ferr, 8125, "qh_settemppush: depth %d temp set %p of %d elements\n",
-      qh_setsize(qhmem.tempstack), set, qh_setsize(set));
-} /* settemppush */
-
-
-/*---------------------------------
-
-  qh_settruncate( set, size )
-    truncate set to size elements
-
-  notes:
-    set must be defined
-
-  see:
-    SETtruncate_
-
-  design:
-    check size
-    update actual size of set
-*/
-void qh_settruncate(setT *set, int size) {
-
-  if (size < 0 || size > set->maxsize) {
-    qh_fprintf(qhmem.ferr, 6181, "qhull internal error (qh_settruncate): size %d out of bounds for set:\n", size);
-    qh_setprint(qhmem.ferr, "", set);
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-  set->e[set->maxsize].i= size+1;   /* maybe overwritten */
-  set->e[size].p= NULL;
-} /* settruncate */
-
-/*---------------------------------
-
-  qh_setunique( set, elem )
-    add elem to unsorted set unless it is already in set
-
-  notes:
-    returns 1 if it is appended
-
-  design:
-    if elem not in set
-      append elem to set
-*/
-int qh_setunique(setT **set, void *elem) {
-
-  if (!qh_setin(*set, elem)) {
-    qh_setappend(set, elem);
-    return 1;
-  }
-  return 0;
-} /* setunique */
-
-/*---------------------------------
-
-  qh_setzero( set, index, size )
-    zero elements from index on
-    set actual size of set to size
-
-  notes:
-    set must be defined
-    the set becomes an indexed set (can not use FOREACH...)
-
-  see also:
-    qh_settruncate
-
-  design:
-    check index and size
-    update actual size
-    zero elements starting at e[index]
-*/
-void qh_setzero(setT *set, int idx, int size) {
-  int count;
-
-  if (idx < 0 || idx >= size || size > set->maxsize) {
-    qh_fprintf(qhmem.ferr, 6182, "qhull internal error (qh_setzero): index %d or size %d out of bounds for set:\n", idx, size);
-    qh_setprint(qhmem.ferr, "", set);
-    qh_errexit(qhmem_ERRqhull, NULL, NULL);
-  }
-  set->e[set->maxsize].i=  size+1;  /* may be overwritten */
-  count= size - idx + 1;   /* +1 for NULL terminator */
-  memset((char *)SETelemaddr_(set, idx, void), 0, (size_t)count * SETelemsize);
-} /* setzero */
-
-
diff --git a/extern/libqhull/qset.h b/extern/libqhull/qset.h
deleted file mode 100644
index 7e4e7d14f6b9..000000000000
--- a/extern/libqhull/qset.h
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
  ---------------------------------
-
-   qset.h
-     header file for qset.c that implements set
-
-   see qh-set.htm and qset.c
-
-   only uses mem.c, malloc/free
-
-   for error handling, writes message and calls
-      qh_errexit(qhmem_ERRqhull, NULL, NULL);
-
-   set operations satisfy the following properties:
-    - sets have a max size, the actual size (if different) is stored at the end
-    - every set is NULL terminated
-    - sets may be sorted or unsorted, the caller must distinguish this
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/qset.h#2 $$Change: 2062 $
-   $DateTime: 2016/01/17 13:13:18 $$Author: bbarber $
-*/
-
-#ifndef qhDEFset
-#define qhDEFset 1
-
-#include 
-
-/*================= -structures- ===============*/
-
-#ifndef DEFsetT
-#define DEFsetT 1
-typedef struct setT setT;   /* a set is a sorted or unsorted array of pointers */
-#endif
-
-/* [jan'15] Decided not to use countT.  Most sets are small.  The code uses signed tests */
-
-/*------------------------------------------
-
-setT
-  a set or list of pointers with maximum size and actual size.
-
-variations:
-  unsorted, unique   -- a list of unique pointers with NULL terminator
-                           user guarantees uniqueness
-  sorted             -- a sorted list of unique pointers with NULL terminator
-                           qset.c guarantees uniqueness
-  unsorted           -- a list of pointers terminated with NULL
-  indexed            -- an array of pointers with NULL elements
-
-structure for set of n elements:
-
-        --------------
-        |  maxsize
-        --------------
-        |  e[0] - a pointer, may be NULL for indexed sets
-        --------------
-        |  e[1]
-
-        --------------
-        |  ...
-        --------------
-        |  e[n-1]
-        --------------
-        |  e[n] = NULL
-        --------------
-        |  ...
-        --------------
-        |  e[maxsize] - n+1 or NULL (determines actual size of set)
-        --------------
-
-*/
-
-/*-- setelemT -- internal type to allow both pointers and indices
-*/
-typedef union setelemT setelemT;
-union setelemT {
-  void    *p;
-  int      i;         /* integer used for e[maxSize] */
-};
-
-struct setT {
-  int maxsize;          /* maximum number of elements (except NULL) */
-  setelemT e[1];        /* array of pointers, tail is NULL */
-                        /* last slot (unless NULL) is actual size+1
-                           e[maxsize]==NULL or e[e[maxsize]-1]==NULL */
-                        /* this may generate a warning since e[] contains
-                           maxsize elements */
-};
-
-/*=========== -constants- =========================*/
-
-/*-------------------------------------
-
-  SETelemsize
-    size of a set element in bytes
-*/
-#define SETelemsize ((int)sizeof(setelemT))
-
-
-/*=========== -macros- =========================*/
-
-/*-------------------------------------
-
-   FOREACHsetelement_(type, set, variable)
-     define FOREACH iterator
-
-   declare:
-     assumes *variable and **variablep are declared
-     no space in "variable)" [DEC Alpha cc compiler]
-
-   each iteration:
-     variable is set element
-     variablep is one beyond variable.
-
-   to repeat an element:
-     variablep--; / *repeat* /
-
-   at exit:
-     variable is NULL at end of loop
-
-   example:
-     #define FOREACHfacet_( facets ) FOREACHsetelement_( facetT, facets, facet )
-
-   notes:
-     use FOREACHsetelement_i_() if need index or include NULLs
-
-   WARNING:
-     nested loops can't use the same variable (define another FOREACH)
-
-     needs braces if nested inside another FOREACH
-     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
-*/
-#define FOREACHsetelement_(type, set, variable) \
-        if (((variable= NULL), set)) for (\
-          variable##p= (type **)&((set)->e[0].p); \
-          (variable= *variable##p++);)
-
-/*------------------------------------------
-
-   FOREACHsetelement_i_(type, set, variable)
-     define indexed FOREACH iterator
-
-   declare:
-     type *variable, variable_n, variable_i;
-
-   each iteration:
-     variable is set element, may be NULL
-     variable_i is index, variable_n is qh_setsize()
-
-   to repeat an element:
-     variable_i--; variable_n-- repeats for deleted element
-
-   at exit:
-     variable==NULL and variable_i==variable_n
-
-   example:
-     #define FOREACHfacet_i_( facets ) FOREACHsetelement_i_( facetT, facets, facet )
-
-   WARNING:
-     nested loops can't use the same variable (define another FOREACH)
-
-     needs braces if nested inside another FOREACH
-     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
-*/
-#define FOREACHsetelement_i_(type, set, variable) \
-        if (((variable= NULL), set)) for (\
-          variable##_i= 0, variable= (type *)((set)->e[0].p), \
-                   variable##_n= qh_setsize(set);\
-          variable##_i < variable##_n;\
-          variable= (type *)((set)->e[++variable##_i].p) )
-
-/*----------------------------------------
-
-   FOREACHsetelementreverse_(type, set, variable)-
-     define FOREACH iterator in reverse order
-
-   declare:
-     assumes *variable and **variablep are declared
-     also declare 'int variabletemp'
-
-   each iteration:
-     variable is set element
-
-   to repeat an element:
-     variabletemp++; / *repeat* /
-
-   at exit:
-     variable is NULL
-
-   example:
-     #define FOREACHvertexreverse_( vertices ) FOREACHsetelementreverse_( vertexT, vertices, vertex )
-
-   notes:
-     use FOREACHsetelementreverse12_() to reverse first two elements
-     WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHsetelementreverse_(type, set, variable) \
-        if (((variable= NULL), set)) for (\
-           variable##temp= qh_setsize(set)-1, variable= qh_setlast(set);\
-           variable; variable= \
-           ((--variable##temp >= 0) ? SETelemt_(set, variable##temp, type) : NULL))
-
-/*-------------------------------------
-
-   FOREACHsetelementreverse12_(type, set, variable)-
-     define FOREACH iterator with e[1] and e[0] reversed
-
-   declare:
-     assumes *variable and **variablep are declared
-
-   each iteration:
-     variable is set element
-     variablep is one after variable.
-
-   to repeat an element:
-     variablep--; / *repeat* /
-
-   at exit:
-     variable is NULL at end of loop
-
-   example
-     #define FOREACHvertexreverse12_( vertices ) FOREACHsetelementreverse12_( vertexT, vertices, vertex )
-
-   notes:
-     WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHsetelementreverse12_(type, set, variable) \
-        if (((variable= NULL), set)) for (\
-          variable##p= (type **)&((set)->e[1].p); \
-          (variable= *variable##p); \
-          variable##p == ((type **)&((set)->e[0].p))?variable##p += 2: \
-              (variable##p == ((type **)&((set)->e[1].p))?variable##p--:variable##p++))
-
-/*-------------------------------------
-
-   FOREACHelem_( set )-
-     iterate elements in a set
-
-   declare:
-     void *elem, *elemp;
-
-   each iteration:
-     elem is set element
-     elemp is one beyond
-
-   to repeat an element:
-     elemp--; / *repeat* /
-
-   at exit:
-     elem == NULL at end of loop
-
-   example:
-     FOREACHelem_(set) {
-
-   notes:
-     WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHelem_(set) FOREACHsetelement_(void, set, elem)
-
-/*-------------------------------------
-
-   FOREACHset_( set )-
-     iterate a set of sets
-
-   declare:
-     setT *set, **setp;
-
-   each iteration:
-     set is set element
-     setp is one beyond
-
-   to repeat an element:
-     setp--; / *repeat* /
-
-   at exit:
-     set == NULL at end of loop
-
-   example
-     FOREACHset_(sets) {
-
-   notes:
-     WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHset_(sets) FOREACHsetelement_(setT, sets, set)
-
-/*-------------------------------------------
-
-   SETindex_( set, elem )
-     return index of elem in set
-
-   notes:
-     for use with FOREACH iteration
-     WARN64 -- Maximum set size is 2G
-
-   example:
-     i= SETindex_(ridges, ridge)
-*/
-#define SETindex_(set, elem) ((int)((void **)elem##p - (void **)&(set)->e[1].p))
-
-/*-----------------------------------------
-
-   SETref_( elem )
-     l.h.s. for modifying the current element in a FOREACH iteration
-
-   example:
-     SETref_(ridge)= anotherridge;
-*/
-#define SETref_(elem) (elem##p[-1])
-
-/*-----------------------------------------
-
-   SETelem_(set, n)
-     return the n'th element of set
-
-   notes:
-      assumes that n is valid [0..size] and that set is defined
-      use SETelemt_() for type cast
-*/
-#define SETelem_(set, n)           ((set)->e[n].p)
-
-/*-----------------------------------------
-
-   SETelemt_(set, n, type)
-     return the n'th element of set as a type
-
-   notes:
-      assumes that n is valid [0..size] and that set is defined
-*/
-#define SETelemt_(set, n, type)    ((type*)((set)->e[n].p))
-
-/*-----------------------------------------
-
-   SETelemaddr_(set, n, type)
-     return address of the n'th element of a set
-
-   notes:
-      assumes that n is valid [0..size] and set is defined
-*/
-#define SETelemaddr_(set, n, type) ((type **)(&((set)->e[n].p)))
-
-/*-----------------------------------------
-
-   SETfirst_(set)
-     return first element of set
-
-*/
-#define SETfirst_(set)             ((set)->e[0].p)
-
-/*-----------------------------------------
-
-   SETfirstt_(set, type)
-     return first element of set as a type
-
-*/
-#define SETfirstt_(set, type)      ((type*)((set)->e[0].p))
-
-/*-----------------------------------------
-
-   SETsecond_(set)
-     return second element of set
-
-*/
-#define SETsecond_(set)            ((set)->e[1].p)
-
-/*-----------------------------------------
-
-   SETsecondt_(set, type)
-     return second element of set as a type
-*/
-#define SETsecondt_(set, type)     ((type*)((set)->e[1].p))
-
-/*-----------------------------------------
-
-   SETaddr_(set, type)
-       return address of set's elements
-*/
-#define SETaddr_(set,type)         ((type **)(&((set)->e[0].p)))
-
-/*-----------------------------------------
-
-   SETreturnsize_(set, size)
-     return size of a set
-
-   notes:
-      set must be defined
-      use qh_setsize(set) unless speed is critical
-*/
-#define SETreturnsize_(set, size) (((size)= ((set)->e[(set)->maxsize].i))?(--(size)):((size)= (set)->maxsize))
-
-/*-----------------------------------------
-
-   SETempty_(set)
-     return true(1) if set is empty
-
-   notes:
-      set may be NULL
-*/
-#define SETempty_(set)            (!set || (SETfirst_(set) ? 0 : 1))
-
-/*---------------------------------
-
-  SETsizeaddr_(set)
-    return pointer to 'actual size+1' of set (set CANNOT be NULL!!)
-    Its type is setelemT* for strict aliasing
-    All SETelemaddr_ must be cast to setelemT
-
-
-  notes:
-    *SETsizeaddr==NULL or e[*SETsizeaddr-1].p==NULL
-*/
-#define SETsizeaddr_(set) (&((set)->e[(set)->maxsize]))
-
-/*-----------------------------------------
-
-   SETtruncate_(set, size)
-     truncate set to size
-
-   see:
-     qh_settruncate()
-
-*/
-#define SETtruncate_(set, size) {set->e[set->maxsize].i= size+1; /* maybe overwritten */ \
-      set->e[size].p= NULL;}
-
-/*======= prototypes in alphabetical order ============*/
-
-void  qh_setaddsorted(setT **setp, void *elem);
-void  qh_setaddnth(setT **setp, int nth, void *newelem);
-void  qh_setappend(setT **setp, void *elem);
-void  qh_setappend_set(setT **setp, setT *setA);
-void  qh_setappend2ndlast(setT **setp, void *elem);
-void  qh_setcheck(setT *set, const char *tname, unsigned id);
-void  qh_setcompact(setT *set);
-setT *qh_setcopy(setT *set, int extra);
-void *qh_setdel(setT *set, void *elem);
-void *qh_setdellast(setT *set);
-void *qh_setdelnth(setT *set, int nth);
-void *qh_setdelnthsorted(setT *set, int nth);
-void *qh_setdelsorted(setT *set, void *newelem);
-setT *qh_setduplicate( setT *set, int elemsize);
-void **qh_setendpointer(setT *set);
-int   qh_setequal(setT *setA, setT *setB);
-int   qh_setequal_except(setT *setA, void *skipelemA, setT *setB, void *skipelemB);
-int   qh_setequal_skip(setT *setA, int skipA, setT *setB, int skipB);
-void  qh_setfree(setT **set);
-void  qh_setfree2( setT **setp, int elemsize);
-void  qh_setfreelong(setT **set);
-int   qh_setin(setT *set, void *setelem);
-int   qh_setindex(setT *set, void *setelem);
-void  qh_setlarger(setT **setp);
-void *qh_setlast(setT *set);
-setT *qh_setnew(int size);
-setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend);
-void  qh_setprint(FILE *fp, const char* string, setT *set);
-void  qh_setreplace(setT *set, void *oldelem, void *newelem);
-int   qh_setsize(setT *set);
-setT *qh_settemp(int setsize);
-void  qh_settempfree(setT **set);
-void  qh_settempfree_all(void);
-setT *qh_settemppop(void);
-void  qh_settemppush(setT *set);
-void  qh_settruncate(setT *set, int size);
-int   qh_setunique(setT **set, void *elem);
-void  qh_setzero(setT *set, int idx, int size);
-
-
-#endif /* qhDEFset */
diff --git a/extern/libqhull/random.c b/extern/libqhull/random.c
deleted file mode 100644
index 176d697aeb5a..000000000000
--- a/extern/libqhull/random.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
  ---------------------------------
-
-   random.c and utilities
-     Park & Miller's minimimal standard random number generator
-     argc/argv conversion
-
-     Used by rbox.  Do not use 'qh' 
-*/
-
-#include "libqhull.h"
-#include "random.h"
-
-#include 
-#include 
-#include 
-
-#ifdef _MSC_VER  /* Microsoft Visual C++ -- warning level 4 */
-#pragma warning( disable : 4706)  /* assignment within conditional function */
-#pragma warning( disable : 4996)  /* function was declared deprecated(strcpy, localtime, etc.) */
-#endif
-
-/*---------------------------------
-
- qh_argv_to_command( argc, argv, command, max_size )
-
-    build command from argc/argv
-    max_size is at least
-
- returns:
-    a space-delimited string of options (just as typed)
-    returns false if max_size is too short
-
- notes:
-    silently removes
-    makes option string easy to input and output
-    matches qh_argv_to_command_size()
-
-    argc may be 0
-*/
-int qh_argv_to_command(int argc, char *argv[], char* command, int max_size) {
-  int i, remaining;
-  char *s;
-  *command= '\0';  /* max_size > 0 */
-
-  if (argc) {
-    if ((s= strrchr( argv[0], '\\')) /* get filename w/o .exe extension */
-    || (s= strrchr( argv[0], '/')))
-        s++;
-    else
-        s= argv[0];
-    if ((int)strlen(s) < max_size)   /* WARN64 */
-        strcpy(command, s);
-    else
-        goto error_argv;
-    if ((s= strstr(command, ".EXE"))
-    ||  (s= strstr(command, ".exe")))
-        *s= '\0';
-  }
-  for (i=1; i < argc; i++) {
-    s= argv[i];
-    remaining= max_size - (int)strlen(command) - (int)strlen(s) - 2;   /* WARN64 */
-    if (!*s || strchr(s, ' ')) {
-      char *t= command + strlen(command);
-      remaining -= 2;
-      if (remaining < 0) {
-        goto error_argv;
-      }
-      *t++= ' ';
-      *t++= '"';
-      while (*s) {
-        if (*s == '"') {
-          if (--remaining < 0)
-            goto error_argv;
-          *t++= '\\';
-        }
-        *t++= *s++;
-      }
-      *t++= '"';
-      *t= '\0';
-    }else if (remaining < 0) {
-      goto error_argv;
-    }else
-      strcat(command, " ");
-      strcat(command, s);
-  }
-  return 1;
-
-error_argv:
-  return 0;
-} /* argv_to_command */
-
-/*---------------------------------
-
-qh_argv_to_command_size( argc, argv )
-
-    return size to allocate for qh_argv_to_command()
-
-notes:
-    argc may be 0
-    actual size is usually shorter
-*/
-int qh_argv_to_command_size(int argc, char *argv[]) {
-    unsigned int count= 1; /* null-terminator if argc==0 */
-    int i;
-    char *s;
-
-    for (i=0; i0 && strchr(argv[i], ' ')) {
-        count += 2;  /* quote delimiters */
-        for (s=argv[i]; *s; s++) {
-          if (*s == '"') {
-            count++;
-          }
-        }
-      }
-    }
-    return count;
-} /* argv_to_command_size */
-
-/*---------------------------------
-
-  qh_rand()
-  qh_srand( seed )
-    generate pseudo-random number between 1 and 2^31 -2
-
-  notes:
-    For qhull and rbox, called from qh_RANDOMint(),etc. [user.h]
-
-    From Park & Miller's minimal standard random number generator
-      Communications of the ACM, 31:1192-1201, 1988.
-    Does not use 0 or 2^31 -1
-      this is silently enforced by qh_srand()
-    Can make 'Rn' much faster by moving qh_rand to qh_distplane
-*/
-
-/* Global variables and constants */
-
-int qh_last_random= 1;  /* define as global variable instead of using qh */
-
-#define qh_rand_a 16807
-#define qh_rand_m 2147483647
-#define qh_rand_q 127773  /* m div a */
-#define qh_rand_r 2836    /* m mod a */
-
-int qh_rand( void) {
-    int lo, hi, test;
-    int seed = qh_last_random;
-
-    hi = seed / qh_rand_q;  /* seed div q */
-    lo = seed % qh_rand_q;  /* seed mod q */
-    test = qh_rand_a * lo - qh_rand_r * hi;
-    if (test > 0)
-        seed= test;
-    else
-        seed= test + qh_rand_m;
-    qh_last_random= seed;
-    /* seed = seed < qh_RANDOMmax/2 ? 0 : qh_RANDOMmax;  for testing */
-    /* seed = qh_RANDOMmax;  for testing */
-    return seed;
-} /* rand */
-
-void qh_srand( int seed) {
-    if (seed < 1)
-        qh_last_random= 1;
-    else if (seed >= qh_rand_m)
-        qh_last_random= qh_rand_m - 1;
-    else
-        qh_last_random= seed;
-} /* qh_srand */
-
-/*---------------------------------
-
-qh_randomfactor( scale, offset )
-  return a random factor r * scale + offset
-
-notes:
-  qh.RANDOMa/b are defined in global.c
-*/
-realT qh_randomfactor(realT scale, realT offset) {
-    realT randr;
-
-    randr= qh_RANDOMint;
-    return randr * scale + offset;
-} /* randomfactor */
-
-/*---------------------------------
-
-qh_randommatrix( buffer, dim, rows )
-  generate a random dim X dim matrix in range [-1,1]
-  assumes buffer is [dim+1, dim]
-
-returns:
-  sets buffer to random numbers
-  sets rows to rows of buffer
-  sets row[dim] as scratch row
-*/
-void qh_randommatrix(realT *buffer, int dim, realT **rows) {
-    int i, k;
-    realT **rowi, *coord, realr;
-
-    coord= buffer;
-    rowi= rows;
-    for (i=0; i < dim; i++) {
-        *(rowi++)= coord;
-        for (k=0; k < dim; k++) {
-            realr= qh_RANDOMint;
-            *(coord++)= 2.0 * realr/(qh_RANDOMmax+1) - 1.0;
-        }
-    }
-    *rowi= coord;
-} /* randommatrix */
-
-/*---------------------------------
-
-  qh_strtol( s, endp) qh_strtod( s, endp)
-    internal versions of strtol() and strtod()
-    does not skip trailing spaces
-  notes:
-    some implementations of strtol()/strtod() skip trailing spaces
-*/
-double qh_strtod(const char *s, char **endp) {
-  double result;
-
-  result= strtod(s, endp);
-  if (s < (*endp) && (*endp)[-1] == ' ')
-    (*endp)--;
-  return result;
-} /* strtod */
-
-int qh_strtol(const char *s, char **endp) {
-  int result;
-
-  result= (int) strtol(s, endp, 10);     /* WARN64 */
-  if (s< (*endp) && (*endp)[-1] == ' ')
-    (*endp)--;
-  return result;
-} /* strtol */
diff --git a/extern/libqhull/random.h b/extern/libqhull/random.h
deleted file mode 100644
index 0c6896b76549..000000000000
--- a/extern/libqhull/random.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
  ---------------------------------
-
-  random.h
-    header file for random and utility routines
-
-   see qh-geom.htm and random.c
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/random.h#2 $$Change: 2026 $
-   $DateTime: 2015/11/07 22:44:39 $$Author: bbarber $
-*/
-
-#ifndef qhDEFrandom
-#define qhDEFrandom 1
-
-#include "libqhull.h"
-
-/*============= prototypes in alphabetical order ======= */
-
-
-int     qh_argv_to_command(int argc, char *argv[], char* command, int max_size);
-int     qh_argv_to_command_size(int argc, char *argv[]);
-int     qh_rand( void);
-void    qh_srand( int seed);
-realT   qh_randomfactor(realT scale, realT offset);
-void    qh_randommatrix(realT *buffer, int dim, realT **row);
-int     qh_strtol(const char *s, char **endp);
-double  qh_strtod(const char *s, char **endp);
-
-#endif /* qhDEFrandom */
-
-
-
diff --git a/extern/libqhull/rboxlib.c b/extern/libqhull/rboxlib.c
deleted file mode 100644
index f945133fa0b7..000000000000
--- a/extern/libqhull/rboxlib.c
+++ /dev/null
@@ -1,870 +0,0 @@
-/*
  ---------------------------------
-
-   rboxlib.c
-     Generate input points
-
-   notes:
-     For documentation, see prompt[] of rbox.c
-     50 points generated for 'rbox D4'
-
-   WARNING:
-     incorrect range if qh_RANDOMmax is defined wrong (user.h)
-*/
-
-#include "libqhull.h"  /* First for user.h */
-#include "random.h"
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#ifdef _MSC_VER  /* Microsoft Visual C++ */
-#pragma warning( disable : 4706)  /* assignment within conditional expression. */
-#pragma warning( disable : 4996)  /* this function (strncat,sprintf,strcpy) or variable may be unsafe. */
-#endif
-
-#define MAXdim 200
-#define PI 3.1415926535897932384
-
-/* ------------------------------ prototypes ----------------*/
-int qh_roundi( double a);
-void qh_out1( double a);
-void qh_out2n( double a, double b);
-void qh_out3n( double a, double b, double c);
-void qh_outcoord(int iscdd, double *coord, int dim);
-void qh_outcoincident(int coincidentpoints, double radius, int iscdd, double *coord, int dim);
-
-void    qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... );
-void    qh_free(void *mem);
-void   *qh_malloc(size_t size);
-int     qh_rand( void);
-void    qh_srand( int seed);
-
-
-/* ------------------------------ globals -------------------*/
-
-/* No state is carried between rbox requests */
-typedef struct rboxT rboxT;
-struct rboxT {
-  FILE *fout;
-  FILE *ferr;
-  int isinteger;
-  double out_offset;
-  jmp_buf errexit;        /* exit label for rboxpoints, defined by setjmp(), called by qh_errexit_rbox() */
-  char  jmpXtra[40];      /* extra bytes in case jmp_buf is defined wrong by compiler */
-};
-
-
-int rbox_inuse= 0;
-rboxT rbox;
-
-/*---------------------------------
-
-  qh_rboxpoints( fout, ferr, rbox_command )
-    Generate points to fout according to rbox options
-    Report errors on ferr
-
-  returns:
-    0 (qh_ERRnone) on success
-    1 (qh_ERRinput) on input error
-    4 (qh_ERRmem) on memory error
-    5 (qh_ERRqhull) on internal error
-
-  notes:
-    To avoid using stdio, redefine qh_malloc, qh_free, and qh_fprintf_rbox (user.c)
-
-  design:
-    Straight line code (consider defining a struct and functions):
-
-    Parse arguments into variables
-    Determine the number of points
-    Generate the points
-*/
-int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
-  int i,j,k;
-  int gendim;
-  int coincidentcount=0, coincidenttotal=0, coincidentpoints=0;
-  int cubesize, diamondsize, seed=0, count, apex;
-  int dim=3, numpoints=0, totpoints, addpoints=0;
-  int issphere=0, isaxis=0,  iscdd=0, islens=0, isregular=0, iswidth=0, addcube=0;
-  int isgap=0, isspiral=0, NOcommand=0, adddiamond=0;
-  int israndom=0, istime=0;
-  int isbox=0, issimplex=0, issimplex2=0, ismesh=0;
-  double width=0.0, gap=0.0, radius=0.0, coincidentradius=0.0;
-  double coord[MAXdim], offset, meshm=3.0, meshn=4.0, meshr=5.0;
-  double *coordp, *simplex= NULL, *simplexp;
-  int nthroot, mult[MAXdim];
-  double norm, factor, randr, rangap, lensangle=0, lensbase=1;
-  double anglediff, angle, x, y, cube=0.0, diamond=0.0;
-  double box= qh_DEFAULTbox; /* scale all numbers before output */
-  double randmax= qh_RANDOMmax;
-  char command[200], seedbuf[200];
-  char *s= command, *t, *first_point= NULL;
-  time_t timedata;
-  int exitcode;
-
-  if (rbox_inuse) {
-    qh_fprintf_rbox(rbox.ferr, 6188, "rbox error: rbox in use by another process.  Please lock calls to rbox.\n");
-    return qh_ERRqhull;
-  }
-  rbox_inuse= True;
-  rbox.ferr= ferr;
-  rbox.fout= fout;
-
-  exitcode= setjmp(rbox.errexit);
-  if (exitcode) {
-    /* same code for error exit and normal return.  qh.NOerrexit is set */
-    if (simplex)
-        qh_free(simplex);
-    rbox_inuse= False;
-    return exitcode;
-  }
-
-  *command= '\0';
-  strncat(command, rbox_command, sizeof(command)-strlen(command)-1);
-
-  while (*s && !isspace(*s))  /* skip program name */
-    s++;
-  while (*s) {
-    while (*s && isspace(*s))
-      s++;
-    if (*s == '-')
-      s++;
-    if (!*s)
-      break;
-    if (isdigit(*s)) {
-      numpoints= qh_strtol(s, &s);
-      continue;
-    }
-    /* ============= read flags =============== */
-    switch (*s++) {
-    case 'c':
-      addcube= 1;
-      t= s;
-      while (isspace(*t))
-        t++;
-      if (*t == 'G')
-        cube= qh_strtod(++t, &s);
-      break;
-    case 'd':
-      adddiamond= 1;
-      t= s;
-      while (isspace(*t))
-        t++;
-      if (*t == 'G')
-        diamond= qh_strtod(++t, &s);
-      break;
-    case 'h':
-      iscdd= 1;
-      break;
-    case 'l':
-      isspiral= 1;
-      break;
-    case 'n':
-      NOcommand= 1;
-      break;
-    case 'r':
-      isregular= 1;
-      break;
-    case 's':
-      issphere= 1;
-      break;
-    case 't':
-      istime= 1;
-      if (isdigit(*s)) {
-        seed= qh_strtol(s, &s);
-        israndom= 0;
-      }else
-        israndom= 1;
-      break;
-    case 'x':
-      issimplex= 1;
-      break;
-    case 'y':
-      issimplex2= 1;
-      break;
-    case 'z':
-      rbox.isinteger= 1;
-      break;
-    case 'B':
-      box= qh_strtod(s, &s);
-      isbox= 1;
-      break;
-    case 'C':
-      if (*s)
-        coincidentpoints=  qh_strtol(s, &s);
-      if (*s == ',') {
-        ++s;
-        coincidentradius=  qh_strtod(s, &s);
-      }
-      if (*s == ',') {
-        ++s;
-        coincidenttotal=  qh_strtol(s, &s);
-      }
-      if (*s && !isspace(*s)) {
-        qh_fprintf_rbox(rbox.ferr, 7080, "rbox error: arguments for 'Cn,r,m' are not 'int', 'float', and 'int'.  Remaining string is '%s'\n", s);
-        qh_errexit_rbox(qh_ERRinput);
-      }
-      if (coincidentpoints==0){
-        qh_fprintf_rbox(rbox.ferr, 6268, "rbox error: missing arguments for 'Cn,r,m' where n is the number of coincident points, r is the radius (default 0.0), and m is the number of points\n");
-        qh_errexit_rbox(qh_ERRinput);
-      }
-      if (coincidentpoints<0 || coincidenttotal<0 || coincidentradius<0.0){
-        qh_fprintf_rbox(rbox.ferr, 6269, "rbox error: negative arguments for 'Cn,m,r' where n (%d) is the number of coincident points, m (%d) is the number of points, and r (%.2g) is the radius (default 0.0)\n", coincidentpoints, coincidenttotal, coincidentradius);
-        qh_errexit_rbox(qh_ERRinput);
-      }
-      break;
-    case 'D':
-      dim= qh_strtol(s, &s);
-      if (dim < 1
-      || dim > MAXdim) {
-        qh_fprintf_rbox(rbox.ferr, 6189, "rbox error: dimension, D%d, out of bounds (>=%d or <=0)", dim, MAXdim);
-        qh_errexit_rbox(qh_ERRinput);
-      }
-      break;
-    case 'G':
-      if (isdigit(*s))
-        gap= qh_strtod(s, &s);
-      else
-        gap= 0.5;
-      isgap= 1;
-      break;
-    case 'L':
-      if (isdigit(*s))
-        radius= qh_strtod(s, &s);
-      else
-        radius= 10;
-      islens= 1;
-      break;
-    case 'M':
-      ismesh= 1;
-      if (*s)
-        meshn= qh_strtod(s, &s);
-      if (*s == ',') {
-        ++s;
-        meshm= qh_strtod(s, &s);
-      }else
-        meshm= 0.0;
-      if (*s == ',') {
-        ++s;
-        meshr= qh_strtod(s, &s);
-      }else
-        meshr= sqrt(meshn*meshn + meshm*meshm);
-      if (*s && !isspace(*s)) {
-        qh_fprintf_rbox(rbox.ferr, 7069, "rbox warning: assuming 'M3,4,5' since mesh args are not integers or reals\n");
-        meshn= 3.0, meshm=4.0, meshr=5.0;
-      }
-      break;
-    case 'O':
-      rbox.out_offset= qh_strtod(s, &s);
-      break;
-    case 'P':
-      if (!first_point)
-        first_point= s-1;
-      addpoints++;
-      while (*s && !isspace(*s))   /* read points later */
-        s++;
-      break;
-    case 'W':
-      width= qh_strtod(s, &s);
-      iswidth= 1;
-      break;
-    case 'Z':
-      if (isdigit(*s))
-        radius= qh_strtod(s, &s);
-      else
-        radius= 1.0;
-      isaxis= 1;
-      break;
-    default:
-      qh_fprintf_rbox(rbox.ferr, 7070, "rbox error: unknown flag at %s.\nExecute 'rbox' without arguments for documentation.\n", s);
-      qh_errexit_rbox(qh_ERRinput);
-    }
-    if (*s && !isspace(*s)) {
-      qh_fprintf_rbox(rbox.ferr, 7071, "rbox error: missing space between flags at %s.\n", s);
-      qh_errexit_rbox(qh_ERRinput);
-    }
-  }
-
-  /* ============= defaults, constants, and sizes =============== */
-  if (rbox.isinteger && !isbox)
-    box= qh_DEFAULTzbox;
-  if (addcube) {
-    cubesize= (int)floor(ldexp(1.0,dim)+0.5);
-    if (cube == 0.0)
-      cube= box;
-  }else
-    cubesize= 0;
-  if (adddiamond) {
-    diamondsize= 2*dim;
-    if (diamond == 0.0)
-      diamond= box;
-  }else
-    diamondsize= 0;
-  if (islens) {
-    if (isaxis) {
-        qh_fprintf_rbox(rbox.ferr, 6190, "rbox error: can not combine 'Ln' with 'Zn'\n");
-        qh_errexit_rbox(qh_ERRinput);
-    }
-    if (radius <= 1.0) {
-        qh_fprintf_rbox(rbox.ferr, 6191, "rbox error: lens radius %.2g should be greater than 1.0\n",
-               radius);
-        qh_errexit_rbox(qh_ERRinput);
-    }
-    lensangle= asin(1.0/radius);
-    lensbase= radius * cos(lensangle);
-  }
-
-  if (!numpoints) {
-    if (issimplex2)
-        ; /* ok */
-    else if (isregular + issimplex + islens + issphere + isaxis + isspiral + iswidth + ismesh) {
-        qh_fprintf_rbox(rbox.ferr, 6192, "rbox error: missing count\n");
-        qh_errexit_rbox(qh_ERRinput);
-    }else if (adddiamond + addcube + addpoints)
-        ; /* ok */
-    else {
-        numpoints= 50;  /* ./rbox D4 is the test case */
-        issphere= 1;
-    }
-  }
-  if ((issimplex + islens + isspiral + ismesh > 1)
-  || (issimplex + issphere + isspiral + ismesh > 1)) {
-    qh_fprintf_rbox(rbox.ferr, 6193, "rbox error: can only specify one of 'l', 's', 'x', 'Ln', or 'Mn,m,r' ('Ln s' is ok).\n");
-    qh_errexit_rbox(qh_ERRinput);
-  }
-  if (coincidentpoints>0 && (numpoints == 0 || coincidenttotal > numpoints)) {
-    qh_fprintf_rbox(rbox.ferr, 6270, "rbox error: 'Cn,r,m' requested n coincident points for each of m points.  Either there is no points or m (%d) is greater than the number of points (%d).\n", coincidenttotal, numpoints);
-    qh_errexit_rbox(qh_ERRinput);
-  }
-  if (coincidenttotal == 0)
-    coincidenttotal= numpoints;
-
-  /* ============= print header with total points =============== */
-  if (issimplex || ismesh)
-    totpoints= numpoints;
-  else if (issimplex2)
-    totpoints= numpoints+dim+1;
-  else if (isregular) {
-    totpoints= numpoints;
-    if (dim == 2) {
-        if (islens)
-          totpoints += numpoints - 2;
-    }else if (dim == 3) {
-        if (islens)
-          totpoints += 2 * numpoints;
-      else if (isgap)
-        totpoints += 1 + numpoints;
-      else
-        totpoints += 2;
-    }
-  }else
-    totpoints= numpoints + isaxis;
-  totpoints += cubesize + diamondsize + addpoints;
-  totpoints += coincidentpoints*coincidenttotal;
-
-  /* ============= seed randoms =============== */
-  if (istime == 0) {
-    for (s=command; *s; s++) {
-      if (issimplex2 && *s == 'y') /* make 'y' same seed as 'x' */
-        i= 'x';
-      else
-        i= *s;
-      seed= 11*seed + i;
-    }
-  }else if (israndom) {
-    seed= (int)time(&timedata);
-    sprintf(seedbuf, " t%d", seed);  /* appends an extra t, not worth removing */
-    strncat(command, seedbuf, sizeof(command)-strlen(command)-1);
-    t= strstr(command, " t ");
-    if (t)
-      strcpy(t+1, t+3); /* remove " t " */
-  } /* else, seed explicitly set to n */
-  qh_RANDOMseed_(seed);
-
-  /* ============= print header =============== */
-
-  if (iscdd)
-      qh_fprintf_rbox(rbox.fout, 9391, "%s\nbegin\n        %d %d %s\n",
-      NOcommand ? "" : command,
-      totpoints, dim+1,
-      rbox.isinteger ? "integer" : "real");
-  else if (NOcommand)
-      qh_fprintf_rbox(rbox.fout, 9392, "%d\n%d\n", dim, totpoints);
-  else
-      /* qh_fprintf_rbox special cases 9393 to append 'command' to the RboxPoints.comment() */
-      qh_fprintf_rbox(rbox.fout, 9393, "%d %s\n%d\n", dim, command, totpoints);
-
-  /* ============= explicit points =============== */
-  if ((s= first_point)) {
-    while (s && *s) { /* 'P' */
-      count= 0;
-      if (iscdd)
-        qh_out1( 1.0);
-      while (*++s) {
-        qh_out1( qh_strtod(s, &s));
-        count++;
-        if (isspace(*s) || !*s)
-          break;
-        if (*s != ',') {
-          qh_fprintf_rbox(rbox.ferr, 6194, "rbox error: missing comma after coordinate in %s\n\n", s);
-          qh_errexit_rbox(qh_ERRinput);
-        }
-      }
-      if (count < dim) {
-        for (k=dim-count; k--; )
-          qh_out1( 0.0);
-      }else if (count > dim) {
-        qh_fprintf_rbox(rbox.ferr, 6195, "rbox error: %d coordinates instead of %d coordinates in %s\n\n",
-                  count, dim, s);
-        qh_errexit_rbox(qh_ERRinput);
-      }
-      qh_fprintf_rbox(rbox.fout, 9394, "\n");
-      while ((s= strchr(s, 'P'))) {
-        if (isspace(s[-1]))
-          break;
-      }
-    }
-  }
-
-  /* ============= simplex distribution =============== */
-  if (issimplex+issimplex2) {
-    if (!(simplex= (double*)qh_malloc( dim * (dim+1) * sizeof(double)))) {
-      qh_fprintf_rbox(rbox.ferr, 6196, "rbox error: insufficient memory for simplex\n");
-      qh_errexit_rbox(qh_ERRmem); /* qh_ERRmem */
-    }
-    simplexp= simplex;
-    if (isregular) {
-      for (i=0; i randmax/2)
-          coord[dim-1]= -coord[dim-1];
-      /* ============= project 'Wn' point toward boundary =============== */
-      }else if (iswidth && !issphere) {
-        j= qh_RANDOMint % gendim;
-        if (coord[j] < 0)
-          coord[j]= -1.0 - coord[j] * width;
-        else
-          coord[j]= 1.0 - coord[j] * width;
-      }
-      /* ============= scale point to box =============== */
-      for (k=0; k=0; k--) {
-        if (j & ( 1 << k))
-          qh_out1( cube);
-        else
-          qh_out1( -cube);
-      }
-      qh_fprintf_rbox(rbox.fout, 9400, "\n");
-    }
-  }
-
-  /* ============= write diamond vertices =============== */
-  if (adddiamond) {
-    for (j=0; j=0; k--) {
-        if (j/2 != k)
-          qh_out1( 0.0);
-        else if (j & 0x1)
-          qh_out1( diamond);
-        else
-          qh_out1( -diamond);
-      }
-      qh_fprintf_rbox(rbox.fout, 9401, "\n");
-    }
-  }
-
-  if (iscdd)
-    qh_fprintf_rbox(rbox.fout, 9402, "end\nhull\n");
-
-  /* same code for error exit and normal return */
-  qh_free(simplex);
-  rbox_inuse= False;
-  return qh_ERRnone;
-} /* rboxpoints */
-
-/*------------------------------------------------
-outxxx - output functions for qh_rboxpoints
-*/
-int qh_roundi( double a) {
-  if (a < 0.0) {
-    if (a - 0.5 < INT_MIN) {
-      qh_fprintf_rbox(rbox.ferr, 6200, "rbox input error: negative coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
-      qh_errexit_rbox(qh_ERRinput);
-    }
-    return (int)(a - 0.5);
-  }else {
-    if (a + 0.5 > INT_MAX) {
-      qh_fprintf_rbox(rbox.ferr, 6201, "rbox input error: coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
-      qh_errexit_rbox(qh_ERRinput);
-    }
-    return (int)(a + 0.5);
-  }
-} /* qh_roundi */
-
-void qh_out1(double a) {
-
-  if (rbox.isinteger)
-    qh_fprintf_rbox(rbox.fout, 9403, "%d ", qh_roundi( a+rbox.out_offset));
-  else
-    qh_fprintf_rbox(rbox.fout, 9404, qh_REAL_1, a+rbox.out_offset);
-} /* qh_out1 */
-
-void qh_out2n( double a, double b) {
-
-  if (rbox.isinteger)
-    qh_fprintf_rbox(rbox.fout, 9405, "%d %d\n", qh_roundi(a+rbox.out_offset), qh_roundi(b+rbox.out_offset));
-  else
-    qh_fprintf_rbox(rbox.fout, 9406, qh_REAL_2n, a+rbox.out_offset, b+rbox.out_offset);
-} /* qh_out2n */
-
-void qh_out3n( double a, double b, double c) {
-
-  if (rbox.isinteger)
-    qh_fprintf_rbox(rbox.fout, 9407, "%d %d %d\n", qh_roundi(a+rbox.out_offset), qh_roundi(b+rbox.out_offset), qh_roundi(c+rbox.out_offset));
-  else
-    qh_fprintf_rbox(rbox.fout, 9408, qh_REAL_3n, a+rbox.out_offset, b+rbox.out_offset, c+rbox.out_offset);
-} /* qh_out3n */
-
-void qh_outcoord(int iscdd, double *coord, int dim) {
-    double *p= coord;
-    int k;
-
-    if (iscdd)
-      qh_out1( 1.0);
-    for (k=0; k < dim; k++)
-      qh_out1(*(p++));
-    qh_fprintf_rbox(rbox.fout, 9396, "\n");
-} /* qh_outcoord */
-
-void qh_outcoincident(int coincidentpoints, double radius, int iscdd, double *coord, int dim) {
-  double *p;
-  double randr, delta;
-  int i,k;
-  double randmax= qh_RANDOMmax;
-
-  for (i= 0; i
  ---------------------------------
-
-   stat.c
-   contains all statistics that are collected for qhull
-
-   see qh-stat.htm and stat.h
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/stat.c#5 $$Change: 2062 $
-   $DateTime: 2016/01/17 13:13:18 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-/*============ global data structure ==========*/
-
-#if qh_QHpointer
-qhstatT *qh_qhstat=NULL;  /* global data structure */
-#else
-qhstatT qh_qhstat;   /* add "={0}" if this causes a compiler error */
-#endif
-
-/*========== functions in alphabetic order ================*/
-
-/*---------------------------------
-
-  qh_allstatA()
-    define statistics in groups of 20
-
-  notes:
-    (otherwise, 'gcc -O2' uses too much memory)
-    uses qhstat.next
-*/
-void qh_allstatA(void) {
-
-   /* zdef_(type,name,doc,average) */
-  zzdef_(zdoc, Zdoc2, "precision statistics", -1);
-  zdef_(zinc, Znewvertex, NULL, -1);
-  zdef_(wadd, Wnewvertex, "ave. distance of a new vertex to a facet(!0s)", Znewvertex);
-  zzdef_(wmax, Wnewvertexmax, "max. distance of a new vertex to a facet", -1);
-  zdef_(wmax, Wvertexmax, "max. distance of an output vertex to a facet", -1);
-  zdef_(wmin, Wvertexmin, "min. distance of an output vertex to a facet", -1);
-  zdef_(wmin, Wmindenom, "min. denominator in hyperplane computation", -1);
-
-  qhstat precision= qhstat next;  /* call qh_precision for each of these */
-  zzdef_(zdoc, Zdoc3, "precision problems (corrected unless 'Q0' or an error)", -1);
-  zzdef_(zinc, Zcoplanarridges, "coplanar half ridges in output", -1);
-  zzdef_(zinc, Zconcaveridges, "concave half ridges in output", -1);
-  zzdef_(zinc, Zflippedfacets, "flipped facets", -1);
-  zzdef_(zinc, Zcoplanarhorizon, "coplanar horizon facets for new vertices", -1);
-  zzdef_(zinc, Zcoplanarpart, "coplanar points during partitioning", -1);
-  zzdef_(zinc, Zminnorm, "degenerate hyperplanes recomputed with gaussian elimination", -1);
-  zzdef_(zinc, Znearlysingular, "nearly singular or axis-parallel hyperplanes", -1);
-  zzdef_(zinc, Zback0, "zero divisors during back substitute", -1);
-  zzdef_(zinc, Zgauss0, "zero divisors during gaussian elimination", -1);
-  zzdef_(zinc, Zmultiridge, "ridges with multiple neighbors", -1);
-}
-void qh_allstatB(void) {
-  zzdef_(zdoc, Zdoc1, "summary information", -1);
-  zdef_(zinc, Zvertices, "number of vertices in output", -1);
-  zdef_(zinc, Znumfacets, "number of facets in output", -1);
-  zdef_(zinc, Znonsimplicial, "number of non-simplicial facets in output", -1);
-  zdef_(zinc, Znowsimplicial, "number of simplicial facets that were merged", -1);
-  zdef_(zinc, Znumridges, "number of ridges in output", -1);
-  zdef_(zadd, Znumridges, "average number of ridges per facet", Znumfacets);
-  zdef_(zmax, Zmaxridges, "maximum number of ridges", -1);
-  zdef_(zadd, Znumneighbors, "average number of neighbors per facet", Znumfacets);
-  zdef_(zmax, Zmaxneighbors, "maximum number of neighbors", -1);
-  zdef_(zadd, Znumvertices, "average number of vertices per facet", Znumfacets);
-  zdef_(zmax, Zmaxvertices, "maximum number of vertices", -1);
-  zdef_(zadd, Znumvneighbors, "average number of neighbors per vertex", Zvertices);
-  zdef_(zmax, Zmaxvneighbors, "maximum number of neighbors", -1);
-  zdef_(wadd, Wcpu, "cpu seconds for qhull after input", -1);
-  zdef_(zinc, Ztotvertices, "vertices created altogether", -1);
-  zzdef_(zinc, Zsetplane, "facets created altogether", -1);
-  zdef_(zinc, Ztotridges, "ridges created altogether", -1);
-  zdef_(zinc, Zpostfacets, "facets before post merge", -1);
-  zdef_(zadd, Znummergetot, "average merges per facet(at most 511)", Znumfacets);
-  zdef_(zmax, Znummergemax, "  maximum merges for a facet(at most 511)", -1);
-  zdef_(zinc, Zangle, NULL, -1);
-  zdef_(wadd, Wangle, "average angle(cosine) of facet normals for all ridges", Zangle);
-  zdef_(wmax, Wanglemax, "  maximum angle(cosine) of facet normals across a ridge", -1);
-  zdef_(wmin, Wanglemin, "  minimum angle(cosine) of facet normals across a ridge", -1);
-  zdef_(wadd, Wareatot, "total area of facets", -1);
-  zdef_(wmax, Wareamax, "  maximum facet area", -1);
-  zdef_(wmin, Wareamin, "  minimum facet area", -1);
-}
-void qh_allstatC(void) {
-  zdef_(zdoc, Zdoc9, "build hull statistics", -1);
-  zzdef_(zinc, Zprocessed, "points processed", -1);
-  zzdef_(zinc, Zretry, "retries due to precision problems", -1);
-  zdef_(wmax, Wretrymax, "  max. random joggle", -1);
-  zdef_(zmax, Zmaxvertex, "max. vertices at any one time", -1);
-  zdef_(zinc, Ztotvisible, "ave. visible facets per iteration", Zprocessed);
-  zdef_(zinc, Zinsidevisible, "  ave. visible facets without an horizon neighbor", Zprocessed);
-  zdef_(zadd, Zvisfacettot,  "  ave. facets deleted per iteration", Zprocessed);
-  zdef_(zmax, Zvisfacetmax,  "    maximum", -1);
-  zdef_(zadd, Zvisvertextot, "ave. visible vertices per iteration", Zprocessed);
-  zdef_(zmax, Zvisvertexmax, "    maximum", -1);
-  zdef_(zinc, Ztothorizon, "ave. horizon facets per iteration", Zprocessed);
-  zdef_(zadd, Znewfacettot,  "ave. new or merged facets per iteration", Zprocessed);
-  zdef_(zmax, Znewfacetmax,  "    maximum(includes initial simplex)", -1);
-  zdef_(wadd, Wnewbalance, "average new facet balance", Zprocessed);
-  zdef_(wadd, Wnewbalance2, "  standard deviation", -1);
-  zdef_(wadd, Wpbalance, "average partition balance", Zpbalance);
-  zdef_(wadd, Wpbalance2, "  standard deviation", -1);
-  zdef_(zinc, Zpbalance, "  number of trials", -1);
-  zdef_(zinc, Zsearchpoints, "searches of all points for initial simplex", -1);
-  zdef_(zinc, Zdetsimplex, "determinants computed(area & initial hull)", -1);
-  zdef_(zinc, Znoarea, "determinants not computed because vertex too low", -1);
-  zdef_(zinc, Znotmax, "points ignored(!above max_outside)", -1);
-  zdef_(zinc, Znotgood, "points ignored(!above a good facet)", -1);
-  zdef_(zinc, Znotgoodnew, "points ignored(didn't create a good new facet)", -1);
-  zdef_(zinc, Zgoodfacet, "good facets found", -1);
-  zzdef_(zinc, Znumvisibility, "distance tests for facet visibility", -1);
-  zdef_(zinc, Zdistvertex, "distance tests to report minimum vertex", -1);
-  zzdef_(zinc, Ztotcheck, "points checked for facets' outer planes", -1);
-  zzdef_(zinc, Zcheckpart, "  ave. distance tests per check", Ztotcheck);
-}
-void qh_allstatD(void) {
-  zdef_(zinc, Zvisit, "resets of visit_id", -1);
-  zdef_(zinc, Zvvisit, "  resets of vertex_visit", -1);
-  zdef_(zmax, Zvisit2max, "  max visit_id/2", -1);
-  zdef_(zmax, Zvvisit2max, "  max vertex_visit/2", -1);
-
-  zdef_(zdoc, Zdoc4, "partitioning statistics(see previous for outer planes)", -1);
-  zzdef_(zadd, Zdelvertextot, "total vertices deleted", -1);
-  zdef_(zmax, Zdelvertexmax, "    maximum vertices deleted per iteration", -1);
-  zdef_(zinc, Zfindbest, "calls to findbest", -1);
-  zdef_(zadd, Zfindbesttot, " ave. facets tested", Zfindbest);
-  zdef_(zmax, Zfindbestmax, " max. facets tested", -1);
-  zdef_(zadd, Zfindcoplanar, " ave. coplanar search", Zfindbest);
-  zdef_(zinc, Zfindnew, "calls to findbestnew", -1);
-  zdef_(zadd, Zfindnewtot, " ave. facets tested", Zfindnew);
-  zdef_(zmax, Zfindnewmax, " max. facets tested", -1);
-  zdef_(zinc, Zfindnewjump, " ave. clearly better", Zfindnew);
-  zdef_(zinc, Zfindnewsharp, " calls due to qh_sharpnewfacets", -1);
-  zdef_(zinc, Zfindhorizon, "calls to findhorizon", -1);
-  zdef_(zadd, Zfindhorizontot, " ave. facets tested", Zfindhorizon);
-  zdef_(zmax, Zfindhorizonmax, " max. facets tested", -1);
-  zdef_(zinc, Zfindjump,       " ave. clearly better", Zfindhorizon);
-  zdef_(zinc, Zparthorizon, " horizon facets better than bestfacet", -1);
-  zdef_(zinc, Zpartangle, "angle tests for repartitioned coplanar points", -1);
-  zdef_(zinc, Zpartflip, "  repartitioned coplanar points for flipped orientation", -1);
-}
-void qh_allstatE(void) {
-  zdef_(zinc, Zpartinside, "inside points", -1);
-  zdef_(zinc, Zpartnear, "  inside points kept with a facet", -1);
-  zdef_(zinc, Zcoplanarinside, "  inside points that were coplanar with a facet", -1);
-  zdef_(zinc, Zbestlower, "calls to findbestlower", -1);
-  zdef_(zinc, Zbestlowerv, "  with search of vertex neighbors", -1);
-  zdef_(zinc, Zbestlowerall, "  with rare search of all facets", -1);
-  zdef_(zmax, Zbestloweralln, "  facets per search of all facets", -1);
-  zdef_(wadd, Wmaxout, "difference in max_outside at final check", -1);
-  zzdef_(zinc, Zpartitionall, "distance tests for initial partition", -1);
-  zdef_(zinc, Ztotpartition, "partitions of a point", -1);
-  zzdef_(zinc, Zpartition, "distance tests for partitioning", -1);
-  zzdef_(zinc, Zdistcheck, "distance tests for checking flipped facets", -1);
-  zzdef_(zinc, Zdistconvex, "distance tests for checking convexity", -1);
-  zdef_(zinc, Zdistgood, "distance tests for checking good point", -1);
-  zdef_(zinc, Zdistio, "distance tests for output", -1);
-  zdef_(zinc, Zdiststat, "distance tests for statistics", -1);
-  zdef_(zinc, Zdistplane, "total number of distance tests", -1);
-  zdef_(zinc, Ztotpartcoplanar, "partitions of coplanar points or deleted vertices", -1);
-  zzdef_(zinc, Zpartcoplanar, "   distance tests for these partitions", -1);
-  zdef_(zinc, Zcomputefurthest, "distance tests for computing furthest", -1);
-}
-void qh_allstatE2(void) {
-  zdef_(zdoc, Zdoc5, "statistics for matching ridges", -1);
-  zdef_(zinc, Zhashlookup, "total lookups for matching ridges of new facets", -1);
-  zdef_(zinc, Zhashtests, "average number of tests to match a ridge", Zhashlookup);
-  zdef_(zinc, Zhashridge, "total lookups of subridges(duplicates and boundary)", -1);
-  zdef_(zinc, Zhashridgetest, "average number of tests per subridge", Zhashridge);
-  zdef_(zinc, Zdupsame, "duplicated ridges in same merge cycle", -1);
-  zdef_(zinc, Zdupflip, "duplicated ridges with flipped facets", -1);
-
-  zdef_(zdoc, Zdoc6, "statistics for determining merges", -1);
-  zdef_(zinc, Zangletests, "angles computed for ridge convexity", -1);
-  zdef_(zinc, Zbestcentrum, "best merges used centrum instead of vertices",-1);
-  zzdef_(zinc, Zbestdist, "distance tests for best merge", -1);
-  zzdef_(zinc, Zcentrumtests, "distance tests for centrum convexity", -1);
-  zzdef_(zinc, Zdistzero, "distance tests for checking simplicial convexity", -1);
-  zdef_(zinc, Zcoplanarangle, "coplanar angles in getmergeset", -1);
-  zdef_(zinc, Zcoplanarcentrum, "coplanar centrums in getmergeset", -1);
-  zdef_(zinc, Zconcaveridge, "concave ridges in getmergeset", -1);
-}
-void qh_allstatF(void) {
-  zdef_(zdoc, Zdoc7, "statistics for merging", -1);
-  zdef_(zinc, Zpremergetot, "merge iterations", -1);
-  zdef_(zadd, Zmergeinittot, "ave. initial non-convex ridges per iteration", Zpremergetot);
-  zdef_(zadd, Zmergeinitmax, "  maximum", -1);
-  zdef_(zadd, Zmergesettot, "  ave. additional non-convex ridges per iteration", Zpremergetot);
-  zdef_(zadd, Zmergesetmax, "  maximum additional in one pass", -1);
-  zdef_(zadd, Zmergeinittot2, "initial non-convex ridges for post merging", -1);
-  zdef_(zadd, Zmergesettot2, "  additional non-convex ridges", -1);
-  zdef_(wmax, Wmaxoutside, "max distance of vertex or coplanar point above facet(w/roundoff)", -1);
-  zdef_(wmin, Wminvertex, "max distance of merged vertex below facet(or roundoff)", -1);
-  zdef_(zinc, Zwidefacet, "centrums frozen due to a wide merge", -1);
-  zdef_(zinc, Zwidevertices, "centrums frozen due to extra vertices", -1);
-  zzdef_(zinc, Ztotmerge, "total number of facets or cycles of facets merged", -1);
-  zdef_(zinc, Zmergesimplex, "merged a simplex", -1);
-  zdef_(zinc, Zonehorizon, "simplices merged into coplanar horizon", -1);
-  zzdef_(zinc, Zcyclehorizon, "cycles of facets merged into coplanar horizon", -1);
-  zzdef_(zadd, Zcyclefacettot, "  ave. facets per cycle", Zcyclehorizon);
-  zdef_(zmax, Zcyclefacetmax, "  max. facets", -1);
-  zdef_(zinc, Zmergeintohorizon, "new facets merged into horizon", -1);
-  zdef_(zinc, Zmergenew, "new facets merged", -1);
-  zdef_(zinc, Zmergehorizon, "horizon facets merged into new facets", -1);
-  zdef_(zinc, Zmergevertex, "vertices deleted by merging", -1);
-  zdef_(zinc, Zcyclevertex, "vertices deleted by merging into coplanar horizon", -1);
-  zdef_(zinc, Zdegenvertex, "vertices deleted by degenerate facet", -1);
-  zdef_(zinc, Zmergeflipdup, "merges due to flipped facets in duplicated ridge", -1);
-  zdef_(zinc, Zneighbor, "merges due to redundant neighbors", -1);
-  zdef_(zadd, Ztestvneighbor, "non-convex vertex neighbors", -1);
-}
-void qh_allstatG(void) {
-  zdef_(zinc, Zacoplanar, "merges due to angle coplanar facets", -1);
-  zdef_(wadd, Wacoplanartot, "  average merge distance", Zacoplanar);
-  zdef_(wmax, Wacoplanarmax, "  maximum merge distance", -1);
-  zdef_(zinc, Zcoplanar, "merges due to coplanar facets", -1);
-  zdef_(wadd, Wcoplanartot, "  average merge distance", Zcoplanar);
-  zdef_(wmax, Wcoplanarmax, "  maximum merge distance", -1);
-  zdef_(zinc, Zconcave, "merges due to concave facets", -1);
-  zdef_(wadd, Wconcavetot, "  average merge distance", Zconcave);
-  zdef_(wmax, Wconcavemax, "  maximum merge distance", -1);
-  zdef_(zinc, Zavoidold, "coplanar/concave merges due to avoiding old merge", -1);
-  zdef_(wadd, Wavoidoldtot, "  average merge distance", Zavoidold);
-  zdef_(wmax, Wavoidoldmax, "  maximum merge distance", -1);
-  zdef_(zinc, Zdegen, "merges due to degenerate facets", -1);
-  zdef_(wadd, Wdegentot, "  average merge distance", Zdegen);
-  zdef_(wmax, Wdegenmax, "  maximum merge distance", -1);
-  zdef_(zinc, Zflipped, "merges due to removing flipped facets", -1);
-  zdef_(wadd, Wflippedtot, "  average merge distance", Zflipped);
-  zdef_(wmax, Wflippedmax, "  maximum merge distance", -1);
-  zdef_(zinc, Zduplicate, "merges due to duplicated ridges", -1);
-  zdef_(wadd, Wduplicatetot, "  average merge distance", Zduplicate);
-  zdef_(wmax, Wduplicatemax, "  maximum merge distance", -1);
-}
-void qh_allstatH(void) {
-  zdef_(zdoc, Zdoc8, "renamed vertex statistics", -1);
-  zdef_(zinc, Zrenameshare, "renamed vertices shared by two facets", -1);
-  zdef_(zinc, Zrenamepinch, "renamed vertices in a pinched facet", -1);
-  zdef_(zinc, Zrenameall, "renamed vertices shared by multiple facets", -1);
-  zdef_(zinc, Zfindfail, "rename failures due to duplicated ridges", -1);
-  zdef_(zinc, Zdupridge, "  duplicate ridges detected", -1);
-  zdef_(zinc, Zdelridge, "deleted ridges due to renamed vertices", -1);
-  zdef_(zinc, Zdropneighbor, "dropped neighbors due to renamed vertices", -1);
-  zdef_(zinc, Zdropdegen, "degenerate facets due to dropped neighbors", -1);
-  zdef_(zinc, Zdelfacetdup, "  facets deleted because of no neighbors", -1);
-  zdef_(zinc, Zremvertex, "vertices removed from facets due to no ridges", -1);
-  zdef_(zinc, Zremvertexdel, "  deleted", -1);
-  zdef_(zinc, Zintersectnum, "vertex intersections for locating redundant vertices", -1);
-  zdef_(zinc, Zintersectfail, "intersections failed to find a redundant vertex", -1);
-  zdef_(zinc, Zintersect, "intersections found redundant vertices", -1);
-  zdef_(zadd, Zintersecttot, "   ave. number found per vertex", Zintersect);
-  zdef_(zmax, Zintersectmax, "   max. found for a vertex", -1);
-  zdef_(zinc, Zvertexridge, NULL, -1);
-  zdef_(zadd, Zvertexridgetot, "  ave. number of ridges per tested vertex", Zvertexridge);
-  zdef_(zmax, Zvertexridgemax, "  max. number of ridges per tested vertex", -1);
-
-  zdef_(zdoc, Zdoc10, "memory usage statistics(in bytes)", -1);
-  zdef_(zadd, Zmemfacets, "for facets and their normals, neighbor and vertex sets", -1);
-  zdef_(zadd, Zmemvertices, "for vertices and their neighbor sets", -1);
-  zdef_(zadd, Zmempoints, "for input points and outside and coplanar sets",-1);
-  zdef_(zadd, Zmemridges, "for ridges and their vertex sets", -1);
-} /* allstat */
-
-void qh_allstatI(void) {
-  qhstat vridges= qhstat next;
-  zzdef_(zdoc, Zdoc11, "Voronoi ridge statistics", -1);
-  zzdef_(zinc, Zridge, "non-simplicial Voronoi vertices for all ridges", -1);
-  zzdef_(wadd, Wridge, "  ave. distance to ridge", Zridge);
-  zzdef_(wmax, Wridgemax, "  max. distance to ridge", -1);
-  zzdef_(zinc, Zridgemid, "bounded ridges", -1);
-  zzdef_(wadd, Wridgemid, "  ave. distance of midpoint to ridge", Zridgemid);
-  zzdef_(wmax, Wridgemidmax, "  max. distance of midpoint to ridge", -1);
-  zzdef_(zinc, Zridgeok, "bounded ridges with ok normal", -1);
-  zzdef_(wadd, Wridgeok, "  ave. angle to ridge", Zridgeok);
-  zzdef_(wmax, Wridgeokmax, "  max. angle to ridge", -1);
-  zzdef_(zinc, Zridge0, "bounded ridges with near-zero normal", -1);
-  zzdef_(wadd, Wridge0, "  ave. angle to ridge", Zridge0);
-  zzdef_(wmax, Wridge0max, "  max. angle to ridge", -1);
-
-  zdef_(zdoc, Zdoc12, "Triangulation statistics(Qt)", -1);
-  zdef_(zinc, Ztricoplanar, "non-simplicial facets triangulated", -1);
-  zdef_(zadd, Ztricoplanartot, "  ave. new facets created(may be deleted)", Ztricoplanar);
-  zdef_(zmax, Ztricoplanarmax, "  max. new facets created", -1);
-  zdef_(zinc, Ztrinull, "null new facets deleted(duplicated vertex)", -1);
-  zdef_(zinc, Ztrimirror, "mirrored pairs of new facets deleted(same vertices)", -1);
-  zdef_(zinc, Ztridegen, "degenerate new facets in output(same ridge)", -1);
-} /* allstat */
-
-/*---------------------------------
-
-  qh_allstatistics()
-    reset printed flag for all statistics
-*/
-void qh_allstatistics(void) {
-  int i;
-
-  for(i=ZEND; i--; )
-    qhstat printed[i]= False;
-} /* allstatistics */
-
-#if qh_KEEPstatistics
-/*---------------------------------
-
-  qh_collectstatistics()
-    collect statistics for qh.facet_list
-
-*/
-void qh_collectstatistics(void) {
-  facetT *facet, *neighbor, **neighborp;
-  vertexT *vertex, **vertexp;
-  realT dotproduct, dist;
-  int sizneighbors, sizridges, sizvertices, i;
-
-  qh old_randomdist= qh RANDOMdist;
-  qh RANDOMdist= False;
-  zval_(Zmempoints)= qh num_points * qh normal_size +
-                             sizeof(qhT) + sizeof(qhstatT);
-  zval_(Zmemfacets)= 0;
-  zval_(Zmemridges)= 0;
-  zval_(Zmemvertices)= 0;
-  zval_(Zangle)= 0;
-  wval_(Wangle)= 0.0;
-  zval_(Znumridges)= 0;
-  zval_(Znumfacets)= 0;
-  zval_(Znumneighbors)= 0;
-  zval_(Znumvertices)= 0;
-  zval_(Znumvneighbors)= 0;
-  zval_(Znummergetot)= 0;
-  zval_(Znummergemax)= 0;
-  zval_(Zvertices)= qh num_vertices - qh_setsize(qh del_vertices);
-  if (qh MERGING || qh APPROXhull || qh JOGGLEmax < REALmax/2)
-    wmax_(Wmaxoutside, qh max_outside);
-  if (qh MERGING)
-    wmin_(Wminvertex, qh min_vertex);
-  FORALLfacets
-    facet->seen= False;
-  if (qh DELAUNAY) {
-    FORALLfacets {
-      if (facet->upperdelaunay != qh UPPERdelaunay)
-        facet->seen= True; /* remove from angle statistics */
-    }
-  }
-  FORALLfacets {
-    if (facet->visible && qh NEWfacets)
-      continue;
-    sizvertices= qh_setsize(facet->vertices);
-    sizneighbors= qh_setsize(facet->neighbors);
-    sizridges= qh_setsize(facet->ridges);
-    zinc_(Znumfacets);
-    zadd_(Znumvertices, sizvertices);
-    zmax_(Zmaxvertices, sizvertices);
-    zadd_(Znumneighbors, sizneighbors);
-    zmax_(Zmaxneighbors, sizneighbors);
-    zadd_(Znummergetot, facet->nummerge);
-    i= facet->nummerge; /* avoid warnings */
-    zmax_(Znummergemax, i);
-    if (!facet->simplicial) {
-      if (sizvertices == qh hull_dim) {
-        zinc_(Znowsimplicial);
-      }else {
-        zinc_(Znonsimplicial);
-      }
-    }
-    if (sizridges) {
-      zadd_(Znumridges, sizridges);
-      zmax_(Zmaxridges, sizridges);
-    }
-    zadd_(Zmemfacets, sizeof(facetT) + qh normal_size + 2*sizeof(setT)
-       + SETelemsize * (sizneighbors + sizvertices));
-    if (facet->ridges) {
-      zadd_(Zmemridges,
-         sizeof(setT) + SETelemsize * sizridges + sizridges *
-         (sizeof(ridgeT) + sizeof(setT) + SETelemsize * (qh hull_dim-1))/2);
-    }
-    if (facet->outsideset)
-      zadd_(Zmempoints, sizeof(setT) + SETelemsize * qh_setsize(facet->outsideset));
-    if (facet->coplanarset)
-      zadd_(Zmempoints, sizeof(setT) + SETelemsize * qh_setsize(facet->coplanarset));
-    if (facet->seen) /* Delaunay upper envelope */
-      continue;
-    facet->seen= True;
-    FOREACHneighbor_(facet) {
-      if (neighbor == qh_DUPLICATEridge || neighbor == qh_MERGEridge
-          || neighbor->seen || !facet->normal || !neighbor->normal)
-        continue;
-      dotproduct= qh_getangle(facet->normal, neighbor->normal);
-      zinc_(Zangle);
-      wadd_(Wangle, dotproduct);
-      wmax_(Wanglemax, dotproduct)
-      wmin_(Wanglemin, dotproduct)
-    }
-    if (facet->normal) {
-      FOREACHvertex_(facet->vertices) {
-        zinc_(Zdiststat);
-        qh_distplane(vertex->point, facet, &dist);
-        wmax_(Wvertexmax, dist);
-        wmin_(Wvertexmin, dist);
-      }
-    }
-  }
-  FORALLvertices {
-    if (vertex->deleted)
-      continue;
-    zadd_(Zmemvertices, sizeof(vertexT));
-    if (vertex->neighbors) {
-      sizneighbors= qh_setsize(vertex->neighbors);
-      zadd_(Znumvneighbors, sizneighbors);
-      zmax_(Zmaxvneighbors, sizneighbors);
-      zadd_(Zmemvertices, sizeof(vertexT) + SETelemsize * sizneighbors);
-    }
-  }
-  qh RANDOMdist= qh old_randomdist;
-} /* collectstatistics */
-#endif /* qh_KEEPstatistics */
-
-/*---------------------------------
-
-  qh_freestatistics(  )
-    free memory used for statistics
-*/
-void qh_freestatistics(void) {
-
-#if qh_QHpointer
-  qh_free(qh_qhstat);
-  qh_qhstat= NULL;
-#endif
-} /* freestatistics */
-
-/*---------------------------------
-
-  qh_initstatistics(  )
-    allocate and initialize statistics
-
-  notes:
-    uses qh_malloc() instead of qh_memalloc() since mem.c not set up yet
-    NOerrors -- qh_initstatistics can not use qh_errexit(), qh_fprintf, or qh.ferr
-    On first call, only qhmem.ferr is defined.  qh_memalloc is not setup.
-    Also invoked by QhullQh().
-*/
-void qh_initstatistics(void) {
-  int i;
-  realT realx;
-  int intx;
-
-#if qh_QHpointer
-  if(qh_qhstat){  /* qh_initstatistics may be called from Qhull::resetStatistics() */
-      qh_free(qh_qhstat);
-      qh_qhstat= 0;
-  }
-  if (!(qh_qhstat= (qhstatT *)qh_malloc(sizeof(qhstatT)))) {
-    qh_fprintf_stderr(6183, "qhull error (qh_initstatistics): insufficient memory\n");
-    qh_exit(qh_ERRmem);  /* can not use qh_errexit() */
-  }
-#endif
-
-  qhstat next= 0;
-  qh_allstatA();
-  qh_allstatB();
-  qh_allstatC();
-  qh_allstatD();
-  qh_allstatE();
-  qh_allstatE2();
-  qh_allstatF();
-  qh_allstatG();
-  qh_allstatH();
-  qh_allstatI();
-  if (qhstat next > (int)sizeof(qhstat id)) {
-    qh_fprintf(qhmem.ferr, 6184, "qhull error (qh_initstatistics): increase size of qhstat.id[].\n\
-      qhstat.next %d should be <= sizeof(qhstat id) %d\n", qhstat next, (int)sizeof(qhstat id));
-#if 0 /* for locating error, Znumridges should be duplicated */
-    for(i=0; i < ZEND; i++) {
-      int j;
-      for(j=i+1; j < ZEND; j++) {
-        if (qhstat id[i] == qhstat id[j]) {
-          qh_fprintf(qhmem.ferr, 6185, "qhull error (qh_initstatistics): duplicated statistic %d at indices %d and %d\n",
-              qhstat id[i], i, j);
-        }
-      }
-    }
-#endif
-    qh_exit(qh_ERRqhull);  /* can not use qh_errexit() */
-  }
-  qhstat init[zinc].i= 0;
-  qhstat init[zadd].i= 0;
-  qhstat init[zmin].i= INT_MAX;
-  qhstat init[zmax].i= INT_MIN;
-  qhstat init[wadd].r= 0;
-  qhstat init[wmin].r= REALmax;
-  qhstat init[wmax].r= -REALmax;
-  for(i=0; i < ZEND; i++) {
-    if (qhstat type[i] > ZTYPEreal) {
-      realx= qhstat init[(unsigned char)(qhstat type[i])].r;
-      qhstat stats[i].r= realx;
-    }else if (qhstat type[i] != zdoc) {
-      intx= qhstat init[(unsigned char)(qhstat type[i])].i;
-      qhstat stats[i].i= intx;
-    }
-  }
-} /* initstatistics */
-
-/*---------------------------------
-
-  qh_newstats(  )
-    returns True if statistics for zdoc
-
-  returns:
-    next zdoc
-*/
-boolT qh_newstats(int idx, int *nextindex) {
-  boolT isnew= False;
-  int start, i;
-
-  if (qhstat type[qhstat id[idx]] == zdoc)
-    start= idx+1;
-  else
-    start= idx;
-  for(i= start; i < qhstat next && qhstat type[qhstat id[i]] != zdoc; i++) {
-    if (!qh_nostatistic(qhstat id[i]) && !qhstat printed[qhstat id[i]])
-        isnew= True;
-  }
-  *nextindex= i;
-  return isnew;
-} /* newstats */
-
-/*---------------------------------
-
-  qh_nostatistic( index )
-    true if no statistic to print
-*/
-boolT qh_nostatistic(int i) {
-
-  if ((qhstat type[i] > ZTYPEreal
-       &&qhstat stats[i].r == qhstat init[(unsigned char)(qhstat type[i])].r)
-      || (qhstat type[i] < ZTYPEreal
-          &&qhstat stats[i].i == qhstat init[(unsigned char)(qhstat type[i])].i))
-    return True;
-  return False;
-} /* nostatistic */
-
-#if qh_KEEPstatistics
-/*---------------------------------
-
-  qh_printallstatistics( fp, string )
-    print all statistics with header 'string'
-*/
-void qh_printallstatistics(FILE *fp, const char *string) {
-
-  qh_allstatistics();
-  qh_collectstatistics();
-  qh_printstatistics(fp, string);
-  qh_memstatistics(fp);
-}
-
-
-/*---------------------------------
-
-  qh_printstatistics( fp, string )
-    print statistics to a file with header 'string'
-    skips statistics with qhstat.printed[] (reset with qh_allstatistics)
-
-  see:
-    qh_printallstatistics()
-*/
-void qh_printstatistics(FILE *fp, const char *string) {
-  int i, k;
-  realT ave;
-
-  if (qh num_points != qh num_vertices) {
-    wval_(Wpbalance)= 0;
-    wval_(Wpbalance2)= 0;
-  }else
-    wval_(Wpbalance2)= qh_stddev(zval_(Zpbalance), wval_(Wpbalance),
-                                 wval_(Wpbalance2), &ave);
-  wval_(Wnewbalance2)= qh_stddev(zval_(Zprocessed), wval_(Wnewbalance),
-                                 wval_(Wnewbalance2), &ave);
-  qh_fprintf(fp, 9350, "\n\
-%s\n\
- qhull invoked by: %s | %s\n%s with options:\n%s\n", string, qh rbox_command,
-     qh qhull_command, qh_version, qh qhull_options);
-  qh_fprintf(fp, 9351, "\nprecision constants:\n\
- %6.2g max. abs. coordinate in the (transformed) input('Qbd:n')\n\
- %6.2g max. roundoff error for distance computation('En')\n\
- %6.2g max. roundoff error for angle computations\n\
- %6.2g min. distance for outside points ('Wn')\n\
- %6.2g min. distance for visible facets ('Vn')\n\
- %6.2g max. distance for coplanar facets ('Un')\n\
- %6.2g max. facet width for recomputing centrum and area\n\
-",
-  qh MAXabs_coord, qh DISTround, qh ANGLEround, qh MINoutside,
-        qh MINvisible, qh MAXcoplanar, qh WIDEfacet);
-  if (qh KEEPnearinside)
-    qh_fprintf(fp, 9352, "\
- %6.2g max. distance for near-inside points\n", qh NEARinside);
-  if (qh premerge_cos < REALmax/2) qh_fprintf(fp, 9353, "\
- %6.2g max. cosine for pre-merge angle\n", qh premerge_cos);
-  if (qh PREmerge) qh_fprintf(fp, 9354, "\
- %6.2g radius of pre-merge centrum\n", qh premerge_centrum);
-  if (qh postmerge_cos < REALmax/2) qh_fprintf(fp, 9355, "\
- %6.2g max. cosine for post-merge angle\n", qh postmerge_cos);
-  if (qh POSTmerge) qh_fprintf(fp, 9356, "\
- %6.2g radius of post-merge centrum\n", qh postmerge_centrum);
-  qh_fprintf(fp, 9357, "\
- %6.2g max. distance for merging two simplicial facets\n\
- %6.2g max. roundoff error for arithmetic operations\n\
- %6.2g min. denominator for divisions\n\
-  zero diagonal for Gauss: ", qh ONEmerge, REALepsilon, qh MINdenom);
-  for(k=0; k < qh hull_dim; k++)
-    qh_fprintf(fp, 9358, "%6.2e ", qh NEARzero[k]);
-  qh_fprintf(fp, 9359, "\n\n");
-  for(i=0 ; i < qhstat next; )
-    qh_printstats(fp, i, &i);
-} /* printstatistics */
-#endif /* qh_KEEPstatistics */
-
-/*---------------------------------
-
-  qh_printstatlevel( fp, id )
-    print level information for a statistic
-
-  notes:
-    nop if id >= ZEND, printed, or same as initial value
-*/
-void qh_printstatlevel(FILE *fp, int id) {
-#define NULLfield "       "
-
-  if (id >= ZEND || qhstat printed[id])
-    return;
-  if (qhstat type[id] == zdoc) {
-    qh_fprintf(fp, 9360, "%s\n", qhstat doc[id]);
-    return;
-  }
-  if (qh_nostatistic(id) || !qhstat doc[id])
-    return;
-  qhstat printed[id]= True;
-  if (qhstat count[id] != -1
-      && qhstat stats[(unsigned char)(qhstat count[id])].i == 0)
-    qh_fprintf(fp, 9361, " *0 cnt*");
-  else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] == -1)
-    qh_fprintf(fp, 9362, "%7.2g", qhstat stats[id].r);
-  else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] != -1)
-    qh_fprintf(fp, 9363, "%7.2g", qhstat stats[id].r/ qhstat stats[(unsigned char)(qhstat count[id])].i);
-  else if (qhstat type[id] < ZTYPEreal && qhstat count[id] == -1)
-    qh_fprintf(fp, 9364, "%7d", qhstat stats[id].i);
-  else if (qhstat type[id] < ZTYPEreal && qhstat count[id] != -1)
-    qh_fprintf(fp, 9365, "%7.3g", (realT) qhstat stats[id].i / qhstat stats[(unsigned char)(qhstat count[id])].i);
-  qh_fprintf(fp, 9366, " %s\n", qhstat doc[id]);
-} /* printstatlevel */
-
-
-/*---------------------------------
-
-  qh_printstats( fp, index, nextindex )
-    print statistics for a zdoc group
-
-  returns:
-    next zdoc if non-null
-*/
-void qh_printstats(FILE *fp, int idx, int *nextindex) {
-  int j, nexti;
-
-  if (qh_newstats(idx, &nexti)) {
-    qh_fprintf(fp, 9367, "\n");
-    for (j=idx; j--------------------------------
-
-  qh_stddev( num, tot, tot2, ave )
-    compute the standard deviation and average from statistics
-
-    tot2 is the sum of the squares
-  notes:
-    computes r.m.s.:
-      (x-ave)^2
-      == x^2 - 2x tot/num +   (tot/num)^2
-      == tot2 - 2 tot tot/num + tot tot/num
-      == tot2 - tot ave
-*/
-realT qh_stddev(int num, realT tot, realT tot2, realT *ave) {
-  realT stddev;
-
-  *ave= tot/num;
-  stddev= sqrt(tot2/num - *ave * *ave);
-  return stddev;
-} /* stddev */
-
-#endif /* qh_KEEPstatistics */
-
-#if !qh_KEEPstatistics
-void    qh_collectstatistics(void) {}
-void    qh_printallstatistics(FILE *fp, char *string) {};
-void    qh_printstatistics(FILE *fp, char *string) {}
-#endif
-
diff --git a/extern/libqhull/stat.h b/extern/libqhull/stat.h
deleted file mode 100644
index d86fc0a87af3..000000000000
--- a/extern/libqhull/stat.h
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
  ---------------------------------
-
-   stat.h
-     contains all statistics that are collected for qhull
-
-   see qh-stat.htm and stat.c
-
-   Copyright (c) 1993-2015 The Geometry Center.
-   $Id: //main/2015/qhull/src/libqhull/stat.h#4 $$Change: 2062 $
-   $DateTime: 2016/01/17 13:13:18 $$Author: bbarber $
-
-   recompile qhull if you change this file
-
-   Integer statistics are Z* while real statistics are W*.
-
-   define maydebugx to call a routine at every statistic event
-
-*/
-
-#ifndef qhDEFstat
-#define qhDEFstat 1
-
-#include "libqhull.h"
-
-/*---------------------------------
-
-  qh_KEEPstatistics
-    0 turns off statistic gathering (except zzdef/zzinc/zzadd/zzval/wwval)
-*/
-#ifndef qh_KEEPstatistics
-#define qh_KEEPstatistics 1
-#endif
-
-/*---------------------------------
-
-  Zxxx for integers, Wxxx for reals
-
-  notes:
-    be sure that all statistics are defined in stat.c
-      otherwise initialization may core dump
-    can pick up all statistics by:
-      grep '[zw].*_[(][ZW]' *.c >z.x
-    remove trailers with query">-
-    remove leaders with  query-replace-regexp [ ^I]+  (
-*/
-#if qh_KEEPstatistics
-enum qh_statistics {     /* alphabetical after Z/W */
-    Zacoplanar,
-    Wacoplanarmax,
-    Wacoplanartot,
-    Zangle,
-    Wangle,
-    Wanglemax,
-    Wanglemin,
-    Zangletests,
-    Wareatot,
-    Wareamax,
-    Wareamin,
-    Zavoidold,
-    Wavoidoldmax,
-    Wavoidoldtot,
-    Zback0,
-    Zbestcentrum,
-    Zbestdist,
-    Zbestlower,
-    Zbestlowerall,
-    Zbestloweralln,
-    Zbestlowerv,
-    Zcentrumtests,
-    Zcheckpart,
-    Zcomputefurthest,
-    Zconcave,
-    Wconcavemax,
-    Wconcavetot,
-    Zconcaveridges,
-    Zconcaveridge,
-    Zcoplanar,
-    Wcoplanarmax,
-    Wcoplanartot,
-    Zcoplanarangle,
-    Zcoplanarcentrum,
-    Zcoplanarhorizon,
-    Zcoplanarinside,
-    Zcoplanarpart,
-    Zcoplanarridges,
-    Wcpu,
-    Zcyclefacetmax,
-    Zcyclefacettot,
-    Zcyclehorizon,
-    Zcyclevertex,
-    Zdegen,
-    Wdegenmax,
-    Wdegentot,
-    Zdegenvertex,
-    Zdelfacetdup,
-    Zdelridge,
-    Zdelvertextot,
-    Zdelvertexmax,
-    Zdetsimplex,
-    Zdistcheck,
-    Zdistconvex,
-    Zdistgood,
-    Zdistio,
-    Zdistplane,
-    Zdiststat,
-    Zdistvertex,
-    Zdistzero,
-    Zdoc1,
-    Zdoc2,
-    Zdoc3,
-    Zdoc4,
-    Zdoc5,
-    Zdoc6,
-    Zdoc7,
-    Zdoc8,
-    Zdoc9,
-    Zdoc10,
-    Zdoc11,
-    Zdoc12,
-    Zdropdegen,
-    Zdropneighbor,
-    Zdupflip,
-    Zduplicate,
-    Wduplicatemax,
-    Wduplicatetot,
-    Zdupridge,
-    Zdupsame,
-    Zflipped,
-    Wflippedmax,
-    Wflippedtot,
-    Zflippedfacets,
-    Zfindbest,
-    Zfindbestmax,
-    Zfindbesttot,
-    Zfindcoplanar,
-    Zfindfail,
-    Zfindhorizon,
-    Zfindhorizonmax,
-    Zfindhorizontot,
-    Zfindjump,
-    Zfindnew,
-    Zfindnewmax,
-    Zfindnewtot,
-    Zfindnewjump,
-    Zfindnewsharp,
-    Zgauss0,
-    Zgoodfacet,
-    Zhashlookup,
-    Zhashridge,
-    Zhashridgetest,
-    Zhashtests,
-    Zinsidevisible,
-    Zintersect,
-    Zintersectfail,
-    Zintersectmax,
-    Zintersectnum,
-    Zintersecttot,
-    Zmaxneighbors,
-    Wmaxout,
-    Wmaxoutside,
-    Zmaxridges,
-    Zmaxvertex,
-    Zmaxvertices,
-    Zmaxvneighbors,
-    Zmemfacets,
-    Zmempoints,
-    Zmemridges,
-    Zmemvertices,
-    Zmergeflipdup,
-    Zmergehorizon,
-    Zmergeinittot,
-    Zmergeinitmax,
-    Zmergeinittot2,
-    Zmergeintohorizon,
-    Zmergenew,
-    Zmergesettot,
-    Zmergesetmax,
-    Zmergesettot2,
-    Zmergesimplex,
-    Zmergevertex,
-    Wmindenom,
-    Wminvertex,
-    Zminnorm,
-    Zmultiridge,
-    Znearlysingular,
-    Zneighbor,
-    Wnewbalance,
-    Wnewbalance2,
-    Znewfacettot,
-    Znewfacetmax,
-    Znewvertex,
-    Wnewvertex,
-    Wnewvertexmax,
-    Znoarea,
-    Znonsimplicial,
-    Znowsimplicial,
-    Znotgood,
-    Znotgoodnew,
-    Znotmax,
-    Znumfacets,
-    Znummergemax,
-    Znummergetot,
-    Znumneighbors,
-    Znumridges,
-    Znumvertices,
-    Znumvisibility,
-    Znumvneighbors,
-    Zonehorizon,
-    Zpartangle,
-    Zpartcoplanar,
-    Zpartflip,
-    Zparthorizon,
-    Zpartinside,
-    Zpartition,
-    Zpartitionall,
-    Zpartnear,
-    Zpbalance,
-    Wpbalance,
-    Wpbalance2,
-    Zpostfacets,
-    Zpremergetot,
-    Zprocessed,
-    Zremvertex,
-    Zremvertexdel,
-    Zrenameall,
-    Zrenamepinch,
-    Zrenameshare,
-    Zretry,
-    Wretrymax,
-    Zridge,
-    Wridge,
-    Wridgemax,
-    Zridge0,
-    Wridge0,
-    Wridge0max,
-    Zridgemid,
-    Wridgemid,
-    Wridgemidmax,
-    Zridgeok,
-    Wridgeok,
-    Wridgeokmax,
-    Zsearchpoints,
-    Zsetplane,
-    Ztestvneighbor,
-    Ztotcheck,
-    Ztothorizon,
-    Ztotmerge,
-    Ztotpartcoplanar,
-    Ztotpartition,
-    Ztotridges,
-    Ztotvertices,
-    Ztotvisible,
-    Ztricoplanar,
-    Ztricoplanarmax,
-    Ztricoplanartot,
-    Ztridegen,
-    Ztrimirror,
-    Ztrinull,
-    Wvertexmax,
-    Wvertexmin,
-    Zvertexridge,
-    Zvertexridgetot,
-    Zvertexridgemax,
-    Zvertices,
-    Zvisfacettot,
-    Zvisfacetmax,
-    Zvisit,
-    Zvisit2max,
-    Zvisvertextot,
-    Zvisvertexmax,
-    Zvvisit,
-    Zvvisit2max,
-    Zwidefacet,
-    Zwidevertices,
-    ZEND};
-
-/*---------------------------------
-
-  Zxxx/Wxxx statistics that remain defined if qh_KEEPstatistics=0
-
-  notes:
-    be sure to use zzdef, zzinc, etc. with these statistics (no double checking!)
-*/
-#else
-enum qh_statistics {     /* for zzdef etc. macros */
-  Zback0,
-  Zbestdist,
-  Zcentrumtests,
-  Zcheckpart,
-  Zconcaveridges,
-  Zcoplanarhorizon,
-  Zcoplanarpart,
-  Zcoplanarridges,
-  Zcyclefacettot,
-  Zcyclehorizon,
-  Zdelvertextot,
-  Zdistcheck,
-  Zdistconvex,
-  Zdistzero,
-  Zdoc1,
-  Zdoc2,
-  Zdoc3,
-  Zdoc11,
-  Zflippedfacets,
-  Zgauss0,
-  Zminnorm,
-  Zmultiridge,
-  Znearlysingular,
-  Wnewvertexmax,
-  Znumvisibility,
-  Zpartcoplanar,
-  Zpartition,
-  Zpartitionall,
-  Zprocessed,
-  Zretry,
-  Zridge,
-  Wridge,
-  Wridgemax,
-  Zridge0,
-  Wridge0,
-  Wridge0max,
-  Zridgemid,
-  Wridgemid,
-  Wridgemidmax,
-  Zridgeok,
-  Wridgeok,
-  Wridgeokmax,
-  Zsetplane,
-  Ztotcheck,
-  Ztotmerge,
-    ZEND};
-#endif
-
-/*---------------------------------
-
-  ztype
-    the type of a statistic sets its initial value.
-
-  notes:
-    The type should be the same as the macro for collecting the statistic
-*/
-enum ztypes {zdoc,zinc,zadd,zmax,zmin,ZTYPEreal,wadd,wmax,wmin,ZTYPEend};
-
-/*========== macros and constants =============*/
-
-/*----------------------------------
-
-  MAYdebugx
-    define as maydebug() to be called frequently for error trapping
-*/
-#define MAYdebugx
-
-/*----------------------------------
-
-  zzdef_, zdef_( type, name, doc, -1)
-    define a statistic (assumes 'qhstat.next= 0;')
-
-  zdef_( type, name, doc, count)
-    define an averaged statistic
-    printed as name/count
-*/
-#define zzdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
-   qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
-#if qh_KEEPstatistics
-#define zdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
-   qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
-#else
-#define zdef_(type,name,doc,count)
-#endif
-
-/*----------------------------------
-
-  zzinc_( name ), zinc_( name)
-    increment an integer statistic
-*/
-#define zzinc_(id) {MAYdebugx; qhstat stats[id].i++;}
-#if qh_KEEPstatistics
-#define zinc_(id) {MAYdebugx; qhstat stats[id].i++;}
-#else
-#define zinc_(id) {}
-#endif
-
-/*----------------------------------
-
-  zzadd_( name, value ), zadd_( name, value ), wadd_( name, value )
-    add value to an integer or real statistic
-*/
-#define zzadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
-#define wwadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
-#if qh_KEEPstatistics
-#define zadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
-#define wadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
-#else
-#define zadd_(id, val) {}
-#define wadd_(id, val) {}
-#endif
-
-/*----------------------------------
-
-  zzval_( name ), zval_( name ), wwval_( name )
-    set or return value of a statistic
-*/
-#define zzval_(id) ((qhstat stats[id]).i)
-#define wwval_(id) ((qhstat stats[id]).r)
-#if qh_KEEPstatistics
-#define zval_(id) ((qhstat stats[id]).i)
-#define wval_(id) ((qhstat stats[id]).r)
-#else
-#define zval_(id) qhstat tempi
-#define wval_(id) qhstat tempr
-#endif
-
-/*----------------------------------
-
-  zmax_( id, val ), wmax_( id, value )
-    maximize id with val
-*/
-#define wwmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
-#if qh_KEEPstatistics
-#define zmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].i,(val));}
-#define wmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
-#else
-#define zmax_(id, val) {}
-#define wmax_(id, val) {}
-#endif
-
-/*----------------------------------
-
-  zmin_( id, val ), wmin_( id, value )
-    minimize id with val
-*/
-#if qh_KEEPstatistics
-#define zmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].i,(val));}
-#define wmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].r,(val));}
-#else
-#define zmin_(id, val) {}
-#define wmin_(id, val) {}
-#endif
-
-/*================== stat.h types ==============*/
-
-
-/*----------------------------------
-
-  intrealT
-    union of integer and real, used for statistics
-*/
-typedef union intrealT intrealT;    /* union of int and realT */
-union intrealT {
-    int i;
-    realT r;
-};
-
-/*----------------------------------
-
-  qhstat
-    global data structure for statistics, similar to qh and qhrbox
-
-  notes:
-   access to qh_qhstat is via the "qhstat" macro.  There are two choices
-   qh_QHpointer = 1     access globals via a pointer
-                        enables qh_saveqhull() and qh_restoreqhull()
-                = 0     qh_qhstat is a static data structure
-                        only one instance of qhull() can be active at a time
-                        default value
-   qh_QHpointer is defined in libqhull.h
-   qh_QHpointer_dllimport and qh_dllimport define qh_qh as __declspec(dllimport) [libqhull.h]
-
-   allocated in stat.c using qh_malloc()
-*/
-#ifndef DEFqhstatT
-#define DEFqhstatT 1
-typedef struct qhstatT qhstatT;
-#endif
-
-#if qh_QHpointer_dllimport
-#define qhstat qh_qhstat->
-__declspec(dllimport) extern qhstatT *qh_qhstat;
-#elif qh_QHpointer
-#define qhstat qh_qhstat->
-extern qhstatT *qh_qhstat;
-#elif qh_dllimport
-#define qhstat qh_qhstat.
-__declspec(dllimport) extern qhstatT qh_qhstat;
-#else
-#define qhstat qh_qhstat.
-extern qhstatT qh_qhstat;
-#endif
-struct qhstatT {
-  intrealT   stats[ZEND];     /* integer and real statistics */
-  unsigned   char id[ZEND+10]; /* id's in print order */
-  const char *doc[ZEND];       /* array of documentation strings */
-  short int  count[ZEND];     /* -1 if none, else index of count to use */
-  char       type[ZEND];      /* type, see ztypes above */
-  char       printed[ZEND];   /* true, if statistic has been printed */
-  intrealT   init[ZTYPEend];  /* initial values by types, set initstatistics */
-
-  int        next;            /* next index for zdef_ */
-  int        precision;       /* index for precision problems */
-  int        vridges;         /* index for Voronoi ridges */
-  int        tempi;
-  realT      tempr;
-};
-
-/*========== function prototypes ===========*/
-
-void    qh_allstatA(void);
-void    qh_allstatB(void);
-void    qh_allstatC(void);
-void    qh_allstatD(void);
-void    qh_allstatE(void);
-void    qh_allstatE2(void);
-void    qh_allstatF(void);
-void    qh_allstatG(void);
-void    qh_allstatH(void);
-void    qh_allstatI(void);
-void    qh_allstatistics(void);
-void    qh_collectstatistics(void);
-void    qh_freestatistics(void);
-void    qh_initstatistics(void);
-boolT   qh_newstats(int idx, int *nextindex);
-boolT   qh_nostatistic(int i);
-void    qh_printallstatistics(FILE *fp, const char *string);
-void    qh_printstatistics(FILE *fp, const char *string);
-void    qh_printstatlevel(FILE *fp, int id);
-void    qh_printstats(FILE *fp, int idx, int *nextindex);
-realT   qh_stddev(int num, realT tot, realT tot2, realT *ave);
-
-#endif   /* qhDEFstat */
diff --git a/extern/libqhull/user.c b/extern/libqhull/user.c
deleted file mode 100644
index 82e2c1744b56..000000000000
--- a/extern/libqhull/user.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
  ---------------------------------
-
-   user.c
-   user redefinable functions
-
-   see user2.c for qh_fprintf, qh_malloc, qh_free
-
-   see README.txt  see COPYING.txt for copyright information.
-
-   see libqhull.h for data structures, macros, and user-callable functions.
-
-   see user_eg.c, user_eg2.c, and unix.c for examples.
-
-   see user.h for user-definable constants
-
-      use qh_NOmem in mem.h to turn off memory management
-      use qh_NOmerge in user.h to turn off facet merging
-      set qh_KEEPstatistics in user.h to 0 to turn off statistics
-
-   This is unsupported software.  You're welcome to make changes,
-   but you're on your own if something goes wrong.  Use 'Tc' to
-   check frequently.  Usually qhull will report an error if
-   a data structure becomes inconsistent.  If so, it also reports
-   the last point added to the hull, e.g., 102.  You can then trace
-   the execution of qhull with "T4P102".
-
-   Please report any errors that you fix to qhull@qhull.org
-
-   Qhull-template is a template for calling qhull from within your application
-
-   if you recompile and load this module, then user.o will not be loaded
-   from qhull.a
-
-   you can add additional quick allocation sizes in qh_user_memsizes
-
-   if the other functions here are redefined to not use qh_print...,
-   then io.o will not be loaded from qhull.a.  See user_eg.c for an
-   example.  We recommend keeping io.o for the extra debugging
-   information it supplies.
-*/
-
-#include "qhull_a.h"
-
-#include 
-
-/*---------------------------------
-
-  Qhull-template
-    Template for calling qhull from inside your program
-
-  returns:
-    exit code(see qh_ERR... in libqhull.h)
-    all memory freed
-
-  notes:
-    This can be called any number of times.
-*/
-#if 0
-{
-  int dim;                  /* dimension of points */
-  int numpoints;            /* number of points */
-  coordT *points;           /* array of coordinates for each point */
-  boolT ismalloc;           /* True if qhull should free points in qh_freeqhull() or reallocation */
-  char flags[]= "qhull Tv"; /* option flags for qhull, see qh_opt.htm */
-  FILE *outfile= stdout;    /* output from qh_produce_output()
-                               use NULL to skip qh_produce_output() */
-  FILE *errfile= stderr;    /* error messages from qhull code */
-  int exitcode;             /* 0 if no error from qhull */
-  facetT *facet;            /* set by FORALLfacets */
-  int curlong, totlong;     /* memory remaining after qh_memfreeshort */
-
-  QHULL_LIB_CHECK /* Check for compatible library */
-
-#if qh_QHpointer  /* see user.h */
-  if (qh_qh){ /* should be NULL */
-      qh_printf_stderr(6238, "Qhull link error.  The global variable qh_qh was not initialized\n\
-              to NULL by global.c.  Please compile this program with -Dqh_QHpointer_dllimport\n\
-              as well as -Dqh_QHpointer, or use libqhullstatic, or use a different tool chain.\n\n");
-      exit(1);
-  }
-#endif
-
-  /* initialize dim, numpoints, points[], ismalloc here */
-  exitcode= qh_new_qhull(dim, numpoints, points, ismalloc,
-                      flags, outfile, errfile);
-  if (!exitcode) {                  /* if no error */
-    /* 'qh facet_list' contains the convex hull */
-    FORALLfacets {
-       /* ... your code ... */
-    }
-  }
-  qh_freeqhull(!qh_ALL);
-  qh_memfreeshort(&curlong, &totlong);
-  if (curlong || totlong)
-    qh_fprintf(errfile, 7068, "qhull internal warning (main): did not free %d bytes of long memory(%d pieces)\n", totlong, curlong);
-}
-#endif
-
-/*---------------------------------
-
-  qh_new_qhull( dim, numpoints, points, ismalloc, qhull_cmd, outfile, errfile )
-    build new qhull data structure and return exitcode (0 if no errors)
-    if numpoints=0 and points=NULL, initializes qhull
-
-  notes:
-    do not modify points until finished with results.
-      The qhull data structure contains pointers into the points array.
-    do not call qhull functions before qh_new_qhull().
-      The qhull data structure is not initialized until qh_new_qhull().
-
-    Default errfile is stderr, outfile may be null
-    qhull_cmd must start with "qhull "
-    projects points to a new point array for Delaunay triangulations ('d' and 'v')
-    transforms points into a new point array for halfspace intersection ('H')
-
-
-  To allow multiple, concurrent calls to qhull()
-    - set qh_QHpointer in user.h
-    - use qh_save_qhull and qh_restore_qhull to swap the global data structure between calls.
-    - use qh_freeqhull(qh_ALL) to free intermediate convex hulls
-
-  see:
-      Qhull-template at the beginning of this file.
-      An example of using qh_new_qhull is user_eg.c
-*/
-int qh_new_qhull(int dim, int numpoints, coordT *points, boolT ismalloc,
-                char *qhull_cmd, FILE *outfile, FILE *errfile) {
-  int exitcode, hulldim;
-  boolT new_ismalloc;
-  static boolT firstcall = True;
-  coordT *new_points;
-
-  if(!errfile){
-      errfile= stderr;
-  }
-  if (firstcall) {
-    qh_meminit(errfile);
-    firstcall= False;
-  } else {
-    qh_memcheck();
-  }
-  if (strncmp(qhull_cmd, "qhull ", (size_t)6)) {
-    qh_fprintf(errfile, 6186, "qhull error (qh_new_qhull): start qhull_cmd argument with \"qhull \"\n");
-    return qh_ERRinput;
-  }
-  qh_initqhull_start(NULL, outfile, errfile);
-  if(numpoints==0 && points==NULL){
-      trace1((qh ferr, 1047, "qh_new_qhull: initialize Qhull\n"));
-      return 0;
-  }
-  trace1((qh ferr, 1044, "qh_new_qhull: build new Qhull for %d %d-d points with %s\n", numpoints, dim, qhull_cmd));
-  exitcode = setjmp(qh errexit);
-  if (!exitcode)
-  {
-    qh NOerrexit = False;
-    qh_initflags(qhull_cmd);
-    if (qh DELAUNAY)
-      qh PROJECTdelaunay= True;
-    if (qh HALFspace) {
-      /* points is an array of halfspaces,
-         the last coordinate of each halfspace is its offset */
-      hulldim= dim-1;
-      qh_setfeasible(hulldim);
-      new_points= qh_sethalfspace_all(dim, numpoints, points, qh feasible_point);
-      new_ismalloc= True;
-      if (ismalloc)
-        qh_free(points);
-    }else {
-      hulldim= dim;
-      new_points= points;
-      new_ismalloc= ismalloc;
-    }
-    qh_init_B(new_points, numpoints, hulldim, new_ismalloc);
-    qh_qhull();
-    qh_check_output();
-    if (outfile) {
-      qh_produce_output();
-    }else {
-      qh_prepare_output();
-    }
-    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
-      qh_check_points();
-  }
-  qh NOerrexit = True;
-  return exitcode;
-} /* new_qhull */
-
-/*---------------------------------
-
-  qh_errexit( exitcode, facet, ridge )
-    report and exit from an error
-    report facet and ridge if non-NULL
-    reports useful information such as last point processed
-    set qh.FORCEoutput to print neighborhood of facet
-
-  see:
-    qh_errexit2() in libqhull.c for printing 2 facets
-
-  design:
-    check for error within error processing
-    compute qh.hulltime
-    print facet and ridge (if any)
-    report commandString, options, qh.furthest_id
-    print summary and statistics (including precision statistics)
-    if qh_ERRsingular
-      print help text for singular data set
-    exit program via long jump (if defined) or exit()
-*/
-void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) {
-
-  if (qh ERREXITcalled) {
-    qh_fprintf(qh ferr, 8126, "\nqhull error while processing previous error.  Exit program\n");
-    qh_exit(qh_ERRqhull);
-  }
-  qh ERREXITcalled= True;
-  if (!qh QHULLfinished)
-    qh hulltime= qh_CPUclock - qh hulltime;
-  qh_errprint("ERRONEOUS", facet, NULL, ridge, NULL);
-  qh_fprintf(qh ferr, 8127, "\nWhile executing: %s | %s\n", qh rbox_command, qh qhull_command);
-  qh_fprintf(qh ferr, 8128, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
-  if (qh furthest_id >= 0) {
-    qh_fprintf(qh ferr, 8129, "Last point added to hull was p%d.", qh furthest_id);
-    if (zzval_(Ztotmerge))
-      qh_fprintf(qh ferr, 8130, "  Last merge was #%d.", zzval_(Ztotmerge));
-    if (qh QHULLfinished)
-      qh_fprintf(qh ferr, 8131, "\nQhull has finished constructing the hull.");
-    else if (qh POSTmerging)
-      qh_fprintf(qh ferr, 8132, "\nQhull has started post-merging.");
-    qh_fprintf(qh ferr, 8133, "\n");
-  }
-  if (qh FORCEoutput && (qh QHULLfinished || (!facet && !ridge)))
-    qh_produce_output();
-  else if (exitcode != qh_ERRinput) {
-    if (exitcode != qh_ERRsingular && zzval_(Zsetplane) > qh hull_dim+1) {
-      qh_fprintf(qh ferr, 8134, "\nAt error exit:\n");
-      qh_printsummary(qh ferr);
-      if (qh PRINTstatistics) {
-        qh_collectstatistics();
-        qh_printstatistics(qh ferr, "at error exit");
-        qh_memstatistics(qh ferr);
-      }
-    }
-    if (qh PRINTprecision)
-      qh_printstats(qh ferr, qhstat precision, NULL);
-  }
-  if (!exitcode)
-    exitcode= qh_ERRqhull;
-  else if (exitcode == qh_ERRsingular)
-    qh_printhelp_singular(qh ferr);
-  else if (exitcode == qh_ERRprec && !qh PREmerge)
-    qh_printhelp_degenerate(qh ferr);
-  if (qh NOerrexit) {
-    qh_fprintf(qh ferr, 6187, "qhull error while ending program, or qh->NOerrexit not cleared after setjmp(). Exit program with error.\n");
-    qh_exit(qh_ERRqhull);
-  }
-  qh ERREXITcalled= False;
-  qh NOerrexit= True;
-  qh ALLOWrestart= False;  /* longjmp will undo qh_build_withrestart */
-  longjmp(qh errexit, exitcode);
-} /* errexit */
-
-
-/*---------------------------------
-
-  qh_errprint( fp, string, atfacet, otherfacet, atridge, atvertex )
-    prints out the information of facets and ridges to fp
-    also prints neighbors and geomview output
-
-  notes:
-    except for string, any parameter may be NULL
-*/
-void qh_errprint(const char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
-  int i;
-
-  if (atfacet) {
-    qh_fprintf(qh ferr, 8135, "%s FACET:\n", string);
-    qh_printfacet(qh ferr, atfacet);
-  }
-  if (otherfacet) {
-    qh_fprintf(qh ferr, 8136, "%s OTHER FACET:\n", string);
-    qh_printfacet(qh ferr, otherfacet);
-  }
-  if (atridge) {
-    qh_fprintf(qh ferr, 8137, "%s RIDGE:\n", string);
-    qh_printridge(qh ferr, atridge);
-    if (atridge->top && atridge->top != atfacet && atridge->top != otherfacet)
-      qh_printfacet(qh ferr, atridge->top);
-    if (atridge->bottom
-        && atridge->bottom != atfacet && atridge->bottom != otherfacet)
-      qh_printfacet(qh ferr, atridge->bottom);
-    if (!atfacet)
-      atfacet= atridge->top;
-    if (!otherfacet)
-      otherfacet= otherfacet_(atridge, atfacet);
-  }
-  if (atvertex) {
-    qh_fprintf(qh ferr, 8138, "%s VERTEX:\n", string);
-    qh_printvertex(qh ferr, atvertex);
-  }
-  if (qh fout && qh FORCEoutput && atfacet && !qh QHULLfinished && !qh IStracing) {
-    qh_fprintf(qh ferr, 8139, "ERRONEOUS and NEIGHBORING FACETS to output\n");
-    for (i=0; i < qh_PRINTEND; i++)  /* use fout for geomview output */
-      qh_printneighborhood(qh fout, qh PRINTout[i], atfacet, otherfacet,
-                            !qh_ALL);
-  }
-} /* errprint */
-
-
-/*---------------------------------
-
-  qh_printfacetlist( fp, facetlist, facets, printall )
-    print all fields for a facet list and/or set of facets to fp
-    if !printall,
-      only prints good facets
-
-  notes:
-    also prints all vertices
-*/
-void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall) {
-  facetT *facet, **facetp;
-
-  qh_printbegin(qh ferr, qh_PRINTfacets, facetlist, facets, printall);
-  FORALLfacet_(facetlist)
-    qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
-  FOREACHfacet_(facets)
-    qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
-  qh_printend(qh ferr, qh_PRINTfacets, facetlist, facets, printall);
-} /* printfacetlist */
-
-
-/*---------------------------------
-
-  qh_printhelp_degenerate( fp )
-    prints descriptive message for precision error
-
-  notes:
-    no message if qh_QUICKhelp
-*/
-void qh_printhelp_degenerate(FILE *fp) {
-
-  if (qh MERGEexact || qh PREmerge || qh JOGGLEmax < REALmax/2)
-    qh_fprintf(fp, 9368, "\n\
-A Qhull error has occurred.  Qhull should have corrected the above\n\
-precision error.  Please send the input and all of the output to\n\
-qhull_bug@qhull.org\n");
-  else if (!qh_QUICKhelp) {
-    qh_fprintf(fp, 9369, "\n\
-Precision problems were detected during construction of the convex hull.\n\
-This occurs because convex hull algorithms assume that calculations are\n\
-exact, but floating-point arithmetic has roundoff errors.\n\
-\n\
-To correct for precision problems, do not use 'Q0'.  By default, Qhull\n\
-selects 'C-0' or 'Qx' and merges non-convex facets.  With option 'QJ',\n\
-Qhull joggles the input to prevent precision problems.  See \"Imprecision\n\
-in Qhull\" (qh-impre.htm).\n\
-\n\
-If you use 'Q0', the output may include\n\
-coplanar ridges, concave ridges, and flipped facets.  In 4-d and higher,\n\
-Qhull may produce a ridge with four neighbors or two facets with the same \n\
-vertices.  Qhull reports these events when they occur.  It stops when a\n\
-concave ridge, flipped facet, or duplicate facet occurs.\n");
-#if REALfloat
-    qh_fprintf(fp, 9370, "\
-\n\
-Qhull is currently using single precision arithmetic.  The following\n\
-will probably remove the precision problems:\n\
-  - recompile qhull for realT precision(#define REALfloat 0 in user.h).\n");
-#endif
-    if (qh DELAUNAY && !qh SCALElast && qh MAXabs_coord > 1e4)
-      qh_fprintf(fp, 9371, "\
-\n\
-When computing the Delaunay triangulation of coordinates > 1.0,\n\
-  - use 'Qbb' to scale the last coordinate to [0,m] (max previous coordinate)\n");
-    if (qh DELAUNAY && !qh ATinfinity)
-      qh_fprintf(fp, 9372, "\
-When computing the Delaunay triangulation:\n\
-  - use 'Qz' to add a point at-infinity.  This reduces precision problems.\n");
-
-    qh_fprintf(fp, 9373, "\
-\n\
-If you need triangular output:\n\
-  - use option 'Qt' to triangulate the output\n\
-  - use option 'QJ' to joggle the input points and remove precision errors\n\
-  - use option 'Ft'.  It triangulates non-simplicial facets with added points.\n\
-\n\
-If you must use 'Q0',\n\
-try one or more of the following options.  They can not guarantee an output.\n\
-  - use 'QbB' to scale the input to a cube.\n\
-  - use 'Po' to produce output and prevent partitioning for flipped facets\n\
-  - use 'V0' to set min. distance to visible facet as 0 instead of roundoff\n\
-  - use 'En' to specify a maximum roundoff error less than %2.2g.\n\
-  - options 'Qf', 'Qbb', and 'QR0' may also help\n",
-               qh DISTround);
-    qh_fprintf(fp, 9374, "\
-\n\
-To guarantee simplicial output:\n\
-  - use option 'Qt' to triangulate the output\n\
-  - use option 'QJ' to joggle the input points and remove precision errors\n\
-  - use option 'Ft' to triangulate the output by adding points\n\
-  - use exact arithmetic (see \"Imprecision in Qhull\", qh-impre.htm)\n\
-");
-  }
-} /* printhelp_degenerate */
-
-
-/*---------------------------------
-
-  qh_printhelp_narrowhull( minangle )
-    Warn about a narrow hull
-
-  notes:
-    Alternatively, reduce qh_WARNnarrow in user.h
-
-*/
-void qh_printhelp_narrowhull(FILE *fp, realT minangle) {
-
-    qh_fprintf(fp, 9375, "qhull precision warning: \n\
-The initial hull is narrow (cosine of min. angle is %.16f).\n\
-Is the input lower dimensional (e.g., on a plane in 3-d)?  Qhull may\n\
-produce a wide facet.  Options 'QbB' (scale to unit box) or 'Qbb' (scale\n\
-last coordinate) may remove this warning.  Use 'Pp' to skip this warning.\n\
-See 'Limitations' in qh-impre.htm.\n",
-          -minangle);   /* convert from angle between normals to angle between facets */
-} /* printhelp_narrowhull */
-
-/*---------------------------------
-
-  qh_printhelp_singular( fp )
-    prints descriptive message for singular input
-*/
-void qh_printhelp_singular(FILE *fp) {
-  facetT *facet;
-  vertexT *vertex, **vertexp;
-  realT min, max, *coord, dist;
-  int i,k;
-
-  qh_fprintf(fp, 9376, "\n\
-The input to qhull appears to be less than %d dimensional, or a\n\
-computation has overflowed.\n\n\
-Qhull could not construct a clearly convex simplex from points:\n",
-           qh hull_dim);
-  qh_printvertexlist(fp, "", qh facet_list, NULL, qh_ALL);
-  if (!qh_QUICKhelp)
-    qh_fprintf(fp, 9377, "\n\
-The center point is coplanar with a facet, or a vertex is coplanar\n\
-with a neighboring facet.  The maximum round off error for\n\
-computing distances is %2.2g.  The center point, facets and distances\n\
-to the center point are as follows:\n\n", qh DISTround);
-  qh_printpointid(fp, "center point", qh hull_dim, qh interior_point, qh_IDunknown);
-  qh_fprintf(fp, 9378, "\n");
-  FORALLfacets {
-    qh_fprintf(fp, 9379, "facet");
-    FOREACHvertex_(facet->vertices)
-      qh_fprintf(fp, 9380, " p%d", qh_pointid(vertex->point));
-    zinc_(Zdistio);
-    qh_distplane(qh interior_point, facet, &dist);
-    qh_fprintf(fp, 9381, " distance= %4.2g\n", dist);
-  }
-  if (!qh_QUICKhelp) {
-    if (qh HALFspace)
-      qh_fprintf(fp, 9382, "\n\
-These points are the dual of the given halfspaces.  They indicate that\n\
-the intersection is degenerate.\n");
-    qh_fprintf(fp, 9383,"\n\
-These points either have a maximum or minimum x-coordinate, or\n\
-they maximize the determinant for k coordinates.  Trial points\n\
-are first selected from points that maximize a coordinate.\n");
-    if (qh hull_dim >= qh_INITIALmax)
-      qh_fprintf(fp, 9384, "\n\
-Because of the high dimension, the min x-coordinate and max-coordinate\n\
-points are used if the determinant is non-zero.  Option 'Qs' will\n\
-do a better, though much slower, job.  Instead of 'Qs', you can change\n\
-the points by randomly rotating the input with 'QR0'.\n");
-  }
-  qh_fprintf(fp, 9385, "\nThe min and max coordinates for each dimension are:\n");
-  for (k=0; k < qh hull_dim; k++) {
-    min= REALmax;
-    max= -REALmin;
-    for (i=qh num_points, coord= qh first_point+k; i--; coord += qh hull_dim) {
-      maximize_(max, *coord);
-      minimize_(min, *coord);
-    }
-    qh_fprintf(fp, 9386, "  %d:  %8.4g  %8.4g  difference= %4.4g\n", k, min, max, max-min);
-  }
-  if (!qh_QUICKhelp) {
-    qh_fprintf(fp, 9387, "\n\
-If the input should be full dimensional, you have several options that\n\
-may determine an initial simplex:\n\
-  - use 'QJ'  to joggle the input and make it full dimensional\n\
-  - use 'QbB' to scale the points to the unit cube\n\
-  - use 'QR0' to randomly rotate the input for different maximum points\n\
-  - use 'Qs'  to search all points for the initial simplex\n\
-  - use 'En'  to specify a maximum roundoff error less than %2.2g.\n\
-  - trace execution with 'T3' to see the determinant for each point.\n",
-                     qh DISTround);
-#if REALfloat
-    qh_fprintf(fp, 9388, "\
-  - recompile qhull for realT precision(#define REALfloat 0 in libqhull.h).\n");
-#endif
-    qh_fprintf(fp, 9389, "\n\
-If the input is lower dimensional:\n\
-  - use 'QJ' to joggle the input and make it full dimensional\n\
-  - use 'Qbk:0Bk:0' to delete coordinate k from the input.  You should\n\
-    pick the coordinate with the least range.  The hull will have the\n\
-    correct topology.\n\
-  - determine the flat containing the points, rotate the points\n\
-    into a coordinate plane, and delete the other coordinates.\n\
-  - add one or more points to make the input full dimensional.\n\
-");
-  }
-} /* printhelp_singular */
-
-/*---------------------------------
-
-  qh_user_memsizes()
-    allocate up to 10 additional, quick allocation sizes
-
-  notes:
-    increase maximum number of allocations in qh_initqhull_mem()
-*/
-void qh_user_memsizes(void) {
-
-  /* qh_memsize(size); */
-} /* user_memsizes */
-
-
diff --git a/extern/libqhull/user.h b/extern/libqhull/user.h
deleted file mode 100644
index 523aa7b4e842..000000000000
--- a/extern/libqhull/user.h
+++ /dev/null
@@ -1,909 +0,0 @@
-/*
  ---------------------------------
-
-   user.h
-   user redefinable constants
-
-   for each source file, user.h is included first
-   see qh-user.htm.  see COPYING for copyright information.
-
-   See user.c for sample code.
-
-   before reading any code, review libqhull.h for data structure definitions and
-   the "qh" macro.
-
-Sections:
-   ============= qhull library constants ======================
-   ============= data types and configuration macros ==========
-   ============= performance related constants ================
-   ============= memory constants =============================
-   ============= joggle constants =============================
-   ============= conditional compilation ======================
-   ============= -merge constants- ============================
-
-Code flags --
-  NOerrors -- the code does not call qh_errexit()
-  WARN64 -- the code may be incompatible with 64-bit pointers
-
-*/
-
-#include 
-
-#ifndef qhDEFuser
-#define qhDEFuser 1
-
-/* Derived from Qt's corelib/global/qglobal.h */
-#if !defined(SAG_COM) && !defined(__CYGWIN__) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
-#   define QHULL_OS_WIN
-#elif defined(__MWERKS__) && defined(__INTEL__) /* Metrowerks discontinued before the release of Intel Macs */
-#   define QHULL_OS_WIN
-#endif
-/*============================================================*/
-/*============= qhull library constants ======================*/
-/*============================================================*/
-
-/*----------------------------------
-
-  FILENAMElen -- max length for TI and TO filenames
-
-*/
-
-#define qh_FILENAMElen 500
-
-/*----------------------------------
-
-  msgcode -- Unique message codes for qh_fprintf
-
-  If add new messages, assign these values and increment in user.h and user_r.h
-  See QhullError.h for 10000 errors.
-
-  def counters =  [27, 1048, 2059, 3026, 4068, 5003,
-     6273, 7081, 8147, 9411, 10000, 11029]
-
-  See: qh_ERR* [libqhull.h]
-*/
-
-#define MSG_TRACE0 0
-#define MSG_TRACE1 1000
-#define MSG_TRACE2 2000
-#define MSG_TRACE3 3000
-#define MSG_TRACE4 4000
-#define MSG_TRACE5 5000
-#define MSG_ERROR  6000   /* errors written to qh.ferr */
-#define MSG_WARNING 7000
-#define MSG_STDERR  8000  /* log messages Written to qh.ferr */
-#define MSG_OUTPUT  9000
-#define MSG_QHULL_ERROR 10000 /* errors thrown by QhullError.cpp (QHULLlastError is in QhullError.h) */
-#define MSG_FIXUP  11000  /* FIXUP QH11... */
-#define MSG_MAXLEN  3000 /* qh_printhelp_degenerate() in user.c */
-
-
-/*----------------------------------
-
-  qh_OPTIONline -- max length of an option line 'FO'
-*/
-#define qh_OPTIONline 80
-
-/*============================================================*/
-/*============= data types and configuration macros ==========*/
-/*============================================================*/
-
-/*----------------------------------
-
-  realT
-    set the size of floating point numbers
-
-  qh_REALdigits
-    maximimum number of significant digits
-
-  qh_REAL_1, qh_REAL_2n, qh_REAL_3n
-    format strings for printf
-
-  qh_REALmax, qh_REALmin
-    maximum and minimum (near zero) values
-
-  qh_REALepsilon
-    machine roundoff.  Maximum roundoff error for addition and multiplication.
-
-  notes:
-   Select whether to store floating point numbers in single precision (float)
-   or double precision (double).
-
-   Use 'float' to save about 8% in time and 25% in space.  This is particularly
-   helpful if high-d where convex hulls are space limited.  Using 'float' also
-   reduces the printed size of Qhull's output since numbers have 8 digits of
-   precision.
-
-   Use 'double' when greater arithmetic precision is needed.  This is needed
-   for Delaunay triangulations and Voronoi diagrams when you are not merging
-   facets.
-
-   If 'double' gives insufficient precision, your data probably includes
-   degeneracies.  If so you should use facet merging (done by default)
-   or exact arithmetic (see imprecision section of manual, qh-impre.htm).
-   You may also use option 'Po' to force output despite precision errors.
-
-   You may use 'long double', but many format statements need to be changed
-   and you may need a 'long double' square root routine.  S. Grundmann
-   (sg@eeiwzb.et.tu-dresden.de) has done this.  He reports that the code runs
-   much slower with little gain in precision.
-
-   WARNING: on some machines,    int f(){realT a= REALmax;return (a == REALmax);}
-      returns False.  Use (a > REALmax/2) instead of (a == REALmax).
-
-   REALfloat =   1      all numbers are 'float' type
-             =   0      all numbers are 'double' type
-*/
-#define REALfloat 0
-
-#if (REALfloat == 1)
-#define realT float
-#define REALmax FLT_MAX
-#define REALmin FLT_MIN
-#define REALepsilon FLT_EPSILON
-#define qh_REALdigits 8   /* maximum number of significant digits */
-#define qh_REAL_1 "%6.8g "
-#define qh_REAL_2n "%6.8g %6.8g\n"
-#define qh_REAL_3n "%6.8g %6.8g %6.8g\n"
-
-#elif (REALfloat == 0)
-#define realT double
-#define REALmax DBL_MAX
-#define REALmin DBL_MIN
-#define REALepsilon DBL_EPSILON
-#define qh_REALdigits 16    /* maximum number of significant digits */
-#define qh_REAL_1 "%6.16g "
-#define qh_REAL_2n "%6.16g %6.16g\n"
-#define qh_REAL_3n "%6.16g %6.16g %6.16g\n"
-
-#else
-#error unknown float option
-#endif
-
-/*----------------------------------
-
-  qh_CPUclock
-    define the clock() function for reporting the total time spent by Qhull
-    returns CPU ticks as a 'long int'
-    qh_CPUclock is only used for reporting the total time spent by Qhull
-
-  qh_SECticks
-    the number of clock ticks per second
-
-  notes:
-    looks for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or assumes microseconds
-    to define a custom clock, set qh_CLOCKtype to 0
-
-    if your system does not use clock() to return CPU ticks, replace
-    qh_CPUclock with the corresponding function.  It is converted
-    to 'unsigned long' to prevent wrap-around during long runs.  By default,
-     defines clock_t as 'long'
-
-   Set qh_CLOCKtype to
-
-     1          for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or microsecond
-                Note:  may fail if more than 1 hour elapsed time
-
-     2          use qh_clock() with POSIX times() (see global.c)
-*/
-#define qh_CLOCKtype 1  /* change to the desired number */
-
-#if (qh_CLOCKtype == 1)
-
-#if defined(CLOCKS_PER_SECOND)
-#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
-#define qh_SECticks CLOCKS_PER_SECOND
-
-#elif defined(CLOCKS_PER_SEC)
-#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
-#define qh_SECticks CLOCKS_PER_SEC
-
-#elif defined(CLK_TCK)
-#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
-#define qh_SECticks CLK_TCK
-
-#else
-#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
-#define qh_SECticks 1E6
-#endif
-
-#elif (qh_CLOCKtype == 2)
-#define qh_CPUclock    qh_clock()  /* return CPU clock */
-#define qh_SECticks 100
-
-#else /* qh_CLOCKtype == ? */
-#error unknown clock option
-#endif
-
-/*----------------------------------
-
-  qh_RANDOMtype, qh_RANDOMmax, qh_RANDOMseed
-    define random number generator
-
-    qh_RANDOMint generates a random integer between 0 and qh_RANDOMmax.
-    qh_RANDOMseed sets the random number seed for qh_RANDOMint
-
-  Set qh_RANDOMtype (default 5) to:
-    1       for random() with 31 bits (UCB)
-    2       for rand() with RAND_MAX or 15 bits (system 5)
-    3       for rand() with 31 bits (Sun)
-    4       for lrand48() with 31 bits (Solaris)
-    5       for qh_rand() with 31 bits (included with Qhull)
-
-  notes:
-    Random numbers are used by rbox to generate point sets.  Random
-    numbers are used by Qhull to rotate the input ('QRn' option),
-    simulate a randomized algorithm ('Qr' option), and to simulate
-    roundoff errors ('Rn' option).
-
-    Random number generators differ between systems.  Most systems provide
-    rand() but the period varies.  The period of rand() is not critical
-    since qhull does not normally use random numbers.
-
-    The default generator is Park & Miller's minimal standard random
-    number generator [CACM 31:1195 '88].  It is included with Qhull.
-
-    If qh_RANDOMmax is wrong, qhull will report a warning and Geomview
-    output will likely be invisible.
-*/
-#define qh_RANDOMtype 5   /* *** change to the desired number *** */
-
-#if (qh_RANDOMtype == 1)
-#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, random()/MAX */
-#define qh_RANDOMint random()
-#define qh_RANDOMseed_(seed) srandom(seed);
-
-#elif (qh_RANDOMtype == 2)
-#ifdef RAND_MAX
-#define qh_RANDOMmax ((realT)RAND_MAX)
-#else
-#define qh_RANDOMmax ((realT)32767)   /* 15 bits (System 5) */
-#endif
-#define qh_RANDOMint  rand()
-#define qh_RANDOMseed_(seed) srand((unsigned)seed);
-
-#elif (qh_RANDOMtype == 3)
-#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, Sun */
-#define qh_RANDOMint  rand()
-#define qh_RANDOMseed_(seed) srand((unsigned)seed);
-
-#elif (qh_RANDOMtype == 4)
-#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, lrand38()/MAX */
-#define qh_RANDOMint lrand48()
-#define qh_RANDOMseed_(seed) srand48(seed);
-
-#elif (qh_RANDOMtype == 5)
-#define qh_RANDOMmax ((realT)2147483646UL)  /* 31 bits, qh_rand/MAX */
-#define qh_RANDOMint qh_rand()
-#define qh_RANDOMseed_(seed) qh_srand(seed);
-/* unlike rand(), never returns 0 */
-
-#else
-#error: unknown random option
-#endif
-
-/*----------------------------------
-
-  qh_ORIENTclock
-    0 for inward pointing normals by Geomview convention
-*/
-#define qh_ORIENTclock 0
-
-
-/*============================================================*/
-/*============= joggle constants =============================*/
-/*============================================================*/
-
-/*----------------------------------
-
-qh_JOGGLEdefault
-default qh.JOGGLEmax is qh.DISTround * qh_JOGGLEdefault
-
-notes:
-rbox s r 100 | qhull QJ1e-15 QR0 generates 90% faults at distround 7e-16
-rbox s r 100 | qhull QJ1e-14 QR0 generates 70% faults
-rbox s r 100 | qhull QJ1e-13 QR0 generates 35% faults
-rbox s r 100 | qhull QJ1e-12 QR0 generates 8% faults
-rbox s r 100 | qhull QJ1e-11 QR0 generates 1% faults
-rbox s r 100 | qhull QJ1e-10 QR0 generates 0% faults
-rbox 1000 W0 | qhull QJ1e-12 QR0 generates 86% faults
-rbox 1000 W0 | qhull QJ1e-11 QR0 generates 20% faults
-rbox 1000 W0 | qhull QJ1e-10 QR0 generates 2% faults
-the later have about 20 points per facet, each of which may interfere
-
-pick a value large enough to avoid retries on most inputs
-*/
-#define qh_JOGGLEdefault 30000.0
-
-/*----------------------------------
-
-qh_JOGGLEincrease
-factor to increase qh.JOGGLEmax on qh_JOGGLEretry or qh_JOGGLEagain
-*/
-#define qh_JOGGLEincrease 10.0
-
-/*----------------------------------
-
-qh_JOGGLEretry
-if ZZretry = qh_JOGGLEretry, increase qh.JOGGLEmax
-
-notes:
-try twice at the original value in case of bad luck the first time
-*/
-#define qh_JOGGLEretry 2
-
-/*----------------------------------
-
-qh_JOGGLEagain
-every following qh_JOGGLEagain, increase qh.JOGGLEmax
-
-notes:
-1 is OK since it's already failed qh_JOGGLEretry times
-*/
-#define qh_JOGGLEagain 1
-
-/*----------------------------------
-
-qh_JOGGLEmaxincrease
-maximum qh.JOGGLEmax due to qh_JOGGLEincrease
-relative to qh.MAXwidth
-
-notes:
-qh.joggleinput will retry at this value until qh_JOGGLEmaxretry
-*/
-#define qh_JOGGLEmaxincrease 1e-2
-
-/*----------------------------------
-
-qh_JOGGLEmaxretry
-stop after qh_JOGGLEmaxretry attempts
-*/
-#define qh_JOGGLEmaxretry 100
-
-/*============================================================*/
-/*============= performance related constants ================*/
-/*============================================================*/
-
-/*----------------------------------
-
-  qh_HASHfactor
-    total hash slots / used hash slots.  Must be at least 1.1.
-
-  notes:
-    =2 for at worst 50% occupancy for qh.hash_table and normally 25% occupancy
-*/
-#define qh_HASHfactor 2
-
-/*----------------------------------
-
-  qh_VERIFYdirect
-    with 'Tv' verify all points against all facets if op count is smaller
-
-  notes:
-    if greater, calls qh_check_bestdist() instead
-*/
-#define qh_VERIFYdirect 1000000
-
-/*----------------------------------
-
-  qh_INITIALsearch
-     if qh_INITIALmax, search points up to this dimension
-*/
-#define qh_INITIALsearch 6
-
-/*----------------------------------
-
-  qh_INITIALmax
-    if dim >= qh_INITIALmax, use min/max coordinate points for initial simplex
-
-  notes:
-    from points with non-zero determinants
-    use option 'Qs' to override (much slower)
-*/
-#define qh_INITIALmax 8
-
-/*============================================================*/
-/*============= memory constants =============================*/
-/*============================================================*/
-
-/*----------------------------------
-
-  qh_MEMalign
-    memory alignment for qh_meminitbuffers() in global.c
-
-  notes:
-    to avoid bus errors, memory allocation must consider alignment requirements.
-    malloc() automatically takes care of alignment.   Since mem.c manages
-    its own memory, we need to explicitly specify alignment in
-    qh_meminitbuffers().
-
-    A safe choice is sizeof(double).  sizeof(float) may be used if doubles
-    do not occur in data structures and pointers are the same size.  Be careful
-    of machines (e.g., DEC Alpha) with large pointers.
-
-    If using gcc, best alignment is  [fmax_() is defined in geom_r.h]
-              #define qh_MEMalign fmax_(__alignof__(realT),__alignof__(void *))
-*/
-#define qh_MEMalign ((int)(fmax_(sizeof(realT), sizeof(void *))))
-
-/*----------------------------------
-
-  qh_MEMbufsize
-    size of additional memory buffers
-
-  notes:
-    used for qh_meminitbuffers() in global.c
-*/
-#define qh_MEMbufsize 0x10000       /* allocate 64K memory buffers */
-
-/*----------------------------------
-
-  qh_MEMinitbuf
-    size of initial memory buffer
-
-  notes:
-    use for qh_meminitbuffers() in global.c
-*/
-#define qh_MEMinitbuf 0x20000      /* initially allocate 128K buffer */
-
-/*----------------------------------
-
-  qh_INFINITE
-    on output, indicates Voronoi center at infinity
-*/
-#define qh_INFINITE  -10.101
-
-/*----------------------------------
-
-  qh_DEFAULTbox
-    default box size (Geomview expects 0.5)
-
-  qh_DEFAULTbox
-    default box size for integer coorindate (rbox only)
-*/
-#define qh_DEFAULTbox 0.5
-#define qh_DEFAULTzbox 1e6
-
-/*============================================================*/
-/*============= conditional compilation ======================*/
-/*============================================================*/
-
-/*----------------------------------
-
-  __cplusplus
-    defined by C++ compilers
-
-  __MSC_VER
-    defined by Microsoft Visual C++
-
-  __MWERKS__ && __INTEL__
-    defined by Metrowerks when compiling for Windows (not Intel-based Macintosh)
-
-  __MWERKS__ && __POWERPC__
-    defined by Metrowerks when compiling for PowerPC-based Macintosh
-  __STDC__
-    defined for strict ANSI C
-*/
-
-/*----------------------------------
-
-  qh_COMPUTEfurthest
-    compute furthest distance to an outside point instead of storing it with the facet
-    =1 to compute furthest
-
-  notes:
-    computing furthest saves memory but costs time
-      about 40% more distance tests for partitioning
-      removes facet->furthestdist
-*/
-#define qh_COMPUTEfurthest 0
-
-/*----------------------------------
-
-  qh_KEEPstatistics
-    =0 removes most of statistic gathering and reporting
-
-  notes:
-    if 0, code size is reduced by about 4%.
-*/
-#define qh_KEEPstatistics 1
-
-/*----------------------------------
-
-  qh_MAXoutside
-    record outer plane for each facet
-    =1 to record facet->maxoutside
-
-  notes:
-    this takes a realT per facet and slightly slows down qhull
-    it produces better outer planes for geomview output
-*/
-#define qh_MAXoutside 1
-
-/*----------------------------------
-
-  qh_NOmerge
-    disables facet merging if defined
-
-  notes:
-    This saves about 10% space.
-
-    Unless 'Q0'
-      qh_NOmerge sets 'QJ' to avoid precision errors
-
-    #define qh_NOmerge
-
-  see:
-    qh_NOmem in mem.c
-
-    see user.c/user_eg.c for removing io.o
-*/
-
-/*----------------------------------
-
-  qh_NOtrace
-    no tracing if defined
-
-  notes:
-    This saves about 5% space.
-
-    #define qh_NOtrace
-*/
-
-/*----------------------------------
-
-  qh_QHpointer
-    access global data with pointer or static structure
-
-  qh_QHpointer  = 1     access globals via a pointer to allocated memory
-                        enables qh_saveqhull() and qh_restoreqhull()
-                        [2010, gcc] costs about 4% in time and 4% in space
-                        [2003, msvc] costs about 8% in time and 2% in space
-
-                = 0     qh_qh and qh_qhstat are static data structures
-                        only one instance of qhull() can be active at a time
-                        default value
-
-  qh_QHpointer_dllimport and qh_dllimport define qh_qh as __declspec(dllimport) [libqhull.h]
-  It is required for msvc-2005.  It is not needed for gcc.
-
-  notes:
-    [jan'16] qh_QHpointer is deprecated for Qhull.  Use libqhull_r instead.
-    all global variables for qhull are in qh, qhmem, and qhstat
-    qh is defined in libqhull.h
-    qhmem is defined in mem.h
-    qhstat is defined in stat.h
-
-*/
-#ifdef qh_QHpointer
-#if qh_dllimport
-#error QH6207 Qhull error: Use qh_QHpointer_dllimport instead of qh_dllimport with qh_QHpointer
-#endif
-#else
-#define qh_QHpointer 0
-#if qh_QHpointer_dllimport
-#error QH6234 Qhull error: Use qh_dllimport instead of qh_QHpointer_dllimport when qh_QHpointer is not defined
-#endif
-#endif
-#if 0  /* sample code */
-    qhT *oldqhA, *oldqhB;
-
-    exitcode= qh_new_qhull(dim, numpoints, points, ismalloc,
-                      flags, outfile, errfile);
-    /* use results from first call to qh_new_qhull */
-    oldqhA= qh_save_qhull();
-    exitcode= qh_new_qhull(dimB, numpointsB, pointsB, ismalloc,
-                      flags, outfile, errfile);
-    /* use results from second call to qh_new_qhull */
-    oldqhB= qh_save_qhull();
-    qh_restore_qhull(&oldqhA);
-    /* use results from first call to qh_new_qhull */
-    qh_freeqhull(qh_ALL);  /* frees all memory used by first call */
-    qh_restore_qhull(&oldqhB);
-    /* use results from second call to qh_new_qhull */
-    qh_freeqhull(!qh_ALL); /* frees long memory used by second call */
-    qh_memfreeshort(&curlong, &totlong);  /* frees short memory and memory allocator */
-#endif
-
-/*----------------------------------
-
-  qh_QUICKhelp
-    =1 to use abbreviated help messages, e.g., for degenerate inputs
-*/
-#define qh_QUICKhelp    0
-
-/*============================================================*/
-/*============= -merge constants- ============================*/
-/*============================================================*/
-/*
-   These constants effect facet merging.  You probably will not need
-   to modify them.  They effect the performance of facet merging.
-*/
-
-/*----------------------------------
-
-  qh_DIMmergeVertex
-    max dimension for vertex merging (it is not effective in high-d)
-*/
-#define qh_DIMmergeVertex 6
-
-/*----------------------------------
-
-  qh_DIMreduceBuild
-     max dimension for vertex reduction during build (slow in high-d)
-*/
-#define qh_DIMreduceBuild 5
-
-/*----------------------------------
-
-  qh_BESTcentrum
-     if > 2*dim+n vertices, qh_findbestneighbor() tests centrums (faster)
-     else, qh_findbestneighbor() tests all vertices (much better merges)
-
-  qh_BESTcentrum2
-     if qh_BESTcentrum2 * DIM3 + BESTcentrum < #vertices tests centrums
-*/
-#define qh_BESTcentrum 20
-#define qh_BESTcentrum2 2
-
-/*----------------------------------
-
-  qh_BESTnonconvex
-    if > dim+n neighbors, qh_findbestneighbor() tests nonconvex ridges.
-
-  notes:
-    It is needed because qh_findbestneighbor is slow for large facets
-*/
-#define qh_BESTnonconvex 15
-
-/*----------------------------------
-
-  qh_MAXnewmerges
-    if >n newmerges, qh_merge_nonconvex() calls qh_reducevertices_centrums.
-
-  notes:
-    It is needed because postmerge can merge many facets at once
-*/
-#define qh_MAXnewmerges 2
-
-/*----------------------------------
-
-  qh_MAXnewcentrum
-    if <= dim+n vertices (n approximates the number of merges),
-      reset the centrum in qh_updatetested() and qh_mergecycle_facets()
-
-  notes:
-    needed to reduce cost and because centrums may move too much if
-    many vertices in high-d
-*/
-#define qh_MAXnewcentrum 5
-
-/*----------------------------------
-
-  qh_COPLANARratio
-    for 3-d+ merging, qh.MINvisible is n*premerge_centrum
-
-  notes:
-    for non-merging, it's DISTround
-*/
-#define qh_COPLANARratio 3
-
-/*----------------------------------
-
-  qh_DISToutside
-    When is a point clearly outside of a facet?
-    Stops search in qh_findbestnew or qh_partitionall
-    qh_findbest uses qh.MINoutside since since it is only called if no merges.
-
-  notes:
-    'Qf' always searches for best facet
-    if !qh.MERGING, same as qh.MINoutside.
-    if qh_USEfindbestnew, increase value since neighboring facets may be ill-behaved
-      [Note: Zdelvertextot occurs normally with interior points]
-            RBOX 1000 s Z1 G1e-13 t1001188774 | QHULL Tv
-    When there is a sharp edge, need to move points to a
-    clearly good facet; otherwise may be lost in another partitioning.
-    if too big then O(n^2) behavior for partitioning in cone
-    if very small then important points not processed
-    Needed in qh_partitionall for
-      RBOX 1000 s Z1 G1e-13 t1001032651 | QHULL Tv
-    Needed in qh_findbestnew for many instances of
-      RBOX 1000 s Z1 G1e-13 t | QHULL Tv
-
-  See:
-    qh_DISToutside -- when is a point clearly outside of a facet
-    qh_SEARCHdist -- when is facet coplanar with the best facet?
-    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
-*/
-#define qh_DISToutside ((qh_USEfindbestnew ? 2 : 1) * \
-     fmax_((qh MERGING ? 2 : 1)*qh MINoutside, qh max_outside))
-
-/*----------------------------------
-
-  qh_RATIOnearinside
-    ratio of qh.NEARinside to qh.ONEmerge for retaining inside points for
-    qh_check_maxout().
-
-  notes:
-    This is overkill since do not know the correct value.
-    It effects whether 'Qc' reports all coplanar points
-    Not used for 'd' since non-extreme points are coplanar
-*/
-#define qh_RATIOnearinside 5
-
-/*----------------------------------
-
-  qh_SEARCHdist
-    When is a facet coplanar with the best facet?
-    qh_findbesthorizon: all coplanar facets of the best facet need to be searched.
-
-  See:
-    qh_DISToutside -- when is a point clearly outside of a facet
-    qh_SEARCHdist -- when is facet coplanar with the best facet?
-    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
-*/
-#define qh_SEARCHdist ((qh_USEfindbestnew ? 2 : 1) * \
-      (qh max_outside + 2 * qh DISTround + fmax_( qh MINvisible, qh MAXcoplanar)));
-
-/*----------------------------------
-
-  qh_USEfindbestnew
-     Always use qh_findbestnew for qh_partitionpoint, otherwise use
-     qh_findbestnew if merged new facet or sharpnewfacets.
-
-  See:
-    qh_DISToutside -- when is a point clearly outside of a facet
-    qh_SEARCHdist -- when is facet coplanar with the best facet?
-    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
-*/
-#define qh_USEfindbestnew (zzval_(Ztotmerge) > 50)
-
-/*----------------------------------
-
-  qh_WIDEcoplanar
-    n*MAXcoplanar or n*MINvisible for a WIDEfacet
-
-    if vertex is further than qh.WIDEfacet from the hyperplane
-    then its ridges are not counted in computing the area, and
-    the facet's centrum is frozen.
-
-  notes:
-   qh.WIDEfacet= max(qh.MAXoutside,qh_WIDEcoplanar*qh.MAXcoplanar,
-      qh_WIDEcoplanar * qh.MINvisible);
-*/
-#define qh_WIDEcoplanar 6
-
-/*----------------------------------
-
-  qh_WIDEduplicate
-    Merge ratio for errexit from qh_forcedmerges due to duplicate ridge
-    Override with option Q12 no-wide-duplicate
-
-    Notes:
-      Merging a duplicate ridge can lead to very wide facets.
-      A future release of qhull will avoid duplicate ridges by removing duplicate sub-ridges from the horizon
-*/
-#define qh_WIDEduplicate 100
-
-/*----------------------------------
-
-  qh_MAXnarrow
-    max. cosine in initial hull that sets qh.NARROWhull
-
-  notes:
-    If qh.NARROWhull, the initial partition does not make
-    coplanar points.  If narrow, a coplanar point can be
-    coplanar to two facets of opposite orientations and
-    distant from the exact convex hull.
-
-    Conservative estimate.  Don't actually see problems until it is -1.0
-*/
-#define qh_MAXnarrow -0.99999999
-
-/*----------------------------------
-
-  qh_WARNnarrow
-    max. cosine in initial hull to warn about qh.NARROWhull
-
-  notes:
-    this is a conservative estimate.
-    Don't actually see problems until it is -1.0.  See qh-impre.htm
-*/
-#define qh_WARNnarrow -0.999999999999999
-
-/*----------------------------------
-
-  qh_ZEROdelaunay
-    a zero Delaunay facet occurs for input sites coplanar with their convex hull
-    the last normal coefficient of a zero Delaunay facet is within
-        qh_ZEROdelaunay * qh.ANGLEround of 0
-
-  notes:
-    qh_ZEROdelaunay does not allow for joggled input ('QJ').
-
-    You can avoid zero Delaunay facets by surrounding the input with a box.
-
-    Use option 'PDk:-n' to explicitly define zero Delaunay facets
-      k= dimension of input sites (e.g., 3 for 3-d Delaunay triangulation)
-      n= the cutoff for zero Delaunay facets (e.g., 'PD3:-1e-12')
-*/
-#define qh_ZEROdelaunay 2
-
-/*============================================================*/
-/*============= Microsoft DevStudio ==========================*/
-/*============================================================*/
-
-/*
-   Finding Memory Leaks Using the CRT Library
-   https://msdn.microsoft.com/en-us/library/x98tx3cf(v=vs.100).aspx
-
-   Reports enabled in qh_lib_check for Debug window and stderr
-
-   From 2005=>msvcr80d, 2010=>msvcr100d, 2012=>msvcr110d
-
-   Watch: {,,msvcr80d.dll}_crtBreakAlloc  Value from {n} in the leak report
-   _CrtSetBreakAlloc(689); // qh_lib_check() [global_r.c]
-
-   Examples
-     http://free-cad.sourceforge.net/SrcDocu/d2/d7f/MemDebug_8cpp_source.html
-     https://github.com/illlust/Game/blob/master/library/MemoryLeak.cpp
-*/
-#if 0   /* off (0) by default for QHULL_CRTDBG */
-#define QHULL_CRTDBG
-#endif
-
-#if defined(_MSC_VER) && defined(_DEBUG) && defined(QHULL_CRTDBG)
-#define _CRTDBG_MAP_ALLOC
-#include 
-#include 
-#endif
-#endif /* qh_DEFuser */
-
-
-
diff --git a/extern/libqhull/usermem.c b/extern/libqhull/usermem.c
deleted file mode 100644
index 0e99e8f66c18..000000000000
--- a/extern/libqhull/usermem.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
  ---------------------------------
-
-   usermem.c
-   qh_exit(), qh_free(), and qh_malloc()
-
-   See README.txt.
-
-   If you redefine one of these functions you must redefine all of them.
-   If you recompile and load this file, then usermem.o will not be loaded
-   from qhull.a or qhull.lib
-
-   See libqhull.h for data structures, macros, and user-callable functions.
-   See user.c for qhull-related, redefinable functions
-   see user.h for user-definable constants
-   See userprintf.c for qh_fprintf and userprintf_rbox.c for qh_fprintf_rbox
-
-   Please report any errors that you fix to qhull@qhull.org
-*/
-
-#include "libqhull.h"
-
-#include 
-#include 
-
-/*---------------------------------
-
-  qh_exit( exitcode )
-    exit program
-
-  notes:
-    qh_exit() is called when qh_errexit() and longjmp() are not available.
-
-    This is the only use of exit() in Qhull
-    To replace qh_exit with 'throw', see libqhullcpp/usermem_r-cpp.cpp
-*/
-void qh_exit(int exitcode) {
-    exit(exitcode);
-} /* exit */
-
-/*---------------------------------
-
-  qh_fprintf_stderr( msgcode, format, list of args )
-    fprintf to stderr with msgcode (non-zero)
-
-  notes:
-    qh_fprintf_stderr() is called when qh.ferr is not defined, usually due to an initialization error
-    
-    It is typically followed by qh_errexit().
-
-    Redefine this function to avoid using stderr
-
-    Use qh_fprintf [userprintf.c] for normal printing
-*/
-void qh_fprintf_stderr(int msgcode, const char *fmt, ... ) {
-    va_list args;
-
-    va_start(args, fmt);
-    if(msgcode)
-      fprintf(stderr, "QH%.4d ", msgcode);
-    vfprintf(stderr, fmt, args);
-    va_end(args);
-} /* fprintf_stderr */
-
-/*---------------------------------
-
-  qh_free( mem )
-    free memory
-
-  notes:
-    same as free()
-    No calls to qh_errexit() 
-*/
-void qh_free(void *mem) {
-    free(mem);
-} /* free */
-
-/*---------------------------------
-
-    qh_malloc( mem )
-      allocate memory
-
-    notes:
-      same as malloc()
-*/
-void *qh_malloc(size_t size) {
-    return malloc(size);
-} /* malloc */
-
-
diff --git a/extern/libqhull/userprintf.c b/extern/libqhull/userprintf.c
deleted file mode 100644
index 190d7cd79b3b..000000000000
--- a/extern/libqhull/userprintf.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
  ---------------------------------
-
-   userprintf.c
-   qh_fprintf()
-
-   see README.txt  see COPYING.txt for copyright information.
-
-   If you recompile and load this file, then userprintf.o will not be loaded
-   from qhull.a or qhull.lib
-
-   See libqhull.h for data structures, macros, and user-callable functions.
-   See user.c for qhull-related, redefinable functions
-   see user.h for user-definable constants
-   See usermem.c for qh_exit(), qh_free(), and qh_malloc()
-   see Qhull.cpp and RboxPoints.cpp for examples.
-
-   Please report any errors that you fix to qhull@qhull.org
-*/
-
-#include "libqhull.h"
-#include "mem.h"
-
-#include 
-#include 
-#include 
-
-/*---------------------------------
-
-   qh_fprintf(fp, msgcode, format, list of args )
-     print arguments to *fp according to format
-     Use qh_fprintf_rbox() for rboxlib.c
-
-   notes:
-     same as fprintf()
-     fgets() is not trapped like fprintf()
-     exit qh_fprintf via qh_errexit()
-     may be called for errors in qh_initstatistics and qh_meminit
-*/
-
-void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... ) {
-    va_list args;
-
-    if (!fp) {
-        /* could use qhmem.ferr, but probably better to be cautious */
-        qh_fprintf_stderr(6232, "Qhull internal error (userprintf.c): fp is 0.  Wrong qh_fprintf called.\n");
-        qh_errexit(6232, NULL, NULL);
-    }
-    va_start(args, fmt);
-#if qh_QHpointer
-    if (qh_qh && qh ANNOTATEoutput) {
-#else
-    if (qh ANNOTATEoutput) {
-#endif
-      fprintf(fp, "[QH%.4d]", msgcode);
-    }else if (msgcode >= MSG_ERROR && msgcode < MSG_STDERR ) {
-      fprintf(fp, "QH%.4d ", msgcode);
-    }
-    vfprintf(fp, fmt, args);
-    va_end(args);
-
-    /* Place debugging traps here. Use with option 'Tn' */
-
-} /* qh_fprintf */
-
diff --git a/extern/libqhull/userprintf_rbox.c b/extern/libqhull/userprintf_rbox.c
deleted file mode 100644
index 8edd2001aa5c..000000000000
--- a/extern/libqhull/userprintf_rbox.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
  ---------------------------------
-
-   userprintf_rbox.c
-   qh_fprintf_rbox()
-
-   see README.txt  see COPYING.txt for copyright information.
-
-   If you recompile and load this file, then userprintf_rbox.o will not be loaded
-   from qhull.a or qhull.lib
-
-   See libqhull.h for data structures, macros, and user-callable functions.
-   See user.c for qhull-related, redefinable functions
-   see user.h for user-definable constants
-   See usermem.c for qh_exit(), qh_free(), and qh_malloc()
-   see Qhull.cpp and RboxPoints.cpp for examples.
-
-   Please report any errors that you fix to qhull@qhull.org
-*/
-
-#include "libqhull.h"
-
-#include 
-#include 
-#include 
-
-/*---------------------------------
-
-   qh_fprintf_rbox(fp, msgcode, format, list of args )
-     print arguments to *fp according to format
-     Use qh_fprintf_rbox() for rboxlib.c
-
-   notes:
-     same as fprintf()
-     fgets() is not trapped like fprintf()
-     exit qh_fprintf_rbox via qh_errexit_rbox()
-*/
-
-void qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... ) {
-    va_list args;
-
-    if (!fp) {
-        qh_fprintf_stderr(6231, "Qhull internal error (userprintf_rbox.c): fp is 0.  Wrong qh_fprintf_rbox called.\n");
-        qh_errexit_rbox(6231);
-    }
-    if (msgcode >= MSG_ERROR && msgcode < MSG_STDERR)
-      fprintf(fp, "QH%.4d ", msgcode);
-    va_start(args, fmt);
-    vfprintf(fp, fmt, args);
-    va_end(args);
-} /* qh_fprintf_rbox */
-
diff --git a/setup.py b/setup.py
index 445a448ebc52..0d656d277c61 100644
--- a/setup.py
+++ b/setup.py
@@ -28,6 +28,7 @@
 from pathlib import Path
 import shutil
 import subprocess
+import tarfile
 
 from setuptools import setup, find_packages, Extension
 from setuptools.command.build_ext import build_ext as BuildExtCommand
@@ -47,7 +48,8 @@
 from distutils.dist import Distribution
 
 import setupext
-from setupext import print_raw, print_status
+from setupext import (
+    download_or_cache, print_raw, print_status, LOCAL_QHULL_VERSION)
 
 # Get the version from versioneer
 import versioneer
@@ -85,8 +87,24 @@ def __init__(self, dist):
               "'python setup.py test'. Please run 'pytest'.")
 
 
+def _download_qhull_to(dest):
+    url = "http://www.qhull.org/download/qhull-2015-src-7.2.0.tgz"
+    sha = "78b010925c3b577adc3d58278787d7df08f7c8fb02c3490e375eab91bb58a436"
+    if (dest / f"qhull-{LOCAL_QHULL_VERSION}").exists():
+        return
+    dest.mkdir(parents=True, exist_ok=True)
+    try:
+        buf = download_or_cache(url, sha)
+    except Exception:
+        raise IOError(f"Failed to download qhull.  Please download {url} and "
+                      f"extract it to {dest}.")
+    with tarfile.open(fileobj=buf, mode="r:gz") as tf:
+        tf.extractall(dest)
+
+
 class BuildExtraLibraries(BuildExtCommand):
     def finalize_options(self):
+        _download_qhull_to(Path("extern"))
         self.distribution.ext_modules[:] = [
             ext
             for package in good_packages
diff --git a/setupext.py b/setupext.py
index 0742230844fc..9e00f9be22ce 100644
--- a/setupext.py
+++ b/setupext.py
@@ -2,7 +2,6 @@
 from distutils import ccompiler, sysconfig
 from distutils.core import Extension
 import functools
-import glob
 import hashlib
 from io import BytesIO
 import logging
@@ -137,6 +136,8 @@ def download_or_cache(url, sha):
 LOCAL_FREETYPE_VERSION = '2.6.1'
 LOCAL_FREETYPE_HASH = _freetype_hashes.get(LOCAL_FREETYPE_VERSION, 'unknown')
 
+LOCAL_QHULL_VERSION = '2015.2'
+
 
 # matplotlib build options, which can be altered using setup.cfg
 setup_cfg = os.environ.get('MPLSETUPCFG', 'setup.cfg')
@@ -514,8 +515,9 @@ def add_qhull_flags(ext):
     if options.get("system_qhull"):
         ext.libraries.append("qhull")
     else:
-        ext.include_dirs.insert(0, "extern")
-        ext.sources.extend(sorted(glob.glob("extern/libqhull/*.c")))
+        qhull_path = Path(f'extern/qhull-{LOCAL_QHULL_VERSION}/src')
+        ext.include_dirs.insert(0, str(qhull_path))
+        ext.sources.extend(map(str, sorted(qhull_path.glob('libqhull/*.c'))))
         if sysconfig.get_config_var("LIBM") == "-lm":
             ext.libraries.extend("m")
 

From dbe44f89a0ce2f5613a33d38a5a476733dc64149 Mon Sep 17 00:00:00 2001
From: Antony Lee 
Date: Wed, 6 Jan 2021 11:22:04 +0100
Subject: [PATCH 2/4] Switch to reentrant qhull 2020 8.0.2.

(the current version)

Co-authored-by: Ian Thomas 
---
 INSTALL.rst                                | 16 ++++++++------
 lib/matplotlib/tests/test_triangulation.py |  2 +-
 lib/mpl_toolkits/tests/test_mplot3d.py     |  2 +-
 setup.cfg.template                         |  7 +++---
 setup.py                                   |  4 ++--
 setupext.py                                |  4 ++--
 src/qhull_wrap.c                           | 25 ++++++++++++----------
 7 files changed, 33 insertions(+), 27 deletions(-)

diff --git a/INSTALL.rst b/INSTALL.rst
index 387df87e3198..e4cea0ec9ad1 100644
--- a/INSTALL.rst
+++ b/INSTALL.rst
@@ -220,13 +220,15 @@ etc., you can install the following:
 FreeType and Qhull
 ------------------
 
-Matplotlib depends on `FreeType `_ (>=
-2.3), a font rendering library, and on `Qhull
-`_ (>= 2015.2), a library for computing
-triangulations.  By default (except on AIX) Matplotlib downloads and
-builds its own copy of FreeType (this is necessary to run the test
-suite, because different versions of FreeType rasterize characters
-differently), and uses its own copy of Qhull.
+Matplotlib depends on FreeType_ (>= 2.3), a font rendering library, and on
+Qhull_ (>= 2020.2), a library for computing triangulations.  By default,
+Matplotlib downloads and builds its own copies of FreeType (this is necessary
+to run the test suite, because different versions of FreeType rasterize
+characters differently) and of Qhull.  As an exception, Matplotlib defaults to
+the system version of FreeType on AIX.
+
+.. _FreeType: https://www.freetype.org/
+.. _Qhull: http://www.qhull.org/
 
 To force Matplotlib to use a copy of FreeType or Qhull already installed in
 your system, create a :file:`setup.cfg` file with the following contents:
diff --git a/lib/matplotlib/tests/test_triangulation.py b/lib/matplotlib/tests/test_triangulation.py
index cd46b954785c..dacbfd39c154 100644
--- a/lib/matplotlib/tests/test_triangulation.py
+++ b/lib/matplotlib/tests/test_triangulation.py
@@ -730,7 +730,7 @@ def z(x, y):
             matest.assert_array_almost_equal(interpz, interp_z0[interp_key])
 
 
-@image_comparison(['tri_smooth_contouring.png'], remove_text=True, tol=0.07)
+@image_comparison(['tri_smooth_contouring.png'], remove_text=True, tol=0.072)
 def test_tri_smooth_contouring():
     # Image comparison based on example tricontour_smooth_user.
     n_angles = 20
diff --git a/lib/mpl_toolkits/tests/test_mplot3d.py b/lib/mpl_toolkits/tests/test_mplot3d.py
index 34562fa1324d..20316c82a8c1 100644
--- a/lib/mpl_toolkits/tests/test_mplot3d.py
+++ b/lib/mpl_toolkits/tests/test_mplot3d.py
@@ -152,7 +152,7 @@ def test_contourf3d_fill():
     ax.set_zlim(-1, 1)
 
 
-@mpl3d_image_comparison(['tricontour.png'])
+@mpl3d_image_comparison(['tricontour.png'], tol=0.02)
 def test_tricontour():
     fig = plt.figure()
 
diff --git a/setup.cfg.template b/setup.cfg.template
index 00ae11c7a4a0..19b25641ffb9 100644
--- a/setup.cfg.template
+++ b/setup.cfg.template
@@ -9,9 +9,10 @@ license_files = LICENSE/*
 # By default, Matplotlib builds with LTO, which may be slow if you re-compile
 # often, and don't need the space saving/speedup.
 #enable_lto = True
-# By default, Matplotlib downloads and builds its own copy of FreeType, and
-# builds its own copy of Qhull.  You may set the following to True to instead
-# link against a system FreeType/Qhull.
+# By default, Matplotlib downloads and builds its own copies of FreeType and of
+# of Qhull.  You may set the following to True to instead link against a system
+# FreeType/Qhull.  As an exception, Matplotlib defaults to the system version
+# of FreeType on AIX.
 #system_freetype = False
 #system_qhull = False
 
diff --git a/setup.py b/setup.py
index 0d656d277c61..99b57506cc5f 100644
--- a/setup.py
+++ b/setup.py
@@ -88,8 +88,8 @@ def __init__(self, dist):
 
 
 def _download_qhull_to(dest):
-    url = "http://www.qhull.org/download/qhull-2015-src-7.2.0.tgz"
-    sha = "78b010925c3b577adc3d58278787d7df08f7c8fb02c3490e375eab91bb58a436"
+    url = "http://www.qhull.org/download/qhull-2020-src-8.0.2.tgz"
+    sha = "b5c2d7eb833278881b952c8a52d20179eab87766b00b865000469a45c1838b7e"
     if (dest / f"qhull-{LOCAL_QHULL_VERSION}").exists():
         return
     dest.mkdir(parents=True, exist_ok=True)
diff --git a/setupext.py b/setupext.py
index 9e00f9be22ce..350e39ebddf9 100644
--- a/setupext.py
+++ b/setupext.py
@@ -136,7 +136,7 @@ def download_or_cache(url, sha):
 LOCAL_FREETYPE_VERSION = '2.6.1'
 LOCAL_FREETYPE_HASH = _freetype_hashes.get(LOCAL_FREETYPE_VERSION, 'unknown')
 
-LOCAL_QHULL_VERSION = '2015.2'
+LOCAL_QHULL_VERSION = '2020.2'
 
 
 # matplotlib build options, which can be altered using setup.cfg
@@ -517,7 +517,7 @@ def add_qhull_flags(ext):
     else:
         qhull_path = Path(f'extern/qhull-{LOCAL_QHULL_VERSION}/src')
         ext.include_dirs.insert(0, str(qhull_path))
-        ext.sources.extend(map(str, sorted(qhull_path.glob('libqhull/*.c'))))
+        ext.sources.extend(map(str, sorted(qhull_path.glob('libqhull_r/*.c'))))
         if sysconfig.get_config_var("LIBM") == "-lm":
             ext.libraries.extend("m")
 
diff --git a/src/qhull_wrap.c b/src/qhull_wrap.c
index 8545cc3c314c..0f7b3938299c 100644
--- a/src/qhull_wrap.c
+++ b/src/qhull_wrap.c
@@ -8,7 +8,7 @@
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
 #include "numpy/ndarrayobject.h"
-#include "libqhull/qhull_a.h"
+#include "libqhull_r/qhull_ra.h"
 #include 
 
 
@@ -32,11 +32,11 @@ static const char* qhull_error_msg[6] = {
 /* Return the indices of the 3 vertices that comprise the specified facet (i.e.
  * triangle). */
 static void
-get_facet_vertices(const facetT* facet, int indices[3])
+get_facet_vertices(qhT* qh, const facetT* facet, int indices[3])
 {
     vertexT *vertex, **vertexp;
     FOREACHvertex_(facet->vertices)
-        *indices++ = qh_pointid(vertex->point);
+        *indices++ = qh_pointid(qh, vertex->point);
 }
 
 /* Return the indices of the 3 triangles that are neighbors of the specified
@@ -88,6 +88,8 @@ static PyObject*
 delaunay_impl(int npoints, const double* x, const double* y,
               int hide_qhull_errors)
 {
+	qhT qh_qh;                  /* qh variable type and name must be like */
+	qhT* qh = &qh_qh;           /* this for Qhull macros to work correctly. */
     coordT* points = NULL;
     facetT* facet;
     int i, ntri, max_facet_id;
@@ -148,7 +150,8 @@ delaunay_impl(int npoints, const double* x, const double* y,
     }
 
     /* Perform Delaunay triangulation. */
-    exitcode = qh_new_qhull(ndim, npoints, points, False,
+    qh_zero(qh, error_file);
+    exitcode = qh_new_qhull(qh, ndim, npoints, points, False,
                             "qhull d Qt Qbb Qc Qz", NULL, error_file);
     if (exitcode != qh_ERRnone) {
         PyErr_Format(PyExc_RuntimeError,
@@ -159,7 +162,7 @@ delaunay_impl(int npoints, const double* x, const double* y,
     }
 
     /* Split facets so that they only have 3 points each. */
-    qh_triangulate();
+    qh_triangulate(qh);
 
     /* Determine ntri and max_facet_id.
        Note that libqhull uses macros to iterate through collections. */
@@ -169,7 +172,7 @@ delaunay_impl(int npoints, const double* x, const double* y,
             ++ntri;
     }
 
-    max_facet_id = qh facet_id - 1;
+    max_facet_id = qh->facet_id - 1;
 
     /* Create array to map facet id to triangle index. */
     tri_indices = (int*)malloc((max_facet_id+1)*sizeof(int));
@@ -204,7 +207,7 @@ delaunay_impl(int npoints, const double* x, const double* y,
     FORALLfacets {
         if (!facet->upperdelaunay) {
             tri_indices[facet->id] = i++;
-            get_facet_vertices(facet, indices);
+            get_facet_vertices(qh, facet, indices);
             *triangles_ptr++ = (facet->toporient ? indices[0] : indices[2]);
             *triangles_ptr++ = indices[1];
             *triangles_ptr++ = (facet->toporient ? indices[2] : indices[0]);
@@ -224,8 +227,8 @@ delaunay_impl(int npoints, const double* x, const double* y,
     }
 
     /* Clean up. */
-    qh_freeqhull(!qh_ALL);
-    qh_memfreeshort(&curlong, &totlong);
+    qh_freeqhull(qh, !qh_ALL);
+    qh_memfreeshort(qh, &curlong, &totlong);
     if (curlong || totlong)
         PyErr_WarnEx(PyExc_RuntimeWarning,
                      "Qhull could not free all allocated memory", 1);
@@ -243,8 +246,8 @@ delaunay_impl(int npoints, const double* x, const double* y,
     /* Clean up. */
     Py_XDECREF(triangles);
     Py_XDECREF(neighbors);
-    qh_freeqhull(!qh_ALL);
-    qh_memfreeshort(&curlong, &totlong);
+    qh_freeqhull(qh, !qh_ALL);
+    qh_memfreeshort(qh, &curlong, &totlong);
     /* Don't bother checking curlong and totlong as raising error anyway. */
     if (hide_qhull_errors)
         fclose(error_file);

From b5a3146beebd59d613b9cb42b3fe61309ebddeb1 Mon Sep 17 00:00:00 2001
From: Antony Lee 
Date: Fri, 8 Jan 2021 00:59:05 +0100
Subject: [PATCH 3/4] Merge the FreeType and Qhull download mechanisms.

---
 .gitignore  |  2 --
 setup.py    | 24 +++++---------
 setupext.py | 91 +++++++++++++++++++++++++++++++----------------------
 3 files changed, 62 insertions(+), 55 deletions(-)

diff --git a/.gitignore b/.gitignore
index 395f8be25efb..ee4a0eb7aef6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -105,5 +105,3 @@ lib/z.lib
 #########################
 lib/matplotlib/backends/web_backend/node_modules/
 lib/matplotlib/backends/web_backend/package-lock.json
-
-extern/qhull-*/
diff --git a/setup.py b/setup.py
index 99b57506cc5f..3de0686c5ceb 100644
--- a/setup.py
+++ b/setup.py
@@ -28,7 +28,6 @@
 from pathlib import Path
 import shutil
 import subprocess
-import tarfile
 
 from setuptools import setup, find_packages, Extension
 from setuptools.command.build_ext import build_ext as BuildExtCommand
@@ -49,7 +48,7 @@
 
 import setupext
 from setupext import (
-    download_or_cache, print_raw, print_status, LOCAL_QHULL_VERSION)
+    get_and_extract_tarball, print_raw, print_status, LOCAL_QHULL_VERSION)
 
 # Get the version from versioneer
 import versioneer
@@ -87,24 +86,17 @@ def __init__(self, dist):
               "'python setup.py test'. Please run 'pytest'.")
 
 
-def _download_qhull_to(dest):
-    url = "http://www.qhull.org/download/qhull-2020-src-8.0.2.tgz"
-    sha = "b5c2d7eb833278881b952c8a52d20179eab87766b00b865000469a45c1838b7e"
-    if (dest / f"qhull-{LOCAL_QHULL_VERSION}").exists():
-        return
-    dest.mkdir(parents=True, exist_ok=True)
-    try:
-        buf = download_or_cache(url, sha)
-    except Exception:
-        raise IOError(f"Failed to download qhull.  Please download {url} and "
-                      f"extract it to {dest}.")
-    with tarfile.open(fileobj=buf, mode="r:gz") as tf:
-        tf.extractall(dest)
+def _download_qhull():
+    toplevel = get_and_extract_tarball(
+        urls=["http://www.qhull.org/download/qhull-2020-src-8.0.2.tgz"],
+        sha="b5c2d7eb833278881b952c8a52d20179eab87766b00b865000469a45c1838b7e",
+        dirname=f"qhull-{LOCAL_QHULL_VERSION}",
+    )
 
 
 class BuildExtraLibraries(BuildExtCommand):
     def finalize_options(self):
-        _download_qhull_to(Path("extern"))
+        _download_qhull()
         self.distribution.ext_modules[:] = [
             ext
             for package in good_packages
diff --git a/setupext.py b/setupext.py
index 350e39ebddf9..638138e9a193 100644
--- a/setupext.py
+++ b/setupext.py
@@ -48,7 +48,7 @@ def _get_ssl_context():
     return ssl.create_default_context(cafile=certifi.where())
 
 
-def download_or_cache(url, sha):
+def get_from_cache_or_download(url, sha):
     """
     Get bytes from the given url or local cache.
 
@@ -86,7 +86,7 @@ def download_or_cache(url, sha):
     file_sha = _get_hash(data)
     if file_sha != sha:
         raise Exception(
-            f"The download file does not match the expected sha.  {url} was "
+            f"The downloaded file does not match the expected sha.  {url} was "
             f"expected to have {sha} but it had {file_sha}")
 
     if cache_dir is not None:  # Try to cache the downloaded file.
@@ -100,6 +100,45 @@ def download_or_cache(url, sha):
     return BytesIO(data)
 
 
+def get_and_extract_tarball(urls, sha, dirname):
+    """
+    Obtain a tarball (from cache or download) and extract it.
+
+    Parameters
+    ----------
+    urls : list[str]
+        URLs from which download is attempted (in order of attempt), if the
+        tarball is not in the cache yet.
+    sha : str
+        SHA256 hash of the tarball; used both as a cache key (by
+        `get_from_cache_or_download`) and to validate a downloaded tarball.
+    dirname : path-like
+        Directory where the tarball is extracted.
+    """
+    toplevel = Path("build", dirname)
+    if not toplevel.exists():  # Download it or load it from cache.
+        Path("build").mkdir(exist_ok=True)
+        for url in urls:
+            try:
+                tar_contents = get_from_cache_or_download(url, sha)
+                break
+            except Exception:
+                pass
+        else:
+            raise IOError(
+                f"Failed to download any of the following: {urls}.  "
+                f"Please download one of these urls and extract it into "
+                f"'build/' at the top-level of the source repository.")
+        print("Extracting {}".format(urllib.parse.urlparse(url).path))
+        with tarfile.open(fileobj=tar_contents, mode="r:gz") as tgz:
+            if os.path.commonpath(tgz.getnames()) != dirname:
+                raise IOError(
+                    f"The downloaded tgz file was expected to have {dirname} "
+                    f"as sole top-level directory, but that is not the case")
+            tgz.extractall("build")
+    return toplevel
+
+
 # SHA256 hashes of the FreeType tarballs
 _freetype_hashes = {
     '2.6.1':
@@ -515,7 +554,7 @@ def add_qhull_flags(ext):
     if options.get("system_qhull"):
         ext.libraries.append("qhull")
     else:
-        qhull_path = Path(f'extern/qhull-{LOCAL_QHULL_VERSION}/src')
+        qhull_path = Path(f'build/qhull-{LOCAL_QHULL_VERSION}/src')
         ext.include_dirs.insert(0, str(qhull_path))
         ext.sources.extend(map(str, sorted(qhull_path.glob('libqhull_r/*.c'))))
         if sysconfig.get_config_var("LIBM") == "-lm":
@@ -560,46 +599,24 @@ def do_custom_build(self, env):
         if options.get('system_freetype'):
             return
 
-        src_path = Path('build', f'freetype-{LOCAL_FREETYPE_VERSION}')
+        tarball = f'freetype-{LOCAL_FREETYPE_VERSION}.tar.gz'
+        src_path = get_and_extract_tarball(
+            urls=[
+                (f'https://downloads.sourceforge.net/project/freetype'
+                 f'/freetype2/{LOCAL_FREETYPE_VERSION}/{tarball}'),
+                (f'https://download.savannah.gnu.org/releases/freetype'
+                 f'/{tarball}')
+            ],
+            sha=LOCAL_FREETYPE_HASH,
+            dirname=f'freetype-{LOCAL_FREETYPE_VERSION}',
+        )
 
-        # We've already built freetype
         if sys.platform == 'win32':
             libfreetype = 'libfreetype.lib'
         else:
             libfreetype = 'libfreetype.a'
-
-        # bailing because it is already built
         if (src_path / 'objs' / '.libs' / libfreetype).is_file():
-            return
-
-        # do we need to download / load the source from cache?
-        if not src_path.exists():
-            os.makedirs('build', exist_ok=True)
-
-            tarball = f'freetype-{LOCAL_FREETYPE_VERSION}.tar.gz'
-            target_urls = [
-                (f'https://downloads.sourceforge.net/project/freetype'
-                 f'/freetype2/{LOCAL_FREETYPE_VERSION}/{tarball}'),
-                (f'https://download.savannah.gnu.org/releases/freetype'
-                 f'/{tarball}')
-            ]
-
-            for tarball_url in target_urls:
-                try:
-                    tar_contents = download_or_cache(tarball_url,
-                                                     LOCAL_FREETYPE_HASH)
-                    break
-                except Exception:
-                    pass
-            else:
-                raise IOError(
-                    f"Failed to download FreeType. Please download one of "
-                    f"{target_urls} and extract it into {src_path} at the "
-                    f"top-level of the source repository.")
-
-            print(f"Extracting {tarball}")
-            with tarfile.open(fileobj=tar_contents, mode="r:gz") as tgz:
-                tgz.extractall("build")
+            return  # Bail out because we have already built FreeType.
 
         print(f"Building freetype in {src_path}")
         if sys.platform != 'win32':  # compilation on non-windows

From 94e81960b635b947fa6568718447dbf072ea2550 Mon Sep 17 00:00:00 2001
From: Antony Lee 
Date: Fri, 8 Jan 2021 00:59:57 +0100
Subject: [PATCH 4/4] Copy qhull license to LICENSES/.

---
 .gitignore | 2 ++
 setup.py   | 1 +
 2 files changed, 3 insertions(+)

diff --git a/.gitignore b/.gitignore
index ee4a0eb7aef6..a5023f04c1a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -105,3 +105,5 @@ lib/z.lib
 #########################
 lib/matplotlib/backends/web_backend/node_modules/
 lib/matplotlib/backends/web_backend/package-lock.json
+
+LICENSE/LICENSE_QHULL
diff --git a/setup.py b/setup.py
index 3de0686c5ceb..450bdfb30b83 100644
--- a/setup.py
+++ b/setup.py
@@ -92,6 +92,7 @@ def _download_qhull():
         sha="b5c2d7eb833278881b952c8a52d20179eab87766b00b865000469a45c1838b7e",
         dirname=f"qhull-{LOCAL_QHULL_VERSION}",
     )
+    shutil.copyfile(toplevel / "COPYING.txt", "LICENSE/LICENSE_QHULL")
 
 
 class BuildExtraLibraries(BuildExtCommand):