diff options
author | supermerill <merill@fr.fr> | 2018-12-06 19:17:25 +0300 |
---|---|---|
committer | supermerill <merill@fr.fr> | 2018-12-06 19:17:25 +0300 |
commit | a36fe262f7f566fe347f27c8bdd8294737af34ce (patch) | |
tree | 4d2677a3d34484b9152ba900e68a07f7815c5637 | |
parent | 345da498c8cf8eea3332834088ba9aa9aa33b8bb (diff) |
some fix on thin_wallsnot_cool
-rw-r--r-- | t/thin.t | 15 | ||||
-rw-r--r-- | xs/src/libslic3r/MedialAxis.cpp | 64 | ||||
-rw-r--r-- | xs/src/libslic3r/MedialAxis.hpp | 1 | ||||
-rw-r--r-- | xs/src/libslic3r/PerimeterGenerator.cpp | 10 |
4 files changed, 56 insertions, 34 deletions
@@ -1,4 +1,4 @@ -use Test::More tests => 28; +use Test::More tests => 29; use strict; use warnings; @@ -102,7 +102,9 @@ if (0) { is scalar(@$res), 1, 'medial axis of a semicircumference is a single line'; # check whether turns are all CCW or all CW - my @lines = @{$res->[0]->lines}; + my @alllines = @{$res->[0]->lines}; + # remove lines taht are near the end. + my @lines = grep($_->a->y >= 1578184 || $_->b->y >= 1578184, @alllines); my @angles = map { $lines[$_-1]->ccw($lines[$_]->b) } 1..$#lines; ok !!(none { $_ < 0 } @angles) || (none { $_ > 0 } @angles), 'all medial axis segments of a semicircumference have the same orientation'; @@ -113,16 +115,25 @@ if (0) { [4.3, 4], [4.3, 0], [4,0], [4,4], [0,4], [0,4.5], [4,4.5], [4,10], [4.3,10], [4.3, 4.5], [6, 4.5], [6,10], [6.2,10], [6.2,4.5], [10,4.5], [10,4], [6.2,4], [6.2,0], [6, 0], [6, 4], )); + $expolygon->contour->make_counter_clockwise(); my $res = $expolygon->medial_axis(scale 0.55, scale 0.25); is scalar(@$res), 2, 'medial axis of a (bit too narrow) french cross is two lines'; ok unscale($res->[0]->length) >= (9.9) - epsilon, 'medial axis has reasonable length'; ok unscale($res->[1]->length) >= (9.9) - epsilon, 'medial axis has reasonable length'; + my @lines1 = @{$res->[0]->lines}; + my @angles1 = map { $lines1[$_-1]->ccw($lines1[$_]->b) } 1..$#lines1; + my @lines2 = @{$res->[1]->lines}; + my @angles2 = map { $lines2[$_-1]->ccw($lines2[$_]->b) } 1..$#lines2; + my @angles = (@angles1, @angles2); + ok !!(none { $_ != 0 } @angles), + 'medial axis of a (bit too narrow) french cross is two lines has only strait lines'; } { my $expolygon = Slic3r::ExPolygon->new(Slic3r::Polygon->new_scale( [0.86526705,1.4509841], [0.57696039,1.8637021], [0.4502297,2.5569978], [0.45626199,3.2965596], [1.1218851,3.3049455], [0.96681072,2.8243202], [0.86328971,2.2056997], [0.85367905,1.7790778], )); + $expolygon->contour->make_counter_clockwise(); my $res = $expolygon->medial_axis(scale 1, scale 0.25); is scalar(@$res), 1, 'medial axis of a (bit too narrow) french cross is two lines'; ok unscale($res->[0]->length) >= (1.4) - epsilon, 'medial axis has reasonable length'; diff --git a/xs/src/libslic3r/MedialAxis.cpp b/xs/src/libslic3r/MedialAxis.cpp index 2b0006129..7be8c0958 100644 --- a/xs/src/libslic3r/MedialAxis.cpp +++ b/xs/src/libslic3r/MedialAxis.cpp @@ -359,21 +359,21 @@ add_point_same_percent(ThickPolyline* pattern, ThickPolyline* to_modify) /// return 1 for an angle of 90° and 0 for an angle of 0° or 180° double get_coeff_from_angle_countour(Point &point, const ExPolygon &contour, coord_t min_dist_between_point) { - double nearestDist = point.distance_to(contour.contour.points.front()); - Point nearest = contour.contour.points.front(); + double nearest_dist = point.distance_to(contour.contour.points.front()); + Point point_nearest = contour.contour.points.front(); size_t id_nearest = 0; - double nearDist = nearestDist; - Point near = nearest; + double near_dist = nearest_dist; + Point point_near = point_nearest; size_t id_near = 0; for (size_t id_point = 1; id_point < contour.contour.points.size(); ++id_point) { - if (nearestDist > point.distance_to(contour.contour.points[id_point])) { - //update near + if (nearest_dist > point.distance_to(contour.contour.points[id_point])) { + //update point_near id_near = id_nearest; - near = nearest; - nearDist = nearestDist; + point_near = point_nearest; + near_dist = nearest_dist; //update nearest - nearestDist = point.distance_to(contour.contour.points[id_point]); - nearest = contour.contour.points[id_point]; + nearest_dist = point.distance_to(contour.contour.points[id_point]); + point_nearest = contour.contour.points[id_point]; id_nearest = id_point; } } @@ -381,7 +381,7 @@ get_coeff_from_angle_countour(Point &point, const ExPolygon &contour, coord_t mi size_t id_before = id_nearest == 0 ? contour.contour.points.size() - 1 : id_nearest - 1; Point point_before = id_nearest == 0 ? contour.contour.points.back() : contour.contour.points[id_nearest - 1]; //Search one point far enough to be relevant - while (nearest.distance_to(point_before) < min_dist_between_point) { + while (point_nearest.distance_to(point_before) < min_dist_between_point) { point_before = id_before == 0 ? contour.contour.points.back() : contour.contour.points[id_before - 1]; id_before = id_before == 0 ? contour.contour.points.size() - 1 : id_before - 1; //don't loop @@ -394,7 +394,7 @@ get_coeff_from_angle_countour(Point &point, const ExPolygon &contour, coord_t mi size_t id_after = id_nearest == contour.contour.points.size() - 1 ? 0 : id_nearest + 1; Point point_after = id_nearest == contour.contour.points.size() - 1 ? contour.contour.points.front() : contour.contour.points[id_nearest + 1]; //Search one point far enough to be relevant - while (nearest.distance_to(point_after) < min_dist_between_point) { + while (point_nearest.distance_to(point_after) < min_dist_between_point) { point_after = id_after == contour.contour.points.size() - 1 ? contour.contour.points.front() : contour.contour.points[id_after + 1]; id_after = id_after == contour.contour.points.size() - 1 ? 0 : id_after + 1; //don't loop @@ -405,15 +405,15 @@ get_coeff_from_angle_countour(Point &point, const ExPolygon &contour, coord_t mi } } //compute angle - angle = nearest.ccw_angle(point_before, point_after); + angle = point_nearest.ccw_angle(point_before, point_after); if (angle >= PI) angle = 2 * PI - angle; // smaller angle //compute the diff from 90° angle = abs(angle - PI / 2); - if (near.coincides_with(nearest) && max(nearestDist, nearDist) + SCALED_EPSILON < nearest.distance_to(near)) { + if (point_near.coincides_with(point_nearest) && max(nearest_dist, near_dist) + SCALED_EPSILON < point_nearest.distance_to(point_near)) { //not only nearest Point point_before = id_near == 0 ? contour.contour.points.back() : contour.contour.points[id_near - 1]; Point point_after = id_near == contour.contour.points.size() - 1 ? contour.contour.points.front() : contour.contour.points[id_near + 1]; - double angle2 = min(nearest.ccw_angle(point_before, point_after), nearest.ccw_angle(point_after, point_before)); + double angle2 = min(point_nearest.ccw_angle(point_before, point_after), point_nearest.ccw_angle(point_after, point_before)); angle2 = abs(angle - PI / 2); angle = (angle + angle2) / 2; } @@ -1319,10 +1319,6 @@ MedialAxis::build(ThickPolylines* polylines_out) // svg.Close(); //} this->expolygon = simplify_polygon_frontier(); - //check area - if (this->expolygon.area() < this->max_width * this->min_width) return; - - //std::cout << "simplify_polygon_frontier\n"; //{ // stringstream stri; // stri << "medial_axis_0.5_simplified_" << id << ".svg"; @@ -1331,6 +1327,11 @@ MedialAxis::build(ThickPolylines* polylines_out) // svg.draw(this->expolygon); // svg.Close(); //} + //safety check + if (this->expolygon.area() < this->min_width * this->min_width) this->expolygon = this->surface; + if (this->expolygon.area() < this->min_width * this->min_width) return; + + //std::cout << "simplify_polygon_frontier\n"; // compute the Voronoi diagram and extract medial axis polylines ThickPolylines pp; this->polyline_from_voronoi(this->expolygon.lines(), &pp); @@ -1366,7 +1367,6 @@ MedialAxis::build(ThickPolylines* polylines_out) // svg.Close(); //} - concatThickPolylines(pp); // Aligned fusion: Fusion the bits at the end of lines by "increasing thickness" // For that, we have to find other lines, @@ -1387,6 +1387,16 @@ MedialAxis::build(ThickPolylines* polylines_out) //fusion right-angle corners. fusion_corners(pp); + if (do_not_overextrude) { + const ExPolygons anchors = offset2_ex(diff_ex(this->bounds, this->expolygon), -SCALED_RESOLUTION, SCALED_RESOLUTION); + for (size_t i = 0; i < pp.size(); ++i) { + ThickPolyline& polyline = pp[i]; + extends_line(polyline, anchors, min_width); + polyline.reverse(); + extends_line(polyline, anchors, min_width); + } + } + //reduce extrusion when it's too thin to be printable remove_too_thin_extrusion(pp); //{ @@ -1412,12 +1422,14 @@ MedialAxis::build(ThickPolylines* polylines_out) // Loop through all returned polylines in order to extend their endpoints to the // expolygon boundaries - const ExPolygons anchors = offset2_ex(diff_ex(this->bounds, this->expolygon), -SCALED_RESOLUTION, SCALED_RESOLUTION); - for (size_t i = 0; i < pp.size(); ++i) { - ThickPolyline& polyline = pp[i]; - extends_line(polyline, anchors, min_width); - polyline.reverse(); - extends_line(polyline, anchors, min_width); + if (!do_not_overextrude) { + const ExPolygons anchors = offset2_ex(diff_ex(this->bounds, this->expolygon), -SCALED_RESOLUTION, SCALED_RESOLUTION); + for (size_t i = 0; i < pp.size(); ++i) { + ThickPolyline& polyline = pp[i]; + extends_line(polyline, anchors, min_width); + polyline.reverse(); + extends_line(polyline, anchors, min_width); + } } //{ // stringstream stri; diff --git a/xs/src/libslic3r/MedialAxis.hpp b/xs/src/libslic3r/MedialAxis.hpp index c65cbdb84..560e2bf03 100644 --- a/xs/src/libslic3r/MedialAxis.hpp +++ b/xs/src/libslic3r/MedialAxis.hpp @@ -22,6 +22,7 @@ namespace Slic3r { const double max_width; const double min_width; const double height; + bool do_not_overextrude = true; MedialAxis(const ExPolygon &_expolygon, const ExPolygon &_bounds, const double _max_width, const double _min_width, const double _height) : surface(_expolygon), bounds(_bounds), max_width(_max_width), min_width(_min_width), height(_height) { }; diff --git a/xs/src/libslic3r/PerimeterGenerator.cpp b/xs/src/libslic3r/PerimeterGenerator.cpp index 549ae0a57..eeb60773c 100644 --- a/xs/src/libslic3r/PerimeterGenerator.cpp +++ b/xs/src/libslic3r/PerimeterGenerator.cpp @@ -292,13 +292,11 @@ void PerimeterGenerator::process() for (ExPolygon &bound : bounds) { if (!intersection_ex(thin[0], bound).empty()) { //be sure it's not too small to extrude reliably - ExPolygon simplifiedPolygon = thin[0]; - simplifiedPolygon.remove_point_too_near(SCALED_RESOLUTION); - if (simplifiedPolygon.area() > min_width*(ext_perimeter_width + ext_perimeter_spacing2)) { - ExPolygon simplifiedBounds = bound; - simplifiedBounds.remove_point_too_near(SCALED_RESOLUTION); + thin[0].remove_point_too_near(SCALED_RESOLUTION); + if (thin[0].area() > min_width*(ext_perimeter_width + ext_perimeter_spacing2)) { + bound.remove_point_too_near(SCALED_RESOLUTION); // the maximum thickness of our thin wall area is equal to the minimum thickness of a single loop - simplifiedPolygon.medial_axis(simplifiedBounds, ext_perimeter_width + ext_perimeter_spacing2, min_width, + thin[0].medial_axis(bound, ext_perimeter_width + ext_perimeter_spacing2, min_width, &thin_walls, this->layer_height); } break; |