Speed up 3D convex hull() by a few orders of magnitude by using a more suitable kernel

master
Oskar Linde 2014-05-22 15:01:14 +02:00
parent 35c2a5e5ca
commit 02cb1f0ca8
3 changed files with 43 additions and 59 deletions

View File

@ -97,15 +97,13 @@ GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren3D(const Abstr
if (children.size() == 0) return ResultObject();
if (op == OPENSCAD_HULL) {
CGAL_Polyhedron P;
if (CGALUtils::applyHull(children, P)) {
PolySet *ps = new PolySet(3);
PolySet *ps = new PolySet(3);
if (!createPolySetFromPolyhedron(P, *ps)) {
return ResultObject(ps);
}
delete ps;
if (CGALUtils::applyHull(children, *ps)) {
return ps;
}
delete ps;
return ResultObject();
}
@ -153,10 +151,11 @@ Geometry *GeometryEvaluator::applyHull3D(const AbstractNode &node)
{
Geometry::ChildList children = collectChildren3D(node);
CGAL_Polyhedron P;
if (CGALUtils::applyHull(children, P)) {
return new CGAL_Nef_polyhedron(new CGAL_Nef_polyhedron3(P));
PolySet *P = new PolySet(3);
if (CGALUtils::applyHull(children, *P)) {
return P;
}
delete P;
return NULL;
}

View File

@ -9,6 +9,7 @@
#include "cgal.h"
#include <CGAL/convex_hull_3.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include "svg.h"
#include "Reindexer.h"
@ -17,25 +18,26 @@
namespace CGALUtils {
bool applyHull(const Geometry::ChildList &children, CGAL_Polyhedron &result)
bool applyHull(const Geometry::ChildList &children, PolySet &result)
{
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
// Collect point cloud
std::vector<CGAL_Polyhedron::Vertex::Point_3> points;
CGAL_Polyhedron P;
std::set<K::Point_3> points;
BOOST_FOREACH(const Geometry::ChildItem &item, children) {
const shared_ptr<const Geometry> &chgeom = item.second;
const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron *>(chgeom.get());
if (N) {
for (CGAL_Nef_polyhedron3::Vertex_const_iterator i = N->p3->vertices_begin(); i != N->p3->vertices_end(); ++i) {
points.push_back(i->point());
points.insert(K::Point_3(to_double(i->point()[0]),to_double(i->point()[1]),to_double(i->point()[2])));
}
}
else {
} else {
const PolySet *ps = dynamic_cast<const PolySet *>(chgeom.get());
BOOST_FOREACH(const PolySet::Polygon &p, ps->polygons) {
BOOST_FOREACH(const Vector3d &v, p) {
points.push_back(CGAL_Polyhedron::Vertex::Point_3(v[0], v[1], v[2]));
if (ps) {
BOOST_FOREACH(const PolySet::Polygon &p, ps->polygons) {
BOOST_FOREACH(const Vector3d &v, p) {
points.insert(K::Point_3(v[0], v[1], v[2]));
}
}
}
}
@ -43,23 +45,13 @@ namespace CGALUtils {
if (points.size() <= 3) return false;
// Remove all duplicated points (speeds up the convex_hull computation significantly)
std::vector<CGAL_Polyhedron::Vertex::Point_3> unique_points;
Grid3d<int> grid(GRID_FINE);
BOOST_FOREACH(CGAL_Polyhedron::Vertex::Point_3 const& p, points) {
double x = to_double(p.x()), y = to_double(p.y()), z = to_double(p.z());
int& v = grid.align(x,y,z);
if (v == 0) {
unique_points.push_back(CGAL_Polyhedron::Vertex::Point_3(x,y,z));
v = 1;
}
}
// Apply hull
if (points.size() >= 4) {
CGAL::convex_hull_3(unique_points.begin(), unique_points.end(), result);
return true;
CGAL::Polyhedron_3<K> r;
CGAL::convex_hull_3(points.begin(), points.end(), r);
if (!createPolySetFromPolyhedron(r, result))
return true;
return false;
} else {
return false;
}
@ -345,41 +337,34 @@ namespace CGALUtils {
};
bool createPolySetFromPolyhedron(const CGAL_Polyhedron &p, PolySet &ps)
template <typename Polyhedron>
bool createPolySetFromPolyhedron(const Polyhedron &p, PolySet &ps)
{
bool err = false;
typedef CGAL_Polyhedron::Vertex Vertex;
typedef CGAL_Polyhedron::Vertex_const_iterator VCI;
typedef CGAL_Polyhedron::Facet_const_iterator FCI;
typedef CGAL_Polyhedron::Halfedge_around_facet_const_circulator HFCC;
typedef typename Polyhedron::Vertex Vertex;
typedef typename Polyhedron::Vertex_const_iterator VCI;
typedef typename Polyhedron::Facet_const_iterator FCI;
typedef typename Polyhedron::Halfedge_around_facet_const_circulator HFCC;
for (FCI fi = p.facets_begin(); fi != p.facets_end(); ++fi) {
HFCC hc = fi->facet_begin();
HFCC hc_end = hc;
Vertex v1, v2, v3;
v1 = *VCI((hc++)->vertex());
v3 = *VCI((hc++)->vertex());
ps.append_poly();
do {
v2 = v3;
v3 = *VCI((hc++)->vertex());
double x1 = CGAL::to_double(v1.point().x());
double y1 = CGAL::to_double(v1.point().y());
double z1 = CGAL::to_double(v1.point().z());
double x2 = CGAL::to_double(v2.point().x());
double y2 = CGAL::to_double(v2.point().y());
double z2 = CGAL::to_double(v2.point().z());
double x3 = CGAL::to_double(v3.point().x());
double y3 = CGAL::to_double(v3.point().y());
double z3 = CGAL::to_double(v3.point().z());
ps.append_poly();
ps.append_vertex(x1, y1, z1);
ps.append_vertex(x2, y2, z2);
ps.append_vertex(x3, y3, z3);
Vertex const& v = *((hc++)->vertex());
double x = CGAL::to_double(v.point().x());
double y = CGAL::to_double(v.point().y());
double z = CGAL::to_double(v.point().z());
ps.append_vertex(x, y, z);
} while (hc != hc_end);
}
return err;
}
template bool createPolySetFromPolyhedron(const CGAL_Polyhedron &p, PolySet &ps);
template bool createPolySetFromPolyhedron(const CGAL::Polyhedron_3<CGAL::Epick> &p, PolySet &ps);
/////// Tessellation begin
typedef CGAL::Plane_3<CGAL_Kernel3> CGAL_Plane_3;

View File

@ -6,7 +6,7 @@
#include "enums.h"
namespace CGALUtils {
bool applyHull(const Geometry::ChildList &children, CGAL_Polyhedron &P);
bool applyHull(const Geometry::ChildList &children, PolySet &P);
void applyOperator(const Geometry::ChildList &children, CGAL_Nef_polyhedron &dest, OpenSCADOperator op);
void applyBinaryOperator(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, OpenSCADOperator op);
Polygon2d *project(const CGAL_Nef_polyhedron &N, bool cut);
@ -14,7 +14,7 @@ namespace CGALUtils {
};
CGAL_Nef_polyhedron *createNefPolyhedronFromGeometry(const class Geometry &geom);
bool createPolySetFromPolyhedron(const CGAL_Polyhedron &p, PolySet &ps);
template <typename Polyhedron> bool createPolySetFromPolyhedron(const Polyhedron &p, PolySet &ps);
bool createPolySetFromNefPolyhedron3(const CGAL_Nef_polyhedron3 &N, PolySet &ps);
bool createPolyhedronFromPolySet(const PolySet &ps, CGAL_Polyhedron &p);