diff --git a/doc/api/api_changes/2017-01-06-IT.rst b/doc/api/api_changes/2017-01-06-IT.rst new file mode 100644 index 000000000000..93d72c9dc923 --- /dev/null +++ b/doc/api/api_changes/2017-01-06-IT.rst @@ -0,0 +1,6 @@ +Updated qhull to 2015.2 +``````````````````````` + +The version of qhull shipped with Matplotlib, which is used for +Delaunay triangulation, has been updated from version 2012.1 to +2015.2. diff --git a/extern/qhull/COPYING.txt b/extern/libqhull/COPYING.txt similarity index 86% rename from extern/qhull/COPYING.txt rename to extern/libqhull/COPYING.txt index a4a4ade56e19..2895ec6a32f1 100644 --- a/extern/qhull/COPYING.txt +++ b/extern/libqhull/COPYING.txt @@ -1,8 +1,8 @@ - Qhull, Copyright (c) 1993-2012 - + Qhull, Copyright (c) 1993-2015 + C.B. Barber - Arlington, MA - + Arlington, MA + and The National Science and Technology Research Center for @@ -12,27 +12,27 @@ 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, +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 +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 +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 +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/qhull/geom.c b/extern/libqhull/geom.c similarity index 98% rename from extern/qhull/geom.c rename to extern/libqhull/geom.c index a1517874aab4..71444f05a4c1 100644 --- a/extern/qhull/geom.c +++ b/extern/libqhull/geom.c @@ -6,9 +6,9 @@ see qh-geom.htm and geom.h - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/geom.c#3 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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 */ @@ -465,7 +465,7 @@ facetT *qh_findbestnew(pointT *point, facetT *startfacet, } /* end of !flipped */ } /* FORALLfacet from startfacet or qh newfacet_list */ } - if (testhorizon || !bestfacet) + 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; @@ -502,7 +502,7 @@ facetT *qh_findbestnew(pointT *point, facetT *startfacet, notes: assumes numrow == numcol-1 - see Golub & van Loan 4.4-9 for back substitution + 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) @@ -682,7 +682,7 @@ pointT *qh_getcenter(setT *vertices) { *coord= 0.0; FOREACHvertex_(vertices) *coord += vertex->point[k]; - *coord /= count; + *coord /= count; /* count>=2 by QH6003 */ } return(center); } /* getcenter */ @@ -801,7 +801,7 @@ void qh_normalize(coordT *normal, int dim, boolT toporient) { if nearzero sets norm to direction of maximum value */ -void qh_normalize2 (coordT *normal, int dim, boolT toporient, +void qh_normalize2(coordT *normal, int dim, boolT toporient, realT *minnorm, boolT *ismin) { int k; realT *colp, *maxp, norm= 0, temp, *norm1, *norm2, *norm3; @@ -894,7 +894,7 @@ pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist) { pointT *newpoint, *np, *normal; int normsize= qh normal_size; int k; - void **freelistp; /* used !qh_NOmem */ + void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */ qh_memalloc_(normsize, freelistp, newpoint, pointT); np= newpoint; @@ -932,7 +932,7 @@ void qh_setfacetplane(facetT *facet) { int normsize= qh normal_size; int k,i, oldtrace= 0; realT dist; - void **freelistp; /* used !qh_NOmem */ + void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */ coordT *coord, *gmcoord; pointT *point0= SETfirstt_(facet->vertices, vertexT)->point; boolT nearzero= False; @@ -1110,7 +1110,7 @@ void qh_sethyperplane_det(int dim, coordT **rows, coordT *point0, if (dim == 2) { normal[0]= dY(1,0); normal[1]= dX(0,1); - qh_normalize2 (normal, dim, toporient, NULL, NULL); + 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) { @@ -1120,7 +1120,7 @@ void qh_sethyperplane_det(int dim, coordT **rows, coordT *point0, 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); + qh_normalize2(normal, dim, toporient, NULL, NULL); *offset= -(point0[0]*normal[0] + point0[1]*normal[1] + point0[2]*normal[2]); maxround= qh DISTround; @@ -1148,7 +1148,7 @@ void qh_sethyperplane_det(int dim, coordT **rows, coordT *point0, 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); + 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; @@ -1229,3 +1229,6 @@ void qh_sethyperplane_gauss(int dim, coordT **rows, pointT *point0, for (k=dim-1; k--; ) *offset -= *pointcoord++ * *normalcoef++; } /* sethyperplane_gauss */ + + + diff --git a/extern/qhull/geom.h b/extern/libqhull/geom.h similarity index 96% rename from extern/qhull/geom.h rename to extern/libqhull/geom.h index b1a3aeccc7c0..16ef48d2d7ae 100644 --- a/extern/qhull/geom.h +++ b/extern/libqhull/geom.h @@ -6,9 +6,9 @@ see qh-geom.htm and geom.c - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/geom.h#3 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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 @@ -113,7 +113,7 @@ 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, +void qh_normalize2(coordT *normal, int dim, boolT toporient, realT *minnorm, boolT *ismin); pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist); @@ -171,3 +171,6 @@ coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feas pointT *qh_voronoi_center(int dim, setT *points); #endif /* qhDEFgeom */ + + + diff --git a/extern/qhull/geom2.c b/extern/libqhull/geom2.c similarity index 96% rename from extern/qhull/geom2.c rename to extern/libqhull/geom2.c index 2ba4a9f251f1..82ec4936efe6 100644 --- a/extern/qhull/geom2.c +++ b/extern/libqhull/geom2.c @@ -7,9 +7,9 @@ see qh-geom.htm and geom.h - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/geom2.c#3 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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 */ @@ -23,6 +23,8 @@ 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; @@ -34,7 +36,7 @@ coordT *qh_copypoints(coordT *points, int numpoints, int dimension) { numpoints); qh_errexit(qh_ERRmem, NULL, NULL); } - memcpy((char *)newpoints, (char *)points, (size_t)size); + memcpy((char *)newpoints, (char *)points, (size_t)size); /* newpoints!=0 by QH6004 */ return newpoints; } /* copypoints */ @@ -89,13 +91,13 @@ realT qh_determinant(realT **rows, int dim, boolT *nearzero) { }else if (dim == 2) { det= det2_(rows[0][0], rows[0][1], rows[1][0], rows[1][1]); - if (fabs_(det) < qh NEARzero[1]) /* not really correct, what should this be? */ + 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) < qh NEARzero[2]) /* not really correct, what should this be? */ + 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*/ @@ -367,8 +369,7 @@ realT qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp) { max dist round for REALepsilon notes: - calculate roundoff error according to - Lemma 3.2-1 of Golub and van Loan "Matrix Computation" + 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 */ @@ -748,7 +749,7 @@ void qh_getarea(facetT *facetlist) { overwrites rows[dim][dim] notes: - see Golub & van Loan Algorithm 6.2-2 + see Golub & van Loan, 1983, Algorithm 6.2-2, "Modified Gram-Schmidt" overflow due to small divisors not handled design: @@ -1031,8 +1032,9 @@ REALepsilon %g REALmin %g REALmax %g -REALmax %g\n", qh MAXsumcoord += maxcoord; qh_setappend(&set, maximum); qh_setappend(&set, minimum); - /* calculation of qh NEARzero is based on error formula 4.4-13 of - Golub & van Loan, authors say n^3 can be ignored and 10 be used in + /* 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; } @@ -1209,7 +1211,7 @@ realT qh_minabsval(realT *normal, int dim) { /*--------------------------------- - qh_mindif ( vecA, vecB, dim ) + qh_mindif( vecA, vecB, dim ) return index of min abs. difference of two vectors */ int qh_mindiff(realT *vecA, realT *vecB, int dim) { @@ -1423,12 +1425,12 @@ void qh_projectinput(void) { int k,i; int newdim= qh input_dim, newnum= qh num_points; signed char *project; - int size= (qh input_dim+1)*sizeof(*project); + int projectsize= (qh input_dim+1)*sizeof(*project); pointT *newpoints, *coord, *infinity; realT paraboloid, maxboloid= 0; - project= (signed char*)qh_memalloc(size); - memset((char*)project, 0, (size_t)size); + 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; @@ -1442,14 +1444,17 @@ void qh_projectinput(void) { 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=(coordT*)qh_malloc(newnum*newdim*sizeof(coordT)))){ + 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")); @@ -1459,17 +1464,19 @@ void qh_projectinput(void) { 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, (qh input_dim+1)*sizeof(*project)); + 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; @@ -1825,9 +1832,10 @@ void qh_setdelaunay(int dim, int count, pointT *points) { halfspace is normal coefficients and offset. returns: - false if feasible point is outside of hull (error message already reported) + 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 @@ -1892,15 +1900,17 @@ boolT qh_sethalfspace(int dim, coordT *coords, coordT **nextp, 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', also set qh feasible_point. It is a malloc'd array - that is freed by qh_freebuffers. + 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 @@ -1922,6 +1932,7 @@ coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feas 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); } @@ -1947,7 +1958,7 @@ coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feas if two facets are in different quadrants set issharp */ -boolT qh_sharpnewfacets() { +boolT qh_sharpnewfacets(void) { facetT *facet; boolT issharp = False; int *quadrant, k; @@ -1982,11 +1993,12 @@ boolT qh_sharpnewfacets() { gh.gm_matrix/qh.gm_row are scratch buffers returns: - center as a temporary point + 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: @@ -2009,6 +2021,7 @@ pointT *qh_voronoi_center(int dim, setT *points) { 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); @@ -2078,3 +2091,4 @@ pointT *qh_voronoi_center(int dim, setT *points) { qh_settempfree(&simplex); return center; } /* voronoi_center */ + diff --git a/extern/qhull/global.c b/extern/libqhull/global.c similarity index 91% rename from extern/qhull/global.c rename to extern/libqhull/global.c index 90f956d7e885..0328fea7b91b 100644 --- a/extern/qhull/global.c +++ b/extern/libqhull/global.c @@ -11,17 +11,15 @@ see qhull_a.h for internal functions - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/global.c#15 $$Change: 1490 $ - $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $ + 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 =======================*/ -int qhull_inuse= 0; /* not used */ - #if qh_QHpointer qhT *qh_qh= NULL; /* pointer to all global variables */ #else @@ -35,19 +33,22 @@ qhT qh_qh; /* all global variables. 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 + 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 = "2012.1 2012/02/18"; +const char qh_version[]= "2015.2 2016/01/18"; +const char qh_version2[]= "qhull 7.2.0 (2015.2 2016/01/18)"; /*--------------------------------- @@ -73,7 +74,7 @@ void qh_appendprint(qh_PRINT format) { qh_checkflags( commandStr, hiddenFlags ) errors if commandStr contains hiddenFlags - hiddenFlags starts and ends with a space and is space deliminated (checked) + hiddenFlags starts and ends with a space and is space delimited (checked) notes: ignores first word (e.g., "qconvex i") @@ -200,7 +201,7 @@ void qh_clear_outputflags(void) { qh TRInormals= False; qh USEstdout= False; qh VERIFYoutput= False; - for (k=qh input_dim+1; k--; ) { /* duplicated in qh_initqhull_buffers and qh_clear_ouputflags */ + 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; @@ -239,7 +240,7 @@ unsigned long qh_clock(void) { #if (qh_CLOCKtype == 2) struct tms time; - static long clktck; /* initialized first call */ + static long clktck; /* initialized first call and never updated */ double ratio, cpu; unsigned long ticks; @@ -433,12 +434,13 @@ void qh_freeqhull(boolT allmem) { >-------------------------------- qh_freeqhull2( allmem ) - free global memory + free global memory and set qhT to 0 if !allmem, - does not free short memory (freed by qh_memfreeshort) + 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() @@ -450,8 +452,8 @@ qh_freeqhull2( allmem ) */ void qh_freeqhull2(boolT allmem) { - trace1((qh ferr, 1006, "qh_freeqhull2: free global memory\n")); 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(); @@ -560,6 +562,7 @@ void qh_init_B(coordT *points, int numpoints, int dim, boolT ismalloc) { 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) @@ -584,6 +587,7 @@ void qh_init_qhull_command(int argc, char *argv[]) { 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 @@ -597,15 +601,15 @@ void qh_init_qhull_command(int argc, char *argv[]) { 'prompt' in unix.c for documentation design: - for each space-deliminated option group + for each space-delimited option group if top-level option check syntax - append approriate option to option string + append appropriate option to option string set appropriate global variable or append printFormat to print options else for each sub-option check syntax - append approriate option to option string + append appropriate option to option string set appropriate global variable or append printFormat to print options */ void qh_initflags(char *command) { @@ -614,6 +618,10 @@ void qh_initflags(char *command) { 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'; @@ -1149,6 +1157,10 @@ void qh_initflags(char *command) { 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]); @@ -1334,7 +1346,9 @@ void qh_initflags(char *command) { qh_copyfilename(filename, (int)sizeof(filename), s, (int)(t-s)); /* WARN64 */ s= t; - if (!freopen(filename, "w", stdout)) { + 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 { @@ -1439,7 +1453,7 @@ void qh_initqhull_buffers(void) { 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_ouputflags */ + 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; @@ -1594,7 +1608,7 @@ void qh_initqhull_globals(coordT *points, int numpoints, int dim, boolT ismalloc qh TRACElastrun= qh IStracing; /* qh_build_withrestart duplicates next conditional */ if (qh IStracing != -1) qh IStracing= 0; - }else if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) { + }else if (qh TRACEpoint != qh_IDunknown || qh TRACEdist < REALmax/2 || qh TRACEmerge) { qh TRACElevel= (qh IStracing? qh IStracing : 3); qh IStracing= 0; } @@ -1854,7 +1868,7 @@ void qh_initqhull_start2(FILE *infile, FILE *outfile, FILE *errfile) { qh ferr= errfile; qh fin= infile; qh fout= outfile; - qh furthest_id= -1; + qh furthest_id= qh_IDunknown; qh JOGGLEmax= REALmax; qh KEEPminArea = REALmax; qh last_low= REALmax; @@ -1882,12 +1896,14 @@ void qh_initqhull_start2(FILE *infile, FILE *outfile, FILE *errfile) { qh totarea= 0.0; qh totvol= 0.0; qh TRACEdist= REALmax; - qh TRACEpoint= -1; /* recompile or use 'TPn' */ + 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+1; /* disallow 0 [UsingLibQhull::NOqhRunId] */ + 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 */ @@ -2011,6 +2027,80 @@ void qh_initthresholds(char *command) { } } /* 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 */ + /*--------------------------------- @@ -2124,3 +2214,4 @@ qhT *qh_save_qhull(void) { } /* save_qhull */ #endif + diff --git a/extern/qhull/io.c b/extern/libqhull/io.c similarity index 97% rename from extern/qhull/io.c rename to extern/libqhull/io.c index 092e3ef79a53..401987ec0827 100644 --- a/extern/qhull/io.c +++ b/extern/libqhull/io.c @@ -13,9 +13,9 @@ 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-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/io.c#3 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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" @@ -84,11 +84,11 @@ void qh_produce_output2(void) { /*--------------------------------- - dfacet( id ) + qh_dfacet( id ) print facet by id, for debugging */ -void dfacet(unsigned id) { +void qh_dfacet(unsigned id) { facetT *facet; FORALLfacets { @@ -103,10 +103,10 @@ void dfacet(unsigned id) { /*--------------------------------- - dvertex( id ) + qh_dvertex( id ) print vertex by id, for debugging */ -void dvertex(unsigned id) { +void qh_dvertex(unsigned id) { vertexT *vertex; FORALLvertices { @@ -118,18 +118,6 @@ void dvertex(unsigned id) { } /* dvertex */ -/*--------------------------------- - - qh_compare_vertexpoint( p1, p2 ) - used by qsort() to order vertices by point id -*/ -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 */ - /*--------------------------------- @@ -179,6 +167,20 @@ int qh_compare_facetvisit(const void *p1, const void *p2) { 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 */ + /*--------------------------------- @@ -514,7 +516,7 @@ setT *qh_detvridge(vertexT *vertex) { if neighbor selected add neighbor to set of Voronoi vertices */ -setT *qh_detvridge3 (vertexT *atvertex, vertexT *vertex) { +setT *qh_detvridge3(vertexT *atvertex, vertexT *vertex) { setT *centers= qh_settemp(qh TEMPsize); setT *tricenters= qh_settemp(qh TEMPsize); facetT *neighbor, **neighborp, *facet= NULL; @@ -669,10 +671,10 @@ int qh_eachvoronoi(FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT 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); + centers= qh_detvridge3(atvertex, vertex); else centers= qh_detvridge(vertex); - (*printvridge) (fp, atvertex, vertex, centers, unbounded); + (*printvridge)(fp, atvertex, vertex, centers, unbounded); qh_settempfree(¢ers); } } @@ -1068,19 +1070,19 @@ void qh_order_vertexneighbors(vertexT *vertex) { */ void qh_prepare_output(void) { if (qh VORONOI) { - qh_clearcenters (qh_ASvoronoi); + 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_checkpolygon(qh facet_list); } - qh_findgood_all (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); + qh_markkeep(qh facet_list); if (qh PRINTstatistics) qh_collectstatistics(); } @@ -1152,9 +1154,9 @@ void qh_printafacet(FILE *fp, qh_PRINT format, facetT *facet, boolT printall) { maximize_(color[k], -1.0); minimize_(color[k], +1.0); } - qh_projectdim3 (color, color); + qh_projectdim3(color, color); if (qh PRINTdim != qh hull_dim) - qh_normalize2 (color, 3, True, NULL, NULL); + qh_normalize2(color, 3, True, NULL, NULL); if (qh hull_dim <= 2) qh_printfacet2geom(fp, facet, color); else if (qh hull_dim == 3) { @@ -1393,14 +1395,14 @@ void qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, b if (qh PRINTdim == 4) qh_printpoint(fp, NULL, point); else - qh_printpoint3 (fp, point); + qh_printpoint3(fp, point); } } FOREACHpoint_(qh other_points) { if (qh PRINTdim == 4) qh_printpoint(fp, NULL, point); else - qh_printpoint3 (fp, point); + qh_printpoint3(fp, point); } qh_fprintf(fp, 9047, "0 1 1 1 # color of points\n"); } @@ -1433,7 +1435,7 @@ void qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, b qh firstcentrum= True; if (qh PRINTcoplanar&& !qh PRINTspheres) { FOREACHvertex_(vertices) - qh_printpointvect2 (fp, vertex->point, NULL, qh interior_point, qh PRINTradius); + qh_printpointvect2(fp, vertex->point, NULL, qh interior_point, qh PRINTradius); } FORALLfacet_(facetlist) { if (!printall && qh_skipfacet(facet)) @@ -1445,9 +1447,9 @@ void qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, b if (!qh PRINTcoplanar) continue; FOREACHpoint_(facet->coplanarset) - qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius); + qh_printpointvect2(fp, point, facet->normal, NULL, qh PRINTradius); FOREACHpoint_(facet->outsideset) - qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius); + qh_printpointvect2(fp, point, facet->normal, NULL, qh PRINTradius); } FOREACHfacet_(facets) { if (!printall && qh_skipfacet(facet)) @@ -1459,9 +1461,9 @@ void qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, b if (!qh PRINTcoplanar) continue; FOREACHpoint_(facet->coplanarset) - qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius); + qh_printpointvect2(fp, point, facet->normal, NULL, qh PRINTradius); FOREACHpoint_(facet->outsideset) - qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius); + qh_printpointvect2(fp, point, facet->normal, NULL, qh PRINTradius); } } qh_settempfree(&vertices); @@ -1529,9 +1531,9 @@ void qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, b + numfacets - numsimplicial, numsimplicial + numridges, totneighbors/2); } FORALLpoints - qh_printpointid(qh fout, NULL, num, point, -1); + qh_printpointid(qh fout, NULL, num, point, qh_IDunknown); FOREACHpoint_(qh other_points) - qh_printpointid(qh fout, NULL, num, point, -1); + qh_printpointid(qh fout, NULL, num, point, qh_IDunknown); if (format == qh_PRINTtriangles && qh hull_dim > 2) { FORALLfacets { if (!facet->simplicial && facet->visitid) @@ -1596,7 +1598,7 @@ void qh_printcenter(FILE *fp, qh_PRINT format, const char *string, facetT *facet for (k=0; k < num; k++) qh_fprintf(fp, 9068, qh_REAL_1, qh_INFINITE); } - }else /* qh CENTERtype == qh_AScentrum */ { + }else /* qh.CENTERtype == qh_AScentrum */ { num= qh hull_dim; if (format == qh_PRINTtriangles && qh DELAUNAY) num--; @@ -1659,15 +1661,15 @@ void qh_printcentrum(FILE *fp, facetT *facet, realT radius) { 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_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_printpoint3(fp, centrum); qh_fprintf(fp, 9078, "1 }}}\n"); qh_memfree(projpt, qh normal_size); qh_printpointvect(fp, centrum, facet->normal, NULL, radius, green); @@ -1871,7 +1873,7 @@ void qh_printextremes_2d(FILE *fp, facetT *facetlist, setT *facets, boolT printa 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); + qh_errexit2(qh_ERRqhull, facet, nextfacet); } if (facet->visitid) { if (vertexA->visitid != qh vertex_visit) { @@ -1956,7 +1958,7 @@ void qh_printfacet(FILE *fp, facetT *facet) { 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 occured. + so a DISTround error may have occurred. */ void qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]) { pointT *point0, *point1; @@ -2144,7 +2146,7 @@ void qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offs 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 occured. + so a DISTround error may have occurred. */ void qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]) { setT *points, *vertices; @@ -2238,7 +2240,7 @@ void qh_printfacet3math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst) qh_memfree(point, qh normal_size); qh_settempfree(&points); qh_settempfree(&vertices); - qh_fprintf(fp, 9110, endfmt); + qh_fprintf(fp, 9110, "%s", endfmt); } /* printfacet3math */ @@ -2514,7 +2516,7 @@ void qh_printfacetheader(FILE *fp, facetT *facet) { 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, -1); + 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); @@ -2655,7 +2657,7 @@ void qh_printfacets(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, 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, -1); + qh_printpointid(fp, NULL, qh hull_dim, center, qh_IDunknown); qh_memfree(center, qh normal_size); qh_settempfree(&vertices); }else if (format == qh_PRINTextremes) { @@ -2747,7 +2749,7 @@ void qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2, 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_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]); @@ -2841,11 +2843,10 @@ void qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT *fac returns: if string is defined - prints 'string p%d' (skips p%d if id=-1) + prints 'string p%d'. Skips p%d if id=qh_IDunknown(-1) or qh_IDnone(-3) notes: nop if point is NULL - prints id unless it is undefined (-1) Same as QhullPoint's printPoint */ void qh_printpoint(FILE *fp, const char *string, pointT *point) { @@ -2862,7 +2863,7 @@ void qh_printpointid(FILE *fp, const char *string, int dim, pointT *point, int i return; if (string) { qh_fprintf(fp, 9211, "%s", string); - if (id != -1) + if (id != qh_IDunknown && id != qh_IDnone) qh_fprintf(fp, 9212, " p%d: ", id); } for (k=dim; k--; ) { @@ -2881,11 +2882,11 @@ void qh_printpointid(FILE *fp, const char *string, int dim, pointT *point, int i 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) { +void qh_printpoint3(FILE *fp, pointT *point) { int k; realT p[4]; - qh_projectdim3 (point, p); + 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)); @@ -2987,7 +2988,7 @@ void qh_printpointvect(FILE *fp, pointT *point, coordT *normal, pointT *center, diff[k]= 0; } if (center) - qh_normalize2 (diff, qh hull_dim, True, NULL, NULL); + 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); @@ -2999,7 +3000,7 @@ void qh_printpointvect(FILE *fp, pointT *point, coordT *normal, pointT *center, 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) { +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); @@ -3101,7 +3102,7 @@ INST geom {define vsphere OFF\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_printpoint3(fp, vertex->point); qh_fprintf(fp, 9229, "1\n"); } qh_fprintf(fp, 9230, "}}}\n"); @@ -3156,9 +3157,9 @@ void qh_printvdiagram(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets qh_errexit(qh_ERRinput, NULL, NULL); } vertices= qh_markvoronoi(facetlist, facets, printall, &isLower, &numcenters); - totcount= qh_printvdiagram2 (NULL, NULL, vertices, innerouter, False); + totcount= qh_printvdiagram2(NULL, NULL, vertices, innerouter, False); qh_fprintf(fp, 9231, "%d\n", totcount); - totcount= qh_printvdiagram2 (fp, printvridge, vertices, innerouter, True /* inorder*/); + totcount= qh_printvdiagram2(fp, printvridge, vertices, innerouter, True /* inorder*/); qh_settempfree(&vertices); #if 0 /* for testing qh_eachvoronoi_all */ qh_fprintf(fp, 9232, "\n"); @@ -3196,7 +3197,7 @@ void qh_printvdiagram(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets see: qh_eachvoronoi_all() */ -int qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder) { +int qh_printvdiagram2(FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder) { int totcount= 0; int vertex_i, vertex_n; vertexT *vertex; @@ -3554,7 +3555,7 @@ void qh_printvridge(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, notes: allocate 4 elements to destination just in case */ -void qh_projectdim3 (pointT *source, pointT *destination) { +void qh_projectdim3(pointT *source, pointT *destination) { int i,k; for (k=0, i=0; k < qh hull_dim; k++) { @@ -3578,7 +3579,7 @@ void qh_projectdim3 (pointT *source, pointT *destination) { returns: number of lines read from qh.fin - sets qh.FEASIBLEpoint with malloc'd coordinates + sets qh.feasible_point with malloc'd coordinates notes: checks for qh.HALFspace @@ -3791,7 +3792,7 @@ coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc) { 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= + 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", @@ -3956,11 +3957,12 @@ Type 'qhull' for a short list of options.\n"); >-------------------------------- qh_setfeasible( dim ) - set qh.FEASIBLEpoint from qh.feasible_string in "n,n,n" or "n n n" format + 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; @@ -4057,3 +4059,4 @@ char *qh_skipfilename(char *filename) { s++; return s; } /* skipfilename */ + diff --git a/extern/qhull/io.h b/extern/libqhull/io.h similarity index 91% rename from extern/qhull/io.h rename to extern/libqhull/io.h index 580d51b9b3fd..eca0369d30e9 100644 --- a/extern/qhull/io.h +++ b/extern/libqhull/io.h @@ -6,9 +6,9 @@ see README, libqhull.h and io.c - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/io.h#3 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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 @@ -77,19 +77,19 @@ typedef void (*printvridgeT)(FILE *fp, vertexT *vertex, vertexT *vertexA, setT * /*============== -prototypes in alphabetical order =========*/ -void dfacet(unsigned id); -void dvertex(unsigned id); +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 */ +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); +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); @@ -131,14 +131,14 @@ void qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT * 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_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_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); +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); @@ -149,7 +149,7 @@ void qh_printvnorm(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers 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); +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); diff --git a/extern/qhull/libqhull.c b/extern/libqhull/libqhull.c similarity index 97% rename from extern/qhull/libqhull.c rename to extern/libqhull/libqhull.c index 34a0fc611289..7696a8a9fee8 100644 --- a/extern/qhull/libqhull.c +++ b/extern/libqhull/libqhull.c @@ -10,9 +10,9 @@ see qhull_a.h for internal functions - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/libqhull.c#4 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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" @@ -85,10 +85,10 @@ void qh_qhull(void) { qh postmerge_cos, qh TESTvneighbors); if (qh visible_list == qh facet_list) { /* i.e., merging done */ qh findbestnew= True; - qh_partitionvisible(/*visible_list, newfacet_list*/ !qh_ALL, &numoutside); + 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 */); + qh_deletevisible(/*qh.visible_list*/); + qh_resetlists(False, qh_RESETvisible /*qh.visible_list newvertex_list newfacet_list */); } } if (qh DOcheckmax){ @@ -174,7 +174,7 @@ boolT qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist) { int numpart, numpoints, numnew, firstnew; qh maxoutdone= False; - if (qh_pointid(furthest) == -1) + 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"); @@ -202,7 +202,7 @@ boolT qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist) { 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 */); + qh_resetlists(False, qh_RESETvisible /*qh.visible_list newvertex_list newfacet_list */); return True; } zzinc_(Zprocessed); @@ -219,7 +219,7 @@ boolT qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist) { FORALLnew_facets qh_delfacet(newfacet); qh_delvertex(vertex); - qh_resetlists(True, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */); + qh_resetlists(True, qh_RESETvisible /*qh.visible_list newvertex_list newfacet_list */); zinc_(Znotgoodnew); facet->notfurthest= True; return True; @@ -247,7 +247,7 @@ boolT qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist) { } }else if (qh BESToutside) qh findbestnew= True; - qh_partitionvisible(/*visible_list, newfacet_list*/ !qh_ALL, &numpoints); + qh_partitionvisible(/*qh.visible_list*/ !qh_ALL, &numpoints); qh findbestnew= False; qh findbest_notsharp= False; zinc_(Zpbalance); @@ -255,7 +255,7 @@ boolT qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist) { * (qh num_points - qh num_vertices)/qh num_vertices; wadd_(Wpbalance, pbalance); wadd_(Wpbalance2, pbalance * pbalance); - qh_deletevisible(/*qh visible_list*/); + qh_deletevisible(/*qh.visible_list*/); zmax_(Zmaxvertex, qh num_vertices); qh NEWfacets= False; if (qh IStracing >= 4) { @@ -271,7 +271,7 @@ boolT qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist) { } 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_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)); @@ -283,6 +283,7 @@ boolT qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist) { 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() */ @@ -296,7 +297,7 @@ void qh_build_withrestart(void) { zzinc_(Zretry); wmax_(Wretrymax, qh JOGGLEmax); /* QH7078 warns about using 'TCn' with 'QJn' */ - qh STOPcone= -1; /* if break from joggle, prevents normal output */ + qh STOPcone= qh_IDunknown; /* if break from joggle, prevents normal output */ } if (!qh RERUN && qh JOGGLEmax < REALmax/2) { if (qh build_cnt > qh_JOGGLEmaxretry) { @@ -322,7 +323,7 @@ void qh_build_withrestart(void) { 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 != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) { + if (qh TRACEpoint != qh_IDunknown || qh TRACEdist < REALmax/2 || qh TRACEmerge) { qh TRACElevel= (qh IStracing? qh IStracing : 3); qh IStracing= 0; } @@ -458,7 +459,7 @@ At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n if (qh TRACEpoint == furthestid) { qh IStracing= qh TRACElevel; qhmem.IStracing= qh TRACElevel; - }else if (qh TRACEpoint != -1 && qh TRACEdist < REALmax/2) { + }else if (qh TRACEpoint != qh_IDunknown && qh TRACEdist < REALmax/2) { qh IStracing= 0; qhmem.IStracing= 0; } @@ -487,14 +488,14 @@ At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n getid_(facet), qh num_outside+1, cpu, qh furthest_id); } zmax_(Zvisit2max, (int)qh visit_id/2); - if (qh visit_id > (unsigned) INT_MAX) { + 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/2) { /* 31 bits */ + if (qh vertex_visit > (unsigned) INT_MAX) { /* 31 bits */ zinc_(Zvvisit); qh vertex_visit= 0; FORALLvertices @@ -692,7 +693,7 @@ pointT *qh_nextfurthest(facetT **visible) { } if (!qh RANDOMoutside && !qh VIRTUALmemory) { if (qh PICKfurthest) { - qh_furthestnext(/* qh facet_list */); + qh_furthestnext(/* qh.facet_list */); facet= qh facet_next; } *visible= facet; @@ -1113,7 +1114,7 @@ void qh_partitionpoint(pointT *point, facetT *facet) { else partition vertex into coplanar sets of new facets */ -void qh_partitionvisible(/*visible_list*/ boolT allpoints, int *numoutside) { +void qh_partitionvisible(/*qh.visible_list*/ boolT allpoints, int *numoutside) { facetT *visible, *newfacet; pointT *point, **pointp; int coplanar=0, size; @@ -1181,6 +1182,7 @@ 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); } } @@ -1397,3 +1399,5 @@ Convex hull of %d points in %d-d:\n\n", size, qh hull_dim); } qh_fprintf(fp, 9345, "\n"); } /* printsummary */ + + diff --git a/extern/qhull/libqhull.h b/extern/libqhull/libqhull.h similarity index 90% rename from extern/qhull/libqhull.h rename to extern/libqhull/libqhull.h index 7a132267bde9..677085808d54 100644 --- a/extern/qhull/libqhull.h +++ b/extern/libqhull/libqhull.h @@ -6,13 +6,13 @@ see qh-qhull.htm, qhull_a.h - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/libqhull.h#7 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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 + of using qh is "qh.DROPdim" which accesses the DROPdim field of qh_qh. Similarly, access to qh_qhstat is via the 'qhstat' macro. @@ -31,8 +31,13 @@ /*=========================== -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 @@ -56,7 +61,8 @@ /*============ constants and basic types ====================*/ -extern const char *qh_version; /* defined in global.c */ +extern const char qh_version[]; /* defined in global.c */ +extern const char qh_version2[]; /* defined in global.c */ /*---------------------------------- @@ -78,8 +84,21 @@ extern const char *qh_version; /* defined in global.c */ 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; /*---------------------------------- @@ -111,6 +130,8 @@ extern const char *qh_version; /* defined in global.c */ #define qh_False 0 #define qh_True 1 +#include "stat.h" /* after define of boolT */ + /*---------------------------------- @@ -119,7 +140,9 @@ extern const char *qh_version; /* defined in global.c */ */ typedef enum { - qh_ASnone = 0, qh_ASvoronoi, qh_AScentrum + 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; @@ -132,7 +155,7 @@ qh_CENTER; notes: - some of these names are similar to qh names. The similar names are only + 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, @@ -181,13 +204,15 @@ qh_FILEstderr Fake stderr to distinguish error output from normal output For C++ interface. Must redefine qh_fprintf_qhull */ -#define qh_FILEstderr (FILE*)1 +#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; @@ -198,11 +223,6 @@ typedef struct facetT facetT; typedef struct setT setT; /* defined in qset.h */ #endif -#ifndef DEFqhstatT -#define DEFqhstatT 1 -typedef struct qhstatT qhstatT; /* defined in stat.h */ -#endif - /*---------------------------------- @@ -263,9 +283,13 @@ struct facetT { facetT *trivisible; /* visible facet for ->tricoplanar facets during qh_triangulate() */ facetT *triowner; /* owner facet for ->tricoplanar, !isarea facets w/ ->keepcentrum */ }f; - coordT *center; /* centrum for convexity, qh CENTERtype == qh_AScentrum */ - /* Voronoi center, qh CENTERtype == qh_ASvoronoi */ - /* if tricoplanar, shared with a neighbor */ + 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 @@ -284,16 +308,16 @@ struct facetT { 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 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 ->center, ->normal, ->offset, ->maxoutside */ /* 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) */ - /* one tricoplanar has ->keepcentrum and ->coplanarset */ /* during qh_triangulate, f.trivisible points to original facet */ - flagT newfacet:1; /* True if facet on qh newfacet_list (new or merged) */ + 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 */ @@ -349,7 +373,7 @@ struct ridgeT { 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:24; /* unique identifier, =>room for 8 flags, bit field matches qh.ridge_id */ + 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 @@ -375,19 +399,15 @@ struct vertexT { pointT *point; /* hull_dim coordinates (coordT) */ setT *neighbors; /* neighboring facets of vertex, qh_vertexneighbors() inits in io.c or after first merge */ - unsigned visitid:31; /* for use with qh vertex_visit, size must match */ - flagT seen2:1; /* another seen flag */ - unsigned id:24; /* unique identifier, bit field matches qh.vertex_id */ - unsigned dim:4; /* dimension of point if non-zero, used by cpp */ - /* =>room for 4 flags */ + 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 */ + flagT deleted:1; /* true if vertex on qh.del_vertices */ + flagT newlist:1; /* true if vertex on qh.newvertex_list */ }; -#define MAX_vdim 15 /* Maximum size of vertex->dim */ - /*======= -global variables -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 { /*-= 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 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) */ + 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(-) @@ -536,7 +574,7 @@ struct qhT { 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 normals (sets Qt) */ + 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 */ @@ -554,9 +592,9 @@ struct qhT { 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 */ + 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 */ + 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 */ @@ -589,7 +627,7 @@ struct qhT { 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 */ + 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 */ @@ -615,11 +653,11 @@ struct qhT { 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() */ + 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() */ + 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_meminit */ + 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*/ @@ -642,7 +680,7 @@ struct qhT { 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 preceeding newfacet_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 */ @@ -654,14 +692,14 @@ struct qhT { 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 visble faces (num_visible) */ + 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:24; /* ID of next, new ridge from newridge() */ - unsigned vertex_id:24; /* ID of next, new vertex from newvertex() */ + unsigned ridge_id; /* ID of next, new ridge from newridge() */ + unsigned vertex_id; /* ID of next, new vertex from newvertex() */ /*---------------------------------- @@ -696,7 +734,7 @@ struct qhT { 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 */ + 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 */ @@ -706,7 +744,7 @@ struct qhT { 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:31; /* unique ID for searching vertices, reset with qh_buildtracing */ + 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) */ @@ -780,9 +818,9 @@ struct qhT { getid_(p) return int ID for facet, ridge, or vertex - return -1 if NULL + return qh_IDunknown(-1) if NULL */ -#define getid_(p) ((p) ? (int)((p)->id) : -1) +#define getid_(p) ((p) ? (int)((p)->id) : qh_IDunknown) /*============== FORALL macros ===================*/ @@ -1009,6 +1047,7 @@ 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); @@ -1053,6 +1092,7 @@ 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); @@ -1061,8 +1101,8 @@ qhT *qh_save_qhull(void); /***** -io.c prototypes (duplicated from io.h) ***********************/ -void dfacet( unsigned id); -void dvertex( unsigned id); +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); @@ -1086,9 +1126,9 @@ 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*/); +void qh_triangulate(void /*qh.facet_list*/); -/********* -rboxpoints.c prototypes **********************/ +/********* -rboxlib.c prototypes **********************/ int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command); void qh_errexit_rbox(int exitcode); diff --git a/extern/qhull/mem.c b/extern/libqhull/mem.c similarity index 80% rename from extern/qhull/mem.c rename to extern/libqhull/mem.c index f0a8a0fc3273..db72bb4e19d9 100644 --- a/extern/qhull/mem.c +++ b/extern/libqhull/mem.c @@ -29,11 +29,12 @@ qh-mem.htm and mem.h global.c (qh_initbuffers) for an example of using mem.c - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/mem.c#4 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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 @@ -49,6 +50,7 @@ typedef struct facetT facetT; 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 @@ -96,6 +98,8 @@ static int qh_intcompare(const void *i, const void *j) { 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 @@ -135,8 +139,8 @@ void *qh_memalloc(int insize) { return(object); }else { qhmem.cntshort++; - if (outsize > qhmem .freesize) { - qhmem .totdropped += qhmem .freesize; + if (outsize > qhmem.freesize) { + qhmem.totdropped += qhmem.freesize; if (!qhmem.curbuffer) bufsize= qhmem.BUFinit; else @@ -146,7 +150,7 @@ void *qh_memalloc(int insize) { qh_errexit(qhmem_ERRmem, NULL, NULL); } *((void **)newbuffer)= qhmem.curbuffer; /* prepend newbuffer to curbuffer - list */ + list. newbuffer!=0 by QH6080 */ qhmem.curbuffer= newbuffer; size= (sizeof(void **) + qhmem.ALIGNmask) & ~qhmem.ALIGNmask; qhmem.freemem= (void *)((char *)newbuffer+size); @@ -176,8 +180,8 @@ void *qh_memalloc(int insize) { qh_errexit(qhmem_ERRqhull, NULL, NULL); } outsize= insize; - qhmem .cntlong++; - qhmem .totlong += outsize; + qhmem.cntlong++; + qhmem.totlong += outsize; if (qhmem.maxlong < qhmem.totlong) qhmem.maxlong= qhmem.totlong; if (!(object= qh_malloc((size_t)outsize))) { @@ -191,6 +195,35 @@ void *qh_memalloc(int insize) { } /* 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 */ + /*---------------------------------- @@ -216,11 +249,11 @@ void qh_memfree(void *object, int insize) { if (!object) return; if (insize <= qhmem.LASTsize) { - qhmem .freeshort++; + qhmem.freeshort++; idx= qhmem.indextable[insize]; outsize= qhmem.sizetable[idx]; - qhmem .totfree += outsize; - qhmem .totshort -= outsize; + qhmem.totfree += outsize; + qhmem.totshort -= outsize; freelistp= qhmem.freelists + idx; *((void **)object)= *freelistp; *freelistp= object; @@ -230,11 +263,11 @@ void qh_memfree(void *object, int insize) { 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; - qh_free(object); + 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 */ @@ -256,17 +289,17 @@ void qh_memfreeshort(int *curlong, int *totlong) { void *buffer, *nextbuffer; FILE *ferr; - *curlong= qhmem .cntlong - qhmem .freelong; - *totlong= qhmem .totlong; + *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); + 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 */ @@ -279,19 +312,24 @@ void qh_memfreeshort(int *curlong, int *totlong) { 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 */ - qhmem.ferr= ferr; + if (ferr) + qhmem.ferr= ferr; + else + qhmem.ferr= stderr; if (sizeof(void*) < sizeof(int)) { - qh_fprintf(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_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(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_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 */ /*-= qhmem .BUFsize || qhmem.LASTsize >= qhmem .BUFinit) { + 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); + qhmem.LASTsize, qhmem.BUFsize, qhmem.BUFinit); qh_errexit(qhmem_ERRmem, NULL, NULL); } if (!(qhmem.indextable= (int *)qh_malloc((qhmem.LASTsize+1) * sizeof(int)))) { @@ -366,7 +404,7 @@ void qh_memsetup(void) { void qh_memsize(int size) { int k; - if (qhmem .LASTsize) { + if (qhmem.LASTsize) { qh_fprintf(qhmem.ferr, 6089, "qhull error (qh_memsize): called after qhmem_setup\n"); qh_errexit(qhmem_ERRqhull, NULL, NULL); } @@ -391,19 +429,11 @@ void qh_memsize(int size) { Verifies that qhmem.totfree == sum of freelists */ void qh_memstatistics(FILE *fp) { - int i, count, totfree= 0; + int i; + int count; void *object; - 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, "qh_memstatistics internal error: totfree %d not equal to freelist total %d\n", qhmem.totfree, totfree); - qh_errexit(qhmem_ERRqhull, NULL, NULL); - } + qh_memcheck(); qh_fprintf(fp, 9278, "\nmemory statistics:\n\ %7d quick allocations\n\ %7d short allocations\n\ @@ -418,12 +448,12 @@ void qh_memstatistics(FILE *fp) { %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); + 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); @@ -431,7 +461,7 @@ void qh_memstatistics(FILE *fp) { } for (i=0; i < qhmem.TABLEsize; i++) { count=0; - for (object= qhmem .freelists[i]; object; object= *((void **)object)) + for (object= qhmem.freelists[i]; object; object= *((void **)object)) count++; qh_fprintf(fp, 9281, " %d->%d", qhmem.sizetable[i], count); } @@ -457,8 +487,8 @@ void *qh_memalloc(int insize) { qh_fprintf(qhmem.ferr, 6090, "qhull error (qh_memalloc): insufficient memory\n"); qh_errexit(qhmem_ERRmem, NULL, NULL); } - qhmem .cntlong++; - qhmem .totlong += insize; + qhmem.cntlong++; + qhmem.totlong += insize; if (qhmem.maxlong < qhmem.totlong) qhmem.maxlong= qhmem.totlong; if (qhmem.IStracing >= 5) @@ -471,24 +501,27 @@ void qh_memfree(void *object, int insize) { if (!object) return; qh_free(object); - qhmem .freelong++; - qhmem .totlong -= insize; + 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; + *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 */ - qhmem.ferr= ferr; + if (ferr) + qhmem.ferr= ferr; + else + qhmem.ferr= stderr; if (sizeof(void*) < sizeof(int)) { - qh_fprintf(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_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); } } @@ -513,9 +546,9 @@ void qh_memstatistics(FILE *fp) { %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); + qhmem.cntlong, + qhmem.freelong, + qhmem.maxlong, qhmem.totlong, qhmem.cntlong - qhmem.freelong); } #endif /* qh_NOmem */ @@ -533,10 +566,11 @@ void qh_memstatistics(FILE *fp) { 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; + *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/qhull/mem.h b/extern/libqhull/mem.h similarity index 94% rename from extern/qhull/mem.h rename to extern/libqhull/mem.h index d65cbe128e48..453f319df3ac 100644 --- a/extern/qhull/mem.h +++ b/extern/libqhull/mem.h @@ -11,9 +11,9 @@ and qh_errexit(qhmem_ERRqhull, NULL, NULL) otherwise - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/mem.h#4 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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 @@ -78,7 +78,9 @@ Trace short and quick memory allocations at T5 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 _MSC_VER && defined(_WIN64) +#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; @@ -125,7 +127,7 @@ struct qhmemT { /* global memory management variables */ 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, only user is qh_fprintf() */ + 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 */ @@ -150,7 +152,7 @@ struct qhmemT { /* global memory management variables */ /*---------------------------------- - qh_memalloc_(insize, object, type) + qh_memalloc_(insize, freelistp, object, type) returns object of size bytes assumes size<=qhmem.LASTsize and void **freelistp is a temp */ @@ -177,7 +179,7 @@ struct qhmemT { /* global memory management variables */ /*---------------------------------- - qh_memfree_(object, insize) + qh_memfree_(object, insize, freelistp) free up an object notes: @@ -195,7 +197,7 @@ struct qhmemT { /* global memory management variables */ #define qh_memfree_(object, insize, freelistp) {\ if (object) { \ - qhmem .freeshort++;\ + qhmem.freeshort++;\ freelistp= qhmem.freelists + qhmem.indextable[insize];\ qhmem.totshort -= qhmem.sizetable[qhmem.indextable[insize]]; \ qhmem.totfree += qhmem.sizetable[qhmem.indextable[insize]]; \ @@ -206,6 +208,7 @@ struct qhmemT { /* global memory management variables */ /*=============== 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); diff --git a/extern/qhull/merge.c b/extern/libqhull/merge.c similarity index 98% rename from extern/qhull/merge.c rename to extern/libqhull/merge.c index 71215d772a4b..22104dc0313d 100644 --- a/extern/qhull/merge.c +++ b/extern/libqhull/merge.c @@ -20,9 +20,9 @@ merges occur in qh_mergefacet and in qh_mergecycle vertex->neighbors not set until the first merge occurs - Copyright (c) 1993-2012 C.B. Barber. - $Id: //main/2011/qhull/src/libqhull/merge.c#4 $$Change: 1490 $ - $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $ + 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" @@ -70,14 +70,14 @@ void qh_premerge(vertexT *apex, realT maxcentrum, realT maxangle) { 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 */); + 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 */ + }else /* qh.hull_dim == 2 */ qh_mergecycle_all(qh newfacet_list, &othermerge); qh_flippedmerges(qh newfacet_list, &othermerge); if (!qh MERGEexact || zzval_(Ztotmerge)) { @@ -216,7 +216,7 @@ void qh_all_merges(boolT othermerge, boolT vneighbors) { facetT *facet1, *facet2; mergeT *merge; boolT wasmerge= True, isreduce; - void **freelistp; /* used !qh_NOmem */ + void **freelistp; /* used if !qh_NOmem by qh_memfree_() */ vertexT *vertex; mergeType mergetype; int numcoplanar=0, numconcave=0, numdegenredun= 0, numnewmerges= 0; @@ -273,7 +273,7 @@ void qh_all_merges(boolT othermerge, boolT vneighbors) { } } } - if (vneighbors && qh_test_vneighbors(/* qh newfacet_list */)) + if (vneighbors && qh_test_vneighbors(/* qh.newfacet_list */)) continue; break; } /* while (True) */ @@ -319,7 +319,7 @@ void qh_all_merges(boolT othermerge, boolT vneighbors) { */ void qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle) { mergeT *merge, *lastmerge; - void **freelistp; /* used !qh_NOmem */ + void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */ if (facet->redundant) return; @@ -347,12 +347,12 @@ void qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, rea 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); + 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); + qh_errexit2(qh_ERRqhull, facet, neighbor); } facet->redundant= True; neighbor->redundant= True; @@ -422,7 +422,7 @@ setT *qh_basevertices(facetT *samecycle) { for all new facets report error if unvisited */ -void qh_checkconnect(void /* qh newfacet_list */) { +void qh_checkconnect(void /* qh.newfacet_list */) { facetT *facet, *newfacet, *errfacet= NULL, *neighbor, **neighborp; facet= qh newfacet_list; @@ -528,7 +528,7 @@ boolT qh_checkzero(boolT testall) { goto LABELnonconvex; } } - if (!testall) { + if (!testall && horizon) { FOREACHvertex_(horizon->vertices) { if (vertex->visitid != qh vertex_visit) { zzinc_(Zdistzero); @@ -893,6 +893,7 @@ void qh_findbest_test(boolT testcentrum, facetT *facet, facetT *neighbor, 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 @@ -915,6 +916,10 @@ facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT 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; @@ -1043,6 +1048,7 @@ void qh_flippedmerges(facetT *facetlist, boolT *wasmerge) { 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 @@ -1063,6 +1069,8 @@ void qh_forcedmerges(boolT *wasmerge) { 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 */ @@ -1074,14 +1082,11 @@ void qh_forcedmerges(boolT *wasmerge) { 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); + qh_errexit2(qh_ERRqhull, facet1, facet2); } - if (qh TRACEmerge-1 == zzval_(Ztotmerge)) - qhmem.IStracing= qh IStracing= qh TRACElevel; dist1= qh_getdistance(facet1, facet2, &mindist1, &maxdist1); dist2= qh_getdistance(facet2, facet1, &mindist2, &maxdist2); - trace0((qh ferr, 16, "qh_forcedmerges: duplicate ridge between f%d and f%d, dist %2.2g and reverse dist %2.2g during p%d\n", - facet1->id, facet2->id, dist1, dist2, qh furthest_id)); + qh_check_dupridge(facet1, dist1, facet2, dist2); if (dist1 < dist2) qh_mergefacet(facet1, facet2, &mindist1, &maxdist1, !qh_MERGEapex); else { @@ -1432,7 +1437,7 @@ void qh_makeridges(facetT *facet) { 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 + could rename vertices that pinch the horizon (thus removing subridge) uses qh.visit_id design: @@ -1602,7 +1607,7 @@ int qh_merge_degenredundant(void) { 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); + qh_errexit2(qh_ERRqhull, facet1, facet2); } facet2= facet2->f.replace; } @@ -2083,7 +2088,7 @@ void qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet) { unsigned int samevisitid; ridgeT *ridge, **ridgep; boolT toporient; - void **freelistp; /* used !qh_NOmem */ + 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; @@ -2271,7 +2276,7 @@ void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdis 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); + qh_errexit2(qh_ERRqhull, facet1, facet2); } if (facet2->tricoplanar) { facet2->tricoplanar= False; @@ -2314,7 +2319,7 @@ void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdis 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); + qh_errexit2(qh_ERRqhull, facet1, facet2); } if (qh num_facets - qh num_visible <= qh hull_dim + 1) { qh_fprintf(qh ferr, 6227, "\n\ @@ -2351,7 +2356,7 @@ too strong.\n", qh hull_dim+1); facet2->nummerge= (short unsigned int)nummerge; facet2->newmerge= True; facet2->dupridge= False; - qh_updatetested (facet1, facet2); + qh_updatetested(facet1, facet2); if (qh hull_dim > 2 && qh_setsize(facet1->vertices) == qh hull_dim) qh_mergesimplex(facet1, facet2, mergeapex); else { @@ -3155,9 +3160,9 @@ void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex) zinc_(Zdelridge); if (ridge->nonconvex) /* only one ridge has nonconvex set */ qh_copynonconvex(ridge); - qh_delridge(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) @@ -3368,7 +3373,7 @@ boolT qh_test_appendmerge(facetT *facet, facetT *neighbor) { for each unvisited facet neighbor of the vertex test new facet and neighbor for convexity */ -boolT qh_test_vneighbors(void /* qh newfacet_list */) { +boolT qh_test_vneighbors(void /* qh.newfacet_list */) { facetT *newfacet, *neighbor, **neighborp; vertexT *vertex, **vertexp; int nummerges= 0; @@ -3620,3 +3625,4 @@ void qh_postmerge(const char *reason, realT maxcentrum, realT maxangle, boolT qh_checkzero(boolT testall) { } #endif /* qh_NOmerge */ + diff --git a/extern/qhull/merge.h b/extern/libqhull/merge.h similarity index 96% rename from extern/qhull/merge.h rename to extern/libqhull/merge.h index da0fb53e7815..7f5ec3fb6176 100644 --- a/extern/qhull/merge.h +++ b/extern/libqhull/merge.h @@ -6,9 +6,9 @@ see qh-merge.htm and merge.c - Copyright (c) 1993-2012 C.B. Barber. - $Id: //main/2011/qhull/src/libqhull/merge.h#3 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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 @@ -119,7 +119,7 @@ void qh_postmerge(const char *reason, realT maxcentrum, realT maxangle, 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 */); +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); @@ -167,7 +167,7 @@ void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvert 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 */); +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); diff --git a/extern/qhull/poly.c b/extern/libqhull/poly.c similarity index 95% rename from extern/qhull/poly.c rename to extern/libqhull/poly.c index 436cbad20547..b8db6a9ef790 100644 --- a/extern/qhull/poly.c +++ b/extern/libqhull/poly.c @@ -9,9 +9,9 @@ infrequent code is in poly2.c (all but top 50 and their callers 12/3/95) - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/poly.c#5 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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" @@ -126,7 +126,7 @@ void qh_appendvertex(vertexT *vertex) { the first ridge of the new facet is the horizon ridge link the new facet into the horizon ridge */ -void qh_attachnewfacets(void ) { +void qh_attachnewfacets(void /* qh.visible_list, newfacet_list */) { facetT *newfacet= NULL, *neighbor, **neighborp, *horizon, *visible; ridgeT *ridge, **ridgep; @@ -173,7 +173,7 @@ void qh_attachnewfacets(void ) { }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); + qh_errexit2(qh_ERRqhull, horizon, newfacet); } }else { /* non-simplicial, with a ridge for newfacet */ FOREACHneighbor_(horizon) { /* may hold for many new facets */ @@ -245,7 +245,7 @@ boolT qh_checkflipped(facetT *facet, realT *distp, boolT allerror) { assumes vertices and ridges already freed */ void qh_delfacet(facetT *facet) { - void **freelistp; /* used !qh_NOmem */ + 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) @@ -255,7 +255,7 @@ void qh_delfacet(facetT *facet) { qh_removefacet(facet); if (!facet->tricoplanar || facet->keepcentrum) { qh_memfree_(facet->normal, qh normal_size, freelistp); - if (qh CENTERtype == qh_ASvoronoi) { /* uses macro calls */ + 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); @@ -289,7 +289,7 @@ void qh_delfacet(facetT *facet) { new facets in qh.newfacet_list uses qh.visit_id; */ -void qh_deletevisible(void /*qh visible_list*/) { +void qh_deletevisible(void /*qh.visible_list*/) { facetT *visible, *nextfacet; vertexT *vertex, **vertexp; int numvisible= 0, numdel= qh_setsize(qh del_vertices); @@ -380,7 +380,7 @@ setT *qh_facetintersect(facetT *facetA, facetT *facetB, 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); + 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", @@ -451,7 +451,7 @@ int qh_gethash(int hashsize, setT *set, int size, int firstindex, void *skipelem } 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); + qh_errexit2(qh_ERRqhull, NULL, NULL); } result= (unsigned)hash; result %= (unsigned)hashsize; @@ -561,7 +561,7 @@ void qh_makenewplanes(void /* newfacet_list */) { */ #ifndef qh_NOmerge facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew) { - void **freelistp; /* used !qh_NOmem */ + void **freelistp; /* used if !qh_NOmem by qh_memfree_() */ ridgeT *ridge, **ridgep; facetT *neighbor, *newfacet= NULL, *samecycle; setT *vertices; @@ -604,7 +604,7 @@ facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew) { 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_errexit2(qh_ERRqhull, neighbor, visible); } qh_setappend(&(neighbor->neighbors), newfacet); }else @@ -661,7 +661,7 @@ facetT *qh_makenew_simplicial(facetT *visible, vertexT *apex, int *numnew) { facetT *neighbor, **neighborp, *newfacet= NULL; setT *vertices; boolT flip, toporient; - int horizonskip, visibleskip; + int horizonskip= 0, visibleskip= 0; FOREACHneighbor_(visible) { if (!neighbor->seen && !neighbor->visible) { @@ -746,7 +746,7 @@ void qh_matchneighbor(facetT *newfacet, int newskip, int hashsize, int *hashcoun 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); + qh_errexit2(qh_ERRprec, facet, newfacet); } ismatch= (same == (boolT)((newfacet->toporient ^ facet->toporient))); matchfacet= SETelemt_(facet->neighbors, skip, facetT); @@ -762,7 +762,7 @@ void qh_matchneighbor(facetT *newfacet, int newskip, int hashsize, int *hashcoun 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); + qh_errexit2(qh_ERRprec, facet, newfacet); } SETelem_(newfacet->neighbors, newskip)= qh_DUPLICATEridge; newfacet->dupridge= True; @@ -779,7 +779,12 @@ void qh_matchneighbor(facetT *newfacet, int newskip, int hashsize, int *hashcoun qh_setfacetplane(facet); if (matchfacet) { matchskip= qh_setindex(matchfacet->neighbors, facet); - SETelem_(matchfacet->neighbors, matchskip)= qh_DUPLICATEridge; + 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); @@ -833,7 +838,7 @@ void qh_matchneighbor(facetT *newfacet, int newskip, int hashsize, int *hashcoun match it with a facet check for flipped facets */ -void qh_matchnewfacets(void /* qh newfacet_list */) { +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; @@ -858,6 +863,7 @@ void qh_matchnewfacets(void /* qh newfacet_list */) { 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 */ { @@ -978,7 +984,7 @@ boolT qh_matchvertices(int firstindex, setT *verticesA, int skipA, */ facetT *qh_newfacet(void) { facetT *facet; - void **freelistp; /* used !qh_NOmem */ + 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)); @@ -1011,15 +1017,14 @@ facetT *qh_newfacet(void) { */ ridgeT *qh_newridge(void) { ridgeT *ridge; - void **freelistp; /* used !qh_NOmem */ + 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 == 0xFFFFFF) { + if (qh ridge_id == UINT_MAX) { qh_fprintf(qh ferr, 7074, "\ -qhull warning: more than %d ridges. ID field overflows and two ridges\n\ -may have the same identifier. Otherwise output ok.\n", 0xFFFFFF); +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)); @@ -1030,15 +1035,16 @@ may have the same identifier. Otherwise output ok.\n", 0xFFFFFF); /*--------------------------------- - qh_pointid( ) + qh_pointid( point ) return id for a point, - returns -3 if null, -2 if interior, or -1 if not known + returns qh_IDnone(-3) if null, qh_IDinterior(-2) if interior, or qh_IDunknown(-1) if not known - alternative code: + 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 @@ -1048,9 +1054,9 @@ int qh_pointid(pointT *point) { ptr_intT offset, id; if (!point) - return -3; + return qh_IDnone; else if (point == qh interior_point) - return -2; + 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); @@ -1058,7 +1064,7 @@ int qh_pointid(pointT *point) { }else if ((id= qh_setindex(qh other_points, point)) != -1) id += qh num_points; else - return -1; + return qh_IDunknown; return (int)id; } /* pointid */ @@ -1146,7 +1152,7 @@ void qh_removevertex(vertexT *vertex) { removes visible facets from neighbor lists marks unused vertices for deletion */ -void qh_updatevertices(void /*qh newvertex_list, newfacet_list, visible_list*/) { +void qh_updatevertices(void /*qh.newvertex_list, newfacet_list, visible_list*/) { facetT *newfacet= NULL, *neighbor, **neighborp, *visible; vertexT *vertex, **vertexp; @@ -1194,3 +1200,6 @@ void qh_updatevertices(void /*qh newvertex_list, newfacet_list, visible_list*/) } } } /* updatevertices */ + + + diff --git a/extern/qhull/poly.h b/extern/libqhull/poly.h similarity index 93% rename from extern/qhull/poly.h rename to extern/libqhull/poly.h index 9cf04cfbacf7..af8b42077f11 100644 --- a/extern/qhull/poly.h +++ b/extern/libqhull/poly.h @@ -6,9 +6,9 @@ see qh-poly.htm, libqhull.h and poly.c - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/poly.h#3 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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 @@ -209,10 +209,10 @@ void qh_appendfacet(facetT *facet); void qh_appendvertex(vertexT *vertex); -void qh_attachnewfacets(void); +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*/); +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); @@ -236,6 +236,7 @@ void qh_updatevertices(void); 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); @@ -257,7 +258,7 @@ 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_furthestnext(void /* qh.facet_list */); void qh_furthestout(facetT *facet); void qh_infiniteloop(facetT *facet); void qh_initbuild(void); @@ -274,21 +275,21 @@ 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*/); +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 newfacet_list visible_list*/); +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(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*/); +void qh_vertexneighbors(void /*qh.facet_list*/); boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB); diff --git a/extern/qhull/poly2.c b/extern/libqhull/poly2.c similarity index 93% rename from extern/qhull/poly2.c rename to extern/libqhull/poly2.c index 317461fc54ef..f6dc15c20b28 100644 --- a/extern/qhull/poly2.c +++ b/extern/libqhull/poly2.c @@ -8,9 +8,9 @@ frequently used code is in poly.c - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/poly2.c#5 $$Change: 1490 $ - $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $ + 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" @@ -78,7 +78,7 @@ void qh_check_bestdist(void) { 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*/); + 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\ @@ -124,13 +124,64 @@ 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); + qh_errexit2(qh_ERRprec, errfacet1, errfacet2); }else if (waserror && qh outside_err > REALmax/2) - qh_errexit2 (qh_ERRprec, errfacet1, errfacet2); + 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 + /*--------------------------------- @@ -179,7 +230,7 @@ void qh_check_maxout(void) { || 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*/); + vertices= qh_pointvertex(/*qh.facet_list*/); FORALLvertices { FOREACHneighbor_(vertex) { zinc_(Zdistvertex); /* distance also computed by main loop below */ @@ -197,7 +248,7 @@ void qh_check_maxout(void) { qh min_vertex= minvertex; qh_settempfree(&vertices); } - facets= qh_pointfacet(/*qh facet_list*/); + facets= qh_pointfacet(/*qh.facet_list*/); do { old_maxoutside= fmax_(qh max_outside, maxoutside); FOREACHfacet_i_(facets) { /* for each point with facet assignment */ @@ -219,7 +270,7 @@ void qh_check_maxout(void) { } 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->id); + qh_pointid(point), dist, (bestfacet ? bestfacet->id : UINT_MAX)); } } }while @@ -532,7 +583,7 @@ void qh_checkconvex(facetT *facetlist, int fault) { } } if (waserror && !qh FORCEoutput) - qh_errexit2 (qh_ERRprec, errfacet1, errfacet2); + qh_errexit2(qh_ERRprec, errfacet1, errfacet2); } /* checkconvex */ @@ -742,7 +793,7 @@ void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp) { if (neighbor->simplicial) { skipA= SETindex_(facet->neighbors, neighbor); skipB= qh_setindex(neighbor->neighbors, facet); - if (!qh_setequal_skip(facet->vertices, skipA, neighbor->vertices, skipB)) { + 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; @@ -884,7 +935,7 @@ void qh_checkpolygon(facetT *facetlist) { if (!vertex->seen) { vertex->seen= True; numvertices++; - if (qh_pointid(vertex->point) == -1) { + 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; @@ -951,7 +1002,7 @@ void qh_checkvertex(vertexT *vertex) { boolT waserror= False; facetT *neighbor, **neighborp, *errfacet=NULL; - if (qh_pointid(vertex->point) == -1) { + 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; } @@ -992,13 +1043,13 @@ void qh_clearcenters(qh_CENTER type) { if (qh CENTERtype != type) { FORALLfacets { if (facet->tricoplanar && !facet->keepcentrum) - facet->center= NULL; + 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 */ { + }else /* qh.CENTERtype == qh_AScentrum */ { if (facet->center) { qh_memfree(facet->center, qh normal_size); facet->center= NULL; @@ -1073,7 +1124,7 @@ void qh_createsimplex(setT *vertices) { ridges also freed in qh_freeqhull */ void qh_delridge(ridgeT *ridge) { - void **freelistp; /* used !qh_NOmem */ + void **freelistp; /* used if !qh_NOmem by qh_memfree_() */ qh_setdel(ridge->top->ridges, ridge); qh_setdel(ridge->bottom->ridges, ridge); @@ -1196,8 +1247,8 @@ facetT *qh_findbestfacet(pointT *point, boolT bestoutside, if (*bestdist < -qh DISTround) { bestfacet= qh_findfacet_all(point, bestdist, isoutside, &numpart); totpart += numpart; - if ((isoutside && bestoutside) - || (!isoutside && bestfacet->upperdelaunay)) { + if ((isoutside && *isoutside && bestoutside) + || (isoutside && !*isoutside && bestfacet->upperdelaunay)) { bestfacet= qh_findbest(point, bestfacet, bestoutside, False, bestoutside, bestdist, isoutside, &totpart); @@ -1205,7 +1256,7 @@ facetT *qh_findbestfacet(pointT *point, boolT bestoutside, } } trace3((qh ferr, 3014, "qh_findbestfacet: f%d dist %2.2g isoutside %d totpart %d\n", - bestfacet->id, *bestdist, *isoutside, totpart)); + bestfacet->id, *bestdist, (isoutside ? *isoutside : UINT_MAX), totpart)); return bestfacet; } /* findbestfacet */ @@ -1229,6 +1280,7 @@ facetT *qh_findbestlower(facetT *upperfacet, pointT *point, realT *bestdistp, in realT bestdist= -REALmax/2 /* avoid underflow */; realT dist; vertexT *vertex; + boolT isoutside= False; /* not used */ zinc_(Zbestlower); FOREACHneighbor_(upperfacet) { @@ -1258,11 +1310,13 @@ facetT *qh_findbestlower(facetT *upperfacet, pointT *point, realT *bestdistp, in } } if (!bestfacet) { - qh_fprintf(qh ferr, 6228, "\n\ -Qhull internal error (qh_findbestlower): all neighbors of facet %d are flipped or upper Delaunay.\n\ -Please report this error to qhull_bug@qhull.org with the input and all of the output.\n", - upperfacet->id); - qh_errexit(qh_ERRqhull, upperfacet, NULL); + 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", @@ -1289,7 +1343,7 @@ Please report this error to qhull_bug@qhull.org with the input and all of the ou number of distance tests notes: - for library users, not used by Qhull + primarily for library users, rarely used by Qhull */ facetT *qh_findfacet_all(pointT *point, realT *bestdist, boolT *isoutside, int *numpart) { @@ -1521,7 +1575,7 @@ void qh_findgood_all(facetT *facetlist) { notes: this may help avoid precision problems */ -void qh_furthestnext(void /* qh facet_list */) { +void qh_furthestnext(void /* qh.facet_list */) { facetT *facet, *bestfacet= NULL; realT dist, bestdist= -REALmax; @@ -1633,7 +1687,7 @@ void qh_initbuild( void) { realT dist; boolT isoutside; - qh furthest_id= -1; + 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; @@ -1690,9 +1744,9 @@ void qh_initbuild( void) { 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_resetlists(False, qh_RESETvisible /*qh.visible_list newvertex_list newfacet_list */); qh facet_next= qh facet_list; - qh_furthestnext(/* qh facet_list */); + qh_furthestnext(/* qh.facet_list */); if (qh PREmerge) { qh cos_max= qh premerge_cos; qh centrum_radius= qh premerge_centrum; @@ -1752,7 +1806,7 @@ void qh_initialhull(setT *vertices) { int k; #endif - qh_createsimplex(vertices); /* qh facet_list */ + 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); @@ -1781,15 +1835,15 @@ void qh_initialhull(setT *vertices) { 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 input error: Can not compute the upper Delaunay triangulation or upper Voronoi diagram of cocircular/cospherical points.\n"); + 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 input error: Use option 'Qz' for the Delaunay triangulation or Voronoi diagram of cocircular/cospherical points. Option 'Qz' adds a point \"at infinity\" (above the corresponding paraboloid).\n"); + 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 facet is coplanar with interior point"); - qh_fprintf(qh ferr, 6154, "qhull precision error: initial facet %d is coplanar with the interior point\n", - facet->id); - qh_errexit(qh_ERRsingular, facet, 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); @@ -1852,7 +1906,7 @@ setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints 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++; /* in case qh_RANDOMint always returns the same value */ idx= idx < qh num_points ? idx : 0; } qh_setappend(&simplex, qh_point(idx)); @@ -1912,7 +1966,7 @@ setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints /*--------------------------------- - qh_isvertex( ) + qh_isvertex( point, vertices ) returns vertex if point is in vertex set, else returns NULL notes: @@ -2059,7 +2113,7 @@ void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcoun 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); + qh_errexit2(qh_ERRqhull, facet, newfacet); } }else if (ismatch && makematch) { if (SETelemt_(newfacet->neighbors, newskip, facetT) == qh_DUPLICATEridge) { @@ -2105,7 +2159,7 @@ void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcoun atfacet->id, atskip, hash); qh_errexit(qh_ERRqhull, atfacet, NULL); } - SETelem_(maxmatch->neighbors, maxskip)= maxmatch2; + SETelem_(maxmatch->neighbors, maxskip)= maxmatch2; /* maxmatch!=0 by QH6157 */ SETelem_(maxmatch2->neighbors, maxskip2)= maxmatch; *hashcount -= 2; /* removed two unmatched facets */ zzinc_(Zmultiridge); @@ -2227,8 +2281,12 @@ vertexT *qh_nearvertex(facetT *facet, pointT *point, realT *bestdistp) { 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->id, *bestdistp, facet->id, qh_pointid(point))); /* bestvertex!=0 by QH2161 */ return bestvertex; } /* nearvertex */ @@ -2274,16 +2332,15 @@ vertexT *qh_newvertex(pointT *point) { zinc_(Ztotvertices); vertex= (vertexT *)qh_memalloc((int)sizeof(vertexT)); memset((char *) vertex, (size_t)0, sizeof(vertexT)); - if (qh vertex_id == 0xFFFFFF) { - qh_fprintf(qh ferr, 6159, "qhull error: more than %d vertices. ID field overflows and two vertices\n\ -may have the same identifier. Vertices will not be sorted correctly.\n", 0xFFFFFF); + 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; - vertex->dim= (unsigned char)(qh hull_dim <= MAX_vdim ? qh hull_dim : 0); trace4((qh ferr, 4060, "qh_newvertex: vertex p%d(v%d) created\n", qh_pointid(vertex->point), vertex->id)); return(vertex); @@ -2450,7 +2507,7 @@ void qh_point_add(setT *set, pointT *point, void *elem) { add each coplanar point add each outside point */ -setT *qh_pointfacet(void /*qh facet_list*/) { +setT *qh_pointfacet(void /*qh.facet_list*/) { int numpoints= qh num_points + qh_setsize(qh other_points); setT *facets; facetT *facet; @@ -2487,7 +2544,7 @@ setT *qh_pointfacet(void /*qh facet_list*/) { FOREACHvertex_i_(vertices) { ... } SETelem_(vertices, i) */ -setT *qh_pointvertex(void /*qh facet_list*/) { +setT *qh_pointvertex(void /*qh.facet_list*/) { int numpoints= qh num_points + qh_setsize(qh other_points); setT *vertices; vertexT *vertex; @@ -2625,7 +2682,7 @@ void qh_printlists(void) { returns: visible_list is empty if qh_deletevisible was called */ -void qh_resetlists(boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/) { +void qh_resetlists(boolT stats, boolT resetVisible /*qh.newvertex_list newfacet_list visible_list*/) { vertexT *vertex; facetT *newfacet, *visible; int totnew=0, totver=0; @@ -2707,7 +2764,7 @@ void qh_setvoronoi_all(void) { 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*/) { +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; @@ -2773,8 +2830,8 @@ void qh_triangulate(void /*qh facet_list*/) { 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*/); + 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")); @@ -2822,15 +2879,15 @@ void qh_triangulate(void /*qh facet_list*/) { owner= NULL; } }else if (facet->tricoplanar) { - if (facet->f.triowner != visible) { + 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); + 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 */ + 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; @@ -2862,7 +2919,7 @@ void qh_triangulate(void /*qh facet_list*/) { /*--------------------------------- - qh_triangulate_facet(facetA) + qh_triangulate_facet(qh, facetA, &firstVertex ) triangulate a non-simplicial facet if qh.CENTERtype=qh_ASvoronoi, sets its Voronoi center returns: @@ -2875,7 +2932,12 @@ void qh_triangulate(void /*qh facet_list*/) { 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 @@ -2919,15 +2981,21 @@ void qh_triangulate_facet(facetT *facetA, vertexT **first_vertex) { newfacet->degenerate= False; newfacet->upperdelaunay= facetA->upperdelaunay; newfacet->good= facetA->good; - if (qh TRInormals) { + if (qh TRInormals) { /* 'Q11' triangulate duplicates ->normal and ->center */ newfacet->keepcentrum= True; - newfacet->normal= qh_copypoints(facetA->normal, 1, qh hull_dim); + 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 - newfacet->center= qh_copypoints(facetA->center, 1, qh hull_dim); + 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; } @@ -2936,7 +3004,7 @@ void qh_triangulate_facet(facetT *facetA, vertexT **first_vertex) { newfacet->maxoutside= facetA->maxoutside; #endif } - qh_matchnewfacets(/*qh newfacet_list*/); + qh_matchnewfacets(/*qh.newfacet_list*/); zinc_(Ztricoplanar); zadd_(Ztricoplanartot, numnew); zmax_(Ztricoplanarmax, numnew); @@ -2944,8 +3012,8 @@ void qh_triangulate_facet(facetT *facetA, vertexT **first_vertex) { if (!(*first_vertex)) (*first_vertex)= qh newvertex_list; qh newvertex_list= NULL; - qh_updatevertices(/*qh newfacet_list, empty visible_list and newvertex_list*/); - qh_resetlists(False, !qh_RESETvisible /*qh newfacet_list, empty visible_list and newvertex_list*/); + 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 */ /*-id, facetB->id, oldfacetA->id, oldfacetB->id); - qh_errexit2 (qh_ERRqhull, facetA, facetB); + qh_errexit2(qh_ERRqhull, facetA, facetB); } qh_setreplace(facetB->neighbors, oldfacetB, facetA); qh_setreplace(facetA->neighbors, oldfacetA, facetB); @@ -3103,7 +3171,7 @@ setT *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB) { for each vertex append facet to vertex->neighbors */ -void qh_vertexneighbors(void /*qh facet_list*/) { +void qh_vertexneighbors(void /*qh.facet_list*/) { facetT *facet; vertexT *vertex, **vertexp; diff --git a/extern/qhull/qhull_a.h b/extern/libqhull/qhull_a.h similarity index 83% rename from extern/qhull/qhull_a.h rename to extern/libqhull/qhull_a.h index 36bbe9652a9c..729b7232768b 100644 --- a/extern/qhull/qhull_a.h +++ b/extern/libqhull/qhull_a.h @@ -2,29 +2,30 @@ >-------------------------------- qhull_a.h - all header files for compiling qhull + 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-defineable constants + see user.h for user-definable constants defines internal functions for libqhull.c global.c - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/qhull_a.h#3 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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 qhull/qhull_a.h' to avoid name clashes + use '#include "libqhull/qhull_a.h"' to avoid name clashes */ #ifndef qhDEFqhulla #define qhDEFqhulla 1 -#include "libqhull.h" /* Defines data types */ +#include "libqhull.h" /* Includes user_r.h and data types */ #include "stat.h" #include "random.h" @@ -94,17 +95,20 @@ /*---------------------------------- + Define an unused variable to avoid compiler warnings + + Derived from Qt's corelib/global/qglobal.h + */ -/* See Qt's qglobal.h */ -#if !defined(SAG_COM) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) -# define QHULL_OS_WIN -#elif defined(__MWERKS__) && defined(__INTEL__) -# define QHULL_OS_WIN +#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 -#define QHULL_UNUSED(x) (void)x; - /***** -libqhull.c prototypes (alphabetical after qhull) ********************/ void qh_qhull(void); @@ -136,7 +140,7 @@ void qh_allstatB(void); void qh_allstatC(void); void qh_allstatD(void); void qh_allstatE(void); -void qh_allstatE2 (void); +void qh_allstatE2(void); void qh_allstatF(void); void qh_allstatG(void); void qh_allstatH(void); diff --git a/extern/qhull/qset.c b/extern/libqhull/qset.c similarity index 97% rename from extern/qhull/qset.c rename to extern/libqhull/qset.c index e5038f4ac192..a969252a7590 100644 --- a/extern/qhull/qset.c +++ b/extern/libqhull/qset.c @@ -11,11 +11,12 @@ either the actual size of the set plus 1, or the NULL terminator of the set (i.e., setelemT). - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/qset.c#6 $$Change: 1475 $ - $DateTime: 2012/01/27 22:32:16 $$Author: bbarber $ + 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 @@ -425,15 +426,15 @@ void *qh_setdelnth(setT *set, int nth) { setelemT *sizep; setelemT *elemp, *lastp; - elemp= (setelemT *)SETelemaddr_(set, nth, void); sizep= SETsizeaddr_(set); if ((sizep->i--)==0) /* if was a full set */ - sizep->i= set->maxsize; /* *sizep= (maxsize-1)+ 1 */ + 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 */ @@ -572,7 +573,7 @@ void **qh_setendpointer(setT *set) { /*--------------------------------- - qh_setequal( ) + qh_setequal( setA, setB ) returns 1 if two sorted sets are equal, otherwise returns 0 notes: @@ -714,7 +715,7 @@ int qh_setequal_skip(setT *setA, int skipA, setT *setB, int skipB) { */ void qh_setfree(setT **setp) { int size; - void **freelistp; /* used !qh_NOmem */ + void **freelistp; /* used if !qh_NOmem by qh_memfree_() */ if (*setp) { size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize; @@ -740,7 +741,7 @@ void qh_setfree(setT **setp) { free each element free set */ -void qh_setfree2 (setT **setp, int elemsize) { +void qh_setfree2(setT **setp, int elemsize) { void *elem, **elemp; FOREACHelem_(*setp) @@ -882,7 +883,7 @@ void qh_setlarger(setT **oldsetp) { /*--------------------------------- - qh_setlast( ) + qh_setlast( set ) return last element of set or NULL (use type conversion) notes: @@ -922,9 +923,9 @@ void *qh_setlast(setT *set) { */ setT *qh_setnew(int setsize) { setT *set; - int sizereceived; /* used !qh_NOmem */ + int sizereceived; /* used if !qh_NOmem */ int size; - void **freelistp; /* used !qh_NOmem */ + void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */ if (!setsize) setsize++; @@ -1244,10 +1245,10 @@ setT *qh_settemppop(void) { append set to tempstack */ void qh_settemppush(setT *set) { - if (!set) { - fprintf (qhmem.ferr, "qhull error (qh_settemppush): can not push a NULL temp\n"); - qh_errexit (qhmem_ERRqhull, NULL, NULL); - } + 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", @@ -1335,3 +1336,5 @@ void qh_setzero(setT *set, int idx, int size) { count= size - idx + 1; /* +1 for NULL terminator */ memset((char *)SETelemaddr_(set, idx, void), 0, (size_t)count * SETelemsize); } /* setzero */ + + diff --git a/extern/qhull/qset.h b/extern/libqhull/qset.h similarity index 98% rename from extern/qhull/qset.h rename to extern/libqhull/qset.h index 759b501a8017..7e4e7d14f6b9 100644 --- a/extern/qhull/qset.h +++ b/extern/libqhull/qset.h @@ -16,9 +16,9 @@ - every set is NULL terminated - sets may be sorted or unsorted, the caller must distinguish this - Copyright (c) 1993-2012 The Geometry Center. - $Id: //main/2011/qhull/src/libqhull/qset.h#4 $$Change: 1464 $ - $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $ + 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 @@ -33,6 +33,8 @@ 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 */ + /*------------------------------------------ @@ -459,10 +461,10 @@ 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_setendpointer(setT *set); void qh_setfree(setT **set); void qh_setfree2( setT **setp, int elemsize); void qh_setfreelong(setT **set); diff --git a/extern/qhull/random.c b/extern/libqhull/random.c similarity index 91% rename from extern/qhull/random.c rename to extern/libqhull/random.c index 21b15025afd6..176d697aeb5a 100644 --- a/extern/qhull/random.c +++ b/extern/libqhull/random.c @@ -1,14 +1,16 @@ /*
  ---------------------------------
 
-   random.c -- utilities
+   random.c and utilities
      Park & Miller's minimimal standard random number generator
      argc/argv conversion
 
-     Used by rbox.  Do not use 'qh'
+     Used by rbox.  Do not use 'qh' 
 */
 
 #include "libqhull.h"
+#include "random.h"
+
 #include 
 #include 
 #include 
@@ -138,7 +140,7 @@ int qh_argv_to_command_size(int argc, char *argv[]) {
 
 /* Global variables and constants */
 
-int qh_rand_seed= 1;  /* define as global variable instead of using qh */
+int qh_last_random= 1;  /* define as global variable instead of using qh */
 
 #define qh_rand_a 16807
 #define qh_rand_m 2147483647
@@ -147,7 +149,7 @@ int qh_rand_seed= 1;  /* define as global variable instead of using qh */
 
 int qh_rand( void) {
     int lo, hi, test;
-    int seed = qh_rand_seed;
+    int seed = qh_last_random;
 
     hi = seed / qh_rand_q;  /* seed div q */
     lo = seed % qh_rand_q;  /* seed mod q */
@@ -156,7 +158,7 @@ int qh_rand( void) {
         seed= test;
     else
         seed= test + qh_rand_m;
-    qh_rand_seed= seed;
+    qh_last_random= seed;
     /* seed = seed < qh_RANDOMmax/2 ? 0 : qh_RANDOMmax;  for testing */
     /* seed = qh_RANDOMmax;  for testing */
     return seed;
@@ -164,21 +166,21 @@ int qh_rand( void) {
 
 void qh_srand( int seed) {
     if (seed < 1)
-        qh_rand_seed= 1;
+        qh_last_random= 1;
     else if (seed >= qh_rand_m)
-        qh_rand_seed= qh_rand_m - 1;
+        qh_last_random= qh_rand_m - 1;
     else
-        qh_rand_seed= seed;
+        qh_last_random= seed;
 } /* qh_srand */
 
 /*---------------------------------
 
 qh_randomfactor( scale, offset )
-return a random factor r * scale + offset
+  return a random factor r * scale + offset
 
 notes:
-qh.RANDOMa/b are defined in global.c
+  qh.RANDOMa/b are defined in global.c
 */
 realT qh_randomfactor(realT scale, realT offset) {
     realT randr;
@@ -191,13 +193,13 @@ realT qh_randomfactor(realT scale, realT offset) {
 >--------------------------------
 
 qh_randommatrix( buffer, dim, rows )
-generate a random dim X dim matrix in range [-1,1]
-assumes buffer is [dim+1, dim]
+  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
+  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;
diff --git a/extern/qhull/random.h b/extern/libqhull/random.h
similarity index 77%
rename from extern/qhull/random.h
rename to extern/libqhull/random.h
index e1e29270419a..0c6896b76549 100644
--- a/extern/qhull/random.h
+++ b/extern/libqhull/random.h
@@ -2,13 +2,13 @@
   >--------------------------------
 
   random.h
-    header file for random routines
+    header file for random and utility routines
 
    see qh-geom.htm and random.c
 
-   Copyright (c) 1993-2012 The Geometry Center.
-   $Id: //main/2011/qhull/src/libqhull/random.h#3 $$Change: 1464 $
-   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+   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
@@ -29,3 +29,6 @@ int     qh_strtol(const char *s, char **endp);
 double  qh_strtod(const char *s, char **endp);
 
 #endif /* qhDEFrandom */
+
+
+
diff --git a/extern/qhull/rboxlib.c b/extern/libqhull/rboxlib.c
similarity index 75%
rename from extern/qhull/rboxlib.c
rename to extern/libqhull/rboxlib.c
index 0122563f7062..f945133fa0b7 100644
--- a/extern/qhull/rboxlib.c
+++ b/extern/libqhull/rboxlib.c
@@ -12,8 +12,8 @@
      incorrect range if qh_RANDOMmax is defined wrong (user.h)
 */
 
+#include "libqhull.h"  /* First for user.h */
 #include "random.h"
-#include "libqhull.h"
 
 #include 
 #include 
@@ -33,10 +33,12 @@
 #define PI 3.1415926535897932384
 
 /* ------------------------------ prototypes ----------------*/
-int roundi( double a);
-void out1( double a);
-void out2n( double a, double b);
-void out3n( double a, double b, double c);
+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);
@@ -55,6 +57,7 @@ struct rboxT {
   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 */
 };
 
 
@@ -75,8 +78,7 @@ rboxT rbox;
     5 (qh_ERRqhull) on internal error
 
   notes:
-    To avoid stdio, redefine qh_malloc, qh_free, and qh_fprintf_rbox (user.c)
-    Rbox is not multithreaded.
+    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):
@@ -88,18 +90,19 @@ rboxT rbox;
 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 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;
+  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 *simplex= NULL, *simplexp;
+  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 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];
@@ -117,7 +120,7 @@ int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
 
   exitcode= setjmp(rbox.errexit);
   if (exitcode) {
-    /* same code for error exit and normal return */
+    /* same code for error exit and normal return.  qh.NOerrexit is set */
     if (simplex)
         qh_free(simplex);
     rbox_inuse= False;
@@ -194,6 +197,30 @@ int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
       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
@@ -313,6 +340,12 @@ int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
     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)
@@ -335,6 +368,7 @@ int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
   }else
     totpoints= numpoints + isaxis;
   totpoints += cubesize + diamondsize + addpoints;
+  totpoints += coincidentpoints*coincidenttotal;
 
   /* ============= seed randoms =============== */
   if (istime == 0) {
@@ -365,6 +399,7 @@ int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
   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 =============== */
@@ -372,9 +407,9 @@ int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
     while (s && *s) { /* 'P' */
       count= 0;
       if (iscdd)
-        out1( 1.0);
+        qh_out1( 1.0);
       while (*++s) {
-        out1( qh_strtod(s, &s));
+        qh_out1( qh_strtod(s, &s));
         count++;
         if (isspace(*s) || !*s)
           break;
@@ -385,7 +420,7 @@ int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
       }
       if (count < dim) {
         for (k=dim-count; k--; )
-          out1( 0.0);
+          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);
@@ -425,9 +460,9 @@ int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
         simplexp= simplex;
       for (i=0; i=0; k--) {
         if (j & ( 1 << k))
-          out1( cube);
+          qh_out1( cube);
         else
-          out1( -cube);
+          qh_out1( -cube);
       }
       qh_fprintf_rbox(rbox.fout, 9400, "\n");
     }
@@ -722,14 +763,14 @@ int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
   if (adddiamond) {
     for (j=0; j=0; k--) {
         if (j/2 != k)
-          out1( 0.0);
+          qh_out1( 0.0);
         else if (j & 0x1)
-          out1( diamond);
+          qh_out1( diamond);
         else
-          out1( -diamond);
+          qh_out1( -diamond);
       }
       qh_fprintf_rbox(rbox.fout, 9401, "\n");
     }
@@ -739,16 +780,15 @@ int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
     qh_fprintf_rbox(rbox.fout, 9402, "end\nhull\n");
 
   /* same code for error exit and normal return */
-  if (simplex)
-    qh_free(simplex);
+  qh_free(simplex);
   rbox_inuse= False;
   return qh_ERRnone;
 } /* rboxpoints */
 
 /*------------------------------------------------
-outxxx - output functions
+outxxx - output functions for qh_rboxpoints
 */
-int roundi( double a) {
+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);
@@ -762,33 +802,69 @@ int roundi( double a) {
     }
     return (int)(a + 0.5);
   }
-} /* roundi */
+} /* qh_roundi */
 
-void out1(double a) {
+void qh_out1(double a) {
 
   if (rbox.isinteger)
-    qh_fprintf_rbox(rbox.fout, 9403, "%d ", roundi( a+rbox.out_offset));
+    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);
-} /* out1 */
+} /* qh_out1 */
 
-void out2n( double a, double b) {
+void qh_out2n( double a, double b) {
 
   if (rbox.isinteger)
-    qh_fprintf_rbox(rbox.fout, 9405, "%d %d\n", roundi(a+rbox.out_offset), roundi(b+rbox.out_offset));
+    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);
-} /* out2n */
+} /* qh_out2n */
 
-void out3n( double a, double b, double c) {
+void qh_out3n( double a, double b, double c) {
 
   if (rbox.isinteger)
-    qh_fprintf_rbox(rbox.fout, 9407, "%d %d %d\n", roundi(a+rbox.out_offset), roundi(b+rbox.out_offset), roundi(c+rbox.out_offset));
+    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);
-} /* out3n */
+} /* 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= ZEND, printed, or same as initial value
 */
-void qh_printstatlevel(FILE *fp, int id, int start) {
+void qh_printstatlevel(FILE *fp, int id) {
 #define NULLfield "       "
 
   if (id >= ZEND || qhstat printed[id])
@@ -640,7 +644,6 @@ void qh_printstatlevel(FILE *fp, int id, int start) {
     qh_fprintf(fp, 9360, "%s\n", qhstat doc[id]);
     return;
   }
-  start= 0; /* not used */
   if (qh_nostatistic(id) || !qhstat doc[id])
     return;
   qhstat printed[id]= True;
@@ -674,7 +677,7 @@ void qh_printstats(FILE *fp, int idx, int *nextindex) {
   if (qh_newstats(idx, &nexti)) {
     qh_fprintf(fp, 9367, "\n");
     for (j=idx; j
 
 /*---------------------------------
+  >--------------------------------
 
-  qh_call_qhull( void )
-    template for calling qhull from inside your program
-    remove #if 0, #endif to compile
+  Qhull-template
+    Template for calling qhull from inside your program
 
   returns:
     exit code(see qh_ERR... in libqhull.h)
@@ -57,10 +56,6 @@
 
   notes:
     This can be called any number of times.
-
-  see:
-    qh_call_qhull_once()
-
 */
 #if 0
 {
@@ -76,12 +71,14 @@
   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){
-      printf ("QH6238: Qhull link error.  The global variable qh_qh was not initialized\n\
+  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;
+      exit(1);
   }
 #endif
 
@@ -106,6 +103,7 @@
 
   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.
@@ -113,7 +111,7 @@
     do not call qhull functions before qh_new_qhull().
       The qhull data structure is not initialized until qh_new_qhull().
 
-    outfile may be null
+    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')
@@ -125,7 +123,8 @@
     - use qh_freeqhull(qh_ALL) to free intermediate convex hulls
 
   see:
-    user_eg.c for an example
+      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) {
@@ -134,15 +133,24 @@ int qh_new_qhull(int dim, int numpoints, coordT *points, boolT 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)) {
+  if (strncmp(qhull_cmd, "qhull ", (size_t)6)) {
     qh_fprintf(errfile, 6186, "qhull error (qh_new_qhull): start qhull_cmd argument with \"qhull \"\n");
-    qh_exit(qh_ERRinput);
+    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)
@@ -246,11 +254,12 @@ void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) {
   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.  Exit program\n");
+    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 */
 
@@ -446,7 +455,7 @@ 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, -1);
+  qh_printpointid(fp, "center point", qh hull_dim, qh interior_point, qh_IDunknown);
   qh_fprintf(fp, 9378, "\n");
   FORALLfacets {
     qh_fprintf(fp, 9379, "facet");
@@ -523,3 +532,5 @@ void qh_user_memsizes(void) {
 
   /* qh_memsize(size); */
 } /* user_memsizes */
+
+
diff --git a/extern/qhull/user.h b/extern/libqhull/user.h
similarity index 91%
rename from extern/qhull/user.h
rename to extern/libqhull/user.h
index 45b3202696a3..523aa7b4e842 100644
--- a/extern/qhull/user.h
+++ b/extern/libqhull/user.h
@@ -4,8 +4,11 @@
    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.
 
@@ -29,6 +32,12 @@ Code flags --
 #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 ======================*/
 /*============================================================*/
@@ -47,10 +56,11 @@ Code flags --
 
   msgcode -- Unique message codes for qh_fprintf
 
-  If add new messages, assign these values and increment.
+  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, 1047, 2059, 3025, 4068, 5003,
-     6241, 7079, 8143, 9410, 10000, 11026]
+  def counters =  [27, 1048, 2059, 3026, 4068, 5003,
+     6273, 7081, 8147, 9411, 10000, 11029]
 
   See: qh_ERR* [libqhull.h]
 */
@@ -65,7 +75,7 @@ Code flags --
 #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 [QhullError.h] */
+#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 */
 
@@ -374,7 +384,7 @@ stop after qh_JOGGLEmaxretry attempts
     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
+    =2 for at worst 50% occupancy for qh.hash_table and normally 25% occupancy
 */
 #define qh_HASHfactor 2
 
@@ -429,7 +439,7 @@ stop after qh_JOGGLEmaxretry attempts
     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
+    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 *))))
@@ -489,9 +499,11 @@ stop after qh_JOGGLEmaxretry attempts
   __MSC_VER
     defined by Microsoft Visual C++
 
-  __MWERKS__ && __POWERPC__
-    defined by Metrowerks when compiling for the Power Macintosh
+  __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
 */
@@ -585,14 +597,12 @@ stop after qh_JOGGLEmaxretry attempts
   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
-    C++ build defines qh_QHpointer [libqhullp.pro, libqhullcpp.pro]
 
-  see:
-    user_eg.c for an example
 */
 #ifdef qh_QHpointer
 #if qh_dllimport
@@ -805,6 +815,19 @@ stop after qh_JOGGLEmaxretry attempts
 */
 #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
+
 /*----------------------------------
 
@@ -852,4 +875,35 @@ stop after qh_JOGGLEmaxretry attempts
 */
 #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/qhull/usermem.c b/extern/libqhull/usermem.c
similarity index 55%
rename from extern/qhull/usermem.c
rename to extern/libqhull/usermem.c
index 722c0b42f871..0e99e8f66c18 100644
--- a/extern/qhull/usermem.c
+++ b/extern/libqhull/usermem.c
@@ -13,13 +13,14 @@
    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
+   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_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
+  qh_free( mem )
+    free memory
 
-notes:
-same as free()
+  notes:
+    same as free()
+    No calls to qh_errexit() 
 */
 void qh_free(void *mem) {
     free(mem);
@@ -60,3 +90,5 @@ void qh_free(void *mem) {
 void *qh_malloc(size_t size) {
     return malloc(size);
 } /* malloc */
+
+
diff --git a/extern/qhull/userprintf.c b/extern/libqhull/userprintf.c
similarity index 86%
rename from extern/qhull/userprintf.c
rename to extern/libqhull/userprintf.c
index d6c245b217b4..190d7cd79b3b 100644
--- a/extern/qhull/userprintf.c
+++ b/extern/libqhull/userprintf.c
@@ -19,6 +19,7 @@
 */
 
 #include "libqhull.h"
+#include "mem.h"
 
 #include 
 #include 
@@ -35,13 +36,15 @@
      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) {
-        fprintf(stderr, "QH6232 Qhull internal error (userprintf.c): fp is 0.  Wrong qh_fprintf called.\n");
+        /* 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);
@@ -60,3 +63,4 @@ void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... ) {
     /* Place debugging traps here. Use with option 'Tn' */
 
 } /* qh_fprintf */
+
diff --git a/extern/qhull/userprintf_rbox.c b/extern/libqhull/userprintf_rbox.c
similarity index 92%
rename from extern/qhull/userprintf_rbox.c
rename to extern/libqhull/userprintf_rbox.c
index 0e1a12ac3f34..8edd2001aa5c 100644
--- a/extern/qhull/userprintf_rbox.c
+++ b/extern/libqhull/userprintf_rbox.c
@@ -41,7 +41,7 @@ void qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... ) {
     va_list args;
 
     if (!fp) {
-        fprintf(stderr, "QH6231 Qhull internal error (userprintf.c): fp is 0.  Wrong qh_fprintf_rbox called.\n");
+        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)
@@ -50,3 +50,4 @@ void qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... ) {
     vfprintf(fp, fmt, args);
     va_end(args);
 } /* qh_fprintf_rbox */
+
diff --git a/setupext.py b/setupext.py
index 0a31d074af58..a53ce2edf101 100644
--- a/setupext.py
+++ b/setupext.py
@@ -1313,14 +1313,14 @@ def check(self):
         self.__class__.found_external = True
         try:
             return self._check_for_pkg_config(
-                'qhull', 'qhull/qhull_a.h', min_version='2003.1')
+                'libqhull', 'libqhull/qhull_a.h', min_version='2015.2')
         except CheckFailed as e:
             self.__class__.found_pkgconfig = False
             # Qhull may not be in the pkg-config system but may still be
             # present on this system, so check if the header files can be
             # found.
             include_dirs = [
-                os.path.join(x, 'qhull') for x in get_include_dirs()]
+                os.path.join(x, 'libqhull') for x in get_include_dirs()]
             if has_include_file(include_dirs, 'qhull_a.h'):
                 return 'Using system Qhull (version unknown, no pkg-config info)'
             else:
@@ -1333,7 +1333,7 @@ def add_flags(self, ext):
                                        default_libraries=['qhull'])
         else:
             ext.include_dirs.append('extern')
-            ext.sources.extend(glob.glob('extern/qhull/*.c'))
+            ext.sources.extend(glob.glob('extern/libqhull/*.c'))
 
 
 class TTConv(SetupPackage):
diff --git a/src/qhull_wrap.c b/src/qhull_wrap.c
index 06d278ebdd57..38779441b4fd 100644
--- a/src/qhull_wrap.c
+++ b/src/qhull_wrap.c
@@ -7,7 +7,7 @@
  */
 #include "Python.h"
 #include "numpy/noprefix.h"
-#include "qhull/qhull_a.h"
+#include "libqhull/qhull_a.h"
 #include 
 
 
@@ -109,6 +109,8 @@ delaunay_impl(int npoints, const double* x, const double* y,
     int* triangles_ptr;
     int* neighbors_ptr;
 
+    QHULL_LIB_CHECK
+
     /* Allocate points. */
     points = (coordT*)malloc(npoints*ndim*sizeof(coordT));
     if (points == NULL) {