Qhull_test.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/qhulltest/Qhull_test.cpp#3 $$Change: 1360 $
00005 ** $DateTime: 2011/04/03 22:26:01 $$Author: bbarber $
00006 **
00007 ****************************************************************************/
00008 
00009 //pre-compiled headers
00010 #include <iostream>
00011 #include "../road/RoadTest.h" // QT_VERSION
00012 
00013 #include "Qhull.h"
00014 #include "QhullError.h"
00015 #include "RboxPoints.h"
00016 #include "QhullFacetList.h"
00017 
00018 using std::cout;
00019 using std::endl;
00020 using std::string;
00021 
00022 namespace orgQhull {
00023 
00026 class Qhull_test : public RoadTest
00027 {
00028     Q_OBJECT
00029 
00030 #//Test slots
00031 private slots:
00032     void cleanup();
00033     void t_construct();
00034     void t_attribute();
00035     void t_message();
00036     void t_getSet();
00037     void t_getQh();
00038     void t_getValue();
00039     void t_foreach();
00040     void t_modify();
00041 };//Qhull_test
00042 
00043 void
00044 add_Qhull_test()
00045 {
00046     new Qhull_test();
00047 }
00048 
00049 //Executed after each testcase
00050 void Qhull_test::
00051 cleanup()
00052 {
00053     UsingLibQhull::checkQhullMemoryEmpty();
00054     RoadTest::cleanup();
00055 }
00056 
00057 void Qhull_test::
00058 t_construct()
00059 {
00060     {
00061         Qhull q;
00062         QCOMPARE(q.dimension(),0);
00063         QVERIFY(q.qhullQh()!=0);
00064         QVERIFY(q.runId()!=0);
00065         QCOMPARE(QString(q.qhullCommand()),QString(""));
00066         QCOMPARE(QString(q.rboxCommand()),QString(""));
00067         try{
00068             QCOMPARE(q.area(),0.0);
00069             QFAIL("area() did not fail.");
00070         }catch (const std::exception &e) {
00071             cout << "INFO   : Caught " << e.what();
00072         }
00073         Qhull q2(q);  // Copy constructor and copy assignment OK if not q.initialized()
00074         QCOMPARE(q2.dimension(),0);
00075         q= q2;
00076         QCOMPARE(q.dimension(),0);
00077     }
00078     {
00079         RboxPoints rbox("10000");
00080         Qhull q(rbox, "QR0"); // Random points in a randomly rotated cube.
00081         QCOMPARE(q.dimension(),3);
00082         QVERIFY(q.volume() < 1.0);
00083         QVERIFY(q.volume() > 0.99);
00084         try{
00085             Qhull q2(q);
00086             QFAIL("Copy constructor did not fail for initialized Qhull.");
00087         }catch (const std::exception &e) {
00088             cout << "INFO   : Caught " << e.what();
00089         }
00090         try{
00091             Qhull q3;
00092             q3= q;
00093             QFAIL("Copy assignment did not fail for initialized Qhull source.");
00094         }catch (const std::exception &e) {
00095             cout << "INFO   : Caught " << e.what();
00096         }
00097         QCOMPARE(q.dimension(),3);
00098         try{
00099             Qhull q4;
00100             q= q4;
00101             QFAIL("Copy assignment did not fail for initialized Qhull destination.");
00102         }catch (const std::exception &e) {
00103             cout << "INFO   : Caught " << e.what();
00104         }
00105         QCOMPARE(q.dimension(),3);
00106     }
00107     {
00108         double points[] = {
00109             0, 0,
00110             1, 0,
00111             1, 1
00112         };
00113         Qhull q("triangle", 2, 3, points, "");
00114         QCOMPARE(q.dimension(),2);
00115         QCOMPARE(q.facetCount(),3);
00116         QCOMPARE(q.vertexCount(),3);
00117         QCOMPARE(q.dimension(),2);
00118         QCOMPARE(q.area(), 2.0+sqrt(2.0)); // length of boundary
00119         QCOMPARE(q.volume(), 0.5);        // the 2-d area
00120     }
00121 }//t_construct
00122 
00123 void Qhull_test::
00124 t_attribute()
00125 {
00126     RboxPoints rcube("c");
00127     {
00128         double normals[] = {
00129             0,  -1, -0.5,
00130            -1,   0, -0.5,
00131             1,   0, -0.5,
00132             0,   1, -0.5
00133         };
00134         Qhull q;
00135         q.feasiblePoint << 0.0 << 0.0;
00136         Coordinates c(std::vector<double>(2, 0.0));
00137         QVERIFY(q.feasiblePoint==c);
00138         q.setOutputStream(&cout);
00139         q.runQhull("normals of square", 3, 4, normals, "H"); // halfspace intersect
00140         QCOMPARE(q.facetList().count(), 4); // Vertices of square
00141         cout << "Expecting summary of halfspace intersect\n";
00142         q.outputQhull();
00143         q.useOutputStream= false;
00144         cout << "Expecting no output from qh_fprintf() in Qhull.cpp\n";
00145         q.outputQhull();
00146     }
00147 }//t_attribute
00148 
00150 void Qhull_test::
00151 t_message()
00152 {
00153     RboxPoints rcube("c");
00154     {
00155         Qhull q;
00156         QCOMPARE(q.qhullMessage(), string(""));
00157         QCOMPARE(q.qhullStatus(), qh_ERRnone);
00158         QVERIFY(!q.hasQhullMessage());
00159         try{
00160             q.runQhull(rcube, "Fd");
00161             QFAIL("runQhull Fd did not fail.");
00162         }catch (const std::exception &e) {
00163             const char *s= e.what();
00164             cout << "INFO   : Caught " << s;
00165             QCOMPARE(QString::fromStdString(s).left(6), QString("QH6029"));
00166             // FIXUP QH11025 -- review decision to clearQhullMessage at QhullError()            // Cleared when copied to QhullError
00167             QVERIFY(!q.hasQhullMessage());
00168             // QCOMPARE(q.qhullMessage(), QString::fromStdString(s).remove(0, 7));
00169             // QCOMPARE(q.qhullStatus(), 6029);
00170             q.clearQhullMessage();  
00171             QVERIFY(!q.hasQhullMessage());
00172         }
00173         q.appendQhullMessage("Append 1");
00174         QVERIFY(q.hasQhullMessage());
00175         QCOMPARE(QString::fromStdString(q.qhullMessage()), QString("Append 1"));
00176         q.appendQhullMessage("\nAppend 2\n");
00177         QCOMPARE(QString::fromStdString(q.qhullMessage()), QString("Append 1\nAppend 2\n"));
00178         q.clearQhullMessage();
00179         QVERIFY(!q.hasQhullMessage());
00180         QCOMPARE(QString::fromStdString(q.qhullMessage()), QString(""));
00181     }
00182     {
00183         cout << "INFO   : Error stream without output stream\n";
00184         Qhull q;
00185         q.setErrorStream(&cout);
00186         q.setOutputStream(0);
00187         try{
00188             q.runQhull(rcube, "Fd");
00189             QFAIL("runQhull Fd did not fail.");
00190         }catch (const QhullError &e) {
00191             cout << "INFO   : Caught " << e;
00192             QCOMPARE(e.errorCode(), 6029);
00193         }
00194         //FIXUP QH11026 Qhullmessage cleared when QhullError thrown.  Switched to e
00195         //QVERIFY(q.hasQhullMessage());
00196         //QCOMPARE(QString::fromStdString(q.qhullMessage()).left(6), QString("QH6029"));
00197         q.clearQhullMessage();
00198         QVERIFY(!q.hasQhullMessage());
00199     }
00200     {
00201         cout << "INFO   : Error output sent to output stream without error stream\n";
00202         Qhull q;
00203         q.setErrorStream(0);
00204         q.setOutputStream(&cout);
00205         try{
00206             q.runQhull(rcube, "Tz H0");
00207             QFAIL("runQhull TZ did not fail.");
00208         }catch (const std::exception &e) {
00209             const char *s= e.what();
00210             cout << "INFO   : Caught " << s;
00211             QCOMPARE(QString::fromAscii(s).left(6), QString("QH6023"));
00212         }
00213         //FIXUP QH11026 Qhullmessage cleared when QhullError thrown.  Switched to e
00214         //QVERIFY(q.hasQhullMessage());
00215         //QCOMPARE(QString::fromStdString(q.qhullMessage()).left(17), QString("qhull: no message"));
00216         //QCOMPARE(q.qhullStatus(), 6023);
00217         q.clearQhullMessage();
00218         QVERIFY(!q.hasQhullMessage());
00219     }
00220     {
00221         cout << "INFO   : No error stream or output stream\n";
00222         Qhull q;
00223         q.setErrorStream(0);
00224         q.setOutputStream(0);
00225         try{
00226             q.runQhull(rcube, "Fd");
00227             QFAIL("outputQhull did not fail.");
00228         }catch (const std::exception &e) {
00229             const char *s= e.what();
00230             cout << "INFO   : Caught " << s;
00231             QCOMPARE(QString::fromAscii(s).left(6), QString("QH6029"));
00232         }
00233         //FIXUP QH11026 Qhullmessage cleared when QhullError thrown.  Switched to e
00234         //QVERIFY(q.hasQhullMessage());
00235         //QCOMPARE(QString::fromStdString(q.qhullMessage()).left(9), QString("qhull err"));
00236         //QCOMPARE(q.qhullStatus(), 6029);
00237         q.clearQhullMessage();
00238         QVERIFY(!q.hasQhullMessage());
00239     }
00240 }//t_message
00241 
00242 void Qhull_test::
00243 t_getSet()
00244 {
00245     RboxPoints rcube("c");
00246     {
00247         Qhull q;
00248         QVERIFY(!q.initialized());
00249         q.runQhull(rcube, "s");
00250         QVERIFY(q.initialized());
00251         QCOMPARE(q.dimension(), 3);
00252         QhullPoint p= q.origin();
00253         QCOMPARE(p.dimension(), 3);
00254         QCOMPARE(p[0]+p[1]+p[2], 0.0);
00255         QVERIFY(q.runId()!=0);
00256         q.setErrorStream(&cout);
00257         q.outputQhull();
00258     }
00259     {
00260         Qhull q;
00261         q.runQhull(rcube, "");
00262         q.setOutputStream(&cout);
00263         q.outputQhull();
00264     }
00265     // qhullQh -- UsingLibQhull [Qhull.cpp]
00266     // runId -- UsingLibQhull [Qhull.cpp]
00267 }//t_getSet
00268 
00269 void Qhull_test::
00270 t_getQh()
00271 {
00272     RboxPoints rcube("c");
00273     {
00274         Qhull q;
00275         q.runQhull(rcube, "s");
00276         QCOMPARE(QString(q.qhullCommand()), QString("qhull s"));
00277         QCOMPARE(QString(q.rboxCommand()), QString("rbox \"c\""));
00278         QCOMPARE(q.facetCount(), 6);
00279         QCOMPARE(q.vertexCount(), 8);
00280         // Sample fields from Qhull's qhT [libqhull.h]
00281         QCOMPARE(q.qhullQh()->ALLpoints, 0u);
00282         QCOMPARE(q.qhullQh()->GOODpoint, 0);
00283         QCOMPARE(q.qhullQh()->IStracing, 0);
00284         QCOMPARE(q.qhullQh()->MAXcoplanar+1.0, 1.0); // fuzzy compare
00285         QCOMPARE(q.qhullQh()->MERGING, 1u);
00286         QCOMPARE(q.qhullQh()->input_dim, 3);
00287         QCOMPARE(QString(q.qhullQh()->qhull_options).left(8), QString("  run-id"));
00288         QCOMPARE(q.qhullQh()->run_id, q.runId());
00289         QCOMPARE(q.qhullQh()->num_facets, 6);
00290         QCOMPARE(q.qhullQh()->hasTriangulation, 0u);
00291         QCOMPARE(q.qhullQh()->max_outside - q.qhullQh()->min_vertex + 1.0, 1.0); // fuzzy compare
00292         QCOMPARE(*q.qhullQh()->gm_matrix+1.0, 1.0); // fuzzy compare
00293     }
00294 }//t_getQh
00295 
00296 void Qhull_test::
00297 t_getValue()
00298 {
00299     RboxPoints rcube("c");
00300     {
00301         Qhull q;
00302         q.runQhull(rcube, "");
00303         QCOMPARE(q.area(), 6.0);
00304         QCOMPARE(q.volume(), 1.0);
00305     }
00306 }//t_getValue
00307 
00308 void Qhull_test::
00309 t_foreach()
00310 {
00311     RboxPoints rcube("c");
00312     {
00313         Qhull q;
00314         QCOMPARE(q.beginFacet(),q.endFacet());
00315         QCOMPARE(q.beginVertex(),q.endVertex());
00316         q.runQhull(rcube, "");
00317         QCOMPARE(q.facetList().count(), 6);
00318 
00319         // defineVertexNeighborFacets() tested in QhullVertex_test::t_io()
00320 
00321         QhullFacetList facets(q.beginFacet(), q.endFacet());
00322         QCOMPARE(facets.count(), 6);
00323         QCOMPARE(q.firstFacet(), q.beginFacet());
00324         QhullVertexList vertices(q.beginVertex(), q.endVertex());
00325         QCOMPARE(vertices.count(), 8);
00326         QCOMPARE(q.firstVertex(), q.beginVertex());
00327         QhullPoints ps= q.points();
00328         QCOMPARE(ps.count(), 8);
00329         QhullPointSet ps2= q.otherPoints();
00330         QCOMPARE(ps2.count(), 0);
00331         // ps2= q.otherPoints(); //disabled, would not copy the points 
00332         QCOMPARE(q.facetCount(), 6);
00333         QCOMPARE(q.vertexCount(), 8);
00334         coordT *c= q.pointCoordinateBegin(); // of q.points()
00335         QVERIFY(*c==0.5 || *c==-0.5);
00336         coordT *c3= q.pointCoordinateEnd();
00337         QVERIFY(c3[-1]==0.5 || c3[-1]==-0.5);
00338         QCOMPARE(c3-c, 8*3);
00339         QCOMPARE(q.vertexList().count(), 8);
00340     }
00341 }//t_foreach
00342 
00343 void Qhull_test::
00344 t_modify()
00345 {
00346     //addPoint() tested in t_foreach
00347     RboxPoints diamond("d");
00348     Qhull q(diamond, "o");
00349     q.setOutputStream(&cout);
00350     cout << "Expecting vertexList and facetList of a 3-d diamond.\n";
00351     q.outputQhull();
00352     cout << "Expecting normals of a 3-d diamond.\n";
00353     q.outputQhull("n");
00354     // runQhull tested in t_attribute(), t_message(), etc.
00355 }//t_modify
00356 
00357 }//orgQhull
00358 
00359 // Redefine Qhull's usermem.c
00360 void qh_exit(int exitcode) {
00361     cout << "FAIL!  : Qhull called qh_exit().  Qhull's error handling not available.\n.. See the corresponding Qhull:qhull_message or setErrorStream().\n";
00362     exit(exitcode);
00363 }
00364 void qh_free(void *mem) {
00365     free(mem);
00366 }
00367 void *qh_malloc(size_t size) {
00368     return malloc(size);
00369 }
00370 
00371 #if 0
00372 template<> char * QTest::
00373 toString(const std::string &s)
00374 {
00375     QByteArray ba = s.c_str();
00376     return qstrdup(ba.data());
00377 }
00378 #endif
00379 
00380 #include "moc/Qhull_test.moc"
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


libqhull
Author(s): Robert Krug
autogenerated on Tue Jun 18 2013 12:38:50