Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/qhull/src/geom.c')
-rw-r--r--extern/qhull/src/geom.c1230
1 files changed, 0 insertions, 1230 deletions
diff --git a/extern/qhull/src/geom.c b/extern/qhull/src/geom.c
deleted file mode 100644
index ca4bcaf2541..00000000000
--- a/extern/qhull/src/geom.c
+++ /dev/null
@@ -1,1230 +0,0 @@
-/*<html><pre> -<a href="qh-geom.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- geom.c
- geometric routines of qhull
-
- see qh-geom.htm and geom.h
-
- copyright (c) 1993-2002 The Geometry Center
-
- infrequent code goes into geom2.c
-*/
-
-#include "qhull_a.h"
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="distplane">-</a>
-
- qh_distplane( point, facet, dist )
- return distance from point to facet
-
- returns:
- dist
- if qh.RANDOMdist, joggles result
-
- notes:
- dist > 0 if point is above facet (i.e., outside)
- does not error (for sortfacets)
-
- see:
- qh_distnorm in geom2.c
-*/
-void qh_distplane (pointT *point, facetT *facet, realT *dist) {
- coordT *normal= facet->normal, *coordp, randr;
- int k;
-
- switch(qh hull_dim){
- case 2:
- *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1];
- break;
- case 3:
- *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1] + point[2] * normal[2];
- break;
- case 4:
- *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3];
- break;
- case 5:
- *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4];
- break;
- case 6:
- *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5];
- break;
- case 7:
- *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6];
- break;
- case 8:
- *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6]+point[7]*normal[7];
- break;
- default:
- *dist= facet->offset;
- coordp= point;
- for (k= qh hull_dim; k--; )
- *dist += *coordp++ * *normal++;
- break;
- }
- zinc_(Zdistplane);
- if (!qh RANDOMdist && qh IStracing < 4)
- return;
- if (qh RANDOMdist) {
- randr= qh_RANDOMint;
- *dist += (2.0 * randr / qh_RANDOMmax - 1.0) *
- qh RANDOMfactor * qh MAXabs_coord;
- }
- if (qh IStracing >= 4) {
- fprintf (qh ferr, "qh_distplane: ");
- fprintf (qh ferr, qh_REAL_1, *dist);
- fprintf (qh ferr, "from p%d to f%d\n", qh_pointid(point), facet->id);
- }
- return;
-} /* distplane */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="findbest">-</a>
-
- qh_findbest( point, startfacet, bestoutside, qh_ISnewfacets, qh_NOupper, dist, isoutside, numpart )
- find facet that is furthest below a point
- for upperDelaunay facets
- returns facet only if !qh_NOupper and clearly above
-
- input:
- starts search at 'startfacet' (can not be flipped)
- if !bestoutside (qh_ALL), stops at qh.MINoutside
-
- returns:
- best facet (reports error if NULL)
- early out if isoutside defined and bestdist > qh.MINoutside
- dist is distance to facet
- isoutside is true if point is outside of facet
- numpart counts the number of distance tests
-
- see also:
- qh_findbestnew()
-
- notes:
- If merging (testhorizon), searches horizon facets of coplanar best facets because
- after qh_distplane, this and qh_partitionpoint are the most expensive in 3-d
- avoid calls to distplane, function calls, and real number operations.
- caller traces result
- Optimized for outside points. Tried recording a search set for qh_findhorizon.
- Made code more complicated.
-
- when called by qh_partitionvisible():
- indicated by qh_ISnewfacets
- qh.newfacet_list is list of simplicial, new facets
- qh_findbestnew set if qh_sharpnewfacets returns True (to use qh_findbestnew)
- qh.bestfacet_notsharp set if qh_sharpnewfacets returns False
-
- when called by qh_findfacet(), qh_partitionpoint(), qh_partitioncoplanar(),
- qh_check_bestdist(), qh_addpoint()
- indicated by !qh_ISnewfacets
- returns best facet in neighborhood of given facet
- this is best facet overall if dist > - qh.MAXcoplanar
- or hull has at least a "spherical" curvature
-
- design:
- initialize and test for early exit
- repeat while there are better facets
- for each neighbor of facet
- exit if outside facet found
- test for better facet
- if point is inside and partitioning
- test for new facets with a "sharp" intersection
- if so, future calls go to qh_findbestnew()
- test horizon facets
-*/
-facetT *qh_findbest (pointT *point, facetT *startfacet,
- boolT bestoutside, boolT isnewfacets, boolT noupper,
- realT *dist, boolT *isoutside, int *numpart) {
- realT bestdist= -REALmax/2 /* avoid underflow */;
- facetT *facet, *neighbor, **neighborp, *bestfacet= NULL;
- /* facetT *bestfacet_all= startfacet; */
- int oldtrace= qh IStracing;
- unsigned int visitid= ++qh visit_id;
- int numpartnew=0;
- boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
-
- zinc_(Zfindbest);
- if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid (point))) {
- if (qh TRACElevel > qh IStracing)
- qh IStracing= qh TRACElevel;
- fprintf (qh ferr, "qh_findbest: point p%d starting at f%d isnewfacets? %d, unless %d exit if > %2.2g\n",
- qh_pointid(point), startfacet->id, isnewfacets, bestoutside, qh MINoutside);
- fprintf(qh ferr, " testhorizon? %d noupper? %d", testhorizon, noupper);
- fprintf (qh ferr, " Last point added was p%d.", qh furthest_id);
- fprintf(qh ferr, " Last merge was #%d. max_outside %2.2g\n", zzval_(Ztotmerge), qh max_outside);
- }
- if (isoutside)
- *isoutside= True;
- if (!startfacet->flipped) { /* test startfacet */
- *numpart= 1;
- qh_distplane (point, startfacet, dist); /* this code is duplicated below */
- if (!bestoutside && *dist >= qh MINoutside
- && (!startfacet->upperdelaunay || !noupper)) {
- bestfacet= startfacet;
- goto LABELreturn_best;
- }
- bestdist= *dist;
- if (!startfacet->upperdelaunay) {
- bestfacet= startfacet;
- }
- }else
- *numpart= 0;
- startfacet->visitid= visitid;
- facet= startfacet;
- while (facet) {
- trace4((qh ferr, "qh_findbest: neighbors of f%d, bestdist %2.2g f%d\n",
- facet->id, bestdist, getid_(bestfacet)));
- FOREACHneighbor_(facet) {
- if (!neighbor->newfacet && isnewfacets)
- continue;
- if (neighbor->visitid == visitid)
- continue;
- neighbor->visitid= visitid;
- if (!neighbor->flipped) { /* code duplicated above */
- (*numpart)++;
- qh_distplane (point, neighbor, dist);
- if (*dist > bestdist) {
- if (!bestoutside && *dist >= qh MINoutside
- && (!neighbor->upperdelaunay || !noupper)) {
- bestfacet= neighbor;
- goto LABELreturn_best;
- }
- if (!neighbor->upperdelaunay) {
- bestfacet= neighbor;
- bestdist= *dist;
- }
- break; /* switch to neighor */
- } /* end of *dist>bestdist */
- } /* end of !flipped */
- } /* end of FOREACHneighbor */
- facet= neighbor; /* non-NULL only if *dist>bestdist */
- } /* end of while facet (directed search) */
- if (isnewfacets) {
- if (!bestfacet) {
- bestdist= -REALmax/2;
- bestfacet= qh_findbestnew (point, startfacet->next, &bestdist, bestoutside, isoutside, &numpartnew);
- testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
- }else if (!qh findbest_notsharp && bestdist < - qh DISTround) {
- if (qh_sharpnewfacets()) {
- /* seldom used, qh_findbestnew will retest all facets */
- zinc_(Zfindnewsharp);
- bestfacet= qh_findbestnew (point, bestfacet, &bestdist, bestoutside, isoutside, &numpartnew);
- testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
- qh findbestnew= True;
- }else
- qh findbest_notsharp= True;
- }
- }
- if (!bestfacet) {
- fprintf(qh ferr, "\n\
-qh_findbest: all neighbors of facet %d are flipped or upper Delaunay.\n\
-Please report this error to qhull_bug@geom.umn.edu with the input and all of the output.\n",
- startfacet->id);
- qh_errexit (qh_ERRqhull, startfacet, NULL);
- }
- if (testhorizon)
- bestfacet= qh_findbesthorizon (!qh_IScheckmax, point, bestfacet, noupper, &bestdist, &numpartnew);
- *dist= bestdist;
- if (isoutside && bestdist < qh MINoutside)
- *isoutside= False;
-LABELreturn_best:
- zadd_(Zfindbesttot, *numpart);
- zmax_(Zfindbestmax, *numpart);
- (*numpart) += numpartnew;
- qh IStracing= oldtrace;
- return bestfacet;
-} /* findbest */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="findbesthorizon">-</a>
-
- qh_findbesthorizon( qh_IScheckmax, point, startfacet, qh_NOupper, &bestdist, &numpart )
- search coplanar and better horizon facets from startfacet/bestdist
- ischeckmax turns off statistics and minsearch update
- all arguments must be initialized
- returns (ischeckmax):
- best facet
- returns (!ischeckmax):
- best facet that is not upperdelaunay
- allows upperdelaunay that is clearly outside
- returns:
- bestdist is distance to bestfacet
- numpart -- updates number of distance tests
-
- notes:
- no early out -- use qh_findbest() or qh_findbestnew()
- Searches coplanar or better horizon facets
-
- when called by qh_check_maxout() (qh_IScheckmax)
- startfacet must be closest to the point
- Otherwise, if point is beyond and below startfacet, startfacet may be a local minimum
- even though other facets are below the point.
- updates facet->maxoutside for good, visited facets
- may return NULL
-
- searchdist is qh.max_outside + 2 * DISTround
- + max( MINvisible('Vn'), MAXcoplanar('Un'));
- This setting is a guess. It must be at least max_outside + 2*DISTround
- because a facet may have a geometric neighbor across a vertex
-
- design:
- for each horizon facet of coplanar best facets
- continue if clearly inside
- unless upperdelaunay or clearly outside
- update best facet
-*/
-facetT *qh_findbesthorizon (boolT ischeckmax, pointT* point, facetT *startfacet, boolT noupper, realT *bestdist, int *numpart) {
- facetT *bestfacet= startfacet;
- realT dist;
- facetT *neighbor, **neighborp, *facet;
- facetT *nextfacet= NULL; /* optimize last facet of coplanarset */
- int numpartinit= *numpart, coplanarset_size;
- unsigned int visitid= ++qh visit_id;
- boolT newbest= False; /* for tracing */
- realT minsearch, searchdist; /* skip facets that are too far from point */
-
- if (!ischeckmax) {
- zinc_(Zfindhorizon);
- }else {
-#if qh_MAXoutside
- if ((!qh ONLYgood || startfacet->good) && *bestdist > startfacet->maxoutside)
- startfacet->maxoutside= *bestdist;
-#endif
- }
- searchdist= qh_SEARCHdist; /* multiple of qh.max_outside and precision constants */
- minsearch= *bestdist - searchdist;
- if (ischeckmax) {
- /* Always check coplanar facets. Needed for RBOX 1000 s Z1 G1e-13 t996564279 | QHULL Tv */
- minimize_(minsearch, -searchdist);
- }
- coplanarset_size= 0;
- facet= startfacet;
- while (True) {
- trace4((qh ferr, "qh_findbesthorizon: neighbors of f%d bestdist %2.2g f%d ischeckmax? %d noupper? %d minsearch %2.2g searchdist %2.2g\n",
- facet->id, *bestdist, getid_(bestfacet), ischeckmax, noupper,
- minsearch, searchdist));
- FOREACHneighbor_(facet) {
- if (neighbor->visitid == visitid)
- continue;
- neighbor->visitid= visitid;
- if (!neighbor->flipped) {
- qh_distplane (point, neighbor, &dist);
- (*numpart)++;
- if (dist > *bestdist) {
- if (!neighbor->upperdelaunay || ischeckmax || (!noupper && dist >= qh MINoutside)) {
- bestfacet= neighbor;
- *bestdist= dist;
- newbest= True;
- if (!ischeckmax) {
- minsearch= dist - searchdist;
- if (dist > *bestdist + searchdist) {
- zinc_(Zfindjump); /* everything in qh.coplanarset at least searchdist below */
- coplanarset_size= 0;
- }
- }
- }
- }else if (dist < minsearch)
- continue; /* if ischeckmax, dist can't be positive */
-#if qh_MAXoutside
- if (ischeckmax && dist > neighbor->maxoutside)
- neighbor->maxoutside= dist;
-#endif
- } /* end of !flipped */
- if (nextfacet) {
- if (!coplanarset_size++) {
- SETfirst_(qh coplanarset)= nextfacet;
- SETtruncate_(qh coplanarset, 1);
- }else
- qh_setappend (&qh coplanarset, nextfacet); /* Was needed for RBOX 1000 s W1e-13 P0 t996547055 | QHULL d Qbb Qc Tv
- and RBOX 1000 s Z1 G1e-13 t996564279 | qhull Tv */
- }
- nextfacet= neighbor;
- } /* end of EACHneighbor */
- facet= nextfacet;
- if (facet)
- nextfacet= NULL;
- else if (!coplanarset_size)
- break;
- else if (!--coplanarset_size) {
- facet= SETfirst_(qh coplanarset);
- SETtruncate_(qh coplanarset, 0);
- }else
- facet= (facetT*)qh_setdellast (qh coplanarset);
- } /* while True, for each facet in qh.coplanarset */
- if (!ischeckmax) {
- zadd_(Zfindhorizontot, *numpart - numpartinit);
- zmax_(Zfindhorizonmax, *numpart - numpartinit);
- if (newbest)
- zinc_(Zparthorizon);
- }
- trace4((qh ferr, "qh_findbesthorizon: newbest? %d bestfacet f%d bestdist %2.2g\n", newbest, getid_(bestfacet), *bestdist));
- return bestfacet;
-} /* findbesthorizon */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="findbestnew">-</a>
-
- qh_findbestnew( point, startfacet, dist, isoutside, numpart )
- find best newfacet for point
- searches all of qh.newfacet_list starting at startfacet
- searches horizon facets of coplanar best newfacets
- searches all facets if startfacet == qh.facet_list
- returns:
- best new or horizon facet that is not upperdelaunay
- early out if isoutside and not 'Qf'
- dist is distance to facet
- isoutside is true if point is outside of facet
- numpart is number of distance tests
-
- notes:
- Always used for merged new facets (see qh_USEfindbestnew)
- Avoids upperdelaunay facet unless (isoutside and outside)
-
- Uses qh.visit_id, qh.coplanarset.
- If share visit_id with qh_findbest, coplanarset is incorrect.
-
- If merging (testhorizon), searches horizon facets of coplanar best facets because
- a point maybe coplanar to the bestfacet, below its horizon facet,
- and above a horizon facet of a coplanar newfacet. For example,
- rbox 1000 s Z1 G1e-13 | qhull
- rbox 1000 s W1e-13 P0 t992110337 | QHULL d Qbb Qc
-
- qh_findbestnew() used if
- qh_sharpnewfacets -- newfacets contains a sharp angle
- if many merges, qh_premerge found a merge, or 'Qf' (qh.findbestnew)
-
- see also:
- qh_partitionall() and qh_findbest()
-
- design:
- for each new facet starting from startfacet
- test distance from point to facet
- return facet if clearly outside
- unless upperdelaunay and a lowerdelaunay exists
- update best facet
- test horizon facets
-*/
-facetT *qh_findbestnew (pointT *point, facetT *startfacet,
- realT *dist, boolT bestoutside, boolT *isoutside, int *numpart) {
- realT bestdist= -REALmax/2; /*, minsearch= -REALmax/2;*/
- facetT *bestfacet= NULL, *facet;
- int oldtrace= qh IStracing, i;
- unsigned int visitid= ++qh visit_id;
- realT distoutside= 0.0;
- boolT isdistoutside; /* True if distoutside is defined */
- boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
-
- if (!startfacet) {
- if (qh MERGING)
- fprintf(qh ferr, "qhull precision error (qh_findbestnew): merging has formed and deleted a cone of new facets. Can not continue.\n");
- else
- fprintf(qh ferr, "qhull internal error (qh_findbestnew): no new facets for point p%d\n",
- qh furthest_id);
- qh_errexit (qh_ERRqhull, NULL, NULL);
- }
- zinc_(Zfindnew);
- if (qh BESToutside || bestoutside)
- isdistoutside= False;
- else {
- isdistoutside= True;
- distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
- }
- if (isoutside)
- *isoutside= True;
- *numpart= 0;
- if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid (point))) {
- if (qh TRACElevel > qh IStracing)
- qh IStracing= qh TRACElevel;
- fprintf(qh ferr, "qh_findbestnew: point p%d facet f%d. Stop? %d if dist > %2.2g\n",
- qh_pointid(point), startfacet->id, isdistoutside, distoutside);
- fprintf(qh ferr, " Last point added p%d visitid %d.", qh furthest_id, visitid);
- fprintf(qh ferr, " Last merge was #%d.\n", zzval_(Ztotmerge));
- }
- /* visit all new facets starting with startfacet, maybe qh facet_list */
- for (i= 0, facet= startfacet; i < 2; i++, facet= qh newfacet_list) {
- FORALLfacet_(facet) {
- if (facet == startfacet && i)
- break;
- facet->visitid= visitid;
- if (!facet->flipped) {
- qh_distplane (point, facet, dist);
- (*numpart)++;
- if (*dist > bestdist) {
- if (!facet->upperdelaunay || *dist >= qh MINoutside) {
- bestfacet= facet;
- if (isdistoutside && *dist >= distoutside)
- goto LABELreturn_bestnew;
- bestdist= *dist;
- }
- }
- } /* end of !flipped */
- } /* FORALLfacet from startfacet or qh newfacet_list */
- }
- if (testhorizon || !bestfacet)
- bestfacet= qh_findbesthorizon (!qh_IScheckmax, point, bestfacet ? bestfacet : startfacet,
- !qh_NOupper, &bestdist, numpart);
- *dist= bestdist;
- if (isoutside && *dist < qh MINoutside)
- *isoutside= False;
-LABELreturn_bestnew:
- zadd_(Zfindnewtot, *numpart);
- zmax_(Zfindnewmax, *numpart);
- trace4((qh ferr, "qh_findbestnew: bestfacet f%d bestdist %2.2g\n", getid_(bestfacet), *dist));
- qh IStracing= oldtrace;
- return bestfacet;
-} /* findbestnew */
-
-/* ============ hyperplane functions -- keep code together [?] ============ */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="backnormal">-</a>
-
- qh_backnormal( rows, numrow, numcol, sign, normal, nearzero )
- given an upper-triangular rows array and a sign,
- solve for normal equation x using back substitution over rows U
-
- returns:
- normal= x
-
- if will not be able to divzero() when normalized (qh.MINdenom_2 and qh.MINdenom_1_2),
- if fails on last row
- this means that the hyperplane intersects [0,..,1]
- sets last coordinate of normal to sign
- otherwise
- sets tail of normal to [...,sign,0,...], i.e., solves for b= [0...0]
- sets nearzero
-
- notes:
- assumes numrow == numcol-1
-
- see Golub & van Loan 4.4-9 for back substitution
-
- solves Ux=b where Ax=b and PA=LU
- b= [0,...,0,sign or 0] (sign is either -1 or +1)
- last row of A= [0,...,0,1]
-
- 1) Ly=Pb == y=b since P only permutes the 0's of b
-
- design:
- for each row from end
- perform back substitution
- if near zero
- use qh_divzero for division
- if zero divide and not last row
- set tail of normal to 0
-*/
-void qh_backnormal (realT **rows, int numrow, int numcol, boolT sign,
- coordT *normal, boolT *nearzero) {
- int i, j;
- coordT *normalp, *normal_tail, *ai, *ak;
- realT diagonal;
- boolT waszero;
- int zerocol= -1;
-
- normalp= normal + numcol - 1;
- *normalp--= (sign ? -1.0 : 1.0);
- for(i= numrow; i--; ) {
- *normalp= 0.0;
- ai= rows[i] + i + 1;
- ak= normalp+1;
- for(j= i+1; j < numcol; j++)
- *normalp -= *ai++ * *ak++;
- diagonal= (rows[i])[i];
- if (fabs_(diagonal) > qh MINdenom_2)
- *(normalp--) /= diagonal;
- else {
- waszero= False;
- *normalp= qh_divzero (*normalp, diagonal, qh MINdenom_1_2, &waszero);
- if (waszero) {
- zerocol= i;
- *(normalp--)= (sign ? -1.0 : 1.0);
- for (normal_tail= normalp+2; normal_tail < normal + numcol; normal_tail++)
- *normal_tail= 0.0;
- }else
- normalp--;
- }
- }
- if (zerocol != -1) {
- zzinc_(Zback0);
- *nearzero= True;
- trace4((qh ferr, "qh_backnormal: zero diagonal at column %d.\n", i));
- qh_precision ("zero diagonal on back substitution");
- }
-} /* backnormal */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="gausselim">-</a>
-
- qh_gausselim( rows, numrow, numcol, sign )
- Gaussian elimination with partial pivoting
-
- returns:
- rows is upper triangular (includes row exchanges)
- flips sign for each row exchange
- sets nearzero if pivot[k] < qh.NEARzero[k], else clears it
-
- notes:
- if nearzero, the determinant's sign may be incorrect.
- assumes numrow <= numcol
-
- design:
- for each row
- determine pivot and exchange rows if necessary
- test for near zero
- perform gaussian elimination step
-*/
-void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero) {
- realT *ai, *ak, *rowp, *pivotrow;
- realT n, pivot, pivot_abs= 0.0, temp;
- int i, j, k, pivoti, flip=0;
-
- *nearzero= False;
- for(k= 0; k < numrow; k++) {
- pivot_abs= fabs_((rows[k])[k]);
- pivoti= k;
- for(i= k+1; i < numrow; i++) {
- if ((temp= fabs_((rows[i])[k])) > pivot_abs) {
- pivot_abs= temp;
- pivoti= i;
- }
- }
- if (pivoti != k) {
- rowp= rows[pivoti];
- rows[pivoti]= rows[k];
- rows[k]= rowp;
- *sign ^= 1;
- flip ^= 1;
- }
- if (pivot_abs <= qh NEARzero[k]) {
- *nearzero= True;
- if (pivot_abs == 0.0) { /* remainder of column == 0 */
- if (qh IStracing >= 4) {
- fprintf (qh ferr, "qh_gausselim: 0 pivot at column %d. (%2.2g < %2.2g)\n", k, pivot_abs, qh DISTround);
- qh_printmatrix (qh ferr, "Matrix:", rows, numrow, numcol);
- }
- zzinc_(Zgauss0);
- qh_precision ("zero pivot for Gaussian elimination");
- goto LABELnextcol;
- }
- }
- pivotrow= rows[k] + k;
- pivot= *pivotrow++; /* signed value of pivot, and remainder of row */
- for(i= k+1; i < numrow; i++) {
- ai= rows[i] + k;
- ak= pivotrow;
- n= (*ai++)/pivot; /* divzero() not needed since |pivot| >= |*ai| */
- for(j= numcol - (k+1); j--; )
- *ai++ -= n * *ak++;
- }
- LABELnextcol:
- ;
- }
- wmin_(Wmindenom, pivot_abs); /* last pivot element */
- if (qh IStracing >= 5)
- qh_printmatrix (qh ferr, "qh_gausselem: result", rows, numrow, numcol);
-} /* gausselim */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="getangle">-</a>
-
- qh_getangle( vect1, vect2 )
- returns the dot product of two vectors
- if qh.RANDOMdist, joggles result
-
- notes:
- the angle may be > 1.0 or < -1.0 because of roundoff errors
-
-*/
-realT qh_getangle(pointT *vect1, pointT *vect2) {
- realT angle= 0, randr;
- int k;
-
- for(k= qh hull_dim; k--; )
- angle += *vect1++ * *vect2++;
- if (qh RANDOMdist) {
- randr= qh_RANDOMint;
- angle += (2.0 * randr / qh_RANDOMmax - 1.0) *
- qh RANDOMfactor;
- }
- trace4((qh ferr, "qh_getangle: %2.2g\n", angle));
- return(angle);
-} /* getangle */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="getcenter">-</a>
-
- qh_getcenter( vertices )
- returns arithmetic center of a set of vertices as a new point
-
- notes:
- allocates point array for center
-*/
-pointT *qh_getcenter(setT *vertices) {
- int k;
- pointT *center, *coord;
- vertexT *vertex, **vertexp;
- int count= qh_setsize(vertices);
-
- if (count < 2) {
- fprintf (qh ferr, "qhull internal error (qh_getcenter): not defined for %d points\n", count);
- qh_errexit (qh_ERRqhull, NULL, NULL);
- }
- center= (pointT *)qh_memalloc(qh normal_size);
- for (k=0; k < qh hull_dim; k++) {
- coord= center+k;
- *coord= 0.0;
- FOREACHvertex_(vertices)
- *coord += vertex->point[k];
- *coord /= count;
- }
- return(center);
-} /* getcenter */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="getcentrum">-</a>
-
- qh_getcentrum( facet )
- returns the centrum for a facet as a new point
-
- notes:
- allocates the centrum
-*/
-pointT *qh_getcentrum(facetT *facet) {
- realT dist;
- pointT *centrum, *point;
-
- point= qh_getcenter(facet->vertices);
- zzinc_(Zcentrumtests);
- qh_distplane (point, facet, &dist);
- centrum= qh_projectpoint(point, facet, dist);
- qh_memfree(point, qh normal_size);
- trace4((qh ferr, "qh_getcentrum: for f%d, %d vertices dist= %2.2g\n",
- facet->id, qh_setsize(facet->vertices), dist));
- return centrum;
-} /* getcentrum */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="getdistance">-</a>
-
- qh_getdistance( facet, neighbor, mindist, maxdist )
- returns the maxdist and mindist distance of any vertex from neighbor
-
- returns:
- the max absolute value
-
- design:
- for each vertex of facet that is not in neighbor
- test the distance from vertex to neighbor
-*/
-realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist) {
- vertexT *vertex, **vertexp;
- realT dist, maxd, mind;
-
- FOREACHvertex_(facet->vertices)
- vertex->seen= False;
- FOREACHvertex_(neighbor->vertices)
- vertex->seen= True;
- mind= 0.0;
- maxd= 0.0;
- FOREACHvertex_(facet->vertices) {
- if (!vertex->seen) {
- zzinc_(Zbestdist);
- qh_distplane(vertex->point, neighbor, &dist);
- if (dist < mind)
- mind= dist;
- else if (dist > maxd)
- maxd= dist;
- }
- }
- *mindist= mind;
- *maxdist= maxd;
- mind= -mind;
- if (maxd > mind)
- return maxd;
- else
- return mind;
-} /* getdistance */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="normalize">-</a>
-
- qh_normalize( normal, dim, toporient )
- normalize a vector and report if too small
- does not use min norm
-
- see:
- qh_normalize2
-*/
-void qh_normalize (coordT *normal, int dim, boolT toporient) {
- qh_normalize2( normal, dim, toporient, NULL, NULL);
-} /* normalize */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="normalize2">-</a>
-
- qh_normalize2( normal, dim, toporient, minnorm, ismin )
- normalize a vector and report if too small
- qh.MINdenom/MINdenom1 are the upper limits for divide overflow
-
- returns:
- normalized vector
- flips sign if !toporient
- if minnorm non-NULL,
- sets ismin if normal < minnorm
-
- notes:
- if zero norm
- sets all elements to sqrt(1.0/dim)
- if divide by zero (divzero ())
- sets largest element to +/-1
- bumps Znearlysingular
-
- design:
- computes norm
- test for minnorm
- if not near zero
- normalizes normal
- else if zero norm
- sets normal to standard value
- else
- uses qh_divzero to normalize
- if nearzero
- sets norm to direction of maximum value
-*/
-void qh_normalize2 (coordT *normal, int dim, boolT toporient,
- realT *minnorm, boolT *ismin) {
- int k;
- realT *colp, *maxp, norm= 0, temp, *norm1, *norm2, *norm3;
- boolT zerodiv;
-
- norm1= normal+1;
- norm2= normal+2;
- norm3= normal+3;
- if (dim == 2)
- norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1));
- else if (dim == 3)
- norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2));
- else if (dim == 4) {
- norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
- + (*norm3)*(*norm3));
- }else if (dim > 4) {
- norm= (*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
- + (*norm3)*(*norm3);
- for (k= dim-4, colp= normal+4; k--; colp++)
- norm += (*colp) * (*colp);
- norm= sqrt(norm);
- }
- if (minnorm) {
- if (norm < *minnorm)
- *ismin= True;
- else
- *ismin= False;
- }
- wmin_(Wmindenom, norm);
- if (norm > qh MINdenom) {
- if (!toporient)
- norm= -norm;
- *normal /= norm;
- *norm1 /= norm;
- if (dim == 2)
- ; /* all done */
- else if (dim == 3)
- *norm2 /= norm;
- else if (dim == 4) {
- *norm2 /= norm;
- *norm3 /= norm;
- }else if (dim >4) {
- *norm2 /= norm;
- *norm3 /= norm;
- for (k= dim-4, colp= normal+4; k--; )
- *colp++ /= norm;
- }
- }else if (norm == 0.0) {
- temp= sqrt (1.0/dim);
- for (k= dim, colp= normal; k--; )
- *colp++ = temp;
- }else {
- if (!toporient)
- norm= -norm;
- for (k= dim, colp= normal; k--; colp++) { /* k used below */
- temp= qh_divzero (*colp, norm, qh MINdenom_1, &zerodiv);
- if (!zerodiv)
- *colp= temp;
- else {
- maxp= qh_maxabsval(normal, dim);
- temp= ((*maxp * norm >= 0.0) ? 1.0 : -1.0);
- for (k= dim, colp= normal; k--; colp++)
- *colp= 0.0;
- *maxp= temp;
- zzinc_(Znearlysingular);
- trace0((qh ferr, "qh_normalize: norm=%2.2g too small during p%d\n",
- norm, qh furthest_id));
- return;
- }
- }
- }
-} /* normalize */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="projectpoint">-</a>
-
- qh_projectpoint( point, facet, dist )
- project point onto a facet by dist
-
- returns:
- returns a new point
-
- notes:
- if dist= distplane(point,facet)
- this projects point to hyperplane
- assumes qh_memfree_() is valid for normal_size
-*/
-pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist) {
- pointT *newpoint, *np, *normal;
- int normsize= qh normal_size,k;
- void **freelistp; /* used !qh_NOmem */
-
- qh_memalloc_(normsize, freelistp, newpoint, pointT);
- np= newpoint;
- normal= facet->normal;
- for(k= qh hull_dim; k--; )
- *(np++)= *point++ - dist * *normal++;
- return(newpoint);
-} /* projectpoint */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="setfacetplane">-</a>
-
- qh_setfacetplane( facet )
- sets the hyperplane for a facet
- if qh.RANDOMdist, joggles hyperplane
-
- notes:
- uses global buffers qh.gm_matrix and qh.gm_row
- overwrites facet->normal if already defined
- updates Wnewvertex if PRINTstatistics
- sets facet->upperdelaunay if upper envelope of Delaunay triangulation
-
- design:
- copy vertex coordinates to qh.gm_matrix/gm_row
- compute determinate
- if nearzero
- recompute determinate with gaussian elimination
- if nearzero
- force outside orientation by testing interior point
-*/
-void qh_setfacetplane(facetT *facet) {
- pointT *point;
- vertexT *vertex, **vertexp;
- int k,i, normsize= qh normal_size, oldtrace= 0;
- realT dist;
- void **freelistp; /* used !qh_NOmem */
- coordT *coord, *gmcoord;
- pointT *point0= SETfirstt_(facet->vertices, vertexT)->point;
- boolT nearzero= False;
-
- zzinc_(Zsetplane);
- if (!facet->normal)
- qh_memalloc_(normsize, freelistp, facet->normal, coordT);
- if (facet == qh tracefacet) {
- oldtrace= qh IStracing;
- qh IStracing= 5;
- fprintf (qh ferr, "qh_setfacetplane: facet f%d created.\n", facet->id);
- fprintf (qh ferr, " Last point added to hull was p%d.", qh furthest_id);
- if (zzval_(Ztotmerge))
- fprintf(qh ferr, " Last merge was #%d.", zzval_(Ztotmerge));
- fprintf (qh ferr, "\n\nCurrent summary is:\n");
- qh_printsummary (qh ferr);
- }
- if (qh hull_dim <= 4) {
- i= 0;
- if (qh RANDOMdist) {
- gmcoord= qh gm_matrix;
- FOREACHvertex_(facet->vertices) {
- qh gm_row[i++]= gmcoord;
- coord= vertex->point;
- for (k= qh hull_dim; k--; )
- *(gmcoord++)= *coord++ * qh_randomfactor();
- }
- }else {
- FOREACHvertex_(facet->vertices)
- qh gm_row[i++]= vertex->point;
- }
- qh_sethyperplane_det(qh hull_dim, qh gm_row, point0, facet->toporient,
- facet->normal, &facet->offset, &nearzero);
- }
- if (qh hull_dim > 4 || nearzero) {
- i= 0;
- gmcoord= qh gm_matrix;
- FOREACHvertex_(facet->vertices) {
- if (vertex->point != point0) {
- qh gm_row[i++]= gmcoord;
- coord= vertex->point;
- point= point0;
- for(k= qh hull_dim; k--; )
- *(gmcoord++)= *coord++ - *point++;
- }
- }
- qh gm_row[i]= gmcoord; /* for areasimplex */
- if (qh RANDOMdist) {
- gmcoord= qh gm_matrix;
- for (i= qh hull_dim-1; i--; ) {
- for (k= qh hull_dim; k--; )
- *(gmcoord++) *= qh_randomfactor();
- }
- }
- qh_sethyperplane_gauss(qh hull_dim, qh gm_row, point0, facet->toporient,
- facet->normal, &facet->offset, &nearzero);
- if (nearzero) {
- if (qh_orientoutside (facet)) {
- trace0((qh ferr, "qh_setfacetplane: flipped orientation after testing interior_point during p%d\n", qh furthest_id));
- /* this is part of using Gaussian Elimination. For example in 5-d
- 1 1 1 1 0
- 1 1 1 1 1
- 0 0 0 1 0
- 0 1 0 0 0
- 1 0 0 0 0
- norm= 0.38 0.38 -0.76 0.38 0
- has a determinate of 1, but g.e. after subtracting pt. 0 has
- 0's in the diagonal, even with full pivoting. It does work
- if you subtract pt. 4 instead. */
- }
- }
- }
- facet->upperdelaunay= False;
- if (qh DELAUNAY) {
- if (qh UPPERdelaunay) { /* matches qh_triangulate_facet and qh.lower_threshold in qh_initbuild */
- if (facet->normal[qh hull_dim -1] >= qh ANGLEround * qh_ZEROdelaunay)
- facet->upperdelaunay= True;
- }else {
- if (facet->normal[qh hull_dim -1] > -qh ANGLEround * qh_ZEROdelaunay)
- facet->upperdelaunay= True;
- }
- }
- if (qh PRINTstatistics || qh IStracing || qh TRACElevel || qh JOGGLEmax < REALmax) {
- qh old_randomdist= qh RANDOMdist;
- qh RANDOMdist= False;
- FOREACHvertex_(facet->vertices) {
- if (vertex->point != point0) {
- boolT istrace= False;
- zinc_(Zdiststat);
- qh_distplane(vertex->point, facet, &dist);
- dist= fabs_(dist);
- zinc_(Znewvertex);
- wadd_(Wnewvertex, dist);
- if (dist > wwval_(Wnewvertexmax)) {
- wwval_(Wnewvertexmax)= dist;
- if (dist > qh max_outside) {
- qh max_outside= dist; /* used by qh_maxouter() */
- if (dist > qh TRACEdist)
- istrace= True;
- }
- }else if (-dist > qh TRACEdist)
- istrace= True;
- if (istrace) {
- fprintf (qh ferr, "qh_setfacetplane: ====== vertex p%d (v%d) increases max_outside to %2.2g for new facet f%d last p%d\n",
- qh_pointid(vertex->point), vertex->id, dist, facet->id, qh furthest_id);
- qh_errprint ("DISTANT", facet, NULL, NULL, NULL);
- }
- }
- }
- qh RANDOMdist= qh old_randomdist;
- }
- if (qh IStracing >= 3) {
- fprintf (qh ferr, "qh_setfacetplane: f%d offset %2.2g normal: ",
- facet->id, facet->offset);
- for (k=0; k < qh hull_dim; k++)
- fprintf (qh ferr, "%2.2g ", facet->normal[k]);
- fprintf (qh ferr, "\n");
- }
- if (facet == qh tracefacet)
- qh IStracing= oldtrace;
-} /* setfacetplane */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="sethyperplane_det">-</a>
-
- qh_sethyperplane_det( dim, rows, point0, toporient, normal, offset, nearzero )
- given dim X dim array indexed by rows[], one row per point,
- toporient (flips all signs),
- and point0 (any row)
- set normalized hyperplane equation from oriented simplex
-
- returns:
- normal (normalized)
- offset (places point0 on the hyperplane)
- sets nearzero if hyperplane not through points
-
- notes:
- only defined for dim == 2..4
- rows[] is not modified
- solves det(P-V_0, V_n-V_0, ..., V_1-V_0)=0, i.e. every point is on hyperplane
- see Bower & Woodworth, A programmer's geometry, Butterworths 1983.
-
- derivation of 3-d minnorm
- Goal: all vertices V_i within qh.one_merge of hyperplane
- Plan: exactly translate the facet so that V_0 is the origin
- exactly rotate the facet so that V_1 is on the x-axis and y_2=0.
- exactly rotate the effective perturbation to only effect n_0
- this introduces a factor of sqrt(3)
- n_0 = ((y_2-y_0)*(z_1-z_0) - (z_2-z_0)*(y_1-y_0)) / norm
- Let M_d be the max coordinate difference
- Let M_a be the greater of M_d and the max abs. coordinate
- Let u be machine roundoff and distround be max error for distance computation
- The max error for n_0 is sqrt(3) u M_a M_d / norm. n_1 is approx. 1 and n_2 is approx. 0
- The max error for distance of V_1 is sqrt(3) u M_a M_d M_d / norm. Offset=0 at origin
- Then minnorm = 1.8 u M_a M_d M_d / qh.ONEmerge
- Note that qh.one_merge is approx. 45.5 u M_a and norm is usually about M_d M_d
-
- derivation of 4-d minnorm
- same as above except rotate the facet so that V_1 on x-axis and w_2, y_3, w_3=0
- [if two vertices fixed on x-axis, can rotate the other two in yzw.]
- n_0 = det3_(...) = y_2 det2_(z_1, w_1, z_3, w_3) = - y_2 w_1 z_3
- [all other terms contain at least two factors nearly zero.]
- The max error for n_0 is sqrt(4) u M_a M_d M_d / norm
- Then minnorm = 2 u M_a M_d M_d M_d / qh.ONEmerge
- Note that qh.one_merge is approx. 82 u M_a and norm is usually about M_d M_d M_d
-*/
-void qh_sethyperplane_det (int dim, coordT **rows, coordT *point0,
- boolT toporient, coordT *normal, realT *offset, boolT *nearzero) {
- realT maxround, dist;
- int i;
- pointT *point;
-
-
- if (dim == 2) {
- normal[0]= dY(1,0);
- normal[1]= dX(0,1);
- qh_normalize2 (normal, dim, toporient, NULL, NULL);
- *offset= -(point0[0]*normal[0]+point0[1]*normal[1]);
- *nearzero= False; /* since nearzero norm => incident points */
- }else if (dim == 3) {
- normal[0]= det2_(dY(2,0), dZ(2,0),
- dY(1,0), dZ(1,0));
- normal[1]= det2_(dX(1,0), dZ(1,0),
- dX(2,0), dZ(2,0));
- normal[2]= det2_(dX(2,0), dY(2,0),
- dX(1,0), dY(1,0));
- qh_normalize2 (normal, dim, toporient, NULL, NULL);
- *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
- + point0[2]*normal[2]);
- maxround= qh DISTround;
- for (i=dim; i--; ) {
- point= rows[i];
- if (point != point0) {
- dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
- + point[2]*normal[2]);
- if (dist > maxround || dist < -maxround) {
- *nearzero= True;
- break;
- }
- }
- }
- }else if (dim == 4) {
- normal[0]= - det3_(dY(2,0), dZ(2,0), dW(2,0),
- dY(1,0), dZ(1,0), dW(1,0),
- dY(3,0), dZ(3,0), dW(3,0));
- normal[1]= det3_(dX(2,0), dZ(2,0), dW(2,0),
- dX(1,0), dZ(1,0), dW(1,0),
- dX(3,0), dZ(3,0), dW(3,0));
- normal[2]= - det3_(dX(2,0), dY(2,0), dW(2,0),
- dX(1,0), dY(1,0), dW(1,0),
- dX(3,0), dY(3,0), dW(3,0));
- normal[3]= det3_(dX(2,0), dY(2,0), dZ(2,0),
- dX(1,0), dY(1,0), dZ(1,0),
- dX(3,0), dY(3,0), dZ(3,0));
- qh_normalize2 (normal, dim, toporient, NULL, NULL);
- *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
- + point0[2]*normal[2] + point0[3]*normal[3]);
- maxround= qh DISTround;
- for (i=dim; i--; ) {
- point= rows[i];
- if (point != point0) {
- dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
- + point[2]*normal[2] + point[3]*normal[3]);
- if (dist > maxround || dist < -maxround) {
- *nearzero= True;
- break;
- }
- }
- }
- }
- if (*nearzero) {
- zzinc_(Zminnorm);
- trace0((qh ferr, "qh_sethyperplane_det: degenerate norm during p%d.\n", qh furthest_id));
- zzinc_(Znearlysingular);
- }
-} /* sethyperplane_det */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="sethyperplane_gauss">-</a>
-
- qh_sethyperplane_gauss( dim, rows, point0, toporient, normal, offset, nearzero )
- given (dim-1) X dim array of rows[i]= V_{i+1} - V_0 (point0)
- set normalized hyperplane equation from oriented simplex
-
- returns:
- normal (normalized)
- offset (places point0 on the hyperplane)
-
- notes:
- if nearzero
- orientation may be incorrect because of incorrect sign flips in gausselim
- solves [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0 .. 0 1]
- or [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0]
- i.e., N is normal to the hyperplane, and the unnormalized
- distance to [0 .. 1] is either 1 or 0
-
- design:
- perform gaussian elimination
- flip sign for negative values
- perform back substitution
- normalize result
- compute offset
-*/
-void qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0,
- boolT toporient, coordT *normal, coordT *offset, boolT *nearzero) {
- coordT *pointcoord, *normalcoef;
- int k;
- boolT sign= toporient, nearzero2= False;
-
- qh_gausselim(rows, dim-1, dim, &sign, nearzero);
- for(k= dim-1; k--; ) {
- if ((rows[k])[k] < 0)
- sign ^= 1;
- }
- if (*nearzero) {
- zzinc_(Znearlysingular);
- trace0((qh ferr, "qh_sethyperplane_gauss: nearly singular or axis parallel hyperplane during p%d.\n", qh furthest_id));
- qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
- }else {
- qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
- if (nearzero2) {
- zzinc_(Znearlysingular);
- trace0((qh ferr, "qh_sethyperplane_gauss: singular or axis parallel hyperplane at normalization during p%d.\n", qh furthest_id));
- }
- }
- if (nearzero2)
- *nearzero= True;
- qh_normalize2(normal, dim, True, NULL, NULL);
- pointcoord= point0;
- normalcoef= normal;
- *offset= -(*pointcoord++ * *normalcoef++);
- for(k= dim-1; k--; )
- *offset -= *pointcoord++ * *normalcoef++;
-} /* sethyperplane_gauss */
-
-
-