From b9afbd92c30fdbbc4339c59f08ee5cbeaefada07 Mon Sep 17 00:00:00 2001 From: "lane.wei" Date: Fri, 16 Jun 2023 17:31:11 +0800 Subject: [PATCH] ENH: CLI: add logic to recompute flush volume matrix for mmu Change-Id: Id9ce0cc054492762da31d2bd9dea53c73421d972 --- src/BambuStudio.cpp | 120 ++++++++++++++++++++++++++--- src/libslic3r/CMakeLists.txt | 2 + src/libslic3r/FlushVolCalc.cpp | 98 +++++++++++++++++++++++ src/libslic3r/FlushVolCalc.hpp | 34 ++++++++ src/slic3r/GUI/WipeTowerDialog.cpp | 77 ++---------------- 5 files changed, 250 insertions(+), 81 deletions(-) create mode 100644 src/libslic3r/FlushVolCalc.cpp create mode 100644 src/libslic3r/FlushVolCalc.hpp diff --git a/src/BambuStudio.cpp b/src/BambuStudio.cpp index d13b36381..d73946874 100644 --- a/src/BambuStudio.cpp +++ b/src/BambuStudio.cpp @@ -63,6 +63,7 @@ using namespace nlohmann; #include "libslic3r/Time.hpp" #include "libslic3r/Thread.hpp" #include "libslic3r/BlacklistedLibraryCheck.hpp" +#include "libslic3r/FlushVolCalc.hpp" #include "libslic3r/Orient.hpp" @@ -388,7 +389,7 @@ int CLI::run(int argc, char **argv) "--export-3mf=output.3mf", "--slice", "0", - "Cube.3mf" + "boats.3mf" }; if (! this->setup(debug_argc, debug_argv))*/ if (!this->setup(argc, argv)) @@ -1294,6 +1295,105 @@ int CLI::run(int argc, char **argv) } } + //compute the flush volume + ConfigOptionStrings* selected_filament_colors_option = m_extra_config.option("filament_colour"); + ConfigOptionStrings *project_filament_colors_option = m_print_config.option("filament_colour"); + if (project_filament_colors_option) + { + std::vector selected_filament_colors; + if (selected_filament_colors_option) { + selected_filament_colors = selected_filament_colors_option->values; + //erase here + m_extra_config.erase("filament_colour"); + } + + std::vector &project_filament_colors = project_filament_colors_option->values; + size_t project_filament_count = project_filament_colors.size(); + BOOST_LOG_TRIVIAL(info) << boost::format("select filament color from cli, size %1%")%selected_filament_colors.size(); + BOOST_LOG_TRIVIAL(info) << boost::format("project filament colors size %1%")%project_filament_colors.size(); + if (project_filament_count > 0) + { + for ( size_t index = 0; index < project_filament_count; index++ ) + { + BOOST_LOG_TRIVIAL(info) << boost::format("project filament %1% original color %2%")%index %project_filament_colors[index]; + if (selected_filament_colors.size() > index) + { + if (!selected_filament_colors[index].empty()) + { + BOOST_LOG_TRIVIAL(info) << boost::format("changed to new color %1%")%selected_filament_colors[index]; + project_filament_colors[index] = selected_filament_colors[index]; + } + } + } + + //computing + ConfigOptionBools* filament_is_support = m_print_config.option("filament_is_support", true); + std::vector& flush_vol_matrix = m_print_config.option("flush_volumes_matrix", true)->values; + //std::vector& flush_vol_vector = m_print_config.option("flush_volumes_vector", true)->values; + flush_vol_matrix.resize(project_filament_count*project_filament_count, 0.f); + //flush_vol_vector.resize(project_filament_count); + //set multiplier to 1? + m_print_config.option("flush_multiplier", true)->set(new ConfigOptionFloat(1.f)); + ConfigOption* extra_flush_volume_opt = m_print_config.option("nozzle_volume"); + int extra_flush_volume = extra_flush_volume_opt ? (int)extra_flush_volume_opt->getFloat() : 0; + + if (filament_is_support->size() != project_filament_count) + { + BOOST_LOG_TRIVIAL(error) << boost::format("filament_is_support's count %1% not equal to filament_colour's size %2%")%filament_is_support->size() %project_filament_count; + flush_and_exit(CLI_CONFIG_FILE_ERROR); + } + + BOOST_LOG_TRIVIAL(info) << boost::format("extra_flush_volume: %1%")%extra_flush_volume; + BOOST_LOG_TRIVIAL(info) << boost::format("filament_is_support: %1%")%filament_is_support->serialize(); + BOOST_LOG_TRIVIAL(info) << boost::format("flush_volumes_matrix before computing: %1%")%m_print_config.option("flush_volumes_matrix")->serialize(); + for (int from_idx = 0; from_idx < project_filament_count; from_idx++) { + const std::string& from_color = project_filament_colors[from_idx]; + unsigned char from_rgb[4] = {}; + Slic3r::GUI::BitmapCache::parse_color4(from_color, from_rgb); + bool is_from_support = filament_is_support->get_at(from_idx); + for (int to_idx = 0; to_idx < project_filament_count; to_idx++) { + bool is_to_support = filament_is_support->get_at(to_idx); + if (from_idx == to_idx) { + flush_vol_matrix[project_filament_count*from_idx + to_idx] = 0.f; + } + else { + int flushing_volume = 0; + if (is_to_support) { + flushing_volume = Slic3r::g_flush_volume_to_support; + } + else { + const std::string& to_color = project_filament_colors[to_idx]; + unsigned char to_rgb[4] = {}; + Slic3r::GUI::BitmapCache::parse_color4(to_color, to_rgb); + //BOOST_LOG_TRIVIAL(info) << boost::format("src_idx %1%, src color %2%, dst idex %3%, dst color %4%")%from_idx %from_color %to_idx %to_color; + //BOOST_LOG_TRIVIAL(info) << boost::format("src_rgba {%1%,%2%,%3%,%4%} dst_rgba {%5%,%6%,%7%,%8%}")%(unsigned int)(from_rgb[0]) %(unsigned int)(from_rgb[1]) %(unsigned int)(from_rgb[2]) %(unsigned int)(from_rgb[3]) + // %(unsigned int)(to_rgb[0]) %(unsigned int)(to_rgb[1]) %(unsigned int)(to_rgb[2]) %(unsigned int)(to_rgb[3]); + + Slic3r::FlushVolCalculator calculator(extra_flush_volume, Slic3r::g_max_flush_volume); + + flushing_volume = calculator.calc_flush_vol(from_rgb[3], from_rgb[0], from_rgb[1], from_rgb[2], to_rgb[3], to_rgb[0], to_rgb[1], to_rgb[2]); + if (is_from_support) { + flushing_volume = std::max(Slic3r::g_min_flush_volume_from_support, flushing_volume); + } + } + + flush_vol_matrix[project_filament_count * from_idx + to_idx] = flushing_volume; + //flushing_volume = int(flushing_volume * get_flush_multiplier()); + } + } + } + BOOST_LOG_TRIVIAL(info) << boost::format("flush_volumes_matrix after computed: %1%")%m_print_config.option("flush_volumes_matrix")->serialize(); + } + else + { + BOOST_LOG_TRIVIAL(warning) << boost::format("filament colors count is 0 in projects"); + } + } + else + { + BOOST_LOG_TRIVIAL(warning) << boost::format("no filament colors found in projects"); + } + //BBS: set default to ptFFF if (printer_technology == ptUnknown) printer_technology = ptFFF; @@ -2321,14 +2421,14 @@ int CLI::run(int argc, char **argv) colors= filament_color->vserialize(); } else - colors.push_back("#FFFFFF"); + colors.push_back("#FFFFFFFF"); std::vector> colors_out(colors.size()); - unsigned char rgb_color[3] = {}; + unsigned char rgb_color[4] = {}; for (const std::string& color : colors) { - Slic3r::GUI::BitmapCache::parse_color(color, rgb_color); + Slic3r::GUI::BitmapCache::parse_color4(color, rgb_color); size_t color_idx = &color - &colors.front(); - colors_out[color_idx] = { float(rgb_color[0]) / 255.f, float(rgb_color[1]) / 255.f, float(rgb_color[2]) / 255.f, 1.f }; + colors_out[color_idx] = { float(rgb_color[0]) / 255.f, float(rgb_color[1]) / 255.f, float(rgb_color[2]) / 255.f, float(rgb_color[3]) / 255.f }; } int gl_major, gl_minor, gl_verbos; @@ -2399,17 +2499,17 @@ int CLI::run(int argc, char **argv) const ModelInstance &model_instance = *model_object.instances[instance_idx]; glvolume_collection.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, "volume", true, false, true); //glvolume_collection.volumes.back()->geometry_id = key.geometry_id; - std::string color = filament_color?filament_color->get_at(extruder_id - 1):"#00FF00"; + std::string color = filament_color?filament_color->get_at(extruder_id - 1):"#00FF00FF"; - unsigned char rgb_color[3] = {}; - Slic3r::GUI::BitmapCache::parse_color(color, rgb_color); - glvolume_collection.volumes.back()->set_render_color( float(rgb_color[0]) / 255.f, float(rgb_color[1]) / 255.f, float(rgb_color[2]) / 255.f, 1.f); + unsigned char rgb_color[4] = {}; + Slic3r::GUI::BitmapCache::parse_color4(color, rgb_color); + glvolume_collection.volumes.back()->set_render_color( float(rgb_color[0]) / 255.f, float(rgb_color[1]) / 255.f, float(rgb_color[2]) / 255.f, float(rgb_color[3]) / 255.f); std::array new_color; new_color[0] = float(rgb_color[0]) / 255.f; new_color[1] = float(rgb_color[1]) / 255.f; new_color[2] = float(rgb_color[2]) / 255.f; - new_color[3] = 1.f; + new_color[3] = float(rgb_color[3]) / 255.f; glvolume_collection.volumes.back()->set_color(new_color); glvolume_collection.volumes.back()->printable = model_instance.printable; } diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 0424aac5e..bdeae1897 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -101,6 +101,8 @@ set(lisbslic3r_sources Fill/FillRectilinear.hpp Flow.cpp Flow.hpp + FlushVolCalc.cpp + FlushVolCalc.hpp format.hpp Format/3mf.cpp Format/3mf.hpp diff --git a/src/libslic3r/FlushVolCalc.cpp b/src/libslic3r/FlushVolCalc.cpp new file mode 100644 index 000000000..29cbcbe40 --- /dev/null +++ b/src/libslic3r/FlushVolCalc.cpp @@ -0,0 +1,98 @@ +#include +#include +#include "slic3r/Utils/ColorSpaceConvert.hpp" + +#include "FlushVolCalc.hpp" + + +namespace Slic3r { + +const int g_min_flush_volume_from_support = 420.f; +const int g_flush_volume_to_support = 230; + +const int g_max_flush_volume = 800; + +static float to_radians(float degree) +{ + return degree / 180.f * M_PI; +} + + +static float get_luminance(float r, float g, float b) +{ + return r * 0.3 + g * 0.59 + b * 0.11; +} + +static float calc_triangle_3rd_edge(float edge_a, float edge_b, float degree_ab) +{ + return std::sqrt(edge_a * edge_a + edge_b * edge_b - 2 * edge_a * edge_b * std::cos(to_radians(degree_ab))); +} + +static float DeltaHS_BBS(float h1, float s1, float v1, float h2, float s2, float v2) +{ + float h1_rad = to_radians(h1); + float h2_rad = to_radians(h2); + + float dx = std::cos(h1_rad) * s1 * v1 - cos(h2_rad) * s2 * v2; + float dy = std::sin(h1_rad) * s1 * v1 - sin(h2_rad) * s2 * v2; + float dxy = std::sqrt(dx * dx + dy * dy); + return std::min(1.2f, dxy); +} + +FlushVolCalculator::FlushVolCalculator(int min, int max, float multiplier) + :m_min_flush_vol(min), m_max_flush_vol(max), m_multiplier(multiplier) +{ +} + +int FlushVolCalculator::calc_flush_vol(unsigned char src_a, unsigned char src_r, unsigned char src_g, unsigned char src_b, + unsigned char dst_a, unsigned char dst_r, unsigned char dst_g, unsigned char dst_b) +{ + // BBS: Transparent materials are treated as white materials + if (src_a == 0) { + src_r = src_g = src_b = 255; + } + if (dst_a == 0) { + dst_r = dst_g = dst_b = 255; + } + + float src_r_f, src_g_f, src_b_f, dst_r_f, dst_g_f, dst_b_f; + float from_hsv_h, from_hsv_s, from_hsv_v; + float to_hsv_h, to_hsv_s, to_hsv_v; + + src_r_f = (float)src_r / 255.f; + src_g_f = (float)src_g / 255.f; + src_b_f = (float)src_b / 255.f; + dst_r_f = (float)dst_r / 255.f; + dst_g_f = (float)dst_g / 255.f; + dst_b_f = (float)dst_b / 255.f; + + // Calculate color distance in HSV color space + RGB2HSV(src_r_f, src_g_f,src_b_f, &from_hsv_h, &from_hsv_s, &from_hsv_v); + RGB2HSV(dst_r_f, dst_g_f, dst_b_f, &to_hsv_h, &to_hsv_s, &to_hsv_v); + float hs_dist = DeltaHS_BBS(from_hsv_h, from_hsv_s, from_hsv_v, to_hsv_h, to_hsv_s, to_hsv_v); + + // 1. Color difference is more obvious if the dest color has high luminance + // 2. Color difference is more obvious if the source color has low luminance + float from_lumi = get_luminance(src_r_f, src_g_f, src_b_f); + float to_lumi = get_luminance(dst_r_f, dst_g_f, dst_b_f); + float lumi_flush = 0.f; + if (to_lumi >= from_lumi) { + lumi_flush = std::pow(to_lumi - from_lumi, 0.7f) * 560.f; + } + else { + lumi_flush = (from_lumi - to_lumi) * 80.f; + + float inter_hsv_v = 0.67 * to_hsv_v + 0.33 * from_hsv_v; + hs_dist = std::min(inter_hsv_v, hs_dist); + } + float hs_flush = 230.f * hs_dist; + + float flush_volume = calc_triangle_3rd_edge(hs_flush, lumi_flush, 120.f); + flush_volume = std::max(flush_volume, 60.f); + + //float flush_multiplier = std::atof(m_flush_multiplier_ebox->GetValue().c_str()); + flush_volume += m_min_flush_vol; + return std::min((int)flush_volume, m_max_flush_vol); +} + +} diff --git a/src/libslic3r/FlushVolCalc.hpp b/src/libslic3r/FlushVolCalc.hpp new file mode 100644 index 000000000..630b11c6a --- /dev/null +++ b/src/libslic3r/FlushVolCalc.hpp @@ -0,0 +1,34 @@ +#ifndef slic3r_FlushVolCalc_hpp_ +#define slic3r_FlushVolCalc_hpp_ + +#include "libslic3r.h" +#include "Config.hpp" + + +namespace Slic3r { + +extern const int g_min_flush_volume_from_support; +extern const int g_flush_volume_to_support; +extern const int g_max_flush_volume; + +class FlushVolCalculator +{ +public: + FlushVolCalculator(int min, int max, float multiplier = 1.0f); + ~FlushVolCalculator() + { + } + + int calc_flush_vol(unsigned char src_a, unsigned char src_r, unsigned char src_g, unsigned char src_b, + unsigned char dst_a, unsigned char dst_r, unsigned char dst_g, unsigned char dst_b); + +private: + int m_min_flush_vol; + int m_max_flush_vol; + float m_multiplier; +}; + + +} + +#endif diff --git a/src/slic3r/GUI/WipeTowerDialog.cpp b/src/slic3r/GUI/WipeTowerDialog.cpp index 6a142d98e..768215bd8 100644 --- a/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/src/slic3r/GUI/WipeTowerDialog.cpp @@ -1,5 +1,6 @@ #include #include +#include "libslic3r/FlushVolCalc.hpp" #include "WipeTowerDialog.hpp" #include "BitmapCache.hpp" #include "GUI.hpp" @@ -45,9 +46,6 @@ static void update_ui(wxWindow* window) #define style wxSP_ARROW_KEYS #endif -static const int m_max_flush_volume = 750.f; -static const int g_min_flush_volume_from_support = 420.f; -static const int g_flush_volume_to_support = 230; static const float g_min_flush_multiplier = 0.f; static const float g_max_flush_multiplier = 3.f; @@ -249,7 +247,7 @@ void WipingPanel::create_panels(wxWindow* parent, const int num) { WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, const std::vector& extruders, const std::vector& extruder_colours, Button* calc_button, int extra_flush_volume, float flush_multiplier) : wxPanel(parent,wxID_ANY, wxDefaultPosition, wxDefaultSize/*,wxBORDER_RAISED*/) -,m_matrix(matrix), m_min_flush_volume(extra_flush_volume), m_max_flush_volume(800) +,m_matrix(matrix), m_min_flush_volume(extra_flush_volume), m_max_flush_volume(Slic3r::g_max_flush_volume) { m_number_of_extruders = (int)(sqrt(matrix.size())+0.001); @@ -487,74 +485,11 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, con }); } -static float to_radians(float degree) -{ - return degree / 180.f * M_PI; -} - -float DeltaHS_BBS(float h1, float s1, float v1, float h2, float s2, float v2) -{ - float h1_rad = to_radians(h1); - float h2_rad = to_radians(h2); - - float dx = std::cos(h1_rad) * s1 * v1 - cos(h2_rad) * s2 * v2; - float dy = std::sin(h1_rad) * s1 * v1 - sin(h2_rad) * s2 * v2; - float dxy = std::sqrt(dx * dx + dy * dy); - return std::min(1.2f, dxy); -} - -static float get_luminance(float r, float g, float b) -{ - return r * 0.3 + g * 0.59 + b * 0.11; -} - -static float calc_triangle_3rd_edge(float edge_a, float edge_b, float degree_ab) -{ - return std::sqrt(edge_a * edge_a + edge_b * edge_b - 2 * edge_a * edge_b * std::cos(to_radians(degree_ab))); -} - int WipingPanel::calc_flushing_volume(const wxColour& from_, const wxColour& to_) { - wxColour from = from_; - wxColour to = to_; - // BBS: Transparent materials are treated as white materials - if (from.Alpha() == 0) { - from.Set(255, 255, 255); - } - if (to.Alpha() == 0) { - to.Set(255, 255, 255); - } + Slic3r::FlushVolCalculator calculator(m_min_flush_volume, m_max_flush_volume); - float from_hsv_h, from_hsv_s, from_hsv_v; - float to_hsv_h, to_hsv_s, to_hsv_v; - - // Calculate color distance in HSV color space - RGB2HSV((float)from.Red() / 255.f, (float)from.Green() / 255.f, (float)from.Blue() / 255.f, &from_hsv_h, &from_hsv_s, &from_hsv_v); - RGB2HSV((float)to.Red() / 255.f, (float)to.Green() / 255.f, (float)to.Blue() / 255.f, &to_hsv_h, &to_hsv_s, &to_hsv_v); - float hs_dist = DeltaHS_BBS(from_hsv_h, from_hsv_s, from_hsv_v, to_hsv_h, to_hsv_s, to_hsv_v); - - // 1. Color difference is more obvious if the dest color has high luminance - // 2. Color difference is more obvious if the source color has low luminance - float from_lumi = get_luminance((float)from.Red() / 255.f, (float)from.Green() / 255.f, (float)from.Blue() / 255.f); - float to_lumi = get_luminance((float)to.Red() / 255.f, (float)to.Green() / 255.f, (float)to.Blue() / 255.f); - float lumi_flush = 0.f; - if (to_lumi >= from_lumi) { - lumi_flush = std::pow(to_lumi - from_lumi, 0.7f) * 560.f; - } - else { - lumi_flush = (from_lumi - to_lumi) * 80.f; - - float inter_hsv_v = 0.67 * to_hsv_v + 0.33 * from_hsv_v; - hs_dist = std::min(inter_hsv_v, hs_dist); - } - float hs_flush = 230.f * hs_dist; - - float flush_volume = calc_triangle_3rd_edge(hs_flush, lumi_flush, 120.f); - flush_volume = std::max(flush_volume, 60.f); - - //float flush_multiplier = std::atof(m_flush_multiplier_ebox->GetValue().c_str()); - flush_volume += m_min_flush_volume; - return std::min((int)flush_volume, m_max_flush_volume); + return calculator.calc_flush_vol(from_.Alpha(), from_.Red(), from_.Green(), from_.Blue(), to_.Alpha(), to_.Red(), to_.Green(), to_.Blue()); } void WipingPanel::update_warning_texts() @@ -614,13 +549,13 @@ void WipingPanel::calc_flushing_volumes() else { int flushing_volume = 0; if (is_to_support) { - flushing_volume = g_flush_volume_to_support; + flushing_volume = Slic3r::g_flush_volume_to_support; } else { const wxColour& to = m_colours[to_idx]; flushing_volume = calc_flushing_volume(from, to); if (is_from_support) { - flushing_volume = std::max(g_min_flush_volume_from_support, flushing_volume); + flushing_volume = std::max(Slic3r::g_min_flush_volume_from_support, flushing_volume); } }