Don't put supports under bridges and potential bridges

This commit is contained in:
Alessandro Ranellucci 2014-04-26 17:19:50 +02:00
parent 129b6651f6
commit ce9cf4d964
7 changed files with 84 additions and 9 deletions

View File

@ -257,6 +257,8 @@ The author of the Silk icon set is Mark James.
--support-material-enforce-layers --support-material-enforce-layers
Enforce support material on the specified number of layers from bottom, Enforce support material on the specified number of layers from bottom,
regardless of --support-material and threshold (0+, default: 0) regardless of --support-material and threshold (0+, default: 0)
--dont-support-bridges
Experimental option for preventing support material from being generated under bridged areas (default: yes)
Retraction options: Retraction options:
--retract-length Length of retraction in mm when pausing extrusion (default: 1) --retract-length Length of retraction in mm when pausing extrusion (default: 1)

View File

@ -493,7 +493,8 @@ sub build {
{ {
title => 'Options for support material and raft', title => 'Options for support material and raft',
options => [qw(support_material_pattern support_material_spacing support_material_angle options => [qw(support_material_pattern support_material_spacing support_material_angle
support_material_interface_layers support_material_interface_spacing)], support_material_interface_layers support_material_interface_spacing
dont_support_bridges)],
}, },
]); ]);

View File

@ -3,7 +3,7 @@ use Moo;
use List::Util qw(first sum max min); use List::Util qw(first sum max min);
use Slic3r::Geometry qw(PI unscale scaled_epsilon rad2deg epsilon); use Slic3r::Geometry qw(PI unscale scaled_epsilon rad2deg epsilon);
use Slic3r::Geometry::Clipper qw(intersection_pl intersection_ex union); use Slic3r::Geometry::Clipper qw(intersection_pl intersection_ex union offset diff_pl union_ex);
has 'expolygon' => (is => 'ro', required => 1); has 'expolygon' => (is => 'ro', required => 1);
has 'lower_slices' => (is => 'rw', required => 1); # ExPolygons or ExPolygonCollection has 'lower_slices' => (is => 'rw', required => 1); # ExPolygons or ExPolygonCollection
@ -213,4 +213,41 @@ sub coverage {
return $coverage; return $coverage;
} }
# this method returns the bridge edges (as polylines) that are not supported
# but would allow the entire bridge area to be bridged with detected angle
# if supported too
sub unsupported_edges {
my ($self, $angle) = @_;
if (!defined $angle) {
return [] if !defined($angle = $self->angle);
}
# get bridge edges (both contour and holes)
my @bridge_edges = map $_->split_at_first_point, @{$self->expolygon};
$_->[0]->translate(1,0) for @bridge_edges; # workaround for Clipper bug, see comments in Slic3r::Polygon::clip_as_polyline()
# get unsupported edges
my $grown_lower = offset([ map @$_, @{$self->lower_slices} ], +$self->extrusion_width);
my $unsupported = diff_pl(
\@bridge_edges,
$grown_lower,
);
if (0) {
require "Slic3r/SVG.pm";
Slic3r::SVG::output(
"unsupported_" . rad2deg($angle) . ".svg",
expolygons => [$self->expolygon],
green_expolygons => $self->_anchors,
red_expolygons => union_ex($grown_lower),
no_arrows => 1,
polylines => [ map $_->split_at_first_point, @{$self->expolygon} ],
red_polylines => $unsupported,
);
}
return $unsupported;
}
1; 1;

View File

@ -33,6 +33,9 @@ has 'fill_surfaces' => (is => 'rw', default => sub { Slic3r::Surface::Collection
# collection of expolygons representing the bridged areas (thus not needing support material) # collection of expolygons representing the bridged areas (thus not needing support material)
has 'bridged' => (is => 'rw', default => sub { Slic3r::ExPolygon::Collection->new }); has 'bridged' => (is => 'rw', default => sub { Slic3r::ExPolygon::Collection->new });
# collection of polylines representing the unsupported bridge edges
has 'unsupported_bridge_edges' => (is => 'rw', default => sub { Slic3r::Polyline::Collection->new });
# ordered collection of extrusion paths/loops to build all perimeters # ordered collection of extrusion paths/loops to build all perimeters
has 'perimeters' => (is => 'rw', default => sub { Slic3r::ExtrusionPath::Collection->new }); has 'perimeters' => (is => 'rw', default => sub { Slic3r::ExtrusionPath::Collection->new });
@ -418,6 +421,7 @@ sub process_external_surfaces {
if (defined $angle && $self->object->config->support_material) { if (defined $angle && $self->object->config->support_material) {
$self->bridged->append(@{ $bridge_detector->coverage($angle) }); $self->bridged->append(@{ $bridge_detector->coverage($angle) });
$self->unsupported_bridge_edges->append(@{ $bridge_detector->unsupported_edges });
} }
} }

View File

@ -158,13 +158,34 @@ sub contact_area {
# Void $diff means that there's no upper perimeter whose centerline is # Void $diff means that there's no upper perimeter whose centerline is
# outside the lower slice boundary, thus no overhang # outside the lower slice boundary, thus no overhang
} }
# remove bridged areas if ($self->object_config->dont_support_bridges) {
$diff = diff( if (1) {
$diff, # remove the entire bridges and only support the unsupported edges
[ map @$_, @{$layerm->bridged} ], my @bridges = map $_->expolygon,
1, grep $_->bridge_angle != -1,
); @{$layerm->fill_surfaces->filter_by_type(S_TYPE_BOTTOMBRIDGE)};
$diff = diff(
$diff,
[ map @$_, @bridges ],
1,
);
push @$diff, @{intersection(
[ map @{$_->grow(+scale MARGIN)}, @{$layerm->unsupported_bridge_edges} ],
[ map @$_, @bridges ],
)}
} else {
# just remove bridged areas
$diff = diff(
$diff,
[ map @$_, @{$layerm->bridged} ],
1,
);
}
}
next if !@$diff; next if !@$diff;
push @overhang, @$diff; # NOTE: this is not the full overhang as it misses the outermost half of the perimeter width! push @overhang, @$diff; # NOTE: this is not the full overhang as it misses the outermost half of the perimeter width!

