Bugfix: many thin walls were not detected correctly. #313
This commit is contained in:
parent
fbfbfac2b6
commit
85ef7ce665
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user