mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	Align rectilinear and line infill across layers (new implementation). #712
This commit is contained in:
		
							parent
							
								
									c723c07f8c
								
							
						
					
					
						commit
						430c825918
					
				
					 7 changed files with 57 additions and 51 deletions
				
			
		|  | @ -161,11 +161,6 @@ sub bounding_box_polygon { | |||
|     ]); | ||||
| } | ||||
| 
 | ||||
| sub bounding_box_center { | ||||
|     my $self = shift; | ||||
|     return Slic3r::Geometry::bounding_box_center($self->contour); | ||||
| } | ||||
| 
 | ||||
| sub clip_line { | ||||
|     my $self = shift; | ||||
|     my ($line) = @_;  # line must be a Slic3r::Line object | ||||
|  |  | |||
|  | @ -39,10 +39,9 @@ sub filler { | |||
|         return $FillTypes{$filler}->new; | ||||
|     } | ||||
|      | ||||
|     if (!$self->fillers->{$filler}) { | ||||
|         my $f = $self->fillers->{$filler} = $FillTypes{$filler}->new; | ||||
|         $f->bounding_box([ $self->print->bounding_box ]) if $f->can('bounding_box'); | ||||
|     } | ||||
|     $self->fillers->{$filler} ||= $FillTypes{$filler}->new( | ||||
|         bounding_box => [ $self->print->bounding_box ], | ||||
|     ); | ||||
|     return $self->fillers->{$filler}; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ use Slic3r::Geometry qw(PI); | |||
| 
 | ||||
| has 'layer_id'            => (is => 'rw'); | ||||
| has 'angle'               => (is => 'rw', default => sub { $Slic3r::Config->fill_angle }); | ||||
| has 'bounding_box'        => (is => 'ro', required => 1); | ||||
| 
 | ||||
| sub angles () { [0, PI/2] } | ||||
| 
 | ||||
|  | @ -15,7 +16,7 @@ sub infill_direction { | |||
|     # set infill angle | ||||
|     my (@rotate, @shift); | ||||
|     $rotate[0] = Slic3r::Geometry::deg2rad($self->angle); | ||||
|     $rotate[1] = $surface->expolygon->bounding_box_center; | ||||
|     $rotate[1] = Slic3r::Geometry::bounding_box_center($self->bounding_box); | ||||
|     @shift = @{$rotate[1]}; | ||||
|      | ||||
|     if (defined $self->layer_id) { | ||||
|  | @ -41,11 +42,9 @@ sub rotate_points { | |||
|     my @rotate = @{$rotate_vector->[0]}; | ||||
|     my @shift  = @{$rotate_vector->[1]}; | ||||
|      | ||||
|     # rotate points as needed | ||||
|     if ($rotate[0]) { | ||||
|         $expolygon->rotate(@rotate); | ||||
|         $expolygon->translate(@shift); | ||||
|     } | ||||
|     # rotate points | ||||
|     $expolygon->rotate(@rotate); | ||||
|     $expolygon->translate(@shift); | ||||
| } | ||||
| 
 | ||||
| sub rotate_points_back { | ||||
|  | @ -54,10 +53,8 @@ sub rotate_points_back { | |||
|     my @rotate = @{$rotate_vector->[0]}; | ||||
|     my @shift  = @{$rotate_vector->[1]}; | ||||
|      | ||||
|     if ($rotate[0]) { | ||||
|         @$paths = map [ Slic3r::Geometry::rotate_points(-$rotate[0], $rotate[1], @$_) ],  | ||||
|             map [ Slic3r::Geometry::move_points([map -$_, @shift], @$_) ], @$paths; | ||||
|     } | ||||
|     @$paths = map [ Slic3r::Geometry::rotate_points(-$rotate[0], $rotate[1], @$_) ],  | ||||
|         map [ Slic3r::Geometry::move_points([map -$_, @shift], @$_) ], @$paths; | ||||
| } | ||||
| 
 | ||||
| sub adjust_solid_spacing { | ||||
|  |  | |||
|  | @ -3,7 +3,6 @@ use Moo; | |||
| 
 | ||||
| extends 'Slic3r::Fill::Base'; | ||||
| 
 | ||||
| has 'bounding_box'  => (is => 'rw'); | ||||
| has 'cache'         => (is => 'rw', default => sub {{}}); | ||||
| 
 | ||||
| use Slic3r::Geometry qw(PI X1 Y1 X2 Y2 X Y scale); | ||||
|  | @ -25,7 +24,7 @@ sub fill_surface { | |||
|      | ||||
|     my $cache_id = sprintf "d%s_s%s_a%s", | ||||
|         $params{density}, $params{flow_spacing}, $rotate_vector->[0][0]; | ||||
|     if (!$self->cache->{$cache_id} || !defined $self->bounding_box) { | ||||
|     if (!$self->cache->{$cache_id}) { | ||||
|          | ||||
|         # hexagons math | ||||
|         my $hex_side = $distance / (sqrt(3)/2); | ||||
|  | @ -39,7 +38,7 @@ sub fill_surface { | |||
|          | ||||
|         # adjust actual bounding box to the nearest multiple of our hex pattern | ||||
|         # and align it so that it matches across layers | ||||
|         my $bounding_box = [ $self->bounding_box ? @{$self->bounding_box} : $expolygon->bounding_box ]; | ||||
|         my $bounding_box = [ @{$self->bounding_box} ];  # clone | ||||
|         $bounding_box->[$_] = 0 for X1, Y1; | ||||
|         { | ||||
|             my $bb_polygon = Slic3r::Polygon->new_from_bounding_box($bounding_box); | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ use Moo; | |||
| 
 | ||||
| extends 'Slic3r::Fill::Base'; | ||||
| 
 | ||||
| has 'cache'         => (is => 'rw', default => sub {{}}); | ||||
| 
 | ||||
| use Slic3r::Geometry qw(X1 Y1 X2 Y2 A B X Y scale unscale scaled_epsilon); | ||||
| 
 | ||||
| sub fill_surface { | ||||
|  | @ -16,39 +18,55 @@ sub fill_surface { | |||
|      | ||||
|     my ($expolygon_off) = $expolygon->offset_ex(scale $params{flow_spacing}/2); | ||||
|     return {} if !$expolygon_off;  # skip some very small polygons (which shouldn't arrive here) | ||||
|     my $bounding_box = [ $expolygon->bounding_box ]; | ||||
|      | ||||
|     my $flow_spacing = $params{flow_spacing}; | ||||
|     my $min_spacing = scale $params{flow_spacing}; | ||||
|     my $distance_between_lines = $min_spacing / $params{density}; | ||||
|     my $line_oscillation = $distance_between_lines - $min_spacing; | ||||
|      | ||||
|     my $flow_spacing = $params{flow_spacing}; | ||||
|     if ($params{density} == 1 && !$params{dont_adjust}) { | ||||
|         $distance_between_lines = $self->adjust_solid_spacing( | ||||
|             width       => $bounding_box->[X2] - $bounding_box->[X1], | ||||
|             distance    => $distance_between_lines, | ||||
|         ); | ||||
|         $flow_spacing = unscale $distance_between_lines; | ||||
|     } | ||||
|      | ||||
|     my $x = $bounding_box->[X1]; | ||||
|     my $is_line_pattern = $self->isa('Slic3r::Fill::Line'); | ||||
|     my @vertical_lines = (); | ||||
|     for (my $i = 0; $x <= $bounding_box->[X2] + scaled_epsilon; $i++) { | ||||
|         my $vertical_line = Slic3r::Line->new([$x, $bounding_box->[Y2]], [$x, $bounding_box->[Y1]]); | ||||
|         if ($is_line_pattern && $i % 2) { | ||||
|             $vertical_line->[A][X] += $line_oscillation; | ||||
|             $vertical_line->[B][X] -= $line_oscillation; | ||||
|      | ||||
|     my $cache_id = sprintf "d%s_s%s_a%s", | ||||
|         $params{density}, $params{flow_spacing}, $rotate_vector->[0][0]; | ||||
|      | ||||
|     if (!$self->cache->{$cache_id}) { | ||||
|         # compute bounding box | ||||
|         my $bounding_box = $self->bounding_box; | ||||
|         { | ||||
|             my $bb_expolygon = Slic3r::ExPolygon->new(Slic3r::Polygon->new_from_bounding_box($bounding_box)); | ||||
|             $self->rotate_points($bb_expolygon, $rotate_vector); | ||||
|             $bounding_box = [ $bb_expolygon->bounding_box ]; | ||||
|         } | ||||
|         push @vertical_lines, $vertical_line; | ||||
|         $x += $distance_between_lines; | ||||
|          | ||||
|         # define flow spacing according to requested density | ||||
|         if ($params{density} == 1 && !$params{dont_adjust}) { | ||||
|             $distance_between_lines = $self->adjust_solid_spacing( | ||||
|                 width       => $bounding_box->[X2] - $bounding_box->[X1], | ||||
|                 distance    => $distance_between_lines, | ||||
|             ); | ||||
|             $flow_spacing = unscale $distance_between_lines; | ||||
|         } | ||||
|          | ||||
|         # generate the basic pattern | ||||
|         my $x = $bounding_box->[X1]; | ||||
|         my @vertical_lines = (); | ||||
|         for (my $i = 0; $x <= $bounding_box->[X2] + scaled_epsilon; $i++) { | ||||
|             my $vertical_line = Slic3r::Line->new([$x, $bounding_box->[Y2]], [$x, $bounding_box->[Y1]]); | ||||
|             if ($is_line_pattern && $i % 2) { | ||||
|                 $vertical_line->[A][X] += $line_oscillation; | ||||
|                 $vertical_line->[B][X] -= $line_oscillation; | ||||
|             } | ||||
|             push @vertical_lines, $vertical_line; | ||||
|             $x += $distance_between_lines; | ||||
|         } | ||||
|          | ||||
|         $self->cache->{$cache_id} = [@vertical_lines]; | ||||
|     } | ||||
|      | ||||
|     # clip paths against a slightly offsetted expolygon, so that the first and last paths | ||||
|     # are kept even if the expolygon has vertical sides | ||||
|     my @paths = @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection( | ||||
|         +($expolygon->offset_ex(scaled_epsilon))[0],  # TODO: we should use all the resulting expolygons and clip the linestrings to a multipolygon object | ||||
|         [ @vertical_lines ], | ||||
|         [ @{ $self->cache->{$cache_id} } ], | ||||
|     ) }; | ||||
|      | ||||
|     # connect lines | ||||
|  |  | |||
|  | @ -679,10 +679,10 @@ sub bounding_box { | |||
| } | ||||
| 
 | ||||
| sub bounding_box_center { | ||||
|     my @bounding_box = bounding_box(@_); | ||||
|     my ($bounding_box) = @_; | ||||
|     return Slic3r::Point->new( | ||||
|         ($bounding_box[X2] + $bounding_box[X1]) / 2, | ||||
|         ($bounding_box[Y2] + $bounding_box[Y1]) / 2, | ||||
|         ($bounding_box->[X2] + $bounding_box->[X1]) / 2, | ||||
|         ($bounding_box->[Y2] + $bounding_box->[Y1]) / 2, | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -894,6 +894,7 @@ sub generate_support_material { | |||
|      | ||||
|     # generate paths for the pattern that we're going to use | ||||
|     Slic3r::debugf "Generating patterns\n"; | ||||
|     my $fill = Slic3r::Fill->new(print => $self->print); | ||||
|     my $support_patterns = []; | ||||
|     my $support_interface_patterns = []; | ||||
|     { | ||||
|  | @ -908,10 +909,7 @@ sub generate_support_material { | |||
|             push @angles, $angles[0] + 90; | ||||
|         } | ||||
|          | ||||
|         my $filler = Slic3r::Fill->filler($pattern); | ||||
|         $filler->bounding_box([ Slic3r::Geometry::bounding_box([ map @$_, map @$_, @areas ]) ]) | ||||
|             if $filler->can('bounding_box'); | ||||
|          | ||||
|         my $filler = $fill->filler($pattern); | ||||
|         my $make_pattern = sub { | ||||
|             my ($expolygon, $density) = @_; | ||||
|              | ||||
|  | @ -996,7 +994,7 @@ sub generate_support_material { | |||
|              | ||||
|             # make a solid base on bottom layer | ||||
|             if ($layer_id == 0) { | ||||
|                 my $filler = Slic3r::Fill->filler('rectilinear'); | ||||
|                 my $filler = $fill->filler('rectilinear'); | ||||
|                 $filler->angle($Slic3r::Config->support_material_angle + 90); | ||||
|                 foreach my $expolygon (@$islands) { | ||||
|                     my @paths = $filler->fill_surface( | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci