00001
00002
00003
00004
00005
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;
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
00084
00085
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;
00103 qh NOerrexit= False;
00104 }
00105
00108 UsingLibQhull::
00109 UsingLibQhull(Qhull *q, int noThrow)
00110 : my_qhull(0)
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
00124
00125
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;
00139 qh NOerrexit= False;
00140 }
00141 }
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;
00167 }
00168
00169
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 }
00187
00188 #//Class methods
00189
00190 void UsingLibQhull::
00191 checkQhullMemoryEmpty()
00192 {
00193 int curlong, totlong, curshort, totshort, maxlong, totbuffer;
00194
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 }
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 }
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 }
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 }
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 }
00249
00250
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 }
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 }
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 }
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 }
00314
00315 #// Methods
00316
00317 void UsingLibQhull::
00318 maybeThrowQhullMessage(int exitCode) const
00319 {
00320 my_qhull->maybeThrowQhullMessage(exitCode);
00321 QhullError e= checkRunId();
00322 if(e.isDefined()){
00323 throw e;
00324 }
00325 }
00326
00327 void UsingLibQhull::
00328 maybeThrowQhullMessage(int exitCode, int noThrow) const
00329 {
00330 my_qhull->maybeThrowQhullMessage(exitCode, noThrow);
00331 QhullError e= checkRunId();
00332 if(e.isDefined()){
00333 e.logError();
00334 }
00335 }
00336
00337 #//Helpers
00338
00340 QhullError UsingLibQhull::
00341 checkRunId() const
00342 {
00343
00344 #if qh_QHpointer
00345 if(qh_qh){
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 }
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 }
00371
00372 }
00373