mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	Move arc fitting code to its own post-processing filter and remove the built-in ExtrusionPath::Arc class
This commit is contained in:
		
							parent
							
								
									0049b02bed
								
							
						
					
					
						commit
						b700278904
					
				
					 10 changed files with 154 additions and 188 deletions
				
			
		
							
								
								
									
										1
									
								
								MANIFEST
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								MANIFEST
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -5,7 +5,6 @@ lib/Slic3r/ExPolygon.pm
 | 
			
		|||
lib/Slic3r/Extruder.pm
 | 
			
		||||
lib/Slic3r/ExtrusionLoop.pm
 | 
			
		||||
lib/Slic3r/ExtrusionPath.pm
 | 
			
		||||
lib/Slic3r/ExtrusionPath/Arc.pm
 | 
			
		||||
lib/Slic3r/ExtrusionPath/Collection.pm
 | 
			
		||||
lib/Slic3r/Fill.pm
 | 
			
		||||
lib/Slic3r/Fill/ArchimedeanChords.pm
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,6 @@ use Slic3r::ExPolygon;
 | 
			
		|||
use Slic3r::Extruder;
 | 
			
		||||
use Slic3r::ExtrusionLoop;
 | 
			
		||||
use Slic3r::ExtrusionPath;
 | 
			
		||||
use Slic3r::ExtrusionPath::Arc;
 | 
			
		||||
use Slic3r::ExtrusionPath::Collection;
 | 
			
		||||
use Slic3r::Fill;
 | 
			
		||||
use Slic3r::Flow;
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +48,7 @@ use Slic3r::Format::AMF;
 | 
			
		|||
use Slic3r::Format::OBJ;
 | 
			
		||||
use Slic3r::Format::STL;
 | 
			
		||||
use Slic3r::GCode;
 | 
			
		||||
use Slic3r::GCode::ArcFitting;
 | 
			
		||||
use Slic3r::GCode::CoolingBuffer;
 | 
			
		||||
use Slic3r::GCode::Layer;
 | 
			
		||||
