问题描述
我对计算几何完全陌生。我想生成一组点的凸包,然后获取生成的凸多面体的平面方程,以便检查点的包含/排除。我遵循了文档,并尝试了整个过程大约十二次,但始终存在一些问题。也许我在这里缺少一些细微之处。整个过程如下。我有以下在Mathematica中生成的图。
我想将凸包中绘图上的每个点都包括在内。因此,我将位于两个平面和原点上所有角的所有点都取了(也许是问题所在。也许有一种方法可以正确选择点,以便覆盖图中的所有点)。该特定图的点如下。请注意,这些点是使用无限精度生成的,因此它们是精确值。
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
的输入值是不同的。
现在,我真的不需要无限精度来解决我的问题。但是我想确保该过程可以无限精确地工作,以便使我对正确性充满信心。但是随后,我尝试使用仅使用64位的CPLEX,并且也以与Z3类似的方式生成了反例。这是一个例子
现在我不知道我在过程的哪一步犯了错误。我怀疑是凸包的起始点的选择。如果有人可以帮助我正确地找到凸包,那将是很好的。据我所读,如果使用无限精度,则凸包算法是精确的。这就是为什么我不使用Mathematica的凸包特征的原因,因为它没有使用无限精度。
编辑:Mathematica无法显示两个较小的平面,如下所示。我也希望选择这些平面上的所有点。但是,较小平面的端点与较大平面的端点一致。这就是为什么我只取较大飞机的角。
编辑2:由于y的范围与其他两个变量相比太大,为上述指定点生成的凸包看起来就像一条直线。
但是,将y值除以1000后,我们可以看到更清晰的图片。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)