mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-03 08:12:07 +00:00
Move many third-party components' source codes from the src folder to a new folder called deps_src. The goal is to make the code structure clearer and easier to navigate.
284 lines
9.4 KiB
C++
284 lines
9.4 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (c) 2008-2015 C.B. Barber. All rights reserved.
|
|
** $Id: //main/2015/qhull/src/qhulltest/QhullFacet_test.cpp#4 $$Change: 2062 $
|
|
** $DateTime: 2016/01/17 13:13:18 $$Author: bbarber $
|
|
**
|
|
****************************************************************************/
|
|
|
|
//pre-compiled headers
|
|
#include <iostream>
|
|
#include "qhulltest/RoadTest.h" // QT_VERSION
|
|
|
|
#include "libqhullcpp/QhullFacet.h"
|
|
#include "libqhullcpp/QhullError.h"
|
|
#include "libqhullcpp/Coordinates.h"
|
|
#include "libqhullcpp/RboxPoints.h"
|
|
#include "libqhullcpp/QhullFacetList.h"
|
|
#include "libqhullcpp/QhullFacetSet.h"
|
|
#include "libqhullcpp/QhullPointSet.h"
|
|
#include "libqhullcpp/QhullRidge.h"
|
|
#include "libqhullcpp/Qhull.h"
|
|
|
|
using std::cout;
|
|
using std::endl;
|
|
using std::ostringstream;
|
|
using std::ostream;
|
|
using std::string;
|
|
|
|
namespace orgQhull {
|
|
|
|
class QhullFacet_test : public RoadTest
|
|
{
|
|
Q_OBJECT
|
|
|
|
#//!\name Test slots
|
|
private slots:
|
|
void cleanup();
|
|
void t_construct_qh();
|
|
void t_constructConvert();
|
|
void t_getSet();
|
|
void t_value();
|
|
void t_foreach();
|
|
void t_io();
|
|
};//QhullFacet_test
|
|
|
|
void
|
|
add_QhullFacet_test()
|
|
{
|
|
new QhullFacet_test(); // RoadTest::s_testcases
|
|
}
|
|
|
|
//Executed after each testcase
|
|
void QhullFacet_test::
|
|
cleanup()
|
|
{
|
|
RoadTest::cleanup();
|
|
}
|
|
|
|
void QhullFacet_test::
|
|
t_construct_qh()
|
|
{
|
|
// Qhull.runQhull() constructs QhullFacets as facetT
|
|
QhullQh qh;
|
|
QhullFacet f(&qh);
|
|
QVERIFY(!f.isValid());
|
|
QCOMPARE(f.dimension(),0);
|
|
}//t_construct_qh
|
|
|
|
void QhullFacet_test::
|
|
t_constructConvert()
|
|
{
|
|
// Qhull.runQhull() constructs QhullFacets as facetT
|
|
Qhull q2;
|
|
QhullFacet f(q2);
|
|
QVERIFY(!f.isValid());
|
|
QCOMPARE(f.dimension(),0);
|
|
RboxPoints rcube("c");
|
|
Qhull q(rcube,"Qt QR0"); // triangulation of rotated unit cube
|
|
QhullFacet f2(q.beginFacet());
|
|
QCOMPARE(f2.dimension(),3);
|
|
f= f2; // copy assignment
|
|
QVERIFY(f.isValid());
|
|
QCOMPARE(f.dimension(),3);
|
|
QhullFacet f5= f2;
|
|
QVERIFY(f5==f2);
|
|
QVERIFY(f5==f);
|
|
QhullFacet f3(q, f2.getFacetT());
|
|
QCOMPARE(f,f3);
|
|
QhullFacet f4(q, f2.getBaseT());
|
|
QCOMPARE(f,f4);
|
|
}//t_constructConvert
|
|
|
|
void QhullFacet_test::
|
|
t_getSet()
|
|
{
|
|
RboxPoints rcube("c");
|
|
{
|
|
Qhull q(rcube,"Qt QR0"); // triangulation of rotated unit cube
|
|
cout << " rbox c | qhull Qt QR0 QR" << q.rotateRandom() << " distanceEpsilon " << q.distanceEpsilon() << endl;
|
|
QCOMPARE(q.facetCount(), 12);
|
|
QCOMPARE(q.vertexCount(), 8);
|
|
QhullFacetListIterator i(q.facetList());
|
|
while(i.hasNext()){
|
|
const QhullFacet f= i.next();
|
|
cout << f.id() << endl;
|
|
QCOMPARE(f.dimension(),3);
|
|
QVERIFY(f.id()>0 && f.id()<=39);
|
|
QVERIFY(f.isValid());
|
|
if(i.hasNext()){
|
|
QCOMPARE(f.next(), i.peekNext());
|
|
QVERIFY(f.next()!=f);
|
|
}
|
|
QVERIFY(i.hasPrevious());
|
|
QCOMPARE(f, i.peekPrevious());
|
|
}
|
|
|
|
// test tricoplanarOwner
|
|
QhullFacet facet = q.beginFacet();
|
|
QhullFacet tricoplanarOwner = facet.tricoplanarOwner();
|
|
int tricoplanarCount= 0;
|
|
i.toFront();
|
|
while(i.hasNext()){
|
|
const QhullFacet f= i.next();
|
|
if(f.tricoplanarOwner()==tricoplanarOwner){
|
|
tricoplanarCount++;
|
|
}
|
|
}
|
|
QCOMPARE(tricoplanarCount, 2);
|
|
int tricoplanarCount2= 0;
|
|
foreach (QhullFacet f, q.facetList()){ // Qt only
|
|
QhullHyperplane h= f.hyperplane();
|
|
cout << "Hyperplane: " << h;
|
|
QCOMPARE(h.count(), 3);
|
|
QCOMPARE(h.offset(), -0.5);
|
|
double n= h.norm();
|
|
QCOMPARE(n, 1.0);
|
|
QhullHyperplane hi= f.innerplane();
|
|
QCOMPARE(hi.count(), 3);
|
|
double innerOffset= hi.offset()+0.5;
|
|
cout << "InnerPlane: " << hi << " innerOffset+0.5 " << innerOffset << endl;
|
|
QVERIFY(innerOffset >= 0.0-(2*q.distanceEpsilon())); // A guessed epsilon. It needs to account for roundoff due to rotation of the vertices
|
|
QhullHyperplane ho= f.outerplane();
|
|
QCOMPARE(ho.count(), 3);
|
|
double outerOffset= ho.offset()+0.5;
|
|
cout << "OuterPlane: " << ho << " outerOffset+0.5 " << outerOffset << endl;
|
|
QVERIFY(outerOffset <= 0.0+(2*q.distanceEpsilon())); // A guessed epsilon. It needs to account for roundoff due to rotation of the vertices
|
|
QVERIFY(outerOffset-innerOffset < 1e-7);
|
|
for(int k= 0; k<3; k++){
|
|
QVERIFY(ho[k]==hi[k]);
|
|
QVERIFY(ho[k]==h[k]);
|
|
}
|
|
QhullPoint center= f.getCenter();
|
|
cout << "Center: " << center;
|
|
double d= f.distance(center);
|
|
QVERIFY(d < innerOffset-outerOffset);
|
|
QhullPoint center2= f.getCenter(qh_PRINTcentrums);
|
|
QCOMPARE(center, center2);
|
|
if(f.tricoplanarOwner()==tricoplanarOwner){
|
|
tricoplanarCount2++;
|
|
}
|
|
cout << endl;
|
|
}
|
|
QCOMPARE(tricoplanarCount2, 2);
|
|
Qhull q2(rcube,"d Qz Qt QR0"); // 3-d triangulation of Delaunay triangulation (the cube)
|
|
cout << " rbox c | qhull d Qz Qt QR0 QR" << q2.rotateRandom() << " distanceEpsilon " << q2.distanceEpsilon() << endl;
|
|
QhullFacet f2= q2.firstFacet();
|
|
QhullPoint center3= f2.getCenter(qh_PRINTtriangles);
|
|
QCOMPARE(center3.dimension(), 3);
|
|
QhullPoint center4= f2.getCenter();
|
|
QCOMPARE(center4.dimension(), 4);
|
|
for(int k= 0; k<3; k++){
|
|
QVERIFY(center4[k]==center3[k]);
|
|
}
|
|
Qhull q3(rcube,"v Qz QR0"); // Voronoi diagram of a cube (one vertex)
|
|
cout << " rbox c | qhull v Qz QR0 QR" << q3.rotateRandom() << " distanceEpsilon " << q3.distanceEpsilon() << endl;
|
|
|
|
q3.setFactorEpsilon(400); // Voronoi vertices are not necessarily within distance episilon
|
|
QhullPoint origin= q3.inputOrigin();
|
|
int voronoiCount= 0;
|
|
foreach(QhullFacet f, q3.facetList()){ //Qt only
|
|
if(f.isGood()){
|
|
++voronoiCount;
|
|
QhullPoint p= f.voronoiVertex();
|
|
cout << p.print("Voronoi vertex: ")
|
|
<< " Is it within " << q3.factorEpsilon() << " * distanceEpsilon (" << q3.distanceEpsilon() << ") of the origin?" << endl;
|
|
QCOMPARE(p, origin);
|
|
}
|
|
}
|
|
QCOMPARE(voronoiCount, 1);
|
|
}
|
|
}//t_getSet
|
|
|
|
void QhullFacet_test::
|
|
t_value()
|
|
{
|
|
RboxPoints rcube("c");
|
|
{
|
|
Qhull q(rcube, "");
|
|
coordT c[]= {0.0, 0.0, 0.0};
|
|
foreach (QhullFacet f, q.facetList()){ // Qt only
|
|
double d= f.distance(q.origin());
|
|
QCOMPARE(d, -0.5);
|
|
double d0= f.distance(c);
|
|
QCOMPARE(d0, -0.5);
|
|
double facetArea= f.facetArea();
|
|
QCOMPARE(facetArea, 1.0);
|
|
#if qh_MAXoutside
|
|
double maxoutside= f.getFacetT()->maxoutside;
|
|
QVERIFY(maxoutside<1e-7);
|
|
#endif
|
|
}
|
|
}
|
|
}//t_value
|
|
|
|
void QhullFacet_test::
|
|
t_foreach()
|
|
{
|
|
RboxPoints rcube("c W0 300"); // cube plus 300 points on its surface
|
|
{
|
|
Qhull q(rcube, "QR0 Qc"); // keep coplanars, thick facet, and rotate the cube
|
|
int coplanarCount= 0;
|
|
foreach(const QhullFacet f, q.facetList()){
|
|
QhullPointSet coplanars= f.coplanarPoints();
|
|
coplanarCount += coplanars.count();
|
|
QhullFacetSet neighbors= f.neighborFacets();
|
|
QCOMPARE(neighbors.count(), 4);
|
|
QhullPointSet outsides= f.outsidePoints();
|
|
QCOMPARE(outsides.count(), 0);
|
|
QhullRidgeSet ridges= f.ridges();
|
|
QCOMPARE(ridges.count(), 4);
|
|
QhullVertexSet vertices= f.vertices();
|
|
QCOMPARE(vertices.count(), 4);
|
|
int ridgeCount= 0;
|
|
QhullRidge r= ridges.first();
|
|
for(int r0= r.id(); ridgeCount==0 || r.id()!=r0; r= r.nextRidge3d(f)){
|
|
++ridgeCount;
|
|
if(!r.hasNextRidge3d(f)){
|
|
QFAIL("Unexpected simplicial facet. They only have ridges to non-simplicial neighbors.");
|
|
}
|
|
}
|
|
QCOMPARE(ridgeCount, 4);
|
|
}
|
|
QCOMPARE(coplanarCount, 300);
|
|
}
|
|
}//t_foreach
|
|
|
|
void QhullFacet_test::
|
|
t_io()
|
|
{
|
|
RboxPoints rcube("c");
|
|
{
|
|
Qhull q(rcube, "");
|
|
QhullFacet f= q.beginFacet();
|
|
cout << f;
|
|
ostringstream os;
|
|
os << f.print("\nWith a message\n");
|
|
os << "\nPrint header for the same facet\n";
|
|
os << f.printHeader();
|
|
os << "\nPrint each component\n";
|
|
os << f.printFlags(" - flags:");
|
|
os << f.printCenter(qh_PRINTfacets, " - center: ");
|
|
os << f.printRidges();
|
|
cout << os.str();
|
|
ostringstream os2;
|
|
os2 << f;
|
|
QString facetString2= QString::fromStdString(os2.str());
|
|
facetString2.replace(QRegExp("\\s\\s+"), " ");
|
|
ostringstream os3;
|
|
q.qh()->setOutputStream(&os3);
|
|
q.outputQhull("f");
|
|
QString facetsString= QString::fromStdString(os3.str());
|
|
QString facetString3= facetsString.mid(facetsString.indexOf("- f1\n"));
|
|
facetString3= facetString3.left(facetString3.indexOf("\n- f")+1);
|
|
facetString3.replace(QRegExp("\\s\\s+"), " ");
|
|
QCOMPARE(facetString2, facetString3);
|
|
}
|
|
}//t_io
|
|
|
|
// toQhullFacet is static_cast only
|
|
|
|
}//orgQhull
|
|
|
|
#include "moc/QhullFacet_test.moc"
|