diff --git a/lib/Slic3r/GCode/ArcFitting.pm b/lib/Slic3r/GCode/ArcFitting.pm index 1e1ae14c..8faa399b 100644 --- a/lib/Slic3r/GCode/ArcFitting.pm +++ b/lib/Slic3r/GCode/ArcFitting.pm @@ -6,9 +6,10 @@ use Slic3r::Geometry qw(X Y PI scale unscale epsilon scaled_epsilon deg2rad angl extends 'Slic3r::GCode::Reader'; has 'config' => (is => 'ro', required => 0); has 'min_segments' => (is => 'rw', default => sub { 2 }); -has 'max_angle' => (is => 'rw', default => sub { deg2rad(15) }); -has 'len_epsilon' => (is => 'rw', default => sub { scale 0.1 }); -has 'angle_epsilon' => (is => 'rw', default => sub { abs(deg2rad(1)) }); +has 'min_total_angle' => (is => 'rw', default => sub { deg2rad(30) }); +has 'max_relative_angle' => (is => 'rw', default => sub { deg2rad(15) }); +has 'len_epsilon' => (is => 'rw', default => sub { scale 0.2 }); +has 'angle_epsilon' => (is => 'rw', default => sub { abs(deg2rad(10)) }); has '_extrusion_axis' => (is => 'lazy'); has '_path' => (is => 'rw'); has '_cur_F' => (is => 'rw'); @@ -131,22 +132,28 @@ sub detect_arcs { # we need at least three points to check whether they form an arc if ($i < $#points) { my $len = $points[$i-1]->distance_to($points[$i]); - my $rel_angle = angle3points(@points[$i, $i-1, $i+1]); - for (my $j = $i+1; $j <= $#points; ++$j) { - # check whether @points[($i-1)..$j] form an arc - last if abs($points[$j-1]->distance_to($points[$j]) - $len) > $self->len_epsilon; - last if abs(angle3points(@points[$j-1, $j-2, $j]) - $rel_angle) > $self->angle_epsilon; - - $end = $j; + my $rel_angle = PI - angle3points(@points[$i, $i-1, $i+1]); + if (abs($rel_angle) <= $self->max_relative_angle) { + for (my $j = $i+1; $j <= $#points; ++$j) { + # check whether @points[($i-1)..$j] form an arc + last if abs($points[$j-1]->distance_to($points[$j]) - $len) > $self->len_epsilon; + last if abs(PI - angle3points(@points[$j-1, $j-2, $j]) - $rel_angle) > $self->angle_epsilon; + + $end = $j; + } } } if (defined $end && ($end - $i + 1) >= $self->min_segments) { - push @chunks, polyline_to_arc(Slic3r::Polyline->new(@points[($i-1)..$end])); + my $arc = polyline_to_arc(Slic3r::Polyline->new(@points[($i-1)..$end])); - # continue scanning after arc points - $i = $end; - next; + if (1||$arc->angle >= $self->min_total_angle) { + push @chunks, $arc; + + # continue scanning after arc points + $i = $end; + next; + } } # if last chunk was a polyline, append to it diff --git a/t/arcs.t b/t/arcs.t index a41d2034..43524d68 100644 --- a/t/arcs.t +++ b/t/arcs.t @@ -2,7 +2,7 @@ use Test::More; use strict; use warnings; -plan tests => 20; +plan tests => 24; BEGIN { use FindBin; @@ -44,20 +44,27 @@ use Slic3r::Geometry qw(scaled_epsilon epsilon scale unscale X Y deg2rad); } } -exit; - #========================================================== { - my $path = Slic3r::Polyline->new( + my $path = Slic3r::Polyline->new_scale( [135322.42,26654.96], [187029.11,99546.23], [222515.14,92381.93], [258001.16,99546.23], [286979.42,119083.91], [306517.1,148062.17], [313681.4,183548.2], [306517.1,219034.23], [286979.42,248012.49], [258001.16,267550.17], [222515.14,274714.47], [187029.11,267550.17], [158050.85,248012.49], [138513.17,219034.23], [131348.87,183548.2], [86948.77,175149.09], [119825.35,100585], ); + $path->scale(1/10000); - my $af = Slic3r::GCode::ArcFitting->new; + if (0) { + require "Slic3r::SVG"; + Slic3r::SVG::output( + "arc.svg", + polylines => [$path], + ); + } + + my $af = Slic3r::GCode::ArcFitting->new(max_relative_angle => deg2rad(30)); my @chunks = $af->detect_arcs($path); is scalar(@chunks), 3, 'path collection now contains three paths'; @@ -66,6 +73,8 @@ exit; isa_ok $chunks[2], 'Slic3r::Polyline', 'third one is polyline'; } +exit; + #========================================================== {