qhull Library - C++ Interface

qhull Library - C++ Interface

本文关键字:Interface C++ Library qhull      更新时间:2023-10-16

qhull 库 ( qhull.org) 在他的网站上有几个示例可以开始,但有关C++的所有信息对我来说都不是很有用。

我正在尝试制作从文件中读取的 3D 点的简单凸包,我不能使用调用 qhull 的网站中建议的技术.exe作为外部应用程序,因为我需要根据我在数据点中所做的一些修改制作几个凸包。

我找不到一个简单的例子来做到这一点,有人可以在这个任务中给我一些帮助吗?任何信息都将是有用的。

谢谢

由于我自己很难将 Qhull 与 c++ 一起使用,并且在网络上找不到任何有用的示例,并且最终成功地获得了有效的结果,因此我在此处发布我的代码以备将来使用。

这个答案适用于Windows,Visual Studio 2012/3。我不知道它如何或是否在其他平台上工作

因此,首先,从此处下载qhull源文件后并在VS中打开一个项目,您唯一需要添加的文件是以下2个目录:

libqhull/
libqhullcpp/

将这些文件添加到您的项目中后,添加以下代码(这是我的方式,显然您可以使用自己的方式):

Qhull.h

namespace orgQhull{
//...
private:
    PointCoordinates *m_externalPoints;
//...
public:
    void runQhull3D(const std::vector<vec3> &points, const char* args);
    void runQhull(const PointCoordinates &points, const char *qhullCommand2);
//...
}

库尔.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.x());
        allPoints.push_back(p.y());
        allPoints.push_back(p.z());
    }
    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);
}

最后,这是如何使用代码:

//not sure all these includes are needed
#include "RboxPoints.h"
#include "QhullError.h"
#include "Qhull.h"
#include "QhullQh.h"
#include "QhullFacet.h"
#include "QhullFacetList.h"
#include "QhullLinkedList.h"
#include "QhullVertex.h"
#include "QhullSet.h"
#include "QhullVertexSet.h"
#include <vector>
int main()
{
    orgQhull::Qhull qhull;
    std::vector<vec3> vertices;
    qhull.runQhull3D(vertices, "Qt");
    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();
            double * coords = p.coordinates();
            vec3 aPoint = vec3(coords[0], coords[1], coords[2]);
            // ...Do what ever you want
        }
    }
    
    // Another way to iterate (c++11), and the way the get the normals
    std::vector<std::pair<vec3, double> > facetsNormals;
    for each (QhullFacet facet : qhull.facetList().toStdVector())
    {
        if (facet.hyperplane().isDefined())
        {
            auto coord = facet.hyperplane().coordinates();
            vec3 normal(coord[0], coord[1], coord[2]);
            double offset = facet.hyperplane().offset();
            facetsNormals.push_back(std::pair<vec3, double>(normal, offset));
        }
    }
}

请注意,我从项目中复制了此代码,并对其进行了一些修改以提供更多信息,但尚未编译此示例。

下面是一个使用来自 c++ 的重入 qhull 的简单示例。我认为这可能有用。

#include <iostream>
#include <vector>
#include <string>
#include "Qhull.h"
int main(int argc, char const *argv[])
{
    std::vector<double> points_3D = {0, 0, 0,
                                     0, 1, 0,
                                     1, 1, 0,
                                     1, 0, 0,
                                     0, 0, 1,
                                     0, 1, 1,
                                     1, 1, 1,
                                     1, 0, 1};
    int ndim = 3;
    int num_points = points_3D.size() / ndim;
    std::string comment = ""; // rbox commands, see http://www.qhull.org/html/rbox.htm
    std::string qhull_command = ""; // For qhull commands, see http://www.qhull.org/html/qhull.htm
    try
    {
        orgQhull::Qhull qhull = orgQhull::Qhull(comment.c_str(), ndim, num_points, points_3D.data(), qhull_command.c_str());
        std::cout << "qhull.hullDimension(): " << qhull.hullDimension() << "n";
        std::cout << "qhull.volume(): " << qhull.volume() << "n";
        std::cout << "qhull.area(): " << qhull.area() << "n";
    }
    catch (orgQhull::QhullError &e)
    {
        std::cerr << e.what() << std::endl;
        return e.errorCode();
    }
}

这篇文章是我能找到的唯一 qHull 示例,所以我想添加这段代码,介绍如何使用 qhull 获取 2D 点集的凸包。

#include <vector>
#include "my_point.h"
#include "libqhullcpp/Qhull.h"
#include "libqhullcpp/QhullVertex.h"
#include "libqhullcpp/QhullVertexSet.h"
#include "libqhullcpp/QhullPoint.h"
std::vector<my_point> getConvexHull2D(const std::vector<my_point> &scatteredPoints)
{
  std::vector<my_point> cHull;
  if(scatteredPoints.size() < 3) return cHull;
  std::vector<double> inputVertices;
  for(int i = 0; i < (int)scatteredPoints.size(); i++)
  {
    const my_point &pt = scatteredPoints[i];
    inputVertices.push_back(pt.x);
    inputVertices.push_back(pt.y);
  }
  orgQhull::Qhull qhull;
  int ndim = 2;
  int num_points = inputVertices.size() / ndim;
  const char *inputComments = "";
  const char *qHullCommands = "";
  qhull.runQhull(inputComments, ndim, num_points, inputVertices.data(), qHullCommands);
  for(const orgQhull::QhullVertex &v: qhull.vertexList())
  {
    const orgQhull::QhullPoint &qhullPt = v.point();
    auto coords = qhullPt.coordinates(); // list of doubles
    cHull.push_back(my_point(coords[0], coords[1]));
  }
  // the vertices are not sorted?
  CCWSort(cHull.data(), cHull.size());
  return cHull;
}

除了向包含路径添加qhull/src之外,我还必须构建库并链接qhullcpp.libqhullstatic_r.lib。包含一个Qt项目,您可以打开并构建它将为您构建库。

我尝试首先使用 boost,但它与一些遗留代码冲突太多。这可能不是最有效的实现,但它比我以前做的要好得多。