mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-15 01:55:56 +08:00
Don't merge adjacent bridges so that more correct angles can be detected for each one
This commit is contained in:
parent
c69edf27e9
commit
a145f1b6aa
@ -411,11 +411,30 @@ sub prepare_fill_surfaces {
|
|||||||
sub process_external_surfaces {
|
sub process_external_surfaces {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
# enlarge top and bottom surfaces
|
my $margin = scale 3; # TODO: ensure this is greater than the total thickness of the perimeters
|
||||||
{
|
|
||||||
# get all external surfaces
|
my @bottom = ();
|
||||||
my @top = grep $_->surface_type == S_TYPE_TOP, @{$self->fill_surfaces};
|
foreach my $surface (grep $_->surface_type == S_TYPE_BOTTOM, @{$self->fill_surfaces}) {
|
||||||
my @bottom = grep $_->surface_type == S_TYPE_BOTTOM, @{$self->fill_surfaces};
|
my ($grown) = $surface->expolygon->offset_ex(+$margin);
|
||||||
|
|
||||||
|
# detect bridge direction before merging grown surfaces otherwise adjacent bridges
|
||||||
|
# would get merged into a single one while they need different directions
|
||||||
|
my $angle = $self->id > 0
|
||||||
|
? $self->_detect_bridge_direction($grown)
|
||||||
|
: undef;
|
||||||
|
|
||||||
|
push @bottom, $surface->clone(expolygon => $grown, bridge_angle => $angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
my @top = ();
|
||||||
|
foreach my $surface (grep $_->surface_type == S_TYPE_TOP, @{$self->fill_surfaces}) {
|
||||||
|
# give priority to bottom surfaces
|
||||||
|
my $grown = diff_ex(
|
||||||
|
[ $surface->expolygon->offset(+$margin) ],
|
||||||
|
[ map $_->p, @bottom ],
|
||||||
|
);
|
||||||
|
push @top, map $surface->clone(expolygon => $_), @$grown;
|
||||||
|
}
|
||||||
|
|
||||||
# if we're slicing with no infill, we can't extend external surfaces
|
# if we're slicing with no infill, we can't extend external surfaces
|
||||||
# over non-existent infill
|
# over non-existent infill
|
||||||
@ -423,37 +442,18 @@ sub process_external_surfaces {
|
|||||||
? @{$self->fill_surfaces}
|
? @{$self->fill_surfaces}
|
||||||
: grep $_->surface_type != S_TYPE_INTERNAL, @{$self->fill_surfaces};
|
: grep $_->surface_type != S_TYPE_INTERNAL, @{$self->fill_surfaces};
|
||||||
|
|
||||||
# offset them and intersect the results with the actual fill boundaries
|
# intersect the grown surfaces with the actual fill boundaries
|
||||||
my $margin = scale 3; # TODO: ensure this is greater than the total thickness of the perimeters
|
|
||||||
@top = @{intersection_ex(
|
|
||||||
[ Slic3r::Geometry::Clipper::offset([ map $_->p, @top ], +$margin) ],
|
|
||||||
[ map $_->p, @fill_boundaries ],
|
|
||||||
undef,
|
|
||||||
1, # to ensure adjacent expolygons are unified
|
|
||||||
)};
|
|
||||||
@bottom = @{intersection_ex(
|
|
||||||
[ Slic3r::Geometry::Clipper::offset([ map $_->p, @bottom ], +$margin) ],
|
|
||||||
[ map $_->p, @fill_boundaries ],
|
|
||||||
undef,
|
|
||||||
1, # to ensure adjacent expolygons are unified
|
|
||||||
)};
|
|
||||||
|
|
||||||
# give priority to bottom surfaces
|
|
||||||
@top = @{diff_ex(
|
|
||||||
[ map @$_, @top ],
|
|
||||||
[ map @$_, @bottom ],
|
|
||||||
)};
|
|
||||||
|
|
||||||
# generate new surfaces
|
|
||||||
my @new_surfaces = ();
|
my @new_surfaces = ();
|
||||||
push @new_surfaces, map Slic3r::Surface->new(
|
foreach my $group (Slic3r::Surface->group(@top, @bottom)) {
|
||||||
expolygon => $_,
|
push @new_surfaces,
|
||||||
surface_type => S_TYPE_TOP,
|
map $group->[0]->clone(expolygon => $_),
|
||||||
), @top;
|
@{intersection_ex(
|
||||||
push @new_surfaces, map Slic3r::Surface->new(
|
[ map $_->p, @$group ],
|
||||||
expolygon => $_,
|
[ map $_->p, @fill_boundaries ],
|
||||||
surface_type => S_TYPE_BOTTOM,
|
undef,
|
||||||
), @bottom;
|
1, # to ensure adjacent expolygons are unified
|
||||||
|
)};
|
||||||
|
}
|
||||||
|
|
||||||
# subtract the new top surfaces from the other non-top surfaces and re-add them
|
# subtract the new top surfaces from the other non-top surfaces and re-add them
|
||||||
my @other = grep $_->surface_type != S_TYPE_TOP && $_->surface_type != S_TYPE_BOTTOM, @{$self->fill_surfaces};
|
my @other = grep $_->surface_type != S_TYPE_TOP && $_->surface_type != S_TYPE_BOTTOM, @{$self->fill_surfaces};
|
||||||
@ -466,23 +466,18 @@ sub process_external_surfaces {
|
|||||||
@{$self->fill_surfaces} = @new_surfaces;
|
@{$self->fill_surfaces} = @new_surfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
# detect bridge direction (skip bottom layer)
|
sub _detect_bridge_direction {
|
||||||
$self->_detect_bridges if $self->id > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _detect_bridges {
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
my ($expolygon) = @_;
|
||||||
|
|
||||||
my @bottom = grep $_->surface_type == S_TYPE_BOTTOM, @{$self->fill_surfaces}; # surfaces
|
|
||||||
my @lower = @{$self->layer->object->layers->[ $self->id - 1 ]->slices}; # expolygons
|
my @lower = @{$self->layer->object->layers->[ $self->id - 1 ]->slices}; # expolygons
|
||||||
|
|
||||||
foreach my $surface (@bottom) {
|
|
||||||
# detect what edges lie on lower slices
|
# detect what edges lie on lower slices
|
||||||
my @edges = (); # polylines
|
my @edges = (); # polylines
|
||||||
foreach my $lower (@lower) {
|
foreach my $lower (@lower) {
|
||||||
# turn bridge contour and holes into polylines and then clip them
|
# turn bridge contour and holes into polylines and then clip them
|
||||||
# with each lower slice's contour
|
# with each lower slice's contour
|
||||||
my @clipped = map $_->split_at_first_point->clip_with_polygon($lower->contour), @{$surface->expolygon};
|
my @clipped = map $_->split_at_first_point->clip_with_polygon($lower->contour), @$expolygon;
|
||||||
if (@clipped == 2) {
|
if (@clipped == 2) {
|
||||||
# If the split_at_first_point() call above happens to split the polygon inside the clipping area
|
# If the split_at_first_point() call above happens to split the polygon inside the clipping area
|
||||||
# we would get two consecutive polylines instead of a single one, so we use this ugly hack to
|
# we would get two consecutive polylines instead of a single one, so we use this ugly hack to
|
||||||
@ -499,14 +494,14 @@ sub _detect_bridges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Slic3r::debugf "Found bridge on layer %d with %d support(s)\n", $self->id, scalar(@edges);
|
Slic3r::debugf "Found bridge on layer %d with %d support(s)\n", $self->id, scalar(@edges);
|
||||||
next if !@edges;
|
return undef if !@edges;
|
||||||
|
|
||||||
my $bridge_angle = undef;
|
my $bridge_angle = undef;
|
||||||
|
|
||||||
if (0) {
|
if (0) {
|
||||||
require "Slic3r/SVG.pm";
|
require "Slic3r/SVG.pm";
|
||||||
Slic3r::SVG::output("bridge_$surface.svg",
|
Slic3r::SVG::output("bridge_$expolygon.svg",
|
||||||
expolygons => [ $surface->expolygon ],
|
expolygons => [ $expolygon ],
|
||||||
red_expolygons => [ @lower ],
|
red_expolygons => [ @lower ],
|
||||||
polylines => [ @edges ],
|
polylines => [ @edges ],
|
||||||
);
|
);
|
||||||
@ -529,11 +524,11 @@ sub _detect_bridges {
|
|||||||
}
|
}
|
||||||
} elsif (@edges) {
|
} elsif (@edges) {
|
||||||
# inset the bridge expolygon; we'll use this one to clip our test lines
|
# inset the bridge expolygon; we'll use this one to clip our test lines
|
||||||
my $inset = [ $surface->expolygon->offset_ex($self->infill_flow->scaled_width) ];
|
my $inset = [ $expolygon->offset_ex($self->infill_flow->scaled_width) ];
|
||||||
|
|
||||||
# detect anchors as intersection between our bridge expolygon and the lower slices
|
# detect anchors as intersection between our bridge expolygon and the lower slices
|
||||||
my $anchors = intersection_ex(
|
my $anchors = intersection_ex(
|
||||||
[ $surface->p ],
|
[ @$expolygon ],
|
||||||
[ map @$_, @lower ],
|
[ map @$_, @lower ],
|
||||||
undef,
|
undef,
|
||||||
1, # safety offset required to avoid Clipper from detecting empty intersection while Boost actually found some @edges
|
1, # safety offset required to avoid Clipper from detecting empty intersection while Boost actually found some @edges
|
||||||
@ -580,8 +575,7 @@ sub _detect_bridges {
|
|||||||
Slic3r::debugf " Optimal infill angle of bridge on layer %d is %d degrees\n",
|
Slic3r::debugf " Optimal infill angle of bridge on layer %d is %d degrees\n",
|
||||||
$self->id, $bridge_angle if defined $bridge_angle;
|
$self->id, $bridge_angle if defined $bridge_angle;
|
||||||
|
|
||||||
$surface->bridge_angle($bridge_angle);
|
return $bridge_angle;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user