diff --git a/lib/Slic3r/Polygon.pm b/lib/Slic3r/Polygon.pm index 124d9ae99..5b13e13ff 100644 --- a/lib/Slic3r/Polygon.pm +++ b/lib/Slic3r/Polygon.pm @@ -45,34 +45,52 @@ sub subdivide { return Slic3r::Polygon->new(@new_points); } -# angle is checked on the internal side of the polygon sub concave_points { my ($self, $angle) = @_; $angle //= PI; + # input angle threshold is checked on the internal side of the polygon + # but angle3points measures CCW angle, so we calculate the complementary angle + my $ccw_angle = 2*PI-$angle; + my @points = @$self; my @points_pp = @{$self->pp}; - return [ - map $points[$_], - grep Slic3r::Geometry::angle3points(@points_pp[$_, $_-1, $_+1]) < $angle, - -1 .. ($#points-1) - ]; + + my @concave = (); + for my $i (-1 .. ($#points-1)) { + next if $points[$i-1]->coincides_with($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]; + } + } + return [@concave]; } -# angle is checked on the internal side of the polygon sub convex_points { my ($self, $angle) = @_; $angle //= PI; + # input angle threshold is checked on the internal side of the polygon + # but angle3points measures CCW angle, so we calculate the complementary angle + my $ccw_angle = 2*PI-$angle; + my @points = @$self; my @points_pp = @{$self->pp}; - return [ - map $points[$_], - grep Slic3r::Geometry::angle3points(@points_pp[$_, $_-1, $_+1]) > $angle, - -1 .. ($#points-1) - ]; + + my @convex = (); + for my $i (-1 .. ($#points-1)) { + next if $points[$i-1]->coincides_with($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 @convex, $points[$i]; + } + } + return [@convex]; } 1; \ No newline at end of file diff --git a/t/geometry.t b/t/geometry.t index 7ff2a2aac..a9326782b 100644 --- a/t/geometry.t +++ b/t/geometry.t @@ -2,7 +2,7 @@ use Test::More; use strict; use warnings; -plan tests => 29; +plan tests => 33; BEGIN { use FindBin; @@ -189,3 +189,27 @@ my $polygons = [ } #========================================================== + +{ + my $square = Slic3r::Polygon->new( + [150,100], + [200,100], + [200,200], + [100,200], + [100,100], + ); + is scalar(@{$square->concave_points(PI*4/3)}), 0, 'no concave vertices detected in convex polygon'; + is scalar(@{$square->convex_points(PI*2/3)}), 4, 'four convex vertices detected in square'; +} + +{ + my $square = Slic3r::Polygon->new( + [200,200], + [100,200], + [100,100], + [150,100], + [200,100], + ); + is scalar(@{$square->concave_points(PI*4/3)}), 0, 'no concave vertices detected in convex polygon'; + is scalar(@{$square->convex_points(PI*2/3)}), 4, 'four convex vertices detected in square'; +}