View File

@ -381,6 +381,8 @@ $j
--support-material-enforce-layers --support-material-enforce-layers
Enforce support material on the specified number of layers from bottom, Enforce support material on the specified number of layers from bottom,
regardless of --support-material and threshold (0+, default: $config->{support_material_enforce_layers}) regardless of --support-material and threshold (0+, default: $config->{support_material_enforce_layers})
--dont-support-bridges
Experimental option for preventing support material from being generated under bridged areas (default: yes)
Retraction options: Retraction options:
--retract-length Length of retraction in mm when pausing extrusion (default: $config->{retract_length}[0]) --retract-length Length of retraction in mm when pausing extrusion (default: $config->{retract_length}[0])

View File

@ -139,6 +139,11 @@ class PrintConfigDef
Options["disable_fan_first_layers"].cli = "disable-fan-first-layers=i"; Options["disable_fan_first_layers"].cli = "disable-fan-first-layers=i";
Options["disable_fan_first_layers"].max = 1000; Options["disable_fan_first_layers"].max = 1000;
Options["dont_support_bridges"].type = coBool;
Options["dont_support_bridges"].label = "Don't support bridges";
Options["dont_support_bridges"].tooltip = "Experimental option for preventing support material from being generated under bridged areas.";
Options["dont_support_bridges"].cli = "dont-support-bridges!";
Options["duplicate_distance"].type = coFloat; Options["duplicate_distance"].type = coFloat;
Options["duplicate_distance"].label = "Distance between copies"; Options["duplicate_distance"].label = "Distance between copies";
Options["duplicate_distance"].tooltip = "Distance used for the auto-arrange feature of the plater."; Options["duplicate_distance"].tooltip = "Distance used for the auto-arrange feature of the plater.";
@ -968,6 +973,7 @@ class StaticPrintConfig : public virtual StaticConfig
class PrintObjectConfig : public virtual StaticPrintConfig class PrintObjectConfig : public virtual StaticPrintConfig
{ {
public: public:
ConfigOptionBool dont_support_bridges;
ConfigOptionFloatOrPercent extrusion_width; ConfigOptionFloatOrPercent extrusion_width;
ConfigOptionFloatOrPercent first_layer_height; ConfigOptionFloatOrPercent first_layer_height;
ConfigOptionBool infill_only_where_needed; ConfigOptionBool infill_only_where_needed;
@ -988,6 +994,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig
ConfigOptionInt support_material_threshold; ConfigOptionInt support_material_threshold;
PrintObjectConfig() : StaticPrintConfig() { PrintObjectConfig() : StaticPrintConfig() {
this->dont_support_bridges.value = true;
this->extrusion_width.value = 0; this->extrusion_width.value = 0;
this->extrusion_width.percent = false; this->extrusion_width.percent = false;
this->first_layer_height.value = 0.35; this->first_layer_height.value = 0.35;
@ -1012,6 +1019,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig
}; };
ConfigOption* option(const t_config_option_key opt_key, bool create = false) { ConfigOption* option(const t_config_option_key opt_key, bool create = false) {
if (opt_key == "dont_support_bridges") return &this->dont_support_bridges;
if (opt_key == "extrusion_width") return &this->extrusion_width; if (opt_key == "extrusion_width") return &this->extrusion_width;
if (opt_key == "first_layer_height") return &this->first_layer_height; if (opt_key == "first_layer_height") return &this->first_layer_height;
if (opt_key == "infill_only_where_needed") return &this->infill_only_where_needed; if (opt_key == "infill_only_where_needed") return &this->infill_only_where_needed;