mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	Merge branch 'master' into xs
This commit is contained in:
		
						commit
						eb2d20d062
					
				
					 18 changed files with 110 additions and 77 deletions
				
			
		
							
								
								
									
										1
									
								
								MANIFEST
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								MANIFEST
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -71,6 +71,7 @@ t/cooling.t
 | 
			
		|||
t/custom_gcode.t
 | 
			
		||||
t/dynamic.t
 | 
			
		||||
t/fill.t
 | 
			
		||||
t/freeze.t
 | 
			
		||||
t/gcode.t
 | 
			
		||||
t/geometry.t
 | 
			
		||||
t/layers.t
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ use List::Util qw(first);
 | 
			
		|||
use Math::Geometry::Voronoi;
 | 
			
		||||
use Slic3r::Geometry qw(X Y A B point_in_polygon same_line epsilon);
 | 
			
		||||
use Slic3r::Geometry::Clipper qw(union_ex JT_MITER);
 | 
			
		||||
use Storable qw();
 | 
			
		||||
 | 
			
		||||
# the constructor accepts an array of polygons 
 | 
			
		||||
# or a Math::Clipper ExPolygon (hashref)
 | 
			
		||||
| 
						 | 
				
			
			@ -17,19 +18,18 @@ sub new {
 | 
			
		|||
    my $self;
 | 
			
		||||
    if (@_ == 1 && ref $_[0] eq 'HASH') {
 | 
			
		||||
        $self = [
 | 
			
		||||
            Slic3r::Polygon->new($_[0]{outer}),
 | 
			
		||||
            map Slic3r::Polygon->new($_), @{$_[0]{holes}},
 | 
			
		||||
            Slic3r::Polygon->new(@{$_[0]{outer}}),
 | 
			
		||||
            map Slic3r::Polygon->new(@$_), @{$_[0]{holes}},
 | 
			
		||||
        ];
 | 
			
		||||
    } else {
 | 
			
		||||
        $self = [ map Slic3r::Polygon->new($_), @_ ];
 | 
			
		||||
        $self = [ map Slic3r::Polygon->new(@$_), @_ ];
 | 
			
		||||
    }
 | 
			
		||||
    bless $self, $class;
 | 
			
		||||
    $self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub clone {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    return (ref $self)->new(map $_->clone, @$self);
 | 
			
		||||
    Storable::dclone($_[0])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub contour {
 | 
			
		||||
| 
						 | 
				
			
			@ -287,7 +287,7 @@ sub medial_axis {
 | 
			
		|||
            next if @$polyline == 2;
 | 
			
		||||
            push @result, Slic3r::Polygon->new(@$polyline[0..$#$polyline-1]);
 | 
			
		||||
        } else {
 | 
			
		||||
            push @result, Slic3r::Polyline->new($polyline);
 | 
			
		||||
            push @result, Slic3r::Polyline->new(@$polyline);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -160,14 +160,14 @@ sub split_at_acute_angles {
 | 
			
		|||
            # if the angle between $p[-2], $p[-1], $p3 is too acute
 | 
			
		||||
            # then consider $p3 only as a starting point of a new
 | 
			
		||||
            # path and stop the current one as it is
 | 
			
		||||
            push @paths, $self->clone(polyline => Slic3r::Polyline->new(\@p));
 | 
			
		||||
            push @paths, $self->clone(polyline => Slic3r::Polyline->new(@p));
 | 
			
		||||
            @p = ($p3);
 | 
			
		||||
            push @p, grep $_, shift @points or last;
 | 
			
		||||
        } else {
 | 
			
		||||
            push @p, $p3;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    push @paths, $self->clone(polyline => Slic3r::Polyline->new(\@p))
 | 
			
		||||
    push @paths, $self->clone(polyline => Slic3r::Polyline->new(@p))
 | 
			
		||||
        if @p > 1;
 | 
			
		||||
    
 | 
			
		||||
    return @paths;
 | 
			
		||||
| 
						 | 
				
			
			@ -254,7 +254,7 @@ sub detect_arcs {
 | 
			
		|||
            }
 | 
			
		||||
            
 | 
			
		||||
            my $arc = Slic3r::ExtrusionPath::Arc->new(
 | 
			
		||||
                polyline    => Slic3r::Polyline->new(\@arc_points),
 | 
			
		||||
                polyline    => Slic3r::Polyline->new(@arc_points),
 | 
			
		||||
                role        => $self->role,
 | 
			
		||||
                flow_spacing => $self->flow_spacing,
 | 
			
		||||
                orientation => $orientation,
 | 
			
		||||
| 
						 | 
				
			
			@ -279,7 +279,7 @@ sub detect_arcs {
 | 
			
		|||
    }
 | 
			
		||||
    
 | 
			
		||||
    # remaining points form a linear path
 | 
			
		||||
    push @paths, $self->clone(polyline => Slic3r::Polyline->new(\@points))
 | 
			
		||||
    push @paths, $self->clone(polyline => Slic3r::Polyline->new(@points))
 | 
			
		||||
        if @points > 1;
 | 
			
		||||
    
 | 
			
		||||
    return @paths;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,7 +71,7 @@ sub fill_surface {
 | 
			
		|||
                $x += $m->{distance};
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            push @polygons, Slic3r::Polygon->new($p);
 | 
			
		||||
            push @polygons, Slic3r::Polygon->new(@$p);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        $_->rotate(-$rotate_vector->[0][0], $m->{hex_center}) for @polygons;
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +88,7 @@ sub fill_surface {
 | 
			
		|||
        # consider polygons as polylines without re-appending the initial point:
 | 
			
		||||
        # this cuts the last segment on purpose, so that the jump to the next 
 | 
			
		||||
        # path is more straight
 | 
			
		||||
        @paths = map Slic3r::Polyline->new($_),
 | 
			
		||||
        @paths = map Slic3r::Polyline->new(@$_),
 | 
			
		||||
            @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection(
 | 
			
		||||
                $surface->expolygon,
 | 
			
		||||
                \@polygons,
 | 
			
		||||
| 
						 | 
				
			
			@ -113,7 +113,7 @@ sub fill_surface {
 | 
			
		|||
        }
 | 
			
		||||
        
 | 
			
		||||
        # clip paths again to prevent connection segments from crossing the expolygon boundaries
 | 
			
		||||
        @paths = map Slic3r::Polyline->new($_),
 | 
			
		||||
        @paths = map Slic3r::Polyline->new(@$_),
 | 
			
		||||
            @{ Boost::Geometry::Utils::multi_polygon_multi_linestring_intersection(
 | 
			
		||||
                [ $surface->expolygon->offset_ex(scaled_epsilon) ],
 | 
			
		||||
                [ @paths ],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,9 +33,9 @@ sub fill_surface {
 | 
			
		|||
    my $path = "Math::PlanePath::$1"->new;
 | 
			
		||||
    my @n = $self->get_n($path, [ map +($_ / $distance_between_lines), @{$bounding_box->bb} ]);
 | 
			
		||||
    
 | 
			
		||||
    my $polyline = Slic3r::Polyline->new([
 | 
			
		||||
    my $polyline = Slic3r::Polyline->new(
 | 
			
		||||
        map [ map {$_*$distance_between_lines} $path->n_to_xy($_) ], @n,
 | 
			
		||||
    ]);
 | 
			
		||||
    );
 | 
			
		||||
    return {} if !@$polyline;
 | 
			
		||||
    
 | 
			
		||||
    $self->process_polyline($polyline, $bounding_box);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,9 @@ use Slic3r::Geometry::Clipper qw(union_ex);
 | 
			
		|||
use Slic3r::Surface ':types';
 | 
			
		||||
 | 
			
		||||
has 'config'             => (is => 'ro', required => 1);
 | 
			
		||||
has 'multiple_extruders' => (is => 'ro', default => sub {0} );
 | 
			
		||||
has 'extruders'          => (is => 'ro', default => sub {0}, required => 1);
 | 
			
		||||
has 'multiple_extruders' => (is => 'lazy');
 | 
			
		||||
has 'enable_wipe'        => (is => 'lazy');   # at least one extruder has wipe enabled
 | 
			
		||||
has 'layer_count'        => (is => 'ro', required => 1 );
 | 
			
		||||
has 'layer'              => (is => 'rw');
 | 
			
		||||
has '_layer_overhangs'   => (is => 'rw');
 | 
			
		||||
| 
						 | 
				
			
			@ -63,6 +65,16 @@ my %role_speeds = (
 | 
			
		|||
    &EXTR_ROLE_GAPFILL                      => 'gap_fill',
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
sub _build_multiple_extruders {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    return @{$self->extruders} > 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _build_enable_wipe {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    return (first { $_->wipe } @{$self->extruders}) ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub set_shift {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my @shift = @_;
 | 
			
		||||
| 
						 | 
				
			
			@ -144,14 +156,14 @@ sub extrude_loop {
 | 
			
		|||
    # find candidate starting points
 | 
			
		||||
    # start looking for concave vertices not being overhangs
 | 
			
		||||
    my @concave = $loop->polygon->concave_points;
 | 
			
		||||
    my @candidates = grep Boost::Geometry::Utils::point_covered_by_multi_polygon($_, $self->_layer_overhangs),
 | 
			
		||||
    my @candidates = grep !Boost::Geometry::Utils::point_covered_by_multi_polygon($_, $self->_layer_overhangs),
 | 
			
		||||
        @concave;
 | 
			
		||||
    if (!@candidates) {
 | 
			
		||||
        # if none, look for any concave vertex
 | 
			
		||||
        @candidates = @concave;
 | 
			
		||||
        if (!@candidates) {
 | 
			
		||||
            # if none, look for any non-overhang vertex
 | 
			
		||||
            @candidates = grep Boost::Geometry::Utils::point_covered_by_multi_polygon($_, $self->_layer_overhangs),
 | 
			
		||||
            @candidates = grep !Boost::Geometry::Utils::point_covered_by_multi_polygon($_, $self->_layer_overhangs),
 | 
			
		||||
                @{$loop->polygon};
 | 
			
		||||
            if (!@candidates) {
 | 
			
		||||
                # if none, all points are valid candidates
 | 
			
		||||
| 
						 | 
				
			
			@ -169,7 +181,8 @@ sub extrude_loop {
 | 
			
		|||
    }
 | 
			
		||||
    
 | 
			
		||||
    # split the loop at the starting point and make a path
 | 
			
		||||
    my $extrusion_path = $loop->split_at(Slic3r::Geometry::nearest_point($last_pos, \@candidates));
 | 
			
		||||
    my $start_at = Slic3r::Geometry::nearest_point($last_pos, \@candidates);
 | 
			
		||||
    my $extrusion_path = $loop->split_at($start_at);
 | 
			
		||||
    
 | 
			
		||||
    # clip the path to avoid the extruder to get exactly on the first point of the loop;
 | 
			
		||||
    # if polyline was shorter than the clipping distance we'd get a null polyline, so
 | 
			
		||||
| 
						 | 
				
			
			@ -192,7 +205,7 @@ sub extrude_loop {
 | 
			
		|||
        # reapply the nearest point search for starting point
 | 
			
		||||
        @paths = Slic3r::ExtrusionPath::Collection
 | 
			
		||||
            ->new(paths => [@paths])
 | 
			
		||||
            ->chained_path($last_pos, 1);
 | 
			
		||||
            ->chained_path($start_at, 1);
 | 
			
		||||
    } else {
 | 
			
		||||
        push @paths, $extrusion_path;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -205,7 +218,7 @@ sub extrude_loop {
 | 
			
		|||
    
 | 
			
		||||
    # extrude along the path
 | 
			
		||||
    my $gcode = join '', map $self->extrude_path($_, $description, %params), @paths;
 | 
			
		||||
    $self->wipe_path($extrusion_path->polyline);
 | 
			
		||||
    $self->wipe_path($extrusion_path->polyline) if $self->enable_wipe;
 | 
			
		||||
    
 | 
			
		||||
    # make a little move inwards before leaving loop
 | 
			
		||||
    if ($loop->role == EXTR_ROLE_EXTERNAL_PERIMETER && $self->config->perimeters > 1) {
 | 
			
		||||
| 
						 | 
				
			
			@ -295,8 +308,8 @@ sub extrude_path {
 | 
			
		|||
            $path_length += $line_length;
 | 
			
		||||
            $gcode .= $self->G1($line->[B], undef, $e * $line_length, $description);
 | 
			
		||||
        }
 | 
			
		||||
        $self->wipe_path(Slic3r::Polyline->new([ reverse @{$path->points} ]))
 | 
			
		||||
            if $self->extruder->wipe;
 | 
			
		||||
        $self->wipe_path(Slic3r::Polyline->new(reverse @{$path->points}))
 | 
			
		||||
            if $self->enable_wipe;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if ($self->config->cooling) {
 | 
			
		||||
| 
						 | 
				
			
			@ -409,7 +422,7 @@ sub retract {
 | 
			
		|||
    # wipe
 | 
			
		||||
    my $wipe_path;
 | 
			
		||||
    if ($self->extruder->wipe && $self->wipe_path) {
 | 
			
		||||
        $wipe_path = Slic3r::Polyline->new([ $self->last_pos, @{$self->wipe_path}[1..$#{$self->wipe_path}] ])
 | 
			
		||||
        $wipe_path = Slic3r::Polyline->new($self->last_pos, @{$self->wipe_path}[1..$#{$self->wipe_path}])
 | 
			
		||||
            ->clip_start($self->extruder->scaled_wipe_distance);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -888,7 +888,7 @@ sub repaint {
 | 
			
		|||
            
 | 
			
		||||
            # if sequential printing is enabled and we have more than one object
 | 
			
		||||
            if ($parent->{config}->complete_objects && (map @{$_->instances}, @{$parent->{objects}}) > 1) {
 | 
			
		||||
            	my $convex_hull = Slic3r::Polygon->new(convex_hull([ map @{$_->contour}, @{$parent->{object_previews}->[-1][2]->expolygons} ]));
 | 
			
		||||
            	my $convex_hull = Slic3r::Polygon->new(@{convex_hull([ map @{$_->contour}, @{$parent->{object_previews}->[-1][2]->expolygons} ])});
 | 
			
		||||
                my ($clearance) = @{offset([$convex_hull], $parent->{config}->extruder_clearance_radius / 2 * $parent->{scaling_factor}, 100, JT_ROUND)};
 | 
			
		||||
                $dc->SetPen($parent->{clearance_pen});
 | 
			
		||||
                $dc->SetBrush($parent->{transparent_brush});
 | 
			
		||||
| 
						 | 
				
			
			@ -899,7 +899,7 @@ sub repaint {
 | 
			
		|||
    
 | 
			
		||||
    # draw skirt
 | 
			
		||||
    if (@{$parent->{object_previews}} && $parent->{config}->skirts) {
 | 
			
		||||
        my $convex_hull = Slic3r::Polygon->new(convex_hull([ map @{$_->contour}, map @{$_->[2]->expolygons}, @{$parent->{object_previews}} ]));
 | 
			
		||||
        my $convex_hull = Slic3r::Polygon->new(@{convex_hull([ map @{$_->contour}, map @{$_->[2]->expolygons}, @{$parent->{object_previews}} ])});
 | 
			
		||||
        ($convex_hull) = @{offset([$convex_hull], $parent->{config}->skirt_distance * $parent->{scaling_factor}, 100, JT_ROUND)};
 | 
			
		||||
        $dc->SetPen($parent->{skirt_pen});
 | 
			
		||||
        $dc->SetBrush($parent->{transparent_brush});
 | 
			
		||||
| 
						 | 
				
			
			@ -1098,7 +1098,7 @@ sub _trigger_model_object {
 | 
			
		|||
	    $self->bounding_box($self->model_object->bounding_box);
 | 
			
		||||
	    
 | 
			
		||||
    	my $mesh = $self->model_object->mesh;
 | 
			
		||||
        $self->convex_hull(Slic3r::Polygon->new(Math::ConvexHull::MonotoneChain::convex_hull($mesh->used_vertices)));
 | 
			
		||||
        $self->convex_hull(Slic3r::Polygon->new(@{Math::ConvexHull::MonotoneChain::convex_hull($mesh->used_vertices)}));
 | 
			
		||||
	    $self->facets(scalar @{$mesh->facets});
 | 
			
		||||
	    $self->vertices(scalar @{$mesh->vertices});
 | 
			
		||||
	    
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,12 +38,12 @@ sub polygon {
 | 
			
		|||
    my $self = shift;
 | 
			
		||||
    
 | 
			
		||||
    my $e = $self->extents;
 | 
			
		||||
    return Slic3r::Polygon->new([
 | 
			
		||||
    return Slic3r::Polygon->new(
 | 
			
		||||
        [ $e->[X][MIN], $e->[Y][MIN] ],
 | 
			
		||||
        [ $e->[X][MAX], $e->[Y][MIN] ],
 | 
			
		||||
        [ $e->[X][MAX], $e->[Y][MAX] ],
 | 
			
		||||
        [ $e->[X][MIN], $e->[Y][MAX] ],
 | 
			
		||||
    ]);
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# note to $self
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,7 +83,7 @@ sub diff {
 | 
			
		|||
    $clipper->add_subject_polygons($subject);
 | 
			
		||||
    $clipper->add_clip_polygons($safety_offset ? safety_offset($clip) : $clip);
 | 
			
		||||
    return [
 | 
			
		||||
        map Slic3r::Polygon->new($_),
 | 
			
		||||
        map Slic3r::Polygon->new(@$_),
 | 
			
		||||
            @{ $clipper->execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO) },
 | 
			
		||||
    ];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -126,7 +126,7 @@ sub intersection {
 | 
			
		|||
    $clipper->add_subject_polygons($subject);
 | 
			
		||||
    $clipper->add_clip_polygons($safety_offset ? safety_offset($clip) : $clip);
 | 
			
		||||
    return [
 | 
			
		||||
        map Slic3r::Polygon->new($_),
 | 
			
		||||
        map Slic3r::Polygon->new(@$_),
 | 
			
		||||
            @{ $clipper->execute(CT_INTERSECTION, $jointype, $jointype) },
 | 
			
		||||
    ];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ use List::Util qw(sum first);
 | 
			
		|||
use Slic3r::ExtrusionPath ':roles';
 | 
			
		||||
use Slic3r::Geometry qw(PI A B scale chained_path_items points_coincide);
 | 
			
		||||
use Slic3r::Geometry::Clipper qw(safety_offset union_ex diff_ex intersection_ex 
 | 
			
		||||
    offset offset2_ex PFT_EVENODD union_pt traverse_pt diff intersection);
 | 
			
		||||
    offset offset2 offset2_ex PFT_EVENODD union_pt traverse_pt diff intersection);
 | 
			
		||||
use Slic3r::Surface ':types';
 | 
			
		||||
 | 
			
		||||
has 'layer' => (
 | 
			
		||||
| 
						 | 
				
			
			@ -98,12 +98,9 @@ sub make_surfaces {
 | 
			
		|||
    # detect thin walls by offsetting slices by half extrusion inwards
 | 
			
		||||
    {
 | 
			
		||||
        my $width = $self->perimeter_flow->scaled_width;
 | 
			
		||||
        my $outgrown = [
 | 
			
		||||
            offset2_ex([ map @$_, map $_->expolygon, @{$self->slices} ], -$width, +$width),
 | 
			
		||||
        ];
 | 
			
		||||
        my $diff = diff_ex(
 | 
			
		||||
            [ map $_->p, @{$self->slices} ],
 | 
			
		||||
            [ map @$_, @$outgrown ],
 | 
			
		||||
            [ offset2([ map @$_, map $_->expolygon, @{$self->slices} ], -$width, +$width) ],
 | 
			
		||||
            1,
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
| 
						 | 
				
			
			@ -195,7 +192,7 @@ sub make_perimeters {
 | 
			
		|||
            
 | 
			
		||||
            # where offset2() collapses the expolygon, then there's no room for an inner loop
 | 
			
		||||
            # and we can extract the gap for later processing
 | 
			
		||||
            {
 | 
			
		||||
            if ($Slic3r::Config->gap_fill_speed > 0 && $Slic3r::Config->fill_density > 0) {
 | 
			
		||||
                my $diff = diff_ex(
 | 
			
		||||
                    [ offset(\@last, -0.5*$spacing) ],
 | 
			
		||||
                    # +2 on the offset here makes sure that Clipper float truncation 
 | 
			
		||||
| 
						 | 
				
			
			@ -226,19 +223,10 @@ sub make_perimeters {
 | 
			
		|||
    
 | 
			
		||||
    $self->_fill_gaps(\@gaps);
 | 
			
		||||
    
 | 
			
		||||
    # TODO: can these be removed?
 | 
			
		||||
    @contours   = grep $_->is_printable($self->perimeter_flow->scaled_width), @contours;
 | 
			
		||||
    @holes      = grep $_->is_printable($self->perimeter_flow->scaled_width), @holes;
 | 
			
		||||
    
 | 
			
		||||
    # find nesting hierarchies separately for contours and holes
 | 
			
		||||
    my $contours_pt = union_pt(\@contours, PFT_EVENODD);
 | 
			
		||||
    my $holes_pt    = union_pt(\@holes, PFT_EVENODD);
 | 
			
		||||
    
 | 
			
		||||
    # get lower layer slices for overhang check
 | 
			
		||||
    my @lower_slices = $self->id == 0
 | 
			
		||||
        ? ()
 | 
			
		||||
        : map @$_, @{$self->layer->object->layers->[$self->id-1]->slices};
 | 
			
		||||
    
 | 
			
		||||
    # prepare a coderef for traversing the PolyTree object
 | 
			
		||||
    # external contours are root items of $contours_pt
 | 
			
		||||
    # internal contours are the ones next to external
 | 
			
		||||
| 
						 | 
				
			
			@ -259,7 +247,7 @@ sub make_perimeters {
 | 
			
		|||
            # return ccw contours and cw holes
 | 
			
		||||
            # GCode.pm will convert all of them to ccw, but it needs to know
 | 
			
		||||
            # what the holes are in order to compute the correct inwards move
 | 
			
		||||
            my $polygon = Slic3r::Polygon->new($polynode->{outer} // [ reverse @{$polynode->{hole}} ]);
 | 
			
		||||
            my $polygon = Slic3r::Polygon->new(defined $polynode->{outer} ? @{$polynode->{outer}} : reverse @{$polynode->{hole}});
 | 
			
		||||
            $polygon->reverse if !$is_contour;
 | 
			
		||||
            
 | 
			
		||||
            my $role = EXTR_ROLE_PERIMETER;
 | 
			
		||||
| 
						 | 
				
			
			@ -312,7 +300,7 @@ sub _fill_gaps {
 | 
			
		|||
    my $self = shift;
 | 
			
		||||
    my ($gaps) = @_;
 | 
			
		||||
    
 | 
			
		||||
    return unless $Slic3r::Config->gap_fill_speed > 0 && $Slic3r::Config->fill_density > 0 && @$gaps;
 | 
			
		||||
    return unless @$gaps;
 | 
			
		||||
    
 | 
			
		||||
    my $filler = $self->layer->object->fill_maker->filler('rectilinear');
 | 
			
		||||
    $filler->layer_id($self->layer->id);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,8 @@ package Slic3r::Point;
 | 
			
		|||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
 | 
			
		||||
use Storable qw();
 | 
			
		||||
 | 
			
		||||
sub new {
 | 
			
		||||
    my $class = shift;
 | 
			
		||||
    my $self;
 | 
			
		||||
| 
						 | 
				
			
			@ -19,8 +21,7 @@ sub new {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
sub clone {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    return (ref $self)->new(@$self);
 | 
			
		||||
    Storable::dclone($_[0])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub coincides_with {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,25 +6,20 @@ use Scalar::Util qw(reftype);
 | 
			
		|||
use Slic3r::Geometry qw(A B X Y X1 X2 Y1 Y2 polyline_remove_parallel_continuous_edges polyline_remove_acute_vertices
 | 
			
		||||
    polyline_lines move_points same_point);
 | 
			
		||||
use Slic3r::Geometry::Clipper qw(JT_SQUARE);
 | 
			
		||||
use Storable qw();
 | 
			
		||||
 | 
			
		||||
# the constructor accepts an array(ref) of points
 | 
			
		||||
sub new {
 | 
			
		||||
    my $class = shift;
 | 
			
		||||
    my $self;
 | 
			
		||||
    if (@_ == 1) {
 | 
			
		||||
        $self = [ @{$_[0]} ];
 | 
			
		||||
    } else {
 | 
			
		||||
        $self = [ @_ ];
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    my $self = [ @_ ];
 | 
			
		||||
    bless $self, $class;
 | 
			
		||||
    bless $_, 'Slic3r::Point' for @$self;
 | 
			
		||||
    $self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub clone {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    return (ref $self)->new(map $_->clone, @$self);
 | 
			
		||||
    Storable::dclone($_[0])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub serialize {
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +60,7 @@ sub simplify {
 | 
			
		|||
    my $tolerance = shift || 10;
 | 
			
		||||
    
 | 
			
		||||
    my $simplified = Boost::Geometry::Utils::linestring_simplify($self, $tolerance);
 | 
			
		||||
    return (ref $self)->new($simplified);
 | 
			
		||||
    return (ref $self)->new(@$simplified);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub reverse {
 | 
			
		||||
| 
						 | 
				
			
			@ -83,9 +78,9 @@ sub grow {
 | 
			
		|||
    my ($distance, $scale, $joinType, $miterLimit) = @_;
 | 
			
		||||
    $joinType //= JT_SQUARE;
 | 
			
		||||
    
 | 
			
		||||
    return map Slic3r::Polygon->new($_),
 | 
			
		||||
    return map Slic3r::Polygon->new(@$_),
 | 
			
		||||
        Slic3r::Geometry::Clipper::offset(
 | 
			
		||||
            [ Slic3r::Polygon->new(@$self, CORE::reverse @$self[1..($#$self-1)]) ],
 | 
			
		||||
            [ [ @$self, CORE::reverse @$self[1..($#$self-1)] ] ],
 | 
			
		||||
            $distance, $scale, $joinType, $miterLimit,
 | 
			
		||||
        );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -170,8 +170,8 @@ sub validate {
 | 
			
		|||
                my $clearance;
 | 
			
		||||
                {
 | 
			
		||||
                    my @points = map [ @$_[X,Y] ], map @{$_->vertices}, @{$self->objects->[$obj_idx]->meshes};
 | 
			
		||||
                    my $convex_hull = Slic3r::Polygon->new(convex_hull(\@points));
 | 
			
		||||
                    ($clearance) = map Slic3r::Polygon->new($_), 
 | 
			
		||||
                    my $convex_hull = Slic3r::Polygon->new(@{convex_hull(\@points)});
 | 
			
		||||
                    ($clearance) = map Slic3r::Polygon->new(@$_), 
 | 
			
		||||
                                        Slic3r::Geometry::Clipper::offset(
 | 
			
		||||
                                            [$convex_hull], scale $Slic3r::Config->extruder_clearance_radius / 2, 1, JT_ROUND);
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -665,7 +665,7 @@ sub make_brim {
 | 
			
		|||
    }
 | 
			
		||||
    
 | 
			
		||||
    @{$self->brim} = map Slic3r::ExtrusionLoop->pack(
 | 
			
		||||
        polygon         => Slic3r::Polygon->new($_),
 | 
			
		||||
        polygon         => Slic3r::Polygon->new(@$_),
 | 
			
		||||
        role            => EXTR_ROLE_SKIRT,
 | 
			
		||||
        flow_spacing    => $flow->spacing,
 | 
			
		||||
    ), reverse traverse_pt( union_pt(\@loops, PFT_EVENODD) );
 | 
			
		||||
| 
						 | 
				
			
			@ -711,7 +711,7 @@ sub write_gcode {
 | 
			
		|||
    # set up our extruder object
 | 
			
		||||
    my $gcodegen = Slic3r::GCode->new(
 | 
			
		||||
        config              => $self->config,
 | 
			
		||||
        multiple_extruders  => (@{$self->extruders} > 1),
 | 
			
		||||
        extruders           => $self->extruders,
 | 
			
		||||
        layer_count         => $self->layer_count,
 | 
			
		||||
    );
 | 
			
		||||
    print $fh "G21 ; set units to millimeters\n" if $Slic3r::Config->gcode_flavor ne 'makerware';
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,9 +57,15 @@ sub model {
 | 
			
		|||
        ],
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    my $mesh = Slic3r::TriangleMesh->new(
 | 
			
		||||
        vertices    => $vertices,
 | 
			
		||||
        facets      => $facets,
 | 
			
		||||
    );
 | 
			
		||||
    $mesh->scale($params{scale}) if $params{scale};
 | 
			
		||||
    
 | 
			
		||||
    my $model = Slic3r::Model->new;
 | 
			
		||||
    my $object = $model->add_object(vertices => $vertices);
 | 
			
		||||
    $object->add_volume(facets => $facets);
 | 
			
		||||
    my $object = $model->add_object(vertices => $mesh->vertices);
 | 
			
		||||
    $object->add_volume(facets => $mesh->facets);
 | 
			
		||||
    $object->add_instance(
 | 
			
		||||
        offset      => [0,0],
 | 
			
		||||
        rotation    => $params{rotation} // 0,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,26 +12,26 @@ BEGIN {
 | 
			
		|||
use Slic3r;
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
    my $polygon = Slic3r::Polygon->new([
 | 
			
		||||
    my $polygon = Slic3r::Polygon->new(
 | 
			
		||||
        [5,0], [10,0], [15,0], [20,0], [20,10], [20,30], [0,0],
 | 
			
		||||
    ]);
 | 
			
		||||
    );
 | 
			
		||||
    
 | 
			
		||||
    $polygon->merge_continuous_lines;
 | 
			
		||||
    is scalar(@$polygon), 3, 'merge_continuous_lines';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
    my $polyline = Slic3r::Polyline->new([
 | 
			
		||||
    my $polyline = Slic3r::Polyline->new(
 | 
			
		||||
        [0,0],[1,0],[2,0],[2,1],[2,2],[1,2],[0,2],[0,1],[0,0],
 | 
			
		||||
    ]);
 | 
			
		||||
    );
 | 
			
		||||
    $polyline = $polyline->simplify(1);
 | 
			
		||||
    is_deeply $polyline, [ [0, 0], [2, 0], [2, 2], [0, 2], [0, 0] ], 'Douglas-Peucker';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
    my $polyline = Slic3r::Polyline->new([
 | 
			
		||||
    my $polyline = Slic3r::Polyline->new(
 | 
			
		||||
        [0,0],[0.5,0.5],[1,0],[1.25,-0.25],[1.5,.5],
 | 
			
		||||
    ]);
 | 
			
		||||
    );
 | 
			
		||||
    $polyline->scale(100);
 | 
			
		||||
    $polyline = $polyline->simplify(25);
 | 
			
		||||
    is_deeply $polyline, [ [0, 0], [50, 50], [125, -25], [150, 50] ], 'Douglas-Peucker';
 | 
			
		||||
| 
						 | 
				
			
			@ -69,7 +69,7 @@ use Slic3r;
 | 
			
		|||
        [197.307,292.831], [199.808,313.1906], [191.5298,315.0787], [187.3082,299.8172], [186.4201,295.3766], 
 | 
			
		||||
        [180.595,296.0487], [161.7854,297.4248], [156.8058,297.6214], [154.3395,317.8592],
 | 
			
		||||
    ];
 | 
			
		||||
    my $polygon = Slic3r::Polygon->new($gear);
 | 
			
		||||
    my $polygon = Slic3r::Polygon->new(@$gear);
 | 
			
		||||
    $polygon->merge_continuous_lines;
 | 
			
		||||
    note sprintf "original points: %d\nnew points: %d", scalar(@$gear), scalar(@$polygon);
 | 
			
		||||
    ok @$polygon < @$gear, 'gear was simplified using merge_continuous_lines';
 | 
			
		||||
| 
						 | 
				
			
			@ -114,7 +114,7 @@ use Slic3r;
 | 
			
		|||
        [3368.3,7868.6],[3409.2,7889.5],[3553.8,7963.2],[3596,7981.4],
 | 
			
		||||
    ];
 | 
			
		||||
    
 | 
			
		||||
    my $polygon = Slic3r::Polygon->new($circle);
 | 
			
		||||
    my $polygon = Slic3r::Polygon->new(@$circle);
 | 
			
		||||
    $polygon->merge_continuous_lines;
 | 
			
		||||
    note sprintf "original points: %d\nnew points: %d", scalar(@$circle), scalar(@$polygon);
 | 
			
		||||
    ok @$polygon >= @$circle/3, 'circle was simplified using merge_continuous_lines';
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										29
									
								
								t/freeze.t
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								t/freeze.t
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
use Test::More tests => 1;
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
 | 
			
		||||
BEGIN {
 | 
			
		||||
    use FindBin;
 | 
			
		||||
    use lib "$FindBin::Bin/../lib";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
use Slic3r;
 | 
			
		||||
use Slic3r::Test;
 | 
			
		||||
use Storable qw(nstore retrieve);
 | 
			
		||||
use Time::HiRes qw(gettimeofday tv_interval);
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
    my $t0 = [gettimeofday];
 | 
			
		||||
    my $print = Slic3r::Test::init_print('20mm_cube', scale => 2);
 | 
			
		||||
    my $gcode = Slic3r::Test::gcode($print);
 | 
			
		||||
    diag sprintf 'Slicing took %s seconds', tv_interval($t0);
 | 
			
		||||
    
 | 
			
		||||
    my $t1 = [gettimeofday];
 | 
			
		||||
    nstore $print, 'print.dat';
 | 
			
		||||
    $print = retrieve 'print.dat';
 | 
			
		||||
    diag sprintf 'Freezing and retrieving took %s seconds', tv_interval($t1);
 | 
			
		||||
    
 | 
			
		||||
    isa_ok $print, 'Slic3r::Print', 'restored Print object';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__END__
 | 
			
		||||
| 
						 | 
				
			
			@ -103,7 +103,7 @@ is_deeply $intersection, [ [120, 120], [180, 160] ], 'internal lines are preserv
 | 
			
		|||
        ], 'tangent line is clipped to square with hole';
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
        my $polyline = Slic3r::Polyline->new([ [50, 180], [250, 180], [250, 150], [150, 150], [150, 120], [120, 120], [120, 50] ]);
 | 
			
		||||
        my $polyline = Slic3r::Polyline->new([50, 180], [250, 180], [250, 150], [150, 150], [150, 120], [120, 120], [120, 50]);
 | 
			
		||||
        is_deeply [ map $_, $polyline->clip_with_expolygon($expolygon) ], [
 | 
			
		||||
            [ [100, 180], [200, 180] ],
 | 
			
		||||
            [ [200, 150], [160, 150] ],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ use Slic3r::Geometry qw(scale);
 | 
			
		|||
    foreach my $point (@$points) {
 | 
			
		||||
        @$point = map scale $_, @$point;
 | 
			
		||||
    }
 | 
			
		||||
    my $polyline = Slic3r::Polyline->new($points);
 | 
			
		||||
    my $polyline = Slic3r::Polyline->new(@$points);
 | 
			
		||||
    my $serialized = $polyline->serialize;
 | 
			
		||||
    my $deserialized = Slic3r::Polyline->deserialize($serialized);
 | 
			
		||||
    is scalar(@$deserialized), scalar(@$points), 'number of deserialized points';
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue