Bugfix: some islands having ho holes and contained in holes themselves were ignored
This commit is contained in:
parent
47df3f8f2d
commit
a86bc260e7
1
MANIFEST
1
MANIFEST
@ -49,3 +49,4 @@ t/collinear.t
|
|||||||
t/geometry.t
|
t/geometry.t
|
||||||
t/polyclip.t
|
t/polyclip.t
|
||||||
t/stl.t
|
t/stl.t
|
||||||
|
utils/post-processing/z-every-line.pl
|
||||||
|
@ -140,4 +140,11 @@ sub rotate {
|
|||||||
$_->rotate(@_) for @$self;
|
$_->rotate(@_) for @$self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub area {
|
||||||
|
my $self = shift;
|
||||||
|
my $area = $self->contour->area;
|
||||||
|
$area -= $_->area for $self->holes;
|
||||||
|
return $area;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -5,7 +5,7 @@ use warnings;
|
|||||||
require Exporter;
|
require Exporter;
|
||||||
our @ISA = qw(Exporter);
|
our @ISA = qw(Exporter);
|
||||||
our @EXPORT_OK = qw(explode_expolygon explode_expolygons safety_offset offset
|
our @EXPORT_OK = qw(explode_expolygon explode_expolygons safety_offset offset
|
||||||
diff_ex diff union_ex intersection_ex PFT_EVENODD JT_MITER JT_ROUND
|
diff_ex diff union_ex intersection_ex xor_ex PFT_EVENODD JT_MITER JT_ROUND
|
||||||
is_counter_clockwise);
|
is_counter_clockwise);
|
||||||
|
|
||||||
use Math::Clipper 1.02 ':all';
|
use Math::Clipper 1.02 ':all';
|
||||||
@ -66,4 +66,16 @@ sub intersection_ex {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub xor_ex {
|
||||||
|
my ($subject, $clip, $jointype) = @_;
|
||||||
|
$jointype = PFT_NONZERO unless defined $jointype;
|
||||||
|
$clipper->clear;
|
||||||
|
$clipper->add_subject_polygons($subject);
|
||||||
|
$clipper->add_clip_polygons($clip);
|
||||||
|
return [
|
||||||
|
map Slic3r::ExPolygon->new($_),
|
||||||
|
@{ $clipper->ex_execute(CT_XOR, $jointype, $jointype) },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -3,7 +3,7 @@ use Moo;
|
|||||||
|
|
||||||
use Math::Clipper ':all';
|
use Math::Clipper ':all';
|
||||||
use Slic3r::Geometry qw(scale collinear X Y A B PI rad2deg_dir bounding_box_center);
|
use Slic3r::Geometry qw(scale collinear X Y A B PI rad2deg_dir bounding_box_center);
|
||||||
use Slic3r::Geometry::Clipper qw(union_ex diff_ex intersection_ex is_counter_clockwise);
|
use Slic3r::Geometry::Clipper qw(union_ex diff_ex intersection_ex xor_ex is_counter_clockwise);
|
||||||
use XXX;
|
use XXX;
|
||||||
|
|
||||||
# a sequential number of layer, starting at 0
|
# a sequential number of layer, starting at 0
|
||||||
@ -112,20 +112,35 @@ sub make_surfaces {
|
|||||||
# we need to ignore such holes, but Clipper will convert them to contours.
|
# we need to ignore such holes, but Clipper will convert them to contours.
|
||||||
# so we identify them and remove them manually.
|
# so we identify them and remove them manually.
|
||||||
|
|
||||||
|
my $area_sum = sub {
|
||||||
|
my $area = 0;
|
||||||
|
$area += $_->area for @_;
|
||||||
|
return $area;
|
||||||
|
};
|
||||||
|
|
||||||
# get expolygons without holes (candidate for reverse holes detection)
|
# get expolygons without holes (candidate for reverse holes detection)
|
||||||
my @expolygons_without_holes = grep { @$_ == 1 } @$expolygons;
|
my @expolygons_without_holes = grep { @$_ == 1 } @$expolygons;
|
||||||
|
|
||||||
# remove all holes from such expolygons
|
# prepare holes as contours to allow for safe xor'ing
|
||||||
my $diff = diff_ex(
|
my @reversed_holes = map [ reverse @$_ ], grep !is_counter_clockwise($_), @$loops;
|
||||||
[ map @$_, @expolygons_without_holes ],
|
|
||||||
[ map [ reverse @$_ ], grep !is_counter_clockwise($_), @$loops ],
|
|
||||||
);
|
|
||||||
|
|
||||||
# merge resulting holes (true holes) and other expolygons
|
# compare each expolygon without holes with each original hole; if their XOR
|
||||||
$expolygons = [
|
# is empty then they're the same and we can remove the hole from our layer
|
||||||
(grep { @$_ > 1 } @$expolygons),
|
my %bogus_holes = ();
|
||||||
@$diff,
|
foreach my $contour (map $_->contour, @expolygons_without_holes) {
|
||||||
];
|
foreach my $hole (grep !exists $bogus_holes{$_}, @reversed_holes) {
|
||||||
|
my $xor = xor_ex([$contour], [$hole]);
|
||||||
|
if (!@$xor || $area_sum->(@$xor) < scale 1) { # TODO: define this threshold better
|
||||||
|
$bogus_holes{$hole} = $hole;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# remove identified holes
|
||||||
|
$expolygons = diff_ex(
|
||||||
|
[ map @$_, @$expolygons ],
|
||||||
|
[ values %bogus_holes ],
|
||||||
|
) if %bogus_holes;
|
||||||
|
|
||||||
Slic3r::debugf " %d surface(s) having %d holes detected from %d polylines\n",
|
Slic3r::debugf " %d surface(s) having %d holes detected from %d polylines\n",
|
||||||
scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@$loops);
|
scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@$loops);
|
||||||
|
Loading…
Reference in New Issue
Block a user