This should fix Clipper-based non-cut projection

customizer
Marius Kintel 2013-11-26 01:31:55 -05:00
parent b2945cc714
commit 2ca39595cd
3 changed files with 46 additions and 9 deletions

View File

@ -112,7 +112,7 @@ Geometry *GeometryEvaluator::applyToChildren3D(const AbstractNode &node, OpenSCA
// cache could have been modified before we reach this point due to a large
// sibling object.
if (!CGALCache::instance()->contains(this->tree.getIdString(*chnode))) {
CGALCache::instance()->insert(this->tree.getIdString(*chnode), *chN);
CGALCache::instance()->insert(this->tree.getIdString(*chnode), chN ? *chN : CGAL_Nef_polyhedron());
}
if (chgeom) {
@ -644,7 +644,33 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node)
// FIXME: Don't use deep access to modinst members
if (chnode->modinst->isBackground()) continue;
const Polygon2d *poly = NULL;
// CGAL version of Geometry projection
// Causes crashes in createNefPolyhedronFromGeometry() for this model:
// projection(cut=false) {
// cube(10);
// difference() {
// sphere(10);
// cylinder(h=30, r=5, center=true);
// }
// }
#if 0
shared_ptr<const PolySet> chPS = dynamic_pointer_cast<const PolySet>(chgeom);
const PolySet *ps2d = NULL;
shared_ptr<const CGAL_Nef_polyhedron> chN = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(chgeom);
if (chN) chPS.reset(chN->convertToPolyset());
if (chPS) ps2d = PolysetUtils::flatten(*chPS);
if (ps2d) {
CGAL_Nef_polyhedron *N2d = createNefPolyhedronFromGeometry(*ps2d);
poly = N2d->convertToPolygon2d();
}
#endif
// Clipper version of Geometry projection
// Clipper doesn't handle meshes very well.
// It's better in V6 but not quite there. FIXME: stand-alone example.
#if 1
// project chgeom -> polygon2d
shared_ptr<const PolySet> chPS = dynamic_pointer_cast<const PolySet>(chgeom);
if (!chPS) {
@ -653,9 +679,10 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node)
chPS.reset(chN->convertToPolyset());
}
}
if (chPS) {
const Polygon2d *poly = PolysetUtils::project(*chPS);
if (chPS) poly = PolysetUtils::project(*chPS);
#endif
if (poly) {
ClipperLib::Polygons result = ClipperUtils::fromPolygon2d(*poly);
// Using NonZero ensures that we don't create holes from polygons sharing
// edges since we're unioning a mesh
@ -667,6 +694,8 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node)
}
}
ClipperLib::Polygons sumresult;
// This is key - without StrictlySimple, we tend to get self-intersecting results
sumclipper.StrictlySimple(true);
sumclipper.Execute(ClipperLib::ctUnion, sumresult, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
geom.reset(ClipperUtils::toPolygon2d(sumresult));
}

View File

@ -10,6 +10,10 @@ namespace ClipperUtils {
BOOST_FOREACH(const Vector2d &v, outline) {
p.push_back(ClipperLib::IntPoint(v[0]*CLIPPER_SCALE, v[1]*CLIPPER_SCALE));
}
// Make sure all polygons point up, since we project also
// back-facing polygon in PolysetUtils::project()
if (!ClipperLib::Orientation(p)) std::reverse(p.begin(), p.end());
result.push_back(p);
}
return result;
@ -19,9 +23,13 @@ namespace ClipperUtils {
Polygon2d *result = new Polygon2d;
BOOST_FOREACH(const ClipperLib::Polygon &p, poly) {
Outline2d outline;
const Vector2d *lastv = NULL;
BOOST_FOREACH(const ClipperLib::IntPoint &ip, p) {
outline.push_back(Vector2d(1.0*ip.X/CLIPPER_SCALE,
1.0*ip.Y/CLIPPER_SCALE));
Vector2d v(1.0*ip.X/CLIPPER_SCALE, 1.0*ip.Y/CLIPPER_SCALE);
// Ignore too close vertices. This is to be nice to subsequent processes.
if (lastv && (v-*lastv).squaredNorm() < 0.001) continue;
outline.push_back(v);
lastv = &outline.back();
}
result->addOutline(outline);
}

View File

@ -6,13 +6,13 @@
namespace PolysetUtils {
// Project all polygons (also back-facing) into a Polygon2d instance.
// It's important to select all faces, since filtering by normal vector here
// will trigger floating point incertainties and cause problems later.
const Polygon2d *project(const PolySet &ps) {
Polygon2d *poly = new Polygon2d;
BOOST_FOREACH(const PolySet::Polygon &p, ps.polygons) {
// Filter away down-facing normal vectors
if ((p[1]-p[0]).cross(p[2]-p[0])[2] <=0) continue;
Outline2d outline;
BOOST_FOREACH(const Vector3d &v, p) {
outline.push_back(Vector2d(v[0], v[1]));