Skip to content

Commit

Permalink
fix unwanted extra gapfill (boost::voronoi bug)
Browse files Browse the repository at this point in the history
Mitigation: remove shallow angles that seems to make it appear.
As the previous remove_colinear was on a fixed dist (taht became too small on long segments)
I created a new one that work from an angle.
#2971
  • Loading branch information
supermerill committed Jul 23, 2022
1 parent a14bf40 commit 6ab161f
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 13 deletions.
16 changes: 8 additions & 8 deletions src/libslic3r/Geometry/MedialAxis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -813,18 +813,18 @@ MedialAxis::polyline_from_voronoi(const ExPolygon& voronoi_polygon, ThickPolylin
// iterate through the valid edges to build polylines
while (!edges.empty()) {
const edge_t* edge = *edges.begin();
if (thickness[edge].first > this->max_width * 1.001) {
//if (thickness[edge].first > this->max_width * 1.001) {
//std::cerr << "Error, edge.first has a thickness of " << unscaled(this->thickness[edge].first) << " > " << unscaled(this->max_width) << "\n";
//(void)this->edges.erase(edge);
//(void)this->edges.erase(edge->twin());
//continue;
}
if (thickness[edge].second > this->max_width * 1.001) {
//}
//if (thickness[edge].second > this->max_width * 1.001) {
//std::cerr << "Error, edge.second has a thickness of " << unscaled(this->thickness[edge].second) << " > " << unscaled(this->max_width) << "\n";
//(void)this->edges.erase(edge);
//(void)this->edges.erase(edge->twin());
//continue;
}
//}

// start a polyline
ThickPolyline polyline;
Expand Down Expand Up @@ -2553,9 +2553,9 @@ MedialAxis::simplify_polygon_frontier()
{
//it will remove every point in the surface contour that aren't on the bounds contour
this->expolygon = this->surface;
this->expolygon.contour.remove_collinear(SCALED_EPSILON);
this->expolygon.contour.remove_collinear_angle(M_PI/180);
for (Polygon& hole : this->expolygon.holes)
hole.remove_collinear(SCALED_EPSILON);
hole.remove_collinear_angle(M_PI / 180);
if (&this->surface != this->bounds) {
bool need_intersect = false;
for (size_t i = 0; i < this->expolygon.contour.points.size(); i++) {
Expand Down Expand Up @@ -2584,9 +2584,9 @@ MedialAxis::simplify_polygon_frontier()
} else {
//can't simplify that much, reuse the given one
this->expolygon = this->surface;
this->expolygon.contour.remove_collinear(SCALED_EPSILON);
this->expolygon.contour.remove_collinear_angle(M_PI / 180);
for (Polygon& hole : this->expolygon.holes)
hole.remove_collinear(SCALED_EPSILON);
hole.remove_collinear_angle(M_PI / 180);
}
}
}
Expand Down
48 changes: 44 additions & 4 deletions src/libslic3r/Polygon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,30 +298,70 @@ size_t Polygon::remove_collinear(coord_t max_offset){
size_t nb_del = 0;
if (points.size() < 3) return 0;

coord_t min_dist = max_offset * max_offset;
while (points.size() > 2 && Line::distance_to_squared(points[0], points.back(), points[1]) < min_dist){
double min_dist_sq = coordf_t(max_offset) * max_offset;
while (points.size() > 2 && Line::distance_to_squared(points[0], points.back(), points[1]) < min_dist_sq){
//colinear! delete!
points.erase(points.begin());
nb_del++;
}
for (size_t idx = 1; idx < points.size()-1; ) {
//if (Line(previous, points[idx + 1]).distance_to(points[idx]) < SCALED_EPSILON){
if (Line::distance_to_squared(points[idx], points[idx-1], points[idx + 1]) < min_dist){
if (Line::distance_to_squared(points[idx], points[idx-1], points[idx + 1]) < min_dist_sq){
//colinear! delete!
points.erase(points.begin() + idx);
nb_del++;
} else {
idx++;
}
}
while (points.size() > 2 && Line::distance_to_squared(points.back(), points[points.size()-2], points.front()) < min_dist) {
while (points.size() > 2 && Line::distance_to_squared(points.back(), points[points.size()-2], points.front()) < min_dist_sq) {
//colinear! delete!
points.erase(points.end()-1);
nb_del++;
}

return nb_del;
}

size_t Polygon::remove_collinear_angle(double angle_radian) {
size_t nb_del = 0;
if (points.size() < 3) return 0;
//std::cout << "== remove_collinear_angle \n";
double min_dist_sq = std::sin(angle_radian);
min_dist_sq = min_dist_sq * min_dist_sq;
while (points.size() > 2 && Line::distance_to_squared(points.front(), points.back(), points[1]) < min_dist_sq * std::min(points.back().distance_to_square(points.front()), points.front().distance_to_square(points[1]))) {
/* if (Line::distance_to_squared(points.front(), points.back(), points[1]) > SCALED_EPSILON) {
std::cout << "Fcolinear angle " << Line::distance_to_squared(points[0], points.back(), points[1]) << " < " << (min_dist_sq * std::min(points.back().distance_to_square(points.front()), points.front().distance_to_square(points[1]))) << " (" << min_dist_sq << " * " << std::min(points.back().distance_to_square(points.front()), points.front().distance_to_square(points[1])) << ")\n";
std::cout << " unscaled= " << unscaled(Line::distance_to(points[0], points.back(), points[1])) << " < " << unscaled(std::sin(angle_radian) * std::min(points.back().distance_to(points.front()), points.front().distance_to(points[1]))) << " (" << std::sin(angle_radian) << " * " << unscaled(std::min(points.back().distance_to(points.front()), points.front().distance_to(points[1]))) << ")\n";
std::cout << " dists: " << unscaled(points.back().distance_to(points.front())) << " => " << unscaled(points.front().distance_to(points[1])) << "\n";
}*/
//colinear! delete!
points.erase(points.begin());
nb_del++;
}
for (size_t idx = 1; idx < points.size() - 1 && points.size() > 2; ) {
if (Line::distance_to_squared(points[idx], points[idx - 1], points[idx + 1]) < min_dist_sq * std::min(points[idx - 1].distance_to_square(points[idx]), points[idx].distance_to_square(points[idx + 1]))) {
/*if (Line::distance_to_squared(points[idx], points[idx - 1], points[idx + 1]) > SCALED_EPSILON) {
std::cout << " colinear angle " << Line::distance_to_squared(points[idx], points[idx - 1], points[idx + 1]) << " < " << (min_dist_sq * std::min(points[idx - 1].distance_to_square(points[idx]), points[idx].distance_to_square(points[idx + 1]))) << " (" << min_dist_sq << " * " << std::min(points[idx - 1].distance_to_square(points[idx]), points[idx].distance_to_square(points[idx + 1])) << ")\n";
std::cout << " unscaled= " << unscaled(Line::distance_to(points[idx], points[idx - 1], points[idx + 1])) << " < " << unscaled(std::sin(angle_radian) * std::min(points[idx - 1].distance_to(points[idx]), points[idx].distance_to(points[idx + 1]))) << " (" << std::sin(angle_radian) << " * " << unscaled(std::min(points[idx - 1].distance_to(points[idx]), points[idx].distance_to(points[idx + 1]))) << ")\n";
std::cout << " dists: " << unscaled(points[idx - 1].distance_to(points[idx])) << " => " << unscaled(points[idx].distance_to(points[idx + 1])) << "\n";
}*/
//colinear! delete!
points.erase(points.begin() + idx);
nb_del++;
} else {
idx++;
}
}
while (points.size() > 2 && Line::distance_to_squared(points.back(), points[points.size() - 2], points.front()) < min_dist_sq * std::min(points.back().distance_to_square(points[points.size() - 2]), points.front().distance_to_square(points.back()))) {
//colinear! delete!
points.erase(points.end() - 1);
nb_del++;
}

return nb_del;
}

BoundingBox get_extents(const Polygon &poly)
{
return poly.bounding_box();
Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/Polygon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class Polygon : public MultiPoint
/// remove points that are (almost) on an existing line from previous & next point.
/// return number of point removed
size_t remove_collinear(coord_t max_offset);
size_t remove_collinear_angle(double angle);

using iterator = Points::iterator;
using const_iterator = Points::const_iterator;
Expand Down
15 changes: 15 additions & 0 deletions src/libslic3r/SVG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,21 @@ void SVG::draw(const ThickLines &thicklines, const std::string &fill, const std:
this->draw(*it, fill, stroke, stroke_width);
}

void SVG::draw(const ThickPolylines &polylines, const std::string &stroke)
{
for (const ThickPolyline& poly : polylines) {
if (poly.points.size() < 2) continue;
Line l{ poly.points.front(), poly.points[1] };
this->draw(Line{ poly.points.front(), l.midpoint() }, stroke, poly.width.front() / 10);
for (int i = 1; i < poly.points.size()-1; ++i) {
Point first_point = l.midpoint();
l=Line{ poly.points[i], poly.points[i+1] };
this->draw(Line{ first_point, l.midpoint() }, stroke, poly.width[i]/10);
}
this->draw(Line{ l.midpoint(), poly.points.back() }, stroke, poly.width.back() / 10);
}
}

void SVG::draw(const ThickPolylines &polylines, const std::string &stroke, coordf_t stroke_width)
{
for (ThickPolylines::const_iterator it = polylines.begin(); it != polylines.end(); ++it)
Expand Down
3 changes: 2 additions & 1 deletion src/libslic3r/SVG.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ class SVG
void draw(const Polyline &polyline, std::string stroke = "black", coordf_t stroke_width = 0);
void draw(const Polylines &polylines, std::string stroke = "black", coordf_t stroke_width = 0);
void draw(const ThickLines &thicklines, const std::string &fill = "lime", const std::string &stroke = "black", coordf_t stroke_width = 0);
void draw(const ThickPolylines &polylines, const std::string &stroke = "black", coordf_t stroke_width = 0);
void draw(const ThickPolylines &thickpolylines, const std::string &stroke = "black");
void draw(const ThickPolylines &polylines, const std::string &stroke, coordf_t stroke_width);
void draw(const ThickPolylines &thickpolylines, const std::string &fill, const std::string &stroke, coordf_t stroke_width);
void draw(const Point &point, std::string fill = "black", coord_t radius = 0);
void draw(const Points &points, std::string fill = "black", coord_t radius = 0);
Expand Down

0 comments on commit 6ab161f

Please sign in to comment.