From f670ad68212fb0df92e2614f3fbc4b41dbef4f37 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sat, 11 Mar 2017 23:35:22 +0100 Subject: [PATCH] New Interior Brim option. #2026 --- lib/Slic3r/GUI/3DScene.pm | 3 +- lib/Slic3r/GUI/Tab.pm | 6 ++- lib/Slic3r/Print/GCode.pm | 3 +- slic3r.pl | 2 + xs/src/libslic3r/ExPolygonCollection.cpp | 14 +++-- xs/src/libslic3r/ExPolygonCollection.hpp | 1 + xs/src/libslic3r/Print.cpp | 65 +++++++++++++++++++----- xs/src/libslic3r/PrintConfig.cpp | 10 +++- xs/src/libslic3r/PrintConfig.hpp | 2 + 9 files changed, 85 insertions(+), 21 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index 56875acc9..0e6ba3c8f 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -1296,6 +1296,7 @@ sub load_print_toolpaths { return if !$print->step_done(STEP_BRIM); return if !$print->has_skirt && $print->config->brim_width == 0 + && $print->config->interior_brim_width == 0 && $print->config->brim_connections_width == 0; my $qverts = Slic3r::GUI::_3DScene::GLVertexArray->new; @@ -1308,7 +1309,7 @@ sub load_print_toolpaths { } else { $skirt_height = min($print->config->skirt_height, $print->total_layer_count); } - $skirt_height ||= 1 if $print->config->brim_width > 0; + $skirt_height ||= 1 if $print->config->brim_width > 0 || $print->config->interior_brim_width; # get first $skirt_height layers (maybe this should be moved to a PrintObject method?) my $object0 = $print->get_object(0); diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 17e7e08ce..e6a5c0f8a 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -479,7 +479,7 @@ sub build { perimeter_acceleration infill_acceleration bridge_acceleration first_layer_acceleration default_acceleration skirts skirt_distance skirt_height min_skirt_length - brim_connections_width brim_width + brim_connections_width brim_width interior_brim_width support_material support_material_threshold support_material_enforce_layers raft_layers support_material_pattern support_material_spacing support_material_angle @@ -572,6 +572,7 @@ sub build { { my $optgroup = $page->new_optgroup('Brim'); $optgroup->append_single_option_line('brim_width'); + $optgroup->append_single_option_line('interior_brim_width'); $optgroup->append_single_option_line('brim_connections_width'); } } @@ -857,7 +858,8 @@ sub _update { $self->get_field($_)->toggle($have_skirt) for qw(skirt_distance skirt_height); - my $have_brim = $config->brim_width > 0 || $config->brim_connections_width; + my $have_brim = $config->brim_width > 0 || $config->interior_brim_width + || $config->brim_connections_width; # perimeter_extruder uses the same logic as in Print::extruders() $self->get_field('perimeter_extruder')->toggle($have_perimeters || $have_brim); diff --git a/lib/Slic3r/Print/GCode.pm b/lib/Slic3r/Print/GCode.pm index 086f7e33f..d6bd99ac0 100644 --- a/lib/Slic3r/Print/GCode.pm +++ b/lib/Slic3r/Print/GCode.pm @@ -318,7 +318,8 @@ sub process_layer { # check whether we're going to apply spiralvase logic if (defined $self->_spiral_vase) { $self->_spiral_vase->enable( - ($layer->id > 0 || $self->print->config->brim_width == 0 || $self->print->config->brim_connections_width == 0) + ($layer->id > 0 || $self->print->config->brim_width == 0 + || $self->print->config->interior_brim_width == 0 || $self->print->config->brim_connections_width == 0) && ($layer->id >= $self->print->config->skirt_height && !$self->print->has_infinite_skirt) && !defined(first { $_->region->config->bottom_solid_layers > $layer->id } @{$layer->regions}) && !defined(first { $_->perimeters->items_count > 1 } @{$layer->regions}) diff --git a/slic3r.pl b/slic3r.pl index 0f9c8e57f..c9c282e8f 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -530,6 +530,8 @@ $j of filament on the first layer, for each extruder (mm, 0+, default: $config->{min_skirt_length}) --brim-width Width of the brim that will get added to each object to help adhesion (mm, default: $config->{brim_width}) + --interior-brim-width Width of the brim that will get printed inside object holes to help adhesion + (mm, default: $config->{interior_brim_width}) Transform options: --scale Factor for scaling input object (default: 1) diff --git a/xs/src/libslic3r/ExPolygonCollection.cpp b/xs/src/libslic3r/ExPolygonCollection.cpp index 10e036210..90498a42d 100644 --- a/xs/src/libslic3r/ExPolygonCollection.cpp +++ b/xs/src/libslic3r/ExPolygonCollection.cpp @@ -116,12 +116,20 @@ Polygons ExPolygonCollection::contours() const { Polygons contours; - for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it) { - contours.push_back(it->contour); - } + for (const ExPolygon &ex : this->expolygons) + contours.push_back(ex.contour); return contours; } +Polygons +ExPolygonCollection::holes() const +{ + Polygons holes; + for (const ExPolygon &ex : this->expolygons) + append_to(holes, ex.holes); + return holes; +} + void ExPolygonCollection::append(const ExPolygons &expp) { diff --git a/xs/src/libslic3r/ExPolygonCollection.hpp b/xs/src/libslic3r/ExPolygonCollection.hpp index e63dd9142..89728c822 100644 --- a/xs/src/libslic3r/ExPolygonCollection.hpp +++ b/xs/src/libslic3r/ExPolygonCollection.hpp @@ -31,6 +31,7 @@ class ExPolygonCollection Polygon convex_hull() const; Lines lines() const; Polygons contours() const; + Polygons holes() const; void append(const ExPolygons &expolygons); }; diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 9dec28e9f..f1bc284d9 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -167,6 +167,7 @@ Print::invalidate_state_by_config_options(const std::vector || *opt_key == "ooze_prevention") { steps.insert(psSkirt); } else if (*opt_key == "brim_width" + || *opt_key == "interior_brim_width" || *opt_key == "brim_connections_width") { steps.insert(psBrim); steps.insert(psSkirt); @@ -308,7 +309,10 @@ Print::object_extruders() const FOREACH_REGION(this, region) { // these checks reflect the same logic used in the GUI for enabling/disabling // extruder selection fields - if ((*region)->config.perimeters.value > 0 || this->config.brim_width.value > 0 || this->config.brim_connections_width.value > 0) + if ((*region)->config.perimeters.value > 0 + || this->config.brim_width.value > 0 + || this->config.interior_brim_width.value > 0 + || this->config.brim_connections_width.value > 0) extruders.insert((*region)->config.perimeter_extruder - 1); if ((*region)->config.fill_density.value > 0) @@ -790,7 +794,9 @@ Print::_make_brim() // checking whether we need to generate them this->brim.clear(); - if (this->config.brim_width == 0 && this->config.brim_connections_width == 0) { + if (this->config.brim_width == 0 + && this->config.interior_brim_width == 0 + && this->config.brim_connections_width == 0) { this->state.set_done(psBrim); return; } @@ -819,12 +825,10 @@ Print::_make_brim() it != support_layer0.support_interface_fills.entities.end(); ++it) append_to(object_islands, offset((*it)->as_polyline(), grow_distance)); } - for (Points::const_iterator copy = (*object)->_shifted_copies.begin(); copy != (*object)->_shifted_copies.end(); - ++copy) { - for (Polygons::const_iterator p = object_islands.begin(); p != object_islands.end(); ++p) { - Polygon p2 = *p; - p2.translate(*copy); - islands.push_back(p2); + for (const Point © : (*object)->_shifted_copies) { + for (Polygon p : object_islands) { + p.translate(copy); + islands.push_back(p); } } } @@ -855,17 +859,17 @@ Print::_make_brim() } if (this->config.brim_connections_width > 0) { - // get islands to connects - for (Polygons::iterator p = islands.begin(); p != islands.end(); ++p) - *p = Geometry::convex_hull(p->points); + // get islands to connect + for (Polygon &p : islands) + p = Geometry::convex_hull(p.points); islands = offset(islands, flow.scaled_spacing() * (num_loops-0.2), 10000, jtSquare); // compute centroid for each island Points centroids; centroids.reserve(islands.size()); - for (Polygons::const_iterator p = islands.begin(); p != islands.end(); ++p) - centroids.push_back(p->centroid()); + for (const Polygon &p : islands) + centroids.push_back(p.centroid()); // in order to check visibility we need to account for the connections width, // so let's use grown islands @@ -912,6 +916,41 @@ Print::_make_brim() } } + if (this->config.interior_brim_width > 0) { + // collect all island holes to fill + Polygons holes; + for (PrintObject* object : this->objects) { + const Layer &layer0 = *object->get_layer(0); + + const Polygons o_holes = layer0.slices.holes(); + for (const Point © : object->_shifted_copies) { + for (Polygon p : o_holes) { + p.translate(copy); + holes.push_back(p); + } + } + } + + Polygons loops; + const int num_loops = floor(this->config.interior_brim_width / flow.width + 0.5); + for (int i = 1; i <= num_loops; ++i) { + append_to(loops, offset2( + holes, + -flow.scaled_spacing() * (i + 0.5), + flow.scaled_spacing(), + 100000, + ClipperLib::jtSquare + )); + } + + loops = union_pt_chained(loops); + for (const Polygon &p : loops) { + ExtrusionPath path(erSkirt, mm3_per_mm, flow.width, first_layer_height); + path.polyline = p.split_at_first_point(); + this->brim.append(ExtrusionLoop(path)); + } + } + this->state.set_done(psBrim); } diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index e024393ba..9cee1a147 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -103,7 +103,7 @@ PrintConfigDef::PrintConfigDef() def->default_value = new ConfigOptionFloat(0); def = this->add("brim_width", coFloat); - def->label = "Brim width"; + def->label = "Exterior brim width"; def->tooltip = "Horizontal width of the brim that will be printed around each object on the first layer."; def->sidetext = "mm"; def->cli = "brim-width=f"; @@ -653,6 +653,14 @@ PrintConfigDef::PrintConfigDef() def->enum_labels.push_back("auto"); def->default_value = new ConfigOptionFloat(80); + def = this->add("interior_brim_width", coFloat); + def->label = "Interior brim width"; + def->tooltip = "Horizontal width of the brim that will be printed inside object holes on the first layer."; + def->sidetext = "mm"; + def->cli = "interior-brim-width=f"; + def->min = 0; + def->default_value = new ConfigOptionFloat(0); + def = this->add("interface_shells", coBool); def->label = "Interface shells"; def->tooltip = "Force the generation of solid shells between adjacent materials/volumes. Useful for multi-extruder prints with translucent materials or manual soluble support material."; diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 3694819c6..715d84296 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -395,6 +395,7 @@ class PrintConfig : public GCodeConfig ConfigOptionBool gcode_arcs; ConfigOptionFloat infill_acceleration; ConfigOptionBool infill_first; + ConfigOptionFloat interior_brim_width; ConfigOptionInt max_fan_speed; ConfigOptionInt min_fan_speed; ConfigOptionFloat min_print_speed; @@ -455,6 +456,7 @@ class PrintConfig : public GCodeConfig OPT_PTR(gcode_arcs); OPT_PTR(infill_acceleration); OPT_PTR(infill_first); + OPT_PTR(interior_brim_width); OPT_PTR(max_fan_speed); OPT_PTR(min_fan_speed); OPT_PTR(min_print_speed);