use Slic3r::GCode::MotionPlanner;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -178,118 +178,6 @@ sub split_at_acute_angles {
 | 
			
		|||
    return @paths;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub detect_arcs {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my ($max_angle, $len_epsilon) = @_;
 | 
			
		||||
    
 | 
			
		||||
    $max_angle = deg2rad($max_angle || 15);
 | 
			
		||||
    $len_epsilon ||= 10 / &Slic3r::SCALING_FACTOR;
 | 
			
		||||
    my $parallel_degrees_limit = abs(Slic3r::Geometry::deg2rad(3));
 | 
			
		||||
    
 | 
			
		||||
    my @points = @{$self->points};
 | 
			
		||||
    my @paths = ();
 | 
			
		||||
    
 | 
			
		||||
    # we require at least 3 consecutive segments to form an arc
 | 
			
		||||
    CYCLE: while (@points >= 4) {
 | 
			
		||||
        POINT: for (my $i = 0; $i <= $#points - 3; $i++) {
 | 
			
		||||
            my $s1 = Slic3r::Line->new($points[$i],   $points[$i+1]);
 | 
			
		||||
            my $s2 = Slic3r::Line->new($points[$i+1], $points[$i+2]);
 | 
			
		||||
            my $s3 = Slic3r::Line->new($points[$i+2], $points[$i+3]);
 | 
			
		||||
            my $s1_len = $s1->length;
 | 
			
		||||
            my $s2_len = $s2->length;
 | 
			
		||||
            my $s3_len = $s3->length;
 | 
			
		||||
            
 | 
			
		||||
            # segments must have the same length
 | 
			
		||||
            if (abs($s3_len - $s2_len) > $len_epsilon) {
 | 
			
		||||
                # optimization: skip a cycle
 | 
			
		||||
                $i++;
 | 
			
		||||
                next;
 | 
			
		||||
            }
 | 
			
		||||
            next if abs($s2_len - $s1_len) > $len_epsilon;
 | 
			
		||||
            
 | 
			
		||||
            # segments must have the same relative angle
 | 
			
		||||
            my $s1_angle = $s1->atan;
 | 
			
		||||
            my $s2_angle = $s2->atan;
 | 
			
		||||
            my $s3_angle = $s3->atan;
 | 
			
		||||
            $s1_angle += 2*PI if $s1_angle < 0;
 | 
			
		||||
            $s2_angle += 2*PI if $s2_angle < 0;
 | 
			
		||||
            $s3_angle += 2*PI if $s3_angle < 0;
 | 
			
		||||
            my $s1s2_angle = $s2_angle - $s1_angle;
 | 
			
		||||
            my $s2s3_angle = $s3_angle - $s2_angle;
 | 
			
		||||
            next if abs($s1s2_angle - $s2s3_angle) > $parallel_degrees_limit;
 | 
			
		||||
            next if abs($s1s2_angle) < $parallel_degrees_limit;     # ignore parallel lines
 | 
			
		||||
            next if $s1s2_angle > $max_angle;  # ignore too sharp vertices
 | 
			
		||||
            my @arc_points = ($points[$i], $points[$i+3]),  # first and last points
 | 
			
		||||
            
 | 
			
		||||
            # now look for more points
 | 
			
		||||
            my $last_line_angle = $s3_angle;
 | 
			
		||||
            my $last_j = $i+3;
 | 
			
		||||
            for (my $j = $i+3; $j < $#points; $j++) {
 | 
			
		||||
                my $line = Slic3r::Line->new($points[$j], $points[$j+1]);
 | 
			
		||||
                last if abs($line->length - $s1_len) > $len_epsilon;
 | 
			
		||||
                my $line_angle = $line->atan;
 | 
			
		||||
                $line_angle += 2*PI if $line_angle < 0;
 | 
			
		||||
                my $anglediff = $line_angle - $last_line_angle;
 | 
			
		||||
                last if abs($s1s2_angle - $anglediff) > $parallel_degrees_limit;
 | 
			
		||||
                
 | 
			
		||||
                # point $j+1 belongs to the arc
 | 
			
		||||
                $arc_points[-1] = $points[$j+1];
 | 
			
		||||
                $last_j = $j+1;
 | 
			
		||||
                
 | 
			
		||||
                $last_line_angle = $line_angle;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            # s1, s2, s3 form an arc
 | 
			
		||||
            my $orientation = $s1->point_on_left($points[$i+2]) ? 'ccw' : 'cw';
 | 
			
		||||
            
 | 
			
		||||
            # to find the center, we intersect the perpendicular lines
 | 
			
		||||
            # passing by midpoints of $s1 and last segment
 | 
			
		||||
            # a better method would be to draw all the perpendicular lines
 | 
			
		||||
            # and find the centroid of the enclosed polygon, or to
 | 
			
		||||
            # intersect multiple lines and find the centroid of the convex hull
 | 
			
		||||
            # around the intersections
 | 
			
		||||
            my $arc_center;
 | 
			
		||||
            {
 | 
			
		||||
                my $s1_mid = $s1->midpoint;
 | 
			
		||||
                my $last_mid = Slic3r::Line->new($points[$last_j-1], $points[$last_j])->midpoint;
 | 
			
		||||
                my $rotation_angle = PI/2 * ($orientation eq 'ccw' ? -1 : 1);
 | 
			
		||||
                my $ray1     = Slic3r::Line->new($s1_mid,   rotate_points($rotation_angle, $s1_mid,   $points[$i+1]));
 | 
			
		||||
                my $last_ray = Slic3r::Line->new($last_mid, rotate_points($rotation_angle, $last_mid, $points[$last_j]));
 | 
			
		||||
                $arc_center = $ray1->intersection($last_ray, 0) or next POINT;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            my $arc = Slic3r::ExtrusionPath::Arc->new(
 | 
			
		||||
                polyline    => Slic3r::Polyline->new(@arc_points),
 | 
			
		||||
                role        => $self->role,
 | 
			
		||||
                flow_spacing => $self->flow_spacing,
 | 
			
		||||
                orientation => $orientation,
 | 
			
		||||
                center      => $arc_center,
 | 
			
		||||
                radius      => $arc_center->distance_to($points[$i]),
 | 
			
		||||
            );
 | 
			
		||||
            
 | 
			
		||||
            # points 0..$i form a linear path
 | 
			
		||||
            push @paths, $self->clone(polyline => Slic3r::Polyline->new(@points[0..$i]))
 | 
			
		||||
                if $i > 0;
 | 
			
		||||
            
 | 
			
		||||
            # add our arc
 | 
			
		||||
            push @paths, $arc;
 | 
			
		||||
            Slic3r::debugf "ARC DETECTED\n";
 | 
			
		||||
            
 | 
			
		||||
            # remove arc points from path, leaving one
 | 
			
		||||
            splice @points, 0, $last_j, ();
 | 
			
		||||
            
 | 
			
		||||
            next CYCLE;
 | 
			
		||||
        }
 | 
			
		||||
        last;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    # remaining points form a linear path
 | 
			
		||||
    push @paths, $self->clone(polyline => Slic3r::Polyline->new(@points))
 | 
			
		||||
        if @points > 1;
 | 
			
		||||
    
 | 
			
		||||
    return @paths;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
package Slic3r::ExtrusionPath::Packed;
 | 
			
		||||
sub unpack {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,27 +0,0 @@
 | 
			
		|||
package Slic3r::ExtrusionPath::Arc;
 | 
			
		||||
use Moo;
 | 
			
		||||
 | 
			
		||||
extends 'Slic3r::ExtrusionPath';
 | 
			
		||||
 | 
			
		||||
has 'center' => (is => 'ro', required => 1);
 | 
			
		||||
has 'radius' => (is => 'ro', required => 1);
 | 
			
		||||
has 'orientation' => (is => 'ro', required => 1);  # cw/ccw
 | 
			
		||||
 | 
			
		||||
use Slic3r::Geometry qw(PI angle3points);
 | 
			
		||||
 | 
			
		||||
sub angle {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    return angle3points($self->center, @{$self->points});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub length {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    
 | 
			
		||||
    if($self->orientation eq 'ccw') {
 | 
			
		||||
        return $self->radius * $self->angle;
 | 
			
		||||
    } else {
 | 
			
		||||
        return $self->radius * (2*PI() - $self->angle);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
| 
						 | 
				
			
			@ -36,9 +36,4 @@ sub cleanup {
 | 
			
		|||
    @{$self->paths} = map $_->split_at_acute_angles, @{$self->paths};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub detect_arcs {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    @{$self->paths} = map $_->detect_arcs(@_), @{$self->paths};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -276,15 +276,6 @@ sub extrude_path {
 | 
			
		|||
    $path = $path->unpack if $path->isa('Slic3r::ExtrusionPath::Packed');
 | 
			
		||||
    $path->simplify(&Slic3r::SCALED_RESOLUTION);
 | 
			
		||||
    
 | 
			
		||||
    # detect arcs
 | 
			
		||||
    if ($self->config->gcode_arcs && !$params{dont_detect_arcs}) {
 | 
			
		||||
        my $gcode = "";
 | 
			
		||||
        foreach my $arc_path ($path->detect_arcs) {
 | 
			
		||||
            $gcode .= $self->extrude_path($arc_path, $description, %params, dont_detect_arcs => 1);
 | 
			
		||||
        }
 | 
			
		||||
        return $gcode;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    # go to first point of extrusion path
 | 
			
		||||
    my $gcode = "";
 | 
			
		||||
    $gcode .= $self->travel_to($path->points->[0], $path->role, "move to first $description point")
 | 
			
		||||
| 
						 | 
				
			
			@ -332,39 +323,7 @@ sub extrude_path {
 | 
			
		|||
    # extrude arc or line
 | 
			
		||||
    $gcode .= ";_BRIDGE_FAN_START\n" if $path->is_bridge;
 | 
			
		||||
    my $path_length = 0;
 | 
			
		||||
    if ($path->isa('Slic3r::ExtrusionPath::Arc')) {
 | 
			
		||||
        $path_length = unscale $path->length;
 | 
			
		||||
        
 | 
			
		||||
        # calculate extrusion length for this arc
 | 
			
		||||
        my $E = 0;
 | 
			
		||||
        if ($e) {
 | 
			
		||||
            $E = $e * $path_length;
 | 
			
		||||
            $self->extruder->e(0) if $self->config->use_relative_e_distances;
 | 
			
		||||
            $self->total_extrusion_length($self->total_extrusion_length + $E);
 | 
			
		||||
            $E = $self->extruder->e($self->extruder->e + $E);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        # compose G-code line
 | 
			
		||||
        my $point = $path->points->[-1];
 | 
			
		||||
        $gcode .= $path->orientation eq 'cw' ? "G2" : "G3";
 | 
			
		||||
        $gcode .= sprintf " X%.3f Y%.3f", 
 | 
			
		||||
            ($point->x * &Slic3r::SCALING_FACTOR) + $self->shift_x - $self->extruder->extruder_offset->[X], 
 | 
			
		||||
            ($point->y * &Slic3r::SCALING_FACTOR) + $self->shift_y - $self->extruder->extruder_offset->[Y]; #**
 | 
			
		||||
        
 | 
			
		||||
        # XY distance of the center from the start position
 | 
			
		||||
        $gcode .= sprintf " I%.3f J%.3f",
 | 
			
		||||
            ($path->center->[X] - $self->last_pos->[X]) * &Slic3r::SCALING_FACTOR,
 | 
			
		||||
            ($path->center->[Y] - $self->last_pos->[Y]) * &Slic3r::SCALING_FACTOR;
 | 
			
		||||
        
 | 
			
		||||
        $gcode .= sprintf(" %s%.5f", $self->config->extrusion_axis, $E)
 | 
			
		||||
            if $E;
 | 
			
		||||
        $gcode .= " F$F";
 | 
			
		||||
        $gcode .= " ; $description"
 | 
			
		||||
            if $self->config->gcode_comments;
 | 
			
		||||
        $gcode .= "\n";
 | 
			
		||||
        
 | 
			
		||||
        $self->wipe_path(undef);
 | 
			
		||||
    } else {
 | 
			
		||||
    {
 | 
			
		||||
        my $local_F = $F;
 | 
			
		||||
        foreach my $line ($path->lines) {
 | 
			
		||||
            $path_length += my $line_length = unscale $line->length;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										133
									
								
								lib/Slic3r/GCode/ArcFitting.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								lib/Slic3r/GCode/ArcFitting.pm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,133 @@
 | 
			
		|||
package Slic3r::GCode::ArcFitting;
 | 
			
		||||
use Moo;
 | 
			
		||||
 | 
			
		||||
use Slic3r::Geometry qw(X Y PI scale unscale deg2rad);
 | 
			
		||||
 | 
			
		||||
extends 'Slic3r::GCode::Reader';
 | 
			
		||||
has 'config'                    => (is => 'ro', required => 1);
 | 
			
		||||
has 'max_angle'                 => (is => 'rw', default => sub { deg2rad(15) });
 | 
			
		||||
has 'len_epsilon'               => (is => 'rw', default => sub { scale 10 });
 | 
			
		||||
has 'parallel_degrees_limit'    => (is => 'rw', default => sub { abs(deg2rad(3)) });
 | 
			
		||||
 | 
			
		||||
sub process {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my ($gcode) = @_;
 | 
			
		||||
    
 | 
			
		||||
    my $new_gcode           = "";
 | 
			
		||||
    my $buffer              = "";
 | 
			
		||||
    my @cur_path            = ();
 | 
			
		||||
    my $cur_len             = 0;
 | 
			
		||||
    my $cur_relative_angle  = 0;
 | 
			
		||||
    
 | 
			
		||||
    $self->parse($gcode, sub {
 | 
			
		||||
        my ($reader, $cmd, $args, $info) = @_;
 | 
			
		||||
        
 | 
			
		||||
        if ($info->{extruding} && $info->{dist_XY} > 0) {
 | 
			
		||||
            my $point = Slic3r::Point->new_scale($args->{X}, $args->{Y});
 | 
			
		||||
            
 | 
			
		||||
            if (@cur_path >= 2) {
 | 
			
		||||
                if ($cur_path[-1]->distance_to($point) > $self->len_epsilon) {
 | 
			
		||||
                    # if the last distance is not compatible with the current arc, flush it
 | 
			
		||||
                    $new_gcode .= $self->flush_path(\@cur_path, \$buffer);
 | 
			
		||||
                } elsif (@cur_path >= 3) {
 | 
			
		||||
                    my $rel_angle = relative_angle(@cur_path[-2,-1], $point);
 | 
			
		||||
                    if (($cur_relative_angle != 0 && abs($rel_angle - $cur_relative_angle) > $self->parallel_degrees_limit)   # relative angle is too different from the previous one
 | 
			
		||||
                        || abs($rel_angle) < $self->parallel_degrees_limit                            # relative angle is almost parallel
 | 
			
		||||
                        || $rel_angle > $self->max_angle) {                                           # relative angle is excessive (too sharp)
 | 
			
		||||
                        # in these cases, $point does not really look like an additional point of the current arc
 | 
			
		||||
                        $new_gcode .= $self->flush_path(\@cur_path, \$buffer);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            if (@cur_path == 0) {
 | 
			
		||||
                # we're starting a path, so let's prepend the previous position
 | 
			
		||||
                push @cur_path, Slic3r::Point->new_scale($self->X, $self->Y), $point;
 | 
			
		||||
                $buffer .= $info->{raw} . "\n";
 | 
			
		||||
                $cur_len = $cur_path[0]->distance_to($cur_path[1]);
 | 
			
		||||
            } else {
 | 
			
		||||
                push @cur_path, $point;
 | 
			
		||||
                $buffer .= $info->{raw} . "\n";
 | 
			
		||||
                if (@cur_path == 3) {
 | 
			
		||||
                    # we have two segments, time to compute a reference angle
 | 
			
		||||
                    $cur_relative_angle = relative_angle(@cur_path[0,1,2]);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            $new_gcode .= $self->flush_path(\@cur_path, \$buffer);
 | 
			
		||||
            $new_gcode .= $info->{raw} . "\n";
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    $new_gcode .= $self->flush_path(\@cur_path, \$buffer);
 | 
			
		||||
    return $new_gcode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub flush_path {
 | 
			
		||||
    my ($self, $cur_path, $buffer) = @_;
 | 
			
		||||
    
 | 
			
		||||
    my $gcode = "";
 | 
			
		||||
    
 | 
			
		||||
    if (@$cur_path >= 3) {
 | 
			
		||||
        # if we have enough points, then we have an arc
 | 
			
		||||
        $$buffer =~ s/^/;/mg;
 | 
			
		||||
        $gcode = "; these moves were replaced by an arc:\n" . $$buffer;
 | 
			
		||||
        
 | 
			
		||||
        my $orientation = Slic3r::Geometry::point_is_on_left_of_segment($cur_path->[2], [ @$cur_path[0,1] ]) ? 'ccw' : 'cw';
 | 
			
		||||
        
 | 
			
		||||
        # to find the center, we intersect the perpendicular lines
 | 
			
		||||
        # passing by midpoints of $s1 and last segment
 | 
			
		||||
        # a better method would be to draw all the perpendicular lines
 | 
			
		||||
        # and find the centroid of the enclosed polygon, or to
 | 
			
		||||
        # intersect multiple lines and find the centroid of the convex hull
 | 
			
		||||
        # around the intersections
 | 
			
		||||
        my $arc_center;
 | 
			
		||||
        {
 | 
			
		||||
            my $s1_mid      = Slic3r::Line->new(@$cur_path[0,1])->midpoint;
 | 
			
		||||
            my $last_mid    = Slic3r::Line->new(@$cur_path[-2,-1])->midpoint;
 | 
			
		||||
            my $rotation_angle = PI/2 * ($orientation eq 'ccw' ? -1 : 1);
 | 
			
		||||
            my $ray1        = Slic3r::Line->new($s1_mid,   $cur_path->[1]->clone->rotate($rotation_angle, $s1_mid));
 | 
			
		||||
            my $last_ray    = Slic3r::Line->new($last_mid, $cur_path->[-1]->clone->rotate($rotation_angle, $last_mid));
 | 
			
		||||
            $arc_center     = $ray1->intersection($last_ray, 0) or next POINT;
 | 
			
		||||
        }
 | 
			
		||||
        my $radius = $arc_center->distance_to($cur_path->[0]);
 | 
			
		||||
        my $total_angle = Slic3r::Geometry::angle3points($arc_center, @$cur_path[0,-1]);
 | 
			
		||||
        my $length = $orientation eq 'ccw'
 | 
			
		||||
            ? $radius * $total_angle
 | 
			
		||||
            : $radius * (2*PI - $total_angle);
 | 
			
		||||
        
 | 
			
		||||
        # compose G-code line
 | 
			
		||||
        $gcode .= $orientation eq 'cw' ? "G2" : "G3";
 | 
			
		||||
        $gcode .= sprintf " X%.3f Y%.3f", map unscale($_), @{$cur_path->[-1]};  # destination point
 | 
			
		||||
        
 | 
			
		||||
        # XY distance of the center from the start position
 | 
			
		||||
        $gcode .= sprintf " I%.3f J%.3f", map { unscale($arc_center->[$_] - $cur_path->[0][$_]) } (X,Y);
 | 
			
		||||
        
 | 
			
		||||
        my $E = 0;  # TODO: compute E using $length
 | 
			
		||||
        $gcode .= sprintf(" %s%.5f", $self->config->extrusion_axis, $E)
 | 
			
		||||
            if $E;
 | 
			
		||||
        
 | 
			
		||||
        my $F = 0;  # TODO: extract F from original moves
 | 
			
		||||
        $gcode .= " F$F\n";
 | 
			
		||||
    } else {
 | 
			
		||||
        $gcode = $$buffer;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    $$buffer = "";
 | 
			
		||||
    splice @$cur_path, 0, $#$cur_path;  # keep last point as starting position for next path
 | 
			
		||||
    return $gcode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub relative_angle {
 | 
			
		||||
    my ($p1, $p2, $p3) = @_;
 | 
			
		||||
    
 | 
			
		||||
    my $s1 = Slic3r::Line->new($p1, $p2);
 | 
			
		||||
    my $s2 = Slic3r::Line->new($p2, $p3);
 | 
			
		||||
    my $s1_angle = $s1->atan;
 | 
			
		||||
    my $s2_angle = $s2->atan;
 | 
			
		||||
    $s1_angle += 2*PI if $s1_angle < 0;
 | 
			
		||||
    $s2_angle += 2*PI if $s2_angle < 0;
 | 
			
		||||
    return $s2_angle - $s1_angle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ has 'shift'                         => (is => 'ro', required => 1);
 | 
			
		|||
 | 
			
		||||
has 'spiralvase'                    => (is => 'lazy');
 | 
			
		||||
has 'vibration_limit'               => (is => 'lazy');
 | 
			
		||||
has 'arc_fitting'                   => (is => 'lazy');
 | 
			
		||||
has 'skirt_done'                    => (is => 'rw', default => sub { {} });  # print_z => 1
 | 
			
		||||
has 'brim_done'                     => (is => 'rw');
 | 
			
		||||
has 'second_layer_things_done'      => (is => 'rw');
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +32,14 @@ sub _build_vibration_limit {
 | 
			
		|||
        : undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _build_arc_fitting {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    
 | 
			
		||||
    return $Slic3r::Config->gcode_arcs
 | 
			
		||||
        ? Slic3r::GCode::ArcFitting->new(config => $self->gcodegen->config)
 | 
			
		||||
        : undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub process_layer {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my ($layer, $object_copies) = @_;
 | 
			
		||||
| 
						 | 
				
			
			@ -177,6 +186,10 @@ sub process_layer {
 | 
			
		|||
    $gcode = $self->vibration_limit->process($gcode)
 | 
			
		||||
        if $Slic3r::Config->vibration_limit != 0;
 | 
			
		||||
    
 | 
			
		||||
    # apply arc fitting if enabled
 | 
			
		||||
    $gcode = $self->arc_fitting->process($gcode)
 | 
			
		||||
        if $Slic3r::Config->gcode_arcs;
 | 
			
		||||
    
 | 
			
		||||
    return $gcode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,11 @@ sub new {
 | 
			
		|||
    return $self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub new_scale {
 | 
			
		||||
    my $class = shift;
 | 
			
		||||
    return $class->new(map Slic3r::Geometry::scale($_), @_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub clone {
 | 
			
		||||
    Storable::dclone($_[0])
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								t/arcs.t
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								t/arcs.t
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2,6 +2,7 @@ use Test::More;
 | 
			
		|||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
 | 
			
		||||
plan skip_all => 'arcs are currently disabled';
 | 
			
		||||
plan tests => 13;
 | 
			
		||||
 | 
			
		||||
BEGIN {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue