diff --git a/lib/Slic3r/Polygon.pm b/lib/Slic3r/Polygon.pm index 5b13e13f..ea18e8ce 100644 --- a/lib/Slic3r/Polygon.pm +++ b/lib/Slic3r/Polygon.pm @@ -59,11 +59,12 @@ sub concave_points { my @concave = (); for my $i (-1 .. ($#points-1)) { - next if $points[$i-1]->coincides_with($points[$i]); + next if $points[$i-1]->coincides_with_epsilon($points[$i]) || $points[$i+1]->coincides_with_epsilon($points[$i]); # angle is measured in ccw orientation my $vertex_angle = Slic3r::Geometry::angle3points(@points_pp[$i, $i-1, $i+1]); if ($vertex_angle <= $ccw_angle) { push @concave, $points[$i]; + use XXX; YYY ($points[$i]->pp); } } return [@concave]; @@ -83,7 +84,7 @@ sub convex_points { my @convex = (); for my $i (-1 .. ($#points-1)) { - next if $points[$i-1]->coincides_with($points[$i]); + next if $points[$i-1]->coincides_with_epsilon($points[$i]) || $points[$i+1]->coincides_with_epsilon($points[$i]); # angle is measured in ccw orientation my $vertex_angle = Slic3r::Geometry::angle3points(@points_pp[$i, $i-1, $i+1]); if ($vertex_angle >= $ccw_angle) { diff --git a/lib/Slic3r/Test.pm b/lib/Slic3r/Test.pm index 5531ae4f..403ca494 100644 --- a/lib/Slic3r/Test.pm +++ b/lib/Slic3r/Test.pm @@ -104,6 +104,13 @@ sub mesh { $facets = [ [0,1,2],[3,4,5],[6,4,0],[6,0,2],[2,1,5],[7,4,3],[1,3,5],[0,4,7],[4,6,8],[6,9,8],[4,8,10],[6,2,9],[2,11,9],[2,12,11],[2,5,12],[5,13,12],[5,14,13],[4,10,15],[5,4,14],[4,15,14],[7,16,17],[0,7,18],[7,17,18],[1,19,20],[1,0,19],[0,18,19],[7,3,21],[3,22,21],[7,21,16],[3,23,22],[3,1,23],[1,20,23],[24,25,26],[25,27,26],[25,28,27],[29,24,30],[24,31,30],[24,26,31],[32,29,33],[29,30,33],[32,33,34],[32,34,35],[25,32,28],[32,35,28],[36,37,24],[38,32,25],[29,32,36],[29,36,24],[24,37,25],[39,32,38],[37,38,25],[36,32,39],[39,40,41],[36,39,42],[39,41,42],[37,43,44],[37,36,43],[36,42,43],[39,38,45],[38,46,45],[39,45,40],[38,47,46],[38,37,47],[37,44,47],[16,8,9],[16,10,8],[10,16,15],[15,16,21],[22,15,21],[15,22,14],[22,23,14],[23,20,14],[17,16,9],[18,17,9],[19,18,9],[19,9,11],[19,11,20],[13,14,20],[20,11,12],[13,20,12],[41,40,30],[42,41,30],[43,42,30],[43,30,31],[43,31,44],[27,28,44],[44,31,26],[27,44,26],[40,33,30],[40,34,33],[34,40,35],[35,40,45],[46,35,45],[35,46,28],[46,47,28],[47,44,28], ]; + } elsif ($name eq 'small_dorito') { + $vertices = [ + [6.00058937072754,-22.9982089996338,0],[22.0010242462158,-49.9998741149902,0],[-9.99957847595215,-49.999870300293,0],[6.00071382522583,-32.2371635437012,28.0019245147705],[11.1670551300049,-37.9727020263672,18.9601669311523],[6.00060224533081,-26.5392456054688,10.7321853637695] + ]; + $facets = [ + [0,1,2],[3,4,5],[2,1,4],[2,4,3],[2,3,5],[2,5,0],[5,4,1],[5,1,0] + ]; } else { return undef; } diff --git a/t/perimeters.t b/t/perimeters.t index d432f480..0954a4c7 100644 --- a/t/perimeters.t +++ b/t/perimeters.t @@ -1,4 +1,4 @@ -use Test::More tests => 9; +use Test::More tests => 11; use strict; use warnings; @@ -250,4 +250,38 @@ use Slic3r::Test; ok Slic3r::Test::gcode($print), 'successful generation of G-code with seam_position = random'; } +{ + my $test = sub { + my ($model_name) = @_; + my $config = Slic3r::Config->new_from_defaults; + $config->set('seam_position', 'aligned'); + $config->set('skirts', 0); + $config->set('perimeters', 1); + $config->set('fill_density', 0); + $config->set('top_solid_layers', 0); + $config->set('bottom_solid_layers', 0); + $config->set('retract_layer_change', [0]); + + my $was_extruding = 0; + my @seam_points = (); + my $print = Slic3r::Test::init_print($model_name, config => $config); + Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { + my ($self, $cmd, $args, $info) = @_; + + if ($info->{extruding}) { + if (!$was_extruding) { + push @seam_points, Slic3r::Point->new_scale($self->X, $self->Y); + } + $was_extruding = 1; + } else { + $was_extruding = 0; + } + }); + my @dist = map unscale($_), map $seam_points[$_]->distance_to($seam_points[$_+1]), 0..($#seam_points-1); + ok !(defined first { $_ > 3 } @dist), 'seam is aligned'; + }; + $test->('20mm_cube'); + $test->('small_dorito'); +} + __END__ diff --git a/xs/src/Point.cpp b/xs/src/Point.cpp index 6129f6ac..a17d0cd3 100644 --- a/xs/src/Point.cpp +++ b/xs/src/Point.cpp @@ -55,6 +55,12 @@ Point::coincides_with(const Point &point) const return this->x == point.x && this->y == point.y; } +bool +Point::coincides_with_epsilon(const Point &point) const +{ + return std::abs(this->x - point.x) < SCALED_EPSILON && std::abs(this->y - point.y) < SCALED_EPSILON; +} + int Point::nearest_point_index(const Points &points) const { diff --git a/xs/src/Point.hpp b/xs/src/Point.hpp index b87fa3a4..9ba665f5 100644 --- a/xs/src/Point.hpp +++ b/xs/src/Point.hpp @@ -33,6 +33,7 @@ class Point void translate(double x, double y); void rotate(double angle, const Point ¢er); bool coincides_with(const Point &point) const; + bool coincides_with_epsilon(const Point &point) const; int nearest_point_index(const Points &points) const; int nearest_point_index(const PointConstPtrs &points) const; int nearest_point_index(const PointPtrs &points) const; diff --git a/xs/xsp/Point.xsp b/xs/xsp/Point.xsp index 4817ca65..1380c01f 100644 --- a/xs/xsp/Point.xsp +++ b/xs/xsp/Point.xsp @@ -37,6 +37,8 @@ %code{% RETVAL = new Point(THIS->projection_onto(*line)); %}; Clone negative() %code{% RETVAL = new Point(THIS->negative()); %}; + bool coincides_with_epsilon(Point* point) + %code{% RETVAL = THIS->coincides_with_epsilon(*point); %}; %{