CASM  1.1.0
A Clusters Approach to Statistical Mechanics
QhullFacet.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (c) 2008-2015 C.B. Barber. All rights reserved.
4 ** $Id: //main/2015/qhull/src/libqhullcpp/QhullFacet.cpp#1 $$Change: 1981 $
5 ** $DateTime: 2015/09/28 20:26:32 $$Author: bbarber $
6 **
7 ****************************************************************************/
8 
9 #
10 
11 #include "QhullError.h"
12 #include "Qhull.h"
13 #include "QhullSet.h"
14 #include "QhullPoint.h"
15 #include "QhullPointSet.h"
16 #include "QhullRidge.h"
17 #include "QhullFacet.h"
18 #include "QhullFacetSet.h"
19 #include "QhullVertex.h"
20 
21 #include <ostream>
22 
23 using std::endl;
24 using std::ostream;
25 
26 #ifdef _MSC_VER // Microsoft Visual C++ -- warning level 4
27 #pragma warning( disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
28 #pragma warning( disable : 4996) // function was declared deprecated(strcpy, localtime, etc.)
29 #endif
30 
31 namespace orgQhull {
32 
33 #
34 facetT QhullFacet::
35 s_empty_facet= {0,0,0,0,{0},
36  0,0,0,0,0,
37  0,0,0,0,0,
38  0,0,0,0,0,
39  0,0,0,0,0,
40  0,0,0,0,0,
41  0,0,0,0,0,
42  0,0,0,0};
43 
44 #
45 
46 QhullFacet::
47 QhullFacet(const Qhull &q)
48 : qh_facet(&s_empty_facet)
49 , qh_qh(q.qh())
50 {
51 }
52 
53 QhullFacet::
54 QhullFacet(const Qhull &q, facetT *f)
55 : qh_facet(f ? f : &s_empty_facet)
56 , qh_qh(q.qh())
57 {
58 }
59 
60 #
61 
67 QhullPoint QhullFacet::
68 getCenter(qh_PRINT printFormat)
69 {
70  if(!qh_qh){
71  // returns QhullPoint()
72  }else if(qh_qh->CENTERtype==qh_ASvoronoi){
73  if(!qh_facet->normal || !qh_facet->upperdelaunay || !qh_qh->ATinfinity){
74  if(!qh_facet->center){
75  QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
76  qh_facet->center= qh_facetcenter(qh_qh, qh_facet->vertices);
77  }
78  qh_qh->NOerrexit= true;
79  qh_qh->maybeThrowQhullMessage(QH_TRY_status);
80  }
81  return QhullPoint(qh_qh, qh_qh->hull_dim-1, qh_facet->center);
82  }
83  }else if(qh_qh->CENTERtype==qh_AScentrum){
84  volatile int numCoords= qh_qh->hull_dim;
85  if(printFormat==qh_PRINTtriangles && qh_qh->DELAUNAY){
86  numCoords--;
87  }
88  if(!qh_facet->center){
89  QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
90  qh_facet->center= qh_getcentrum(qh_qh, getFacetT());
91  }
92  qh_qh->NOerrexit= true;
93  qh_qh->maybeThrowQhullMessage(QH_TRY_status);
94  }
95  return QhullPoint(qh_qh, numCoords, qh_facet->center);
96  }
97  return QhullPoint();
98  }//getCenter
99 
102 QhullHyperplane QhullFacet::
103 innerplane() const{
104  QhullHyperplane h;
105  if(qh_qh){
106  realT inner;
107  // Does not error, TRY_QHULL_ not needed
108  qh_outerinner(qh_qh, const_cast<facetT *>(getFacetT()), NULL, &inner);
109  h= hyperplane();
110  h.setOffset(h.offset()-inner); //inner is negative
111  }
112  return h;
113 }//innerplane
114 
117 QhullHyperplane QhullFacet::
118 outerplane() const{
119  QhullHyperplane h;
120  if(qh_qh){
121  realT outer;
122  // Does not error, TRY_QHULL_ not needed
123  qh_outerinner(qh_qh, const_cast<facetT *>(getFacetT()), &outer, NULL);
124  h= hyperplane();
125  h.setOffset(h.offset()-outer); //outer is positive
126  }
127  return h;
128 }//outerplane
129 
132 QhullFacet QhullFacet::
133 tricoplanarOwner() const
134 {
135  if(qh_facet->tricoplanar){
136  if(qh_facet->isarea){
137  throw QhullError(10018, "Qhull error: facetArea() or qh_getarea() previously called. triCoplanarOwner() is not available.");
138  }
139  return QhullFacet(qh_qh, qh_facet->f.triowner);
140  }
141  return QhullFacet(qh_qh);
142 }//tricoplanarOwner
143 
144 QhullPoint QhullFacet::
145 voronoiVertex()
146 {
147  if(qh_qh && qh_qh->CENTERtype!=qh_ASvoronoi){
148  throw QhullError(10052, "Error: QhullFacet.voronoiVertex() requires option 'v' (qh_ASvoronoi)");
149  }
150  return getCenter();
151 }//voronoiVertex
152 
153 #
154 
156 double QhullFacet::
157 facetArea()
158 {
159  if(qh_qh && !qh_facet->isarea){
160  QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
161  qh_facet->f.area= qh_facetarea(qh_qh, qh_facet);
162  qh_facet->isarea= True;
163  }
164  qh_qh->NOerrexit= true;
165  qh_qh->maybeThrowQhullMessage(QH_TRY_status);
166  }
167  return qh_facet->f.area;
168 }//facetArea
169 
170 #
171 
172 QhullPointSet QhullFacet::
173 coplanarPoints() const
174 {
175  return QhullPointSet(qh_qh, qh_facet->coplanarset);
176 }//coplanarPoints
177 
178 QhullFacetSet QhullFacet::
179 neighborFacets() const
180 {
181  return QhullFacetSet(qh_qh, qh_facet->neighbors);
182 }//neighborFacets
183 
184 QhullPointSet QhullFacet::
185 outsidePoints() const
186 {
187  return QhullPointSet(qh_qh, qh_facet->outsideset);
188 }//outsidePoints
189 
190 QhullRidgeSet QhullFacet::
191 ridges() const
192 {
193  return QhullRidgeSet(qh_qh, qh_facet->ridges);
194 }//ridges
195 
196 QhullVertexSet QhullFacet::
197 vertices() const
198 {
199  return QhullVertexSet(qh_qh, qh_facet->vertices);
200 }//vertices
201 
202 }//namespace orgQhull
203 
204 #
205 
206 using std::ostream;
207 
208 using orgQhull::QhullFacet;
209 using orgQhull::QhullFacetSet;
210 using orgQhull::QhullPoint;
211 using orgQhull::QhullPointSet;
212 using orgQhull::QhullRidge;
213 using orgQhull::QhullRidgeSet;
214 using orgQhull::QhullSetBase;
215 using orgQhull::QhullVertexSet;
216 
217 ostream &
218 operator<<(ostream &os, const QhullFacet::PrintFacet &pr)
219 {
220  os << pr.message;
221  QhullFacet f= *pr.facet;
222  if(f.getFacetT()==0){ // Special values from set iterator
223  os << " NULLfacet" << endl;
224  return os;
225  }
226  if(f.getFacetT()==qh_MERGEridge){
227  os << " MERGEridge" << endl;
228  return os;
229  }
230  if(f.getFacetT()==qh_DUPLICATEridge){
231  os << " DUPLICATEridge" << endl;
232  return os;
233  }
234  os << f.printHeader();
235  if(!f.ridges().isEmpty()){
236  os << f.printRidges();
237  }
238  return os;
239 }//operator<< PrintFacet
240 
244 ostream &
245 operator<<(ostream &os, const QhullFacet::PrintCenter &pr)
246 {
247  facetT *f= pr.facet->getFacetT();
248  if(pr.facet->qh()->CENTERtype!=qh_ASvoronoi && pr.facet->qh()->CENTERtype!=qh_AScentrum){
249  return os;
250  }
251  if (pr.message){
252  os << pr.message;
253  }
254  int numCoords;
255  if(pr.facet->qh()->CENTERtype==qh_ASvoronoi){
256  numCoords= pr.facet->qh()->hull_dim-1;
257  if(!f->normal || !f->upperdelaunay || !pr.facet->qh()->ATinfinity){
258  if(!f->center){
259  f->center= qh_facetcenter(pr.facet->qh(), f->vertices);
260  }
261  for(int k=0; k<numCoords; k++){
262  os << f->center[k] << " "; // FIXUP QH11010 qh_REAL_1
263  }
264  }else{
265  for(int k=0; k<numCoords; k++){
266  os << qh_INFINITE << " "; // FIXUP QH11010 qh_REAL_1
267  }
268  }
269  }else{ // qh CENTERtype==qh_AScentrum
270  numCoords= pr.facet->qh()->hull_dim;
271  if(pr.print_format==qh_PRINTtriangles && pr.facet->qh()->DELAUNAY){
272  numCoords--;
273  }
274  if(!f->center){
275  f->center= qh_getcentrum(pr.facet->qh(), f);
276  }
277  for(int k=0; k<numCoords; k++){
278  os << f->center[k] << " "; // FIXUP QH11010 qh_REAL_1
279  }
280  }
281  if(pr.print_format==qh_PRINTgeom && numCoords==2){
282  os << " 0";
283  }
284  os << endl;
285  return os;
286 }//operator<< PrintCenter
287 
289 ostream &
290 operator<<(ostream &os, const QhullFacet::PrintFlags &p)
291 {
292  const facetT *f= p.facet->getFacetT();
293  if(p.message){
294  os << p.message;
295  }
296 
297  os << (p.facet->isTopOrient() ? " top" : " bottom");
298  if(p.facet->isSimplicial()){
299  os << " simplicial";
300  }
301  if(p.facet->isTriCoplanar()){
302  os << " tricoplanar";
303  }
304  if(p.facet->isUpperDelaunay()){
305  os << " upperDelaunay";
306  }
307  if(f->visible){
308  os << " visible";
309  }
310  if(f->newfacet){
311  os << " new";
312  }
313  if(f->tested){
314  os << " tested";
315  }
316  if(!f->good){
317  os << " notG";
318  }
319  if(f->seen){
320  os << " seen";
321  }
322  if(f->coplanar){
323  os << " coplanar";
324  }
325  if(f->mergehorizon){
326  os << " mergehorizon";
327  }
328  if(f->keepcentrum){
329  os << " keepcentrum";
330  }
331  if(f->dupridge){
332  os << " dupridge";
333  }
334  if(f->mergeridge && !f->mergeridge2){
335  os << " mergeridge1";
336  }
337  if(f->mergeridge2){
338  os << " mergeridge2";
339  }
340  if(f->newmerge){
341  os << " newmerge";
342  }
343  if(f->flipped){
344  os << " flipped";
345  }
346  if(f->notfurthest){
347  os << " notfurthest";
348  }
349  if(f->degenerate){
350  os << " degenerate";
351  }
352  if(f->redundant){
353  os << " redundant";
354  }
355  os << endl;
356  return os;
357 }//operator<< PrintFlags
358 
360 ostream &
361 operator<<(ostream &os, const QhullFacet::PrintHeader &pr)
362 {
363  QhullFacet facet= *pr.facet;
364  facetT *f= facet.getFacetT();
365  os << "- f" << facet.id() << endl;
366  os << facet.printFlags(" - flags:");
367  if(f->isarea){
368  os << " - area: " << f->f.area << endl; //FIXUP QH11010 2.2g
369  }else if(pr.facet->qh()->NEWfacets && f->visible && f->f.replace){
370  os << " - replacement: f" << f->f.replace->id << endl;
371  }else if(f->newfacet){
372  if(f->f.samecycle && f->f.samecycle != f){
373  os << " - shares same visible/horizon as f" << f->f.samecycle->id << endl;
374  }
375  }else if(f->tricoplanar /* !isarea */){
376  if(f->f.triowner){
377  os << " - owner of normal & centrum is facet f" << f->f.triowner->id << endl;
378  }
379  }else if(f->f.newcycle){
380  os << " - was horizon to f" << f->f.newcycle->id << endl;
381  }
382  if(f->nummerge){
383  os << " - merges: " << f->nummerge << endl;
384  }
385  os << facet.hyperplane().print(" - normal: ", "\n - offset: "); // FIXUP QH11010 %10.7g
386  if(pr.facet->qh()->CENTERtype==qh_ASvoronoi || f->center){
387  os << facet.printCenter(qh_PRINTfacets, " - center: ");
388  }
389 #if qh_MAXoutside
390  if(f->maxoutside > pr.facet->qh()->DISTround){
391  os << " - maxoutside: " << f->maxoutside << endl; //FIXUP QH11010 %10.7g
392  }
393 #endif
394  QhullPointSet ps= facet.outsidePoints();
395  if(!ps.isEmpty()){
396  QhullPoint furthest= ps.last();
397  if (ps.size() < 6) {
398  os << " - outside set(furthest p" << furthest.id() << "):" << endl;
399  for(QhullPointSet::iterator i=ps.begin(); i!=ps.end(); ++i){
400  QhullPoint p= *i;
401  os << p.print(" ");
402  }
403  }else if(ps.size()<21){
404  os << ps.print(" - outside set:");
405  }else{
406  os << " - outside set: " << ps.size() << " points.";
407  os << furthest.print(" Furthest");
408  }
409 #if !qh_COMPUTEfurthest
410  os << " - furthest distance= " << f->furthestdist << endl; //FIXUP QH11010 %2.2g
411 #endif
412  }
413  QhullPointSet cs= facet.coplanarPoints();
414  if(!cs.isEmpty()){
415  QhullPoint furthest= cs.last();
416  if (cs.size() < 6) {
417  os << " - coplanar set(furthest p" << furthest.id() << "):" << endl;
418  for(QhullPointSet::iterator i=cs.begin(); i!=cs.end(); ++i){
419  QhullPoint p= *i;
420  os << p.print(" ");
421  }
422  }else if(cs.size()<21){
423  os << cs.print(" - coplanar set:");
424  }else{
425  os << " - coplanar set: " << cs.size() << " points.";
426  os << furthest.print(" Furthest");
427  }
428  // FIXUP QH11027 Can/should zinc_(Zdistio) be called from C++ interface
429  double d= facet.distance(furthest);
430  os << " furthest distance= " << d << endl; //FIXUP QH11010 %2.2g
431  }
432  QhullVertexSet vs= facet.vertices();
433  if(!vs.isEmpty()){
434  os << vs.print(" - vertices:");
435  }
436  QhullFacetSet fs= facet.neighborFacets();
437  fs.selectAll();
438  if(!fs.isEmpty()){
439  os << fs.printIdentifiers(" - neighboring facets:");
440  }
441  return os;
442 }//operator<< PrintHeader
443 
444 
446 ostream &
447 operator<<(ostream &os, const QhullFacet::PrintRidges &pr)
448 {
449  const QhullFacet facet= *pr.facet;
450  facetT *f= facet.getFacetT();
451  QhullRidgeSet rs= facet.ridges();
452  if(!rs.isEmpty()){
453  if(f->visible && pr.facet->qh()->NEWfacets){
454  os << " - ridges(ids may be garbage):";
455  for(QhullRidgeSet::iterator i=rs.begin(); i!=rs.end(); ++i){
456  QhullRidge r= *i;
457  os << " r" << r.id();
458  }
459  os << endl;
460  }else{
461  os << " - ridges:" << endl;
462  }
463 
464  // Keep track of printed ridges
465  for(QhullRidgeSet::iterator i=rs.begin(); i!=rs.end(); ++i){
466  QhullRidge r= *i;
467  r.getRidgeT()->seen= false;
468  }
469  int ridgeCount= 0;
470  if(facet.dimension()==3){
471  for(QhullRidge r= rs.first(); !r.getRidgeT()->seen; r= r.nextRidge3d(facet)){
472  r.getRidgeT()->seen= true;
473  os << r.print("");
474  ++ridgeCount;
475  if(!r.hasNextRidge3d(facet)){
476  break;
477  }
478  }
479  }else {
480  QhullFacetSet ns(facet.neighborFacets());
481  for(QhullFacetSet::iterator i=ns.begin(); i!=ns.end(); ++i){
482  QhullFacet neighbor= *i;
483  QhullRidgeSet nrs(neighbor.ridges());
484  for(QhullRidgeSet::iterator j=nrs.begin(); j!=nrs.end(); ++j){
485  QhullRidge r= *j;
486  if(r.otherFacet(neighbor)==facet){
487  r.getRidgeT()->seen= true;
488  os << r.print("");
489  ridgeCount++;
490  }
491  }
492  }
493  }
494  if(ridgeCount!=rs.count()){
495  os << " - all ridges:";
496  for(QhullRidgeSet::iterator i=rs.begin(); i!=rs.end(); ++i){
497  QhullRidge r= *i;
498  os << " r" << r.id();
499  }
500  os << endl;
501  }
502  for(QhullRidgeSet::iterator i=rs.begin(); i!=rs.end(); ++i){
503  QhullRidge r= *i;
504  if(!r.getRidgeT()->seen){
505  os << r.print("");
506  }
507  }
508  }
509  return os;
510 }//operator<< PrintRidges
511 
512 // "No conversion" error if defined inline
513 ostream &
514 operator<<(ostream &os, QhullFacet &f)
515 {
516  os << f.print("");
517  return os;
518 }//<< QhullFacet
ostream & operator<<(ostream &os, const QhullFacet::PrintFacet &pr)
Definition: QhullFacet.cpp:218
QhullRidge – Qhull's ridge structure, ridgeT, as a C++ class.
Definition: Coordinates.cpp:20