正确生成凸包并获得平面方程

问题描述

我对计算几何完全陌生。我想生成一组点的凸包,然后获取生成的凸多面体的平面方程,以便检查点的包含/排除。我遵循了文档,并尝试了整个过程大约十二次,但始终存在一些问题。也许我在这里缺少一些细微之处。整个过程如下。我有以下在Mathematica中生成的图。

A plot,generated from a secret function

我想将凸包中绘图上的每个点都包括在内。因此,我将位于两个平面和原点上所有角的所有点都取了(也许是问题所在。也许有一种方法可以正确选择点,以便覆盖图中的所有点)。该特定图的点如下。请注意,这些点是使用无限精度生成的,因此它们是精确值。

pts = {
  {-24298771/25000000000,-223461425901/50000000000,0},{11285077/10000000000,{-24298771/25000000000,-11285077/10000000000,120551411529/25000000000,-24298771/25000000000},11285077/10000000000},24298771/25000000000,{0,0}
};

然后,我使用以下CGAL程序生成凸包和平面方程。同样,尝试使事物保持无限的精度。

#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/GMP/Gmpq_type.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/convex_hull_3.h>
#include <CGAL/Side_of_triangle_mesh.h>
#include <CGAL/number_utils.h>
#include <unistd.h>
#include <iomanip>

typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron_3;
typedef Kernel::Point_3 Point_3;
typedef Kernel::Plane_3 Plane_3;
typedef Kernel::Vector_3 Vector_3;
typedef CGAL::Side_of_triangle_mesh<Polyhedron_3,Kernel> Point_inside;

struct Plane_equation {
    template <class Facet>
    typename Facet::Plane_3 operator()( Facet& f) {
    typename Facet::Halfedge_handle h = f.halfedge();
    typedef typename Facet::Plane_3  Plane;
    return Plane( h->vertex()->point(),h->next()->vertex()->point(),h->next()->next()->vertex()->point());
    }
};

Point_3 create_point(std::vector<std::string> points) {
  auto x = points[0],y = points[1],z = points[2];
  Point_3 p;
  std::istringstream input(x + " " + y + " " + z);
  input >> p;
  return p;
}

std::vector<std::string> create_coords_from_line(std::string line) {
  std::vector<std::string> points;
  std::istringstream stream(line);
  std::string pt;
  getline(stream,pt,' ');
  points.push_back(pt);
  getline(stream,pt);
  points.push_back(pt);
  return points;
}

int main() {
    std::vector<Point_3> points;
    std::string line;

    for (auto i = 0; i < 9; ++i) {
      getline(std::cin,line);
      points.push_back(create_point(create_coords_from_line(line)));
    }

    Polyhedron_3 poly;
    CGAL::convex_hull_3(points.begin(),points.end(),poly);
    // CGAL::draw(poly);
    std::transform(poly.facets_begin(),poly.facets_end(),poly.planes_begin(),Plane_equation());
    CGAL::set_pretty_mode(std::cout);

    for (auto it = poly.planes_begin(); it != poly.planes_end(); ++it) {
      if (isatty(fileno(stdin))) {
        std::cout << "A = " << it->a().exact() << "\n";
        std::cout << "B = " << it->b().exact() << "\n";
        std::cout << "C = " << it->c().exact() << "\n";
        std::cout << "D = " << it->d().exact() << "\n";
        std::cout << "\n";
      } else {
        std::cout << it->a().exact() << " " << it->b().exact() << " "
                  << it->c().exact() << " " << it->d().exact() << "\n";
      }
    }

    return EXIT_SUCCESS;
}

现在,为了确保所生成的方程式正确并涵盖所有要点,我创建了一个Z3py脚本。其中,f是用于生成图的函数,g是具有适当不等式()的所有平面方程的合集。然后,我检查是否为f ---> g。我将实数理论用于无限精度。但是它总是带有反例。这些反例总是在平面的某个边缘上。这是几张图片,其中红色圆圈表示反例的位置。这与上面的图不同,但是过程相同。只是f的输入值是不同的。

Plot with counterexample 1

Plot with counterexample 2

现在,我真的不需要无限精度来解决我的问题。但是我想确保该过程可以无限精确地工作,以便使我对正确性充满信心。但是随后,我尝试使用仅使用64位的CPLEX,并且也以与Z3类似的方式生成了反例。这是一个例子

Plot with CPLEX counterexample

现在我不知道我在过程的哪一步犯了错误。我怀疑是凸包的起始点的选择。如果有人可以帮助我正确地找到凸包,那将是很好的。据我所读,如果使用无限精度,则凸包算法是精确的。这就是为什么我不使用Mathematica的凸包特征的原因,因为它没有使用无限精度。

编辑:Mathematica无法显示两个较小的平面,如下所示。我也希望选择这些平面上的所有点。但是,较小平面的端点与较大平面的端点一致。这就是为什么我只取较大飞机的角。

Smaller planes

编辑2:由于y的范围与其他两个变量相比太大,为上述指定点生成的凸包看起来就像一条直线。

original Convex hull

但是,将y值除以1000后,我们可以看到更清晰的图片。

smaller convex hull

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...