mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	Bugfix: many thin walls were not detected correctly. #313
This commit is contained in:
		
							parent
							
								
									fbfbfac2b6
								
							
						
					
					
						commit
						85ef7ce665
					
				
					 2 changed files with 67 additions and 45 deletions
				
			
		|  | @ -215,54 +215,73 @@ sub medial_axis { | |||
|     } | ||||
|     return undef if !@skeleton_lines; | ||||
|      | ||||
|     # now build a single polyline | ||||
|     my $polyline = []; | ||||
|     # now walk along the medial axis and build continuos polylines or polygons | ||||
|     my @polylines = (); | ||||
|     { | ||||
|         my %pointmap = (); | ||||
|         foreach my $line (@skeleton_lines) { | ||||
|             foreach my $point_id (@$line) { | ||||
|                 $pointmap{$point_id} ||= []; | ||||
|                 push @{$pointmap{$point_id}}, $line; | ||||
|         # build a map of line endpoints | ||||
|         my %pointmap = ();  # point_idx => [line_idx, line_idx ...] | ||||
|         for my $line_idx (0 .. $#skeleton_lines) { | ||||
|             for my $point_idx (@{$skeleton_lines[$line_idx]}) { | ||||
|                 $pointmap{$point_idx} ||= []; | ||||
|                 push @{$pointmap{$point_idx}}, $line_idx; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         # start from a point having only one line | ||||
|         foreach my $point_id (keys %pointmap) { | ||||
|             if (@{$pointmap{$point_id}} == 1) { | ||||
|                 push @$polyline, grep $_ ne $point_id, map @$_, shift @{$pointmap{$point_id}}; | ||||
|                 last; | ||||
|             } | ||||
|         } | ||||
|         # build the list of available lines | ||||
|         my %spare_lines = map {$_ => 1} (0 .. $#skeleton_lines); | ||||
|          | ||||
|         # if no such point is found, pick a random one | ||||
|         push @$polyline, shift @{ +(values %pointmap)[0][0] } if !@$polyline; | ||||
|          | ||||
|         my %visited_lines = (); | ||||
|         while (1) { | ||||
|             my $last_point_id = $polyline->[-1]; | ||||
|         CYCLE: while (%spare_lines) { | ||||
|             push @polylines, []; | ||||
|             my $polyline = $polylines[-1]; | ||||
|              | ||||
|             shift @{ $pointmap{$last_point_id} } | ||||
|                 while @{ $pointmap{$last_point_id} } && $visited_lines{$pointmap{$last_point_id}[0]}; | ||||
|             my $next_line = shift @{ $pointmap{$last_point_id} } or last; | ||||
|             $visited_lines{$next_line} = 1; | ||||
|             push @$polyline, grep $_ ne $last_point_id, @$next_line; | ||||
|             # start from a random line | ||||
|             my $first_line_idx = +(keys %spare_lines)[0]; | ||||
|             delete $spare_lines{$first_line_idx}; | ||||
|             push @$polyline, @{ $skeleton_lines[$first_line_idx] }; | ||||
|              | ||||
|             while (1) { | ||||
|                 my $last_point_id = $polyline->[-1]; | ||||
|                 my $lines_starting_here = $pointmap{$last_point_id}; | ||||
|                  | ||||
|                 # remove all the visited lines from the array | ||||
|                 shift @$lines_starting_here | ||||
|                     while @$lines_starting_here && !$spare_lines{$lines_starting_here->[0]}; | ||||
|                  | ||||
|                 # do we have a line starting here? | ||||
|                 my $next_line_idx = shift @$lines_starting_here; | ||||
|                 if (!defined $next_line_idx) { | ||||
|                     delete $pointmap{$last_point_id}; | ||||
|                     next CYCLE; | ||||
|                 } | ||||
|                  | ||||
|                 # line is not available anymore | ||||
|                 delete $spare_lines{$next_line_idx}; | ||||
|                  | ||||
|                 # add the other point to our polyline and continue walking | ||||
|                 push @$polyline, grep $_ ne $last_point_id, @{$skeleton_lines[$next_line_idx]}; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     # now replace point indexes with coordinates | ||||
|     @$polyline = map $vertices->[$_], @$polyline; | ||||
|      | ||||
|     # cleanup | ||||
|     Slic3r::Geometry::polyline_remove_short_segments($polyline, $width / 2); | ||||
|     $polyline = Slic3r::Geometry::douglas_peucker($polyline, $width / 7); | ||||
|     Slic3r::Geometry::polyline_remove_parallel_continuous_edges($polyline); | ||||
|      | ||||
|     if (Slic3r::Geometry::same_point($polyline->[0], $polyline->[-1])) { | ||||
|         return undef if @$polyline == 2; | ||||
|         return Slic3r::Polygon->new(@$polyline[0..$#$polyline-1]); | ||||
|     } else { | ||||
|         return Slic3r::Polyline->new($polyline); | ||||
|     my @result = (); | ||||
|     foreach my $polyline (@polylines) { | ||||
|         next unless @$polyline >= 2; | ||||
|          | ||||
|         # now replace point indexes with coordinates | ||||
|         @$polyline = map $vertices->[$_], @$polyline; | ||||
|          | ||||
|         # cleanup | ||||
|         $polyline = Slic3r::Geometry::douglas_peucker($polyline, $width / 7); | ||||
|          | ||||
|         if (Slic3r::Geometry::same_point($polyline->[0], $polyline->[-1])) { | ||||
|             next if @$polyline == 2; | ||||
|             push @result, Slic3r::Polygon->new(@$polyline[0..$#$polyline-1]); | ||||
|         } else { | ||||
|             push @result, Slic3r::Polyline->new($polyline); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return @result; | ||||
| } | ||||
| 
 | ||||
| 1; | ||||
|  |  | |||
|  | @ -174,7 +174,6 @@ sub make_surfaces { | |||
|             @$diff = grep $_->area > ($area_threshold), @$diff; | ||||
|              | ||||
|             push @{$self->thin_walls}, | ||||
|                 grep $_, | ||||
|                 map $_->medial_axis(scale $self->perimeters_flow->width), | ||||
|                 @$diff; | ||||
|              | ||||
|  | @ -260,7 +259,6 @@ sub make_perimeters { | |||
|                 [ map @$_, map $_->offset_ex(+$distance/2), @fill_boundaries ], | ||||
|             ); | ||||
|             push @{ $self->thin_fills }, | ||||
|                 grep $_, | ||||
|                 map $_->medial_axis(scale $self->perimeters_flow->width), | ||||
|                 @$small_gaps if 0; | ||||
|         } | ||||
|  | @ -320,12 +318,17 @@ sub make_perimeters { | |||
|     } | ||||
|      | ||||
|     # add thin walls as perimeters | ||||
|     for (@{ $self->thin_walls }) { | ||||
|         if ($_->isa('Slic3r::Polygon')) { | ||||
|             push @{ $self->perimeters }, Slic3r::ExtrusionLoop->new(polygon => $_, role => EXTR_ROLE_PERIMETER); | ||||
|         } else { | ||||
|             push @{ $self->perimeters }, Slic3r::ExtrusionPath->new(polyline => $_, role => EXTR_ROLE_PERIMETER); | ||||
|     { | ||||
|         my @thin_paths = (); | ||||
|         for (@{ $self->thin_walls }) { | ||||
|             if ($_->isa('Slic3r::Polygon')) { | ||||
|                 push @thin_paths, Slic3r::ExtrusionLoop->new(polygon => $_, role => EXTR_ROLE_PERIMETER); | ||||
|             } else { | ||||
|                 push @thin_paths, Slic3r::ExtrusionPath->new(polyline => $_, role => EXTR_ROLE_PERIMETER); | ||||
|             } | ||||
|         } | ||||
|         my $collection = Slic3r::ExtrusionPath::Collection->new(paths => \@thin_paths); | ||||
|         push @{ $self->perimeters }, $collection->shortest_path; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci