diff --git a/.github/workflows/ccpp_win.yml b/.github/workflows/ccpp_win.yml index 1bd841de42c..cf320f95355 100644 --- a/.github/workflows/ccpp_win.yml +++ b/.github/workflows/ccpp_win.yml @@ -41,19 +41,28 @@ jobs: - name: change date in version shell: powershell run: (Get-Content version.inc) | Foreach-Object {$_ -replace "\+UNKNOWN", ("_" + [datetime]::Today.ToString("yyyy-MM-dd"))} | Set-Content version.inc - - name: mkdir in deps directory - run: mkdir deps/destdir + - run: mkdir deps/destdir - name: download deps uses: actions/download-artifact@v1 with: name: deps_win path: deps/destdir - - name: echo dir deps - run: dir deps - - name: echo dir deps destdir - run: dir deps/destdir - - name: mkdir - run: mkdir build + - run: dir deps + - run: dir deps/destdir + - run: mkdir msgfmt_bin + - name: copy gettext + working-directory: ./msgfmt_bin + shell: powershell + run: '(new-object System.Net.WebClient).DownloadFile("https://github.com/supermerill/SuperSlicer_deps/releases/download/gettext/gettext-tools-static-0.18.1.1.zip", "gettext.zip")' + - name: unzip + working-directory: ./msgfmt_bin + shell: cmd + run: '"C:/Program Files/7-Zip/7z.exe" x gettext.zip' + - name: add msgfmt to path + shell: powershell + working-directory: msgfmt_bin + run: echo "$pwd;" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + - run: mkdir build - name: cmake working-directory: ./build run: cmake .. -G "Visual Studio 16 2019" -A x64 -DCMAKE_PREFIX_PATH="d:\a\${{ github.event.repository.name }}\${{ github.event.repository.name }}\deps\destdir\usr\local" diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 55c689566a6..3797c13ebad 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -516,7 +516,7 @@ class ConfigOptionVectorBase : public ConfigOption { virtual bool empty() const = 0; // Get if the size of this vector is/should be the same as nozzle_diameter bool is_extruder_size() const { return (flags & FCO_EXTRUDER_ARRAY) != 0; } - ConfigOptionVectorBase* set_is_extruder_size(bool is_extruder_size) { + ConfigOptionVectorBase* set_is_extruder_size(bool is_extruder_size = true) { if (is_extruder_size) this->flags |= FCO_EXTRUDER_ARRAY; else this->flags &= uint8_t(0xFF ^ FCO_EXTRUDER_ARRAY); return this; } diff --git a/src/libslic3r/Flow.cpp b/src/libslic3r/Flow.cpp index 26aea7e79a4..85ddccc3a0e 100644 --- a/src/libslic3r/Flow.cpp +++ b/src/libslic3r/Flow.cpp @@ -80,10 +80,6 @@ double Flow::extrusion_width(const std::string& opt_key, const ConfigOptionFloat } if (opt->percent) { - auto opt_key_layer_height = first_layer ? "first_layer_height" : "layer_height"; - auto opt_layer_height = config.option(opt_key_layer_height); - if (opt_layer_height == nullptr) - throw_on_missing_variable(opt_key, opt_key_layer_height); // first_layer_height depends on first_printing_extruder auto opt_nozzle_diameters = config.option("nozzle_diameter"); if (opt_nozzle_diameters == nullptr) diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 3fae1662a82..ca667080cfa 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -688,7 +688,7 @@ static std::vector s_Preset_print_options { "compatible_printers", "compatible_printers_condition", "inherits", "infill_dense", "infill_dense_algo", "no_perimeter_unsupported_algo", - "exact_last_layer_height", + // "exact_last_layer_height", "perimeter_loop", "perimeter_loop_seam", "infill_connection", "infill_connection_solid", "infill_connection_top", "infill_connection_bottom", "infill_connection_bridge", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index ab63b9f9c54..dd21018f5c6 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -621,6 +621,7 @@ double Print::get_object_first_layer_height(const PrintObject& object) const { object_first_layer_height = std::min(object_first_layer_height, object.config().first_layer_height.get_abs_value(nozzle_diameter)); } } + assert(object_first_layer_height < 1000000000); return object_first_layer_height; } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 72c04ae9bfd..c9abe3b6d24 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3275,6 +3275,7 @@ void PrintConfigDef::init_fff_params() // and it contains a sum of "inherits" values over the print and filament profiles. def = this->add("inherits_cummulative", coStrings); def->set_default_value(new ConfigOptionStrings()); + def->mode = comPrusa; def->cli = ConfigOptionDef::nocli; def = this->add("interface_shells", coBool); @@ -3400,12 +3401,12 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert | comSuSi; def->set_default_value(new ConfigOptionString("")); - def = this->add("exact_last_layer_height", coBool); - def->label = L("Exact last layer height"); - def->category = OptionCategory::perimeter; - def->tooltip = L("This setting controls the height of last object layers to put the last layer at the exact highest height possible. Experimental."); - def->mode = comHidden; - def->set_default_value(new ConfigOptionBool(false)); + // def = this->add("exact_last_layer_height", coBool); + // def->label = L("Exact last layer height"); + // def->category = OptionCategory::perimeter; + // def->tooltip = L("This setting controls the height of last object layers to put the last layer at the exact highest height possible. Experimental."); + // def->mode = comHidden; + // def->set_default_value(new ConfigOptionBool(false)); def = this->add("remaining_times", coBool); def->label = L("Supports remaining times"); @@ -7686,6 +7687,7 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va "seal_position", "vibration_limit", "bed_size", "print_center", "g0", "threads", "pressure_advance", "wipe_tower_per_color_wipe", "cooling", "serial_port", "serial_speed", + "exact_last_layer_height", // Introduced in some PrusaSlicer 2.3.1 alpha, later renamed or removed. "fuzzy_skin_perimeter_mode", "fuzzy_skin_shape", // Introduced in PrusaSlicer 2.3.0-alpha2, later replaced by automatic calculation based on extrusion width. @@ -8090,7 +8092,7 @@ std::unordered_set prusa_export_to_remove_keys = { "curve_smoothing_precision", "default_speed", "enforce_full_fill_volume", -"exact_last_layer_height", +// "exact_last_layer_height", "external_infill_margin", "external_perimeter_acceleration", "external_perimeter_cut_corners", @@ -8731,7 +8733,7 @@ void DynamicPrintConfig::normalize_fdm() this->opt("support_material", true)->value = false; this->opt("solid_over_perimeters")->value = 0; this->opt("support_material_enforce_layers")->value = 0; - this->opt("exact_last_layer_height", true)->value = false; + // this->opt("exact_last_layer_height", true)->value = false; this->opt("ensure_vertical_shell_thickness", true)->value = false; this->opt("infill_dense", true)->value = false; this->opt("extra_perimeters", true)->value = false; diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 6c3075a6ba3..d08278c77e1 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -720,7 +720,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionBool, clip_multipart_objects)) ((ConfigOptionBool, dont_support_bridges)) ((ConfigOptionPercent, external_perimeter_cut_corners)) - ((ConfigOptionBool, exact_last_layer_height)) + //((ConfigOptionBool, exact_last_layer_height)) ((ConfigOptionFloatOrPercent, extrusion_width)) ((ConfigOptionFloatOrPercent, extrusion_spacing)) ((ConfigOptionFloatOrPercent, first_layer_acceleration_over_raft)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 67913ec4d11..7db8108f277 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -552,11 +552,11 @@ namespace Slic3r { { m_max_sparse_spacing = 0; std::atomic_int64_t max_sparse_spacing; - //tbb::parallel_for( - // tbb::blocked_range(0, m_layers.size()), - // [this, &max_sparse_spacing](const tbb::blocked_range& range) { - //for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { - for (size_t layer_idx = 0; layer_idx < m_layers.size(); ++layer_idx) { + tbb::parallel_for( + tbb::blocked_range(0, m_layers.size()), + [this, &max_sparse_spacing](const tbb::blocked_range& range) { + for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { + //for (size_t layer_idx = 0; layer_idx < m_layers.size(); ++layer_idx) { m_print->throw_if_canceled(); const Layer *layer = m_layers[layer_idx]; for (const LayerRegion *layerm : layer->regions()) { @@ -566,17 +566,14 @@ namespace Slic3r { coord_t spacing = layerm->region().flow(*this, frInfill, layer->height, layer->id()).scaled_spacing(); // update atomic to max int64_t prev_value = max_sparse_spacing.load(); - std::cout<<"will update "< "< SlicingParameters::create_from_config( // if the first_layer_height setting depends of the nozzle width, use the first one. Apply the z_step //get object first layer height - coordf_t first_layer_height = object_config.first_layer_height.value; + double first_layer_height = object_config.first_layer_height.value; if (object_config.first_layer_height.percent) { first_layer_height = 1000000000.; for (uint16_t extruder_id : object_extruders) { if (print_config.nozzle_diameter.size() <= extruder_id) break; - coordf_t nozzle_diameter = print_config.nozzle_diameter.values[extruder_id]; + double nozzle_diameter = print_config.nozzle_diameter.values[extruder_id]; first_layer_height = std::min(first_layer_height, object_config.first_layer_height.get_abs_value(nozzle_diameter)); } if (first_layer_height == 1000000000.) first_layer_height = 0; } - - if (first_layer_height == 0) + + first_layer_height = check_z_step(first_layer_height, print_config.z_step); + assert(first_layer_height > 0); + for (uint16_t extruder_id : object_extruders) + assert(first_layer_height >= + print_config.min_layer_height.get_abs_value(extruder_id, print_config.nozzle_diameter.get_at(extruder_id)) - EPSILON); + if (first_layer_height <= EPSILON) object_config.layer_height.value; first_layer_height = check_z_step(first_layer_height, print_config.z_step); + assert(first_layer_height > 0); + // If object_config.support_material_extruder == 0 resp. object_config.support_material_interface_extruder == 0, // print_config.nozzle_diameter.get_at(size_t(-1)) returns the 0th nozzle diameter, // which is consistent with the requirement that if support_material_extruder == 0 resp. support_material_interface_extruder == 0, @@ -138,7 +145,7 @@ std::shared_ptr SlicingParameters::create_from_config( params.max_layer_height = std::numeric_limits::max(); params.max_suport_layer_height = 0; params.min_suport_layer_height = 0; - params.exact_last_layer_height = object_config.exact_last_layer_height.value; + // params.exact_last_layer_height = object_config.exact_last_layer_height.value; if (object_config.support_material.value || params.base_raft_layers > 0 || object_config.support_material_enforce_layers > 0) { // Has some form of support. Add the support layers to the minimum / maximum layer height limits. if (object_config.support_material_extruder > 0) @@ -799,32 +806,33 @@ std::vector generate_object_layers( } // Adjust the last layer to align with the top object layer exactly - if (out.size() > 0 && slicing_params.object_print_z_height() != out[out.size() - 1] && slicing_params.exact_last_layer_height) { - float neededPrintZ = slicing_params.object_print_z_height(); - int idx_layer = out.size() / 2 - 1; - float diffZ = neededPrintZ - out[idx_layer * 2 + 1]; - while (diffZ > EPSILON || diffZ < -EPSILON && idx_layer >= 0){ - float newH = out[idx_layer * 2 + 1] - out[idx_layer * 2]; - if (diffZ > 0){ - newH = std::min((float)slicing_params.max_layer_height, newH + diffZ); - } else{ - newH = std::max((float)slicing_params.min_layer_height, newH + diffZ); - } - out[idx_layer * 2 + 1] = neededPrintZ; - out[idx_layer * 2] = neededPrintZ - newH; - - //next item - neededPrintZ = out[idx_layer * 2]; - idx_layer--; - if (idx_layer >= 0){ - diffZ = neededPrintZ - out[idx_layer * 2 + 1]; - } else{ - //unlikely to happen. note: can create a layer outside the min/max bounds. - diffZ = 0; - out[idx_layer * 2] = 0; - } - } - } + // FIXME + // if (out.size() > 0 && slicing_params.object_print_z_height() != out[out.size() - 1] && slicing_params.exact_last_layer_height) { + // float neededPrintZ = slicing_params.object_print_z_height(); + // int idx_layer = out.size() / 2 - 1; + // float diffZ = neededPrintZ - out[idx_layer * 2 + 1]; + // while (diffZ > EPSILON || diffZ < -EPSILON && idx_layer >= 0){ + // float newH = out[idx_layer * 2 + 1] - out[idx_layer * 2]; + // if (diffZ > 0){ + // newH = std::min((float)slicing_params.max_layer_height, newH + diffZ); + // } else{ + // newH = std::max((float)slicing_params.min_layer_height, newH + diffZ); + // } + // out[idx_layer * 2 + 1] = neededPrintZ; + // out[idx_layer * 2] = neededPrintZ - newH; + + // //next item + // neededPrintZ = out[idx_layer * 2]; + // idx_layer--; + // if (idx_layer >= 0){ + // diffZ = neededPrintZ - out[idx_layer * 2 + 1]; + // } else{ + // //unlikely to happen. note: can create a layer outside the min/max bounds. + // diffZ = 0; + // out[idx_layer * 2] = 0; + // } + // } + // } #ifdef _DEBUG for (size_t i = 0; i < out.size(); i++) diff --git a/src/libslic3r/Slicing.hpp b/src/libslic3r/Slicing.hpp index 9254b6f9453..247723a2e8d 100644 --- a/src/libslic3r/Slicing.hpp +++ b/src/libslic3r/Slicing.hpp @@ -71,7 +71,7 @@ struct SlicingParameters coordf_t max_layer_height { 0 }; coordf_t max_suport_layer_height { 0 }; coordf_t min_suport_layer_height { 0 }; - bool exact_last_layer_height; + // bool exact_last_layer_height; // min common divisor for all layer height coordf_t z_step; diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index a61f450473a..741a97146d9 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -77,7 +77,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con && config->opt_bool("support_material") == false && config->opt_int("support_material_enforce_layers") == 0 && config->opt_enum("perimeter_generator") == PerimeterGeneratorType::Classic - && config->opt_bool("exact_last_layer_height") == false + // && config->opt_bool("exact_last_layer_height") == false && config->opt_bool("ensure_vertical_shell_thickness") == true && config->opt_bool("infill_dense") == false && config->opt_bool("extra_perimeters") == false @@ -97,7 +97,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con "- no support material\n" "- Ensure vertical shell thickness enabled\n" "- disabled 'no solid infill over perimeters'\n" - "- unchecked 'exact last layer height'\n" + // "- unchecked 'exact last layer height'\n" "- unchecked 'dense infill'\n" "- unchecked 'extra perimeters'" "- unchecked 'gap fill after last perimeter'" @@ -123,8 +123,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con new_conf.set_key_value("support_material", new ConfigOptionBool(false)); else if (this->local_config->get().optptr("support_material_enforce_layers")) new_conf.set_key_value("support_material_enforce_layers", new ConfigOptionInt(0)); - else if (this->local_config->get().optptr("exact_last_layer_height")) - new_conf.set_key_value("exact_last_layer_height", new ConfigOptionBool(false)); + // else if (this->local_config->get().optptr("exact_last_layer_height")) + // new_conf.set_key_value("exact_last_layer_height", new ConfigOptionBool(false)); else if (this->local_config->get().optptr("ensure_vertical_shell_thickness")) new_conf.set_key_value("ensure_vertical_shell_thickness", new ConfigOptionBool(true)); else if (this->local_config->get().optptr("infill_dense")) @@ -154,7 +154,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con new_conf.set_key_value("perimeter_generator", new ConfigOptionEnum(PerimeterGeneratorType::Classic)); new_conf.set_key_value("support_material", new ConfigOptionBool(false)); new_conf.set_key_value("support_material_enforce_layers", new ConfigOptionInt(0)); - new_conf.set_key_value("exact_last_layer_height", new ConfigOptionBool(false)); + // new_conf.set_key_value("exact_last_layer_height", new ConfigOptionBool(false)); new_conf.set_key_value("ensure_vertical_shell_thickness", new ConfigOptionBool(true)); new_conf.set_key_value("infill_dense", new ConfigOptionBool(false)); new_conf.set_key_value("extra_perimeters", new ConfigOptionBool(false)); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 095719a33a8..f82061b7ad5 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -4405,14 +4405,14 @@ void GCodeViewer::render_legend(float& legend_height) imgui.text(min_label); ImGui::SameLine(); ImGui::PushItemWidth(imgui.get_style_scaling() * size); - ImGui::InputFloat(m_extrusions.ranges.min_max_cstr_id[size_t(m_view_type)].second.c_str(), &mod_max, 0.0f, + ImGui::InputFloat(m_extrusions.ranges.min_max_cstr_id[size_t(m_view_type)].second.c_str(), &mod_min, 0.0f, 0.0f, format.c_str(), ImGuiInputTextFlags_CharsDecimal, 0.f); // draw max ImGui::SameLine(); imgui.text(max_label); ImGui::SameLine(); ImGui::PushItemWidth(imgui.get_style_scaling() * size); - ImGui::InputFloat(m_extrusions.ranges.min_max_cstr_id[size_t(m_view_type)].first.c_str(), &mod_min, 0.0f, + ImGui::InputFloat(m_extrusions.ranges.min_max_cstr_id[size_t(m_view_type)].first.c_str(), &mod_max, 0.0f, 0.0f, format.c_str(), ImGuiInputTextFlags_CharsDecimal, 0.f); } else { diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index ee590f9457b..b4bbbc2580c 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -567,6 +567,9 @@ void Tab::OnActivate() void Tab::update_label_colours() { + if (!this->completed()) + return; + if (m_sys_label_clr == wxGetApp().get_label_clr_sys() && m_modified_label_clr == wxGetApp().get_label_clr_modified() && m_default_label_clr == wxGetApp().get_label_clr_default() diff --git a/tests/superslicerlibslic3r/test_flow.cpp b/tests/superslicerlibslic3r/test_flow.cpp index 7d4c7db16e9..39ac288769f 100644 --- a/tests/superslicerlibslic3r/test_flow.cpp +++ b/tests/superslicerlibslic3r/test_flow.cpp @@ -15,6 +15,16 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + using namespace Slic3r::Test; using namespace Slic3r; @@ -27,6 +37,7 @@ SCENARIO("Extrusion width specifics", "[!mayfail]") { config.set_key_value("perimeters", new ConfigOptionInt{3}); config.set_key_value("fill_density", new ConfigOptionPercent{40}); config.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent{100, true}); + config.set_key_value("extruder", new ConfigOptionInt{0}); WHEN("first layer width set to 2mm") { Slic3r::Model model; @@ -46,10 +57,11 @@ SCENARIO("Extrusion width specifics", "[!mayfail]") { Slic3r::Test::gcode(gcode_filepath, print); GCodeReader parser {Slic3r::GCodeReader()}; const double layer_height = config.opt_float("layer_height"); + const double first_layer_height = config.get_computed_value("first_layer_height"); std::string gcode_from_file= read_to_string(gcode_filepath); - parser.parse_buffer(gcode_from_file, [&E_per_mm_bottom, layer_height] (Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line) + parser.parse_buffer(gcode_from_file, [&E_per_mm_bottom, layer_height, first_layer_height] (Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line) { - if (self.z() == Approx(layer_height).margin(0.01)) { // only consider first layer + if (self.z() <= first_layer_height + 0.01) { // only consider first layer if (line.extruding(self) && line.dist_XY(self) > 0) { E_per_mm_bottom.emplace_back(line.dist_E(self) / line.dist_XY(self)); } @@ -104,30 +116,33 @@ SCENARIO(" Bridge flow specifics.", "[!mayfail]") { /// Test the expected behavior for auto-width, /// spacing, etc SCENARIO("Flow: Flow math for non-bridges", "[!mayfail]") { - auto width_0 = ConfigOptionFloatOrPercent(1.0, false); - auto spacing_0 = ConfigOptionFloatOrPercent(1.0, false,true); + auto width_0 = ConfigOptionFloatOrPercent(0.0, false); + auto spacing_0 = ConfigOptionFloatOrPercent(0.0, false,true); GIVEN("Nozzle Diameter of 0.4, a desired width of 1mm and layer height of 0.5") { auto width_1 = ConfigOptionFloatOrPercent(1.0, false); auto spacing_1 = ConfigOptionFloatOrPercent(1.0, false,true); float spacing {0.4f}; float nozzle_diameter {0.4f}; float bridge_flow {1.0f}; - float layer_height {0.5f}; + float layer_height {0.25f}; + float spacing_ratio = 1.0f; + + assert(layer_height < nozzle_diameter); // Spacing for non-bridges is has some overlap THEN("External perimeter flow has a default spacing fixed to 1.05*nozzle_diameter") { - Flow flow = Flow::new_from_config_width(frExternalPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, 0.0f); + Flow flow = Flow::new_from_config_width(frExternalPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, spacing_ratio); REQUIRE(flow.spacing() == Approx((1.05f*nozzle_diameter) - layer_height * (1.0 - PI / 4.0))); } THEN("Internal perimeter flow has a default spacing fixed to 1.125*nozzle_diameter") { - Flow flow {Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, 0.0f)}; + Flow flow {Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, spacing_ratio)}; REQUIRE(flow.spacing() == Approx((1.125*nozzle_diameter) - layer_height * (1.0 - PI / 4.0))); } THEN("Spacing for supplied width is 0.8927f") { - Flow flow {Flow::new_from_config_width(frExternalPerimeter, width_1, spacing_1, nozzle_diameter, layer_height, 0.0f)}; + Flow flow {Flow::new_from_config_width(frExternalPerimeter, width_1, spacing_1, nozzle_diameter, layer_height, spacing_ratio)}; REQUIRE(flow.spacing() == Approx(width_1.get_abs_value(1.f) - layer_height * (1.0 - PI / 4.0))); - flow = Flow::new_from_config_width(frPerimeter, width_1, spacing_1, nozzle_diameter, layer_height, 0.0f); + flow = Flow::new_from_config_width(frPerimeter, width_1, spacing_1, nozzle_diameter, layer_height, spacing_ratio); REQUIRE(flow.spacing() == Approx(width_1.get_abs_value(1.f) - layer_height * (1.0 - PI / 4.0))); } } @@ -135,25 +150,26 @@ SCENARIO("Flow: Flow math for non-bridges", "[!mayfail]") { GIVEN("Nozzle Diameter of 0.25 with extreme width") { float nozzle_diameter {0.25f}; float layer_height {0.5f}; + float spacing_ratio {1.0f}; WHEN("layer height is set to 0.15") { - layer_height = 5.f; + layer_height = 0.15f; THEN("Max width is respected.") { - auto flow {Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, 0.0f)}; + auto flow {Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, spacing_ratio)}; REQUIRE(flow.width() <= Approx(1.4*nozzle_diameter)); } THEN("Min width is respected") { - auto flow{ Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, 0.0f) }; + auto flow{ Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, spacing_ratio) }; REQUIRE(flow.width() >= Approx(1.05*nozzle_diameter)); } } WHEN("Layer height is set to 0.3") { layer_height = 0.01f; THEN("Max width is respected.") { - auto flow{ Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, 0.0f) }; + auto flow{ Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, spacing_ratio) }; REQUIRE(flow.width() <= Approx(1.4*nozzle_diameter)); } THEN("Min width is respected.") { - auto flow{ Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, 0.0f) }; + auto flow{ Flow::new_from_config_width(frPerimeter, width_0, spacing_0, nozzle_diameter, layer_height, spacing_ratio) }; REQUIRE(flow.width() >= Approx(1.05*nozzle_diameter)); } } @@ -185,26 +201,8 @@ SCENARIO("Flow: Flow math for bridges", "[!mayfail]") { float nozzle_diameter {0.4f}; float spacing_ratio {1.0f}; float layer_height {0.5f}; - WHEN("Flow role is frExternalPerimeter") { - auto flow {Flow::new_from_config_width(frExternalPerimeter, width, spacing, nozzle_diameter, layer_height, spacing_ratio)}; - THEN("Bridge width is same as nozzle diameter") { - REQUIRE(flow.width() == Approx(nozzle_diameter)); - } - THEN("Bridge spacing is same as nozzle diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter") { - REQUIRE(flow.spacing() == Approx(nozzle_diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter)); - } - } - WHEN("Flow role is frInfill") { - auto flow {Flow::new_from_config_width(frInfill, width, spacing, nozzle_diameter, layer_height, spacing_ratio)}; - THEN("Bridge width is same as nozzle diameter") { - REQUIRE(flow.width() == Approx(nozzle_diameter)); - } - THEN("Bridge spacing is same as nozzle diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter") { - REQUIRE(flow.spacing() == Approx(nozzle_diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter)); - } - } - WHEN("Flow role is frPerimeter") { - auto flow {Flow::new_from_config_width(frPerimeter, width, spacing, nozzle_diameter, layer_height, spacing_ratio)}; + WHEN("via bridging_flow()") { + auto flow {Flow::bridging_flow(nozzle_diameter, nozzle_diameter)}; THEN("Bridge width is same as nozzle diameter") { REQUIRE(flow.width() == Approx(nozzle_diameter)); } @@ -212,14 +210,217 @@ SCENARIO("Flow: Flow math for bridges", "[!mayfail]") { REQUIRE(flow.spacing() == Approx(nozzle_diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter)); } } - WHEN("Flow role is frSupportMaterial") { - auto flow {Flow::new_from_config_width(frSupportMaterial, width, spacing, nozzle_diameter, layer_height, spacing_ratio)}; - THEN("Bridge width is same as nozzle diameter") { - REQUIRE(flow.width() == Approx(nozzle_diameter)); - } - THEN("Bridge spacing is same as nozzle diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter") { - REQUIRE(flow.spacing() == Approx(nozzle_diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter)); + REQUIRE(Flow::bridge_extrusion_spacing(nozzle_diameter) == Approx(nozzle_diameter + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter)); + } +} + +SCENARIO("Flow: stats are okay") { + DynamicPrintConfig &config{Slic3r::DynamicPrintConfig::full_print_config()}; + config.set_key_value("skirts", new ConfigOptionInt{0}); + config.set_key_value("brim_width", new ConfigOptionFloat{0}); + config.set_key_value("fill_density", new ConfigOptionPercent{0}); + config.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent{0.2, false}); + config.set_key_value("layer_height", new ConfigOptionFloat{0.2}); + config.set_key_value("top_solid_layers", new ConfigOptionInt{1000}); + config.set_key_value("bottom_solid_layers", new ConfigOptionInt{1000}); + config.set_key_value("extruder", new ConfigOptionInt{0}); + config.set_key_value("nozzle_diameter", new ConfigOptionFloats(1, 0.5f)); + config.set_key_value("solid_fill_pattern", new ConfigOptionEnum(ipRectilinear)); + config.set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + config.set_key_value("solid_infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + config.set_key_value("top_infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + config.set_key_value("external_perimeter_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + config.set_key_value("perimeter_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false)); + config.update_phony({}); + + double cube_side_spacing = 20; + std::string name; + + WHEN("20x20x20 cube with only infill") + { + // only infill -> the sube border is at the spacing (so extrusion may go a bit outside) + config.set_key_value("perimeters", new ConfigOptionInt{0}); + name = "no_peri"; + } + + + WHEN("20x20x20 cube with one perimeter") + { + // only infill -> the perimeter width touch the border, so it has less fill than with only infill. + // also, set seam_gap to 0 to avoid removing bits of the perimeters + cube_side_spacing = 20 - 0.2/*height*/ * float(1. - 0.25 * PI); + config.set_key_value("perimeters", new ConfigOptionInt{1}); + config.set_key_value("seam_gap", (new ConfigOptionFloatsOrPercents(1, FloatOrPercent{0,false}))->set_is_extruder_size()); + + name = "one_peri"; + } + + WHEN("20x20x20 cube with three perimeters") + { + // only infill -> the perimeter width touch the border, so it has less fill than with only infill. + // also, set seam_gap to 0 to avoid removing bits of the perimeters + cube_side_spacing = 20 - 0.2/*height*/ * float(1. - 0.25 * PI); + config.set_key_value("perimeters", new ConfigOptionInt{3}); + config.set_key_value("seam_gap", (new ConfigOptionFloatsOrPercents(1, FloatOrPercent{0,false}))->set_is_extruder_size()); + + name = "three_peri"; + } + + WHEN("20x20x20 cube with three arachne perimeters") + { + // only infill -> the perimeter width touch the border, so it has less fill than with only infill. + // also, set seam_gap to 0 to avoid removing bits of the perimeters + cube_side_spacing = 20 - 0.2/*height*/ * float(1. - 0.25 * PI); + config.set_key_value("perimeters", new ConfigOptionInt{3}); + config.set_key_value("perimeter_generator", new ConfigOptionEnum(PerimeterGeneratorType::Arachne)); + config.set_key_value("seam_gap", (new ConfigOptionFloatsOrPercents(1, FloatOrPercent{0, false}))->set_is_extruder_size()); + name = "arachne_three_peri"; + } + + Slic3r::Model model; + Print print; + Slic3r::Test::init_print(print, {TestMesh::cube_20x20x20}, model, &config); + const double volume = (cube_side_spacing*cube_side_spacing*20); + const double volume_layer = (cube_side_spacing*cube_side_spacing*0.2); + print.process(); + REQUIRE(print.get_object(0)->get_layer(0)->height == Approx(0.2)); + REQUIRE(print.get_object(0)->get_layer(1)->height == Approx(0.2)); + + std::string gcode_filepath{ "" }; + Slic3r::Test::gcode(gcode_filepath, print); + std::string gcode_from_file = read_to_string(gcode_filepath); + Slic3r::PrintStatistics &stats = print.print_statistics(); + //string[] lineArray = gcode_from_file + GCodeReader parser; + double volume_extruded = 0; + //int idx = 0; + int step = 0; + double volume_perimeter_extruded = 0; + double volume_infill_extruded = 0; + double volume_other_extruded = 0; + // add remaining time lines where needed + parser.parse_buffer(gcode_from_file, + [&](GCodeReader& reader, const GCodeReader::GCodeLine& line) + { + if(line.comment() == "TYPE:External perimeter" || line.comment() == "TYPE:Internal perimeter") + step = 1; + else if(line.comment() == "TYPE:Solid infill" || line.comment() == "TYPE:Top solid infill") + step = 2; + else if(boost::starts_with(line.comment(),"TYPE:")) + step = 0; + if (line.cmd_is("G1")) + { + if (line.dist_E(reader) > 0 && line.dist_XY(reader) > 0) { + volume_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.); + if (step == 0) volume_other_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.); + else if (step == 1) volume_perimeter_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.); + else if (step == 2) volume_infill_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.); } } + }); + REQUIRE(volume_other_extruded == 0); + + REQUIRE(print.get_object(0)->layers().size() == 100); + for (size_t layer_id = 0; layer_id < 100; layer_id++) { + double volumeExtrPerimeter = ExtrusionVolume{}.get(print.get_object(0)->get_layer(layer_id)->regions()[0]->perimeters); + double volumeExtrInfill = ExtrusionVolume{}.get(print.get_object(0)->get_layer(layer_id)->regions()[0]->fills); + REQUIRE(volume_layer == Approx(volumeExtrInfill + volumeExtrPerimeter)); + // no perimeter -> no fill_no_overlap_expolygons + REQUIRE( (config.option("perimeters")->get_int() == 0) == (volumeExtrPerimeter == 0)); + REQUIRE( (volumeExtrPerimeter == 0) == print.get_object(0)->get_layer(0)->regions()[0]->fill_no_overlap_expolygons.empty()); } + + std::cout<get_float(); +// std::cout<<"cube side: "<< (20 + layer_height * float(1. - 0.25 * PI))<<"\n"; +// const double cube_side_spacing = 20;// - layer_height * float(1. - 0.25 * PI); +// const double volume = (cube_side_spacing*cube_side_spacing*1); +// const double volume_layer = (cube_side_spacing*cube_side_spacing*layer_height); +// print.process(); +// REQUIRE(print.get_object(0)->get_layer(0)->height == Approx(layer_height)); +// REQUIRE(print.get_object(0)->get_layer(1)->height == Approx(layer_height)); +// +// std::string gcode_filepath{ "" }; +// Slic3r::Test::gcode(gcode_filepath, print); +// std::string gcode_from_file = read_to_string(gcode_filepath); +// Slic3r::PrintStatistics &stats = print.print_statistics(); +// //string[] lineArray = gcode_from_file +// GCodeReader parser; +// double volume_extruded = 0; +// //int idx = 0; +// int step = 0; +// double volume_perimeter_extruded = 0; +// double volume_infill_extruded = 0; +// double volume_other_extruded = 0; +// double volume_this_layer = 0; +// // add remaining time lines where needed +// parser.parse_buffer(gcode_from_file, +// [&](GCodeReader& reader, const GCodeReader::GCodeLine& line) +// { +// if(line.comment() == "TYPE:External perimeter" || line.comment() == "TYPE:Internal perimeter") +// step = 1; +// else if(line.comment() == "TYPE:Solid infill" || line.comment() == "TYPE:Top solid infill") +// step = 2; +// else if(boost::starts_with(line.comment(),"TYPE:")) +// step = 0; +// if (line.cmd_is("G1")) +// { +// if (line.dist_E(reader) > 0 && line.dist_XY(reader) > 0) { +// volume_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.); +// volume_this_layer += line.dist_E(reader)*(PI*1.75*1.75 / 4.); +// if (step == 0) volume_other_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.); +// else if (step == 1) volume_perimeter_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.); +// else if (step == 2) volume_infill_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.); +// } +// } +// if (boost::starts_with(line.comment(), "LAYER_CHANGE")) { +// std::cout<<"layer volume: "<layers().size(); layer_id++) { +// double volumeExtrPerimeter = ExtrusionVolume{}.get(print.get_object(0)->get_layer(layer_id)->regions()[0]->perimeters); +// double volumeExtrInfill = ExtrusionVolume{}.get(print.get_object(0)->get_layer(layer_id)->regions()[0]->fills); +// REQUIRE(volume_layer == Approx(volumeExtrInfill + volumeExtrPerimeter)); +// //std::cout<<" +// // no perimeter -> no fill_no_overlap_expolygons +// REQUIRE( (config.option("perimeters")->get_int() == 0) == (volumeExtrPerimeter == 0)); +// REQUIRE( (volumeExtrPerimeter == 0) == print.get_object(0)->get_layer(0)->regions()[0]->fill_no_overlap_expolygons.empty()); +// +// tot_vol_extrusion_struct += volumeExtrPerimeter + volumeExtrInfill; +// } +// +// std::cout<<"from3mf"<<" : "<