Bugfix: prevent crashes from rounding issues caused by almost-collinear points in the new FillRectilinear. #3684

This commit is contained in:
Alessandro Ranellucci 2017-03-18 14:56:23 +01:00
parent 086fd2e8a8
commit 702cf43a0a
5 changed files with 47 additions and 5 deletions

View File

@ -129,6 +129,14 @@ ExPolygon::has_boundary_point(const Point &point) const
return false;
}
void
ExPolygon::remove_vertical_collinear_points(coord_t tolerance)
{
this->contour.remove_vertical_collinear_points(tolerance);
for (Polygon &p : this->holes)
p.remove_vertical_collinear_points(tolerance);
}
void
ExPolygon::simplify_p(double tolerance, Polygons* polygons) const
{

View File

@ -29,6 +29,7 @@ class ExPolygon
bool contains(const Point &point) const;
bool contains_b(const Point &point) const;
bool has_boundary_point(const Point &point) const;
void remove_vertical_collinear_points(coord_t tolerance);
void simplify_p(double tolerance, Polygons* polygons) const;
Polygons simplify_p(double tolerance) const;
ExPolygons simplify(double tolerance) const;

View File

@ -1,3 +1,9 @@
//#define DEBUG_RECTILINEAR
#ifdef DEBUG_RECTILINEAR
#undef NDEBUG
#include "../SVG.hpp"
#endif
#include "../ClipperUtils.hpp"
#include "../ExPolygon.hpp"
#include "../PolylineCollection.hpp"
@ -7,17 +13,16 @@
#include "FillRectilinear.hpp"
//#define DEBUG_RECTILINEAR
#ifdef DEBUG_RECTILINEAR
#include "../SVG.hpp"
#endif
namespace Slic3r {
void
FillRectilinear::_fill_single_direction(ExPolygon expolygon,
const direction_t &direction, coord_t x_shift, Polylines* out)
{
// Remove almost collinear points (vertical ones might break this algorithm
// because of rounding).
expolygon.remove_vertical_collinear_points(1);
// rotate polygons so that we can work with vertical lines here
expolygon.rotate(-direction.first);

View File

@ -148,6 +148,32 @@ Polygon::contains(const Point &point) const
return result;
}
void
Polygon::douglas_peucker(double tolerance)
{
this->points.push_back(this->points.front());
this->points = MultiPoint::_douglas_peucker(this->points, tolerance);
this->points.pop_back();
}
void
Polygon::remove_vertical_collinear_points(coord_t tolerance)
{
Points &pp = this->points;
pp.push_back(pp.front());
for (size_t i = 0; i < pp.size()-1; ++i) {
while (i < pp.size()-1) {
Point &next = pp[i+1];
if (std::abs(next.x - pp[i].x) <= tolerance) {
pp.erase(pp.begin() + i+1);
} else {
break;
}
}
}
pp.pop_back();
}
// this only works on CCW polygons as CW will be ripped out by Clipper's simplify_polygons()
Polygons
Polygon::simplify(double tolerance) const

View File

@ -39,6 +39,8 @@ class Polygon : public MultiPoint {
// Does an unoriented polygon contain a point?
// Tested by counting intersections along a horizontal line.
bool contains(const Point &point) const;
void douglas_peucker(double tolerance);
void remove_vertical_collinear_points(coord_t tolerance);
Polygons simplify(double tolerance) const;
void simplify(double tolerance, Polygons &polygons) const;
void triangulate_convex(Polygons* polygons) const;