00001 /**************************************************************************** 00002 ** 00003 ** Copyright (c) 2008-2011 C.B. Barber. All rights reserved. 00004 ** $Id: //main/2011/qhull/src/libqhullcpp/UsingLibQhull.h#5 $$Change: 1382 $ 00005 ** $DateTime: 2011/05/14 10:45:42 $$Author: bbarber $ 00006 ** 00007 ****************************************************************************/ 00008 00009 #ifndef USINGlibqhull_H 00010 #define USINGlibqhull_H 00011 00012 #include "QhullError.h" 00013 extern "C" { 00014 #include "libqhull/libqhull.h" 00015 } 00016 00017 namespace orgQhull { 00018 00019 #//Types 00020 00021 00022 00023 /******************************* 00024 00025 UsingLibQhull is stack based, but as a call 00026 Qhull declarations are stack-based. But can't define a 00027 setjmp environment, since the target goes away. So must be UsingLibQhull, but can only have one 00028 setjmp at a time? Can embedded another Using as long as save/restore 00029 longjmp on exit. 00030 */ 00031 class UsingLibQhull; 00032 00033 // Defined elsewhere 00034 class Qhull; 00035 00036 #// Global variables 00037 extern Qhull *s_qhull_output; 00038 00039 class UsingLibQhull { 00040 00041 private: 00042 #//Fields 00043 Qhull *my_qhull; 00044 int qh_exitcode; 00045 00046 #//Class globals 00047 00048 static bool s_using_libqhull; 00049 00051 static bool s_has_angle_epsilon; 00052 static bool s_has_distance_epsilon; 00053 static bool s_has_points; 00054 static bool s_has_vertex_dimension; 00055 00057 static double s_angle_epsilon; 00058 static double s_distance_epsilon; 00059 static const coordT *s_points_begin; 00060 static const coordT *s_points_end; 00061 static int s_points_dimension; 00062 static int s_vertex_dimension; 00063 00064 public: 00065 #//Class constants 00066 static const int NOqhRunId= 0; 00067 static const int NOthrow= 1; 00068 static const int FACTORepsilon= 10; 00069 static const double DEFAULTdistanceEpsilon; 00070 static const double DEFAULTangleEpsilon; 00071 00072 #//Class members 00073 static void checkQhullMemoryEmpty(); 00074 static double currentAngleEpsilon(); 00075 static double currentDistanceEpsilon(); 00076 static const coordT *currentPoints(int *dimension, const coordT **pointsEnd); 00077 static Qhull ¤tQhull(); 00078 static int currentVertexDimension(); 00079 static double globalAngleEpsilon() { return s_has_angle_epsilon ? s_angle_epsilon : currentAngleEpsilon(); } 00080 static double globalDistanceEpsilon() { return s_has_distance_epsilon ? s_distance_epsilon : currentDistanceEpsilon(); } 00081 static double globalMachineEpsilon() { return REALepsilon; } 00082 static const coordT *globalPoints(int *dimension, const coordT **pointsEnd); 00083 static int globalVertexDimension() { return s_has_vertex_dimension ? s_vertex_dimension : currentVertexDimension(); } 00084 static bool hasPoints(); // inline would require Qhull.h 00085 static bool hasVertexDimension(); 00086 static void setGlobalAngleEpsilon(double d) { s_angle_epsilon=d; s_has_angle_epsilon= true; } 00087 static void setGlobalDistanceEpsilon(double d) { s_distance_epsilon= d; s_has_distance_epsilon= true; } 00088 static void setGlobalPoints(int dimension, const coordT *pointsBegin, const coordT *pointsEnd) { s_points_dimension= dimension; s_points_begin= pointsBegin; s_points_end= pointsEnd; s_has_points= true; } 00089 static void setGlobalVertexDimension(int i) { s_vertex_dimension= i; s_has_vertex_dimension= true; } 00090 static void setGlobals(); 00091 static void unsetGlobalAngleEpsilon() { s_has_angle_epsilon= false; } 00092 static void unsetGlobalDistanceEpsilon() { s_has_distance_epsilon= false; } 00093 static void unsetGlobalPoints() { s_has_points= false; } 00094 static void unsetGlobalVertexDimension() { s_has_vertex_dimension= false; } 00095 static void unsetGlobals(); 00096 00097 #//Constructors 00098 UsingLibQhull(Qhull *p); 00099 UsingLibQhull(Qhull *p, int noThrow); 00100 UsingLibQhull(int qhRunId); 00101 ~UsingLibQhull(); 00102 00103 private: 00104 UsingLibQhull(); 00105 UsingLibQhull(const UsingLibQhull &); 00106 UsingLibQhull &operator=(const UsingLibQhull &); 00107 public: 00108 00109 #//Methods 00110 #//Access 00111 bool defined() const { return my_qhull!=0; } 00112 void maybeThrowQhullMessage(int exitCode) const; 00113 void maybeThrowQhullMessage(int exitCode, int noThrow) const; 00114 00115 #//Helpers 00116 private: 00117 QhullError checkRunId() const; 00118 void checkUsingLibQhull() const; 00119 00120 /*********************************** 00121 You may use global variables in 'qh' after declaring UsingLibQhull. For example 00122 00123 UsingLibQhull q(qhRunId); 00124 // NOerrors -- no calls that throw libqhull errors 00125 cout << "Delaunay Mode: " << qh DELAUNAY; 00126 00127 To trap errors from libqhull, UsingLibQhull must be followed by 00128 00129 UsingLibQhull q(qhRunId); 00130 int exitCode = setjmp(qh errexit); 00131 if(!exitCode){ // no object creation -- destructors skipped on longjmp() 00132 calls to libqhull 00133 } 00134 q.maybeThrowQhullMessage(exitCode); 00135 00136 The call to setjmp() can not be moved to a method. The stack must be preserved for error exits from libqhull. 00137 00138 */ 00139 00140 };//UsingLibQhull 00141 00142 }//namespace orgQhull 00143 00144 #endif // USINGlibqhull_H