mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-24 07:03:59 -06:00
Large refactoring. Cleaner logic, smaller memory footprint.
This commit is contained in:
parent
13ef24b5eb
commit
8598b66b0a
6 changed files with 178 additions and 247 deletions
|
@ -29,20 +29,6 @@ has 'surfaces' => (
|
|||
default => sub { [] },
|
||||
);
|
||||
|
||||
# collection of surfaces representing bridges
|
||||
has 'bridges' => (
|
||||
is => 'rw',
|
||||
#isa => 'ArrayRef[Slic3r::Surface]',
|
||||
default => sub { [] },
|
||||
);
|
||||
|
||||
# collection of surfaces to make perimeters for
|
||||
has 'perimeter_surfaces' => (
|
||||
is => 'rw',
|
||||
#isa => 'ArrayRef[Slic3r::Surface]',
|
||||
default => sub { [] },
|
||||
);
|
||||
|
||||
# ordered collection of extrusion paths to build all perimeters
|
||||
has 'perimeters' => (
|
||||
is => 'rw',
|
||||
|
@ -58,10 +44,10 @@ has 'skirts' => (
|
|||
);
|
||||
|
||||
# collection of surfaces generated by offsetting the innermost perimeter(s)
|
||||
# they represent boundaries of areas to fill (grouped by original objects)
|
||||
has 'fill_surfaces' => (
|
||||
# they represent boundaries of areas to fill
|
||||
has 'fill_boundaries' => (
|
||||
is => 'rw',
|
||||
#isa => 'ArrayRef[ArrayRef[Slic3r::Surface]]',
|
||||
#isa => 'ArrayRef[Slic3r::Surface]',
|
||||
default => sub { [] },
|
||||
);
|
||||
|
||||
|
@ -352,6 +338,8 @@ sub remove_small_perimeters {
|
|||
sub process_bridges {
|
||||
my $self = shift;
|
||||
|
||||
my @bridges = ();
|
||||
|
||||
# a bottom surface on a layer > 0 is either a bridge or a overhang
|
||||
# or a combination of both; any top surface is a candidate for
|
||||
# reverse bridge processing
|
||||
|
@ -426,8 +414,8 @@ sub process_bridges {
|
|||
|
||||
# now, extend our bridge by taking a portion of supporting surfaces
|
||||
{
|
||||
# offset the bridge by the specified amount of mm
|
||||
my $bridge_overlap = 2 * $Slic3r::perimeters * $Slic3r::flow_width / $Slic3r::resolution;
|
||||
# offset the bridge by the specified amount of mm (minimum 3)
|
||||
my $bridge_overlap = 3 / $Slic3r::resolution;
|
||||
my ($bridge_offset) = $expolygon->contour->offset($bridge_overlap, $Slic3r::resolution * 100, JT_MITER, 2);
|
||||
|
||||
# calculate the new bridge
|
||||
|
@ -436,7 +424,7 @@ sub process_bridges {
|
|||
[ $bridge_offset ],
|
||||
);
|
||||
|
||||
push @{$self->bridges}, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
push @bridges, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
surface_type => $surface->surface_type,
|
||||
bridge_angle => $bridge_angle,
|
||||
), @$intersection;
|
||||
|
@ -446,86 +434,52 @@ sub process_bridges {
|
|||
# now we need to merge bridges to avoid overlapping
|
||||
{
|
||||
# build a list of unique bridge types
|
||||
my @surface_groups = Slic3r::Surface->group(@{$self->bridges});
|
||||
my @surface_groups = Slic3r::Surface->group(@bridges);
|
||||
|
||||
# merge bridges of the same type, removing any of the bridges already merged;
|
||||
# the order of @surface_groups determines the priority between bridges having
|
||||
# different surface_type or bridge_angle
|
||||
@{$self->bridges} = ();
|
||||
@bridges = ();
|
||||
foreach my $surfaces (@surface_groups) {
|
||||
my $union = union_ex([ map $_->p, @$surfaces ]);
|
||||
my $diff = diff_ex(
|
||||
[ map @$_, @$union ],
|
||||
[ map $_->p, @{$self->bridges} ],
|
||||
[ map $_->p, @bridges ],
|
||||
);
|
||||
|
||||
push @{$self->bridges}, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
push @bridges, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
surface_type => $surfaces->[0]->surface_type,
|
||||
bridge_angle => $surfaces->[0]->bridge_angle,
|
||||
), @$union;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# generates a set of surfaces that will be used to make perimeters
|
||||
# thus, we need to merge internal surfaces and bridges
|
||||
sub detect_perimeter_surfaces {
|
||||
my $self = shift;
|
||||
|
||||
# little optimization: skip the Clipper UNION if we have no bridges
|
||||
if (!@{$self->bridges}) {
|
||||
push @{$self->perimeter_surfaces}, @{$self->surfaces};
|
||||
} else {
|
||||
my $union = union_ex([
|
||||
(map $_->p, grep $_->surface_type =~ /internal/, @{$self->surfaces}),
|
||||
(map $_->p, @{$self->bridges}),
|
||||
]);
|
||||
# apply bridges to layer
|
||||
{
|
||||
my @surfaces = @{$self->surfaces};
|
||||
@{$self->surfaces} = ();
|
||||
|
||||
# schedule perimeters for internal surfaces merged with bridges
|
||||
push @{$self->perimeter_surfaces},
|
||||
map Slic3r::Surface->cast_from_expolygon($_, surface_type => 'internal'),
|
||||
@$union;
|
||||
|
||||
# schedule perimeters for the remaining surfaces
|
||||
foreach my $type (qw(top bottom)) {
|
||||
my $diff = diff_ex(
|
||||
[ map $_->p, grep $_->surface_type eq $type, @{$self->surfaces} ],
|
||||
[ map @$_, @$union ],
|
||||
);
|
||||
push @{$self->perimeter_surfaces},
|
||||
map Slic3r::Surface->cast_from_expolygon($_, surface_type => $type),
|
||||
@$diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# splits fill_surfaces in internal and bridge surfaces
|
||||
sub split_bridges_fills {
|
||||
my $self = shift;
|
||||
|
||||
foreach my $surfaces (@{$self->fill_surfaces}) {
|
||||
my @surfaces = @$surfaces;
|
||||
@$surfaces = ();
|
||||
|
||||
# intersect fill_surfaces with bridges to get actual bridges
|
||||
foreach my $bridge (@{$self->bridges}) {
|
||||
my $intersection = intersection_ex(
|
||||
# intersect layer surfaces with bridges to get actual bridges
|
||||
foreach my $bridge (@bridges) {
|
||||
my $actual_bridge = intersection_ex(
|
||||
[ map $_->p, @surfaces ],
|
||||
[ $bridge->p ],
|
||||
);
|
||||
|
||||
push @$surfaces, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
push @{$self->surfaces}, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
surface_type => $bridge->surface_type,
|
||||
bridge_angle => $bridge->bridge_angle,
|
||||
), @$intersection;
|
||||
), @$actual_bridge;
|
||||
}
|
||||
|
||||
# difference between fill_surfaces and bridges are the other surfaces
|
||||
foreach my $type (qw(top bottom internal internal-solid)) {
|
||||
my @my_surfaces = grep $_->surface_type eq $type, @surfaces;
|
||||
my $difference = diff_ex([ map $_->p, @my_surfaces ], [ map $_->p, @{$self->bridges} ]);
|
||||
push @$surfaces, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
surface_type => $type), @$difference;
|
||||
# difference between layer surfaces and bridges are the other surfaces
|
||||
foreach my $group (Slic3r::Surface->group(@surfaces)) {
|
||||
my $difference = diff_ex(
|
||||
[ map $_->p, @$group ],
|
||||
[ map $_->p, @bridges ],
|
||||
);
|
||||
push @{$self->surfaces}, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
surface_type => $group->[0]->surface_type), @$difference;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue