00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "qhull_a.h"
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 void qh_distplane(pointT *point, facetT *facet, realT *dist) {
00037 coordT *normal= facet->normal, *coordp, randr;
00038 int k;
00039
00040 switch (qh hull_dim){
00041 case 2:
00042 *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1];
00043 break;
00044 case 3:
00045 *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1] + point[2] * normal[2];
00046 break;
00047 case 4:
00048 *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3];
00049 break;
00050 case 5:
00051 *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4];
00052 break;
00053 case 6:
00054 *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];
00055 break;
00056 case 7:
00057 *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];
00058 break;
00059 case 8:
00060 *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];
00061 break;
00062 default:
00063 *dist= facet->offset;
00064 coordp= point;
00065 for (k=qh hull_dim; k--; )
00066 *dist += *coordp++ * *normal++;
00067 break;
00068 }
00069 zinc_(Zdistplane);
00070 if (!qh RANDOMdist && qh IStracing < 4)
00071 return;
00072 if (qh RANDOMdist) {
00073 randr= qh_RANDOMint;
00074 *dist += (2.0 * randr / qh_RANDOMmax - 1.0) *
00075 qh RANDOMfactor * qh MAXabs_coord;
00076 }
00077 if (qh IStracing >= 4) {
00078 qh_fprintf(qh ferr, 8001, "qh_distplane: ");
00079 qh_fprintf(qh ferr, 8002, qh_REAL_1, *dist);
00080 qh_fprintf(qh ferr, 8003, "from p%d to f%d\n", qh_pointid(point), facet->id);
00081 }
00082 return;
00083 }
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 facetT *qh_findbest(pointT *point, facetT *startfacet,
00141 boolT bestoutside, boolT isnewfacets, boolT noupper,
00142 realT *dist, boolT *isoutside, int *numpart) {
00143 realT bestdist= -REALmax/2 ;
00144 facetT *facet, *neighbor, **neighborp;
00145 facetT *bestfacet= NULL, *lastfacet= NULL;
00146 int oldtrace= qh IStracing;
00147 unsigned int visitid= ++qh visit_id;
00148 int numpartnew=0;
00149 boolT testhorizon = True;
00150
00151 zinc_(Zfindbest);
00152 if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid(point))) {
00153 if (qh TRACElevel > qh IStracing)
00154 qh IStracing= qh TRACElevel;
00155 qh_fprintf(qh ferr, 8004, "qh_findbest: point p%d starting at f%d isnewfacets? %d, unless %d exit if > %2.2g\n",
00156 qh_pointid(point), startfacet->id, isnewfacets, bestoutside, qh MINoutside);
00157 qh_fprintf(qh ferr, 8005, " testhorizon? %d noupper? %d", testhorizon, noupper);
00158 qh_fprintf(qh ferr, 8006, " Last point added was p%d.", qh furthest_id);
00159 qh_fprintf(qh ferr, 8007, " Last merge was #%d. max_outside %2.2g\n", zzval_(Ztotmerge), qh max_outside);
00160 }
00161 if (isoutside)
00162 *isoutside= True;
00163 if (!startfacet->flipped) {
00164 *numpart= 1;
00165 qh_distplane(point, startfacet, dist);
00166 if (!bestoutside && *dist >= qh MINoutside
00167 && (!startfacet->upperdelaunay || !noupper)) {
00168 bestfacet= startfacet;
00169 goto LABELreturn_best;
00170 }
00171 bestdist= *dist;
00172 if (!startfacet->upperdelaunay) {
00173 bestfacet= startfacet;
00174 }
00175 }else
00176 *numpart= 0;
00177 startfacet->visitid= visitid;
00178 facet= startfacet;
00179 while (facet) {
00180 trace4((qh ferr, 4001, "qh_findbest: neighbors of f%d, bestdist %2.2g f%d\n",
00181 facet->id, bestdist, getid_(bestfacet)));
00182 lastfacet= facet;
00183 FOREACHneighbor_(facet) {
00184 if (!neighbor->newfacet && isnewfacets)
00185 continue;
00186 if (neighbor->visitid == visitid)
00187 continue;
00188 neighbor->visitid= visitid;
00189 if (!neighbor->flipped) {
00190 (*numpart)++;
00191 qh_distplane(point, neighbor, dist);
00192 if (*dist > bestdist) {
00193 if (!bestoutside && *dist >= qh MINoutside
00194 && (!neighbor->upperdelaunay || !noupper)) {
00195 bestfacet= neighbor;
00196 goto LABELreturn_best;
00197 }
00198 if (!neighbor->upperdelaunay) {
00199 bestfacet= neighbor;
00200 bestdist= *dist;
00201 break;
00202 }else if (!bestfacet) {
00203 bestdist= *dist;
00204 break;
00205 }
00206 }
00207 }
00208 }
00209 facet= neighbor;
00210 }
00211 if (isnewfacets) {
00212 if (!bestfacet) {
00213 bestdist= -REALmax/2;
00214 bestfacet= qh_findbestnew(point, startfacet->next, &bestdist, bestoutside, isoutside, &numpartnew);
00215 testhorizon= False;
00216 }else if (!qh findbest_notsharp && bestdist < - qh DISTround) {
00217 if (qh_sharpnewfacets()) {
00218
00219 zinc_(Zfindnewsharp);
00220 bestfacet= qh_findbestnew(point, bestfacet, &bestdist, bestoutside, isoutside, &numpartnew);
00221 testhorizon= False;
00222 qh findbestnew= True;
00223 }else
00224 qh findbest_notsharp= True;
00225 }
00226 }
00227 if (!bestfacet)
00228 bestfacet= qh_findbestlower(lastfacet, point, &bestdist, numpart);
00229 if (testhorizon)
00230 bestfacet= qh_findbesthorizon(!qh_IScheckmax, point, bestfacet, noupper, &bestdist, &numpartnew);
00231 *dist= bestdist;
00232 if (isoutside && bestdist < qh MINoutside)
00233 *isoutside= False;
00234 LABELreturn_best:
00235 zadd_(Zfindbesttot, *numpart);
00236 zmax_(Zfindbestmax, *numpart);
00237 (*numpart) += numpartnew;
00238 qh IStracing= oldtrace;
00239 return bestfacet;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 facetT *qh_findbesthorizon(boolT ischeckmax, pointT* point, facetT *startfacet, boolT noupper, realT *bestdist, int *numpart) {
00282 facetT *bestfacet= startfacet;
00283 realT dist;
00284 facetT *neighbor, **neighborp, *facet;
00285 facetT *nextfacet= NULL;
00286 int numpartinit= *numpart, coplanarfacetset_size;
00287 unsigned int visitid= ++qh visit_id;
00288 boolT newbest= False;
00289 realT minsearch, searchdist;
00290
00291 if (!ischeckmax) {
00292 zinc_(Zfindhorizon);
00293 }else {
00294 #if qh_MAXoutside
00295 if ((!qh ONLYgood || startfacet->good) && *bestdist > startfacet->maxoutside)
00296 startfacet->maxoutside= *bestdist;
00297 #endif
00298 }
00299 searchdist= qh_SEARCHdist;
00300 minsearch= *bestdist - searchdist;
00301 if (ischeckmax) {
00302
00303 minimize_(minsearch, -searchdist);
00304 }
00305 coplanarfacetset_size= 0;
00306 facet= startfacet;
00307 while (True) {
00308 trace4((qh ferr, 4002, "qh_findbesthorizon: neighbors of f%d bestdist %2.2g f%d ischeckmax? %d noupper? %d minsearch %2.2g searchdist %2.2g\n",
00309 facet->id, *bestdist, getid_(bestfacet), ischeckmax, noupper,
00310 minsearch, searchdist));
00311 FOREACHneighbor_(facet) {
00312 if (neighbor->visitid == visitid)
00313 continue;
00314 neighbor->visitid= visitid;
00315 if (!neighbor->flipped) {
00316 qh_distplane(point, neighbor, &dist);
00317 (*numpart)++;
00318 if (dist > *bestdist) {
00319 if (!neighbor->upperdelaunay || ischeckmax || (!noupper && dist >= qh MINoutside)) {
00320 bestfacet= neighbor;
00321 *bestdist= dist;
00322 newbest= True;
00323 if (!ischeckmax) {
00324 minsearch= dist - searchdist;
00325 if (dist > *bestdist + searchdist) {
00326 zinc_(Zfindjump);
00327 coplanarfacetset_size= 0;
00328 }
00329 }
00330 }
00331 }else if (dist < minsearch)
00332 continue;
00333 #if qh_MAXoutside
00334 if (ischeckmax && dist > neighbor->maxoutside)
00335 neighbor->maxoutside= dist;
00336 #endif
00337 }
00338 if (nextfacet) {
00339 if (!coplanarfacetset_size++) {
00340 SETfirst_(qh coplanarfacetset)= nextfacet;
00341 SETtruncate_(qh coplanarfacetset, 1);
00342 }else
00343 qh_setappend(&qh coplanarfacetset, nextfacet);
00344
00345 }
00346 nextfacet= neighbor;
00347 }
00348 facet= nextfacet;
00349 if (facet)
00350 nextfacet= NULL;
00351 else if (!coplanarfacetset_size)
00352 break;
00353 else if (!--coplanarfacetset_size) {
00354 facet= SETfirstt_(qh coplanarfacetset, facetT);
00355 SETtruncate_(qh coplanarfacetset, 0);
00356 }else
00357 facet= (facetT*)qh_setdellast(qh coplanarfacetset);
00358 }
00359 if (!ischeckmax) {
00360 zadd_(Zfindhorizontot, *numpart - numpartinit);
00361 zmax_(Zfindhorizonmax, *numpart - numpartinit);
00362 if (newbest)
00363 zinc_(Zparthorizon);
00364 }
00365 trace4((qh ferr, 4003, "qh_findbesthorizon: newbest? %d bestfacet f%d bestdist %2.2g\n", newbest, getid_(bestfacet), *bestdist));
00366 return bestfacet;
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 facetT *qh_findbestnew(pointT *point, facetT *startfacet,
00413 realT *dist, boolT bestoutside, boolT *isoutside, int *numpart) {
00414 realT bestdist= -REALmax/2;
00415 facetT *bestfacet= NULL, *facet;
00416 int oldtrace= qh IStracing, i;
00417 unsigned int visitid= ++qh visit_id;
00418 realT distoutside= 0.0;
00419 boolT isdistoutside;
00420 boolT testhorizon = True;
00421
00422 if (!startfacet) {
00423 if (qh MERGING)
00424 qh_fprintf(qh ferr, 6001, "qhull precision error (qh_findbestnew): merging has formed and deleted a cone of new facets. Can not continue.\n");
00425 else
00426 qh_fprintf(qh ferr, 6002, "qhull internal error (qh_findbestnew): no new facets for point p%d\n",
00427 qh furthest_id);
00428 qh_errexit(qh_ERRqhull, NULL, NULL);
00429 }
00430 zinc_(Zfindnew);
00431 if (qh BESToutside || bestoutside)
00432 isdistoutside= False;
00433 else {
00434 isdistoutside= True;
00435 distoutside= qh_DISToutside;
00436 }
00437 if (isoutside)
00438 *isoutside= True;
00439 *numpart= 0;
00440 if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid(point))) {
00441 if (qh TRACElevel > qh IStracing)
00442 qh IStracing= qh TRACElevel;
00443 qh_fprintf(qh ferr, 8008, "qh_findbestnew: point p%d facet f%d. Stop? %d if dist > %2.2g\n",
00444 qh_pointid(point), startfacet->id, isdistoutside, distoutside);
00445 qh_fprintf(qh ferr, 8009, " Last point added p%d visitid %d.", qh furthest_id, visitid);
00446 qh_fprintf(qh ferr, 8010, " Last merge was #%d.\n", zzval_(Ztotmerge));
00447 }
00448
00449 for (i=0, facet=startfacet; i < 2; i++, facet= qh newfacet_list) {
00450 FORALLfacet_(facet) {
00451 if (facet == startfacet && i)
00452 break;
00453 facet->visitid= visitid;
00454 if (!facet->flipped) {
00455 qh_distplane(point, facet, dist);
00456 (*numpart)++;
00457 if (*dist > bestdist) {
00458 if (!facet->upperdelaunay || *dist >= qh MINoutside) {
00459 bestfacet= facet;
00460 if (isdistoutside && *dist >= distoutside)
00461 goto LABELreturn_bestnew;
00462 bestdist= *dist;
00463 }
00464 }
00465 }
00466 }
00467 }
00468 if (testhorizon || !bestfacet)
00469 bestfacet= qh_findbesthorizon(!qh_IScheckmax, point, bestfacet ? bestfacet : startfacet,
00470 !qh_NOupper, &bestdist, numpart);
00471 *dist= bestdist;
00472 if (isoutside && *dist < qh MINoutside)
00473 *isoutside= False;
00474 LABELreturn_bestnew:
00475 zadd_(Zfindnewtot, *numpart);
00476 zmax_(Zfindnewmax, *numpart);
00477 trace4((qh ferr, 4004, "qh_findbestnew: bestfacet f%d bestdist %2.2g\n", getid_(bestfacet), *dist));
00478 qh IStracing= oldtrace;
00479 return bestfacet;
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 void qh_backnormal(realT **rows, int numrow, int numcol, boolT sign,
00522 coordT *normal, boolT *nearzero) {
00523 int i, j;
00524 coordT *normalp, *normal_tail, *ai, *ak;
00525 realT diagonal;
00526 boolT waszero;
00527 int zerocol= -1;
00528
00529 normalp= normal + numcol - 1;
00530 *normalp--= (sign ? -1.0 : 1.0);
00531 for (i=numrow; i--; ) {
00532 *normalp= 0.0;
00533 ai= rows[i] + i + 1;
00534 ak= normalp+1;
00535 for (j=i+1; j < numcol; j++)
00536 *normalp -= *ai++ * *ak++;
00537 diagonal= (rows[i])[i];
00538 if (fabs_(diagonal) > qh MINdenom_2)
00539 *(normalp--) /= diagonal;
00540 else {
00541 waszero= False;
00542 *normalp= qh_divzero(*normalp, diagonal, qh MINdenom_1_2, &waszero);
00543 if (waszero) {
00544 zerocol= i;
00545 *(normalp--)= (sign ? -1.0 : 1.0);
00546 for (normal_tail= normalp+2; normal_tail < normal + numcol; normal_tail++)
00547 *normal_tail= 0.0;
00548 }else
00549 normalp--;
00550 }
00551 }
00552 if (zerocol != -1) {
00553 zzinc_(Zback0);
00554 *nearzero= True;
00555 trace4((qh ferr, 4005, "qh_backnormal: zero diagonal at column %d.\n", i));
00556 qh_precision("zero diagonal on back substitution");
00557 }
00558 }
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581 void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero) {
00582 realT *ai, *ak, *rowp, *pivotrow;
00583 realT n, pivot, pivot_abs= 0.0, temp;
00584 int i, j, k, pivoti, flip=0;
00585
00586 *nearzero= False;
00587 for (k=0; k < numrow; k++) {
00588 pivot_abs= fabs_((rows[k])[k]);
00589 pivoti= k;
00590 for (i=k+1; i < numrow; i++) {
00591 if ((temp= fabs_((rows[i])[k])) > pivot_abs) {
00592 pivot_abs= temp;
00593 pivoti= i;
00594 }
00595 }
00596 if (pivoti != k) {
00597 rowp= rows[pivoti];
00598 rows[pivoti]= rows[k];
00599 rows[k]= rowp;
00600 *sign ^= 1;
00601 flip ^= 1;
00602 }
00603 if (pivot_abs <= qh NEARzero[k]) {
00604 *nearzero= True;
00605 if (pivot_abs == 0.0) {
00606 if (qh IStracing >= 4) {
00607 qh_fprintf(qh ferr, 8011, "qh_gausselim: 0 pivot at column %d. (%2.2g < %2.2g)\n", k, pivot_abs, qh DISTround);
00608 qh_printmatrix(qh ferr, "Matrix:", rows, numrow, numcol);
00609 }
00610 zzinc_(Zgauss0);
00611 qh_precision("zero pivot for Gaussian elimination");
00612 goto LABELnextcol;
00613 }
00614 }
00615 pivotrow= rows[k] + k;
00616 pivot= *pivotrow++;
00617 for (i=k+1; i < numrow; i++) {
00618 ai= rows[i] + k;
00619 ak= pivotrow;
00620 n= (*ai++)/pivot;
00621 for (j= numcol - (k+1); j--; )
00622 *ai++ -= n * *ak++;
00623 }
00624 LABELnextcol:
00625 ;
00626 }
00627 wmin_(Wmindenom, pivot_abs);
00628 if (qh IStracing >= 5)
00629 qh_printmatrix(qh ferr, "qh_gausselem: result", rows, numrow, numcol);
00630 }
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644 realT qh_getangle(pointT *vect1, pointT *vect2) {
00645 realT angle= 0, randr;
00646 int k;
00647
00648 for (k=qh hull_dim; k--; )
00649 angle += *vect1++ * *vect2++;
00650 if (qh RANDOMdist) {
00651 randr= qh_RANDOMint;
00652 angle += (2.0 * randr / qh_RANDOMmax - 1.0) *
00653 qh RANDOMfactor;
00654 }
00655 trace4((qh ferr, 4006, "qh_getangle: %2.2g\n", angle));
00656 return(angle);
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669 pointT *qh_getcenter(setT *vertices) {
00670 int k;
00671 pointT *center, *coord;
00672 vertexT *vertex, **vertexp;
00673 int count= qh_setsize(vertices);
00674
00675 if (count < 2) {
00676 qh_fprintf(qh ferr, 6003, "qhull internal error (qh_getcenter): not defined for %d points\n", count);
00677 qh_errexit(qh_ERRqhull, NULL, NULL);
00678 }
00679 center= (pointT *)qh_memalloc(qh normal_size);
00680 for (k=0; k < qh hull_dim; k++) {
00681 coord= center+k;
00682 *coord= 0.0;
00683 FOREACHvertex_(vertices)
00684 *coord += vertex->point[k];
00685 *coord /= count;
00686 }
00687 return(center);
00688 }
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700 pointT *qh_getcentrum(facetT *facet) {
00701 realT dist;
00702 pointT *centrum, *point;
00703
00704 point= qh_getcenter(facet->vertices);
00705 zzinc_(Zcentrumtests);
00706 qh_distplane(point, facet, &dist);
00707 centrum= qh_projectpoint(point, facet, dist);
00708 qh_memfree(point, qh normal_size);
00709 trace4((qh ferr, 4007, "qh_getcentrum: for f%d, %d vertices dist= %2.2g\n",
00710 facet->id, qh_setsize(facet->vertices), dist));
00711 return centrum;
00712 }
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist) {
00729 vertexT *vertex, **vertexp;
00730 realT dist, maxd, mind;
00731
00732 FOREACHvertex_(facet->vertices)
00733 vertex->seen= False;
00734 FOREACHvertex_(neighbor->vertices)
00735 vertex->seen= True;
00736 mind= 0.0;
00737 maxd= 0.0;
00738 FOREACHvertex_(facet->vertices) {
00739 if (!vertex->seen) {
00740 zzinc_(Zbestdist);
00741 qh_distplane(vertex->point, neighbor, &dist);
00742 if (dist < mind)
00743 mind= dist;
00744 else if (dist > maxd)
00745 maxd= dist;
00746 }
00747 }
00748 *mindist= mind;
00749 *maxdist= maxd;
00750 mind= -mind;
00751 if (maxd > mind)
00752 return maxd;
00753 else
00754 return mind;
00755 }
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768 void qh_normalize(coordT *normal, int dim, boolT toporient) {
00769 qh_normalize2( normal, dim, toporient, NULL, NULL);
00770 }
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804 void qh_normalize2 (coordT *normal, int dim, boolT toporient,
00805 realT *minnorm, boolT *ismin) {
00806 int k;
00807 realT *colp, *maxp, norm= 0, temp, *norm1, *norm2, *norm3;
00808 boolT zerodiv;
00809
00810 norm1= normal+1;
00811 norm2= normal+2;
00812 norm3= normal+3;
00813 if (dim == 2)
00814 norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1));
00815 else if (dim == 3)
00816 norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2));
00817 else if (dim == 4) {
00818 norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
00819 + (*norm3)*(*norm3));
00820 }else if (dim > 4) {
00821 norm= (*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
00822 + (*norm3)*(*norm3);
00823 for (k=dim-4, colp=normal+4; k--; colp++)
00824 norm += (*colp) * (*colp);
00825 norm= sqrt(norm);
00826 }
00827 if (minnorm) {
00828 if (norm < *minnorm)
00829 *ismin= True;
00830 else
00831 *ismin= False;
00832 }
00833 wmin_(Wmindenom, norm);
00834 if (norm > qh MINdenom) {
00835 if (!toporient)
00836 norm= -norm;
00837 *normal /= norm;
00838 *norm1 /= norm;
00839 if (dim == 2)
00840 ;
00841 else if (dim == 3)
00842 *norm2 /= norm;
00843 else if (dim == 4) {
00844 *norm2 /= norm;
00845 *norm3 /= norm;
00846 }else if (dim >4) {
00847 *norm2 /= norm;
00848 *norm3 /= norm;
00849 for (k=dim-4, colp=normal+4; k--; )
00850 *colp++ /= norm;
00851 }
00852 }else if (norm == 0.0) {
00853 temp= sqrt(1.0/dim);
00854 for (k=dim, colp=normal; k--; )
00855 *colp++ = temp;
00856 }else {
00857 if (!toporient)
00858 norm= -norm;
00859 for (k=dim, colp=normal; k--; colp++) {
00860 temp= qh_divzero(*colp, norm, qh MINdenom_1, &zerodiv);
00861 if (!zerodiv)
00862 *colp= temp;
00863 else {
00864 maxp= qh_maxabsval(normal, dim);
00865 temp= ((*maxp * norm >= 0.0) ? 1.0 : -1.0);
00866 for (k=dim, colp=normal; k--; colp++)
00867 *colp= 0.0;
00868 *maxp= temp;
00869 zzinc_(Znearlysingular);
00870 trace0((qh ferr, 1, "qh_normalize: norm=%2.2g too small during p%d\n",
00871 norm, qh furthest_id));
00872 return;
00873 }
00874 }
00875 }
00876 }
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893 pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist) {
00894 pointT *newpoint, *np, *normal;
00895 int normsize= qh normal_size;
00896 int k;
00897 void **freelistp;
00898
00899 qh_memalloc_(normsize, freelistp, newpoint, pointT);
00900 np= newpoint;
00901 normal= facet->normal;
00902 for (k=qh hull_dim; k--; )
00903 *(np++)= *point++ - dist * *normal++;
00904 return(newpoint);
00905 }
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929 void qh_setfacetplane(facetT *facet) {
00930 pointT *point;
00931 vertexT *vertex, **vertexp;
00932 int normsize= qh normal_size;
00933 int k,i, oldtrace= 0;
00934 realT dist;
00935 void **freelistp;
00936 coordT *coord, *gmcoord;
00937 pointT *point0= SETfirstt_(facet->vertices, vertexT)->point;
00938 boolT nearzero= False;
00939
00940 zzinc_(Zsetplane);
00941 if (!facet->normal)
00942 qh_memalloc_(normsize, freelistp, facet->normal, coordT);
00943 if (facet == qh tracefacet) {
00944 oldtrace= qh IStracing;
00945 qh IStracing= 5;
00946 qh_fprintf(qh ferr, 8012, "qh_setfacetplane: facet f%d created.\n", facet->id);
00947 qh_fprintf(qh ferr, 8013, " Last point added to hull was p%d.", qh furthest_id);
00948 if (zzval_(Ztotmerge))
00949 qh_fprintf(qh ferr, 8014, " Last merge was #%d.", zzval_(Ztotmerge));
00950 qh_fprintf(qh ferr, 8015, "\n\nCurrent summary is:\n");
00951 qh_printsummary(qh ferr);
00952 }
00953 if (qh hull_dim <= 4) {
00954 i= 0;
00955 if (qh RANDOMdist) {
00956 gmcoord= qh gm_matrix;
00957 FOREACHvertex_(facet->vertices) {
00958 qh gm_row[i++]= gmcoord;
00959 coord= vertex->point;
00960 for (k=qh hull_dim; k--; )
00961 *(gmcoord++)= *coord++ * qh_randomfactor(qh RANDOMa, qh RANDOMb);
00962 }
00963 }else {
00964 FOREACHvertex_(facet->vertices)
00965 qh gm_row[i++]= vertex->point;
00966 }
00967 qh_sethyperplane_det(qh hull_dim, qh gm_row, point0, facet->toporient,
00968 facet->normal, &facet->offset, &nearzero);
00969 }
00970 if (qh hull_dim > 4 || nearzero) {
00971 i= 0;
00972 gmcoord= qh gm_matrix;
00973 FOREACHvertex_(facet->vertices) {
00974 if (vertex->point != point0) {
00975 qh gm_row[i++]= gmcoord;
00976 coord= vertex->point;
00977 point= point0;
00978 for (k=qh hull_dim; k--; )
00979 *(gmcoord++)= *coord++ - *point++;
00980 }
00981 }
00982 qh gm_row[i]= gmcoord;
00983 if (qh RANDOMdist) {
00984 gmcoord= qh gm_matrix;
00985 for (i=qh hull_dim-1; i--; ) {
00986 for (k=qh hull_dim; k--; )
00987 *(gmcoord++) *= qh_randomfactor(qh RANDOMa, qh RANDOMb);
00988 }
00989 }
00990 qh_sethyperplane_gauss(qh hull_dim, qh gm_row, point0, facet->toporient,
00991 facet->normal, &facet->offset, &nearzero);
00992 if (nearzero) {
00993 if (qh_orientoutside(facet)) {
00994 trace0((qh ferr, 2, "qh_setfacetplane: flipped orientation after testing interior_point during p%d\n", qh furthest_id));
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005 }
01006 }
01007 }
01008 facet->upperdelaunay= False;
01009 if (qh DELAUNAY) {
01010 if (qh UPPERdelaunay) {
01011 if (facet->normal[qh hull_dim -1] >= qh ANGLEround * qh_ZEROdelaunay)
01012 facet->upperdelaunay= True;
01013 }else {
01014 if (facet->normal[qh hull_dim -1] > -qh ANGLEround * qh_ZEROdelaunay)
01015 facet->upperdelaunay= True;
01016 }
01017 }
01018 if (qh PRINTstatistics || qh IStracing || qh TRACElevel || qh JOGGLEmax < REALmax) {
01019 qh old_randomdist= qh RANDOMdist;
01020 qh RANDOMdist= False;
01021 FOREACHvertex_(facet->vertices) {
01022 if (vertex->point != point0) {
01023 boolT istrace= False;
01024 zinc_(Zdiststat);
01025 qh_distplane(vertex->point, facet, &dist);
01026 dist= fabs_(dist);
01027 zinc_(Znewvertex);
01028 wadd_(Wnewvertex, dist);
01029 if (dist > wwval_(Wnewvertexmax)) {
01030 wwval_(Wnewvertexmax)= dist;
01031 if (dist > qh max_outside) {
01032 qh max_outside= dist;
01033 if (dist > qh TRACEdist)
01034 istrace= True;
01035 }
01036 }else if (-dist > qh TRACEdist)
01037 istrace= True;
01038 if (istrace) {
01039 qh_fprintf(qh ferr, 8016, "qh_setfacetplane: ====== vertex p%d(v%d) increases max_outside to %2.2g for new facet f%d last p%d\n",
01040 qh_pointid(vertex->point), vertex->id, dist, facet->id, qh furthest_id);
01041 qh_errprint("DISTANT", facet, NULL, NULL, NULL);
01042 }
01043 }
01044 }
01045 qh RANDOMdist= qh old_randomdist;
01046 }
01047 if (qh IStracing >= 3) {
01048 qh_fprintf(qh ferr, 8017, "qh_setfacetplane: f%d offset %2.2g normal: ",
01049 facet->id, facet->offset);
01050 for (k=0; k < qh hull_dim; k++)
01051 qh_fprintf(qh ferr, 8018, "%2.2g ", facet->normal[k]);
01052 qh_fprintf(qh ferr, 8019, "\n");
01053 }
01054 if (facet == qh tracefacet)
01055 qh IStracing= oldtrace;
01056 }
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103 void qh_sethyperplane_det(int dim, coordT **rows, coordT *point0,
01104 boolT toporient, coordT *normal, realT *offset, boolT *nearzero) {
01105 realT maxround, dist;
01106 int i;
01107 pointT *point;
01108
01109
01110 if (dim == 2) {
01111 normal[0]= dY(1,0);
01112 normal[1]= dX(0,1);
01113 qh_normalize2 (normal, dim, toporient, NULL, NULL);
01114 *offset= -(point0[0]*normal[0]+point0[1]*normal[1]);
01115 *nearzero= False;
01116 }else if (dim == 3) {
01117 normal[0]= det2_(dY(2,0), dZ(2,0),
01118 dY(1,0), dZ(1,0));
01119 normal[1]= det2_(dX(1,0), dZ(1,0),
01120 dX(2,0), dZ(2,0));
01121 normal[2]= det2_(dX(2,0), dY(2,0),
01122 dX(1,0), dY(1,0));
01123 qh_normalize2 (normal, dim, toporient, NULL, NULL);
01124 *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
01125 + point0[2]*normal[2]);
01126 maxround= qh DISTround;
01127 for (i=dim; i--; ) {
01128 point= rows[i];
01129 if (point != point0) {
01130 dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
01131 + point[2]*normal[2]);
01132 if (dist > maxround || dist < -maxround) {
01133 *nearzero= True;
01134 break;
01135 }
01136 }
01137 }
01138 }else if (dim == 4) {
01139 normal[0]= - det3_(dY(2,0), dZ(2,0), dW(2,0),
01140 dY(1,0), dZ(1,0), dW(1,0),
01141 dY(3,0), dZ(3,0), dW(3,0));
01142 normal[1]= det3_(dX(2,0), dZ(2,0), dW(2,0),
01143 dX(1,0), dZ(1,0), dW(1,0),
01144 dX(3,0), dZ(3,0), dW(3,0));
01145 normal[2]= - det3_(dX(2,0), dY(2,0), dW(2,0),
01146 dX(1,0), dY(1,0), dW(1,0),
01147 dX(3,0), dY(3,0), dW(3,0));
01148 normal[3]= det3_(dX(2,0), dY(2,0), dZ(2,0),
01149 dX(1,0), dY(1,0), dZ(1,0),
01150 dX(3,0), dY(3,0), dZ(3,0));
01151 qh_normalize2 (normal, dim, toporient, NULL, NULL);
01152 *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
01153 + point0[2]*normal[2] + point0[3]*normal[3]);
01154 maxround= qh DISTround;
01155 for (i=dim; i--; ) {
01156 point= rows[i];
01157 if (point != point0) {
01158 dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
01159 + point[2]*normal[2] + point[3]*normal[3]);
01160 if (dist > maxround || dist < -maxround) {
01161 *nearzero= True;
01162 break;
01163 }
01164 }
01165 }
01166 }
01167 if (*nearzero) {
01168 zzinc_(Zminnorm);
01169 trace0((qh ferr, 3, "qh_sethyperplane_det: degenerate norm during p%d.\n", qh furthest_id));
01170 zzinc_(Znearlysingular);
01171 }
01172 }
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201 void qh_sethyperplane_gauss(int dim, coordT **rows, pointT *point0,
01202 boolT toporient, coordT *normal, coordT *offset, boolT *nearzero) {
01203 coordT *pointcoord, *normalcoef;
01204 int k;
01205 boolT sign= toporient, nearzero2= False;
01206
01207 qh_gausselim(rows, dim-1, dim, &sign, nearzero);
01208 for (k=dim-1; k--; ) {
01209 if ((rows[k])[k] < 0)
01210 sign ^= 1;
01211 }
01212 if (*nearzero) {
01213 zzinc_(Znearlysingular);
01214 trace0((qh ferr, 4, "qh_sethyperplane_gauss: nearly singular or axis parallel hyperplane during p%d.\n", qh furthest_id));
01215 qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
01216 }else {
01217 qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
01218 if (nearzero2) {
01219 zzinc_(Znearlysingular);
01220 trace0((qh ferr, 5, "qh_sethyperplane_gauss: singular or axis parallel hyperplane at normalization during p%d.\n", qh furthest_id));
01221 }
01222 }
01223 if (nearzero2)
01224 *nearzero= True;
01225 qh_normalize2(normal, dim, True, NULL, NULL);
01226 pointcoord= point0;
01227 normalcoef= normal;
01228 *offset= -(*pointcoord++ * *normalcoef++);
01229 for (k=dim-1; k--; )
01230 *offset -= *pointcoord++ * *normalcoef++;
01231 }
01232
01233
01234