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