00001
00002
00003
00004
00005
00006
00007
00008
00009 #//! QhullFacet -- Qhull's facet structure, facetT, as a C++ class
00010
00011 #include "QhullError.h"
00012 #include "QhullSet.h"
00013 #include "QhullPoint.h"
00014 #include "QhullPointSet.h"
00015 #include "QhullRidge.h"
00016 #include "QhullFacet.h"
00017 #include "QhullFacetSet.h"
00018 #include "QhullVertex.h"
00019
00020 #include <ostream>
00021
00022 using std::endl;
00023 using std::string;
00024 using std::vector;
00025 using std::ostream;
00026
00027 #ifdef _MSC_VER // Microsoft Visual C++ -- warning level 4
00028 #pragma warning( disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
00029 #pragma warning( disable : 4996) // function was declared deprecated(strcpy, localtime, etc.)
00030 #endif
00031
00032 namespace orgQhull {
00033
00034 #//class statics
00035 facetT QhullFacet::
00036 s_empty_facet= {0,0,0,0,{0},
00037 0,0,0,0,0,
00038 0,0,0,0,0,
00039 0,0,0,0,0,
00040 0,0,0,0,0,
00041 0,0,0,0,0,
00042 0,0,0,0,0,
00043 0,0,0,0};
00044
00045 #//GetSet
00046
00047 int QhullFacet::
00048 dimension() const
00049 {
00050 if(qh_facet->ridges){
00051 setT *s= qh_facet->ridges;
00052 ridgeT *r= reinterpret_cast<ridgeT *>(SETfirst_(s));
00053 return r ? QhullSetBase::count(r->vertices)+1 : 0;
00054 }else{
00055 return QhullSetBase::count(qh_facet->vertices);
00056 }
00057 }
00058
00064 QhullPoint QhullFacet::
00065 getCenter(int qhRunId, qh_PRINT printFormat)
00066 {
00067 UsingLibQhull q(qhRunId);
00068
00069 if(qh CENTERtype==qh_ASvoronoi){
00070 if(!qh_facet->normal || !qh_facet->upperdelaunay || !qh ATinfinity){
00071 if(!qh_facet->center){
00072 int exitCode = setjmp(qh errexit);
00073 if(!exitCode){
00074 qh_facet->center= qh_facetcenter(qh_facet->vertices);
00075 }
00076 q.maybeThrowQhullMessage(exitCode);
00077 }
00078 return QhullPoint(qh hull_dim-1, qh_facet->center);
00079 }
00080 }else if(qh CENTERtype==qh_AScentrum){
00081 volatile int numCoords= qh hull_dim;
00082 if(printFormat==qh_PRINTtriangles && qh DELAUNAY){
00083 numCoords--;
00084 }
00085 if(!qh_facet->center){
00086 int exitCode = setjmp(qh errexit);
00087 if(!exitCode){
00088 qh_facet->center= qh_getcentrum(getFacetT());
00089 }
00090 q.maybeThrowQhullMessage(exitCode);
00091 }
00092 return QhullPoint(numCoords, qh_facet->center);
00093 }
00094 return QhullPoint();
00095 }
00096
00099 QhullHyperplane QhullFacet::
00100 innerplane(int qhRunId) const{
00101 UsingLibQhull q(qhRunId);
00102 realT inner;
00103
00104 qh_outerinner(const_cast<facetT *>(getFacetT()), NULL, &inner);
00105 QhullHyperplane h= hyperplane();
00106 h.setOffset(h.offset()-inner);
00107 return h;
00108 }
00109
00112 QhullHyperplane QhullFacet::
00113 outerplane(int qhRunId) const{
00114 UsingLibQhull q(qhRunId);
00115 realT outer;
00116
00117 qh_outerinner(const_cast<facetT *>(getFacetT()), &outer, NULL);
00118 QhullHyperplane h= hyperplane();
00119 h.setOffset(h.offset()-outer);
00120 return h;
00121 }
00122
00125 QhullFacet QhullFacet::
00126 tricoplanarOwner() const
00127 {
00128 if(qh_facet->tricoplanar){
00129 if(qh_facet->isarea){
00130 throw QhullError(10018, "Qhull error: facetArea() or qh_getarea() previously called. triCoplanarOwner() is not available.");
00131 }
00132 return qh_facet->f.triowner;
00133 }
00134 return 0;
00135 }
00136
00137 QhullPoint QhullFacet::
00138 voronoiVertex(int qhRunId)
00139 {
00140 if(
00141 #if qh_QHpointer
00142 !qh_qh ||
00143 #endif
00144 qh CENTERtype!=qh_ASvoronoi){
00145 throw QhullError(10052, "Error: QhullFacet.voronoiVertex() requires option 'v' (qh_ASvoronoi)");
00146 }
00147 return getCenter(qhRunId);
00148 }
00149
00150 #//Value
00151
00153 double QhullFacet::
00154 facetArea(int qhRunId)
00155 {
00156 if(!qh_facet->isarea){
00157 UsingLibQhull q(qhRunId);
00158 int exitCode = setjmp(qh errexit);
00159 if(!exitCode){
00160 qh_facet->f.area= qh_facetarea(qh_facet);
00161 qh_facet->isarea= True;
00162 }
00163 q.maybeThrowQhullMessage(exitCode);
00164 }
00165 return qh_facet->f.area;
00166 }
00167
00168 #//Foreach
00169
00170 QhullPointSet QhullFacet::
00171 coplanarPoints() const
00172 {
00173 return QhullPointSet(dimension(), qh_facet->coplanarset);
00174 }
00175
00176 QhullFacetSet QhullFacet::
00177 neighborFacets() const
00178 {
00179 return QhullFacetSet(qh_facet->neighbors);
00180 }
00181
00182 QhullPointSet QhullFacet::
00183 outsidePoints() const
00184 {
00185 return QhullPointSet(dimension(), qh_facet->outsideset);
00186 }
00187
00188 QhullRidgeSet QhullFacet::
00189 ridges() const
00190 {
00191 return QhullRidgeSet(qh_facet->ridges);
00192 }
00193
00194 QhullVertexSet QhullFacet::
00195 vertices() const
00196 {
00197 return QhullVertexSet(qh_facet->vertices);
00198 }
00199
00200
00201 }
00202
00203 #//operator<<
00204
00205 using std::ostream;
00206
00207 using orgQhull::QhullFacet;
00208 using orgQhull::QhullFacetSet;
00209 using orgQhull::QhullPoint;
00210 using orgQhull::QhullPointSet;
00211 using orgQhull::QhullRidge;
00212 using orgQhull::QhullRidgeSet;
00213 using orgQhull::QhullSetBase;
00214 using orgQhull::QhullVertexSet;
00215 using orgQhull::UsingLibQhull;
00216
00217 ostream &
00218 operator<<(ostream &os, const QhullFacet::PrintFacet &pr)
00219 {
00220 QhullFacet f= *pr.facet;
00221 if(f.getFacetT()==0){
00222 os << " NULLfacet" << endl;
00223 return os;
00224 }
00225 if(f.getFacetT()==qh_MERGEridge){
00226 os << " MERGEridge" << endl;
00227 return os;
00228 }
00229 if(f.getFacetT()==qh_DUPLICATEridge){
00230 os << " DUPLICATEridge" << endl;
00231 return os;
00232 }
00233 os << f.printHeader(pr.run_id);
00234 if(!f.ridges().isEmpty()){
00235 os << f.printRidges(pr.run_id);
00236 }
00237 return os;
00238 }
00239
00243 ostream &
00244 operator<<(ostream &os, const QhullFacet::PrintCenter &pr)
00245 {
00246 facetT *f= pr.facet->getFacetT();
00247 if(qh CENTERtype!=qh_ASvoronoi && qh CENTERtype!=qh_AScentrum){
00248 return os;
00249 }
00250 if (pr.message){
00251 os << pr.message;
00252 }
00253 int numCoords;
00254 if(qh CENTERtype==qh_ASvoronoi){
00255 numCoords= qh hull_dim-1;
00256 if(!f->normal || !f->upperdelaunay || !qh ATinfinity){
00257 if(!f->center){
00258 f->center= qh_facetcenter(f->vertices);
00259 }
00260 for(int k=0; k<numCoords; k++){
00261 os << f->center[k] << " ";
00262 }
00263 }else{
00264 for(int k=0; k<numCoords; k++){
00265 os << qh_INFINITE << " ";
00266 }
00267 }
00268 }else{
00269 numCoords= qh hull_dim;
00270 if(pr.print_format==qh_PRINTtriangles && qh DELAUNAY){
00271 numCoords--;
00272 }
00273 if(!f->center){
00274 f->center= qh_getcentrum(f);
00275 }
00276 for(int k=0; k<numCoords; k++){
00277 os << f->center[k] << " ";
00278 }
00279 }
00280 if(pr.print_format==qh_PRINTgeom && numCoords==2){
00281 os << " 0";
00282 }
00283 os << endl;
00284 return os;
00285 }
00286
00288 ostream &
00289 operator<<(ostream &os, const QhullFacet::PrintFlags &p)
00290 {
00291 const facetT *f= p.facet->getFacetT();
00292 if(p.message){
00293 os << p.message;
00294 }
00295
00296 os << (p.facet->isTopOrient() ? " top" : " bottom");
00297 if(p.facet->isSimplicial()){
00298 os << " simplicial";
00299 }
00300 if(p.facet->isTriCoplanar()){
00301 os << " tricoplanar";
00302 }
00303 if(p.facet->isUpperDelaunay()){
00304 os << " upperDelaunay";
00305 }
00306 if(f->visible){
00307 os << " visible";
00308 }
00309 if(f->newfacet){
00310 os << " new";
00311 }
00312 if(f->tested){
00313 os << " tested";
00314 }
00315 if(!f->good){
00316 os << " notG";
00317 }
00318 if(f->seen){
00319 os << " seen";
00320 }
00321 if(f->coplanar){
00322 os << " coplanar";
00323 }
00324 if(f->mergehorizon){
00325 os << " mergehorizon";
00326 }
00327 if(f->keepcentrum){
00328 os << " keepcentrum";
00329 }
00330 if(f->dupridge){
00331 os << " dupridge";
00332 }
00333 if(f->mergeridge && !f->mergeridge2){
00334 os << " mergeridge1";
00335 }
00336 if(f->mergeridge2){
00337 os << " mergeridge2";
00338 }
00339 if(f->newmerge){
00340 os << " newmerge";
00341 }
00342 if(f->flipped){
00343 os << " flipped";
00344 }
00345 if(f->notfurthest){
00346 os << " notfurthest";
00347 }
00348 if(f->degenerate){
00349 os << " degenerate";
00350 }
00351 if(f->redundant){
00352 os << " redundant";
00353 }
00354 os << endl;
00355 return os;
00356 }
00357
00359 ostream &
00360 operator<<(ostream &os, const QhullFacet::PrintHeader &pr)
00361 {
00362 QhullFacet facet= *pr.facet;
00363 facetT *f= facet.getFacetT();
00364 os << "- f" << facet.id() << endl;
00365 os << facet.printFlags(" - flags:");
00366 if(f->isarea){
00367 os << " - area: " << f->f.area << endl;
00368 }else if(qh NEWfacets && f->visible && f->f.replace){
00369 os << " - replacement: f" << f->f.replace->id << endl;
00370 }else if(f->newfacet){
00371 if(f->f.samecycle && f->f.samecycle != f){
00372 os << " - shares same visible/horizon as f" << f->f.samecycle->id << endl;
00373 }
00374 }else if(f->tricoplanar ){
00375 if(f->f.triowner){
00376 os << " - owner of normal & centrum is facet f" << f->f.triowner->id << endl;
00377 }
00378 }else if(f->f.newcycle){
00379 os << " - was horizon to f" << f->f.newcycle->id << endl;
00380 }
00381 if(f->nummerge){
00382 os << " - merges: " << f->nummerge << endl;
00383 }
00384 os << facet.hyperplane().print(" - normal: ", "\n - offset: ");
00385 if(qh CENTERtype==qh_ASvoronoi || f->center){
00386 os << facet.printCenter(pr.run_id, qh_PRINTfacets, " - center: ");
00387 }
00388 #if qh_MAXoutside
00389 if(f->maxoutside > qh DISTround){
00390 os << " - maxoutside: " << f->maxoutside << endl;
00391 }
00392 #endif
00393 QhullPointSet ps= facet.outsidePoints();
00394 if(!ps.isEmpty()){
00395 QhullPoint furthest= ps.last();
00396 if (ps.size() < 6) {
00397 os << " - outside set(furthest p" << furthest.id(pr.run_id) << "):" << endl;
00398 for(QhullPointSet::iterator i=ps.begin(); i!=ps.end(); ++i){
00399 QhullPoint p= *i;
00400 os << p.print(pr.run_id, " ");
00401 }
00402 }else if(ps.size()<21){
00403 os << ps.print(pr.run_id, " - outside set:");
00404 }else{
00405 os << " - outside set: " << ps.size() << " points.";
00406 os << furthest.print(pr.run_id, " Furthest");
00407 }
00408 #if !qh_COMPUTEfurthest
00409 os << " - furthest distance= " << f->furthestdist << endl;
00410 #endif
00411 }
00412 QhullPointSet cs= facet.coplanarPoints();
00413 if(!cs.isEmpty()){
00414 QhullPoint furthest= cs.last();
00415 if (cs.size() < 6) {
00416 os << " - coplanar set(furthest p" << furthest.id(pr.run_id) << "):" << endl;
00417 for(QhullPointSet::iterator i=cs.begin(); i!=cs.end(); ++i){
00418 QhullPoint p= *i;
00419 os << p.print(pr.run_id, " ");
00420 }
00421 }else if(cs.size()<21){
00422 os << cs.print(pr.run_id, " - coplanar set:");
00423 }else{
00424 os << " - coplanar set: " << cs.size() << " points.";
00425 os << furthest.print(pr.run_id, " Furthest");
00426 }
00427 zinc_(Zdistio);
00428 double d= facet.distance(furthest);
00429 os << " furthest distance= " << d << endl;
00430 }
00431 QhullVertexSet vs= facet.vertices();
00432 if(!vs.isEmpty()){
00433 os << vs.print(pr.run_id, " - vertices:");
00434 }
00435 QhullFacetSet fs= facet.neighborFacets();
00436 fs.selectAll();
00437 if(!fs.isEmpty()){
00438 os << fs.printIdentifiers(" - neighboring facets:");
00439 }
00440 return os;
00441 }
00442
00443
00446 ostream &
00447 operator<<(ostream &os, const QhullFacet::PrintRidges &pr)
00448 {
00449 const QhullFacet facet= *pr.facet;
00450 facetT *f= facet.getFacetT();
00451 QhullRidgeSet rs= facet.ridges();
00452 if(!rs.isEmpty()){
00453 if(pr.run_id!=UsingLibQhull::NOqhRunId){
00454 UsingLibQhull q(pr.run_id);
00455
00456 if(f->visible && qh NEWfacets){
00457 os << " - ridges(ids may be garbage):";
00458 for(QhullRidgeSet::iterator i=rs.begin(); i!=rs.end(); ++i){
00459 QhullRidge r= *i;
00460 os << " r" << r.id();
00461 }
00462 os << endl;
00463 }else{
00464 os << " - ridges:" << endl;
00465 }
00466 }else{
00467 os << " - ridges:" << endl;
00468 }
00469
00470
00471 for(QhullRidgeSet::iterator i=rs.begin(); i!=rs.end(); ++i){
00472 QhullRidge r= *i;
00473 r.getRidgeT()->seen= false;
00474 }
00475 int ridgeCount= 0;
00476 if(facet.dimension()==3){
00477 for(QhullRidge r= rs.first(); !r.getRidgeT()->seen; r= r.nextRidge3d(facet)){
00478 r.getRidgeT()->seen= true;
00479 os << r.print(pr.run_id);
00480 ++ridgeCount;
00481 if(!r.hasNextRidge3d(facet)){
00482 break;
00483 }
00484 }
00485 }else {
00486 QhullFacetSet ns(facet.neighborFacets());
00487 for(QhullFacetSet::iterator i=ns.begin(); i!=ns.end(); ++i){
00488 QhullFacet neighbor= *i;
00489 QhullRidgeSet nrs(neighbor.ridges());
00490 for(QhullRidgeSet::iterator j=nrs.begin(); j!=nrs.end(); ++j){
00491 QhullRidge r= *j;
00492 if(r.otherFacet(neighbor)==facet){
00493 r.getRidgeT()->seen= true;
00494 os << r.print(pr.run_id);
00495 ridgeCount++;
00496 }
00497 }
00498 }
00499 }
00500 if(ridgeCount!=rs.count()){
00501 os << " - all ridges:";
00502 for(QhullRidgeSet::iterator i=rs.begin(); i!=rs.end(); ++i){
00503 QhullRidge r= *i;
00504 os << " r" << r.id();
00505 }
00506 os << endl;
00507 }
00508 for(QhullRidgeSet::iterator i=rs.begin(); i!=rs.end(); ++i){
00509 QhullRidge r= *i;
00510 if(!r.getRidgeT()->seen){
00511 os << r.print(pr.run_id);
00512 }
00513 }
00514 }
00515 return os;
00516 }
00517
00518
00519 ostream &
00520 operator<<(ostream &os, QhullFacet &f)
00521 {
00522 os << f.print(UsingLibQhull::NOqhRunId);
00523 return os;
00524 }