00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "qhull_a.h"
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 coordT *qh_copypoints(coordT *points, int numpoints, int dimension) {
00028 int size;
00029 coordT *newpoints;
00030
00031 size= numpoints * dimension * (int)sizeof(coordT);
00032 if (!(newpoints=(coordT*)qh_malloc((size_t)size))) {
00033 qh_fprintf(qh ferr, 6004, "qhull error: insufficient memory to copy %d points\n",
00034 numpoints);
00035 qh_errexit(qh_ERRmem, NULL, NULL);
00036 }
00037 memcpy((char *)newpoints, (char *)points, (size_t)size);
00038 return newpoints;
00039 }
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 void qh_crossproduct(int dim, realT vecA[3], realT vecB[3], realT vecC[3]){
00053
00054 if (dim == 3) {
00055 vecC[0]= det2_(vecA[1], vecA[2],
00056 vecB[1], vecB[2]);
00057 vecC[1]= - det2_(vecA[0], vecA[2],
00058 vecB[0], vecB[2]);
00059 vecC[2]= det2_(vecA[0], vecA[1],
00060 vecB[0], vecB[1]);
00061 }
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 realT qh_determinant(realT **rows, int dim, boolT *nearzero) {
00081 realT det=0;
00082 int i;
00083 boolT sign= False;
00084
00085 *nearzero= False;
00086 if (dim < 2) {
00087 qh_fprintf(qh ferr, 6005, "qhull internal error (qh_determinate): only implemented for dimension >= 2\n");
00088 qh_errexit(qh_ERRqhull, NULL, NULL);
00089 }else if (dim == 2) {
00090 det= det2_(rows[0][0], rows[0][1],
00091 rows[1][0], rows[1][1]);
00092 if (fabs_(det) < qh NEARzero[1])
00093 *nearzero= True;
00094 }else if (dim == 3) {
00095 det= det3_(rows[0][0], rows[0][1], rows[0][2],
00096 rows[1][0], rows[1][1], rows[1][2],
00097 rows[2][0], rows[2][1], rows[2][2]);
00098 if (fabs_(det) < qh NEARzero[2])
00099 *nearzero= True;
00100 }else {
00101 qh_gausselim(rows, dim, dim, &sign, nearzero);
00102 det= 1.0;
00103 for (i=dim; i--; )
00104 det *= (rows[i])[i];
00105 if (sign)
00106 det= -det;
00107 }
00108 return det;
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 realT qh_detjoggle(pointT *points, int numpoints, int dimension) {
00128 realT abscoord, distround, joggle, maxcoord, mincoord;
00129 pointT *point, *pointtemp;
00130 realT maxabs= -REALmax;
00131 realT sumabs= 0;
00132 realT maxwidth= 0;
00133 int k;
00134
00135 for (k=0; k < dimension; k++) {
00136 if (qh SCALElast && k == dimension-1)
00137 abscoord= maxwidth;
00138 else if (qh DELAUNAY && k == dimension-1)
00139 abscoord= 2 * maxabs * maxabs;
00140 else {
00141 maxcoord= -REALmax;
00142 mincoord= REALmax;
00143 FORALLpoint_(points, numpoints) {
00144 maximize_(maxcoord, point[k]);
00145 minimize_(mincoord, point[k]);
00146 }
00147 maximize_(maxwidth, maxcoord-mincoord);
00148 abscoord= fmax_(maxcoord, -mincoord);
00149 }
00150 sumabs += abscoord;
00151 maximize_(maxabs, abscoord);
00152 }
00153 distround= qh_distround(qh hull_dim, maxabs, sumabs);
00154 joggle= distround * qh_JOGGLEdefault;
00155 maximize_(joggle, REALepsilon * qh_JOGGLEdefault);
00156 trace2((qh ferr, 2001, "qh_detjoggle: joggle=%2.2g maxwidth=%2.2g\n", joggle, maxwidth));
00157 return joggle;
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 void qh_detroundoff(void) {
00191
00192 qh_option("_max-width", NULL, &qh MAXwidth);
00193 if (!qh SETroundoff) {
00194 qh DISTround= qh_distround(qh hull_dim, qh MAXabs_coord, qh MAXsumcoord);
00195 if (qh RANDOMdist)
00196 qh DISTround += qh RANDOMfactor * qh MAXabs_coord;
00197 qh_option("Error-roundoff", NULL, &qh DISTround);
00198 }
00199 qh MINdenom= qh MINdenom_1 * qh MAXabs_coord;
00200 qh MINdenom_1_2= sqrt(qh MINdenom_1 * qh hull_dim) ;
00201 qh MINdenom_2= qh MINdenom_1_2 * qh MAXabs_coord;
00202
00203 qh ANGLEround= 1.01 * qh hull_dim * REALepsilon;
00204 if (qh RANDOMdist)
00205 qh ANGLEround += qh RANDOMfactor;
00206 if (qh premerge_cos < REALmax/2) {
00207 qh premerge_cos -= qh ANGLEround;
00208 if (qh RANDOMdist)
00209 qh_option("Angle-premerge-with-random", NULL, &qh premerge_cos);
00210 }
00211 if (qh postmerge_cos < REALmax/2) {
00212 qh postmerge_cos -= qh ANGLEround;
00213 if (qh RANDOMdist)
00214 qh_option("Angle-postmerge-with-random", NULL, &qh postmerge_cos);
00215 }
00216 qh premerge_centrum += 2 * qh DISTround;
00217 qh postmerge_centrum += 2 * qh DISTround;
00218 if (qh RANDOMdist && (qh MERGEexact || qh PREmerge))
00219 qh_option("Centrum-premerge-with-random", NULL, &qh premerge_centrum);
00220 if (qh RANDOMdist && qh POSTmerge)
00221 qh_option("Centrum-postmerge-with-random", NULL, &qh postmerge_centrum);
00222 {
00223 realT maxangle= 1.0, maxrho;
00224
00225 minimize_(maxangle, qh premerge_cos);
00226 minimize_(maxangle, qh postmerge_cos);
00227
00228 qh ONEmerge= sqrt((realT)qh hull_dim) * qh MAXwidth *
00229 sqrt(1.0 - maxangle * maxangle) + qh DISTround;
00230 maxrho= qh hull_dim * qh premerge_centrum + qh DISTround;
00231 maximize_(qh ONEmerge, maxrho);
00232 maxrho= qh hull_dim * qh postmerge_centrum + qh DISTround;
00233 maximize_(qh ONEmerge, maxrho);
00234 if (qh MERGING)
00235 qh_option("_one-merge", NULL, &qh ONEmerge);
00236 }
00237 qh NEARinside= qh ONEmerge * qh_RATIOnearinside;
00238 if (qh JOGGLEmax < REALmax/2 && (qh KEEPcoplanar || qh KEEPinside)) {
00239 realT maxdist;
00240 qh KEEPnearinside= True;
00241 maxdist= sqrt((realT)qh hull_dim) * qh JOGGLEmax + qh DISTround;
00242 maxdist= 2*maxdist;
00243 maximize_(qh NEARinside, maxdist);
00244 }
00245 if (qh KEEPnearinside)
00246 qh_option("_near-inside", NULL, &qh NEARinside);
00247 if (qh JOGGLEmax < qh DISTround) {
00248 qh_fprintf(qh ferr, 6006, "qhull error: the joggle for 'QJn', %.2g, is below roundoff for distance computations, %.2g\n",
00249 qh JOGGLEmax, qh DISTround);
00250 qh_errexit(qh_ERRinput, NULL, NULL);
00251 }
00252 if (qh MINvisible > REALmax/2) {
00253 if (!qh MERGING)
00254 qh MINvisible= qh DISTround;
00255 else if (qh hull_dim <= 3)
00256 qh MINvisible= qh premerge_centrum;
00257 else
00258 qh MINvisible= qh_COPLANARratio * qh premerge_centrum;
00259 if (qh APPROXhull && qh MINvisible > qh MINoutside)
00260 qh MINvisible= qh MINoutside;
00261 qh_option("Visible-distance", NULL, &qh MINvisible);
00262 }
00263 if (qh MAXcoplanar > REALmax/2) {
00264 qh MAXcoplanar= qh MINvisible;
00265 qh_option("U-coplanar-distance", NULL, &qh MAXcoplanar);
00266 }
00267 if (!qh APPROXhull) {
00268 qh MINoutside= 2 * qh MINvisible;
00269 if (qh premerge_cos < REALmax/2)
00270 maximize_(qh MINoutside, (1- qh premerge_cos) * qh MAXabs_coord);
00271 qh_option("Width-outside", NULL, &qh MINoutside);
00272 }
00273 qh WIDEfacet= qh MINoutside;
00274 maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MAXcoplanar);
00275 maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MINvisible);
00276 qh_option("_wide-facet", NULL, &qh WIDEfacet);
00277 if (qh MINvisible > qh MINoutside + 3 * REALepsilon
00278 && !qh BESToutside && !qh FORCEoutput)
00279 qh_fprintf(qh ferr, 7001, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g. Flipped facets are likely.\n",
00280 qh MINvisible, qh MINoutside);
00281 qh max_vertex= qh DISTround;
00282 qh min_vertex= -qh DISTround;
00283
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero) {
00303 pointT *coorda, *coordp, *gmcoord, *point, **pointp;
00304 coordT **rows;
00305 int k, i=0;
00306 realT det;
00307
00308 zinc_(Zdetsimplex);
00309 gmcoord= qh gm_matrix;
00310 rows= qh gm_row;
00311 FOREACHpoint_(points) {
00312 if (i == dim)
00313 break;
00314 rows[i++]= gmcoord;
00315 coordp= point;
00316 coorda= apex;
00317 for (k=dim; k--; )
00318 *(gmcoord++)= *coordp++ - *coorda++;
00319 }
00320 if (i < dim) {
00321 qh_fprintf(qh ferr, 6007, "qhull internal error (qh_detsimplex): #points %d < dimension %d\n",
00322 i, dim);
00323 qh_errexit(qh_ERRqhull, NULL, NULL);
00324 }
00325 det= qh_determinant(rows, dim, nearzero);
00326 trace2((qh ferr, 2002, "qh_detsimplex: det=%2.2g for point p%d, dim %d, nearzero? %d\n",
00327 det, qh_pointid(apex), dim, *nearzero));
00328 return det;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 realT qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp) {
00347 coordT *normalp= normal, *coordp= point;
00348 realT dist;
00349 int k;
00350
00351 dist= *offsetp;
00352 for (k=dim; k--; )
00353 dist += *(coordp++) * *(normalp++);
00354 return dist;
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 realT qh_distround(int dimension, realT maxabs, realT maxsumabs) {
00376 realT maxdistsum, maxround;
00377
00378 maxdistsum= sqrt((realT)dimension) * maxabs;
00379 minimize_( maxdistsum, maxsumabs);
00380 maxround= REALepsilon * (dimension * maxdistsum * 1.01 + maxabs);
00381
00382 trace4((qh ferr, 4008, "qh_distround: %2.2g maxabs %2.2g maxsumabs %2.2g maxdistsum %2.2g\n",
00383 maxround, maxabs, maxsumabs, maxdistsum));
00384 return maxround;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 realT qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv) {
00409 realT temp, numerx, denomx;
00410
00411
00412 if (numer < mindenom1 && numer > -mindenom1) {
00413 numerx= fabs_(numer);
00414 denomx= fabs_(denom);
00415 if (numerx < denomx) {
00416 *zerodiv= False;
00417 return numer/denom;
00418 }else {
00419 *zerodiv= True;
00420 return 0.0;
00421 }
00422 }
00423 temp= denom/numer;
00424 if (temp > mindenom1 || temp < -mindenom1) {
00425 *zerodiv= False;
00426 return numer/denom;
00427 }else {
00428 *zerodiv= True;
00429 return 0.0;
00430 }
00431 }
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 realT qh_facetarea(facetT *facet) {
00457 vertexT *apex;
00458 pointT *centrum;
00459 realT area= 0.0;
00460 ridgeT *ridge, **ridgep;
00461
00462 if (facet->simplicial) {
00463 apex= SETfirstt_(facet->vertices, vertexT);
00464 area= qh_facetarea_simplex(qh hull_dim, apex->point, facet->vertices,
00465 apex, facet->toporient, facet->normal, &facet->offset);
00466 }else {
00467 if (qh CENTERtype == qh_AScentrum)
00468 centrum= facet->center;
00469 else
00470 centrum= qh_getcentrum(facet);
00471 FOREACHridge_(facet->ridges)
00472 area += qh_facetarea_simplex(qh hull_dim, centrum, ridge->vertices,
00473 NULL, (boolT)(ridge->top == facet), facet->normal, &facet->offset);
00474 if (qh CENTERtype != qh_AScentrum)
00475 qh_memfree(centrum, qh normal_size);
00476 }
00477 if (facet->upperdelaunay && qh DELAUNAY)
00478 area= -area;
00479 trace4((qh ferr, 4009, "qh_facetarea: f%d area %2.2g\n", facet->id, area));
00480 return area;
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 realT qh_facetarea_simplex(int dim, coordT *apex, setT *vertices,
00517 vertexT *notvertex, boolT toporient, coordT *normal, realT *offset) {
00518 pointT *coorda, *coordp, *gmcoord;
00519 coordT **rows, *normalp;
00520 int k, i=0;
00521 realT area, dist;
00522 vertexT *vertex, **vertexp;
00523 boolT nearzero;
00524
00525 gmcoord= qh gm_matrix;
00526 rows= qh gm_row;
00527 FOREACHvertex_(vertices) {
00528 if (vertex == notvertex)
00529 continue;
00530 rows[i++]= gmcoord;
00531 coorda= apex;
00532 coordp= vertex->point;
00533 normalp= normal;
00534 if (notvertex) {
00535 for (k=dim; k--; )
00536 *(gmcoord++)= *coordp++ - *coorda++;
00537 }else {
00538 dist= *offset;
00539 for (k=dim; k--; )
00540 dist += *coordp++ * *normalp++;
00541 if (dist < -qh WIDEfacet) {
00542 zinc_(Znoarea);
00543 return 0.0;
00544 }
00545 coordp= vertex->point;
00546 normalp= normal;
00547 for (k=dim; k--; )
00548 *(gmcoord++)= (*coordp++ - dist * *normalp++) - *coorda++;
00549 }
00550 }
00551 if (i != dim-1) {
00552 qh_fprintf(qh ferr, 6008, "qhull internal error (qh_facetarea_simplex): #points %d != dim %d -1\n",
00553 i, dim);
00554 qh_errexit(qh_ERRqhull, NULL, NULL);
00555 }
00556 rows[i]= gmcoord;
00557 if (qh DELAUNAY) {
00558 for (i=0; i < dim-1; i++)
00559 rows[i][dim-1]= 0.0;
00560 for (k=dim; k--; )
00561 *(gmcoord++)= 0.0;
00562 rows[dim-1][dim-1]= -1.0;
00563 }else {
00564 normalp= normal;
00565 for (k=dim; k--; )
00566 *(gmcoord++)= *normalp++;
00567 }
00568 zinc_(Zdetsimplex);
00569 area= qh_determinant(rows, dim, &nearzero);
00570 if (toporient)
00571 area= -area;
00572 area *= qh AREAfactor;
00573 trace4((qh ferr, 4010, "qh_facetarea_simplex: area=%2.2g for point p%d, toporient %d, nearzero? %d\n",
00574 area, qh_pointid(apex), toporient, nearzero));
00575 return area;
00576 }
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 pointT *qh_facetcenter(setT *vertices) {
00591 setT *points= qh_settemp(qh_setsize(vertices));
00592 vertexT *vertex, **vertexp;
00593 pointT *center;
00594
00595 FOREACHvertex_(vertices)
00596 qh_setappend(&points, vertex->point);
00597 center= qh_voronoi_center(qh hull_dim-1, points);
00598 qh_settempfree(&points);
00599 return center;
00600 }
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629 facetT *qh_findgooddist(pointT *point, facetT *facetA, realT *distp,
00630 facetT **facetlist) {
00631 realT bestdist= -REALmax, dist;
00632 facetT *neighbor, **neighborp, *bestfacet=NULL, *facet;
00633 boolT goodseen= False;
00634
00635 if (facetA->good) {
00636 zzinc_(Zcheckpart);
00637 qh_distplane(point, facetA, &bestdist);
00638 bestfacet= facetA;
00639 goodseen= True;
00640 }
00641 qh_removefacet(facetA);
00642 qh_appendfacet(facetA);
00643 *facetlist= facetA;
00644 facetA->visitid= ++qh visit_id;
00645 FORALLfacet_(*facetlist) {
00646 FOREACHneighbor_(facet) {
00647 if (neighbor->visitid == qh visit_id)
00648 continue;
00649 neighbor->visitid= qh visit_id;
00650 if (goodseen && !neighbor->good)
00651 continue;
00652 zzinc_(Zcheckpart);
00653 qh_distplane(point, neighbor, &dist);
00654 if (dist > 0) {
00655 qh_removefacet(neighbor);
00656 qh_appendfacet(neighbor);
00657 if (neighbor->good) {
00658 goodseen= True;
00659 if (dist > bestdist) {
00660 bestdist= dist;
00661 bestfacet= neighbor;
00662 }
00663 }
00664 }
00665 }
00666 }
00667 if (bestfacet) {
00668 *distp= bestdist;
00669 trace2((qh ferr, 2003, "qh_findgooddist: p%d is %2.2g above good facet f%d\n",
00670 qh_pointid(point), bestdist, bestfacet->id));
00671 return bestfacet;
00672 }
00673 trace4((qh ferr, 4011, "qh_findgooddist: no good facet for p%d above f%d\n",
00674 qh_pointid(point), facetA->id));
00675 return NULL;
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701 void qh_getarea(facetT *facetlist) {
00702 realT area;
00703 realT dist;
00704 facetT *facet;
00705
00706 if (qh hasAreaVolume)
00707 return;
00708 if (qh REPORTfreq)
00709 qh_fprintf(qh ferr, 8020, "computing area of each facet and volume of the convex hull\n");
00710 else
00711 trace1((qh ferr, 1001, "qh_getarea: computing volume and area for each facet\n"));
00712 qh totarea= qh totvol= 0.0;
00713 FORALLfacet_(facetlist) {
00714 if (!facet->normal)
00715 continue;
00716 if (facet->upperdelaunay && qh ATinfinity)
00717 continue;
00718 if (!facet->isarea) {
00719 facet->f.area= qh_facetarea(facet);
00720 facet->isarea= True;
00721 }
00722 area= facet->f.area;
00723 if (qh DELAUNAY) {
00724 if (facet->upperdelaunay == qh UPPERdelaunay)
00725 qh totarea += area;
00726 }else {
00727 qh totarea += area;
00728 qh_distplane(qh interior_point, facet, &dist);
00729 qh totvol += -dist * area/ qh hull_dim;
00730 }
00731 if (qh PRINTstatistics) {
00732 wadd_(Wareatot, area);
00733 wmax_(Wareamax, area);
00734 wmin_(Wareamin, area);
00735 }
00736 }
00737 qh hasAreaVolume= True;
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762 boolT qh_gram_schmidt(int dim, realT **row) {
00763 realT *rowi, *rowj, norm;
00764 int i, j, k;
00765
00766 for (i=0; i < dim; i++) {
00767 rowi= row[i];
00768 for (norm= 0.0, k= dim; k--; rowi++)
00769 norm += *rowi * *rowi;
00770 norm= sqrt(norm);
00771 wmin_(Wmindenom, norm);
00772 if (norm == 0.0)
00773 return False;
00774 for (k=dim; k--; )
00775 *(--rowi) /= norm;
00776 for (j=i+1; j < dim; j++) {
00777 rowj= row[j];
00778 for (norm= 0.0, k=dim; k--; )
00779 norm += *rowi++ * *rowj++;
00780 for (k=dim; k--; )
00781 *(--rowj) -= *(--rowi) * norm;
00782 }
00783 }
00784 return True;
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810 boolT qh_inthresholds(coordT *normal, realT *angle) {
00811 boolT within= True;
00812 int k;
00813 realT threshold;
00814
00815 if (angle)
00816 *angle= 0.0;
00817 for (k=0; k < qh hull_dim; k++) {
00818 threshold= qh lower_threshold[k];
00819 if (threshold > -REALmax/2) {
00820 if (normal[k] < threshold)
00821 within= False;
00822 if (angle) {
00823 threshold -= normal[k];
00824 *angle += fabs_(threshold);
00825 }
00826 }
00827 if (qh upper_threshold[k] < REALmax/2) {
00828 threshold= qh upper_threshold[k];
00829 if (normal[k] > threshold)
00830 within= False;
00831 if (angle) {
00832 threshold -= normal[k];
00833 *angle += fabs_(threshold);
00834 }
00835 }
00836 }
00837 return within;
00838 }
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873 void qh_joggleinput(void) {
00874 int i, seed, size;
00875 coordT *coordp, *inputp;
00876 realT randr, randa, randb;
00877
00878 if (!qh input_points) {
00879 qh input_points= qh first_point;
00880 qh input_malloc= qh POINTSmalloc;
00881 size= qh num_points * qh hull_dim * sizeof(coordT);
00882 if (!(qh first_point=(coordT*)qh_malloc((size_t)size))) {
00883 qh_fprintf(qh ferr, 6009, "qhull error: insufficient memory to joggle %d points\n",
00884 qh num_points);
00885 qh_errexit(qh_ERRmem, NULL, NULL);
00886 }
00887 qh POINTSmalloc= True;
00888 if (qh JOGGLEmax == 0.0) {
00889 qh JOGGLEmax= qh_detjoggle(qh input_points, qh num_points, qh hull_dim);
00890 qh_option("QJoggle", NULL, &qh JOGGLEmax);
00891 }
00892 }else {
00893 if (!qh RERUN && qh build_cnt > qh_JOGGLEretry) {
00894 if (((qh build_cnt-qh_JOGGLEretry-1) % qh_JOGGLEagain) == 0) {
00895 realT maxjoggle= qh MAXwidth * qh_JOGGLEmaxincrease;
00896 if (qh JOGGLEmax < maxjoggle) {
00897 qh JOGGLEmax *= qh_JOGGLEincrease;
00898 minimize_(qh JOGGLEmax, maxjoggle);
00899 }
00900 }
00901 }
00902 qh_option("QJoggle", NULL, &qh JOGGLEmax);
00903 }
00904 if (qh build_cnt > 1 && qh JOGGLEmax > fmax_(qh MAXwidth/4, 0.1)) {
00905 qh_fprintf(qh ferr, 6010, "qhull error: the current joggle for 'QJn', %.2g, is too large for the width\nof the input. If possible, recompile Qhull with higher-precision reals.\n",
00906 qh JOGGLEmax);
00907 qh_errexit(qh_ERRqhull, NULL, NULL);
00908 }
00909
00910 seed= qh_RANDOMint;
00911 qh_option("_joggle-seed", &seed, NULL);
00912 trace0((qh ferr, 6, "qh_joggleinput: joggle input by %2.2g with seed %d\n",
00913 qh JOGGLEmax, seed));
00914 inputp= qh input_points;
00915 coordp= qh first_point;
00916 randa= 2.0 * qh JOGGLEmax/qh_RANDOMmax;
00917 randb= -qh JOGGLEmax;
00918 size= qh num_points * qh hull_dim;
00919 for (i=size; i--; ) {
00920 randr= qh_RANDOMint;
00921 *(coordp++)= *(inputp++) + (randr * randa + randb);
00922 }
00923 if (qh DELAUNAY) {
00924 qh last_low= qh last_high= qh last_newhigh= REALmax;
00925 qh_setdelaunay(qh hull_dim, qh num_points, qh first_point);
00926 }
00927 }
00928
00929
00930
00931
00932
00933
00934
00935
00936 realT *qh_maxabsval(realT *normal, int dim) {
00937 realT maxval= -REALmax;
00938 realT *maxp= NULL, *colp, absval;
00939 int k;
00940
00941 for (k=dim, colp= normal; k--; colp++) {
00942 absval= fabs_(*colp);
00943 if (absval > maxval) {
00944 maxval= absval;
00945 maxp= colp;
00946 }
00947 }
00948 return maxp;
00949 }
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978 setT *qh_maxmin(pointT *points, int numpoints, int dimension) {
00979 int k;
00980 realT maxcoord, temp;
00981 pointT *minimum, *maximum, *point, *pointtemp;
00982 setT *set;
00983
00984 qh max_outside= 0.0;
00985 qh MAXabs_coord= 0.0;
00986 qh MAXwidth= -REALmax;
00987 qh MAXsumcoord= 0.0;
00988 qh min_vertex= 0.0;
00989 qh WAScoplanar= False;
00990 if (qh ZEROcentrum)
00991 qh ZEROall_ok= True;
00992 if (REALmin < REALepsilon && REALmin < REALmax && REALmin > -REALmax
00993 && REALmax > 0.0 && -REALmax < 0.0)
00994 ;
00995 else {
00996 qh_fprintf(qh ferr, 6011, "qhull error: floating point constants in user.h are wrong\n\
00997 REALepsilon %g REALmin %g REALmax %g -REALmax %g\n",
00998 REALepsilon, REALmin, REALmax, -REALmax);
00999 qh_errexit(qh_ERRinput, NULL, NULL);
01000 }
01001 set= qh_settemp(2*dimension);
01002 for (k=0; k < dimension; k++) {
01003 if (points == qh GOODpointp)
01004 minimum= maximum= points + dimension;
01005 else
01006 minimum= maximum= points;
01007 FORALLpoint_(points, numpoints) {
01008 if (point == qh GOODpointp)
01009 continue;
01010 if (maximum[k] < point[k])
01011 maximum= point;
01012 else if (minimum[k] > point[k])
01013 minimum= point;
01014 }
01015 if (k == dimension-1) {
01016 qh MINlastcoord= minimum[k];
01017 qh MAXlastcoord= maximum[k];
01018 }
01019 if (qh SCALElast && k == dimension-1)
01020 maxcoord= qh MAXwidth;
01021 else {
01022 maxcoord= fmax_(maximum[k], -minimum[k]);
01023 if (qh GOODpointp) {
01024 temp= fmax_(qh GOODpointp[k], -qh GOODpointp[k]);
01025 maximize_(maxcoord, temp);
01026 }
01027 temp= maximum[k] - minimum[k];
01028 maximize_(qh MAXwidth, temp);
01029 }
01030 maximize_(qh MAXabs_coord, maxcoord);
01031 qh MAXsumcoord += maxcoord;
01032 qh_setappend(&set, maximum);
01033 qh_setappend(&set, minimum);
01034
01035
01036
01037 qh NEARzero[k]= 80 * qh MAXsumcoord * REALepsilon;
01038 }
01039 if (qh IStracing >=1)
01040 qh_printpoints(qh ferr, "qh_maxmin: found the max and min points(by dim):", set);
01041 return(set);
01042 }
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064 realT qh_maxouter(void) {
01065 realT dist;
01066
01067 dist= fmax_(qh max_outside, qh DISTround);
01068 dist += qh DISTround;
01069 trace4((qh ferr, 4012, "qh_maxouter: max distance from facet to outer plane is %2.2g max_outside is %2.2g\n", dist, qh max_outside));
01070 return dist;
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 void qh_maxsimplex(int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) {
01097 pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL;
01098 boolT nearzero, maxnearzero= False;
01099 int k, sizinit;
01100 realT maxdet= -REALmax, det, mincoord= REALmax, maxcoord= -REALmax;
01101
01102 sizinit= qh_setsize(*simplex);
01103 if (sizinit < 2) {
01104 if (qh_setsize(maxpoints) >= 2) {
01105 FOREACHpoint_(maxpoints) {
01106 if (maxcoord < point[0]) {
01107 maxcoord= point[0];
01108 maxx= point;
01109 }
01110 if (mincoord > point[0]) {
01111 mincoord= point[0];
01112 minx= point;
01113 }
01114 }
01115 }else {
01116 FORALLpoint_(points, numpoints) {
01117 if (point == qh GOODpointp)
01118 continue;
01119 if (maxcoord < point[0]) {
01120 maxcoord= point[0];
01121 maxx= point;
01122 }
01123 if (mincoord > point[0]) {
01124 mincoord= point[0];
01125 minx= point;
01126 }
01127 }
01128 }
01129 qh_setunique(simplex, minx);
01130 if (qh_setsize(*simplex) < 2)
01131 qh_setunique(simplex, maxx);
01132 sizinit= qh_setsize(*simplex);
01133 if (sizinit < 2) {
01134 qh_precision("input has same x coordinate");
01135 if (zzval_(Zsetplane) > qh hull_dim+1) {
01136 qh_fprintf(qh ferr, 6012, "qhull precision error (qh_maxsimplex for voronoi_center):\n%d points with the same x coordinate.\n",
01137 qh_setsize(maxpoints)+numpoints);
01138 qh_errexit(qh_ERRprec, NULL, NULL);
01139 }else {
01140 qh_fprintf(qh ferr, 6013, "qhull input error: input is less than %d-dimensional since it has the same x coordinate\n", qh hull_dim);
01141 qh_errexit(qh_ERRinput, NULL, NULL);
01142 }
01143 }
01144 }
01145 for (k=sizinit; k < dim+1; k++) {
01146 maxpoint= NULL;
01147 maxdet= -REALmax;
01148 FOREACHpoint_(maxpoints) {
01149 if (!qh_setin(*simplex, point)) {
01150 det= qh_detsimplex(point, *simplex, k, &nearzero);
01151 if ((det= fabs_(det)) > maxdet) {
01152 maxdet= det;
01153 maxpoint= point;
01154 maxnearzero= nearzero;
01155 }
01156 }
01157 }
01158 if (!maxpoint || maxnearzero) {
01159 zinc_(Zsearchpoints);
01160 if (!maxpoint) {
01161 trace0((qh ferr, 7, "qh_maxsimplex: searching all points for %d-th initial vertex.\n", k+1));
01162 }else {
01163 trace0((qh ferr, 8, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g\n",
01164 k+1, qh_pointid(maxpoint), maxdet));
01165 }
01166 FORALLpoint_(points, numpoints) {
01167 if (point == qh GOODpointp)
01168 continue;
01169 if (!qh_setin(*simplex, point)) {
01170 det= qh_detsimplex(point, *simplex, k, &nearzero);
01171 if ((det= fabs_(det)) > maxdet) {
01172 maxdet= det;
01173 maxpoint= point;
01174 maxnearzero= nearzero;
01175 }
01176 }
01177 }
01178 }
01179 if (!maxpoint) {
01180 qh_fprintf(qh ferr, 6014, "qhull internal error (qh_maxsimplex): not enough points available\n");
01181 qh_errexit(qh_ERRqhull, NULL, NULL);
01182 }
01183 qh_setappend(simplex, maxpoint);
01184 trace1((qh ferr, 1002, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%2.2g\n",
01185 qh_pointid(maxpoint), k+1, maxdet));
01186 }
01187 }
01188
01189
01190
01191
01192
01193
01194
01195 realT qh_minabsval(realT *normal, int dim) {
01196 realT minval= 0;
01197 realT maxval= 0;
01198 realT *colp;
01199 int k;
01200
01201 for (k=dim, colp=normal; k--; colp++) {
01202 maximize_(maxval, *colp);
01203 minimize_(minval, *colp);
01204 }
01205 return fmax_(maxval, -minval);
01206 }
01207
01208
01209
01210
01211
01212
01213
01214
01215 int qh_mindiff(realT *vecA, realT *vecB, int dim) {
01216 realT mindiff= REALmax, diff;
01217 realT *vecAp= vecA, *vecBp= vecB;
01218 int k, mink= 0;
01219
01220 for (k=0; k < dim; k++) {
01221 diff= *vecAp++ - *vecBp++;
01222 diff= fabs_(diff);
01223 if (diff < mindiff) {
01224 mindiff= diff;
01225 mink= k;
01226 }
01227 }
01228 return mink;
01229 }
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242 boolT qh_orientoutside(facetT *facet) {
01243 int k;
01244 realT dist;
01245
01246 qh_distplane(qh interior_point, facet, &dist);
01247 if (dist > 0) {
01248 for (k=qh hull_dim; k--; )
01249 facet->normal[k]= -facet->normal[k];
01250 facet->offset= -facet->offset;
01251 return True;
01252 }
01253 return False;
01254 }
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277 void qh_outerinner(facetT *facet, realT *outerplane, realT *innerplane) {
01278 realT dist, mindist;
01279 vertexT *vertex, **vertexp;
01280
01281 if (outerplane) {
01282 if (!qh_MAXoutside || !facet || !qh maxoutdone) {
01283 *outerplane= qh_maxouter();
01284 }else {
01285 #if qh_MAXoutside
01286 *outerplane= facet->maxoutside + qh DISTround;
01287 #endif
01288
01289 }
01290 if (qh JOGGLEmax < REALmax/2)
01291 *outerplane += qh JOGGLEmax * sqrt((realT)qh hull_dim);
01292 }
01293 if (innerplane) {
01294 if (facet) {
01295 mindist= REALmax;
01296 FOREACHvertex_(facet->vertices) {
01297 zinc_(Zdistio);
01298 qh_distplane(vertex->point, facet, &dist);
01299 minimize_(mindist, dist);
01300 }
01301 *innerplane= mindist - qh DISTround;
01302 }else
01303 *innerplane= qh min_vertex - qh DISTround;
01304 if (qh JOGGLEmax < REALmax/2)
01305 *innerplane -= qh JOGGLEmax * sqrt((realT)qh hull_dim);
01306 }
01307 }
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318 coordT qh_pointdist(pointT *point1, pointT *point2, int dim) {
01319 coordT dist, diff;
01320 int k;
01321
01322 dist= 0.0;
01323 for (k= (dim > 0 ? dim : -dim); k--; ) {
01324 diff= *point1++ - *point2++;
01325 dist += diff * diff;
01326 }
01327 if (dim > 0)
01328 return(sqrt(dist));
01329 return dist;
01330 }
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343 void qh_printmatrix(FILE *fp, const char *string, realT **rows, int numrow, int numcol) {
01344 realT *rowp;
01345 realT r;
01346 int i,k;
01347
01348 qh_fprintf(fp, 9001, "%s\n", string);
01349 for (i=0; i < numrow; i++) {
01350 rowp= rows[i];
01351 for (k=0; k < numcol; k++) {
01352 r= *rowp++;
01353 qh_fprintf(fp, 9002, "%6.3g ", r);
01354 }
01355 qh_fprintf(fp, 9003, "\n");
01356 }
01357 }
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367 void qh_printpoints(FILE *fp, const char *string, setT *points) {
01368 pointT *point, **pointp;
01369
01370 if (string) {
01371 qh_fprintf(fp, 9004, "%s", string);
01372 FOREACHpoint_(points)
01373 qh_fprintf(fp, 9005, " p%d", qh_pointid(point));
01374 qh_fprintf(fp, 9006, "\n");
01375 }else {
01376 FOREACHpoint_(points)
01377 qh_fprintf(fp, 9007, " %d", qh_pointid(point));
01378 qh_fprintf(fp, 9008, "\n");
01379 }
01380 }
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422 void qh_projectinput(void) {
01423 int k,i;
01424 int newdim= qh input_dim, newnum= qh num_points;
01425 signed char *project;
01426 int size= (qh input_dim+1)*sizeof(*project);
01427 pointT *newpoints, *coord, *infinity;
01428 realT paraboloid, maxboloid= 0;
01429
01430 project= (signed char*)qh_memalloc(size);
01431 memset((char*)project, 0, (size_t)size);
01432 for (k=0; k < qh input_dim; k++) {
01433 if (qh lower_bound[k] == 0 && qh upper_bound[k] == 0) {
01434 project[k]= -1;
01435 newdim--;
01436 }
01437 }
01438 if (qh DELAUNAY) {
01439 project[k]= 1;
01440 newdim++;
01441 if (qh ATinfinity)
01442 newnum++;
01443 }
01444 if (newdim != qh hull_dim) {
01445 qh_fprintf(qh ferr, 6015, "qhull internal error (qh_projectinput): dimension after projection %d != hull_dim %d\n", newdim, qh hull_dim);
01446 qh_errexit(qh_ERRqhull, NULL, NULL);
01447 }
01448 if (!(newpoints=(coordT*)qh_malloc(newnum*newdim*sizeof(coordT)))){
01449 qh_fprintf(qh ferr, 6016, "qhull error: insufficient memory to project %d points\n",
01450 qh num_points);
01451 qh_errexit(qh_ERRmem, NULL, NULL);
01452 }
01453 qh_projectpoints(project, qh input_dim+1, qh first_point,
01454 qh num_points, qh input_dim, newpoints, newdim);
01455 trace1((qh ferr, 1003, "qh_projectinput: updating lower and upper_bound\n"));
01456 qh_projectpoints(project, qh input_dim+1, qh lower_bound,
01457 1, qh input_dim+1, qh lower_bound, newdim+1);
01458 qh_projectpoints(project, qh input_dim+1, qh upper_bound,
01459 1, qh input_dim+1, qh upper_bound, newdim+1);
01460 if (qh HALFspace) {
01461 if (!qh feasible_point) {
01462 qh_fprintf(qh ferr, 6017, "qhull internal error (qh_projectinput): HALFspace defined without qh.feasible_point\n");
01463 qh_errexit(qh_ERRqhull, NULL, NULL);
01464 }
01465 qh_projectpoints(project, qh input_dim, qh feasible_point,
01466 1, qh input_dim, qh feasible_point, newdim);
01467 }
01468 qh_memfree(project, (qh input_dim+1)*sizeof(*project));
01469 if (qh POINTSmalloc)
01470 qh_free(qh first_point);
01471 qh first_point= newpoints;
01472 qh POINTSmalloc= True;
01473 if (qh DELAUNAY && qh ATinfinity) {
01474 coord= qh first_point;
01475 infinity= qh first_point + qh hull_dim * qh num_points;
01476 for (k=qh hull_dim-1; k--; )
01477 infinity[k]= 0.0;
01478 for (i=qh num_points; i--; ) {
01479 paraboloid= 0.0;
01480 for (k=0; k < qh hull_dim-1; k++) {
01481 paraboloid += *coord * *coord;
01482 infinity[k] += *coord;
01483 coord++;
01484 }
01485 *(coord++)= paraboloid;
01486 maximize_(maxboloid, paraboloid);
01487 }
01488
01489 for (k=qh hull_dim-1; k--; )
01490 *(coord++) /= qh num_points;
01491 *(coord++)= maxboloid * 1.1;
01492 qh num_points++;
01493 trace0((qh ferr, 9, "qh_projectinput: projected points to paraboloid for Delaunay\n"));
01494 }else if (qh DELAUNAY)
01495 qh_setdelaunay( qh hull_dim, qh num_points, qh first_point);
01496 }
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524 void qh_projectpoints(signed char *project, int n, realT *points,
01525 int numpoints, int dim, realT *newpoints, int newdim) {
01526 int testdim= dim, oldk=0, newk=0, i,j=0,k;
01527 realT *newp, *oldp;
01528
01529 for (k=0; k < n; k++)
01530 testdim += project[k];
01531 if (testdim != newdim) {
01532 qh_fprintf(qh ferr, 6018, "qhull internal error (qh_projectpoints): newdim %d should be %d after projection\n",
01533 newdim, testdim);
01534 qh_errexit(qh_ERRqhull, NULL, NULL);
01535 }
01536 for (j=0; j<n; j++) {
01537 if (project[j] == -1)
01538 oldk++;
01539 else {
01540 newp= newpoints+newk++;
01541 if (project[j] == +1) {
01542 if (oldk >= dim)
01543 continue;
01544 oldp= points+oldk;
01545 }else
01546 oldp= points+oldk++;
01547 for (i=numpoints; i--; ) {
01548 *newp= *oldp;
01549 newp += newdim;
01550 oldp += dim;
01551 }
01552 }
01553 if (oldk >= dim)
01554 break;
01555 }
01556 trace1((qh ferr, 1004, "qh_projectpoints: projected %d points from dim %d to dim %d\n",
01557 numpoints, dim, newdim));
01558 }
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577 void qh_rotateinput(realT **rows) {
01578
01579 if (!qh POINTSmalloc) {
01580 qh first_point= qh_copypoints(qh first_point, qh num_points, qh hull_dim);
01581 qh POINTSmalloc= True;
01582 }
01583 qh_rotatepoints(qh first_point, qh num_points, qh hull_dim, rows);
01584 }
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603 void qh_rotatepoints(realT *points, int numpoints, int dim, realT **row) {
01604 realT *point, *rowi, *coord= NULL, sum, *newval;
01605 int i,j,k;
01606
01607 if (qh IStracing >= 1)
01608 qh_printmatrix(qh ferr, "qh_rotatepoints: rotate points by", row, dim, dim);
01609 for (point= points, j= numpoints; j--; point += dim) {
01610 newval= row[dim];
01611 for (i=0; i < dim; i++) {
01612 rowi= row[i];
01613 coord= point;
01614 for (sum= 0.0, k= dim; k--; )
01615 sum += *rowi++ * *coord++;
01616 *(newval++)= sum;
01617 }
01618 for (k=dim; k--; )
01619 *(--coord)= *(--newval);
01620 }
01621 }
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639 void qh_scaleinput(void) {
01640
01641 if (!qh POINTSmalloc) {
01642 qh first_point= qh_copypoints(qh first_point, qh num_points, qh hull_dim);
01643 qh POINTSmalloc= True;
01644 }
01645 qh_scalepoints(qh first_point, qh num_points, qh hull_dim,
01646 qh lower_bound, qh upper_bound);
01647 }
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668 void qh_scalelast(coordT *points, int numpoints, int dim, coordT low,
01669 coordT high, coordT newhigh) {
01670 realT scale, shift;
01671 coordT *coord;
01672 int i;
01673 boolT nearzero= False;
01674
01675 trace4((qh ferr, 4013, "qh_scalelast: scale last coordinate from [%2.2g, %2.2g] to [0,%2.2g]\n",
01676 low, high, newhigh));
01677 qh last_low= low;
01678 qh last_high= high;
01679 qh last_newhigh= newhigh;
01680 scale= qh_divzero(newhigh, high - low,
01681 qh MINdenom_1, &nearzero);
01682 if (nearzero) {
01683 if (qh DELAUNAY)
01684 qh_fprintf(qh ferr, 6019, "qhull input error: can not scale last coordinate. Input is cocircular\n or cospherical. Use option 'Qz' to add a point at infinity.\n");
01685 else
01686 qh_fprintf(qh ferr, 6020, "qhull input error: can not scale last coordinate. New bounds [0, %2.2g] are too wide for\nexisting bounds [%2.2g, %2.2g] (width %2.2g)\n",
01687 newhigh, low, high, high-low);
01688 qh_errexit(qh_ERRinput, NULL, NULL);
01689 }
01690 shift= - low * newhigh / (high-low);
01691 coord= points + dim - 1;
01692 for (i=numpoints; i--; coord += dim)
01693 *coord= *coord * scale + shift;
01694 }
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714 void qh_scalepoints(pointT *points, int numpoints, int dim,
01715 realT *newlows, realT *newhighs) {
01716 int i,k;
01717 realT shift, scale, *coord, low, high, newlow, newhigh, mincoord, maxcoord;
01718 boolT nearzero= False;
01719
01720 for (k=0; k < dim; k++) {
01721 newhigh= newhighs[k];
01722 newlow= newlows[k];
01723 if (newhigh > REALmax/2 && newlow < -REALmax/2)
01724 continue;
01725 low= REALmax;
01726 high= -REALmax;
01727 for (i=numpoints, coord=points+k; i--; coord += dim) {
01728 minimize_(low, *coord);
01729 maximize_(high, *coord);
01730 }
01731 if (newhigh > REALmax/2)
01732 newhigh= high;
01733 if (newlow < -REALmax/2)
01734 newlow= low;
01735 if (qh DELAUNAY && k == dim-1 && newhigh < newlow) {
01736 qh_fprintf(qh ferr, 6021, "qhull input error: 'Qb%d' or 'QB%d' inverts paraboloid since high bound %.2g < low bound %.2g\n",
01737 k, k, newhigh, newlow);
01738 qh_errexit(qh_ERRinput, NULL, NULL);
01739 }
01740 scale= qh_divzero(newhigh - newlow, high - low,
01741 qh MINdenom_1, &nearzero);
01742 if (nearzero) {
01743 qh_fprintf(qh ferr, 6022, "qhull input error: %d'th dimension's new bounds [%2.2g, %2.2g] too wide for\nexisting bounds [%2.2g, %2.2g]\n",
01744 k, newlow, newhigh, low, high);
01745 qh_errexit(qh_ERRinput, NULL, NULL);
01746 }
01747 shift= (newlow * high - low * newhigh)/(high-low);
01748 coord= points+k;
01749 for (i=numpoints; i--; coord += dim)
01750 *coord= *coord * scale + shift;
01751 coord= points+k;
01752 if (newlow < newhigh) {
01753 mincoord= newlow;
01754 maxcoord= newhigh;
01755 }else {
01756 mincoord= newhigh;
01757 maxcoord= newlow;
01758 }
01759 for (i=numpoints; i--; coord += dim) {
01760 minimize_(*coord, maxcoord);
01761 maximize_(*coord, mincoord);
01762 }
01763 trace0((qh ferr, 10, "qh_scalepoints: scaled %d'th coordinate [%2.2g, %2.2g] to [%.2g, %.2g] for %d points by %2.2g and shifted %2.2g\n",
01764 k, low, high, newlow, newhigh, numpoints, scale, shift));
01765 }
01766 }
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799 void qh_setdelaunay(int dim, int count, pointT *points) {
01800 int i, k;
01801 coordT *coordp, coord;
01802 realT paraboloid;
01803
01804 trace0((qh ferr, 11, "qh_setdelaunay: project %d points to paraboloid for Delaunay triangulation\n", count));
01805 coordp= points;
01806 for (i=0; i < count; i++) {
01807 coord= *coordp++;
01808 paraboloid= coord*coord;
01809 for (k=dim-2; k--; ) {
01810 coord= *coordp++;
01811 paraboloid += coord*coord;
01812 }
01813 *coordp++ = paraboloid;
01814 }
01815 if (qh last_low < REALmax/2)
01816 qh_scalelast(points, count, dim, qh last_low, qh last_high, qh last_newhigh);
01817 }
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836 boolT qh_sethalfspace(int dim, coordT *coords, coordT **nextp,
01837 coordT *normal, coordT *offset, coordT *feasible) {
01838 coordT *normp= normal, *feasiblep= feasible, *coordp= coords;
01839 realT dist;
01840 realT r;
01841 int k;
01842 boolT zerodiv;
01843
01844 dist= *offset;
01845 for (k=dim; k--; )
01846 dist += *(normp++) * *(feasiblep++);
01847 if (dist > 0)
01848 goto LABELerroroutside;
01849 normp= normal;
01850 if (dist < -qh MINdenom) {
01851 for (k=dim; k--; )
01852 *(coordp++)= *(normp++) / -dist;
01853 }else {
01854 for (k=dim; k--; ) {
01855 *(coordp++)= qh_divzero(*(normp++), -dist, qh MINdenom_1, &zerodiv);
01856 if (zerodiv)
01857 goto LABELerroroutside;
01858 }
01859 }
01860 *nextp= coordp;
01861 if (qh IStracing >= 4) {
01862 qh_fprintf(qh ferr, 8021, "qh_sethalfspace: halfspace at offset %6.2g to point: ", *offset);
01863 for (k=dim, coordp=coords; k--; ) {
01864 r= *coordp++;
01865 qh_fprintf(qh ferr, 8022, " %6.2g", r);
01866 }
01867 qh_fprintf(qh ferr, 8023, "\n");
01868 }
01869 return True;
01870 LABELerroroutside:
01871 feasiblep= feasible;
01872 normp= normal;
01873 qh_fprintf(qh ferr, 6023, "qhull input error: feasible point is not clearly inside halfspace\nfeasible point: ");
01874 for (k=dim; k--; )
01875 qh_fprintf(qh ferr, 8024, qh_REAL_1, r=*(feasiblep++));
01876 qh_fprintf(qh ferr, 8025, "\n halfspace: ");
01877 for (k=dim; k--; )
01878 qh_fprintf(qh ferr, 8026, qh_REAL_1, r=*(normp++));
01879 qh_fprintf(qh ferr, 8027, "\n at offset: ");
01880 qh_fprintf(qh ferr, 8028, qh_REAL_1, *offset);
01881 qh_fprintf(qh ferr, 8029, " and distance: ");
01882 qh_fprintf(qh ferr, 8030, qh_REAL_1, dist);
01883 qh_fprintf(qh ferr, 8031, "\n");
01884 return False;
01885 }
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908 coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feasible) {
01909 int i, newdim;
01910 pointT *newpoints;
01911 coordT *coordp, *normalp, *offsetp;
01912
01913 trace0((qh ferr, 12, "qh_sethalfspace_all: compute dual for halfspace intersection\n"));
01914 newdim= dim - 1;
01915 if (!(newpoints=(coordT*)qh_malloc(count*newdim*sizeof(coordT)))){
01916 qh_fprintf(qh ferr, 6024, "qhull error: insufficient memory to compute dual of %d halfspaces\n",
01917 count);
01918 qh_errexit(qh_ERRmem, NULL, NULL);
01919 }
01920 coordp= newpoints;
01921 normalp= halfspaces;
01922 for (i=0; i < count; i++) {
01923 offsetp= normalp + newdim;
01924 if (!qh_sethalfspace(newdim, coordp, &coordp, normalp, offsetp, feasible)) {
01925 qh_fprintf(qh ferr, 8032, "The halfspace was at index %d\n", i);
01926 qh_errexit(qh_ERRinput, NULL, NULL);
01927 }
01928 normalp= offsetp + 1;
01929 }
01930 return newpoints;
01931 }
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950 boolT qh_sharpnewfacets() {
01951 facetT *facet;
01952 boolT issharp = False;
01953 int *quadrant, k;
01954
01955 quadrant= (int*)qh_memalloc(qh hull_dim * sizeof(int));
01956 FORALLfacet_(qh newfacet_list) {
01957 if (facet == qh newfacet_list) {
01958 for (k=qh hull_dim; k--; )
01959 quadrant[ k]= (facet->normal[ k] > 0);
01960 }else {
01961 for (k=qh hull_dim; k--; ) {
01962 if (quadrant[ k] != (facet->normal[ k] > 0)) {
01963 issharp= True;
01964 break;
01965 }
01966 }
01967 }
01968 if (issharp)
01969 break;
01970 }
01971 qh_memfree( quadrant, qh hull_dim * sizeof(int));
01972 trace3((qh ferr, 3001, "qh_sharpnewfacets: %d\n", issharp));
01973 return issharp;
01974 }
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000 pointT *qh_voronoi_center(int dim, setT *points) {
02001 pointT *point, **pointp, *point0;
02002 pointT *center= (pointT*)qh_memalloc(qh center_size);
02003 setT *simplex;
02004 int i, j, k, size= qh_setsize(points);
02005 coordT *gmcoord;
02006 realT *diffp, sum2, *sum2row, *sum2p, det, factor;
02007 boolT nearzero, infinite;
02008
02009 if (size == dim+1)
02010 simplex= points;
02011 else if (size < dim+1) {
02012 qh_fprintf(qh ferr, 6025, "qhull internal error (qh_voronoi_center):\n need at least %d points to construct a Voronoi center\n",
02013 dim+1);
02014 qh_errexit(qh_ERRqhull, NULL, NULL);
02015 simplex= points;
02016 }else {
02017 simplex= qh_settemp(dim+1);
02018 qh_maxsimplex(dim, points, NULL, 0, &simplex);
02019 }
02020 point0= SETfirstt_(simplex, pointT);
02021 gmcoord= qh gm_matrix;
02022 for (k=0; k < dim; k++) {
02023 qh gm_row[k]= gmcoord;
02024 FOREACHpoint_(simplex) {
02025 if (point != point0)
02026 *(gmcoord++)= point[k] - point0[k];
02027 }
02028 }
02029 sum2row= gmcoord;
02030 for (i=0; i < dim; i++) {
02031 sum2= 0.0;
02032 for (k=0; k < dim; k++) {
02033 diffp= qh gm_row[k] + i;
02034 sum2 += *diffp * *diffp;
02035 }
02036 *(gmcoord++)= sum2;
02037 }
02038 det= qh_determinant(qh gm_row, dim, &nearzero);
02039 factor= qh_divzero(0.5, det, qh MINdenom, &infinite);
02040 if (infinite) {
02041 for (k=dim; k--; )
02042 center[k]= qh_INFINITE;
02043 if (qh IStracing)
02044 qh_printpoints(qh ferr, "qh_voronoi_center: at infinity for ", simplex);
02045 }else {
02046 for (i=0; i < dim; i++) {
02047 gmcoord= qh gm_matrix;
02048 sum2p= sum2row;
02049 for (k=0; k < dim; k++) {
02050 qh gm_row[k]= gmcoord;
02051 if (k == i) {
02052 for (j=dim; j--; )
02053 *(gmcoord++)= *sum2p++;
02054 }else {
02055 FOREACHpoint_(simplex) {
02056 if (point != point0)
02057 *(gmcoord++)= point[k] - point0[k];
02058 }
02059 }
02060 }
02061 center[i]= qh_determinant(qh gm_row, dim, &nearzero)*factor + point0[i];
02062 }
02063 #ifndef qh_NOtrace
02064 if (qh IStracing >= 3) {
02065 qh_fprintf(qh ferr, 8033, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor);
02066 qh_printmatrix(qh ferr, "center:", ¢er, 1, dim);
02067 if (qh IStracing >= 5) {
02068 qh_printpoints(qh ferr, "points", simplex);
02069 FOREACHpoint_(simplex)
02070 qh_fprintf(qh ferr, 8034, "p%d dist %.2g, ", qh_pointid(point),
02071 qh_pointdist(point, center, dim));
02072 qh_fprintf(qh ferr, 8035, "\n");
02073 }
02074 }
02075 #endif
02076 }
02077 if (simplex != points)
02078 qh_settempfree(&simplex);
02079 return center;
02080 }
02081