00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 #include "qhull_a.h"
00027 
00028 #ifndef qh_NOmerge
00029 
00030 
00031 
00032 static int qh_compareangle(const void *p1, const void *p2);
00033 static int qh_comparemerge(const void *p1, const void *p2);
00034 static int qh_comparevisit (const void *p1, const void *p2);
00035 
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 void qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle) {
00062   boolT othermerge= False;
00063   facetT *newfacet;
00064   
00065   if (qh ZEROcentrum && qh_checkzero(!qh_ALL))
00066     return;    
00067   trace2((qh ferr, "qh_premerge: premerge centrum %2.2g angle %2.2g for apex v%d facetlist f%d\n",
00068             maxcentrum, maxangle, apex->id, getid_(qh newfacet_list)));
00069   if (qh IStracing >= 4 && qh num_facets < 50)
00070     qh_printlists();
00071   qh centrum_radius= maxcentrum;
00072   qh cos_max= maxangle;
00073   qh degen_mergeset= qh_settemp (qh TEMPsize);
00074   qh facet_mergeset= qh_settemp (qh TEMPsize);
00075   if (qh hull_dim >=3) { 
00076     qh_mark_dupridges (qh newfacet_list); 
00077     qh_mergecycle_all (qh newfacet_list, &othermerge);
00078     qh_forcedmerges (&othermerge ); 
00079     FORALLnew_facets {  
00080       if (!newfacet->simplicial && !newfacet->mergeridge)
00081         qh_degen_redundant_neighbors (newfacet, NULL);
00082     }
00083     if (qh_merge_degenredundant())
00084       othermerge= True;
00085   }else 
00086     qh_mergecycle_all (qh newfacet_list, &othermerge);
00087   qh_flippedmerges (qh newfacet_list, &othermerge);
00088   if (!qh MERGEexact || zzval_(Ztotmerge)) {
00089     zinc_(Zpremergetot);
00090     qh POSTmerging= False;
00091     qh_getmergeset_initial (qh newfacet_list);
00092     qh_all_merges (othermerge, False);
00093   }
00094   qh_settempfree(&qh facet_mergeset);
00095   qh_settempfree(&qh degen_mergeset);
00096 } 
00097   
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 void qh_postmerge (char *reason, realT maxcentrum, realT maxangle, 
00135                       boolT vneighbors) {
00136   facetT *newfacet;
00137   boolT othermerges= False;
00138   vertexT *vertex;
00139 
00140   if (qh REPORTfreq || qh IStracing) {
00141     qh_buildtracing (NULL, NULL);
00142     qh_printsummary (qh ferr);
00143     if (qh PRINTstatistics) 
00144       qh_printallstatistics (qh ferr, "reason");
00145     fprintf (qh ferr, "\n%s with 'C%.2g' and 'A%.2g'\n", 
00146         reason, maxcentrum, maxangle);
00147   }
00148   trace2((qh ferr, "qh_postmerge: postmerge.  test vneighbors? %d\n",
00149             vneighbors));
00150   qh centrum_radius= maxcentrum;
00151   qh cos_max= maxangle;
00152   qh POSTmerging= True;
00153   qh degen_mergeset= qh_settemp (qh TEMPsize);
00154   qh facet_mergeset= qh_settemp (qh TEMPsize);
00155   if (qh visible_list != qh facet_list) {  
00156     qh NEWfacets= True;
00157     qh visible_list= qh newfacet_list= qh facet_list;
00158     FORALLnew_facets {
00159       newfacet->newfacet= True;
00160        if (!newfacet->simplicial)
00161         newfacet->newmerge= True;
00162      zinc_(Zpostfacets);
00163     }
00164     qh newvertex_list= qh vertex_list;
00165     FORALLvertices
00166       vertex->newlist= True;
00167     if (qh VERTEXneighbors) { 
00168       FORALLvertices
00169         vertex->delridge= True; 
00170       if (qh MERGEexact) {
00171         if (qh hull_dim <= qh_DIMreduceBuild)
00172           qh_reducevertices(); 
00173       }
00174     }
00175     if (!qh PREmerge && !qh MERGEexact) 
00176       qh_flippedmerges (qh newfacet_list, &othermerges);
00177   }
00178   qh_getmergeset_initial (qh newfacet_list);
00179   qh_all_merges (False, vneighbors);
00180   qh_settempfree(&qh facet_mergeset);
00181   qh_settempfree(&qh degen_mergeset);
00182 } 
00183 
00184 
00185 
00186 
00187 
00188 
00189 
00190 
00191 
00192 
00193 
00194 
00195 
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 void qh_all_merges (boolT othermerge, boolT vneighbors) {
00221   facetT *facet1, *facet2;
00222   mergeT *merge;
00223   boolT wasmerge= True, isreduce;
00224   void **freelistp;  
00225   vertexT *vertex;
00226   mergeType mergetype;
00227   int numcoplanar=0, numconcave=0, numdegenredun= 0, numnewmerges= 0;
00228   
00229   trace2((qh ferr, "qh_all_merges: starting to merge facets beginning from f%d\n",
00230             getid_(qh newfacet_list)));
00231   while (True) {
00232     wasmerge= False;
00233     while (qh_setsize (qh facet_mergeset)) {
00234       while ((merge= (mergeT*)qh_setdellast(qh facet_mergeset))) {
00235         facet1= merge->facet1;
00236         facet2= merge->facet2;
00237         mergetype= merge->type;
00238         qh_memfree_(merge, sizeof(mergeT), freelistp);
00239         if (facet1->visible || facet2->visible) 
00240           continue;  
00241         if ((facet1->newfacet && !facet1->tested)
00242                 || (facet2->newfacet && !facet2->tested)) {
00243           if (qh MERGEindependent && mergetype <= MRGanglecoplanar)
00244             continue;      
00245         }
00246         qh_merge_nonconvex (facet1, facet2, mergetype);
00247         numdegenredun += qh_merge_degenredundant();
00248         numnewmerges++;
00249         wasmerge= True;
00250         if (mergetype == MRGconcave)
00251           numconcave++;
00252         else 
00253           numcoplanar++;
00254       } 
00255       if (qh POSTmerging && qh hull_dim <= qh_DIMreduceBuild 
00256       && numnewmerges > qh_MAXnewmerges) {
00257         numnewmerges= 0;
00258         qh_reducevertices();  
00259       }
00260       qh_getmergeset (qh newfacet_list); 
00261     } 
00262     if (qh VERTEXneighbors) {
00263       isreduce= False;
00264       if (qh hull_dim >=4 && qh POSTmerging) {
00265         FORALLvertices  
00266           vertex->delridge= True;
00267         isreduce= True;
00268       }
00269       if ((wasmerge || othermerge) && (!qh MERGEexact || qh POSTmerging) 
00270           && qh hull_dim <= qh_DIMreduceBuild) {
00271         othermerge= False;
00272         isreduce= True;
00273       }
00274       if (isreduce) {
00275         if (qh_reducevertices()) {
00276           qh_getmergeset (qh newfacet_list); 
00277           continue;
00278         }
00279       }
00280     }
00281     if (vneighbors && qh_test_vneighbors()) 
00282       continue;
00283     break;
00284   } 
00285   if (qh CHECKfrequently && !qh MERGEexact) {
00286     qh old_randomdist= qh RANDOMdist;
00287     qh RANDOMdist= False;
00288     qh_checkconvex (qh newfacet_list, qh_ALGORITHMfault);
00289     
00290     qh RANDOMdist= qh old_randomdist;
00291   }
00292   trace1((qh ferr, "qh_all_merges: merged %d coplanar facets %d concave facets and %d degen or redundant facets.\n",
00293     numcoplanar, numconcave, numdegenredun));
00294   if (qh IStracing >= 4 && qh num_facets < 50)
00295     qh_printlists ();
00296 } 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 void qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle) {
00326   mergeT *merge, *lastmerge;
00327   void **freelistp; 
00328 
00329   if (facet->redundant)
00330     return;
00331   if (facet->degenerate && mergetype == MRGdegen)
00332     return;
00333   qh_memalloc_(sizeof(mergeT), freelistp, merge, mergeT);
00334   merge->facet1= facet;
00335   merge->facet2= neighbor;
00336   merge->type= mergetype;
00337   if (angle && qh ANGLEmerge)
00338     merge->angle= *angle;
00339   if (mergetype < MRGdegen)
00340     qh_setappend (&(qh facet_mergeset), merge);
00341   else if (mergetype == MRGdegen) {
00342     facet->degenerate= True;
00343     if (!(lastmerge= (mergeT*)qh_setlast (qh degen_mergeset)) 
00344     || lastmerge->type == MRGdegen)
00345       qh_setappend (&(qh degen_mergeset), merge);
00346     else
00347       qh_setaddnth (&(qh degen_mergeset), 0, merge);
00348   }else { 
00349     facet->redundant= True;
00350     qh_setappend (&(qh degen_mergeset), merge);
00351   }
00352 } 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 setT *qh_basevertices (facetT *samecycle) {
00376   facetT *same;
00377   vertexT *apex, *vertex, **vertexp;
00378   setT *vertices= qh_settemp (qh TEMPsize);
00379   
00380   apex= SETfirstt_(samecycle->vertices, vertexT);
00381   apex->visitid= ++qh vertex_visit;
00382   FORALLsame_cycle_(samecycle) {
00383     if (same->mergeridge)
00384       continue;
00385     FOREACHvertex_(same->vertices) {
00386       if (vertex->visitid != qh vertex_visit) {
00387         qh_setappend (&vertices, vertex);
00388         vertex->visitid= qh vertex_visit;
00389         vertex->seen= False;
00390       }
00391     }
00392   }
00393   trace4((qh ferr, "qh_basevertices: found %d vertices\n", 
00394          qh_setsize (vertices)));
00395   return vertices;
00396 } 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 void qh_checkconnect (void ) {
00417   facetT *facet, *newfacet, *errfacet= NULL, *neighbor, **neighborp;
00418 
00419   facet= qh newfacet_list;
00420   qh_removefacet (facet);
00421   qh_appendfacet (facet);
00422   facet->visitid= ++qh visit_id;
00423   FORALLfacet_(facet) {
00424     FOREACHneighbor_(facet) {
00425       if (neighbor->visitid != qh visit_id) {
00426         qh_removefacet (neighbor);
00427         qh_appendfacet (neighbor);
00428         neighbor->visitid= qh visit_id;
00429       }
00430     }
00431   }
00432   FORALLnew_facets {
00433     if (newfacet->visitid == qh visit_id)
00434       break;
00435     fprintf(qh ferr, "qhull error: f%d is not attached to the new facets\n",
00436          newfacet->id);
00437     errfacet= newfacet;
00438   }
00439   if (errfacet)
00440     qh_errexit (qh_ERRqhull, errfacet, NULL);
00441 } 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 
00458 
00459 
00460 
00461 
00462 
00463 
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 boolT qh_checkzero (boolT testall) {
00480   facetT *facet, *neighbor, **neighborp;
00481   facetT *horizon, *facetlist;
00482   int neighbor_i;
00483   vertexT *vertex, **vertexp;
00484   realT dist;
00485 
00486   if (testall) 
00487     facetlist= qh facet_list;
00488   else {
00489     facetlist= qh newfacet_list;
00490     FORALLfacet_(facetlist) {
00491       horizon= SETfirstt_(facet->neighbors, facetT);
00492       if (!horizon->simplicial)
00493         goto LABELproblem;
00494       if (facet->flipped || facet->dupridge || !facet->normal)
00495         goto LABELproblem;
00496     }
00497     if (qh MERGEexact && qh ZEROall_ok) {
00498       trace2((qh ferr, "qh_checkzero: skip convexity check until first pre-merge\n"));
00499       return True;
00500     }
00501   }
00502   FORALLfacet_(facetlist) {
00503     qh vertex_visit++;
00504     neighbor_i= 0;
00505     horizon= NULL;
00506     FOREACHneighbor_(facet) {
00507       if (!neighbor_i && !testall) {
00508         horizon= neighbor;
00509         neighbor_i++;
00510         continue; 
00511       }
00512       vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
00513       vertex->visitid= qh vertex_visit;
00514       zzinc_(Zdistzero);
00515       qh_distplane (vertex->point, neighbor, &dist);
00516       if (dist >= -qh DISTround) {
00517         qh ZEROall_ok= False;
00518         if (!qh MERGEexact || testall || dist > qh DISTround)
00519           goto LABELnonconvex;
00520       }
00521     }
00522     if (!testall) {
00523       FOREACHvertex_(horizon->vertices) {
00524         if (vertex->visitid != qh vertex_visit) {
00525           zzinc_(Zdistzero);
00526           qh_distplane (vertex->point, facet, &dist);
00527           if (dist >= -qh DISTround) {
00528             qh ZEROall_ok= False;
00529             if (!qh MERGEexact || dist > qh DISTround)
00530               goto LABELnonconvex;
00531           }
00532           break;
00533         }
00534       }
00535     }
00536   }
00537   trace2((qh ferr, "qh_checkzero: testall %d, facets are %s\n", testall,
00538         (qh MERGEexact && !testall) ? 
00539            "not concave, flipped, or duplicate ridged" : "clearly convex"));
00540   return True;
00541 
00542  LABELproblem:
00543   qh ZEROall_ok= False;
00544   trace2((qh ferr, "qh_checkzero: facet f%d needs pre-merging\n",
00545        facet->id));
00546   return False;
00547 
00548  LABELnonconvex:
00549   trace2((qh ferr, "qh_checkzero: facet f%d and f%d are not clearly convex.  v%d dist %.2g\n",
00550          facet->id, neighbor->id, vertex->id, dist));
00551   return False;
00552 } 
00553 
00554 
00555 
00556 
00557 
00558 
00559 
00560 static int qh_compareangle(const void *p1, const void *p2) {
00561   mergeT *a= *((mergeT **)p1), *b= *((mergeT **)p2);
00562  
00563   return ((a->angle > b->angle) ? 1 : -1);
00564 } 
00565 
00566 
00567 
00568 
00569 
00570 
00571 
00572 static int qh_comparemerge(const void *p1, const void *p2) {
00573   mergeT *a= *((mergeT **)p1), *b= *((mergeT **)p2);
00574  
00575   return (a->type - b->type);
00576 } 
00577 
00578 
00579 
00580 
00581 
00582 
00583 
00584 static int qh_comparevisit (const void *p1, const void *p2) {
00585   vertexT *a= *((vertexT **)p1), *b= *((vertexT **)p2);
00586  
00587   return (a->visitid - b->visitid);
00588 } 
00589 
00590 
00591 
00592 
00593 
00594 
00595 
00596 
00597 
00598 
00599 
00600 
00601 
00602 
00603 
00604 void qh_copynonconvex (ridgeT *atridge) {
00605   facetT *facet, *otherfacet;
00606   ridgeT *ridge, **ridgep;
00607 
00608   facet= atridge->top;
00609   otherfacet= atridge->bottom;
00610   FOREACHridge_(facet->ridges) {
00611     if (otherfacet == otherfacet_(ridge, facet) && ridge != atridge) {
00612       ridge->nonconvex= True;
00613       trace4((qh ferr, "qh_copynonconvex: moved nonconvex flag from r%d to r%d\n",
00614               atridge->id, ridge->id));
00615       break;
00616     }
00617   }
00618 } 
00619 
00620 
00621 
00622 
00623 
00624 
00625 
00626 
00627 
00628 
00629 
00630 
00631 
00632 
00633 
00634 
00635 
00636 
00637 
00638 void qh_degen_redundant_facet (facetT *facet) {
00639   vertexT *vertex, **vertexp;
00640   facetT *neighbor, **neighborp;
00641 
00642   trace4((qh ferr, "qh_degen_redundant_facet: test facet f%d for degen/redundant\n",
00643           facet->id));
00644   FOREACHneighbor_(facet) {
00645     qh vertex_visit++;
00646     FOREACHvertex_(neighbor->vertices)
00647       vertex->visitid= qh vertex_visit;
00648     FOREACHvertex_(facet->vertices) {
00649       if (vertex->visitid != qh vertex_visit)
00650         break;
00651     }
00652     if (!vertex) {
00653       qh_appendmergeset (facet, neighbor, MRGredundant, NULL);
00654       trace2((qh ferr, "qh_degen_redundant_facet: f%d is contained in f%d.  merge\n", facet->id, neighbor->id)); 
00655       return;
00656     }
00657   }
00658   if (qh_setsize (facet->neighbors) < qh hull_dim) {
00659     qh_appendmergeset (facet, facet, MRGdegen, NULL);
00660     trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate.\n", facet->id));
00661   }
00662 } 
00663 
00664 
00665 
00666 
00667 
00668 
00669 
00670 
00671 
00672 
00673 
00674 
00675 
00676 
00677 
00678 
00679 
00680 
00681 
00682 
00683 
00684 
00685 
00686 
00687 
00688 
00689 
00690 
00691 
00692 
00693 
00694 void qh_degen_redundant_neighbors (facetT *facet, facetT *delfacet) {
00695   vertexT *vertex, **vertexp;
00696   facetT *neighbor, **neighborp;
00697   int size;
00698 
00699   trace4((qh ferr, "qh_degen_redundant_neighbors: test neighbors of f%d with delfacet f%d\n", 
00700           facet->id, getid_(delfacet)));
00701   if ((size= qh_setsize (facet->neighbors)) < qh hull_dim) {
00702     qh_appendmergeset (facet, facet, MRGdegen, NULL);
00703     trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors.\n", facet->id, size));
00704   }
00705   if (!delfacet)
00706     delfacet= facet;
00707   qh vertex_visit++;
00708   FOREACHvertex_(facet->vertices)
00709     vertex->visitid= qh vertex_visit;
00710   FOREACHneighbor_(delfacet) {
00711     
00712     if (neighbor == facet)
00713       continue;
00714     FOREACHvertex_(neighbor->vertices) {
00715       if (vertex->visitid != qh vertex_visit)
00716         break;
00717     }
00718     if (!vertex) {
00719       qh_appendmergeset (neighbor, facet, MRGredundant, NULL);
00720       trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is contained in f%d.  merge\n", neighbor->id, facet->id)); 
00721     }
00722   }
00723   FOREACHneighbor_(delfacet) {   
00724     if (neighbor == facet)
00725       continue;
00726     if ((size= qh_setsize (neighbor->neighbors)) < qh hull_dim) {
00727       qh_appendmergeset (neighbor, neighbor, MRGdegen, NULL);
00728       trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors.  Neighbor of f%d.\n", neighbor->id, size, facet->id)); 
00729     }
00730   }
00731 } 
00732 
00733 
00734 
00735 
00736 
00737 
00738 
00739 
00740 
00741 
00742 
00743 
00744 
00745 
00746 
00747 
00748 
00749 
00750 
00751 
00752 
00753 
00754 
00755 
00756 
00757 
00758 
00759 
00760 
00761 
00762 
00763 
00764 vertexT *qh_find_newvertex (vertexT *oldvertex, setT *vertices, setT *ridges) {
00765   vertexT *vertex, **vertexp;
00766   setT *newridges;
00767   ridgeT *ridge, **ridgep;
00768   int size, hashsize;
00769   int hash;
00770 
00771 #ifndef qh_NOtrace
00772   if (qh IStracing >= 4) {
00773     fprintf (qh ferr, "qh_find_newvertex: find new vertex for v%d from ",
00774              oldvertex->id);
00775     FOREACHvertex_(vertices) 
00776       fprintf (qh ferr, "v%d ", vertex->id);
00777     FOREACHridge_(ridges)
00778       fprintf (qh ferr, "r%d ", ridge->id);
00779     fprintf (qh ferr, "\n");
00780   }
00781 #endif
00782   FOREACHvertex_(vertices) 
00783     vertex->visitid= 0;
00784   FOREACHridge_(ridges) {
00785     FOREACHvertex_(ridge->vertices) 
00786       vertex->visitid++;
00787   }
00788   FOREACHvertex_(vertices) {
00789     if (!vertex->visitid) {
00790       qh_setdelnth (vertices, SETindex_(vertices,vertex));
00791       vertexp--; 
00792     }
00793   }
00794   qh vertex_visit += qh_setsize (ridges);
00795   if (!qh_setsize (vertices)) {
00796     trace4((qh ferr, "qh_find_newvertex: vertices not in ridges for v%d\n",
00797             oldvertex->id));
00798     return NULL;
00799   }
00800   qsort (SETaddr_(vertices, vertexT), qh_setsize (vertices),
00801                 sizeof (vertexT *), qh_comparevisit);
00802   
00803   if (qh PRINTstatistics) {
00804     size= qh_setsize (vertices);
00805     zinc_(Zintersect);
00806     zadd_(Zintersecttot, size);
00807     zmax_(Zintersectmax, size);
00808   }
00809   hashsize= qh_newhashtable (qh_setsize (ridges));
00810   FOREACHridge_(ridges)
00811     qh_hashridge (qh hash_table, hashsize, ridge, oldvertex);
00812   FOREACHvertex_(vertices) {
00813     newridges= qh_vertexridges (vertex);
00814     FOREACHridge_(newridges) {
00815       if (qh_hashridge_find (qh hash_table, hashsize, ridge, vertex, oldvertex, &hash)) {
00816         zinc_(Zdupridge);
00817         break;
00818       }
00819     }
00820     qh_settempfree (&newridges);
00821     if (!ridge)
00822       break;  
00823   }
00824   if (vertex) {
00825     
00826     trace2((qh ferr, "qh_find_newvertex: found v%d for old v%d from %d vertices and %d ridges.\n",
00827       vertex->id, oldvertex->id, qh_setsize (vertices), qh_setsize (ridges)));
00828   }else {
00829     zinc_(Zfindfail);
00830     trace0((qh ferr, "qh_find_newvertex: no vertex for renaming v%d (all duplicated ridges) during p%d\n",
00831       oldvertex->id, qh furthest_id));
00832   }
00833   qh_setfree (&qh hash_table);
00834   return vertex;
00835 } 
00836 
00837 
00838 
00839 
00840 
00841 
00842 
00843 
00844 
00845 
00846 
00847 
00848 
00849 
00850 
00851 void qh_findbest_test (boolT testcentrum, facetT *facet, facetT *neighbor,
00852       facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp) {
00853   realT dist, mindist, maxdist;
00854 
00855   if (testcentrum) {
00856     zzinc_(Zbestdist);
00857     qh_distplane(facet->center, neighbor, &dist);
00858     dist *= qh hull_dim; 
00859     if (dist < 0) {
00860       maxdist= 0;
00861       mindist= dist;
00862       dist= -dist;
00863     }else
00864       maxdist= dist;
00865   }else
00866     dist= qh_getdistance (facet, neighbor, &mindist, &maxdist);
00867   if (dist < *distp) {
00868     *bestfacet= neighbor;
00869     *mindistp= mindist;
00870     *maxdistp= maxdist;
00871     *distp= dist;
00872   }
00873 } 
00874 
00875 
00876 
00877 
00878 
00879 
00880 
00881 
00882 
00883 
00884 
00885 
00886 
00887 
00888 
00889 
00890 
00891 
00892 
00893 
00894 
00895 
00896 
00897 
00898 
00899 
00900 
00901 facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp) {
00902   facetT *neighbor, **neighborp, *bestfacet= NULL;
00903   ridgeT *ridge, **ridgep;
00904   boolT nonconvex= True, testcentrum= False;
00905   int size= qh_setsize (facet->vertices);
00906 
00907   *distp= REALmax;
00908   if (size > qh_BESTcentrum2 * qh hull_dim + qh_BESTcentrum) {
00909     testcentrum= True;
00910     zinc_(Zbestcentrum);
00911     if (!facet->center)
00912        facet->center= qh_getcentrum (facet);
00913   }
00914   if (size > qh hull_dim + qh_BESTnonconvex) {
00915     FOREACHridge_(facet->ridges) {
00916       if (ridge->nonconvex) {
00917         neighbor= otherfacet_(ridge, facet);
00918         qh_findbest_test (testcentrum, facet, neighbor,
00919                           &bestfacet, distp, mindistp, maxdistp);
00920       }
00921     }
00922   }
00923   if (!bestfacet) {     
00924     nonconvex= False;
00925     FOREACHneighbor_(facet)
00926       qh_findbest_test (testcentrum, facet, neighbor,
00927                         &bestfacet, distp, mindistp, maxdistp);
00928   }
00929   if (!bestfacet) {
00930     fprintf (qh ferr, "qhull internal error (qh_findbestneighbor): no neighbors for f%d\n", facet->id);
00931     
00932     qh_errexit (qh_ERRqhull, facet, NULL);
00933   }
00934   if (testcentrum) 
00935     qh_getdistance (facet, bestfacet, mindistp, maxdistp);
00936   trace3((qh ferr, "qh_findbestneighbor: f%d is best neighbor for f%d testcentrum? %d nonconvex? %d dist %2.2g min %2.2g max %2.2g\n",
00937      bestfacet->id, facet->id, testcentrum, nonconvex, *distp, *mindistp, *maxdistp));
00938   return(bestfacet);
00939 } 
00940 
00941 
00942 
00943 
00944 
00945 
00946 
00947 
00948 
00949 
00950 
00951 
00952 
00953 
00954 
00955 
00956 
00957 
00958 
00959 
00960 
00961 
00962 
00963 
00964 
00965 
00966 void qh_flippedmerges(facetT *facetlist, boolT *wasmerge) {
00967   facetT *facet, *neighbor, *facet1;
00968   realT dist, mindist, maxdist;
00969   mergeT *merge, **mergep;
00970   setT *othermerges;
00971   int nummerge=0;
00972 
00973   trace4((qh ferr, "qh_flippedmerges: begin\n"));
00974   FORALLfacet_(facetlist) {
00975     if (facet->flipped && !facet->visible) 
00976       qh_appendmergeset (facet, facet, MRGflip, NULL);
00977   }
00978   othermerges= qh_settemppop(); 
00979   qh facet_mergeset= qh_settemp (qh TEMPsize);
00980   qh_settemppush (othermerges);
00981   FOREACHmerge_(othermerges) {
00982     facet1= merge->facet1;
00983     if (merge->type != MRGflip || facet1->visible) 
00984       continue;
00985     if (qh TRACEmerge-1 == zzval_(Ztotmerge))
00986       qhmem.IStracing= qh IStracing= qh TRACElevel;
00987     neighbor= qh_findbestneighbor (facet1, &dist, &mindist, &maxdist);
00988     trace0((qh ferr, "qh_flippedmerges: merge flipped f%d into f%d dist %2.2g during p%d\n",
00989       facet1->id, neighbor->id, dist, qh furthest_id));
00990     qh_mergefacet (facet1, neighbor, &mindist, &maxdist, !qh_MERGEapex);
00991     nummerge++;
00992     if (qh PRINTstatistics) {
00993       zinc_(Zflipped);
00994       wadd_(Wflippedtot, dist);
00995       wmax_(Wflippedmax, dist);
00996     }
00997     qh_merge_degenredundant();
00998   }
00999   FOREACHmerge_(othermerges) {
01000     if (merge->facet1->visible || merge->facet2->visible)
01001       qh_memfree (merge, sizeof(mergeT));
01002     else
01003       qh_setappend (&qh facet_mergeset, merge);
01004   }
01005   qh_settempfree (&othermerges);
01006   if (nummerge)
01007     *wasmerge= True;
01008   trace1((qh ferr, "qh_flippedmerges: merged %d flipped facets into a good neighbor\n", nummerge));
01009 } 
01010 
01011 
01012 
01013 
01014 
01015 
01016 
01017 
01018 
01019 
01020 
01021 
01022 
01023 
01024 
01025 
01026 
01027 
01028 
01029 
01030 
01031 
01032 
01033 
01034 
01035 
01036 
01037 
01038 
01039 void qh_forcedmerges(boolT *wasmerge) {
01040   facetT *facet1, *facet2;
01041   mergeT *merge, **mergep;
01042   realT dist1, dist2, mindist1, mindist2, maxdist1, maxdist2;
01043   setT *othermerges;
01044   int nummerge=0, numflip=0;
01045 
01046   if (qh TRACEmerge-1 == zzval_(Ztotmerge))
01047     qhmem.IStracing= qh IStracing= qh TRACElevel;
01048   trace4((qh ferr, "qh_forcedmerges: begin\n"));  
01049   othermerges= qh_settemppop(); 
01050   qh facet_mergeset= qh_settemp (qh TEMPsize);
01051   qh_settemppush (othermerges);
01052   FOREACHmerge_(othermerges) {
01053     if (merge->type != MRGridge) 
01054         continue;
01055     facet1= merge->facet1;
01056     facet2= merge->facet2;
01057     while (facet1->visible)      
01058       facet1= facet1->f.replace; 
01059     while (facet2->visible)
01060       facet2= facet2->f.replace; 
01061     if (facet1 == facet2)
01062       continue;
01063     if (!qh_setin (facet2->neighbors, facet1)) {
01064       fprintf (qh ferr, "qhull internal error (qh_forcedmerges): f%d and f%d had a duplicate ridge but as f%d and f%d they are no longer neighbors\n",
01065                merge->facet1->id, merge->facet2->id, facet1->id, facet2->id);
01066       qh_errexit2 (qh_ERRqhull, facet1, facet2);
01067     }
01068     if (qh TRACEmerge-1 == zzval_(Ztotmerge))
01069       qhmem.IStracing= qh IStracing= qh TRACElevel;
01070     dist1= qh_getdistance (facet1, facet2, &mindist1, &maxdist1);
01071     dist2= qh_getdistance (facet2, facet1, &mindist2, &maxdist2);
01072     trace0((qh ferr, "qh_forcedmerges: duplicate ridge between f%d and f%d, dist %2.2g and reverse dist %2.2g during p%d\n",
01073             facet1->id, facet2->id, dist1, dist2, qh furthest_id));
01074     if (dist1 < dist2) 
01075       qh_mergefacet (facet1, facet2, &mindist1, &maxdist1, !qh_MERGEapex);
01076     else {
01077       qh_mergefacet (facet2, facet1, &mindist2, &maxdist2, !qh_MERGEapex);
01078       dist1= dist2;
01079       facet1= facet2;
01080     }
01081     if (facet1->flipped) {
01082       zinc_(Zmergeflipdup);
01083       numflip++;
01084     }else
01085       nummerge++;
01086     if (qh PRINTstatistics) {
01087       zinc_(Zduplicate);
01088       wadd_(Wduplicatetot, dist1);
01089       wmax_(Wduplicatemax, dist1);
01090     }
01091   }
01092   FOREACHmerge_(othermerges) {
01093     if (merge->type == MRGridge)
01094       qh_memfree (merge, sizeof(mergeT));
01095     else
01096       qh_setappend (&qh facet_mergeset, merge);
01097   }
01098   qh_settempfree (&othermerges);
01099   if (nummerge)
01100     *wasmerge= True;
01101   trace1((qh ferr, "qh_forcedmerges: merged %d facets and %d flipped facets across duplicated ridges\n", 
01102                 nummerge, numflip));
01103 } 
01104 
01105 
01106 
01107 
01108 
01109 
01110 
01111 
01112 
01113 
01114 
01115 
01116 
01117 
01118 
01119 
01120 
01121 
01122 
01123 
01124 
01125 
01126 
01127 
01128 
01129 
01130 
01131 
01132 
01133 
01134 
01135 void qh_getmergeset(facetT *facetlist) {
01136   facetT *facet, *neighbor, **neighborp;
01137   ridgeT *ridge, **ridgep;
01138   int nummerges;
01139   
01140   nummerges= qh_setsize (qh facet_mergeset);
01141   trace4((qh ferr, "qh_getmergeset: started.\n"));
01142   qh visit_id++;
01143   FORALLfacet_(facetlist) {
01144     if (facet->tested)
01145       continue;
01146     facet->visitid= qh visit_id;
01147     facet->tested= True;  
01148     FOREACHneighbor_(facet)
01149       neighbor->seen= False;
01150     FOREACHridge_(facet->ridges) {
01151       if (ridge->tested && !ridge->nonconvex)
01152         continue;
01153       
01154       neighbor= otherfacet_(ridge, facet);
01155       if (neighbor->seen) {
01156         ridge->tested= True;
01157         ridge->nonconvex= False;
01158       }else if (neighbor->visitid != qh visit_id) {
01159         ridge->tested= True;
01160         ridge->nonconvex= False;
01161         neighbor->seen= True;      
01162         if (qh_test_appendmerge (facet, neighbor))
01163           ridge->nonconvex= True;
01164       }
01165     }
01166   }
01167   nummerges= qh_setsize (qh facet_mergeset);
01168   if (qh ANGLEmerge)
01169     qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_compareangle);
01170   else
01171     qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_comparemerge);
01172   if (qh POSTmerging) {
01173     zadd_(Zmergesettot2, nummerges);
01174   }else {
01175     zadd_(Zmergesettot, nummerges);
01176     zmax_(Zmergesetmax, nummerges);
01177   }
01178   trace2((qh ferr, "qh_getmergeset: %d merges found\n", nummerges));
01179 } 
01180 
01181 
01182 
01183 
01184 
01185 
01186 
01187 
01188 
01189 
01190 
01191 
01192 
01193 
01194 
01195 
01196 
01197 
01198 
01199 
01200 
01201 
01202 
01203 
01204 
01205 
01206 
01207 
01208 void qh_getmergeset_initial (facetT *facetlist) {
01209   facetT *facet, *neighbor, **neighborp;
01210   ridgeT *ridge, **ridgep;
01211   int nummerges;
01212 
01213   qh visit_id++;
01214   FORALLfacet_(facetlist) {
01215     facet->visitid= qh visit_id;
01216     facet->tested= True;
01217     FOREACHneighbor_(facet) {
01218       if (neighbor->visitid != qh visit_id) {
01219         if (qh_test_appendmerge (facet, neighbor)) {
01220           FOREACHridge_(neighbor->ridges) {
01221             if (facet == otherfacet_(ridge, neighbor)) {
01222               ridge->nonconvex= True;
01223               break;    
01224             }
01225           }
01226         }
01227       }
01228     }
01229     FOREACHridge_(facet->ridges)
01230       ridge->tested= True;
01231   }
01232   nummerges= qh_setsize (qh facet_mergeset);
01233   if (qh ANGLEmerge)
01234     qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_compareangle);
01235   else
01236     qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_comparemerge);
01237   if (qh POSTmerging) {
01238     zadd_(Zmergeinittot2, nummerges);
01239   }else {
01240     zadd_(Zmergeinittot, nummerges);
01241     zmax_(Zmergeinitmax, nummerges);
01242   }
01243   trace2((qh ferr, "qh_getmergeset_initial: %d merges found\n", nummerges));
01244 } 
01245 
01246 
01247 
01248 
01249 
01250 
01251 
01252 
01253 
01254 
01255 
01256 
01257 
01258 
01259 
01260 void qh_hashridge (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex) {
01261   int hash;
01262   ridgeT *ridgeA;
01263 
01264   hash= (int)qh_gethash (hashsize, ridge->vertices, qh hull_dim-1, 0, oldvertex);
01265   while (True) {
01266     if (!(ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
01267       SETelem_(hashtable, hash)= ridge;
01268       break;
01269     }else if (ridgeA == ridge)
01270       break;
01271     if (++hash == hashsize)
01272       hash= 0;
01273   }
01274 } 
01275 
01276 
01277 
01278 
01279 
01280 
01281 
01282 
01283 
01284 
01285 
01286 
01287 
01288 
01289 
01290 
01291 
01292 
01293 
01294 
01295 
01296 
01297 
01298 
01299 
01300 
01301 
01302 
01303 ridgeT *qh_hashridge_find (setT *hashtable, int hashsize, ridgeT *ridge, 
01304               vertexT *vertex, vertexT *oldvertex, int *hashslot) {
01305   int hash;
01306   ridgeT *ridgeA;
01307 
01308   *hashslot= 0;
01309   zinc_(Zhashridge);
01310   hash= (int)qh_gethash (hashsize, ridge->vertices, qh hull_dim-1, 0, vertex);
01311   while ((ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
01312     if (ridgeA == ridge)
01313       *hashslot= -1;      
01314     else {
01315       zinc_(Zhashridgetest);
01316       if (qh_setequal_except (ridge->vertices, vertex, ridgeA->vertices, oldvertex))
01317         return ridgeA;
01318     }
01319     if (++hash == hashsize)
01320       hash= 0;
01321   }
01322   if (!*hashslot)
01323     *hashslot= hash;
01324   return NULL;
01325 } 
01326 
01327 
01328 
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 void qh_makeridges(facetT *facet) {
01355   facetT *neighbor, **neighborp;
01356   ridgeT *ridge, **ridgep;
01357   int neighbor_i, neighbor_n;
01358   boolT toporient, mergeridge= False;
01359   
01360   if (!facet->simplicial)
01361     return;
01362   trace4((qh ferr, "qh_makeridges: make ridges for f%d\n", facet->id));
01363   facet->simplicial= False;
01364   FOREACHneighbor_(facet) {
01365     if (neighbor == qh_MERGEridge)
01366       mergeridge= True;
01367     else
01368       neighbor->seen= False;
01369   }
01370   FOREACHridge_(facet->ridges)
01371     otherfacet_(ridge, facet)->seen= True;
01372   FOREACHneighbor_i_(facet) {
01373     if (neighbor == qh_MERGEridge)
01374       continue;  
01375     else if (!neighbor->seen) {  
01376       ridge= qh_newridge();
01377       ridge->vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim,
01378                                                           neighbor_i, 0);
01379       toporient= facet->toporient ^ (neighbor_i & 0x1);
01380       if (toporient) {
01381         ridge->top= facet;
01382         ridge->bottom= neighbor;
01383       }else {
01384         ridge->top= neighbor;
01385         ridge->bottom= facet;
01386       }
01387 #if 0 
01388       flip= (facet->toporient ^ neighbor->toporient)^(skip1 & 0x1) ^ (skip2 & 0x1);
01389       if (facet->toporient ^ (skip1 & 0x1) ^ flip) {
01390         ridge->top= neighbor;
01391         ridge->bottom= facet;
01392       }else {
01393         ridge->top= facet;
01394         ridge->bottom= neighbor;
01395       }
01396 #endif
01397       qh_setappend(&(facet->ridges), ridge);
01398       qh_setappend(&(neighbor->ridges), ridge);
01399     }
01400   }
01401   if (mergeridge) {
01402     while (qh_setdel (facet->neighbors, qh_MERGEridge))
01403       ; 
01404   }
01405 } 
01406 
01407 
01408 
01409 
01410 
01411 
01412 
01413 
01414 
01415 
01416 
01417 
01418 
01419 
01420 
01421 
01422 
01423 
01424 
01425 
01426 
01427 
01428 
01429 
01430 
01431 
01432 
01433 
01434 
01435 
01436 
01437 
01438 
01439 
01440 
01441 
01442 
01443 
01444 void qh_mark_dupridges(facetT *facetlist) {
01445   facetT *facet, *neighbor, **neighborp;
01446   int nummerge=0;
01447   mergeT *merge, **mergep;
01448   
01449 
01450   trace4((qh ferr, "qh_mark_dupridges: identify duplicate ridges\n"));  
01451   FORALLfacet_(facetlist) {
01452     if (facet->dupridge) {
01453       FOREACHneighbor_(facet) {
01454         if (neighbor == qh_MERGEridge) {
01455           facet->mergeridge= True;
01456           continue;
01457         }
01458         if (neighbor->dupridge
01459         && !qh_setin (neighbor->neighbors, facet)) { 
01460           qh_appendmergeset (facet, neighbor, MRGridge, NULL);
01461           facet->mergeridge2= True;
01462           facet->mergeridge= True;
01463           nummerge++;
01464         }
01465       }
01466     }
01467   }
01468   if (!nummerge)
01469     return;
01470   FORALLfacet_(facetlist) {            
01471     if (facet->mergeridge && !facet->mergeridge2)   
01472       qh_makeridges (facet);
01473   }
01474   FOREACHmerge_(qh facet_mergeset) {   
01475     if (merge->type == MRGridge) {
01476       qh_setappend (&merge->facet2->neighbors, merge->facet1);
01477       qh_makeridges (merge->facet1);   
01478     }
01479   }
01480   trace1((qh ferr, "qh_mark_dupridges: found %d duplicated ridges\n", 
01481                 nummerge));
01482 } 
01483 
01484 
01485 
01486 
01487 
01488 
01489 
01490 
01491 
01492 
01493 
01494 
01495 
01496 
01497 
01498 
01499 
01500 
01501 
01502 
01503 
01504 
01505 
01506 
01507 
01508 void qh_maydropneighbor (facetT *facet) {
01509   ridgeT *ridge, **ridgep;
01510   realT angledegen= qh_ANGLEdegen;
01511   facetT *neighbor, **neighborp;
01512 
01513   qh visit_id++;
01514   trace4((qh ferr, "qh_maydropneighbor: test f%d for no ridges to a neighbor\n",
01515           facet->id));
01516   FOREACHridge_(facet->ridges) {
01517     ridge->top->visitid= qh visit_id;
01518     ridge->bottom->visitid= qh visit_id;
01519   }
01520   FOREACHneighbor_(facet) {
01521     if (neighbor->visitid != qh visit_id) {
01522       trace0((qh ferr, "qh_maydropneighbor: facets f%d and f%d are no longer neighbors during p%d\n",
01523             facet->id, neighbor->id, qh furthest_id));
01524       zinc_(Zdropneighbor);
01525       qh_setdel (facet->neighbors, neighbor);
01526       neighborp--;  
01527       qh_setdel (neighbor->neighbors, facet);
01528       if (qh_setsize (neighbor->neighbors) < qh hull_dim) {
01529         zinc_(Zdropdegen);
01530         qh_appendmergeset (neighbor, neighbor, MRGdegen, &angledegen);
01531         trace2((qh ferr, "qh_maydropneighbors: f%d is degenerate.\n", neighbor->id));
01532       }
01533     }
01534   }
01535   if (qh_setsize (facet->neighbors) < qh hull_dim) {
01536     zinc_(Zdropdegen);
01537     qh_appendmergeset (facet, facet, MRGdegen, &angledegen);
01538     trace2((qh ferr, "qh_maydropneighbors: f%d is degenerate.\n", facet->id));
01539   }
01540 } 
01541 
01542 
01543 
01544 
01545 
01546 
01547 
01548 
01549 
01550 
01551 
01552 
01553 
01554 
01555 
01556 
01557 
01558 
01559 
01560 
01561 
01562 
01563 
01564 
01565 
01566 
01567 
01568 int qh_merge_degenredundant (void) {
01569   int size;
01570   mergeT *merge;
01571   facetT *bestneighbor, *facet1, *facet2;
01572   realT dist, mindist, maxdist;
01573   vertexT *vertex, **vertexp;
01574   int nummerges= 0;
01575   mergeType mergetype;
01576 
01577   while ((merge= (mergeT*)qh_setdellast (qh degen_mergeset))) {
01578     facet1= merge->facet1;
01579     facet2= merge->facet2;
01580     mergetype= merge->type;
01581     qh_memfree (merge, sizeof(mergeT));
01582     if (facet1->visible)
01583       continue;
01584     facet1->degenerate= False; 
01585     facet1->redundant= False; 
01586     if (qh TRACEmerge-1 == zzval_(Ztotmerge))
01587       qhmem.IStracing= qh IStracing= qh TRACElevel;
01588     if (mergetype == MRGredundant) {
01589       zinc_(Zneighbor);
01590       while (facet2->visible) {
01591         if (!facet2->f.replace) {
01592           fprintf (qh ferr, "qhull internal error (qh_merge_degenredunant): f%d redundant but f%d has no replacement\n",
01593                facet1->id, facet2->id);
01594           qh_errexit2 (qh_ERRqhull, facet1, facet2);
01595         }
01596         facet2= facet2->f.replace;
01597       }
01598       if (facet1 == facet2) {
01599         qh_degen_redundant_facet (facet1); 
01600         continue;
01601       }
01602       trace2((qh ferr, "qh_merge_degenredundant: facet f%d is contained in f%d, will merge\n",
01603             facet1->id, facet2->id));
01604       qh_mergefacet(facet1, facet2, NULL, NULL, !qh_MERGEapex);
01605       
01606       nummerges++;
01607     }else {  
01608       if (!(size= qh_setsize (facet1->neighbors))) {
01609         zinc_(Zdelfacetdup);
01610         trace2((qh ferr, "qh_merge_degenredundant: facet f%d has no neighbors.  Deleted\n", facet1->id));
01611         qh_willdelete (facet1, NULL);
01612         FOREACHvertex_(facet1->vertices) {
01613           qh_setdel (vertex->neighbors, facet1);
01614           if (!SETfirst_(vertex->neighbors)) {
01615             zinc_(Zdegenvertex);
01616             trace2((qh ferr, "qh_merge_degenredundant: deleted v%d because f%d has no neighbors\n",
01617                  vertex->id, facet1->id));
01618             vertex->deleted= True;
01619             qh_setappend (&qh del_vertices, vertex);
01620           }
01621         }
01622         nummerges++;
01623       }else if (size < qh hull_dim) {
01624         bestneighbor= qh_findbestneighbor(facet1, &dist, &mindist, &maxdist);
01625         trace2((qh ferr, "qh_merge_degenredundant: facet f%d has %d neighbors, merge into f%d dist %2.2g\n",
01626               facet1->id, size, bestneighbor->id, dist));
01627         qh_mergefacet(facet1, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
01628         nummerges++;
01629         if (qh PRINTstatistics) {
01630           zinc_(Zdegen);
01631           wadd_(Wdegentot, dist);
01632           wmax_(Wdegenmax, dist);
01633         }
01634       } 
01635     }
01636   }
01637   return nummerges;
01638 } 
01639 
01640 
01641 
01642 
01643 
01644 
01645 
01646 
01647 
01648 
01649 
01650 
01651 
01652 
01653 
01654 
01655 
01656 
01657 void qh_merge_nonconvex (facetT *facet1, facetT *facet2, mergeType mergetype) {
01658   facetT *bestfacet, *bestneighbor, *neighbor;
01659   realT dist, dist2, mindist, mindist2, maxdist, maxdist2;
01660 
01661   if (qh TRACEmerge-1 == zzval_(Ztotmerge))
01662     qhmem.IStracing= qh IStracing= qh TRACElevel;
01663   trace3((qh ferr, "qh_merge_nonconvex: merge #%d for f%d and f%d type %d\n",
01664       zzval_(Ztotmerge) + 1, facet1->id, facet2->id, mergetype));
01665   
01666   if (!facet1->newfacet) {
01667     bestfacet= facet2;   
01668     facet2= facet1;
01669     facet1= bestfacet;
01670   }else
01671     bestfacet= facet1;
01672   bestneighbor= qh_findbestneighbor(bestfacet, &dist, &mindist, &maxdist);
01673   neighbor= qh_findbestneighbor(facet2, &dist2, &mindist2, &maxdist2);
01674   if (dist < dist2) {
01675     qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
01676   }else if (qh AVOIDold && !facet2->newfacet
01677   && ((mindist >= -qh MAXcoplanar && maxdist <= qh max_outside)
01678        || dist * 1.5 < dist2)) {
01679     zinc_(Zavoidold);
01680     wadd_(Wavoidoldtot, dist);
01681     wmax_(Wavoidoldmax, dist);
01682     trace2((qh ferr, "qh_merge_nonconvex: avoid merging old facet f%d dist %2.2g.  Use f%d dist %2.2g instead\n",
01683            facet2->id, dist2, facet1->id, dist2));
01684     qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
01685   }else {
01686     qh_mergefacet(facet2, neighbor, &mindist2, &maxdist2, !qh_MERGEapex);
01687     dist= dist2;
01688   }
01689   if (qh PRINTstatistics) {
01690     if (mergetype == MRGanglecoplanar) {
01691       zinc_(Zacoplanar);
01692       wadd_(Wacoplanartot, dist);
01693       wmax_(Wacoplanarmax, dist);
01694     }else if (mergetype == MRGconcave) {
01695       zinc_(Zconcave);
01696       wadd_(Wconcavetot, dist);
01697       wmax_(Wconcavemax, dist);
01698     }else { 
01699       zinc_(Zcoplanar);
01700       wadd_(Wcoplanartot, dist);
01701       wmax_(Wcoplanarmax, dist);
01702     }
01703   }
01704 } 
01705 
01706 
01707 
01708 
01709 
01710 
01711 
01712 
01713 
01714 
01715 
01716 
01717 
01718 
01719 
01720 
01721 
01722 
01723 
01724 
01725 
01726 
01727 
01728 
01729 
01730 
01731 
01732 
01733 
01734 
01735 void qh_mergecycle (facetT *samecycle, facetT *newfacet) {
01736   int traceonce= False, tracerestore= 0;
01737   vertexT *apex;
01738 #ifndef qh_NOtrace
01739   facetT *same;
01740 #endif
01741 
01742   if (!qh VERTEXneighbors)
01743     qh_vertexneighbors();
01744   zzinc_(Ztotmerge);
01745   if (qh REPORTfreq2 && qh POSTmerging) {
01746     if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
01747       qh_tracemerging();
01748   }
01749 #ifndef qh_NOtrace
01750   if (qh TRACEmerge == zzval_(Ztotmerge))
01751     qhmem.IStracing= qh IStracing= qh TRACElevel;
01752   trace2((qh ferr, "qh_mergecycle: merge #%d for facets from cycle f%d into coplanar horizon f%d\n", 
01753         zzval_(Ztotmerge), samecycle->id, newfacet->id));
01754   if (newfacet == qh tracefacet) {
01755     tracerestore= qh IStracing;
01756     qh IStracing= 4;
01757     fprintf (qh ferr, "qh_mergecycle: ========= trace merge %d of samecycle %d into trace f%d, furthest is p%d\n",
01758                zzval_(Ztotmerge), samecycle->id, newfacet->id,  qh furthest_id);
01759     traceonce= True;
01760   }
01761   if (qh IStracing >=4) {
01762     fprintf (qh ferr, "  same cycle:");
01763     FORALLsame_cycle_(samecycle)
01764       fprintf(qh ferr, " f%d", same->id);
01765     fprintf (qh ferr, "\n");
01766   }
01767   if (qh IStracing >=4)
01768     qh_errprint ("MERGING CYCLE", samecycle, newfacet, NULL, NULL);
01769 #endif 
01770   apex= SETfirstt_(samecycle->vertices, vertexT);
01771   qh_makeridges (newfacet);
01772   qh_mergecycle_neighbors (samecycle, newfacet);
01773   qh_mergecycle_ridges (samecycle, newfacet);
01774   qh_mergecycle_vneighbors (samecycle, newfacet);
01775   if (SETfirstt_(newfacet->vertices, vertexT) != apex) 
01776     qh_setaddnth (&newfacet->vertices, 0, apex);  
01777   if (!newfacet->newfacet)
01778     qh_newvertices (newfacet->vertices);
01779   qh_mergecycle_facets (samecycle, newfacet);
01780   qh_tracemerge (samecycle, newfacet);
01781   
01782   if (traceonce) {
01783     fprintf (qh ferr, "qh_mergecycle: end of trace facet\n");
01784     qh IStracing= tracerestore;
01785   }
01786 } 
01787 
01788 
01789 
01790 
01791 
01792 
01793 
01794 
01795 
01796 
01797 
01798 
01799 
01800 
01801 
01802 
01803 
01804 
01805 
01806 
01807 
01808 
01809 
01810 
01811 
01812 
01813 
01814 
01815 
01816 
01817 void qh_mergecycle_all (facetT *facetlist, boolT *wasmerge) {
01818   facetT *facet, *same, *prev, *horizon;
01819   facetT *samecycle= NULL, *nextfacet, *nextsame;
01820   vertexT *apex, *vertex, **vertexp;
01821   int cycles=0, total=0, facets, nummerge;
01822 
01823   trace2((qh ferr, "qh_mergecycle_all: begin\n"));
01824   for (facet= facetlist; facet && (nextfacet= facet->next); facet= nextfacet) {
01825     if (facet->normal)
01826       continue;
01827     if (!facet->mergehorizon) {
01828       fprintf (qh ferr, "qh_mergecycle_all: f%d without normal\n", facet->id);
01829       qh_errexit (qh_ERRqhull, facet, NULL);
01830     }
01831     horizon= SETfirstt_(facet->neighbors, facetT);
01832     if (facet->f.samecycle == facet) {
01833       zinc_(Zonehorizon);  
01834       
01835       apex= SETfirstt_(facet->vertices, vertexT);
01836       FOREACHvertex_(facet->vertices) {
01837         if (vertex != apex)
01838           vertex->delridge= True;
01839       }
01840       horizon->f.newcycle= NULL;
01841       qh_mergefacet (facet, horizon, NULL, NULL, qh_MERGEapex);
01842     }else {
01843       samecycle= facet;
01844       facets= 0;
01845       prev= facet;
01846       for (same= facet->f.samecycle; same;  
01847            same= (same == facet ? NULL :nextsame)) { 
01848         nextsame= same->f.samecycle;
01849         if (same->cycledone || same->visible)
01850           qh_infiniteloop (same);
01851         same->cycledone= True;
01852         if (same->normal) { 
01853           prev->f.samecycle= same->f.samecycle; 
01854           same->f.samecycle= NULL;
01855         }else {
01856           prev= same;
01857           facets++;
01858         }
01859       }
01860       while (nextfacet && nextfacet->cycledone)  
01861         nextfacet= nextfacet->next;
01862       horizon->f.newcycle= NULL;
01863       qh_mergecycle (samecycle, horizon);
01864       nummerge= horizon->nummerge + facets;
01865       if (nummerge > qh_MAXnummerge) 
01866         horizon->nummerge= qh_MAXnummerge;
01867       else
01868         horizon->nummerge= nummerge;
01869       zzinc_(Zcyclehorizon);
01870       total += facets;
01871       zzadd_(Zcyclefacettot, facets);
01872       zmax_(Zcyclefacetmax, facets);
01873     }
01874     cycles++;
01875   }
01876   if (cycles)
01877     *wasmerge= True;
01878   trace1((qh ferr, "qh_mergecycle_all: merged %d same cycles or facets into coplanar horizons\n", cycles));
01879 } 
01880 
01881 
01882 
01883 
01884 
01885 
01886 
01887 
01888 
01889 
01890 
01891 
01892 
01893 
01894 
01895 
01896 
01897 
01898 
01899 
01900 
01901 
01902 
01903 
01904 
01905 void qh_mergecycle_facets (facetT *samecycle, facetT *newfacet) {
01906   facetT *same, *next;
01907   
01908   trace4((qh ferr, "qh_mergecycle_facets: make newfacet new and samecycle deleted\n"));  
01909   qh_removefacet(newfacet);  
01910   qh_appendfacet(newfacet);
01911   newfacet->newfacet= True;
01912   newfacet->simplicial= False;
01913   newfacet->newmerge= True;
01914   
01915   for (same= samecycle->f.samecycle; same; same= (same == samecycle ?  NULL : next)) {
01916     next= same->f.samecycle;  
01917     qh_willdelete (same, newfacet);
01918   }
01919   if (newfacet->center 
01920       && qh_setsize (newfacet->vertices) <= qh hull_dim + qh_MAXnewcentrum) {
01921     qh_memfree (newfacet->center, qh normal_size);
01922     newfacet->center= NULL;
01923   }
01924   trace3((qh ferr, "qh_mergecycle_facets: merged facets from cycle f%d into f%d\n", 
01925              samecycle->id, newfacet->id));
01926 } 
01927 
01928 
01929 
01930 
01931 
01932 
01933 
01934 
01935 
01936 
01937 
01938 
01939 
01940 
01941 
01942 
01943 
01944 
01945 
01946 
01947 
01948 
01949 
01950 
01951 
01952 
01953 
01954 
01955 
01956 
01957 
01958 
01959 
01960 
01961 
01962 
01963 void qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet) {
01964   facetT *same, *neighbor, **neighborp;
01965   int delneighbors= 0, newneighbors= 0;
01966   unsigned int samevisitid;
01967   ridgeT *ridge, **ridgep;
01968 
01969   samevisitid= ++qh visit_id;
01970   FORALLsame_cycle_(samecycle) {
01971     if (same->visitid == samevisitid || same->visible)
01972       qh_infiniteloop (samecycle);
01973     same->visitid= samevisitid;
01974   }
01975   newfacet->visitid= ++qh visit_id;
01976   trace4((qh ferr, "qh_mergecycle_neighbors: delete shared neighbors from newfacet\n"));  
01977   FOREACHneighbor_(newfacet) {
01978     if (neighbor->visitid == samevisitid) {
01979       SETref_(neighbor)= NULL;  
01980       delneighbors++;
01981     }else
01982       neighbor->visitid= qh visit_id;
01983   }
01984   qh_setcompact (newfacet->neighbors);
01985 
01986   trace4((qh ferr, "qh_mergecycle_neighbors: update neighbors\n"));  
01987   FORALLsame_cycle_(samecycle) {
01988     FOREACHneighbor_(same) {
01989       if (neighbor->visitid == samevisitid)
01990         continue;
01991       if (neighbor->simplicial) {
01992         if (neighbor->visitid != qh visit_id) {
01993           qh_setappend (&newfacet->neighbors, neighbor);
01994           qh_setreplace (neighbor->neighbors, same, newfacet);
01995           newneighbors++;
01996           neighbor->visitid= qh visit_id;
01997           FOREACHridge_(neighbor->ridges) { 
01998             if (ridge->top == same) {
01999               ridge->top= newfacet;
02000               break;
02001             }else if (ridge->bottom == same) {
02002               ridge->bottom= newfacet;
02003               break;
02004             }
02005           }
02006         }else {
02007           qh_makeridges (neighbor);
02008           qh_setdel (neighbor->neighbors, same);
02009           
02010         }
02011       }else { 
02012         qh_setdel (neighbor->neighbors, same);
02013         if (neighbor->visitid != qh visit_id) {
02014           qh_setappend (&neighbor->neighbors, newfacet);
02015           qh_setappend (&newfacet->neighbors, neighbor);
02016           neighbor->visitid= qh visit_id;
02017           newneighbors++;
02018         } 
02019       }
02020     }
02021   }
02022   trace2((qh ferr, "qh_mergecycle_neighbors: deleted %d neighbors and added %d\n", 
02023              delneighbors, newneighbors));
02024 } 
02025 
02026 
02027 
02028 
02029 
02030 
02031 
02032 
02033 
02034 
02035 
02036 
02037 
02038 
02039 
02040 
02041 
02042 
02043 
02044 
02045 
02046 
02047 
02048 
02049 
02050 
02051 
02052 
02053 
02054 
02055 
02056 
02057 
02058 
02059 
02060 void qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet) {
02061   facetT *same, *neighbor= NULL;
02062   int numold=0, numnew=0;
02063   int neighbor_i, neighbor_n;
02064   unsigned int samevisitid;
02065   ridgeT *ridge, **ridgep;
02066   boolT toporient;
02067   void **freelistp; 
02068 
02069   trace4((qh ferr, "qh_mergecycle_ridges: delete shared ridges from newfacet\n"));  
02070   samevisitid= qh visit_id -1;
02071   FOREACHridge_(newfacet->ridges) {
02072     neighbor= otherfacet_(ridge, newfacet);
02073     if (neighbor->visitid == samevisitid)
02074       SETref_(ridge)= NULL;   
02075   }
02076   qh_setcompact (newfacet->ridges);
02077   
02078   trace4((qh ferr, "qh_mergecycle_ridges: add ridges to newfacet\n"));  
02079   FORALLsame_cycle_(samecycle) {
02080     FOREACHridge_(same->ridges) {
02081       if (ridge->top == same) {
02082         ridge->top= newfacet;
02083         neighbor= ridge->bottom;
02084       }else if (ridge->bottom == same) {
02085         ridge->bottom= newfacet;
02086         neighbor= ridge->top;
02087       }else if (ridge->top == newfacet || ridge->bottom == newfacet) {
02088         qh_setappend (&newfacet->ridges, ridge);
02089         numold++;  
02090         continue;  
02091       }else {
02092         fprintf (qh ferr, "qhull internal error (qh_mergecycle_ridges): bad ridge r%d\n", ridge->id);
02093         qh_errexit (qh_ERRqhull, NULL, ridge);
02094       }
02095       if (neighbor == newfacet) {
02096         qh_setfree(&(ridge->vertices)); 
02097         qh_memfree_(ridge, sizeof(ridgeT), freelistp);
02098         numold++;
02099       }else if (neighbor->visitid == samevisitid) {
02100         qh_setdel (neighbor->ridges, ridge);
02101         qh_setfree(&(ridge->vertices)); 
02102         qh_memfree_(ridge, sizeof(ridgeT), freelistp);
02103         numold++;
02104       }else {
02105         qh_setappend (&newfacet->ridges, ridge);
02106         numold++;
02107       }
02108     }
02109     if (same->ridges)
02110       qh_settruncate (same->ridges, 0);
02111     if (!same->simplicial)
02112       continue;
02113     FOREACHneighbor_i_(same) {       
02114       if (neighbor->visitid != samevisitid && neighbor->simplicial) {
02115         ridge= qh_newridge();
02116         ridge->vertices= qh_setnew_delnthsorted (same->vertices, qh hull_dim,
02117                                                           neighbor_i, 0);
02118         toporient= same->toporient ^ (neighbor_i & 0x1);
02119         if (toporient) {
02120           ridge->top= newfacet;
02121           ridge->bottom= neighbor;
02122         }else {
02123           ridge->top= neighbor;
02124           ridge->bottom= newfacet;
02125         }
02126         qh_setappend(&(newfacet->ridges), ridge);
02127         qh_setappend(&(neighbor->ridges), ridge);
02128         numnew++;
02129       }
02130     }
02131   }
02132 
02133   trace2((qh ferr, "qh_mergecycle_ridges: found %d old ridges and %d new ones\n", 
02134              numold, numnew));
02135 } 
02136 
02137 
02138 
02139 
02140 
02141 
02142 
02143 
02144 
02145 
02146 
02147 
02148 
02149 
02150 
02151 
02152 
02153 
02154 
02155 
02156 
02157 
02158 
02159 
02160 
02161 
02162 void qh_mergecycle_vneighbors (facetT *samecycle, facetT *newfacet) {
02163   facetT *neighbor, **neighborp;
02164   unsigned int mergeid;
02165   vertexT *vertex, **vertexp, *apex;
02166   setT *vertices;
02167   
02168   trace4((qh ferr, "qh_mergecycle_vneighbors: update vertex neighbors for newfacet\n"));  
02169   mergeid= qh visit_id - 1;
02170   newfacet->visitid= mergeid;
02171   vertices= qh_basevertices (samecycle); 
02172   apex= SETfirstt_(samecycle->vertices, vertexT);
02173   qh_setappend (&vertices, apex);
02174   FOREACHvertex_(vertices) {
02175     vertex->delridge= True;
02176     FOREACHneighbor_(vertex) {
02177       if (neighbor->visitid == mergeid)
02178         SETref_(neighbor)= NULL;
02179     }
02180     qh_setcompact (vertex->neighbors);
02181     qh_setappend (&vertex->neighbors, newfacet);
02182     if (!SETsecond_(vertex->neighbors)) {
02183       zinc_(Zcyclevertex);
02184       trace2((qh ferr, "qh_mergecycle_vneighbors: deleted v%d when merging cycle f%d into f%d\n",
02185         vertex->id, samecycle->id, newfacet->id));
02186       qh_setdelsorted (newfacet->vertices, vertex);
02187       vertex->deleted= True;
02188       qh_setappend (&qh del_vertices, vertex);
02189     }
02190   }
02191   qh_settempfree (&vertices);
02192   trace3((qh ferr, "qh_mergecycle_vneighbors: merged vertices from cycle f%d into f%d\n", 
02193              samecycle->id, newfacet->id));
02194 } 
02195 
02196 
02197 
02198 
02199 
02200 
02201 
02202 
02203 
02204 
02205 
02206 
02207 
02208 
02209 
02210 
02211 
02212 
02213 
02214 
02215 
02216 
02217 
02218 
02219 
02220 
02221 
02222 
02223 
02224 
02225 
02226 
02227 
02228 
02229 
02230 
02231 
02232 
02233 
02234 
02235 
02236 
02237 
02238 
02239 
02240 
02241 
02242 
02243 
02244 
02245 
02246 
02247 void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex) {
02248   boolT traceonce= False;
02249   vertexT *vertex, **vertexp;
02250   int tracerestore=0, nummerge;
02251 
02252   zzinc_(Ztotmerge);
02253   if (qh REPORTfreq2 && qh POSTmerging) {
02254     if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
02255       qh_tracemerging();
02256   }
02257 #ifndef qh_NOtrace
02258   if (qh build_cnt >= qh RERUN) {
02259     if (mindist && (-*mindist > qh TRACEdist || *maxdist > qh TRACEdist)) {
02260       tracerestore= 0;
02261       qh IStracing= qh TRACElevel;
02262       traceonce= True;
02263       fprintf (qh ferr, "qh_mergefacet: ========= trace wide merge #%d (%2.2g) for f%d into f%d, last point was p%d\n", zzval_(Ztotmerge),
02264              fmax_(-*mindist, *maxdist), facet1->id, facet2->id, qh furthest_id);
02265     }else if (facet1 == qh tracefacet || facet2 == qh tracefacet) {
02266       tracerestore= qh IStracing;
02267       qh IStracing= 4;
02268       traceonce= True;
02269       fprintf (qh ferr, "qh_mergefacet: ========= trace merge #%d involving f%d, furthest is p%d\n",
02270                  zzval_(Ztotmerge), qh tracefacet_id,  qh furthest_id);
02271     }
02272   }
02273   if (qh IStracing >= 2) {
02274     realT mergemin= -2;
02275     realT mergemax= -2;
02276     
02277     if (mindist) {
02278       mergemin= *mindist;
02279       mergemax= *maxdist;
02280     }
02281     fprintf (qh ferr, "qh_mergefacet: #%d merge f%d into f%d, mindist= %2.2g, maxdist= %2.2g\n", 
02282     zzval_(Ztotmerge), facet1->id, facet2->id, mergemin, mergemax);
02283   }
02284 #endif 
02285   if (facet1 == facet2 || facet1->visible || facet2->visible) {
02286     fprintf (qh ferr, "qhull internal error (qh_mergefacet): either f%d and f%d are the same or one is a visible facet\n",
02287              facet1->id, facet2->id);
02288     qh_errexit2 (qh_ERRqhull, facet1, facet2);
02289   }
02290   if (qh num_facets - qh num_visible <= qh hull_dim + 1) {
02291     fprintf(qh ferr, "\n\
02292 qhull precision error: Only %d facets remain.  Can not merge another\n\
02293 pair.  The convexity constraints may be too strong.  Reduce the\n\
02294 magnitude of 'Cn' or increase the magnitude of 'An'.  For example,\n\
02295 try 'C-0.001' instead of 'C-0.1' or 'A-0.999' instead of 'A-0.9'.\n", 
02296                  qh hull_dim+1);
02297     if (qh hull_dim >= 5 && !qh MERGEexact)
02298       fprintf(qh ferr, "Option 'Qx' may avoid this problem.\n");
02299     qh_errexit(qh_ERRinput, NULL, NULL);
02300   }
02301   if (!qh VERTEXneighbors)
02302     qh_vertexneighbors();
02303   qh_makeridges(facet1);
02304   qh_makeridges(facet2);
02305   if (qh IStracing >=4)
02306     qh_errprint ("MERGING", facet1, facet2, NULL, NULL);
02307   if (mindist) {
02308     maximize_(qh max_outside, *maxdist);
02309     maximize_(qh max_vertex, *maxdist);
02310 #if qh_MAXoutside
02311     maximize_(facet2->maxoutside, *maxdist);
02312 #endif
02313     minimize_(qh min_vertex, *mindist);
02314     if (!facet2->keepcentrum 
02315     && (*maxdist > qh WIDEfacet || *mindist < -qh WIDEfacet)) {
02316       facet2->keepcentrum= True;
02317       zinc_(Zwidefacet);
02318     }
02319   }
02320   nummerge= facet1->nummerge + facet2->nummerge + 1;
02321   if (nummerge >= qh_MAXnummerge) 
02322     facet2->nummerge= qh_MAXnummerge;
02323   else
02324     facet2->nummerge= nummerge;
02325   facet2->newmerge= True;
02326   facet2->dupridge= False;
02327   qh_updatetested  (facet1, facet2);
02328   if (qh hull_dim > 2 && qh_setsize (facet1->vertices) == qh hull_dim)
02329     qh_mergesimplex (facet1, facet2, mergeapex);
02330   else {
02331     qh vertex_visit++;
02332     FOREACHvertex_(facet2->vertices)
02333       vertex->visitid= qh vertex_visit;
02334     if (qh hull_dim == 2) 
02335       qh_mergefacet2d(facet1, facet2);
02336     else {
02337       qh_mergeneighbors(facet1, facet2);
02338       qh_mergevertices(facet1->vertices, &facet2->vertices);
02339     }
02340     qh_mergeridges(facet1, facet2);
02341     qh_mergevertex_neighbors(facet1, facet2);
02342     if (!facet2->newfacet)
02343       qh_newvertices (facet2->vertices);
02344   }
02345   if (!mergeapex)
02346     qh_degen_redundant_neighbors (facet2, facet1);
02347   if (facet2->coplanar || !facet2->newfacet) {
02348     zinc_(Zmergeintohorizon);
02349   }else if (!facet1->newfacet && facet2->newfacet) {
02350     zinc_(Zmergehorizon);
02351   }else {
02352     zinc_(Zmergenew);
02353   }
02354   qh_willdelete (facet1, facet2);
02355   qh_removefacet(facet2);  
02356   qh_appendfacet(facet2);
02357   facet2->newfacet= True;
02358   facet2->tested= False;
02359   qh_tracemerge (facet1, facet2);
02360   if (traceonce) {
02361     fprintf (qh ferr, "qh_mergefacet: end of wide tracing\n");
02362     qh IStracing= tracerestore;
02363   }
02364 } 
02365 
02366 
02367 
02368 
02369 
02370 
02371 
02372 
02373 
02374 
02375 
02376 
02377 
02378 
02379 
02380 
02381 
02382 
02383 
02384 
02385 
02386 
02387 
02388 
02389 
02390 void qh_mergefacet2d (facetT *facet1, facetT *facet2) {
02391   vertexT *vertex1A, *vertex1B, *vertex2A, *vertex2B, *vertexA, *vertexB;
02392   facetT *neighbor1A, *neighbor1B, *neighbor2A, *neighbor2B, *neighborA, *neighborB;
02393 
02394   vertex1A= SETfirstt_(facet1->vertices, vertexT);
02395   vertex1B= SETsecondt_(facet1->vertices, vertexT);
02396   vertex2A= SETfirstt_(facet2->vertices, vertexT);
02397   vertex2B= SETsecondt_(facet2->vertices, vertexT);
02398   neighbor1A= SETfirstt_(facet1->neighbors, facetT);
02399   neighbor1B= SETsecondt_(facet1->neighbors, facetT);
02400   neighbor2A= SETfirstt_(facet2->neighbors, facetT);
02401   neighbor2B= SETsecondt_(facet2->neighbors, facetT);
02402   if (vertex1A == vertex2A) {
02403     vertexA= vertex1B;
02404     vertexB= vertex2B;
02405     neighborA= neighbor2A;
02406     neighborB= neighbor1A;
02407   }else if (vertex1A == vertex2B) {
02408     vertexA= vertex1B;
02409     vertexB= vertex2A;
02410     neighborA= neighbor2B;
02411     neighborB= neighbor1A;
02412   }else if (vertex1B == vertex2A) {
02413     vertexA= vertex1A;
02414     vertexB= vertex2B;
02415     neighborA= neighbor2A;
02416     neighborB= neighbor1B;
02417   }else { 
02418     vertexA= vertex1A;
02419     vertexB= vertex2A;
02420     neighborA= neighbor2B;
02421     neighborB= neighbor1B;
02422   }
02423   
02424   if (vertexA->id > vertexB->id) {
02425     SETfirst_(facet2->vertices)= vertexA;
02426     SETsecond_(facet2->vertices)= vertexB;
02427     if (vertexB == vertex2A)
02428       facet2->toporient= !facet2->toporient;
02429     SETfirst_(facet2->neighbors)= neighborA;
02430     SETsecond_(facet2->neighbors)= neighborB;
02431   }else {
02432     SETfirst_(facet2->vertices)= vertexB;
02433     SETsecond_(facet2->vertices)= vertexA;
02434     if (vertexB == vertex2B)
02435       facet2->toporient= !facet2->toporient;
02436     SETfirst_(facet2->neighbors)= neighborB;
02437     SETsecond_(facet2->neighbors)= neighborA;
02438   }
02439   qh_makeridges (neighborB);
02440   qh_setreplace(neighborB->neighbors, facet1, facet2);
02441   trace4((qh ferr, "qh_mergefacet2d: merged v%d and neighbor f%d of f%d into f%d\n",
02442        vertexA->id, neighborB->id, facet1->id, facet2->id));
02443 } 
02444 
02445 
02446 
02447 
02448 
02449 
02450 
02451 
02452 
02453 
02454 
02455 
02456 
02457 
02458 
02459 
02460 
02461 
02462 
02463 
02464 
02465 void qh_mergeneighbors(facetT *facet1, facetT *facet2) {
02466   facetT *neighbor, **neighborp;
02467 
02468   trace4((qh ferr, "qh_mergeneighbors: merge neighbors of f%d and f%d\n",
02469           facet1->id, facet2->id));
02470   qh visit_id++;
02471   FOREACHneighbor_(facet2) {
02472     neighbor->visitid= qh visit_id;
02473   }
02474   FOREACHneighbor_(facet1) {
02475     if (neighbor->visitid == qh visit_id) {
02476       if (neighbor->simplicial)    
02477         qh_makeridges (neighbor);
02478       if (SETfirstt_(neighbor->neighbors, facetT) != facet1) 
02479         qh_setdel (neighbor->neighbors, facet1);
02480       else {
02481         qh_setdel(neighbor->neighbors, facet2);
02482         qh_setreplace(neighbor->neighbors, facet1, facet2);
02483       }
02484     }else if (neighbor != facet2) {
02485       qh_setappend(&(facet2->neighbors), neighbor);
02486       qh_setreplace(neighbor->neighbors, facet1, facet2);
02487     }
02488   }
02489   qh_setdel(facet1->neighbors, facet2);  
02490   qh_setdel(facet2->neighbors, facet1);
02491 } 
02492 
02493 
02494 
02495 
02496 
02497 
02498 
02499 
02500 
02501 
02502 
02503 
02504 
02505 
02506 
02507 
02508 
02509 
02510 
02511 
02512 
02513 void qh_mergeridges(facetT *facet1, facetT *facet2) {
02514   ridgeT *ridge, **ridgep;
02515   vertexT *vertex, **vertexp;
02516 
02517   trace4((qh ferr, "qh_mergeridges: merge ridges of f%d and f%d\n",
02518           facet1->id, facet2->id));
02519   FOREACHridge_(facet2->ridges) {
02520     if ((ridge->top == facet1) || (ridge->bottom == facet1)) {
02521       FOREACHvertex_(ridge->vertices)
02522         vertex->delridge= True;
02523       qh_delridge(ridge);  
02524       ridgep--; 
02525     }
02526   }
02527   FOREACHridge_(facet1->ridges) {
02528     if (ridge->top == facet1)
02529       ridge->top= facet2;
02530     else
02531       ridge->bottom= facet2;
02532     qh_setappend(&(facet2->ridges), ridge);
02533   }
02534 } 
02535 
02536 
02537 
02538 
02539 
02540 
02541 
02542 
02543 
02544 
02545 
02546 
02547 
02548 
02549 
02550 
02551 
02552 
02553 
02554 
02555 
02556 
02557 
02558 
02559 
02560 
02561 
02562 
02563 
02564 
02565 
02566 
02567 
02568 
02569 
02570 
02571 
02572 
02573 
02574 
02575 
02576 
02577 
02578 
02579 
02580 void qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex) {
02581   vertexT *vertex, **vertexp, *apex;
02582   ridgeT *ridge, **ridgep;
02583   boolT issubset= False;
02584   int vertex_i= -1, vertex_n;
02585   facetT *neighbor, **neighborp, *otherfacet;
02586 
02587   if (mergeapex) {
02588     if (!facet2->newfacet)
02589       qh_newvertices (facet2->vertices);  
02590     apex= SETfirstt_(facet1->vertices, vertexT);
02591     if (SETfirstt_(facet2->vertices, vertexT) != apex) 
02592       qh_setaddnth (&facet2->vertices, 0, apex);  
02593     else
02594       issubset= True;
02595   }else {
02596     zinc_(Zmergesimplex);
02597     FOREACHvertex_(facet1->vertices)
02598       vertex->seen= False;
02599     FOREACHridge_(facet1->ridges) {
02600       if (otherfacet_(ridge, facet1) == facet2) {
02601         FOREACHvertex_(ridge->vertices) {
02602           vertex->seen= True;
02603           vertex->delridge= True;
02604         }
02605         break;
02606       }
02607     }
02608     FOREACHvertex_(facet1->vertices) {
02609       if (!vertex->seen)
02610         break;  
02611     }
02612     apex= vertex;
02613     trace4((qh ferr, "qh_mergesimplex: merge apex v%d of f%d into facet f%d\n",
02614           apex->id, facet1->id, facet2->id));
02615     FOREACHvertex_i_(facet2->vertices) {
02616       if (vertex->id < apex->id) {
02617         break;
02618       }else if (vertex->id == apex->id) {
02619         issubset= True;
02620         break;
02621       }
02622     }
02623     if (!issubset)
02624       qh_setaddnth (&facet2->vertices, vertex_i, apex);
02625     if (!facet2->newfacet)
02626       qh_newvertices (facet2->vertices);
02627     else if (!apex->newlist) {
02628       qh_removevertex (apex);
02629       qh_appendvertex (apex);
02630     }
02631   }
02632   trace4((qh ferr, "qh_mergesimplex: update vertex neighbors of f%d\n",
02633           facet1->id));
02634   FOREACHvertex_(facet1->vertices) {
02635     if (vertex == apex && !issubset)
02636       qh_setreplace (vertex->neighbors, facet1, facet2);
02637     else {
02638       qh_setdel (vertex->neighbors, facet1);
02639       if (!SETsecond_(vertex->neighbors))
02640         qh_mergevertex_del (vertex, facet1, facet2);
02641     }
02642   }
02643   trace4((qh ferr, "qh_mergesimplex: merge ridges and neighbors of f%d into f%d\n",
02644           facet1->id, facet2->id));
02645   qh visit_id++;
02646   FOREACHneighbor_(facet2)
02647     neighbor->visitid= qh visit_id;
02648   FOREACHridge_(facet1->ridges) {
02649     otherfacet= otherfacet_(ridge, facet1);
02650     if (otherfacet == facet2) {
02651       qh_setdel (facet2->ridges, ridge);
02652       qh_setfree(&(ridge->vertices)); 
02653       qh_memfree (ridge, sizeof(ridgeT));
02654       qh_setdel (facet2->neighbors, facet1);
02655     }else {
02656       qh_setappend (&facet2->ridges, ridge);
02657       if (otherfacet->visitid != qh visit_id) {
02658         qh_setappend (&facet2->neighbors, otherfacet);
02659         qh_setreplace (otherfacet->neighbors, facet1, facet2);
02660         otherfacet->visitid= qh visit_id;
02661       }else {
02662         if (otherfacet->simplicial)    
02663           qh_makeridges (otherfacet);
02664         if (SETfirstt_(otherfacet->neighbors, facetT) != facet1)
02665           qh_setdel (otherfacet->neighbors, facet1);
02666         else {   
02667           qh_setdel(otherfacet->neighbors, facet2);
02668           qh_setreplace(otherfacet->neighbors, facet1, facet2);
02669         }
02670       }
02671       if (ridge->top == facet1) 
02672         ridge->top= facet2;
02673       else 
02674         ridge->bottom= facet2;
02675     }
02676   }
02677   SETfirst_(facet1->ridges)= NULL; 
02678   trace3((qh ferr, "qh_mergesimplex: merged simplex f%d apex v%d into facet f%d\n",
02679           facet1->id, getid_(apex), facet2->id));
02680 } 
02681 
02682 
02683 
02684 
02685 
02686 
02687 
02688 
02689 
02690 
02691 
02692 void qh_mergevertex_del (vertexT *vertex, facetT *facet1, facetT *facet2) {
02693 
02694   zinc_(Zmergevertex);
02695   trace2((qh ferr, "qh_mergevertex_del: deleted v%d when merging f%d into f%d\n",
02696           vertex->id, facet1->id, facet2->id));
02697   qh_setdelsorted (facet2->vertices, vertex);
02698   vertex->deleted= True;
02699   qh_setappend (&qh del_vertices, vertex);
02700 } 
02701 
02702 
02703 
02704 
02705 
02706 
02707 
02708 
02709 
02710 
02711 
02712 
02713 
02714 
02715 
02716 
02717 
02718 void qh_mergevertex_neighbors(facetT *facet1, facetT *facet2) {
02719   vertexT *vertex, **vertexp;
02720 
02721   trace4((qh ferr, "qh_mergevertex_neighbors: merge vertex neighbors of f%d and f%d\n",
02722           facet1->id, facet2->id));
02723   if (qh tracevertex) {
02724     fprintf (qh ferr, "qh_mergevertex_neighbors: of f%d and f%d at furthest p%d f0= %p\n",
02725              facet1->id, facet2->id, qh furthest_id, qh tracevertex->neighbors->e[0].p);
02726     qh_errprint ("TRACE", NULL, NULL, NULL, qh tracevertex);
02727   }
02728   FOREACHvertex_(facet1->vertices) {
02729     if (vertex->visitid != qh vertex_visit) 
02730       qh_setreplace(vertex->neighbors, facet1, facet2);
02731     else {
02732       qh_setdel(vertex->neighbors, facet1);
02733       if (!SETsecond_(vertex->neighbors))
02734         qh_mergevertex_del (vertex, facet1, facet2);
02735     }
02736   }
02737   if (qh tracevertex) 
02738     qh_errprint ("TRACE", NULL, NULL, NULL, qh tracevertex);
02739 } 
02740 
02741 
02742 
02743 
02744 
02745 
02746 
02747 
02748 
02749 
02750 
02751 
02752 
02753 
02754 
02755 
02756 void qh_mergevertices(setT *vertices1, setT **vertices2) {
02757   int newsize= qh_setsize(vertices1)+qh_setsize(*vertices2) - qh hull_dim + 1;
02758   setT *mergedvertices;
02759   vertexT *vertex, **vertexp, **vertex2= SETaddr_(*vertices2, vertexT);
02760 
02761   mergedvertices= qh_settemp (newsize);
02762   FOREACHvertex_(vertices1) {
02763     if (!*vertex2 || vertex->id > (*vertex2)->id)
02764       qh_setappend (&mergedvertices, vertex);
02765     else {
02766       while (*vertex2 && (*vertex2)->id > vertex->id)
02767         qh_setappend (&mergedvertices, *vertex2++);
02768       if (!*vertex2 || (*vertex2)->id < vertex->id)
02769         qh_setappend (&mergedvertices, vertex);
02770       else
02771         qh_setappend (&mergedvertices, *vertex2++);
02772     }
02773   }
02774   while (*vertex2)
02775     qh_setappend (&mergedvertices, *vertex2++);
02776   if (newsize < qh_setsize (mergedvertices)) {
02777     fprintf (qh ferr, "qhull internal error (qh_mergevertices): facets did not share a ridge\n");
02778     qh_errexit (qh_ERRqhull, NULL, NULL);
02779   }
02780   qh_setfree(vertices2);
02781   *vertices2= mergedvertices;
02782   qh_settemppop ();
02783 } 
02784 
02785 
02786 
02787 
02788 
02789 
02790 
02791 
02792 
02793 
02794 
02795 
02796 
02797 
02798 
02799 
02800 
02801 
02802 
02803 
02804 
02805 
02806 
02807 
02808 
02809 setT *qh_neighbor_intersections (vertexT *vertex) {
02810   facetT *neighbor, **neighborp, *neighborA, *neighborB;
02811   setT *intersect;
02812   int neighbor_i, neighbor_n;
02813 
02814   FOREACHneighbor_(vertex) {
02815     if (neighbor->simplicial)
02816       return NULL;
02817   }
02818   neighborA= SETfirstt_(vertex->neighbors, facetT);
02819   neighborB= SETsecondt_(vertex->neighbors, facetT);
02820   zinc_(Zintersectnum);
02821   if (!neighborA)
02822     return NULL;
02823   if (!neighborB)
02824     intersect= qh_setcopy (neighborA->vertices, 0);
02825   else
02826     intersect= qh_vertexintersect_new (neighborA->vertices, neighborB->vertices);
02827   qh_settemppush (intersect);
02828   qh_setdelsorted (intersect, vertex);
02829   FOREACHneighbor_i_(vertex) {
02830     if (neighbor_i >= 2) {
02831       zinc_(Zintersectnum);
02832       qh_vertexintersect (&intersect, neighbor->vertices);
02833       if (!SETfirst_(intersect)) {
02834         zinc_(Zintersectfail);
02835         qh_settempfree (&intersect);
02836         return NULL;
02837       }
02838     }
02839   }
02840   trace3((qh ferr, "qh_neighbor_intersections: %d vertices in neighbor intersection of v%d\n", 
02841           qh_setsize (intersect), vertex->id));
02842   return intersect;
02843 } 
02844 
02845 
02846 
02847 
02848 
02849 
02850 
02851 
02852 
02853 
02854 
02855 void qh_newvertices (setT *vertices) {
02856   vertexT *vertex, **vertexp;
02857 
02858   FOREACHvertex_(vertices) {
02859     if (!vertex->newlist) {
02860       qh_removevertex (vertex);
02861       qh_appendvertex (vertex);
02862     }
02863   }
02864 } 
02865 
02866 
02867 
02868 
02869 
02870 
02871 
02872 
02873 
02874 
02875 
02876 
02877 
02878 
02879 
02880 
02881 
02882 
02883 
02884 
02885 
02886 
02887 
02888 
02889 
02890 
02891 
02892 
02893 boolT qh_reducevertices (void) {
02894   int numshare=0, numrename= 0;
02895   boolT degenredun= False;
02896   facetT *newfacet;
02897   vertexT *vertex, **vertexp;
02898 
02899   if (qh hull_dim == 2) 
02900     return False;
02901   if (qh_merge_degenredundant())
02902     degenredun= True;
02903  LABELrestart:
02904   FORALLnew_facets {
02905     if (newfacet->newmerge) { 
02906       if (!qh MERGEvertices)
02907         newfacet->newmerge= False;
02908       qh_remove_extravertices (newfacet);
02909     }
02910   }
02911   if (!qh MERGEvertices)
02912     return False;
02913   FORALLnew_facets {
02914     if (newfacet->newmerge) {
02915       newfacet->newmerge= False;
02916       FOREACHvertex_(newfacet->vertices) {
02917         if (vertex->delridge) {
02918           if (qh_rename_sharedvertex (vertex, newfacet)) {
02919             numshare++;
02920             vertexp--; 
02921           }
02922         }
02923       }
02924     }
02925   }
02926   FORALLvertex_(qh newvertex_list) {
02927     if (vertex->delridge && !vertex->deleted) {
02928       vertex->delridge= False;
02929       if (qh hull_dim >= 4 && qh_redundant_vertex (vertex)) {
02930         numrename++;
02931         if (qh_merge_degenredundant()) {
02932           degenredun= True;
02933           goto LABELrestart;
02934         }
02935       }
02936     }
02937   }
02938   trace1((qh ferr, "qh_reducevertices: renamed %d shared vertices and %d redundant vertices. Degen? %d\n",
02939           numshare, numrename, degenredun));
02940   return degenredun;
02941 } 
02942       
02943 
02944 
02945 
02946 
02947 
02948 
02949 
02950 
02951 
02952 
02953 
02954 
02955 
02956 
02957 
02958 
02959 
02960 
02961 
02962 
02963 
02964 
02965 vertexT *qh_redundant_vertex (vertexT *vertex) {
02966   vertexT *newvertex= NULL;
02967   setT *vertices, *ridges;
02968 
02969   trace3((qh ferr, "qh_redundant_vertex: check if v%d can be renamed\n", vertex->id));  
02970   if ((vertices= qh_neighbor_intersections (vertex))) {
02971     ridges= qh_vertexridges (vertex);
02972     if ((newvertex= qh_find_newvertex (vertex, vertices, ridges)))
02973       qh_renamevertex (vertex, newvertex, ridges, NULL, NULL);
02974     qh_settempfree (&ridges);
02975     qh_settempfree (&vertices);
02976   }
02977   return newvertex;
02978 } 
02979 
02980 
02981 
02982 
02983 
02984 
02985 
02986 
02987 
02988 
02989 
02990 
02991 
02992 
02993 
02994 
02995 
02996 
02997 boolT qh_remove_extravertices (facetT *facet) {
02998   ridgeT *ridge, **ridgep;
02999   vertexT *vertex, **vertexp;
03000   boolT foundrem= False;
03001 
03002   trace4((qh ferr, "qh_remove_extravertices: test f%d for extra vertices\n",
03003           facet->id));
03004   FOREACHvertex_(facet->vertices)
03005     vertex->seen= False;
03006   FOREACHridge_(facet->ridges) { 
03007     FOREACHvertex_(ridge->vertices)
03008       vertex->seen= True;
03009   }
03010   FOREACHvertex_(facet->vertices) {
03011     if (!vertex->seen) {
03012       foundrem= True;
03013       zinc_(Zremvertex);
03014       qh_setdelsorted (facet->vertices, vertex);
03015       qh_setdel (vertex->neighbors, facet);
03016       if (!qh_setsize (vertex->neighbors)) {
03017         vertex->deleted= True;
03018         qh_setappend (&qh del_vertices, vertex);
03019         zinc_(Zremvertexdel);
03020         trace2((qh ferr, "qh_remove_extravertices: v%d deleted because it's lost all ridges\n", vertex->id));
03021       }else
03022         trace3((qh ferr, "qh_remove_extravertices: v%d removed from f%d because it's lost all ridges\n", vertex->id, facet->id));
03023       vertexp--; 
03024     }
03025   }
03026   return foundrem;
03027 } 
03028 
03029 
03030 
03031 
03032 
03033 
03034 
03035 
03036 
03037 
03038 
03039 
03040 
03041 
03042 
03043 
03044 
03045 
03046 
03047 
03048 
03049 
03050 
03051 
03052 
03053 
03054 
03055 
03056 vertexT *qh_rename_sharedvertex (vertexT *vertex, facetT *facet) {
03057   facetT *neighbor, **neighborp, *neighborA= NULL;
03058   setT *vertices, *ridges;
03059   vertexT *newvertex;
03060 
03061   if (qh_setsize (vertex->neighbors) == 2) {
03062     neighborA= SETfirstt_(vertex->neighbors, facetT);
03063     if (neighborA == facet)
03064       neighborA= SETsecondt_(vertex->neighbors, facetT);
03065   }else if (qh hull_dim == 3)
03066     return NULL;
03067   else {
03068     qh visit_id++;
03069     FOREACHneighbor_(facet)
03070       neighbor->visitid= qh visit_id;
03071     FOREACHneighbor_(vertex) {
03072       if (neighbor->visitid == qh visit_id) {
03073         if (neighborA)
03074           return NULL;
03075         neighborA= neighbor;
03076       }
03077     }
03078     if (!neighborA) {
03079       fprintf (qh ferr, "qhull internal error (qh_rename_sharedvertex): v%d's neighbors not in f%d\n",
03080         vertex->id, facet->id);
03081       qh_errprint ("ERRONEOUS", facet, NULL, NULL, vertex);
03082       qh_errexit (qh_ERRqhull, NULL, NULL);
03083     }
03084   }
03085   
03086   ridges= qh_settemp (qh TEMPsize);
03087   neighborA->visitid= ++qh visit_id;
03088   qh_vertexridges_facet (vertex, facet, &ridges);
03089   trace2((qh ferr, "qh_rename_sharedvertex: p%d (v%d) is shared by f%d (%d ridges) and f%d\n",
03090     qh_pointid(vertex->point), vertex->id, facet->id, qh_setsize (ridges), neighborA->id));
03091   zinc_(Zintersectnum);
03092   vertices= qh_vertexintersect_new (facet->vertices, neighborA->vertices);
03093   qh_setdel (vertices, vertex);
03094   qh_settemppush (vertices);
03095   if ((newvertex= qh_find_newvertex (vertex, vertices, ridges))) 
03096     qh_renamevertex (vertex, newvertex, ridges, facet, neighborA);
03097   qh_settempfree (&vertices);
03098   qh_settempfree (&ridges);
03099   return newvertex;
03100 } 
03101 
03102 
03103 
03104 
03105 
03106 
03107 
03108 
03109 
03110 
03111 
03112 
03113 
03114 
03115 
03116 
03117 
03118 
03119 void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex) {
03120   int nth= 0, oldnth;
03121   facetT *temp;
03122   vertexT *vertex, **vertexp;
03123 
03124   oldnth= qh_setindex (ridge->vertices, oldvertex);
03125   qh_setdelnthsorted (ridge->vertices, oldnth);
03126   FOREACHvertex_(ridge->vertices) {
03127     if (vertex == newvertex) {
03128       zinc_(Zdelridge);
03129       if (ridge->nonconvex) 
03130         qh_copynonconvex (ridge);
03131       qh_delridge (ridge);
03132       trace2((qh ferr, "qh_renameridgevertex: ridge r%d deleted.  It contained both v%d and v%d\n",
03133         ridge->id, oldvertex->id, newvertex->id));
03134       return;
03135     }
03136     if (vertex->id < newvertex->id)
03137       break;
03138     nth++;
03139   }
03140   qh_setaddnth(&ridge->vertices, nth, newvertex);
03141   if (abs(oldnth - nth)%2) {
03142     trace3((qh ferr, "qh_renameridgevertex: swapped the top and bottom of ridge r%d\n", 
03143             ridge->id));
03144     temp= ridge->top;
03145     ridge->top= ridge->bottom;
03146     ridge->bottom= temp;
03147   }
03148 } 
03149 
03150 
03151 
03152 
03153 
03154 
03155 
03156 
03157 
03158 
03159 
03160 
03161 
03162 
03163 
03164 
03165 
03166 
03167 
03168 
03169 
03170 
03171 
03172 
03173 
03174 
03175 
03176 
03177 
03178 
03179 
03180 
03181 void qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges, facetT *oldfacet, facetT *neighborA) {
03182   facetT *neighbor, **neighborp;
03183   ridgeT *ridge, **ridgep;
03184   boolT istrace= False;
03185 
03186   if (qh IStracing >= 2 || oldvertex->id == qh tracevertex_id ||
03187         newvertex->id == qh tracevertex_id)
03188     istrace= True;
03189   FOREACHridge_(ridges) 
03190     qh_renameridgevertex (ridge, oldvertex, newvertex);
03191   if (!oldfacet) {
03192     zinc_(Zrenameall);
03193     if (istrace)
03194       fprintf (qh ferr, "qh_renamevertex: renamed v%d to v%d in several facets\n",
03195                oldvertex->id, newvertex->id);
03196     FOREACHneighbor_(oldvertex) {
03197       qh_maydropneighbor (neighbor);
03198       qh_setdelsorted (neighbor->vertices, oldvertex);
03199       if (qh_remove_extravertices (neighbor))
03200         neighborp--; 
03201     }
03202     if (!oldvertex->deleted) {
03203       oldvertex->deleted= True;
03204       qh_setappend (&qh del_vertices, oldvertex);
03205     }
03206   }else if (qh_setsize (oldvertex->neighbors) == 2) {
03207     zinc_(Zrenameshare);
03208     if (istrace)
03209       fprintf (qh ferr, "qh_renamevertex: renamed v%d to v%d in oldfacet f%d\n", 
03210                oldvertex->id, newvertex->id, oldfacet->id);
03211     FOREACHneighbor_(oldvertex)
03212       qh_setdelsorted (neighbor->vertices, oldvertex);
03213     oldvertex->deleted= True;
03214     qh_setappend (&qh del_vertices, oldvertex);
03215   }else {
03216     zinc_(Zrenamepinch);
03217     if (istrace || qh IStracing)
03218       fprintf (qh ferr, "qh_renamevertex: renamed pinched v%d to v%d between f%d and f%d\n", 
03219                oldvertex->id, newvertex->id, oldfacet->id, neighborA->id);
03220     qh_setdelsorted (oldfacet->vertices, oldvertex);
03221     qh_setdel (oldvertex->neighbors, oldfacet);
03222     qh_remove_extravertices (neighborA);
03223   }
03224 } 
03225 
03226 
03227 
03228 
03229 
03230 
03231 
03232 
03233 
03234 
03235 
03236 
03237 
03238 
03239 
03240 
03241 
03242 
03243 
03244 
03245 
03246 
03247 
03248 
03249 
03250 
03251 
03252 
03253 
03254 
03255 
03256 
03257 
03258 
03259 
03260 
03261 boolT qh_test_appendmerge (facetT *facet, facetT *neighbor) {
03262   realT dist, dist2= -REALmax, angle= -REALmax;
03263   boolT isconcave= False, iscoplanar= False, okangle= False;
03264 
03265   if (qh SKIPconvex && !qh POSTmerging)
03266     return False;
03267   if ((!qh MERGEexact || qh POSTmerging) && qh cos_max < REALmax/2) {
03268     angle= qh_getangle(facet->normal, neighbor->normal);
03269     zinc_(Zangletests);
03270     if (angle > qh cos_max) {
03271       zinc_(Zcoplanarangle);
03272       qh_appendmergeset(facet, neighbor, MRGanglecoplanar, &angle);
03273       trace2((qh ferr, "qh_test_appendmerge: coplanar angle %4.4g between f%d and f%d\n",
03274          angle, facet->id, neighbor->id));
03275       return True;
03276     }else
03277       okangle= True;
03278   }
03279   if (!facet->center)
03280     facet->center= qh_getcentrum (facet);
03281   zzinc_(Zcentrumtests);
03282   qh_distplane(facet->center, neighbor, &dist);
03283   if (dist > qh centrum_radius)
03284     isconcave= True;
03285   else {
03286     if (dist > -qh centrum_radius)
03287       iscoplanar= True;
03288     if (!neighbor->center)
03289       neighbor->center= qh_getcentrum (neighbor);
03290     zzinc_(Zcentrumtests);
03291     qh_distplane(neighbor->center, facet, &dist2);
03292     if (dist2 > qh centrum_radius)
03293       isconcave= True;
03294     else if (!iscoplanar && dist2 > -qh centrum_radius)
03295       iscoplanar= True;
03296   }
03297   if (!isconcave && (!iscoplanar || (qh MERGEexact && !qh POSTmerging)))
03298     return False;
03299   if (!okangle && qh ANGLEmerge) {
03300     angle= qh_getangle(facet->normal, neighbor->normal);
03301     zinc_(Zangletests);
03302   }
03303   if (isconcave) {
03304     zinc_(Zconcaveridge);
03305     if (qh ANGLEmerge)
03306       angle += qh_ANGLEconcave + 0.5;
03307     qh_appendmergeset(facet, neighbor, MRGconcave, &angle);
03308     trace0((qh ferr, "qh_test_appendmerge: concave f%d to f%d dist %4.4g and reverse dist %4.4g angle %4.4g during p%d\n",
03309            facet->id, neighbor->id, dist, dist2, angle, qh furthest_id));
03310   }else  {
03311     zinc_(Zcoplanarcentrum);
03312     qh_appendmergeset(facet, neighbor, MRGcoplanar, &angle);
03313     trace2((qh ferr, "qh_test_appendmerge: coplanar f%d to f%d dist %4.4g, reverse dist %4.4g angle %4.4g\n",
03314               facet->id, neighbor->id, dist, dist2, angle));
03315   }
03316   return True;
03317 } 
03318 
03319 
03320 
03321 
03322 
03323 
03324 
03325 
03326 
03327 
03328 
03329 
03330 
03331 
03332 
03333 
03334 
03335 
03336 
03337 
03338 
03339 
03340 
03341 
03342 
03343 
03344 boolT qh_test_vneighbors (void ) {
03345   facetT *newfacet, *neighbor, **neighborp;
03346   vertexT *vertex, **vertexp;
03347   int nummerges= 0;
03348 
03349   trace1((qh ferr, "qh_test_vneighbors: testing vertex neighbors for convexity\n"));
03350   if (!qh VERTEXneighbors)
03351     qh_vertexneighbors();
03352   FORALLnew_facets 
03353     newfacet->seen= False;
03354   FORALLnew_facets {
03355     newfacet->seen= True;
03356     newfacet->visitid= qh visit_id++;
03357     FOREACHneighbor_(newfacet)
03358       newfacet->visitid= qh visit_id;
03359     FOREACHvertex_(newfacet->vertices) {
03360       FOREACHneighbor_(vertex) {
03361         if (neighbor->seen || neighbor->visitid == qh visit_id)
03362           continue;
03363         if (qh_test_appendmerge (newfacet, neighbor))
03364           nummerges++;
03365       }
03366     }
03367   }
03368   zadd_(Ztestvneighbor, nummerges);
03369   trace1((qh ferr, "qh_test_vneighbors: found %d non-convex, vertex neighbors\n",
03370            nummerges));
03371   return (nummerges > 0);    
03372 } 
03373 
03374 
03375 
03376 
03377 
03378 
03379 
03380 void qh_tracemerge (facetT *facet1, facetT *facet2) {
03381   boolT waserror= False;
03382 
03383 #ifndef qh_NOtrace
03384   if (qh IStracing >= 4) 
03385     qh_errprint ("MERGED", facet2, NULL, NULL, NULL);
03386   if (facet2 == qh tracefacet || (qh tracevertex && qh tracevertex->newlist)) {
03387     fprintf (qh ferr, "qh_tracemerge: trace facet and vertex after merge of f%d and f%d, furthest p%d\n", facet1->id, facet2->id, qh furthest_id);
03388     if (facet2 != qh tracefacet)
03389       qh_errprint ("TRACE", qh tracefacet, 
03390         (qh tracevertex && qh tracevertex->neighbors) ? 
03391            SETfirstt_(qh tracevertex->neighbors, facetT) : NULL,
03392         NULL, qh tracevertex);      
03393   }
03394   if (qh tracevertex) {
03395     if (qh tracevertex->deleted)
03396       fprintf (qh ferr, "qh_tracemerge: trace vertex deleted at furthest p%d\n",
03397             qh furthest_id);
03398     else
03399       qh_checkvertex (qh tracevertex);
03400   }
03401   if (qh tracefacet) {
03402     qh_checkfacet (qh tracefacet, True, &waserror);
03403     if (waserror)
03404       qh_errexit (qh_ERRqhull, qh tracefacet, NULL);
03405   }
03406 #endif 
03407   if (qh CHECKfrequently || qh IStracing >= 4) { 
03408     qh_checkfacet (facet2, True, &waserror);
03409     if (waserror)
03410       qh_errexit(qh_ERRqhull, NULL, NULL);
03411   }
03412 } 
03413 
03414 
03415 
03416 
03417 
03418 
03419 
03420 
03421 
03422 
03423 
03424 
03425 
03426 
03427 
03428 
03429 void qh_tracemerging (void) {
03430   realT cpu;
03431   int total;
03432   time_t timedata;
03433   struct tm *tp;
03434 
03435   qh mergereport= zzval_(Ztotmerge);
03436   time (&timedata);
03437   tp= localtime (&timedata);
03438   cpu= qh_CPUclock;
03439   cpu /= qh_SECticks;
03440   total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
03441   fprintf (qh ferr, "\n\
03442 At %d:%d:%d & %2.5g CPU secs, qhull has merged %d facets.  The hull\n\
03443   contains %d facets and %d vertices.\n",
03444       tp->tm_hour, tp->tm_min, tp->tm_sec, cpu,
03445       total, qh num_facets - qh num_visible,
03446       qh num_vertices-qh_setsize (qh del_vertices));
03447 } 
03448 
03449 
03450 
03451 
03452 
03453 
03454 
03455 
03456 
03457 
03458 
03459 
03460 
03461 
03462 
03463 
03464 
03465 
03466 
03467 
03468 
03469 
03470 
03471 void qh_updatetested (facetT *facet1, facetT *facet2) {
03472   ridgeT *ridge, **ridgep;
03473   int size;
03474   
03475   facet2->tested= False;
03476   FOREACHridge_(facet1->ridges)
03477     ridge->tested= False;
03478   if (!facet2->center)
03479     return;
03480   size= qh_setsize (facet2->vertices);
03481   if (!facet2->keepcentrum) {
03482     if (size > qh hull_dim + qh_MAXnewcentrum) {
03483       facet2->keepcentrum= True;
03484       zinc_(Zwidevertices);
03485     }
03486   }else if (size <= qh hull_dim + qh_MAXnewcentrum) {
03487     
03488     if (size == qh hull_dim || qh POSTmerging)
03489       facet2->keepcentrum= False; 
03490   }
03491   if (!facet2->keepcentrum) {
03492     qh_memfree (facet2->center, qh normal_size);
03493     facet2->center= NULL;
03494     FOREACHridge_(facet2->ridges)
03495       ridge->tested= False;
03496   }
03497 } 
03498 
03499 
03500 
03501 
03502 
03503 
03504 
03505 
03506 
03507 
03508 
03509 
03510 
03511 
03512 
03513 
03514 setT *qh_vertexridges (vertexT *vertex) {
03515   facetT *neighbor, **neighborp;
03516   setT *ridges= qh_settemp (qh TEMPsize);
03517   int size;
03518 
03519   qh visit_id++;
03520   FOREACHneighbor_(vertex)
03521     neighbor->visitid= qh visit_id;
03522   FOREACHneighbor_(vertex) {
03523     if (*neighborp)   
03524       qh_vertexridges_facet (vertex, neighbor, &ridges);
03525   }
03526   if (qh PRINTstatistics || qh IStracing) {
03527     size= qh_setsize (ridges);
03528     zinc_(Zvertexridge);
03529     zadd_(Zvertexridgetot, size);
03530     zmax_(Zvertexridgemax, size);
03531     trace3((qh ferr, "qh_vertexridges: found %d ridges for v%d\n",
03532              size, vertex->id));
03533   }
03534   return ridges;
03535 } 
03536 
03537 
03538 
03539 
03540 
03541 
03542 
03543 
03544 
03545 
03546 
03547 
03548 
03549 
03550 
03551 
03552 
03553 
03554 
03555 void qh_vertexridges_facet (vertexT *vertex, facetT *facet, setT **ridges) {
03556   ridgeT *ridge, **ridgep;
03557   facetT *neighbor;
03558 
03559   FOREACHridge_(facet->ridges) {
03560     neighbor= otherfacet_(ridge, facet);
03561     if (neighbor->visitid == qh visit_id 
03562     && qh_setin (ridge->vertices, vertex))
03563       qh_setappend (ridges, ridge);
03564   }
03565   facet->visitid= qh visit_id-1;
03566 } 
03567 
03568 
03569 
03570 
03571 
03572 
03573 
03574 
03575 
03576 
03577 
03578 void qh_willdelete (facetT *facet, facetT *replace) {
03579 
03580   qh_removefacet(facet);
03581   qh_prependfacet (facet, &qh visible_list);
03582   qh num_visible++;
03583   facet->visible= True;
03584   facet->f.replace= replace;
03585 } 
03586 
03587 #else 
03588 void qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle) {
03589 }
03590 void qh_postmerge (char *reason, realT maxcentrum, realT maxangle, 
03591                       boolT vneighbors) {
03592 }
03593 boolT qh_checkzero (boolT testall) {
03594    }
03595 #endif 
03596