UsingLibQhull.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (c) 2008-2011 C.B. Barber. All rights reserved.
00004 ** $Id: //main/2011/qhull/src/libqhullcpp/UsingLibQhull.cpp#3 $$Change: 1342 $
00005 ** $DateTime: 2011/03/07 21:55:47 $$Author: bbarber $
00006 **
00007 ****************************************************************************/
00008 
00009 #//! UsingLibQhull -- Set up qhull C code from C++
00010 
00011 #include "Qhull.h"
00012 #include "UsingLibQhull.h"
00013 #include "QhullError.h"
00014 #include "QhullQh.h"
00015 
00016 #ifdef _MSC_VER  // Microsoft Visual C++ -- warning level 4
00017 #endif
00018 
00019 namespace orgQhull {
00020 
00021 #//Class objects
00022 
00023 const double UsingLibQhull::
00024 DEFAULTdistanceEpsilon= 1e-15*FACTORepsilon; 
00025 
00026 const double UsingLibQhull::
00027 DEFAULTangleEpsilon= 1e-15*FACTORepsilon; 
00028 
00030 Qhull *
00031 s_qhull_output= 0;
00032 
00033 double UsingLibQhull::
00034 s_angle_epsilon= 0;
00035 
00036 double UsingLibQhull::
00037 s_distance_epsilon= 0;
00038 
00040 const coordT *UsingLibQhull::
00041 s_points_begin= 0;
00042 const coordT *UsingLibQhull::
00043 s_points_end= 0;
00044 int UsingLibQhull::
00045 s_points_dimension= 0;
00046 
00047 int UsingLibQhull::
00048 s_vertex_dimension= 0;  // FIXUP QH11023: s_vertex_dimension is required if dimension>15.  Cannot store in QhullVertex
00049 
00050 bool UsingLibQhull::
00051 s_has_points= false;
00052 
00053 bool UsingLibQhull::
00054 s_has_angle_epsilon= false;
00055 
00056 bool UsingLibQhull::
00057 s_has_vertex_dimension= false;
00058 
00059 bool UsingLibQhull::
00060 s_has_distance_epsilon= false;
00061 
00062 bool UsingLibQhull::
00063 s_using_libqhull= false;
00064 
00065 #//Constructors
00066 
00070 UsingLibQhull::
00071 UsingLibQhull(Qhull *q)
00072 : my_qhull(q)
00073 , qh_exitcode(0)
00074 {
00075     checkUsingLibQhull();
00076     QhullQh *qhullqh= q->qhullQh();
00077     if(!qhullqh){
00078         throw QhullError(10014, "Qhull internal error: Qhull.qhullQh() not defined. initializeQhull() not called.");
00079     }
00080     if(qhullqh->run_id != q->qhull_run_id){
00081         throw QhullError(10015, "Qhull error: QhullQh.runId %d != Qhull.runId %d.  Overwritten?", qhullqh->run_id, q->qhull_run_id);
00082     }
00083     // qh.old_qhstat is zero at initialization
00084     // qh.old_tempstack is zero when empty
00085     // QhullQh() and UsingLibQhull() are the same
00086 #if qh_QHpointer
00087     if(qh_qh){
00088         qh old_qhstat= qh_qhstat;
00089         qh old_tempstack= qhmem.tempstack;
00090     }
00091     qh_qh= qhullqh;
00092     qh_qhstat= qhullqh->old_qhstat;
00093     qhmem.tempstack= qhullqh->old_tempstack;
00094     qhullqh->old_qhstat= 0;
00095     qhullqh->old_tempstack= 0;
00096 #else
00097     #error FIXUP QH11024 static qh_qh not tested.  Delete the line to try.
00098     if(qhullqh!=&qh_qh){
00099         throw QhullError(10040, "Qhull internal error: Qhull.qhullQh() is not qh_qh (%x, static).  Overwrite?", 0,0,0.0, &qh_qh);
00100     }
00101 #endif
00102     s_qhull_output= q;      // set s_qhull_output for qh_fprintf()
00103     qh NOerrexit= False;   // assumes setjmp called next
00104 }//UsingLibQhull qhull
00105 
00108 UsingLibQhull::
00109 UsingLibQhull(Qhull *q, int noThrow)
00110 : my_qhull(0)  // Fail by default
00111 , qh_exitcode(0)
00112 {
00113     QHULL_UNUSED(noThrow);
00114 
00115     QhullQh *qhullqh= q->qhullQh();
00116     if(s_using_libqhull){
00117         QhullError e(10050, "Qhull error: UsingLibQhull already in use");
00118         e.logError();
00119     }else if(!qhullqh || qhullqh->run_id != q->qhull_run_id){
00120         QhullError e(10051, "Qhull error: Qhull.qhullQh (%x) undefined or QhullQh.runId %d != Qhull.runId %d.  Overwritten?", (qhullqh ? qhullqh->run_id : -1), q->qhull_run_id, 0.0, qhullqh);
00121         e.logError();
00122     }else{
00123         // qh.old_qhstat is zero at initialization
00124         // qh.old_tempstack is zero when empty
00125         // QhullQh() and UsingLibQhull() are the same
00126 #if qh_QHpointer
00127         if(qh_qh){
00128             qh old_qhstat= qh_qhstat;
00129             qh old_tempstack= qhmem.tempstack;
00130         }
00131         qh_qh= qhullqh;
00132         qh_qhstat= qhullqh->old_qhstat;
00133         qhmem.tempstack= qhullqh->old_tempstack;
00134         qhullqh->old_qhstat= 0;
00135         qhullqh->old_tempstack= 0;
00136 #endif
00137         my_qhull= q;
00138         s_qhull_output= q;          // set s_qhull_output for qh_fprintf()
00139         qh NOerrexit= False;   // assumes setjmp called next
00140     }
00141 }//UsingLibQhull qhull noThrow
00142 
00145 UsingLibQhull::
00146 UsingLibQhull(int qhRunId)
00147 : my_qhull(0)
00148 , qh_exitcode(0)
00149 {
00150     checkUsingLibQhull();
00151 #if qh_QHpointer
00152     if(!qh_qh || !qh_qhstat){
00153         throw QhullError(10024, "Qhull error: UsingLibQhull is not active (qh_qh %x or qh_qhstat is not defined)", 0,0,0.0, qh_qh);
00154     }
00155 #endif
00156     if(qh run_id!=qhRunId){
00157         throw QhullError(10036, "Qhull error: qhRunId %d != qh_qh.runId %d.  Is another Qhull active?", qhRunId, qh run_id);
00158     }
00159     if(!s_qhull_output){
00160         throw QhullError(10037, "Qhull error: UsingLibQhull not active(s_qhull_output undefined).  Invoke UsingLibQhull before this call");
00161     }
00162     if(s_qhull_output->qhull_run_id!=qhRunId){
00163         throw QhullError(10046, "Qhull error: qhRunId %d != s_qhull_output.runId %d.  Is another Qhull active", qhRunId, s_qhull_output->qhull_run_id);
00164     }
00165     my_qhull= s_qhull_output;
00166     qh NOerrexit= False;   // assumes setjmp called next
00167 }//UsingLibQhull runId
00168 
00169 //Leaves libqhull active for runId access
00170 UsingLibQhull::
00171 ~UsingLibQhull()
00172 {
00173     QhullError e= checkRunId();
00174     if(e.isDefined()){
00175         e.logError();
00176     }else{
00177 #if qh_QHpointer
00178         if(qh_qh){
00179             qh NOerrexit= true;
00180         }
00181 #else
00182         qh NOerrexit= true;
00183 #endif
00184     }
00185     s_using_libqhull= false;
00186 }//~UsingLibQhull
00187 
00188 #//Class methods
00189 
00190 void UsingLibQhull::
00191 checkQhullMemoryEmpty()
00192 {
00193     int curlong, totlong, curshort, totshort, maxlong, totbuffer;
00194     // qh_memtotal does not error
00195     qh_memtotal(&curlong, &totlong, &curshort, &totshort, &maxlong, &totbuffer);
00196     if (curlong || totlong){
00197         throw QhullError(10026, "Qhull error: qhull did not free %d bytes of long memory (%d pieces).", totlong, curlong);
00198     }
00199     if (curshort || totshort){
00200         throw QhullError(10035, "Qhull error: qhull did not free %d bytes of short memory (%d pieces).", totshort, curshort);
00201     }
00202 }//checkQhullMemoryEmpty
00203 
00204 double UsingLibQhull::
00205 currentAngleEpsilon()
00206 {
00207     if(s_qhull_output && s_qhull_output->initialized()){
00208         return s_qhull_output->qhullQh()->ANGLEround*FACTORepsilon;
00209     }else if(s_has_angle_epsilon){
00210         return s_angle_epsilon;
00211     }
00212     return UsingLibQhull::DEFAULTangleEpsilon;
00213 }//currentAngleEpsilon
00214 
00215 double UsingLibQhull::
00216 currentDistanceEpsilon()
00217 {
00218     if(s_qhull_output && s_qhull_output->initialized()){
00219         return s_qhull_output->qhullQh()->DISTround*FACTORepsilon;
00220     }else if(s_has_distance_epsilon){
00221         return s_distance_epsilon;
00222     }
00223     return UsingLibQhull::DEFAULTdistanceEpsilon;
00224 }//currentDistanceEpsilon
00225 
00226 const coordT *UsingLibQhull::
00227 currentPoints(int *dimension, const coordT **pointsEnd)
00228 {
00229     if(s_qhull_output && s_qhull_output->initialized()){
00230         *dimension= qh hull_dim;
00231         *pointsEnd= qh first_point+qh num_points*qh hull_dim;
00232         return qh first_point;
00233     }else if(s_has_points){
00234         *dimension= s_points_dimension;
00235         *pointsEnd= s_points_end;
00236         return s_points_begin;
00237     }
00238     throw QhullError(10059, "Qhull error: missing definition for currentPoints().  Need currentQhull() or setGlobalDistanceEpsilon()");
00239 }//currentPoints
00240 
00241 Qhull &UsingLibQhull::
00242 currentQhull()
00243 {
00244     if(!s_qhull_output){
00245         throw QhullError(10055, "Qhull error: currentQhull not defined.  Run qhull first.");
00246     }
00247     return *s_qhull_output;
00248 }//currentQhull
00249 
00250 // for QhullVertex::dimension() when >= 16
00251 int UsingLibQhull::
00252 currentVertexDimension()
00253 {
00254     if(s_qhull_output && s_qhull_output->initialized()){
00255         return s_qhull_output->dimension();
00256     }else if(s_has_vertex_dimension){
00257         return s_vertex_dimension;
00258     }
00259     throw QhullError(10057, "Qhull error: missing definition for currentVertexDimension().  Need currentQhull() or setGlobalVertexDimension()");
00260 }//currentVertexDimension
00261 
00262 const coordT *UsingLibQhull::
00263 globalPoints(int *dimension, const coordT **pointsEnd)
00264 {
00265     if(s_has_points){
00266         *dimension= s_points_dimension;
00267         *pointsEnd= s_points_end;
00268         return s_points_begin;
00269     }else{
00270         return currentPoints(dimension, pointsEnd);
00271     }
00272 }//globalPoints
00273 
00274 bool UsingLibQhull::
00275 hasPoints()
00276 {
00277     return s_has_points || (s_qhull_output && s_qhull_output->initialized());
00278 }
00279 
00280 bool UsingLibQhull::
00281 hasVertexDimension()
00282 {
00283     return s_has_vertex_dimension || (s_qhull_output && s_qhull_output->initialized());
00284 }
00285 
00286 void UsingLibQhull::
00287 setGlobals()
00288 {
00289     if(s_qhull_output && s_qhull_output->initialized()){
00290         QhullQh *qqh= s_qhull_output->qhullQh();
00291         s_angle_epsilon= qqh->ANGLEround*FACTORepsilon;
00292         s_distance_epsilon= qqh->DISTround*FACTORepsilon;
00293         s_points_begin= qqh->first_point;
00294         s_points_dimension= qqh->hull_dim;
00295         s_points_end= s_points_begin+qqh->num_points*s_points_dimension;
00296         s_vertex_dimension= qqh->hull_dim;
00297         s_has_angle_epsilon= true;
00298         s_has_distance_epsilon= true;
00299         s_has_points= true;
00300         s_has_vertex_dimension= true;
00301     }else{
00302         throw QhullError(10058, "Qhull error: setGlobals can only be called for currentQhull().  Run qhull first.");
00303     }
00304  }//setGlobals
00305 
00306 void UsingLibQhull::
00307 unsetGlobals()
00308 {
00309     s_has_angle_epsilon= false;
00310     s_has_distance_epsilon= false;
00311     s_has_points= false;
00312     s_has_vertex_dimension= false;
00313 }//unsetGlobals
00314 
00315 #// Methods
00316 
00317 void UsingLibQhull::
00318 maybeThrowQhullMessage(int exitCode) const
00319 {
00320     my_qhull->maybeThrowQhullMessage(exitCode);
00321     QhullError e= checkRunId(); // Check for qhRunId after libqhull returns. For convenience, ought to be at end of libqhull try block
00322     if(e.isDefined()){
00323         throw e;
00324     }
00325 }//maybeThrowQhullMessage
00326 
00327 void UsingLibQhull::
00328 maybeThrowQhullMessage(int exitCode, int noThrow) const
00329 {
00330     my_qhull->maybeThrowQhullMessage(exitCode, noThrow);
00331     QhullError e= checkRunId(); // Check for qhRunId after libqhull returns. For convenience, ought to be at end of libqhull try block
00332     if(e.isDefined()){
00333         e.logError();
00334     }
00335 }//maybeThrowQhullMessage
00336 
00337 #//Helpers
00338 
00340 QhullError UsingLibQhull::
00341 checkRunId() const
00342 {
00343     // Predeclaring QhullError results in four copy constructors, none used here
00344 #if qh_QHpointer
00345     if(qh_qh){ // 0 if ~Qhull
00346         if(my_qhull->qhull_run_id!=qh run_id){
00347             return QhullError(10047, "Qhull internal error: Global state (qh_qh, run_id %d) changed.  Should be runId %d.  Another thread?", qh run_id, my_qhull->qhull_run_id);
00348         }
00349     }
00350 #else
00351     if(qh run_id!=0 && my_qhull->qhull_run_id!=qh run_id){
00352         return QhullError(10048, "Qhull internal error: Global state (qh_qh, run_id %d) changed.  Should be runId %d.  Another thread?", qh run_id, my_qhull->qhull_run_id);
00353     }
00354 #endif
00355     return QhullError();
00356 }//checkRunId
00357 
00359 void UsingLibQhull::
00360 checkUsingLibQhull() const
00361 {
00362     if(s_using_libqhull){
00363         if(s_qhull_output){
00364             throw QhullError(10049, "Qhull error: UsingLibQhull already in use by QhullQh.runId %d", s_qhull_output->qhull_run_id);
00365         }else{
00366             throw QhullError(10050, "Qhull error: UsingLibQhull already in use.  No s_qhull_output");
00367         }
00368     }
00369     s_using_libqhull= true;
00370 }//checkUsingLibQhull
00371 
00372 }//namespace orgQhull
00373 


libqhull-ours
Author(s): Robert Krug
autogenerated on Mon Jan 6 2014 11:32:11