mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06: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
	
	 Alessandro Ranellucci
						Alessandro Ranellucci