From 552a759b58bdec1cfb4cf042935c48df29c40406 Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Sat, 20 Apr 2019 10:28:07 -0500 Subject: [PATCH 1/2] #641 Make brims capable of printing on multiple layers. --- src/test/libslic3r/test_print.cpp | 6 +++--- xs/src/libslic3r/Print.cpp | 28 ++++++++++++++++------------ xs/src/libslic3r/Print.hpp | 5 +++-- xs/src/libslic3r/PrintConfig.cpp | 9 +++++++++ xs/src/libslic3r/PrintConfig.hpp | 2 ++ xs/src/libslic3r/PrintGCode.cpp | 6 +++--- 6 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/test/libslic3r/test_print.cpp b/src/test/libslic3r/test_print.cpp index abfed1a7de..703d0bab7a 100644 --- a/src/test/libslic3r/test_print.cpp +++ b/src/test/libslic3r/test_print.cpp @@ -122,7 +122,7 @@ SCENARIO("Print: Brim generation") { auto print {Slic3r::Test::init_print({m}, model, config)}; print->make_brim(); THEN("Brim Extrusion collection has 3 loops in it") { - REQUIRE(print->brim.items_count() == 3); + REQUIRE(print->brim[0].items_count() == 3); } } WHEN("Brim is set to 6mm") { @@ -130,7 +130,7 @@ SCENARIO("Print: Brim generation") { auto print {Slic3r::Test::init_print({m}, model, config)}; print->make_brim(); THEN("Brim Extrusion collection has 6 loops in it") { - REQUIRE(print->brim.items_count() == 6); + REQUIRE(print->brim[0].items_count() == 6); } } WHEN("Brim is set to 6mm, extrusion width 0.5mm") { @@ -139,7 +139,7 @@ SCENARIO("Print: Brim generation") { auto print {Slic3r::Test::init_print({m}, model, config)}; print->make_brim(); THEN("Brim Extrusion collection has 12 loops in it") { - REQUIRE(print->brim.items_count() == 12); + REQUIRE(print->brim[0].items_count() == 12); } } } diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index ae80248cc4..c0de2efe95 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -133,7 +133,11 @@ Print::make_brim() this->state.set_started(psBrim); if (this->status_cb != nullptr) this->status_cb(88, "Generating brim"); - this->_make_brim(); + // since this method must be idempotent, we clear brim paths *before* + // checking whether we need to generate them + this->brim.clear(); + for (size_t i = 0; i < this->config.brim_layers; i++) + this->_make_brim(i); this->state.set_done(psBrim); } @@ -1063,14 +1067,11 @@ Print::skirt_flow() const } void -Print::_make_brim() +Print::_make_brim(size_t i) { if (this->state.is_done(psBrim)) return; this->state.set_started(psBrim); - // since this method must be idempotent, we clear brim paths *before* - // checking whether we need to generate them - this->brim.clear(); if (this->objects.empty() || (this->config.brim_width == 0 @@ -1087,9 +1088,11 @@ Print::_make_brim() const coord_t grow_distance = flow.scaled_width()/2; Polygons islands; Points pt_ears; + ExtrusionEntityCollection tmp_brim; + tmp_brim.clear(); for (PrintObject* object : this->objects) { - const Layer* layer0 = object->get_layer(0); + const Layer* layer0 = object->get_layer(i); Polygons object_islands = layer0->slices.contours(); @@ -1244,7 +1247,7 @@ Print::_make_brim() for (Polyline &to_extrude : lines_sorted) { ExtrusionPath path(erSkirt, mm3_per_mm, flow.width, flow.height); path.polyline = to_extrude; - this->brim.append(path); + tmp_brim.append(path); } } else @@ -1253,7 +1256,7 @@ Print::_make_brim() for (Polygons::const_reverse_iterator p = chained.rbegin(); p != chained.rend(); ++p) { ExtrusionPath path(erSkirt, mm3_per_mm, flow.width, flow.height); path.polyline = p->split_at_first_point(); - this->brim.append(ExtrusionLoop(path)); + tmp_brim.append(ExtrusionLoop(path)); } } @@ -1309,7 +1312,7 @@ Print::_make_brim() for (Polylines::const_iterator pl = paths.begin(); pl != paths.end(); ++pl) { ExtrusionPath path(erSkirt, mm3_per_mm, flow.width, flow.height); path.polyline = *pl; - this->brim.append(path); + tmp_brim.append(path); } } } @@ -1352,11 +1355,12 @@ Print::_make_brim() for (const Polygon &p : loops) { ExtrusionPath path(erSkirt, mm3_per_mm, flow.width, flow.height); path.polyline = p.split_at_first_point(); - this->brim.append(ExtrusionLoop(path)); + tmp_brim.append(ExtrusionLoop(path)); } } - - this->state.set_done(psBrim); + this->brim.push_back(tmp_brim); + if (this->brim.size() == (this->config.brim_layers - 1)) + this->state.set_done(psBrim); } diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index 494e1fe7ec..95dd0e6858 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -242,7 +242,8 @@ class Print PrintState state; // ordered collections of extrusion paths to build skirt loops and brim - ExtrusionEntityCollection skirt, brim; + ExtrusionEntityCollection skirt; + std::vector brim; double skirt_height_z {-1.0}; Print(); @@ -294,7 +295,7 @@ class Print double skirt_first_layer_height() const; Flow brim_flow() const; Flow skirt_flow() const; - void _make_brim(); + void _make_brim(size_t i); /// Generates a skirt around the union of all of /// the objects in the print. diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 2901f8909d..1af7b2c304 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -185,6 +185,15 @@ PrintConfigDef::PrintConfigDef() def->cli = "brim-width=f"; def->min = 0; def->default_value = new ConfigOptionFloat(0); + + def = this->add("brim_layers", coInt); + def->label = __TRANS("Brim layers"); + def->category = __TRANS("Skirt and brim"); + def->tooltip = __TRANS("Number of layers to place the brim."); + def->sidetext = ""; + def->cli = "brim-layers=i"; + def->min = 1; + def->default_value = new ConfigOptionInt(1); def = this->add("compatible_printers", coStrings); def->label = __TRANS("Compatible printers"); diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 7a989b8041..2c8e3e2c8d 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -436,6 +436,7 @@ class PrintConfig : public GCodeConfig ConfigOptionBool brim_ears; ConfigOptionFloat brim_ears_max_angle; ConfigOptionFloat brim_width; + ConfigOptionInt brim_layers; ConfigOptionBool complete_objects; ConfigOptionBool cooling; ConfigOptionFloat default_acceleration; @@ -500,6 +501,7 @@ class PrintConfig : public GCodeConfig OPT_PTR(brim_ears); OPT_PTR(brim_ears_max_angle); OPT_PTR(brim_width); + OPT_PTR(brim_layers); OPT_PTR(complete_objects); OPT_PTR(cooling); OPT_PTR(default_acceleration); diff --git a/xs/src/libslic3r/PrintGCode.cpp b/xs/src/libslic3r/PrintGCode.cpp index 387c17aff6..32d5bc40a9 100644 --- a/xs/src/libslic3r/PrintGCode.cpp +++ b/xs/src/libslic3r/PrintGCode.cpp @@ -557,14 +557,14 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies) } // extrude brim - if (!this->_brim_done) { + if (layer->id() < _print.brim.size()) { + ExtrusionEntityCollection& local_brim { _print.brim.at(layer->id())}; gcode += _gcodegen.set_extruder(_print.brim_extruder() - 1); _gcodegen.set_origin(Pointf(0,0)); _gcodegen.avoid_crossing_perimeters.use_external_mp = true; - for (const auto& b : _print.brim.entities) { + for (const auto& b : local_brim.entities) { gcode += _gcodegen.extrude(*b, "brim", obj.config.get_abs_value("support_material_speed")); } - this->_brim_done = true; _gcodegen.avoid_crossing_perimeters.use_external_mp = false; // allow a straight travel move to the first object point From 2c5ec33a61aec65d15dc1021102a9e592393dfe0 Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Sat, 6 Jul 2019 22:28:39 -0500 Subject: [PATCH 2/2] Hack in feature for multilayer brim on perl side --- lib/Slic3r/GUI/3DScene.pm | 39 ++++++++++++++-------------- lib/Slic3r/GUI/Plater/2DToolpaths.pm | 4 +-- lib/Slic3r/GUI/PresetEditor.pm | 3 ++- lib/Slic3r/Print.pm | 4 ++- lib/Slic3r/Print/GCode.pm | 7 ++--- xs/src/libslic3r/Print.cpp | 2 +- xs/xsp/Print.xsp | 9 +++++-- xs/xsp/typemap.xspt | 1 + 8 files changed, 40 insertions(+), 29 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index d59e8da5ec..2e9231d397 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -1444,26 +1444,27 @@ sub load_print_toolpaths { } my $color_by_extruder = $self->color_toolpaths_by eq 'extruder'; - - if (!$print->brim->empty) { - my $color = $color_by_extruder - ? $self->colors->[ ($print->brim_extruder-1) % @{$self->colors} ] - : $self->colors->[2]; - - push @{$self->volumes}, my $volume = Slic3r::GUI::3DScene::Volume->new( - bounding_box => $bb, - color => $color, - qverts => Slic3r::GUI::_3DScene::GLVertexArray->new, - tverts => Slic3r::GUI::_3DScene::GLVertexArray->new, - offsets => {}, # print_z => [ qverts, tverts ] - ); - - my $top_z = $print->get_object(0)->get_layer(0)->print_z; - $volume->offsets->{$top_z} = [0, 0]; - $self->_extrusionentity_to_verts($print->brim, $top_z, Slic3r::Point->new(0,0), - $volume->qverts, $volume->tverts); + + if ($print->brim_count > 0) { # hack out brim display because of experimental brim. + for (my $id = 0; $id < $print->brim_count; $id++) { + my $color = $color_by_extruder + ? $self->colors->[ ($print->brim_extruder-1) % @{$self->colors} ] + : $self->colors->[2]; + + push @{$self->volumes}, my $volume = Slic3r::GUI::3DScene::Volume->new( + bounding_box => $bb, + color => $color, + qverts => Slic3r::GUI::_3DScene::GLVertexArray->new, + tverts => Slic3r::GUI::_3DScene::GLVertexArray->new, + offsets => {}, # print_z => [ qverts, tverts ] + ); + + my $top_z = $print->get_object(0)->get_layer($id)->print_z; + $volume->offsets->{$top_z} = [0, 0]; + $self->_extrusionentity_to_verts($print->brim_layer($id), $top_z, Slic3r::Point->new(0,0), + $volume->qverts, $volume->tverts); + } } - if (!$print->skirt->empty) { # TODO: it's a bit difficult to predict skirt extruders with the current skirt logic. # We need to rewrite it anyway. diff --git a/lib/Slic3r/GUI/Plater/2DToolpaths.pm b/lib/Slic3r/GUI/Plater/2DToolpaths.pm index 87d819c748..fb16e714b1 100644 --- a/lib/Slic3r/GUI/Plater/2DToolpaths.pm +++ b/lib/Slic3r/GUI/Plater/2DToolpaths.pm @@ -414,9 +414,9 @@ sub Render { my $print_z = $layer->print_z; # draw brim - if ($self->print->step_done(STEP_BRIM) && $layer->id == 0 && !$brim_drawn) { + if ($self->print->step_done(STEP_BRIM) && $layer->id < $self->print->brim_count && !$brim_drawn) { $self->color(@TOOL_DARK); - $self->_draw(undef, $print_z, $_) for @{$self->print->brim}; + $self->_draw(undef, $print_z, $_) for @{$self->print->brim_layer($layer->id)}; $brim_drawn = 1; } if ($self->print->step_done(STEP_SKIRT) diff --git a/lib/Slic3r/GUI/PresetEditor.pm b/lib/Slic3r/GUI/PresetEditor.pm index 8dd307e808..9fe629d15e 100644 --- a/lib/Slic3r/GUI/PresetEditor.pm +++ b/lib/Slic3r/GUI/PresetEditor.pm @@ -454,7 +454,7 @@ sub options { perimeter_acceleration infill_acceleration bridge_acceleration first_layer_acceleration default_acceleration skirts skirt_distance skirt_height min_skirt_length - brim_connections_width brim_ears brim_ears_max_angle brim_width interior_brim_width + brim_connections_width brim_layers brim_ears brim_ears_max_angle brim_width interior_brim_width support_material support_material_threshold support_material_max_layers support_material_enforce_layers raft_layers support_material_pattern support_material_spacing support_material_angle @@ -594,6 +594,7 @@ sub build { my $optgroup = $page->new_optgroup('Brim'); $optgroup->append_single_option_line('brim_width'); $optgroup->append_single_option_line('brim_ears'); + $optgroup->append_single_option_line('brim_layers'); $optgroup->append_single_option_line('brim_ears_max_angle'); $optgroup->append_single_option_line('interior_brim_width'); $optgroup->append_single_option_line('brim_connections_width'); diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 3b0bfea252..738286b240 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -265,7 +265,9 @@ sub make_brim { $self->make_skirt; $self->status_cb->(88, "Generating brim"); - $self->_make_brim; + for (my $i = 0; $i < $self->config->brim_layers; $i++) { + $self->_make_brim($i); + } } # Wrapper around the C++ Slic3r::Print::validate() diff --git a/lib/Slic3r/Print/GCode.pm b/lib/Slic3r/Print/GCode.pm index bc0cd9df4a..eea3a32220 100644 --- a/lib/Slic3r/Print/GCode.pm +++ b/lib/Slic3r/Print/GCode.pm @@ -539,13 +539,14 @@ sub process_layer { } # extrude brim - if (!$self->_brim_done) { + if ($layer->id < $self->print->brim_count) { + print("Layer: " . $layer->id. " size: " . $self->print->brim_count . "\n"); + my $brim = $self->print->brim_layer($layer->id); $gcode .= $self->_gcodegen->set_extruder($self->print->brim_extruder-1); $self->_gcodegen->set_origin(Slic3r::Pointf->new(0,0)); $self->_gcodegen->avoid_crossing_perimeters->set_use_external_mp(1); $gcode .= $self->_gcodegen->extrude($_, 'brim', $object->config->support_material_speed) - for @{$self->print->brim}; - $self->_brim_done(1); + for @{$brim}; $self->_gcodegen->avoid_crossing_perimeters->set_use_external_mp(0); # allow a straight travel move to the first object point diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index c0de2efe95..1ebeb2547a 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -1359,7 +1359,7 @@ Print::_make_brim(size_t i) } } this->brim.push_back(tmp_brim); - if (this->brim.size() == (this->config.brim_layers - 1)) + if (this->brim.size() == (this->config.brim_layers)) this->state.set_done(psBrim); } diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 0bf82d06da..2bbc15a48b 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -178,9 +178,14 @@ _constant() // TODO: status_cb Ref skirt() %code%{ RETVAL = &THIS->skirt; %}; - Ref brim() + Ref > brim() %code%{ RETVAL = &THIS->brim; %}; + Ref brim_layer(int id) + %code%{ RETVAL = &(THIS->brim.at(id)); %}; + size_t brim_count() + %code%{ RETVAL = THIS->brim.size(); %}; + PrintObjectPtrs* objects() %code%{ RETVAL = &THIS->objects; %}; void clear_objects(); @@ -288,7 +293,7 @@ _constant() Clone brim_flow(); Clone skirt_flow(); void make_skirt(); - void _make_brim(); + void _make_brim(size_t i); %{ double diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index 6a1847b948..7e0ab73dcf 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -13,6 +13,7 @@ %typemap{std::vector}; %typemap{std::vector*}; %typemap{std::vector}; +%typemap{Ref< std::vector >}; %typemap{t_layer_height_ranges}; %typemap{void*}; %typemap{SV*};