Bugfix: many thin walls were not detected correctly. #313

This commit is contained in:
Alessandro Ranellucci 2012-06-06 21:27:39 +02:00
parent fbfbfac2b6
commit 85ef7ce665
2 changed files with 67 additions and 45 deletions

View File

@ -215,54 +215,73 @@ sub medial_axis {
} }
return undef if !@skeleton_lines; return undef if !@skeleton_lines;
# now build a single polyline # now walk along the medial axis and build continuos polylines or polygons
my $polyline = []; my @polylines = ();
{ {
my %pointmap = (); # build a map of line endpoints
foreach my $line (@skeleton_lines) { my %pointmap = (); # point_idx => [line_idx, line_idx ...]
foreach my $point_id (@$line) { for my $line_idx (0 .. $#skeleton_lines) {
$pointmap{$point_id} ||= []; for my $point_idx (@{$skeleton_lines[$line_idx]}) {
push @{$pointmap{$point_id}}, $line; $pointmap{$point_idx} ||= [];
push @{$pointmap{$point_idx}}, $line_idx;
} }
} }
# start from a point having only one line # build the list of available lines
foreach my $point_id (keys %pointmap) { my %spare_lines = map {$_ => 1} (0 .. $#skeleton_lines);
if (@{$pointmap{$point_id}} == 1) {
push @$polyline, grep $_ ne $point_id, map @$_, shift @{$pointmap{$point_id}};
last;
}
}
# if no such point is found, pick a random one CYCLE: while (%spare_lines) {
push @$polyline, shift @{ +(values %pointmap)[0][0] } if !@$polyline; push @polylines, [];
my $polyline = $polylines[-1];
# 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] };
my %visited_lines = ();
while (1) { while (1) {
my $last_point_id = $polyline->[-1]; my $last_point_id = $polyline->[-1];
my $lines_starting_here = $pointmap{$last_point_id};
shift @{ $pointmap{$last_point_id} } # remove all the visited lines from the array
while @{ $pointmap{$last_point_id} } && $visited_lines{$pointmap{$last_point_id}[0]}; shift @$lines_starting_here
my $next_line = shift @{ $pointmap{$last_point_id} } or last; while @$lines_starting_here && !$spare_lines{$lines_starting_here->[0]};
$visited_lines{$next_line} = 1;
push @$polyline, grep $_ ne $last_point_id, @$next_line; # 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]};
} }
} }
}
my @result = ();
foreach my $polyline (@polylines) {
next unless @$polyline >= 2;
# now replace point indexes with coordinates # now replace point indexes with coordinates
@$polyline = map $vertices->[$_], @$polyline; @$polyline = map $vertices->[$_], @$polyline;
# cleanup # cleanup
Slic3r::Geometry::polyline_remove_short_segments($polyline, $width / 2);
$polyline = Slic3r::Geometry::douglas_peucker($polyline, $width / 7); $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])) { if (Slic3r::Geometry::same_point($polyline->[0], $polyline->[-1])) {
return undef if @$polyline == 2; next if @$polyline == 2;
return Slic3r::Polygon->new(@$polyline[0..$#$polyline-1]); push @result, Slic3r::Polygon->new(@$polyline[0..$#$polyline-1]);
} else { } else {
return Slic3r::Polyline->new($polyline); push @result, Slic3r::Polyline->new($polyline);
} }
}
return @result;
} }
1; 1;

View File

@ -174,7 +174,6 @@ sub make_surfaces {
@$diff = grep $_->area > ($area_threshold), @$diff; @$diff = grep $_->area > ($area_threshold), @$diff;
push @{$self->thin_walls}, push @{$self->thin_walls},
grep $_,
map $_->medial_axis(scale $self->perimeters_flow->width), map $_->medial_axis(scale $self->perimeters_flow->width),
@$diff; @$diff;
@ -260,7 +259,6 @@ sub make_perimeters {
[ map @$_, map $_->offset_ex(+$distance/2), @fill_boundaries ], [ map @$_, map $_->offset_ex(+$distance/2), @fill_boundaries ],
); );
push @{ $self->thin_fills }, push @{ $self->thin_fills },
grep $_,
map $_->medial_axis(scale $self->perimeters_flow->width), map $_->medial_axis(scale $self->perimeters_flow->width),
@$small_gaps if 0; @$small_gaps if 0;
} }
@ -320,13 +318,18 @@ sub make_perimeters {
} }
# add thin walls as perimeters # add thin walls as perimeters
{
my @thin_paths = ();
for (@{ $self->thin_walls }) { for (@{ $self->thin_walls }) {
if ($_->isa('Slic3r::Polygon')) { if ($_->isa('Slic3r::Polygon')) {
push @{ $self->perimeters }, Slic3r::ExtrusionLoop->new(polygon => $_, role => EXTR_ROLE_PERIMETER); push @thin_paths, Slic3r::ExtrusionLoop->new(polygon => $_, role => EXTR_ROLE_PERIMETER);
} else { } else {
push @{ $self->perimeters }, Slic3r::ExtrusionPath->new(polyline => $_, role => EXTR_ROLE_PERIMETER); 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;
}
} }
sub add_perimeter { sub add_perimeter {