mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-25 23:54:00 -06:00
Fix handling of dirty models with overlapping facets, where some holes became filled because of wrong slice nesting
This commit is contained in:
parent
da1b6117df
commit
097912755b
1 changed files with 28 additions and 14 deletions
|
@ -92,6 +92,16 @@ sub make_surfaces {
|
||||||
return if !@$loops;
|
return if !@$loops;
|
||||||
$self->slices([ _merge_loops($loops) ]);
|
$self->slices([ _merge_loops($loops) ]);
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
require "Slic3r/SVG.pm";
|
||||||
|
Slic3r::SVG::output("surfaces.svg",
|
||||||
|
#polylines => $loops,
|
||||||
|
red_polylines => [ grep $_->is_counter_clockwise, @$loops ],
|
||||||
|
green_polylines => [ grep !$_->is_counter_clockwise, @$loops ],
|
||||||
|
expolygons => [ map $_->expolygon, @{$self->slices} ],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
# detect thin walls by offsetting slices by half extrusion inwards
|
# detect thin walls by offsetting slices by half extrusion inwards
|
||||||
if ($Slic3r::Config->thin_walls) {
|
if ($Slic3r::Config->thin_walls) {
|
||||||
$self->thin_walls([]);
|
$self->thin_walls([]);
|
||||||
|
@ -111,14 +121,6 @@ sub make_surfaces {
|
||||||
Slic3r::debugf " %d thin walls detected\n", scalar(@{$self->thin_walls});
|
Slic3r::debugf " %d thin walls detected\n", scalar(@{$self->thin_walls});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0) {
|
|
||||||
require "Slic3r/SVG.pm";
|
|
||||||
Slic3r::SVG::output("surfaces.svg",
|
|
||||||
polygons => [ map $_->contour, @{$self->slices} ],
|
|
||||||
red_polygons => [ map $_->p, map @{$_->holes}, @{$self->slices} ],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _merge_loops {
|
sub _merge_loops {
|
||||||
|
@ -130,14 +132,26 @@ sub _merge_loops {
|
||||||
# would ignore holes inside two concentric contours.
|
# would ignore holes inside two concentric contours.
|
||||||
# So we're ordering loops and collapse consecutive concentric loops having the same
|
# So we're ordering loops and collapse consecutive concentric loops having the same
|
||||||
# winding order.
|
# winding order.
|
||||||
# TODO: find a faster algorithm for this.
|
# TODO: find a faster algorithm for this, maybe with some sort of binary search.
|
||||||
my @loops = sort { $a->encloses_point($b->[0]) ? 0 : 1 } @$loops; # outer first
|
# If we computed a "nesting tree" we could also just remove the consecutive loops
|
||||||
|
# having the same winding order, and remove the extra one(s) so that we could just
|
||||||
|
# supply everything to offset_ex() instead of performing several union/diff calls.
|
||||||
|
|
||||||
|
# we sort by area assuming that the outermost loops have larger area;
|
||||||
|
# the previous sorting method, based on $b->encloses_point($a->[0]), failed to nest
|
||||||
|
# loops correctly in some edge cases when original model had overlapping facets
|
||||||
|
my @abs_area = map abs($_), my @area = map $_->area, @$loops;
|
||||||
|
my @sorted = sort { $abs_area[$b] <=> $abs_area[$a] } 0..$#$loops; # outer first
|
||||||
|
|
||||||
# we don't perform a safety offset now because it might reverse cw loops
|
# we don't perform a safety offset now because it might reverse cw loops
|
||||||
my $slices = [];
|
my $slices = [];
|
||||||
foreach my $loop (@loops) {
|
for my $i (@sorted) {
|
||||||
$slices = $loop->is_counter_clockwise
|
# we rely on the already computed area to determine the winding order
|
||||||
? union([ $loop, @$slices ])
|
# of the loops, since the Orientation() function provided by Clipper
|
||||||
: diff($slices, [$loop]);
|
# would do the same, thus repeating the calculation
|
||||||
|
$slices = ($area[$i] >= 0)
|
||||||
|
? union([ $loops->[$i], @$slices ])
|
||||||
|
: diff($slices, [$loops->[$i]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
# perform a safety offset to merge very close facets (TODO: find test case for this)
|
# perform a safety offset to merge very close facets (TODO: find test case for this)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue