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