00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "qhull_a.h"
00015
00016 #ifdef USE_DMALLOC
00017 #include "dmalloc.h"
00018 #endif
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 void qh_addhash (void* newelem, setT *hashtable, int hashsize, unsigned hash) {
00029 int scan;
00030 void *elem;
00031
00032 for (scan= (int)hash; (elem= SETelem_(hashtable, scan));
00033 scan= (++scan >= hashsize ? 0 : scan)) {
00034 if (elem == newelem)
00035 break;
00036 }
00037
00038 if (!elem)
00039 SETelem_(hashtable, scan)= newelem;
00040 }
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 void qh_check_bestdist (void) {
00067 boolT waserror= False, isoutside, unassigned;
00068 facetT *facet, *bestfacet, *errfacet1= NULL, *errfacet2= NULL;
00069 facetT *facetlist;
00070 realT dist, maxoutside, maxdist= -REALmax;
00071 pointT *point;
00072 int numpart, facet_i, facet_n, notgood= 0, notverified= 0;
00073 setT *facets;
00074
00075 trace1((qh ferr, "qh_check_bestdist: check points below nearest facet. Facet_list f%d\n",
00076 qh facet_list->id));
00077 maxoutside= qh_maxouter();
00078 maxoutside += qh DISTround;
00079
00080 trace1((qh ferr, "qh_check_bestdist: check that all points are within %2.2g of best facet\n", maxoutside));
00081 facets= qh_pointfacet ();
00082 if (!qh_QUICKhelp && qh PRINTprecision)
00083 fprintf (qh ferr, "\n\
00084 qhull output completed. Verifying that %d points are\n\
00085 below %2.2g of the nearest %sfacet.\n",
00086 qh_setsize(facets), maxoutside, (qh ONLYgood ? "good " : ""));
00087 FOREACHfacet_i_(facets) {
00088 if (facet)
00089 unassigned= False;
00090 else {
00091 unassigned= True;
00092 facet= qh facet_list;
00093 }
00094 point= qh_point(facet_i);
00095 if (point == qh GOODpointp)
00096 continue;
00097 bestfacet= qh_findbest (point, facet, qh_ALL, False, !qh_NOupper,
00098 &dist, &isoutside, &numpart);
00099
00100 maximize_(maxdist, dist);
00101 if (dist > maxoutside) {
00102 if (qh ONLYgood && !bestfacet->good
00103 && !((bestfacet= qh_findgooddist (point, bestfacet, &dist, &facetlist))
00104 && dist > maxoutside))
00105 notgood++;
00106 else {
00107 waserror= True;
00108 fprintf(qh ferr, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
00109 facet_i, bestfacet->id, dist, maxoutside);
00110 errfacet2= errfacet1;
00111 errfacet1= bestfacet;
00112 }
00113 }else if (unassigned && dist < -qh MAXcoplanar)
00114 notverified++;
00115 }
00116 qh_settempfree (&facets);
00117 if (notverified && !qh DELAUNAY && !qh_QUICKhelp && qh PRINTprecision)
00118 fprintf(qh ferr, "\n%d points were well inside the hull. If the hull contains\n\
00119 a lens-shaped component, these points were not verified. Use\n\
00120 options 'Qci Tv' to verify all points.\n", notverified);
00121 if (maxdist > qh outside_err) {
00122 fprintf( qh ferr, "qhull precision error (qh_check_bestdist): a coplanar point is %6.2g from convex hull. The maximum value (qh.outside_err) is %6.2g\n",
00123 maxdist, qh outside_err);
00124 qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
00125 }else if (waserror && qh outside_err > REALmax/2)
00126 qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
00127 else if (waserror)
00128 ;
00129 trace0((qh ferr, "qh_check_bestdist: max distance outside %2.2g\n", maxdist));
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 #ifndef qh_NOmerge
00165 void qh_check_maxout (void) {
00166 facetT *facet, *bestfacet, *neighbor, **neighborp, *facetlist;
00167 realT dist, maxoutside, minvertex;
00168 pointT *point;
00169 int numpart, facet_i, facet_n, notgood= 0;
00170 setT *facets, *vertices;
00171 vertexT *vertex;
00172
00173 maxoutside= minvertex= 0;
00174 if (qh VERTEXneighbors
00175 && (qh PRINTsummary || qh KEEPinside || qh KEEPcoplanar
00176 || qh TRACElevel || qh PRINTstatistics
00177 || qh PRINTout[0] == qh_PRINTsummary || qh PRINTout[0] == qh_PRINTnone)) {
00178 trace1((qh ferr, "qh_check_maxout: determine actual maxoutside and minvertex\n"));
00179 vertices= qh_pointvertex ();
00180 FORALLvertices {
00181 FOREACHneighbor_(vertex) {
00182 zinc_(Zdistvertex);
00183 qh_distplane (vertex->point, neighbor, &dist);
00184 minimize_(minvertex, dist);
00185 if (-dist > qh TRACEdist || dist > qh TRACEdist
00186 || neighbor == qh tracefacet || vertex == qh tracevertex)
00187 fprintf (qh ferr, "qh_check_maxout: p%d (v%d) is %.2g from f%d\n",
00188 qh_pointid (vertex->point), vertex->id, dist, neighbor->id);
00189 }
00190 }
00191 if (qh MERGING) {
00192 wmin_(Wminvertex, qh min_vertex);
00193 }
00194 qh min_vertex= minvertex;
00195 qh_settempfree (&vertices);
00196 }
00197 facets= qh_pointfacet ();
00198 FOREACHfacet_i_(facets) {
00199 if (facet) {
00200 point= qh_point(facet_i);
00201 if (point == qh GOODpointp)
00202 continue;
00203 zinc_(Ztotcheck);
00204 bestfacet= qh_findbest (point, facet, qh_ALL, False, !qh_NOupper,
00205 &dist, NULL, &numpart);
00206 zadd_(Zcheckpart, numpart);
00207 if (bestfacet && dist > maxoutside) {
00208 if (qh ONLYgood && !bestfacet->good
00209 && !((bestfacet= qh_findgooddist (point, bestfacet, &dist, &facetlist))
00210 && dist > maxoutside))
00211 notgood++;
00212 else
00213 maxoutside= dist;
00214 }
00215 if (dist > qh TRACEdist || (bestfacet && bestfacet == qh tracefacet))
00216 fprintf (qh ferr, "qh_check_maxout: p%d is %.2g above f%d\n",
00217 qh_pointid (point), dist, bestfacet->id);
00218 }
00219 }
00220 qh_settempfree (&facets);
00221 wval_(Wmaxout)= maxoutside - qh max_outside;
00222 wmax_(Wmaxoutside, qh max_outside);
00223 qh max_outside= maxoutside;
00224 qh_nearcoplanar ();
00225 qh maxoutdone= True;
00226 trace1((qh ferr, "qh_check_maxout: maxoutside %2.2g, min_vertex %2.2g, outside of not good %d\n",
00227 maxoutside, qh min_vertex, notgood));
00228 }
00229 #else
00230 void qh_check_maxout (void) {
00231 }
00232 #endif
00233
00234
00235
00236
00237
00238
00239
00240 void qh_check_output (void) {
00241 int i;
00242
00243 if (qh STOPcone)
00244 return;
00245 if (qh VERIFYoutput | qh IStracing | qh CHECKfrequently) {
00246 qh_checkpolygon (qh facet_list);
00247 qh_checkflipped_all (qh facet_list);
00248 qh_checkconvex (qh facet_list, qh_ALGORITHMfault);
00249 }else if (!qh MERGING && qh_newstats (qhstat precision, &i)) {
00250 qh_checkflipped_all (qh facet_list);
00251 qh_checkconvex (qh facet_list, qh_ALGORITHMfault);
00252 }
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 void qh_check_point (pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2) {
00264 realT dist;
00265
00266
00267 qh_distplane(point, facet, &dist);
00268 if (dist > *maxoutside) {
00269 *errfacet2= *errfacet1;
00270 *errfacet1= facet;
00271 fprintf(qh ferr, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
00272 qh_pointid(point), facet->id, dist, *maxoutside);
00273 }
00274 maximize_(*maxdist, dist);
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 void qh_check_points (void) {
00301 facetT *facet, *errfacet1= NULL, *errfacet2= NULL;
00302 realT total, maxoutside, maxdist= -REALmax;
00303 pointT *point, **pointp, *pointtemp;
00304 boolT testouter;
00305
00306 maxoutside= qh_maxouter();
00307 maxoutside += qh DISTround;
00308
00309 trace1((qh ferr, "qh_check_points: check all points below %2.2g of all facet planes\n",
00310 maxoutside));
00311 if (qh num_good)
00312 total= (float) qh num_good * qh num_points;
00313 else
00314 total= (float) qh num_facets * qh num_points;
00315 if (total >= qh_VERIFYdirect && !qh maxoutdone) {
00316 if (!qh_QUICKhelp && qh SKIPcheckmax && qh MERGING)
00317 fprintf (qh ferr, "\n\
00318 qhull input warning: merging without checking outer planes ('Q5').\n\
00319 Verify may report that a point is outside of a facet.\n");
00320 qh_check_bestdist();
00321 }else {
00322 if (qh_MAXoutside && qh maxoutdone)
00323 testouter= True;
00324 else
00325 testouter= False;
00326 if (!qh_QUICKhelp) {
00327 if (qh MERGEexact || qh SKIPcheckmax || qh NOnearinside)
00328 fprintf (qh ferr, "\n\
00329 qhull input warning: exact merge ('Qx'), no outer plane check ('Q5'), or\n\
00330 no processing of near-inside points ('Q8'). Verify may report that a point\n\
00331 is outside of a facet.\n");
00332 }
00333 if (qh PRINTprecision) {
00334 if (testouter)
00335 fprintf (qh ferr, "\n\
00336 Output completed. Verifying that all points are below outer planes of\n\
00337 all %sfacets. Will make %2.0f distance computations.\n",
00338 (qh ONLYgood ? "good " : ""), total);
00339 else
00340 fprintf (qh ferr, "\n\
00341 Output completed. Verifying that all points are below %2.2g of\n\
00342 all %sfacets. Will make %2.0f distance computations.\n",
00343 maxoutside, (qh ONLYgood ? "good " : ""), total);
00344 }
00345 FORALLfacets {
00346 if (!facet->good && qh ONLYgood)
00347 continue;
00348 if (facet->flipped)
00349 continue;
00350 if (testouter) {
00351 #if qh_MAXoutside
00352 maxoutside= facet->maxoutside + 2* qh DISTround;
00353
00354 #endif
00355 }
00356 FORALLpoints {
00357 if (point != qh GOODpointp)
00358 qh_check_point (point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
00359 }
00360 FOREACHpoint_(qh other_points) {
00361 if (point != qh GOODpointp)
00362 qh_check_point (point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
00363 }
00364 }
00365 if (maxdist > qh outside_err) {
00366 fprintf( qh ferr, "qhull precision error (qh_check_points): a coplanar point is %6.2g from convex hull. The maximum value (qh.outside_err) is %6.2g\n",
00367 maxdist, qh outside_err );
00368 qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
00369 }else if (errfacet1 && qh outside_err > REALmax/2)
00370 qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
00371 else if (errfacet1)
00372 ;
00373 trace0((qh ferr, "qh_check_points: max distance outside %2.2g\n", maxdist));
00374 }
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 void qh_checkconvex(facetT *facetlist, int fault) {
00407 facetT *facet, *neighbor, **neighborp, *errfacet1=NULL, *errfacet2=NULL;
00408 vertexT *vertex;
00409 realT dist;
00410 pointT *centrum;
00411 boolT waserror= False, tempcentrum= False, allsimplicial;
00412 int neighbor_i;
00413
00414 trace1((qh ferr, "qh_checkconvex: check all ridges are convex\n"));
00415 if (!qh RERUN) {
00416 zzval_(Zconcaveridges)= 0;
00417 zzval_(Zcoplanarridges)= 0;
00418 }
00419 FORALLfacet_(facetlist) {
00420 if (facet->flipped) {
00421 qh_precision ("flipped facet");
00422 fprintf (qh ferr, "qhull precision error: f%d is flipped (interior point is outside)\n",
00423 facet->id);
00424 errfacet1= facet;
00425 waserror= True;
00426 continue;
00427 }
00428 if (qh MERGING && (!qh ZEROcentrum || !facet->simplicial))
00429 allsimplicial= False;
00430 else {
00431 allsimplicial= True;
00432 neighbor_i= 0;
00433 FOREACHneighbor_(facet) {
00434 vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
00435 if (!neighbor->simplicial) {
00436 allsimplicial= False;
00437 continue;
00438 }
00439 qh_distplane (vertex->point, neighbor, &dist);
00440 if (dist > -qh DISTround) {
00441 if (fault == qh_DATAfault) {
00442 qh_precision ("coplanar or concave ridge");
00443 fprintf (qh ferr, "qhull precision error: initial simplex is not convex. Distance=%.2g\n", dist);
00444 qh_errexit(qh_ERRsingular, NULL, NULL);
00445 }
00446 if (dist > qh DISTround) {
00447 zzinc_(Zconcaveridges);
00448 qh_precision ("concave ridge");
00449 fprintf (qh ferr, "qhull precision error: f%d is concave to f%d, since p%d (v%d) is %6.4g above\n",
00450 facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
00451 errfacet1= facet;
00452 errfacet2= neighbor;
00453 waserror= True;
00454 }else if (qh ZEROcentrum) {
00455 if (dist > 0) {
00456 zzinc_(Zcoplanarridges);
00457 qh_precision ("coplanar ridge");
00458 fprintf (qh ferr, "qhull precision error: f%d is clearly not convex to f%d, since p%d (v%d) is %6.4g above\n",
00459 facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
00460 errfacet1= facet;
00461 errfacet2= neighbor;
00462 waserror= True;
00463 }
00464 }else {
00465 zzinc_(Zcoplanarridges);
00466 qh_precision ("coplanar ridge");
00467 trace0((qh ferr, "qhull precision error: f%d may be coplanar to f%d, since p%d (v%d) is within %6.4g during p%d\n",
00468 facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist, qh furthest_id));
00469 }
00470 }
00471 }
00472 }
00473 if (!allsimplicial) {
00474 if (qh CENTERtype == qh_AScentrum) {
00475 if (!facet->center)
00476 facet->center= qh_getcentrum (facet);
00477 centrum= facet->center;
00478 }else {
00479 centrum= qh_getcentrum(facet);
00480 tempcentrum= True;
00481 }
00482 FOREACHneighbor_(facet) {
00483 if (qh ZEROcentrum && facet->simplicial && neighbor->simplicial)
00484 continue;
00485 zzinc_(Zdistconvex);
00486 qh_distplane (centrum, neighbor, &dist);
00487 if (dist > qh DISTround) {
00488 zzinc_(Zconcaveridges);
00489 qh_precision ("concave ridge");
00490 fprintf (qh ferr, "qhull precision error: f%d is concave to f%d. Centrum of f%d is %6.4g above f%d\n",
00491 facet->id, neighbor->id, facet->id, dist, neighbor->id);
00492 errfacet1= facet;
00493 errfacet2= neighbor;
00494 waserror= True;
00495 }else if (dist >= 0.0) {
00496
00497 zzinc_(Zcoplanarridges);
00498 qh_precision ("coplanar ridge");
00499 fprintf (qh ferr, "qhull precision error: f%d is coplanar or concave to f%d. Centrum of f%d is %6.4g above f%d\n",
00500 facet->id, neighbor->id, facet->id, dist, neighbor->id);
00501 errfacet1= facet;
00502 errfacet2= neighbor;
00503 waserror= True;
00504 }
00505 }
00506 if (tempcentrum)
00507 qh_memfree(centrum, qh normal_size);
00508 }
00509 }
00510 if (waserror && !qh FORCEoutput)
00511 qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp) {
00553 facetT *neighbor, **neighborp, *errother=NULL;
00554 ridgeT *ridge, **ridgep, *errridge= NULL, *ridge2;
00555 vertexT *vertex, **vertexp;
00556 unsigned previousid= INT_MAX;
00557 int numneighbors, numvertices, numridges=0, numRvertices=0;
00558 boolT waserror= False;
00559 int skipA, skipB, ridge_i, ridge_n, i;
00560 setT *intersection;
00561
00562 if (facet->visible) {
00563 fprintf (qh ferr, "qhull internal error (qh_checkfacet): facet f%d is on the visible_list\n",
00564 facet->id);
00565 qh_errexit (qh_ERRqhull, facet, NULL);
00566 }
00567 if (!facet->normal) {
00568 fprintf (qh ferr, "qhull internal error (qh_checkfacet): facet f%d does not have a normal\n",
00569 facet->id);
00570 waserror= True;
00571 }
00572 qh_setcheck (facet->vertices, "vertices for f", facet->id);
00573 qh_setcheck (facet->ridges, "ridges for f", facet->id);
00574 qh_setcheck (facet->outsideset, "outsideset for f", facet->id);
00575 qh_setcheck (facet->coplanarset, "coplanarset for f", facet->id);
00576 qh_setcheck (facet->neighbors, "neighbors for f", facet->id);
00577 FOREACHvertex_(facet->vertices) {
00578 if (vertex->deleted) {
00579 fprintf(qh ferr, "qhull internal error (qh_checkfacet): deleted vertex v%d in f%d\n", vertex->id, facet->id);
00580 qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex);
00581 waserror= True;
00582 }
00583 if (vertex->id >= previousid) {
00584 fprintf(qh ferr, "qhull internal error (qh_checkfacet): vertices of f%d are not in descending id order at v%d\n", facet->id, vertex->id);
00585 waserror= True;
00586 break;
00587 }
00588 previousid= vertex->id;
00589 }
00590 numneighbors= qh_setsize(facet->neighbors);
00591 numvertices= qh_setsize(facet->vertices);
00592 numridges= qh_setsize(facet->ridges);
00593 if (facet->simplicial) {
00594 if (numvertices+numneighbors != 2*qh hull_dim
00595 && !facet->degenerate && !facet->redundant) {
00596 fprintf(qh ferr, "qhull internal error (qh_checkfacet): for simplicial facet f%d, #vertices %d + #neighbors %d != 2*qh hull_dim\n",
00597 facet->id, numvertices, numneighbors);
00598 qh_setprint (qh ferr, "", facet->neighbors);
00599 waserror= True;
00600 }
00601 }else {
00602 if (!newmerge
00603 &&(numvertices < qh hull_dim || numneighbors < qh hull_dim)
00604 && !facet->degenerate && !facet->redundant) {
00605 fprintf(qh ferr, "qhull internal error (qh_checkfacet): for facet f%d, #vertices %d or #neighbors %d < qh hull_dim\n",
00606 facet->id, numvertices, numneighbors);
00607 waserror= True;
00608 }
00609 if (numridges < numneighbors
00610 ||(qh hull_dim == 3 && numvertices != numridges && !qh NEWfacets)
00611 ||(qh hull_dim == 2 && numridges + numvertices + numneighbors != 6)) {
00612 if (!facet->degenerate && !facet->redundant) {
00613 fprintf(qh ferr, "qhull internal error (qh_checkfacet): for facet f%d, #ridges %d < #neighbors %d or (3-d) != #vertices %d or (2-d) not all 2\n",
00614 facet->id, numridges, numneighbors, numvertices);
00615 waserror= True;
00616 }
00617 }
00618 }
00619 FOREACHneighbor_(facet) {
00620 if (neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) {
00621 fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d still has a MERGE or DUP neighbor\n", facet->id);
00622 qh_errexit (qh_ERRqhull, facet, NULL);
00623 }
00624 neighbor->seen= True;
00625 }
00626 FOREACHneighbor_(facet) {
00627 if (!qh_setin(neighbor->neighbors, facet)) {
00628 fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d has neighbor f%d, but f%d does not have neighbor f%d\n",
00629 facet->id, neighbor->id, neighbor->id, facet->id);
00630 errother= neighbor;
00631 waserror= True;
00632 }
00633 if (!neighbor->seen) {
00634 fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d has a duplicate neighbor f%d\n",
00635 facet->id, neighbor->id);
00636 errother= neighbor;
00637 waserror= True;
00638 }
00639 neighbor->seen= False;
00640 }
00641 FOREACHridge_(facet->ridges) {
00642 qh_setcheck (ridge->vertices, "vertices for r", ridge->id);
00643 ridge->seen= False;
00644 }
00645 FOREACHridge_(facet->ridges) {
00646 if (ridge->seen) {
00647 fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d has a duplicate ridge r%d\n",
00648 facet->id, ridge->id);
00649 errridge= ridge;
00650 waserror= True;
00651 }
00652 ridge->seen= True;
00653 numRvertices= qh_setsize(ridge->vertices);
00654 if (numRvertices != qh hull_dim - 1) {
00655 fprintf(qh ferr, "qhull internal error (qh_checkfacet): ridge between f%d and f%d has %d vertices\n",
00656 ridge->top->id, ridge->bottom->id, numRvertices);
00657 errridge= ridge;
00658 waserror= True;
00659 }
00660 neighbor= otherfacet_(ridge, facet);
00661 neighbor->seen= True;
00662 if (!qh_setin(facet->neighbors, neighbor)) {
00663 fprintf(qh ferr, "qhull internal error (qh_checkfacet): for facet f%d, neighbor f%d of ridge r%d not in facet\n",
00664 facet->id, neighbor->id, ridge->id);
00665 errridge= ridge;
00666 waserror= True;
00667 }
00668 }
00669 if (!facet->simplicial) {
00670 FOREACHneighbor_(facet) {
00671 if (!neighbor->seen) {
00672 fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d does not have a ridge for neighbor f%d\n",
00673 facet->id, neighbor->id);
00674 errother= neighbor;
00675 waserror= True;
00676 }
00677 intersection= qh_vertexintersect_new(facet->vertices, neighbor->vertices);
00678 qh_settemppush (intersection);
00679 FOREACHvertex_(facet->vertices) {
00680 vertex->seen= False;
00681 vertex->seen2= False;
00682 }
00683 FOREACHvertex_(intersection)
00684 vertex->seen= True;
00685 FOREACHridge_(facet->ridges) {
00686 if (neighbor != otherfacet_(ridge, facet))
00687 continue;
00688 FOREACHvertex_(ridge->vertices) {
00689 if (!vertex->seen) {
00690 fprintf (qh ferr, "qhull internal error (qh_checkfacet): vertex v%d in r%d not in f%d intersect f%d\n",
00691 vertex->id, ridge->id, facet->id, neighbor->id);
00692 qh_errexit (qh_ERRqhull, facet, ridge);
00693 }
00694 vertex->seen2= True;
00695 }
00696 }
00697 if (!newmerge) {
00698 FOREACHvertex_(intersection) {
00699 if (!vertex->seen2) {
00700 if (qh IStracing >=3 || !qh MERGING) {
00701 fprintf (qh ferr, "qhull precision error (qh_checkfacet): vertex v%d in f%d intersect f%d but\n\
00702 not in a ridge. This is ok under merging. Last point was p%d\n",
00703 vertex->id, facet->id, neighbor->id, qh furthest_id);
00704 if (!qh FORCEoutput && !qh MERGING) {
00705 qh_errprint ("ERRONEOUS", facet, neighbor, NULL, vertex);
00706 if (!qh MERGING)
00707 qh_errexit (qh_ERRqhull, NULL, NULL);
00708 }
00709 }
00710 }
00711 }
00712 }
00713 qh_settempfree (&intersection);
00714 }
00715 }else {
00716 FOREACHneighbor_(facet) {
00717 if (neighbor->simplicial) {
00718 skipA= SETindex_(facet->neighbors, neighbor);
00719 skipB= qh_setindex (neighbor->neighbors, facet);
00720 if (!qh_setequal_skip (facet->vertices, skipA, neighbor->vertices, skipB)) {
00721 fprintf (qh ferr, "qhull internal error (qh_checkfacet): facet f%d skip %d and neighbor f%d skip %d do not match \n",
00722 facet->id, skipA, neighbor->id, skipB);
00723 errother= neighbor;
00724 waserror= True;
00725 }
00726 }
00727 }
00728 }
00729 if (qh hull_dim < 5 && (qh IStracing > 2 || qh CHECKfrequently)) {
00730 FOREACHridge_i_(facet->ridges) {
00731 for (i= ridge_i+1; i < ridge_n; i++) {
00732 ridge2= SETelemt_(facet->ridges, i, ridgeT);
00733 if (qh_setequal (ridge->vertices, ridge2->vertices)) {
00734 fprintf (qh ferr, "qh_checkfacet: ridges r%d and r%d have the same vertices\n",
00735 ridge->id, ridge2->id);
00736 errridge= ridge;
00737 waserror= True;
00738 }
00739 }
00740 }
00741 }
00742 if (waserror) {
00743 qh_errprint("ERRONEOUS", facet, errother, errridge, NULL);
00744 *waserrorp= True;
00745 }
00746 }
00747
00748
00749
00750
00751
00752
00753
00754
00755 void qh_checkflipped_all (facetT *facetlist) {
00756 facetT *facet;
00757 boolT waserror= False;
00758 realT dist;
00759
00760 if (facetlist == qh facet_list)
00761 zzval_(Zflippedfacets)= 0;
00762 FORALLfacet_(facetlist) {
00763 if (facet->normal && !qh_checkflipped (facet, &dist, !qh_ALL)) {
00764 fprintf(qh ferr, "qhull precision error: facet f%d is flipped, distance= %6.12g\n",
00765 facet->id, dist);
00766 if (!qh FORCEoutput) {
00767 qh_errprint("ERRONEOUS", facet, NULL, NULL, NULL);
00768 waserror= True;
00769 }
00770 }
00771 }
00772 if (waserror) {
00773 fprintf (qh ferr, "\n\
00774 A flipped facet occurs when its distance to the interior point is\n\
00775 greater than %2.2g, the maximum roundoff error.\n", -qh DISTround);
00776 qh_errexit(qh_ERRprec, NULL, NULL);
00777 }
00778 }
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802 void qh_checkpolygon(facetT *facetlist) {
00803 facetT *facet;
00804 vertexT *vertex, **vertexp, *vertexlist;
00805 int numfacets= 0, numvertices= 0, numridges= 0;
00806 int totvneighbors= 0, totvertices= 0;
00807 boolT waserror= False, nextseen= False, visibleseen= False;
00808
00809 trace1((qh ferr, "qh_checkpolygon: check all facets from f%d\n", facetlist->id));
00810 if (facetlist != qh facet_list || qh ONLYgood)
00811 nextseen= True;
00812 FORALLfacet_(facetlist) {
00813 if (facet == qh visible_list)
00814 visibleseen= True;
00815 if (!facet->visible) {
00816 if (!nextseen) {
00817 if (facet == qh facet_next)
00818 nextseen= True;
00819 else if (qh_setsize (facet->outsideset)
00820 && !(qh NARROWhull && qh CHECKfrequently)) {
00821 fprintf (qh ferr, "qhull internal error (qh_checkpolygon): f%d has outside set before qh facet_next\n",
00822 facet->id);
00823 qh_errexit (qh_ERRqhull, facet, NULL);
00824 }
00825 }
00826 numfacets++;
00827 qh_checkfacet(facet, False, &waserror);
00828 }
00829 }
00830 if (qh visible_list && !visibleseen && facetlist == qh facet_list) {
00831 fprintf (qh ferr, "qhull internal error (qh_checkpolygon): visible list f%d no longer on facet list\n", qh visible_list->id);
00832 qh_printlists();
00833 qh_errexit (qh_ERRqhull, qh visible_list, NULL);
00834 }
00835 if (facetlist == qh facet_list)
00836 vertexlist= qh vertex_list;
00837 else if (facetlist == qh newfacet_list)
00838 vertexlist= qh newvertex_list;
00839 else
00840 vertexlist= NULL;
00841 FORALLvertex_(vertexlist) {
00842 vertex->seen= False;
00843 vertex->visitid= 0;
00844 }
00845 FORALLfacet_(facetlist) {
00846 if (facet->visible)
00847 continue;
00848 if (facet->simplicial)
00849 numridges += qh hull_dim;
00850 else
00851 numridges += qh_setsize (facet->ridges);
00852 FOREACHvertex_(facet->vertices) {
00853 vertex->visitid++;
00854 if (!vertex->seen) {
00855 vertex->seen= True;
00856 numvertices++;
00857 if (qh_pointid (vertex->point) == -1) {
00858 fprintf (qh ferr, "qhull internal error (qh_checkpolygon): unknown point %p for vertex v%d first_point %p\n",
00859 vertex->point, vertex->id, qh first_point);
00860 waserror= True;
00861 }
00862 }
00863 }
00864 }
00865 qh vertex_visit += numfacets;
00866 if (facetlist == qh facet_list) {
00867 if (numfacets != qh num_facets - qh num_visible) {
00868 fprintf(qh ferr, "qhull internal error (qh_checkpolygon): actual number of facets is %d, cumulative facet count is %d\n",
00869 numfacets, qh num_facets- qh num_visible);
00870 waserror= True;
00871 }
00872 qh vertex_visit++;
00873 if (qh VERTEXneighbors) {
00874 FORALLvertices {
00875 qh_setcheck (vertex->neighbors, "neighbors for v", vertex->id);
00876 if (vertex->deleted)
00877 continue;
00878 totvneighbors += qh_setsize (vertex->neighbors);
00879 }
00880 FORALLfacet_(facetlist)
00881 totvertices += qh_setsize (facet->vertices);
00882 if (totvneighbors != totvertices) {
00883 fprintf(qh ferr, "qhull internal error (qh_checkpolygon): vertex neighbors inconsistent. Totvneighbors %d, totvertices %d\n",
00884 totvneighbors, totvertices);
00885 waserror= True;
00886 }
00887 }
00888 if (numvertices != qh num_vertices - qh_setsize(qh del_vertices)) {
00889 fprintf(qh ferr, "qhull internal error (qh_checkpolygon): actual number of vertices is %d, cumulative vertex count is %d\n",
00890 numvertices, qh num_vertices - qh_setsize(qh del_vertices));
00891 waserror= True;
00892 }
00893 if (qh hull_dim == 2 && numvertices != numfacets) {
00894 fprintf (qh ferr, "qhull internal error (qh_checkpolygon): #vertices %d != #facets %d\n",
00895 numvertices, numfacets);
00896 waserror= True;
00897 }
00898 if (qh hull_dim == 3 && numvertices + numfacets - numridges/2 != 2) {
00899 fprintf (qh ferr, "qhull internal error (qh_checkpolygon): #vertices %d + #facets %d - #edges %d != 2\n",
00900 numvertices, numfacets, numridges/2);
00901 waserror= True;
00902 }
00903 }
00904 if (waserror)
00905 qh_errexit(qh_ERRqhull, NULL, NULL);
00906 }
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919 void qh_checkvertex (vertexT *vertex) {
00920 boolT waserror= False;
00921 facetT *neighbor, **neighborp, *errfacet=NULL;
00922
00923 if (qh_pointid (vertex->point) == -1) {
00924 fprintf (qh ferr, "qhull internal error (qh_checkvertex): unknown point id %p\n", vertex->point);
00925 waserror= True;
00926 }
00927 if (vertex->id >= qh vertex_id) {
00928 fprintf (qh ferr, "qhull internal error (qh_checkvertex): unknown vertex id %d\n", vertex->id);
00929 waserror= True;
00930 }
00931 if (!waserror && !vertex->deleted) {
00932 if (qh_setsize (vertex->neighbors)) {
00933 FOREACHneighbor_(vertex) {
00934 if (!qh_setin (neighbor->vertices, vertex)) {
00935 fprintf (qh ferr, "qhull internal error (qh_checkvertex): neighbor f%d does not contain v%d\n", neighbor->id, vertex->id);
00936 errfacet= neighbor;
00937 waserror= True;
00938 }
00939 }
00940 }
00941 }
00942 if (waserror) {
00943 qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex);
00944 qh_errexit (qh_ERRqhull, errfacet, NULL);
00945 }
00946 }
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958 void qh_clearcenters (qh_CENTER type) {
00959 facetT *facet;
00960
00961 if (qh CENTERtype != type) {
00962 FORALLfacets {
00963 if (qh CENTERtype == qh_ASvoronoi){
00964 if (facet->center) {
00965 qh_memfree (facet->center, qh center_size);
00966 facet->center= NULL;
00967 }
00968 }else {
00969 if (facet->center) {
00970 qh_memfree (facet->center, qh normal_size);
00971 facet->center= NULL;
00972 }
00973 }
00974 }
00975 qh CENTERtype= type;
00976 }
00977 trace2((qh ferr, "qh_clearcenters: switched to center type %d\n", type));
00978 }
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998 void qh_createsimplex(setT *vertices) {
00999 facetT *facet= NULL, *newfacet;
01000 boolT toporient= True;
01001 int vertex_i, vertex_n, nth;
01002 setT *newfacets= qh_settemp (qh hull_dim+1);
01003 vertexT *vertex;
01004
01005 qh facet_list= qh newfacet_list= qh facet_tail= qh_newfacet();
01006 qh num_facets= qh num_vertices= 0;
01007 qh vertex_list= qh newvertex_list= qh vertex_tail= qh_newvertex(NULL);
01008 FOREACHvertex_i_(vertices) {
01009 newfacet= qh_newfacet();
01010 newfacet->vertices= qh_setnew_delnthsorted (vertices, vertex_n,
01011 vertex_i, 0);
01012 newfacet->toporient= toporient;
01013 qh_appendfacet(newfacet);
01014 newfacet->newfacet= True;
01015 qh_appendvertex (vertex);
01016 qh_setappend (&newfacets, newfacet);
01017 toporient ^= True;
01018 }
01019 FORALLnew_facets {
01020 nth= 0;
01021 FORALLfacet_(qh newfacet_list) {
01022 if (facet != newfacet)
01023 SETelem_(newfacet->neighbors, nth++)= facet;
01024 }
01025 qh_settruncate (newfacet->neighbors, qh hull_dim);
01026 }
01027 qh_settempfree (&newfacets);
01028 trace1((qh ferr, "qh_createsimplex: created simplex\n"));
01029 }
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042 void qh_delridge(ridgeT *ridge) {
01043 void **freelistp;
01044
01045 qh_setdel(ridge->top->ridges, ridge);
01046 qh_setdel(ridge->bottom->ridges, ridge);
01047 qh_setfree(&(ridge->vertices));
01048 qh_memfree_(ridge, sizeof(ridgeT), freelistp);
01049 }
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 void qh_delvertex (vertexT *vertex) {
01063
01064 if (vertex == qh tracevertex)
01065 qh tracevertex= NULL;
01066 qh_removevertex (vertex);
01067 qh_setfree (&vertex->neighbors);
01068 qh_memfree(vertex, sizeof(vertexT));
01069 }
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085 setT *qh_facet3vertex (facetT *facet) {
01086 ridgeT *ridge, *firstridge;
01087 vertexT *vertex;
01088 int cntvertices, cntprojected=0;
01089 setT *vertices;
01090
01091 cntvertices= qh_setsize(facet->vertices);
01092 vertices= qh_settemp (cntvertices);
01093 if (facet->simplicial) {
01094 if (cntvertices != 3) {
01095 fprintf (qh ferr, "qhull internal error (qh_facet3vertex): only %d vertices for simplicial facet f%d\n",
01096 cntvertices, facet->id);
01097 qh_errexit(qh_ERRqhull, facet, NULL);
01098 }
01099 qh_setappend (&vertices, SETfirst_(facet->vertices));
01100 if (facet->toporient ^ qh_ORIENTclock)
01101 qh_setappend (&vertices, SETsecond_(facet->vertices));
01102 else
01103 qh_setaddnth (&vertices, 0, SETsecond_(facet->vertices));
01104 qh_setappend (&vertices, SETelem_(facet->vertices, 2));
01105 }else {
01106 ridge= firstridge= SETfirstt_(facet->ridges, ridgeT);
01107 while ((ridge= qh_nextridge3d (ridge, facet, &vertex))) {
01108 qh_setappend (&vertices, vertex);
01109 if (++cntprojected > cntvertices || ridge == firstridge)
01110 break;
01111 }
01112 if (!ridge || cntprojected != cntvertices) {
01113 fprintf (qh ferr, "qhull internal error (qh_facet3vertex): ridges for facet %d don't match up. got at least %d\n",
01114 facet->id, cntprojected);
01115 qh_errexit(qh_ERRqhull, facet, ridge);
01116 }
01117 }
01118 return vertices;
01119 }
01120
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
01147
01148
01149
01150 facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
01151 realT *bestdist, boolT *isoutside) {
01152 facetT *bestfacet= NULL;
01153 int numpart, totpart= 0;
01154
01155 bestfacet= qh_findbest (point, qh facet_list,
01156 bestoutside, False, bestoutside,
01157 bestdist, isoutside, &totpart);
01158 if (!bestfacet) {
01159 fprintf (qh ferr, "qh_findbestfacet: all facets are flipped or upper Delaunay\n");
01160 qh_errexit (qh_ERRqhull, NULL, NULL);
01161 }
01162 if (*bestdist < -qh DISTround) {
01163 bestfacet= qh_findfacet_all (point, bestdist, isoutside, &numpart);
01164 totpart += numpart;
01165 if ((isoutside && bestoutside)
01166 || (!isoutside && bestfacet->upperdelaunay)) {
01167 bestfacet= qh_findbest (point, bestfacet,
01168 bestoutside, False, bestoutside,
01169 bestdist, isoutside, &totpart);
01170 totpart += numpart;
01171 }
01172 }
01173 trace3((qh ferr, "qh_findbestfacet: f%d dist %2.2g isoutside %d totpart %d\n",
01174 bestfacet->id, *bestdist, *isoutside, totpart));
01175 return bestfacet;
01176 }
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196 facetT *qh_findfacet_all (pointT *point, realT *bestdist, boolT *isoutside,
01197 int *numpart) {
01198 facetT *bestfacet= NULL, *facet;
01199 realT dist;
01200 int totpart= 0;
01201
01202 *bestdist= REALmin;
01203 *isoutside= False;
01204 FORALLfacets {
01205 if (facet->flipped || !facet->normal)
01206 continue;
01207 totpart++;
01208 qh_distplane (point, facet, &dist);
01209 if (dist > *bestdist) {
01210 *bestdist= dist;
01211 bestfacet= facet;
01212 if (dist > qh MINoutside) {
01213 *isoutside= True;
01214 break;
01215 }
01216 }
01217 }
01218 *numpart= totpart;
01219 trace3((qh ferr, "qh_findfacet_all: f%d dist %2.2g isoutside %d totpart %d\n",
01220 getid_(bestfacet), *bestdist, *isoutside, totpart));
01221 return bestfacet;
01222 }
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256 int qh_findgood (facetT *facetlist, int goodhorizon) {
01257 facetT *facet, *bestfacet= NULL;
01258 realT angle, bestangle= REALmax, dist;
01259 int numgood=0;
01260
01261 FORALLfacet_(facetlist) {
01262 if (facet->good)
01263 numgood++;
01264 }
01265 if (qh GOODvertex>0 && !qh MERGING) {
01266 FORALLfacet_(facetlist) {
01267 if (!qh_isvertex (qh GOODvertexp, facet->vertices)) {
01268 facet->good= False;
01269 numgood--;
01270 }
01271 }
01272 }
01273 if (qh GOODpoint && numgood) {
01274 FORALLfacet_(facetlist) {
01275 if (facet->good && facet->normal) {
01276 zinc_(Zdistgood);
01277 qh_distplane (qh GOODpointp, facet, &dist);
01278 if ((qh GOODpoint > 0) ^ (dist > 0.0)) {
01279 facet->good= False;
01280 numgood--;
01281 }
01282 }
01283 }
01284 }
01285 if (qh GOODthreshold && (numgood || goodhorizon || qh GOODclosest)) {
01286 FORALLfacet_(facetlist) {
01287 if (facet->good && facet->normal) {
01288 if (!qh_inthresholds (facet->normal, &angle)) {
01289 facet->good= False;
01290 numgood--;
01291 if (angle < bestangle) {
01292 bestangle= angle;
01293 bestfacet= facet;
01294 }
01295 }
01296 }
01297 }
01298 if (!numgood && (!goodhorizon || qh GOODclosest)) {
01299 if (qh GOODclosest) {
01300 if (qh GOODclosest->visible)
01301 qh GOODclosest= NULL;
01302 else {
01303 qh_inthresholds (qh GOODclosest->normal, &angle);
01304 if (angle < bestangle)
01305 bestfacet= qh GOODclosest;
01306 }
01307 }
01308 if (bestfacet && bestfacet != qh GOODclosest) {
01309 if (qh GOODclosest)
01310 qh GOODclosest->good= False;
01311 qh GOODclosest= bestfacet;
01312 bestfacet->good= True;
01313 numgood++;
01314 trace2((qh ferr, "qh_findgood: f%d is closest (%2.2g) to thresholds\n",
01315 bestfacet->id, bestangle));
01316 return numgood;
01317 }
01318 }else if (qh GOODclosest) {
01319 qh GOODclosest->good= False;
01320 qh GOODclosest= NULL;
01321 }
01322 }
01323 zadd_(Zgoodfacet, numgood);
01324 trace2((qh ferr, "qh_findgood: found %d good facets with %d good horizon\n",
01325 numgood, goodhorizon));
01326 if (!numgood && qh GOODvertex>0 && !qh MERGING)
01327 return goodhorizon;
01328 return numgood;
01329 }
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356 void qh_findgood_all (facetT *facetlist) {
01357 facetT *facet, *bestfacet=NULL;
01358 realT angle, bestangle= REALmax;
01359 int numgood=0, startgood;
01360
01361 if (!qh GOODvertex && !qh GOODthreshold && !qh GOODpoint
01362 && !qh SPLITthresholds)
01363 return;
01364 if (!qh ONLYgood)
01365 qh_findgood (qh facet_list, 0);
01366 FORALLfacet_(facetlist) {
01367 if (facet->good)
01368 numgood++;
01369 }
01370 if (qh GOODvertex <0 || (qh GOODvertex > 0 && qh MERGING)) {
01371 FORALLfacet_(facetlist) {
01372 if (facet->good && ((qh GOODvertex > 0) ^ !!qh_isvertex (qh GOODvertexp, facet->vertices))) {
01373 if (!--numgood) {
01374 fprintf (qh ferr, "qhull warning: good vertex p%d does not match last good facet f%d. Ignored.\n",
01375 qh_pointid(qh GOODvertexp), facet->id);
01376 return;
01377 }
01378 facet->good= False;
01379 }
01380 }
01381 }
01382 startgood= numgood;
01383 if (qh SPLITthresholds) {
01384 FORALLfacet_(facetlist) {
01385 if (facet->good) {
01386 if (!qh_inthresholds (facet->normal, &angle)) {
01387 facet->good= False;
01388 numgood--;
01389 if (angle < bestangle) {
01390 bestangle= angle;
01391 bestfacet= facet;
01392 }
01393 }
01394 }
01395 }
01396 if (!numgood && bestfacet) {
01397 bestfacet->good= True;
01398 numgood++;
01399 trace0((qh ferr, "qh_findgood_all: f%d is closest (%2.2g) to thresholds\n",
01400 bestfacet->id, bestangle));
01401 return;
01402 }
01403 }
01404 qh num_good= numgood;
01405 trace0((qh ferr, "qh_findgood_all: %d good facets remain out of %d facets\n",
01406 numgood, startgood));
01407 }
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419 void qh_furthestnext (void ) {
01420 facetT *facet, *bestfacet= NULL;
01421 realT dist, bestdist= -REALmax;
01422
01423 FORALLfacets {
01424 if (facet->outsideset) {
01425 #if qh_COMPUTEfurthest
01426 pointT *furthest;
01427 furthest= (pointT*)qh_setlast (facet->outsideset);
01428 zinc_(Zcomputefurthest);
01429 qh_distplane (furthest, facet, &dist);
01430 #else
01431 dist= facet->furthestdist;
01432 #endif
01433 if (dist > bestdist) {
01434 bestfacet= facet;
01435 bestdist= dist;
01436 }
01437 }
01438 }
01439 if (bestfacet) {
01440 qh_removefacet (bestfacet);
01441 qh_prependfacet (bestfacet, &qh facet_next);
01442 trace1((qh ferr, "qh_furthestnext: made f%d next facet (dist %.2g)\n",
01443 bestfacet->id, bestdist));
01444 }
01445 }
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462 void qh_furthestout (facetT *facet) {
01463 pointT *point, **pointp, *bestpoint= NULL;
01464 realT dist, bestdist= -REALmax;
01465
01466 FOREACHpoint_(facet->outsideset) {
01467 qh_distplane (point, facet, &dist);
01468 zinc_(Zcomputefurthest);
01469 if (dist > bestdist) {
01470 bestpoint= point;
01471 bestdist= dist;
01472 }
01473 }
01474 if (bestpoint) {
01475 qh_setdel (facet->outsideset, point);
01476 qh_setappend (&facet->outsideset, point);
01477 #if !qh_COMPUTEfurthest
01478 facet->furthestdist= bestdist;
01479 #endif
01480 }
01481 facet->notfurthest= False;
01482 trace3((qh ferr, "qh_furthestout: p%d is furthest outside point of f%d\n",
01483 qh_pointid (point), facet->id));
01484 }
01485
01486
01487
01488
01489
01490
01491
01492
01493 void qh_infiniteloop (facetT *facet) {
01494
01495 fprintf (qh ferr, "qhull internal error (qh_infiniteloop): potential infinite loop detected\n");
01496 qh_errexit (qh_ERRqhull, facet, NULL);
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_initbuild( void) {
01525 setT *maxpoints, *vertices;
01526 facetT *facet;
01527 int numpart;
01528 realT dist;
01529 boolT isoutside;
01530
01531 qh furthest_id= -1;
01532 qh lastreport= 0;
01533 qh facet_id= qh vertex_id= qh ridge_id= 0;
01534 qh visit_id= qh vertex_visit= 0;
01535 qh maxoutdone= False;
01536
01537 if (qh GOODpoint > 0)
01538 qh GOODpointp= qh_point (qh GOODpoint-1);
01539 else if (qh GOODpoint < 0)
01540 qh GOODpointp= qh_point (-qh GOODpoint-1);
01541 if (qh GOODvertex > 0)
01542 qh GOODvertexp= qh_point (qh GOODvertex-1);
01543 else if (qh GOODvertex < 0)
01544 qh GOODvertexp= qh_point (-qh GOODvertex-1);
01545 if ((qh GOODpoint
01546 && (qh GOODpointp < qh first_point
01547 || qh GOODpointp > qh_point (qh num_points-1)))
01548 || (qh GOODvertex
01549 && (qh GOODvertexp < qh first_point
01550 || qh GOODvertexp > qh_point (qh num_points-1)))) {
01551 fprintf (qh ferr, "qhull input error: either QGn or QVn point is > p%d\n",
01552 qh num_points-1);
01553 qh_errexit (qh_ERRinput, NULL, NULL);
01554 }
01555 maxpoints= qh_maxmin(qh first_point, qh num_points, qh hull_dim);
01556 if (qh SCALElast)
01557 qh_scalelast (qh first_point, qh num_points, qh hull_dim,
01558 qh MINlastcoord, qh MAXlastcoord, qh MAXwidth);
01559 qh_detroundoff();
01560 vertices= qh_initialvertices(qh hull_dim, maxpoints, qh first_point, qh num_points);
01561 qh_initialhull (vertices);
01562 qh_partitionall (vertices, qh first_point, qh num_points);
01563 if (qh PRINToptions1st || qh TRACElevel || qh IStracing) {
01564 if (qh TRACElevel || qh IStracing)
01565 fprintf (qh ferr, "\nTrace level %d for %s | %s\n",
01566 qh IStracing ? qh IStracing : qh TRACElevel, qh rbox_command, qh qhull_command);
01567 fprintf (qh ferr, "Options selected for qhull %s:\n%s\n", qh_version, qh qhull_options);
01568 }
01569 qh_resetlists (False );
01570 qh facet_next= qh facet_list;
01571 qh_furthestnext ();
01572 if (qh PREmerge) {
01573 qh cos_max= qh premerge_cos;
01574 qh centrum_radius= qh premerge_centrum;
01575 }
01576 if (qh ONLYgood) {
01577 if (qh GOODvertex > 0 && qh MERGING) {
01578 fprintf (qh ferr, "qhull input error: 'Qg QVn' (only good vertex) does not work with merging.\nUse 'QJ' to joggle the input or 'Q0' to turn off merging.\n");
01579 qh_errexit (qh_ERRinput, NULL, NULL);
01580 }
01581 if (!(qh GOODthreshold || qh GOODpoint
01582 || (!qh MERGEexact && !qh PREmerge && qh GOODvertexp))) {
01583 fprintf (qh ferr, "qhull input error: 'Qg' (ONLYgood) needs a good threshold ('Pd0D0'), a\n\
01584 good point (QGn or QG-n), or a good vertex with 'QJ' or 'Q0' (QVn).\n");
01585 qh_errexit (qh_ERRinput, NULL, NULL);
01586 }
01587 if (qh GOODvertex > 0 && !qh MERGING
01588 && !qh_isvertex (qh GOODvertexp, vertices)) {
01589 facet= qh_findbestnew (qh GOODvertexp, qh facet_list,
01590 &dist, &isoutside, &numpart);
01591 zadd_(Zdistgood, numpart);
01592 if (!isoutside) {
01593 fprintf (qh ferr, "qhull input error: point for QV%d is inside initial simplex. It can not be made a vertex.\n",
01594 qh_pointid(qh GOODvertexp));
01595 qh_errexit (qh_ERRinput, NULL, NULL);
01596 }
01597 if (!qh_addpoint (qh GOODvertexp, facet, False)) {
01598 qh_settempfree(&vertices);
01599 qh_settempfree(&maxpoints);
01600 return;
01601 }
01602 }
01603 qh_findgood (qh facet_list, 0);
01604 }
01605 qh_settempfree(&vertices);
01606 qh_settempfree(&maxpoints);
01607 trace1((qh ferr, "qh_initbuild: initial hull created and points partitioned\n"));
01608 }
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624 void qh_initialhull(setT *vertices) {
01625 facetT *facet, *firstfacet, *neighbor, **neighborp;
01626 realT dist, angle, minangle= REALmax;
01627 #ifndef qh_NOtrace
01628 int k;
01629 #endif
01630
01631 qh_createsimplex(vertices);
01632 qh_resetlists (False);
01633 qh facet_next= qh facet_list;
01634 qh interior_point= qh_getcenter(vertices);
01635 firstfacet= qh facet_list;
01636 qh_setfacetplane(firstfacet);
01637 zinc_(Znumvisibility);
01638 qh_distplane(qh interior_point, firstfacet, &dist);
01639 if (dist > 0) {
01640 FORALLfacets
01641 facet->toporient ^= True;
01642 }
01643 FORALLfacets
01644 qh_setfacetplane(facet);
01645 FORALLfacets {
01646 if (!qh_checkflipped (facet, NULL, qh_ALL)) {
01647 trace1((qh ferr, "qh_initialhull: initial orientation incorrect. Correct all facets\n"));
01648 facet->flipped= False;
01649 FORALLfacets {
01650 facet->toporient ^= True;
01651 qh_orientoutside (facet);
01652 }
01653 break;
01654 }
01655 }
01656 FORALLfacets {
01657 if (!qh_checkflipped (facet, NULL, !qh_ALL)) {
01658 qh_precision ("initial facet is coplanar with interior point");
01659 fprintf (qh ferr, "qhull precision error: initial facet %d is coplanar with the interior point\n",
01660 facet->id);
01661 qh_errexit (qh_ERRsingular, facet, NULL);
01662 }
01663 FOREACHneighbor_(facet) {
01664 angle= qh_getangle (facet->normal, neighbor->normal);
01665 minimize_( minangle, angle);
01666 }
01667 }
01668 if (minangle < qh_MAXnarrow) {
01669 realT diff= 1.0 + minangle;
01670
01671 qh NARROWhull= True;
01672 qh_option ("_narrow-hull", NULL, &diff);
01673 if (minangle < qh_WARNnarrow && !qh RERUN && qh PRINTprecision)
01674 fprintf (qh ferr, "qhull precision warning: \n\
01675 The initial hull is narrow (the cosine of the minimum angle is %.9g).\n\
01676 A coplanar point may lead to a wide facet. Options 'Qs' (search for best\n\
01677 initial hull), 'QbB' (scale to unit box), or 'Qbb' (scale last coordinate)\n\
01678 may remove this warning. Use 'Pp' to ignore this warning.\n\
01679 See 'Limitations' in qh-impre.htm.\n",
01680 minangle);
01681 }
01682 zzval_(Zprocessed)= qh hull_dim+1;
01683 qh_checkpolygon (qh facet_list);
01684 qh_checkconvex(qh facet_list, qh_DATAfault);
01685 #ifndef qh_NOtrace
01686 if (qh IStracing >= 1) {
01687 fprintf(qh ferr, "qh_initialhull: simplex constructed, interior point:");
01688 for (k=0; k < qh hull_dim; k++)
01689 fprintf (qh ferr, " %6.4g", qh interior_point[k]);
01690 fprintf (qh ferr, "\n");
01691 }
01692 #endif
01693 }
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713 setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints) {
01714 pointT *point, **pointp;
01715 setT *vertices, *simplex, *tested;
01716 realT randr;
01717 int index, point_i, point_n, k;
01718 boolT nearzero= False;
01719
01720 vertices= qh_settemp (dim + 1);
01721 simplex= qh_settemp (dim+1);
01722 if (qh ALLpoints)
01723 qh_maxsimplex (dim, NULL, points, numpoints, &simplex);
01724 else if (qh RANDOMoutside) {
01725 while (qh_setsize (simplex) != dim+1) {
01726 randr= qh_RANDOMint;
01727 randr= randr/(qh_RANDOMmax+1);
01728 index= (int)floor(qh num_points * randr);
01729 point= qh_point (index);
01730 qh_setunique (&simplex, point);
01731 }
01732 }else if (qh hull_dim >= qh_INITIALmax) {
01733 tested= qh_settemp (dim+1);
01734 qh_setappend (&simplex, SETfirst_(maxpoints));
01735 qh_setappend (&simplex, SETsecond_(maxpoints));
01736 qh_maxsimplex (fmin_(qh_INITIALsearch, dim), maxpoints, points, numpoints, &simplex);
01737 k= qh_setsize (simplex);
01738 FOREACHpoint_i_(maxpoints) {
01739 if (point_i & 0x1) {
01740 if (!qh_setin (simplex, point) && !qh_setin (tested, point)){
01741 qh_detsimplex(point, simplex, k, &nearzero);
01742 if (nearzero)
01743 qh_setappend (&tested, point);
01744 else {
01745 qh_setappend (&simplex, point);
01746 if (++k == dim)
01747 break;
01748 }
01749 }
01750 }
01751 }
01752 while (k != dim && (point= (pointT*)qh_setdellast (maxpoints))) {
01753 if (!qh_setin (simplex, point) && !qh_setin (tested, point)){
01754 qh_detsimplex (point, simplex, k, &nearzero);
01755 if (nearzero)
01756 qh_setappend (&tested, point);
01757 else {
01758 qh_setappend (&simplex, point);
01759 k++;
01760 }
01761 }
01762 }
01763 index= 0;
01764 while (k != dim && (point= qh_point (index++))) {
01765 if (!qh_setin (simplex, point) && !qh_setin (tested, point)){
01766 qh_detsimplex (point, simplex, k, &nearzero);
01767 if (!nearzero){
01768 qh_setappend (&simplex, point);
01769 k++;
01770 }
01771 }
01772 }
01773 qh_settempfree (&tested);
01774 qh_maxsimplex (dim, maxpoints, points, numpoints, &simplex);
01775 }else
01776 qh_maxsimplex (dim, maxpoints, points, numpoints, &simplex);
01777 FOREACHpoint_(simplex)
01778 qh_setaddnth (&vertices, 0, qh_newvertex(point));
01779 qh_settempfree (&simplex);
01780 return vertices;
01781 }
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793 vertexT *qh_isvertex (pointT *point, setT *vertices) {
01794 vertexT *vertex, **vertexp;
01795
01796 FOREACHvertex_(vertices) {
01797 if (vertex->point == point)
01798 return vertex;
01799 }
01800 return NULL;
01801 }
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829 vertexT *qh_makenewfacets (pointT *point ) {
01830 facetT *visible, *newfacet= NULL, *newfacet2= NULL, *neighbor, **neighborp;
01831 vertexT *apex;
01832 int numnew=0;
01833
01834 qh newfacet_list= qh facet_tail;
01835 qh newvertex_list= qh vertex_tail;
01836 apex= qh_newvertex(point);
01837 qh_appendvertex (apex);
01838 qh visit_id++;
01839 if (!qh ONLYgood)
01840 qh NEWfacets= True;
01841 FORALLvisible_facets {
01842 FOREACHneighbor_(visible)
01843 neighbor->seen= False;
01844 if (visible->ridges) {
01845 visible->visitid= qh visit_id;
01846 newfacet2= qh_makenew_nonsimplicial (visible, apex, &numnew);
01847 }
01848 if (visible->simplicial)
01849 newfacet= qh_makenew_simplicial (visible, apex, &numnew);
01850 if (!qh ONLYgood) {
01851 if (newfacet2)
01852 newfacet= newfacet2;
01853 if (newfacet)
01854 visible->f.replace= newfacet;
01855 else
01856 zinc_(Zinsidevisible);
01857 SETfirst_(visible->neighbors)= NULL;
01858 }
01859 }
01860 trace1((qh ferr, "qh_makenewfacets: created %d new facets from point p%d to horizon\n",
01861 numnew, qh_pointid(point)));
01862 if (qh IStracing >= 4)
01863 qh_printfacetlist (qh newfacet_list, NULL, qh_ALL);
01864 return apex;
01865 }
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892 #ifndef qh_NOmerge
01893 void qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount) {
01894 boolT same, ismatch;
01895 int hash, scan;
01896 facetT *facet, *newfacet, *maxmatch= NULL, *maxmatch2= NULL, *nextfacet;
01897 int skip, newskip, nextskip= 0, maxskip= 0, maxskip2= 0, makematch;
01898 realT maxdist= -REALmax, mindist, dist2, low, high;
01899
01900 hash= (int)qh_gethash (hashsize, atfacet->vertices, qh hull_dim, 1,
01901 SETelem_(atfacet->vertices, atskip));
01902 trace2((qh ferr, "qh_matchduplicates: find duplicate matches for f%d skip %d hash %d hashcount %d\n",
01903 atfacet->id, atskip, hash, *hashcount));
01904 for (makematch= 0; makematch < 2; makematch++) {
01905 qh visit_id++;
01906 for (newfacet= atfacet, newskip= atskip; newfacet; newfacet= nextfacet, newskip= nextskip) {
01907 zinc_(Zhashlookup);
01908 nextfacet= NULL;
01909 newfacet->visitid= qh visit_id;
01910 for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT));
01911 scan= (++scan >= hashsize ? 0 : scan)) {
01912 if (!facet->dupridge || facet->visitid == qh visit_id)
01913 continue;
01914 zinc_(Zhashtests);
01915 if (qh_matchvertices (1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
01916 ismatch= (same == (newfacet->toporient ^ facet->toporient));
01917 if (SETelemt_(facet->neighbors, skip, facetT) != qh_DUPLICATEridge) {
01918 if (!makematch) {
01919 fprintf (qh ferr, "qhull internal error (qh_matchduplicates): missing dupridge at f%d skip %d for new f%d skip %d hash %d\n",
01920 facet->id, skip, newfacet->id, newskip, hash);
01921 qh_errexit2 (qh_ERRqhull, facet, newfacet);
01922 }
01923 }else if (ismatch && makematch) {
01924 if (SETelemt_(newfacet->neighbors, newskip, facetT) == qh_DUPLICATEridge) {
01925 SETelem_(facet->neighbors, skip)= newfacet;
01926 SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;
01927 *hashcount -= 2;
01928 trace4((qh ferr, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d merge\n",
01929 facet->id, skip, newfacet->id, newskip));
01930 }
01931 }else if (ismatch) {
01932 mindist= qh_getdistance (facet, newfacet, &low, &high);
01933 dist2= qh_getdistance (newfacet, facet, &low, &high);
01934 minimize_(mindist, dist2);
01935 if (mindist > maxdist) {
01936 maxdist= mindist;
01937 maxmatch= facet;
01938 maxskip= skip;
01939 maxmatch2= newfacet;
01940 maxskip2= newskip;
01941 }
01942 trace3((qh ferr, "qh_matchduplicates: duplicate f%d skip %d new f%d skip %d at dist %2.2g, max is now f%d f%d\n",
01943 facet->id, skip, newfacet->id, newskip, mindist,
01944 maxmatch->id, maxmatch2->id));
01945 }else {
01946 nextfacet= facet;
01947 nextskip= skip;
01948 }
01949 }
01950 if (makematch && !facet
01951 && SETelemt_(facet->neighbors, skip, facetT) == qh_DUPLICATEridge) {
01952 fprintf (qh ferr, "qhull internal error (qh_matchduplicates): no MERGEridge match for duplicate f%d skip %d at hash %d\n",
01953 newfacet->id, newskip, hash);
01954 qh_errexit (qh_ERRqhull, newfacet, NULL);
01955 }
01956 }
01957 }
01958 if (!makematch) {
01959 if (!maxmatch) {
01960 fprintf (qh ferr, "qhull internal error (qh_matchduplicates): no maximum match at duplicate f%d skip %d at hash %d\n",
01961 atfacet->id, atskip, hash);
01962 qh_errexit (qh_ERRqhull, atfacet, NULL);
01963 }
01964 SETelem_(maxmatch->neighbors, maxskip)= maxmatch2;
01965 SETelem_(maxmatch2->neighbors, maxskip2)= maxmatch;
01966 *hashcount -= 2;
01967 zzinc_(Zmultiridge);
01968 trace0((qh ferr, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d keep\n",
01969 maxmatch->id, maxskip, maxmatch2->id, maxskip2));
01970 qh_precision ("ridge with multiple neighbors");
01971 if (qh IStracing >= 4)
01972 qh_errprint ("DUPLICATED/MATCH", maxmatch, maxmatch2, NULL, NULL);
01973 }
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 void qh_nearcoplanar ( void ) {
02001 facetT *facet;
02002 pointT *point, **pointp;
02003 int numpart;
02004 realT dist, innerplane;
02005
02006 if (!qh KEEPcoplanar && !qh KEEPinside) {
02007 FORALLfacets {
02008 if (facet->coplanarset)
02009 qh_setfree( &facet->coplanarset);
02010 }
02011 }else if (!qh KEEPcoplanar || !qh KEEPinside) {
02012 qh_outerinner (NULL, NULL, &innerplane);
02013 if (qh JOGGLEmax < REALmax/2)
02014 innerplane -= qh JOGGLEmax * sqrt (qh hull_dim);
02015 numpart= 0;
02016 FORALLfacets {
02017 if (facet->coplanarset) {
02018 FOREACHpoint_(facet->coplanarset) {
02019 numpart++;
02020 qh_distplane (point, facet, &dist);
02021 if (dist < innerplane) {
02022 if (!qh KEEPinside)
02023 SETref_(point)= NULL;
02024 }else if (!qh KEEPcoplanar)
02025 SETref_(point)= NULL;
02026 }
02027 qh_setcompact (facet->coplanarset);
02028 }
02029 }
02030 zadd_(Zcheckpart, numpart);
02031 }
02032 }
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047 vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp) {
02048 realT bestdist= REALmax, dist;
02049 vertexT *bestvertex= NULL, *vertex, **vertexp;
02050 int dim= qh hull_dim;
02051
02052 if (qh DELAUNAY)
02053 dim--;
02054 FOREACHvertex_(facet->vertices) {
02055 dist= qh_pointdist (vertex->point, point, -dim);
02056 if (dist < bestdist) {
02057 bestdist= dist;
02058 bestvertex= vertex;
02059 }
02060 }
02061 *bestdistp= sqrt (bestdist);
02062 return bestvertex;
02063 }
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076 int qh_newhashtable(int newsize) {
02077 int size;
02078
02079 size= ((newsize+1)*qh_HASHfactor) | 0x1;
02080 while (True) {
02081 if ((size%3) && (size%5))
02082 break;
02083 size += 2;
02084
02085 }
02086 qh hash_table= qh_setnew (size);
02087 qh_setzero (qh hash_table, 0, size);
02088 return size;
02089 }
02090
02091
02092
02093
02094
02095
02096
02097 vertexT *qh_newvertex(pointT *point) {
02098 vertexT *vertex;
02099
02100 zinc_(Ztotvertices);
02101 vertex= (vertexT *)qh_memalloc(sizeof(vertexT));
02102 memset ((char *) vertex, 0, sizeof (vertexT));
02103 if (qh vertex_id == 0xFFFFFF) {
02104 fprintf(qh ferr, "qhull input error: more than %d vertices. Id field overflows and two vertices\n\
02105 may have the same identifier. Vertices not sorted correctly.\n", 0xFFFFFF);
02106 qh_errexit(qh_ERRinput, NULL, NULL);
02107 }
02108 if (qh vertex_id == qh tracevertex_id)
02109 qh tracevertex= vertex;
02110 vertex->id= qh vertex_id++;
02111 vertex->point= point;
02112 trace4((qh ferr, "qh_newvertex: vertex p%d (v%d) created\n", qh_pointid(vertex->point),
02113 vertex->id));
02114 return (vertex);
02115 }
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132 ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp) {
02133 vertexT *atvertex, *vertex, *othervertex;
02134 ridgeT *ridge, **ridgep;
02135
02136 if ((atridge->top == facet) ^ qh_ORIENTclock)
02137 atvertex= SETsecondt_(atridge->vertices, vertexT);
02138 else
02139 atvertex= SETfirstt_(atridge->vertices, vertexT);
02140 FOREACHridge_(facet->ridges) {
02141 if (ridge == atridge)
02142 continue;
02143 if ((ridge->top == facet) ^ qh_ORIENTclock) {
02144 othervertex= SETsecondt_(ridge->vertices, vertexT);
02145 vertex= SETfirstt_(ridge->vertices, vertexT);
02146 }else {
02147 vertex= SETsecondt_(ridge->vertices, vertexT);
02148 othervertex= SETfirstt_(ridge->vertices, vertexT);
02149 }
02150 if (vertex == atvertex) {
02151 if (vertexp)
02152 *vertexp= othervertex;
02153 return ridge;
02154 }
02155 }
02156 return NULL;
02157 }
02158 #else
02159 void qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount) {
02160 }
02161 ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp) {
02162
02163 return NULL;
02164 }
02165 #endif
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181 void qh_outcoplanar (void ) {
02182 pointT *point, **pointp;
02183 facetT *facet;
02184 realT dist;
02185
02186 trace1((qh ferr, "qh_outcoplanar: move outsideset to coplanarset for qh NARROWhull\n"));
02187 FORALLfacets {
02188 FOREACHpoint_(facet->outsideset) {
02189 qh num_outside--;
02190 if (qh KEEPcoplanar || qh KEEPnearinside) {
02191 qh_distplane (point, facet, &dist);
02192 zinc_(Zpartition);
02193 qh_partitioncoplanar (point, facet, &dist);
02194 }
02195 }
02196 qh_setfree (&facet->outsideset);
02197 }
02198 }
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210 pointT *qh_point (int id) {
02211
02212 if (id < 0)
02213 return NULL;
02214 if (id < qh num_points)
02215 return qh first_point + id * qh hull_dim;
02216 id -= qh num_points;
02217 if (id < qh_setsize (qh other_points))
02218 return SETelemt_(qh other_points, id, pointT);
02219 return NULL;
02220 }
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234 void qh_point_add (setT *set, pointT *point, void *elem) {
02235 int id, size;
02236
02237 SETreturnsize_(set, size);
02238 if ((id= qh_pointid(point)) < 0)
02239 fprintf (qh ferr, "qhull internal warning (point_add): unknown point %p id %d\n",
02240 point, id);
02241 else if (id >= size) {
02242 fprintf (qh ferr, "qhull internal errror (point_add): point p%d is out of bounds (%d)\n",
02243 id, size);
02244 qh_errexit (qh_ERRqhull, NULL, NULL);
02245 }else
02246 SETelem_(set, id)= elem;
02247 }
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274 setT *qh_pointfacet (void ) {
02275 int numpoints= qh num_points + qh_setsize (qh other_points);
02276 setT *facets;
02277 facetT *facet;
02278 vertexT *vertex, **vertexp;
02279 pointT *point, **pointp;
02280
02281 facets= qh_settemp (numpoints);
02282 qh_setzero (facets, 0, numpoints);
02283 qh vertex_visit++;
02284 FORALLfacets {
02285 FOREACHvertex_(facet->vertices) {
02286 if (vertex->visitid != qh vertex_visit) {
02287 vertex->visitid= qh vertex_visit;
02288 qh_point_add (facets, vertex->point, facet);
02289 }
02290 }
02291 FOREACHpoint_(facet->coplanarset)
02292 qh_point_add (facets, point, facet);
02293 FOREACHpoint_(facet->outsideset)
02294 qh_point_add (facets, point, facet);
02295 }
02296 return facets;
02297 }
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311 setT *qh_pointvertex (void ) {
02312 int numpoints= qh num_points + qh_setsize (qh other_points);
02313 setT *vertices;
02314 vertexT *vertex;
02315
02316 vertices= qh_settemp (numpoints);
02317 qh_setzero (vertices, 0, numpoints);
02318 FORALLvertices
02319 qh_point_add (vertices, vertex->point, vertex);
02320 return vertices;
02321 }
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338 void qh_prependfacet(facetT *facet, facetT **facetlist) {
02339 facetT *prevfacet, *list= *facetlist;
02340
02341
02342 trace4((qh ferr, "qh_prependfacet: prepend f%d before f%d\n",
02343 facet->id, list->id));
02344 prevfacet= list->previous;
02345 facet->previous= prevfacet;
02346 if (prevfacet)
02347 prevfacet->next= facet;
02348 list->previous= facet;
02349 facet->next= *facetlist;
02350 if (qh facet_list == list)
02351 qh facet_list= facet;
02352 if (qh facet_next == list)
02353 qh facet_next= facet;
02354 *facetlist= facet;
02355 qh num_facets++;
02356 }
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374 void qh_printhashtable(FILE *fp) {
02375 facetT *facet, *neighbor;
02376 int id, facet_i, facet_n, neighbor_i= 0, neighbor_n= 0;
02377 vertexT *vertex, **vertexp;
02378
02379 FOREACHfacet_i_(qh hash_table) {
02380 if (facet) {
02381 FOREACHneighbor_i_(facet) {
02382 if (!neighbor || neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge)
02383 break;
02384 }
02385 if (neighbor_i == neighbor_n)
02386 continue;
02387 fprintf (fp, "hash %d f%d ", facet_i, facet->id);
02388 FOREACHvertex_(facet->vertices)
02389 fprintf (fp, "v%d ", vertex->id);
02390 fprintf (fp, "\n neighbors:");
02391 FOREACHneighbor_i_(facet) {
02392 if (neighbor == qh_MERGEridge)
02393 id= -3;
02394 else if (neighbor == qh_DUPLICATEridge)
02395 id= -2;
02396 else
02397 id= getid_(neighbor);
02398 fprintf (fp, " %d", id);
02399 }
02400 fprintf (fp, "\n");
02401 }
02402 }
02403 }
02404
02405
02406
02407
02408
02409
02410
02411
02412 void qh_printlists (void) {
02413 facetT *facet;
02414 vertexT *vertex;
02415
02416 fprintf (qh ferr, "qh_printlists: facets:");
02417 FORALLfacets
02418 fprintf (qh ferr, " %d", facet->id);
02419 fprintf (qh ferr, "\n new facets %d visible facets %d next facet for addpoint %d\n vertices (new %d):",
02420 getid_(qh newfacet_list), getid_(qh visible_list), getid_(qh facet_next),
02421 getid_(qh newvertex_list));
02422 FORALLvertices
02423 fprintf (qh ferr, " %d", vertex->id);
02424 fprintf (qh ferr, "\n");
02425 }
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439 void qh_resetlists (boolT stats ) {
02440 vertexT *vertex;
02441 facetT *newfacet, *visible;
02442 int totnew=0, totver=0;
02443
02444 if (stats) {
02445 FORALLvertex_(qh newvertex_list)
02446 totver++;
02447 FORALLnew_facets
02448 totnew++;
02449 zadd_(Zvisvertextot, totver);
02450 zmax_(Zvisvertexmax, totver);
02451 zadd_(Znewfacettot, totnew);
02452 zmax_(Znewfacetmax, totnew);
02453 }
02454 FORALLvertex_(qh newvertex_list)
02455 vertex->newlist= False;
02456 qh newvertex_list= NULL;
02457 FORALLnew_facets
02458 newfacet->newfacet= False;
02459 qh newfacet_list= NULL;
02460 FORALLvisible_facets {
02461 visible->f.replace= NULL;
02462 visible->visible= False;
02463 }
02464 qh visible_list= NULL;
02465 qh num_visible= 0;
02466 qh NEWfacets= False;
02467 }
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487 void qh_setvoronoi_all (void) {
02488 facetT *facet;
02489
02490 qh_clearcenters (qh_ASvoronoi);
02491 qh_vertexneighbors();
02492
02493 FORALLfacets {
02494 if (!facet->normal || !facet->upperdelaunay || qh UPPERdelaunay) {
02495 if (!facet->center)
02496 facet->center= qh_facetcenter (facet->vertices);
02497 }
02498 }
02499 }
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514 void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB) {
02515 setT *intersection;
02516
02517 intersection= qh_vertexintersect_new (*vertexsetA, vertexsetB);
02518 qh_settempfree (vertexsetA);
02519 *vertexsetA= intersection;
02520 qh_settemppush (intersection);
02521 }
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532 setT *qh_vertexintersect_new (setT *vertexsetA,setT *vertexsetB) {
02533 setT *intersection= qh_setnew (qh hull_dim - 1);
02534 vertexT **vertexA= SETaddr_(vertexsetA, vertexT);
02535 vertexT **vertexB= SETaddr_(vertexsetB, vertexT);
02536
02537 while (*vertexA && *vertexB) {
02538 if (*vertexA == *vertexB) {
02539 qh_setappend(&intersection, *vertexA);
02540 vertexA++; vertexB++;
02541 }else {
02542 if ((*vertexA)->id > (*vertexB)->id)
02543 vertexA++;
02544 else
02545 vertexB++;
02546 }
02547 }
02548 return intersection;
02549 }
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571 void qh_vertexneighbors (void ) {
02572 facetT *facet;
02573 vertexT *vertex, **vertexp;
02574
02575 if (qh VERTEXneighbors)
02576 return;
02577 trace1((qh ferr, "qh_vertexneighbors: determing neighboring facets for each vertex\n"));
02578 qh vertex_visit++;
02579 FORALLfacets {
02580 if (facet->visible)
02581 continue;
02582 FOREACHvertex_(facet->vertices) {
02583 if (vertex->visitid != qh vertex_visit) {
02584 vertex->visitid= qh vertex_visit;
02585 vertex->neighbors= qh_setnew (qh hull_dim);
02586 }
02587 qh_setappend (&vertex->neighbors, facet);
02588 }
02589 }
02590 qh VERTEXneighbors= True;
02591 }
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603 boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB) {
02604 vertexT **vertexA= (vertexT **) SETaddr_(vertexsetA, vertexT);
02605 vertexT **vertexB= (vertexT **) SETaddr_(vertexsetB, vertexT);
02606
02607 while (True) {
02608 if (!*vertexA)
02609 return True;
02610 if (!*vertexB)
02611 return False;
02612 if ((*vertexA)->id > (*vertexB)->id)
02613 return False;
02614 if (*vertexA == *vertexB)
02615 vertexA++;
02616 vertexB++;
02617 }
02618 return False;
02619 }