Qhull(http://www.qhull.org/)是一個強大的計算幾何庫,可以用於計算高維的convex hull, Delaunay triangulation, Voronoi diagram等,在python中調用非常方便,最近由於需要將項目遷移到C++,因此折騰了一下。qhull的c++接口並不太完善,很多接口是基於Rbox(生成數據),因此我根據自身需要,修改了qhull的c++接口。
總體要求:輸入:3D/4D點集,輸出:對應的凸包。
主要修改libqhullcpp文件夾中的:Qhull.h 和 Qhull.cpp
1 Qhull.h 代碼修改
1 .1 Qhull.h 中增加3D/4D點集數據結構
struct vec3 {
double v[3];
vec3(double x_ = 0, double y_ = 0, double z_ = 0) {
v[0] = x_;
v[1] = y_;
v[2] = z_;
}
};
struct vec4 {
double v[4];
vec4(double x_ = 0, double y_ = 0, double z_ = 0, double w_ = 0) {
v[0] = x_;
v[1] = y_;
v[2] = z_;
v[3] = w_;
}
};
1 .2 Qhull.h 中增加接口
public:
void runQhull3D(const std::vector<vec3> &points, const char* args);
void runQhull4D(const std::vector<vec4> &points, const char* args);
void runQhull(const PointCoordinates &points, const char *qhullCommand2);
2 Qhull.cpp 代碼修改
void Qhull::runQhull3D(const std::vector<vec3> &points, const char* args)
{
m_externalPoints = new PointCoordinates(3, ""); //3 = dimension
vector<double> allPoints;
for each (vec3 p in points)
{
allPoints.push_back(p.v[0]);
allPoints.push_back(p.v[1]);
allPoints.push_back(p.v[2]);
}
m_externalPoints->append(allPoints); //convert to vector<double>
runQhull(*m_externalPoints, args);
}
void Qhull::runQhull4D(const std::vector<vec4> &points, const char* args)
{
m_externalPoints = new PointCoordinates(4, ""); //3 = dimension
vector<double> allPoints;
for each (vec4 p in points)
{
allPoints.push_back(p.v[0]);
allPoints.push_back(p.v[1]);
allPoints.push_back(p.v[2]);
allPoints.push_back(p.v[3]);
}
m_externalPoints->append(allPoints); //convert to vector<double>
runQhull(*m_externalPoints, args);
}
void Qhull::runQhull(const PointCoordinates &points, const char *qhullCommand2)
{
runQhull(points.comment().c_str(), points.dimension(), points.count(), &*points.coordinates(), qhullCommand2);
}
3.測試代碼
求如下立方體的凸包:
#include "libqhullcpp/QhullFacetList.h"
#include "libqhullcpp/Qhull.h"
#include <iostream>
#include <vector>
using namespace orgQhull;
using namespace std;
void print_facets(Qhull& qhull) {
QhullFacetList facets = qhull.facetList();
for (QhullFacetList::iterator it = facets.begin(); it != facets.end(); ++it)
{
if (!(*it).isGood()) continue;
QhullFacet f = *it;
QhullVertexSet vSet = f.vertices();
for (QhullVertexSet::iterator vIt = vSet.begin(); vIt != vSet.end(); ++vIt)
{
QhullVertex v = *vIt;
QhullPoint p = v.point();
cout << p.id() << " ";
}
cout << endl;
}
cout << endl;
}
int main(int argc, char **argv) {
Qhull qhull;
std::vector<vec3> vertices1(9);
vertices1[0] = vec3(0, 0, 0);
vertices1[1] = vec3(2, 0, 0);
vertices1[2] = vec3(2, 2, 0);
vertices1[3] = vec3(0, 2, 0);
vertices1[4] = vec3(0, 0, 2);
vertices1[5] = vec3(2, 0, 2);
vertices1[6] = vec3(2, 2, 2);
vertices1[7] = vec3(0, 2, 2);
vertices1[8] = vec3(0, 0, 0);
qhull.runQhull3D(vertices1, "Qt");
print_facets(qhull);
}
輸出:
3 2 1
3 1 0
5 1 0
5 4 0
7 3 0
7 4 0
6 2 1
6 5 1
6 3 2
6 7 3
6 5 4
6 7 4