CASM  1.1.0
A Clusters Approach to Statistical Mechanics
Qhull.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/Qhull.cpp#1 $$Change: 1981 $
5 ** $DateTime: 2015/09/28 20:26:32 $$Author: bbarber $
6 **
7 ****************************************************************************/
8 
9 #
10 #
11 
12 #include "QhullError.h"
13 #include "RboxPoints.h"
14 #include "QhullQh.h"
15 #include "QhullFacet.h"
16 #include "QhullFacetList.h"
17 #include "Qhull.h"
18 extern "C" {
19  #include "../libqhull_r/qhull_ra.h"
20 }
21 
22 #include <iostream>
23 
24 using std::cerr;
25 using std::string;
26 using std::vector;
27 using std::ostream;
28 
29 #ifdef _MSC_VER // Microsoft Visual C++ -- warning level 4
30 #pragma warning( disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
31 #pragma warning( disable : 4996) // function was declared deprecated(strcpy, localtime, etc.)
32 #endif
33 
34 namespace orgQhull {
35 
36 #
37 
38 const char s_unsupported_options[]=" Fd TI ";
39 const char s_not_output_options[]= " Fd TI A C d E H P Qb QbB Qbb Qc Qf Qg Qi Qm QJ Qr QR Qs Qt Qv Qx Qz Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q10 Q11 R Tc TC TM TP TR Tv TV TW U v V W ";
40 
41 #
42 Qhull::
43 Qhull()
44 : qh_qh(0)
45 , origin_point()
46 , run_called(false)
47 , feasible_point()
48 {
49  allocateQhullQh();
50 }//Qhull
51 
56 Qhull::
57 Qhull(const RboxPoints &rboxPoints, const char *qhullCommand2)
58 : qh_qh(0)
59 , origin_point()
60 , run_called(false)
61 , feasible_point()
62 {
63  allocateQhullQh();
64  runQhull(rboxPoints, qhullCommand2);
65 }//Qhull rbox
66 
70 Qhull::
71 Qhull(const char *inputComment2, int pointDimension, int pointCount, const realT *pointCoordinates, const char *qhullCommand2)
72 : qh_qh(0)
73 , origin_point()
74 , run_called(false)
75 , feasible_point()
76 {
77  allocateQhullQh();
78  runQhull(inputComment2, pointDimension, pointCount, pointCoordinates, qhullCommand2);
79 }//Qhull points
80 
81 void Qhull::
82 allocateQhullQh()
83 {
84  QHULL_LIB_CHECK /* Check for compatible library */
85 
86  qh_qh= new QhullQh;
87  void *p= qh_qh;
88  void *p2= static_cast<qhT *>(qh_qh);
89  char *s= static_cast<char *>(p);
90  char *s2= static_cast<char *>(p2);
91  if(s!=s2){
92  throw QhullError(10074, "Qhull error: QhullQh at a different address than base type QhT (%d bytes). Please report compiler to qhull.org", int(s2-s));
93  }
94 }//allocateQhullQh
95 
96 Qhull::
97 ~Qhull() throw()
98 {
99  // Except for cerr, does not throw errors
100  if(qh_qh->hasQhullMessage()){
101  cerr<< "\nQhull output at end\n"; //FIXUP QH11005: where should error and log messages go on ~Qhull?
102  cerr<< qh_qh->qhullMessage();
103  qh_qh->clearQhullMessage();
104  }
105  delete qh_qh;
106  qh_qh= 0;
107 }//~Qhull
108 
109 #
110 
111 void Qhull::
112 checkIfQhullInitialized()
113 {
114  if(!initialized()){ // qh_initqhull_buffers() not called
115  throw QhullError(10023, "Qhull error: checkIfQhullInitialized failed. Call runQhull() first.");
116  }
117 }//checkIfQhullInitialized
118 
121 Coordinates Qhull::
122 feasiblePoint() const
123 {
124  Coordinates result;
125  if(qh_qh->feasible_point){
126  result.append(qh_qh->hull_dim, qh_qh->feasible_point);
127  }else{
128  result= feasible_point;
129  }
130  return result;
131 }//feasiblePoint
132 
134 QhullPoint Qhull::
135 inputOrigin()
136 {
137  QhullPoint result= origin();
138  result.setDimension(qh_qh->input_dim);
139  return result;
140 }//inputOrigin
141 
142 #
143 
144 double Qhull::
145 area(){
146  checkIfQhullInitialized();
147  if(!qh_qh->hasAreaVolume){
148  QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
149  qh_getarea(qh_qh, qh_qh->facet_list);
150  }
151  qh_qh->NOerrexit= true;
152  qh_qh->maybeThrowQhullMessage(QH_TRY_status);
153  }
154  return qh_qh->totarea;
155 }//area
156 
157 double Qhull::
158 volume(){
159  checkIfQhullInitialized();
160  if(!qh_qh->hasAreaVolume){
161  QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
162  qh_getarea(qh_qh, qh_qh->facet_list);
163  }
164  qh_qh->NOerrexit= true;
165  qh_qh->maybeThrowQhullMessage(QH_TRY_status);
166  }
167  return qh_qh->totvol;
168 }//volume
169 
170 #
171 
175 void Qhull::
176 defineVertexNeighborFacets(){
177  checkIfQhullInitialized();
178  if(!qh_qh->hasAreaVolume){
179  QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
180  qh_vertexneighbors(qh_qh);
181  }
182  qh_qh->NOerrexit= true;
183  qh_qh->maybeThrowQhullMessage(QH_TRY_status);
184  }
185 }//defineVertexNeighborFacets
186 
187 QhullFacetList Qhull::
188 facetList() const{
189  return QhullFacetList(beginFacet(), endFacet());
190 }//facetList
191 
192 QhullPoints Qhull::
193 points() const
194 {
195  return QhullPoints(qh_qh, qh_qh->hull_dim, qh_qh->num_points*qh_qh->hull_dim, qh_qh->first_point);
196 }//points
197 
198 QhullPointSet Qhull::
199 otherPoints() const
200 {
201  return QhullPointSet(qh_qh, qh_qh->other_points);
202 }//otherPoints
203 
205 QhullVertexList Qhull::
206 vertexList() const{
207  return QhullVertexList(beginVertex(), endVertex());
208 }//vertexList
209 
210 #
211 
212 void Qhull::
213 outputQhull()
214 {
215  checkIfQhullInitialized();
216  QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
217  qh_produce_output2(qh_qh);
218  }
219  qh_qh->NOerrexit= true;
220  qh_qh->maybeThrowQhullMessage(QH_TRY_status);
221 }//outputQhull
222 
223 void Qhull::
224 outputQhull(const char *outputflags)
225 {
226  checkIfQhullInitialized();
227  string cmd(" "); // qh_checkflags skips first word
228  cmd += outputflags;
229  char *command= const_cast<char*>(cmd.c_str());
230  QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
231  qh_clear_outputflags(qh_qh);
232  char *s = qh_qh->qhull_command + strlen(qh_qh->qhull_command) + 1; //space
233  strncat(qh_qh->qhull_command, command, sizeof(qh_qh->qhull_command)-strlen(qh_qh->qhull_command)-1);
234  qh_checkflags(qh_qh, command, const_cast<char *>(s_not_output_options));
235  qh_initflags(qh_qh, s);
236  qh_initqhull_outputflags(qh_qh);
237  if(qh_qh->KEEPminArea < REALmax/2
238  || (0 != qh_qh->KEEParea + qh_qh->KEEPmerge + qh_qh->GOODvertex
239  + qh_qh->GOODthreshold + qh_qh->GOODpoint + qh_qh->SPLITthresholds)){
240  facetT *facet;
241  qh_qh->ONLYgood= False;
242  FORALLfacet_(qh_qh->facet_list) {
243  facet->good= True;
244  }
245  qh_prepare_output(qh_qh);
246  }
247  qh_produce_output2(qh_qh);
248  if(qh_qh->VERIFYoutput && !qh_qh->STOPpoint && !qh_qh->STOPcone){
249  qh_check_points(qh_qh);
250  }
251  }
252  qh_qh->NOerrexit= true;
253  qh_qh->maybeThrowQhullMessage(QH_TRY_status);
254 }//outputQhull
255 
257 void Qhull::
258 runQhull(const RboxPoints &rboxPoints, const char *qhullCommand2)
259 {
260  runQhull(rboxPoints.comment().c_str(), rboxPoints.dimension(), rboxPoints.count(), &*rboxPoints.coordinates(), qhullCommand2);
261 }//runQhull, RboxPoints
262 
267 void Qhull::
268 runQhull(const char *inputComment2, int pointDimension, int pointCount, const realT *pointCoordinates, const char *qhullCommand2)
269 {
270  if(run_called){
271  throw QhullError(10027, "Qhull error: runQhull called twice. Only one call allowed.");
272  }
273  run_called= true;
274  string s("qhull ");
275  s += qhullCommand2;
276  char *command= const_cast<char*>(s.c_str());
277  /************* Expansion of QH_TRY_ for debugging
278  int QH_TRY_status;
279  if(qh_qh->NOerrexit){
280  qh_qh->NOerrexit= False;
281  QH_TRY_status= setjmp(qh_qh->errexit);
282  }else{
283  QH_TRY_status= QH_TRY_ERROR;
284  }
285  if(!QH_TRY_status){
286  *************/
287  QH_TRY_(qh_qh){ // no object creation -- destructors are skipped on longjmp()
288  qh_checkflags(qh_qh, command, const_cast<char *>(s_unsupported_options));
289  qh_initflags(qh_qh, command);
290  *qh_qh->rbox_command= '\0';
291  strncat( qh_qh->rbox_command, inputComment2, sizeof(qh_qh->rbox_command)-1);
292  if(qh_qh->DELAUNAY){
293  qh_qh->PROJECTdelaunay= True; // qh_init_B() calls qh_projectinput()
294  }
295  pointT *newPoints= const_cast<pointT*>(pointCoordinates);
296  int newDimension= pointDimension;
297  int newIsMalloc= False;
298  if(qh_qh->HALFspace){
299  --newDimension;
300  initializeFeasiblePoint(newDimension);
301  newPoints= qh_sethalfspace_all(qh_qh, pointDimension, pointCount, newPoints, qh_qh->feasible_point);
302  newIsMalloc= True;
303  }
304  qh_init_B(qh_qh, newPoints, pointCount, newDimension, newIsMalloc);
305  qh_qhull(qh_qh);
306  qh_check_output(qh_qh);
307  qh_prepare_output(qh_qh);
308  if(qh_qh->VERIFYoutput && !qh_qh->STOPpoint && !qh_qh->STOPcone){
309  qh_check_points(qh_qh);
310  }
311  }
312  qh_qh->NOerrexit= true;
313  for(int k= qh_qh->hull_dim; k--; ){ // Do not move into QH_TRY block. It may throw an error
314  origin_point << 0.0;
315  }
316  qh_qh->maybeThrowQhullMessage(QH_TRY_status);
317 }//runQhull
318 
319 #
320 
324 void Qhull::
325 initializeFeasiblePoint(int hulldim)
326 {
327  if(qh_qh->feasible_string){
328  qh_setfeasible(qh_qh, hulldim);
329  }else{
330  if(feasible_point.isEmpty()){
331  qh_fprintf(qh_qh, qh_qh->ferr, 6209, "qhull error: missing feasible point for halfspace intersection. Use option 'Hn,n' or Qhull::setFeasiblePoint before runQhull()\n");
332  qh_errexit(qh_qh, qh_ERRmem, NULL, NULL);
333  }
334  if(feasible_point.size()!=(size_t)hulldim){
335  qh_fprintf(qh_qh, qh_qh->ferr, 6210, "qhull error: dimension of feasiblePoint should be %d. It is %u", hulldim, feasible_point.size());
336  qh_errexit(qh_qh, qh_ERRmem, NULL, NULL);
337  }
338  if (!(qh_qh->feasible_point= (coordT*)qh_malloc(hulldim * sizeof(coordT)))) {
339  qh_fprintf(qh_qh, qh_qh->ferr, 6202, "qhull error: insufficient memory for feasible point\n");
340  qh_errexit(qh_qh, qh_ERRmem, NULL, NULL);
341  }
342  coordT *t= qh_qh->feasible_point;
343  // No qh_... routines after here -- longjmp() ignores destructor
344  for(Coordinates::ConstIterator p=feasible_point.begin(); p<feasible_point.end(); p++){
345  *t++= *p;
346  }
347  }
348 }//initializeFeasiblePoint
349 
350 }//namespace orgQhull
351 
std::set< std::string > & s
void qh_fprintf(qhT *qh, FILE *fp, int msgcode, const char *fmt,...)
Definition: QhullQh.cpp:202
GenericScelFormatter< double > volume()
Definition: SupercellIO.cc:258
QhullRidge – Qhull's ridge structure, ridgeT, as a C++ class.
Definition: Coordinates.cpp:20
const char s_unsupported_options[]
Definition: Qhull.cpp:38
const char s_not_output_options[]
Definition: Qhull.cpp:39