mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Bugfix: when processing with fill_density = 0, top/bottom solid shells were missing regions thinner than 3 * extrusion width. Includes regression test. #1602
This commit is contained in:
		
							parent
							
								
									cfbbb539a5
								
							
						
					
					
						commit
						7be042567d
					
				
					 3 changed files with 78 additions and 25 deletions
				
			
		|  | @ -584,7 +584,8 @@ sub discover_horizontal_shells { | |||
|                     next if $n < 0 || $n > $#{$self->layers}; | ||||
|                     Slic3r::debugf "  looking for neighbors on layer %d...\n", $n; | ||||
|                      | ||||
|                     my $neighbor_fill_surfaces = $self->layers->[$n]->regions->[$region_id]->fill_surfaces; | ||||
|                     my $neighbor_layerm = $self->layers->[$n]->regions->[$region_id]; | ||||
|                     my $neighbor_fill_surfaces = $neighbor_layerm->fill_surfaces; | ||||
|                     my @neighbor_fill_surfaces = map $_->clone, @$neighbor_fill_surfaces;  # clone because we will use these surfaces even after clearing the collection | ||||
|                      | ||||
|                     # find intersection between neighbor and current layer's surfaces | ||||
|  | @ -603,41 +604,49 @@ sub discover_horizontal_shells { | |||
|                     ); | ||||
|                     next EXTERNAL if !@$new_internal_solid; | ||||
|                      | ||||
|                     # make sure the new internal solid is wide enough, as it might get collapsed when | ||||
|                     # spacing is added in Fill.pm | ||||
|                     if ($self->config->fill_density == 0) { | ||||
|                         # if we're printing a hollow object we discard any solid shell thinner | ||||
|                         # than a perimeter width, since it's probably just crossing a sloping wall | ||||
|                         # and it's not wanted in a hollow print even if it would make sense when | ||||
|                         # obeying the solid shell count option strictly (DWIM!) | ||||
|                         my $margin = $neighbor_layerm->perimeter_flow->scaled_width; | ||||
|                         my $too_narrow = diff( | ||||
|                             $new_internal_solid, | ||||
|                             offset2($new_internal_solid, -$margin, +$margin, CLIPPER_OFFSET_SCALE, JT_MITER, 5), | ||||
|                             1, | ||||
|                         ); | ||||
|                         $new_internal_solid = $solid = diff( | ||||
|                             $new_internal_solid, | ||||
|                             $too_narrow, | ||||
|                         ) if @$too_narrow; | ||||
|                     } | ||||
|                      | ||||
|                     # make sure the new internal solid is wide enough, as it might get collapsed | ||||
|                     # when spacing is added in Fill.pm | ||||
|                     { | ||||
|                         my $margin = 3 * $layerm->solid_infill_flow->scaled_width; # require at least this size | ||||
|                         # we use a higher miterLimit here to handle areas with acute angles | ||||
|                         # in those cases, the default miterLimit would cut the corner and we'd | ||||
|                         # get a triangle in $too_narrow; if we grow it below then the shell | ||||
|                         # would have a different shape from the external surface and we'd still | ||||
|                         # have the same angle, so the next shell would be grown even more and so on. | ||||
|                         my $margin = 3 * $layerm->solid_infill_flow->scaled_width; # require at least this size | ||||
|                         my $too_narrow = diff( | ||||
|                             $new_internal_solid, | ||||
|                             offset2($new_internal_solid, -$margin, +$margin, CLIPPER_OFFSET_SCALE, JT_MITER, 5), | ||||
|                             1, | ||||
|                         ); | ||||
|                          | ||||
|                         # if some parts are going to collapse, use a different strategy according to fill density | ||||
|                         if (@$too_narrow) { | ||||
|                             if ($self->config->fill_density > 0) { | ||||
|                                 # if we have internal infill, grow the collapsing parts and add the extra area to  | ||||
|                                 # the neighbor layer as well as to our original surfaces so that we support this  | ||||
|                                 # additional area in the next shell too | ||||
| 
 | ||||
|                                 # make sure our grown surfaces don't exceed the fill area | ||||
|                                 my @grown = @{intersection( | ||||
|                                     offset($too_narrow, +$margin), | ||||
|                                     [ map $_->p, @neighbor_fill_surfaces ], | ||||
|                                 )}; | ||||
|                                 $new_internal_solid = $solid = [ @grown, @$new_internal_solid ]; | ||||
|                             } else { | ||||
|                                 # if we're printing a hollow object, we discard such small parts | ||||
|                                 $new_internal_solid = $solid = diff( | ||||
|                                     $new_internal_solid, | ||||
|                                     $too_narrow, | ||||
|                                 ); | ||||
|                             } | ||||
|                             # grow the collapsing parts and add the extra area to  the neighbor layer  | ||||
|                             # as well as to our original surfaces so that we support this  | ||||
|                             # additional area in the next shell too | ||||
|                          | ||||
|                             # make sure our grown surfaces don't exceed the fill area | ||||
|                             my @grown = @{intersection( | ||||
|                                 offset($too_narrow, +$margin), | ||||
|                                 [ map $_->p, @neighbor_fill_surfaces ], | ||||
|                             )}; | ||||
|                             $new_internal_solid = $solid = [ @grown, @$new_internal_solid ]; | ||||
|                         } | ||||
|                     } | ||||
|                      | ||||
|  |  | |||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										41
									
								
								t/fill.t
									
										
									
									
									
								
							
							
						
						
									
										41
									
								
								t/fill.t
									
										
									
									
									
								
							|  | @ -2,7 +2,7 @@ use Test::More; | |||
| use strict; | ||||
| use warnings; | ||||
| 
 | ||||
| plan tests => 40; | ||||
| plan tests => 41; | ||||
| 
 | ||||
| BEGIN { | ||||
|     use FindBin; | ||||
|  | @ -13,7 +13,7 @@ use List::Util qw(first); | |||
| use Math::ConvexHull::MonotoneChain qw(convex_hull); | ||||
| use Slic3r; | ||||
| use Slic3r::Geometry qw(scale X Y); | ||||
| use Slic3r::Geometry::Clipper qw(diff_ex); | ||||
| use Slic3r::Geometry::Clipper qw(union diff_ex); | ||||
| use Slic3r::Surface qw(:types); | ||||
| use Slic3r::Test; | ||||
| 
 | ||||
|  | @ -208,4 +208,41 @@ for my $pattern (qw(rectilinear honeycomb hilbertcurve concentric)) { | |||
|         "solid_infill_below_area and solid_infill_every_layers are ignored when fill_density is 0"; | ||||
| } | ||||
| 
 | ||||
| { | ||||
|     my $config = Slic3r::Config->new_from_defaults; | ||||
|     $config->set('skirts', 0); | ||||
|     $config->set('perimeters', 3); | ||||
|     $config->set('fill_density', 0); | ||||
|     $config->set('layer_height', 0.2); | ||||
|     $config->set('first_layer_height', 0.2); | ||||
|     $config->set('nozzle_diameter', [0.35]); | ||||
|     $config->set('infill_extruder', 2); | ||||
|     $config->set('infill_extrusion_width', 0.52); | ||||
|      | ||||
|     my $print = Slic3r::Test::init_print('A', config => $config); | ||||
|     my %infill = ();  # Z => [ Line, Line ... ] | ||||
|     my $tool = undef; | ||||
|     Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { | ||||
|         my ($self, $cmd, $args, $info) = @_; | ||||
|          | ||||
|         if ($cmd =~ /^T(\d+)/) { | ||||
|             $tool = $1; | ||||
|         } elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) { | ||||
|             if ($tool == $config->infill_extruder-1) { | ||||
|                 my $z = 1 * $self->Z; | ||||
|                 $infill{$z} ||= []; | ||||
|                 push @{$infill{$z}}, Slic3r::Line->new_scale( | ||||
|                     [ $self->X, $self->Y ], | ||||
|                     [ $info->{new_X}, $info->{new_Y} ], | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
|     my $grow_d = scale($config->infill_extrusion_width)/2; | ||||
|     my $layer0_infill = union([ map $_->grow($grow_d), @{ $infill{0.2} } ]); | ||||
|     my $layer1_infill = union([ map $_->grow($grow_d), @{ $infill{0.4} } ]); | ||||
|     my $diff = [ grep $_->area >= 2*$grow_d**2, @{diff_ex($layer0_infill, $layer1_infill)} ]; | ||||
|     is scalar(@$diff), 0, 'no missing parts in solid shell when fill_density is 0'; | ||||
| } | ||||
| 
 | ||||
| __END__ | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci