mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 09:17:52 -06:00
Several changes to support material, including a fix to prevent vertical overlapping and horizontal fusion of support and object
This commit is contained in:
parent
c08d4cc798
commit
28e9682d0e
2 changed files with 67 additions and 41 deletions
|
@ -773,7 +773,9 @@ sub generate_support_material {
|
||||||
return unless ($self->config->support_material || $self->config->raft_layers > 0)
|
return unless ($self->config->support_material || $self->config->raft_layers > 0)
|
||||||
&& $self->layer_count >= 2;
|
&& $self->layer_count >= 2;
|
||||||
|
|
||||||
Slic3r::Print::SupportMaterial->new->generate($self);
|
Slic3r::Print::SupportMaterial
|
||||||
|
->new(config => $self->config, flow => $self->print->support_material_flow)
|
||||||
|
->generate($self);
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -7,17 +7,16 @@ use Slic3r::Geometry qw(scale PI rad2deg deg2rad);
|
||||||
use Slic3r::Geometry::Clipper qw(offset diff union_ex intersection offset_ex offset2);
|
use Slic3r::Geometry::Clipper qw(offset diff union_ex intersection offset_ex offset2);
|
||||||
use Slic3r::Surface ':types';
|
use Slic3r::Surface ':types';
|
||||||
|
|
||||||
has 'config' => (is => 'rw', default => sub { Slic3r::Config->new_from_defaults });
|
has 'config' => (is => 'rw', required => 1);
|
||||||
has 'flow' => (is => 'rw');
|
has 'flow' => (is => 'rw', required => 1);
|
||||||
|
|
||||||
|
use constant DEBUG_CONTACT_ONLY => 0;
|
||||||
|
|
||||||
sub generate {
|
sub generate {
|
||||||
my ($self, $object) = @_;
|
my ($self, $object) = @_;
|
||||||
|
|
||||||
$self->flow($object->print->support_material_flow);
|
|
||||||
$self->config($object->config);
|
|
||||||
|
|
||||||
# Determine the top surfaces of the support, defined as:
|
# Determine the top surfaces of the support, defined as:
|
||||||
# contact = overhangs - margin
|
# contact = overhangs - clearance + margin
|
||||||
# This method is responsible for identifying what contact surfaces
|
# This method is responsible for identifying what contact surfaces
|
||||||
# should the support material expose to the object in order to guarantee
|
# should the support material expose to the object in order to guarantee
|
||||||
# that it will be effective, regardless of how it's built below.
|
# that it will be effective, regardless of how it's built below.
|
||||||
|
@ -64,8 +63,7 @@ sub contact_area {
|
||||||
my ($self, $object) = @_;
|
my ($self, $object) = @_;
|
||||||
|
|
||||||
# how much we extend support around the actual contact area
|
# how much we extend support around the actual contact area
|
||||||
#my $margin = $flow->scaled_width / 2;
|
my $margin = $self->flow->scaled_width * 3;
|
||||||
my $margin = scale 3;
|
|
||||||
|
|
||||||
# increment used to reach $margin in steps to avoid trespassing thin objects
|
# increment used to reach $margin in steps to avoid trespassing thin objects
|
||||||
my $margin_step = $margin/3;
|
my $margin_step = $margin/3;
|
||||||
|
@ -123,6 +121,8 @@ sub contact_area {
|
||||||
# outside the lower slice boundary, thus no overhang
|
# outside the lower slice boundary, thus no overhang
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# TODO: this is the place to remove bridged areas
|
||||||
|
|
||||||
next if !@$diff;
|
next if !@$diff;
|
||||||
push @overhang, @{union_ex($diff)}; # NOTE: this is not the full overhang as it misses the outermost half of the perimeter width!
|
push @overhang, @{union_ex($diff)}; # NOTE: this is not the full overhang as it misses the outermost half of the perimeter width!
|
||||||
|
|
||||||
|
@ -179,32 +179,30 @@ sub object_top {
|
||||||
# find object top surfaces
|
# find object top surfaces
|
||||||
# we'll use them to clip our support and detect where does it stick
|
# we'll use them to clip our support and detect where does it stick
|
||||||
my %top = (); # print_z => [ expolygons ]
|
my %top = (); # print_z => [ expolygons ]
|
||||||
{
|
my $projection = [];
|
||||||
my $projection = [];
|
foreach my $layer (reverse @{$object->layers}) {
|
||||||
foreach my $layer (reverse @{$object->layers}) {
|
if (my @top = map @{$_->slices->filter_by_type(S_TYPE_TOP)}, @{$layer->regions}) {
|
||||||
if (my @top = map @{$_->slices->filter_by_type(S_TYPE_TOP)}, @{$layer->regions}) {
|
# compute projection of the contact areas above this top layer
|
||||||
# compute projection of the contact areas above this top layer
|
# first add all the 'new' contact areas to the current projection
|
||||||
# first add all the 'new' contact areas to the current projection
|
# ('new' means all the areas that are lower than the last top layer
|
||||||
# ('new' means all the areas that are lower than the last top layer
|
# we considered)
|
||||||
# we considered)
|
my $min_top = min(keys %top) // max(keys %$contact);
|
||||||
my $min_top = min(keys %top) // max(keys %$contact);
|
# use <= instead of just < because otherwise we'd ignore any contact regions
|
||||||
# use <= instead of just < because otherwise we'd ignore any contact regions
|
# having the same Z of top layers
|
||||||
# having the same Z of top layers
|
push @$projection, map @{$contact->{$_}}, grep { $_ > $layer->print_z && $_ <= $min_top } keys %$contact;
|
||||||
push @$projection, map @{$contact->{$_}}, grep { $_ > $layer->print_z && $_ <= $min_top } keys %$contact;
|
|
||||||
|
# now find whether any projection falls onto this top surface
|
||||||
# now find whether any projection falls onto this top surface
|
my $touching = intersection($projection, [ map $_->p, @top ]);
|
||||||
my $touching = intersection($projection, [ map $_->p, @top ]);
|
if (@$touching) {
|
||||||
if (@$touching) {
|
# grow top surfaces so that interface and support generation are generated
|
||||||
# grow top surfaces so that interface and support generation are generated
|
# with some spacing from object - it looks we don't need the actual
|
||||||
# with some spacing from object - it looks we don't need the actual
|
# top shapes so this can be done here
|
||||||
# top shapes so this can be done here
|
$top{ $layer->print_z } = offset($touching, $self->flow->scaled_spacing);
|
||||||
$top{ $layer->print_z } = offset($touching, $self->flow->scaled_spacing);
|
|
||||||
}
|
|
||||||
|
|
||||||
# remove the areas that touched from the projection that will continue on
|
|
||||||
# next, lower, top surfaces
|
|
||||||
$projection = diff($projection, $touching);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# remove the areas that touched from the projection that will continue on
|
||||||
|
# next, lower, top surfaces
|
||||||
|
$projection = diff($projection, $touching);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,19 +264,23 @@ sub generate_interface_layers {
|
||||||
# count contact layer as interface layer
|
# count contact layer as interface layer
|
||||||
for (my $i = $layer_id-1; $i >= 0 && $i > $layer_id-$interface_layers; $i--) {
|
for (my $i = $layer_id-1; $i >= 0 && $i > $layer_id-$interface_layers; $i--) {
|
||||||
$z = $support_z->[$i];
|
$z = $support_z->[$i];
|
||||||
|
my @overlapping_layers = $self->overlapping_layers($i, $support_z);
|
||||||
|
my @overlapping_z = map $support_z->[$_], @overlapping_layers;
|
||||||
|
|
||||||
# Compute interface area on this layer as diff of upper contact area
|
# Compute interface area on this layer as diff of upper contact area
|
||||||
# (or upper interface area) and layer slices.
|
# (or upper interface area) and layer slices.
|
||||||
# This diff is responsible of the contact between support material and
|
# This diff is responsible of the contact between support material and
|
||||||
# the top surfaces of the object. We should probably offset the top
|
# the top surfaces of the object. We should probably offset the top
|
||||||
# surfaces before performing the diff, but this needs investigation.
|
# surfaces vertically before performing the diff, but this needs
|
||||||
|
# investigation.
|
||||||
$this = $interface{$i} = diff(
|
$this = $interface{$i} = diff(
|
||||||
[
|
[
|
||||||
@$this, # clipped projection of the current contact regions
|
@$this, # clipped projection of the current contact regions
|
||||||
@{ $interface{$i} || [] }, # interface regions already applied to this layer
|
@{ $interface{$i} || [] }, # interface regions already applied to this layer
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@{ $top->{$z} || [] }, # top slices on this layer
|
(map @$_, map $top->{$_}, grep exists $top->{$_}, @overlapping_z), # top slices on this layer
|
||||||
@{ $contact->{$z} || [] }, # contact regions on this layer
|
(map @$_, map $contact->{$_}, grep exists $contact->{$_}, @overlapping_z), # contact regions on this layer
|
||||||
],
|
],
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
@ -296,15 +298,18 @@ sub generate_base_layers {
|
||||||
{
|
{
|
||||||
for my $i (reverse 0 .. $#$support_z-1) {
|
for my $i (reverse 0 .. $#$support_z-1) {
|
||||||
my $z = $support_z->[$i];
|
my $z = $support_z->[$i];
|
||||||
|
my @overlapping_layers = $self->overlapping_layers($i, $support_z);
|
||||||
|
my @overlapping_z = map $support_z->[$_], @overlapping_layers;
|
||||||
|
|
||||||
$base->{$i} = diff(
|
$base->{$i} = diff(
|
||||||
[
|
[
|
||||||
@{ $base->{$i+1} || [] }, # support regions on upper layer
|
@{ $base->{$i+1} || [] }, # support regions on upper layer
|
||||||
@{ $interface->{$i+1} || [] }, # interface regions on upper layer
|
@{ $interface->{$i+1} || [] }, # interface regions on upper layer
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@{ $top->{$z} || [] }, # top slices on this layer
|
(map @$_, map $top->{$_}, grep exists $top->{$_}, @overlapping_z), # top slices on this layer
|
||||||
@{ $interface->{$i} || [] }, # interface regions on this layer
|
(map @$_, map $interface->{$_}, grep exists $interface->{$_}, @overlapping_layers), # interface regions on this layer
|
||||||
@{ $contact->{$z} || [] }, # contact regions on this layer
|
(map @$_, map $contact->{$_}, grep exists $contact->{$_}, @overlapping_z), # contact regions on this layer
|
||||||
],
|
],
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
@ -356,6 +361,11 @@ sub generate_toolpaths {
|
||||||
my $interface = $interface->{$layer_id} || [];
|
my $interface = $interface->{$layer_id} || [];
|
||||||
my $base = $base->{$layer_id} || [];
|
my $base = $base->{$layer_id} || [];
|
||||||
|
|
||||||
|
if (DEBUG_CONTACT_ONLY) {
|
||||||
|
$interface = [];
|
||||||
|
$base = [];
|
||||||
|
}
|
||||||
|
|
||||||
if (0) {
|
if (0) {
|
||||||
require "Slic3r/SVG.pm";
|
require "Slic3r/SVG.pm";
|
||||||
Slic3r::SVG::output("layer_" . $z . ".svg",
|
Slic3r::SVG::output("layer_" . $z . ".svg",
|
||||||
|
@ -422,7 +432,7 @@ sub generate_toolpaths {
|
||||||
offset([ @$interface, @$contact_infill ], scale 3),
|
offset([ @$interface, @$contact_infill ], scale 3),
|
||||||
[ @$interface, @$base, @$contact_infill ],
|
[ @$interface, @$base, @$contact_infill ],
|
||||||
1,
|
1,
|
||||||
);
|
) if 0; # this causes bad overlapping with other layers as it doesn't take Z overlap into account
|
||||||
$base = diff(
|
$base = diff(
|
||||||
$base,
|
$base,
|
||||||
$interface,
|
$interface,
|
||||||
|
@ -524,4 +534,18 @@ sub generate_toolpaths {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# this method returns the indices of the layers overlapping with the given one
|
||||||
|
sub overlapping_layers {
|
||||||
|
my ($self, $i, $support_z) = @_;
|
||||||
|
|
||||||
|
my $zmax = $support_z->[$i];
|
||||||
|
my $zmin = ($i == 0) ? 0 : $support_z->[$i-1];
|
||||||
|
|
||||||
|
return grep {
|
||||||
|
my $zmax2 = $support_z->[$_];
|
||||||
|
my $zmin2 = ($_ == 0) ? 0 : $support_z->[$_-1];
|
||||||
|
$zmax > $zmin2 && $zmin < $zmax2;
|
||||||
|
} 0..$#$support_z;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue