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;
# 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;

View File

@ -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;
}
}