diff options
author | YuSanka <yusanka@gmail.com> | 2021-12-09 16:16:17 +0300 |
---|---|---|
committer | YuSanka <yusanka@gmail.com> | 2021-12-09 16:16:47 +0300 |
commit | 27883caa08983f7c963cad8f185e3e45fc1432eb (patch) | |
tree | 4934aae1f5058c27c39b56d1860a0aa50d8ab051 | |
parent | 7880c20330065d7a3a8623a3be29aecf81e2412c (diff) |
Follow-up https://github.com/prusa3d/PrusaSlicer/commit/b3074ad2cce49ab9ca929faf42ad5721f1b76849
Change random values of the S and V in HSV colors.
To avoid generation of the extremely light or dark colors we use now generated values from the range [0.65; 0.1]
-rw-r--r-- | src/slic3r/GUI/DoubleSlider.cpp | 22 | ||||
-rw-r--r-- | src/slic3r/GUI/DoubleSlider.hpp | 2 | ||||
-rw-r--r-- | src/slic3r/GUI/DoubleSlider_Utils.hpp | 308 |
3 files changed, 175 insertions, 157 deletions
diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index 5b0cf430c..3d914d5b6 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -1,6 +1,5 @@ #include "libslic3r/libslic3r.h" #include "DoubleSlider.hpp" -#include "DoubleSlider_Utils.hpp" #include "libslic3r/GCode.hpp" #include "GUI.hpp" #include "GUI_App.hpp" @@ -27,7 +26,6 @@ #include <cmath> #include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/split.hpp> -#include <random> #include "Field.hpp" #include "format.hpp" #include "NotificationManager.hpp" @@ -2562,7 +2560,7 @@ std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int if (mode == SingleExtruder && type == ColorChange && m_use_default_colors) { #if 1 if (ticks.empty()) - return get_opposite_color((*m_colors)[0]); + return color_generator.get_opposite_color((*m_colors)[0]); auto before_tick_it = std::lower_bound(ticks.begin(), ticks.end(), tick); if (before_tick_it == ticks.end()) @@ -2571,24 +2569,24 @@ std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int if (--before_tick_it; before_tick_it->type == ColorChange) break; if (before_tick_it->type == ColorChange) - return get_opposite_color(before_tick_it->color); - return get_opposite_color((*m_colors)[0]); + return color_generator.get_opposite_color(before_tick_it->color); + return color_generator.get_opposite_color((*m_colors)[0]); } if (before_tick_it == ticks.begin()) { const std::string& frst_color = (*m_colors)[0]; if (before_tick_it->type == ColorChange) - return get_opposite_color(frst_color, before_tick_it->color); + return color_generator.get_opposite_color(frst_color, before_tick_it->color); auto next_tick_it = before_tick_it; while (next_tick_it != ticks.end()) if (++next_tick_it; next_tick_it->type == ColorChange) break; if (next_tick_it->type == ColorChange) - return get_opposite_color(frst_color, next_tick_it->color); + return color_generator.get_opposite_color(frst_color, next_tick_it->color); - return get_opposite_color(frst_color); + return color_generator.get_opposite_color(frst_color); } std::string frst_color = ""; @@ -2609,13 +2607,13 @@ std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int if (before_tick_it->type == ColorChange) { if (frst_color.empty()) - return get_opposite_color(before_tick_it->color); - return get_opposite_color(before_tick_it->color, frst_color); + return color_generator.get_opposite_color(before_tick_it->color); + return color_generator.get_opposite_color(before_tick_it->color, frst_color); } if (frst_color.empty()) - return get_opposite_color((*m_colors)[0]); - return get_opposite_color((*m_colors)[0], frst_color); + return color_generator.get_opposite_color((*m_colors)[0]); + return color_generator.get_opposite_color((*m_colors)[0], frst_color); #else const std::vector<std::string>& colors = ColorPrintColors::get(); if (ticks.empty()) diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSlider.hpp index e0f713d87..23275cf2a 100644 --- a/src/slic3r/GUI/DoubleSlider.hpp +++ b/src/slic3r/GUI/DoubleSlider.hpp @@ -3,6 +3,7 @@ #include "libslic3r/CustomGCode.hpp" #include "wxExtensions.hpp" +#include "DoubleSlider_Utils.hpp" #include <wx/window.h> #include <wx/control.h> @@ -118,6 +119,7 @@ class TickCodeInfo // int m_default_color_idx = 0; std::vector<std::string>* m_colors {nullptr}; + ColorGenerator color_generator; std::string get_color_for_tick(TickCode tick, Type type, const int extruder); diff --git a/src/slic3r/GUI/DoubleSlider_Utils.hpp b/src/slic3r/GUI/DoubleSlider_Utils.hpp index 704eb5a87..b5955f2fc 100644 --- a/src/slic3r/GUI/DoubleSlider_Utils.hpp +++ b/src/slic3r/GUI/DoubleSlider_Utils.hpp @@ -1,173 +1,191 @@ #include <stdio.h> -#include "wx/colour.h" - -// next code is borrowed from https://stackoverflow.com/questions/3018313/algorithm-to-convert-rgb-to-hsv-and-hsv-to-rgb-in-range-0-255-for-both - -typedef struct { - double r; // a fraction between 0 and 1 - double g; // a fraction between 0 and 1 - double b; // a fraction between 0 and 1 -} rgb; - -typedef struct { - double h; // angle in degrees - double s; // a fraction between 0 and 1 - double v; // a fraction between 0 and 1 -} hsv; +#include <random> -static hsv rgb2hsv(rgb in); -static rgb hsv2rgb(hsv in); +#include "wx/colour.h" -hsv rgb2hsv(rgb in) +class ColorGenerator { - hsv out; - double min, max, delta; - - min = in.r < in.g ? in.r : in.g; - min = min < in.b ? min : in.b; + // Some of next code is borrowed from https://stackoverflow.com/questions/3018313/algorithm-to-convert-rgb-to-hsv-and-hsv-to-rgb-in-range-0-255-for-both + typedef struct { + double r; // a fraction between 0 and 1 + double g; // a fraction between 0 and 1 + double b; // a fraction between 0 and 1 + } rgb; + + typedef struct { + double h; // angle in degrees + double s; // a fraction between 0 and 1 + double v; // a fraction between 0 and 1 + } hsv; + + //static hsv rgb2hsv(rgb in); + //static rgb hsv2rgb(hsv in); + + hsv rgb2hsv(rgb in) + { + hsv out; + double min, max, delta; + + min = in.r < in.g ? in.r : in.g; + min = min < in.b ? min : in.b; + + max = in.r > in.g ? in.r : in.g; + max = max > in.b ? max : in.b; + + out.v = max; // v + delta = max - min; + if (delta < 0.00001) + { + out.s = 0; + out.h = 0; // undefined, maybe nan? + return out; + } + if (max > 0.0) { // NOTE: if Max is == 0, this divide would cause a crash + out.s = (delta / max); // s + } + else { + // if max is 0, then r = g = b = 0 + // s = 0, h is undefined + out.s = 0.0; + out.h = NAN; // its now undefined + return out; + } + if (in.r >= max) // > is bogus, just keeps compilor happy + out.h = (in.g - in.b) / delta; // between yellow & magenta + else + if (in.g >= max) + out.h = 2.0 + (in.b - in.r) / delta; // between cyan & yellow + else + out.h = 4.0 + (in.r - in.g) / delta; // between magenta & cyan + + out.h *= 60.0; // degrees + + if (out.h < 0.0) + out.h += 360.0; - max = in.r > in.g ? in.r : in.g; - max = max > in.b ? max : in.b; + return out; + } - out.v = max; // v - delta = max - min; - if (delta < 0.00001) + hsv rgb2hsv(const std::string& str_clr_in) { - out.s = 0; - out.h = 0; // undefined, maybe nan? - return out; + wxColour clr(str_clr_in); + rgb in = { clr.Red() / 255.0, clr.Green() / 255.0, clr.Blue() / 255.0 }; + return rgb2hsv(in); } - if( max > 0.0 ) { // NOTE: if Max is == 0, this divide would cause a crash - out.s = (delta / max); // s - } else { - // if max is 0, then r = g = b = 0 - // s = 0, h is undefined - out.s = 0.0; - out.h = NAN; // its now undefined + + + rgb hsv2rgb(hsv in) + { + double hh, p, q, t, ff; + long i; + rgb out; + + if (in.s <= 0.0) { // < is bogus, just shuts up warnings + out.r = in.v; + out.g = in.v; + out.b = in.v; + return out; + } + hh = in.h; + if (hh >= 360.0) hh -= 360.0;//hh = 0.0; + hh /= 60.0; + i = (long)hh; + ff = hh - i; + p = in.v * (1.0 - in.s); + q = in.v * (1.0 - (in.s * ff)); + t = in.v * (1.0 - (in.s * (1.0 - ff))); + + switch (i) { + case 0: + out.r = in.v; + out.g = t; + out.b = p; + break; + case 1: + out.r = q; + out.g = in.v; + out.b = p; + break; + case 2: + out.r = p; + out.g = in.v; + out.b = t; + break; + + case 3: + out.r = p; + out.g = q; + out.b = in.v; + break; + case 4: + out.r = t; + out.g = p; + out.b = in.v; + break; + case 5: + default: + out.r = in.v; + out.g = p; + out.b = q; + break; + } return out; } - if( in.r >= max ) // > is bogus, just keeps compilor happy - out.h = ( in.g - in.b ) / delta; // between yellow & magenta - else - if( in.g >= max ) - out.h = 2.0 + ( in.b - in.r ) / delta; // between cyan & yellow - else - out.h = 4.0 + ( in.r - in.g ) / delta; // between magenta & cyan - out.h *= 60.0; // degrees + std::random_device rd; - if( out.h < 0.0 ) - out.h += 360.0; +public: - return out; -} - -hsv rgb2hsv(const std::string& str_clr_in) -{ - wxColour clr(str_clr_in); - rgb in = { clr.Red() / 255.0, clr.Green() / 255.0, clr.Blue() / 255.0 }; - return rgb2hsv(in); -} + ColorGenerator() {} + ~ColorGenerator() {} + double rand_val() + { + std::mt19937 rand_generator(rd()); -rgb hsv2rgb(hsv in) -{ - double hh, p, q, t, ff; - long i; - rgb out; - - if(in.s <= 0.0) { // < is bogus, just shuts up warnings - out.r = in.v; - out.g = in.v; - out.b = in.v; - return out; - } - hh = in.h; - if (hh >= 360.0) hh -= 360.0;//hh = 0.0; - hh /= 60.0; - i = (long)hh; - ff = hh - i; - p = in.v * (1.0 - in.s); - q = in.v * (1.0 - (in.s * ff)); - t = in.v * (1.0 - (in.s * (1.0 - ff))); - - switch(i) { - case 0: - out.r = in.v; - out.g = t; - out.b = p; - break; - case 1: - out.r = q; - out.g = in.v; - out.b = p; - break; - case 2: - out.r = p; - out.g = in.v; - out.b = t; - break; - - case 3: - out.r = p; - out.g = q; - out.b = in.v; - break; - case 4: - out.r = t; - out.g = p; - out.b = in.v; - break; - case 5: - default: - out.r = in.v; - out.g = p; - out.b = q; - break; + // this value will be used for Saturation and Value + // to avoid extremely light/dark colors, take this value from range [0.65; 1.0] + std::uniform_real_distribution<double> distrib(0.65, 1.0); + return distrib(rand_generator); } - return out; -} -double rand_val() -{ - return 0.1 * (10 - rand() % 8); -} -std::string get_opposite_color(const std::string& color) -{ - std::string opp_color = ""; + std::string get_opposite_color(const std::string& color) + { + std::string opp_color = ""; - hsv hsv_clr = rgb2hsv(color); - hsv_clr.h += 65; // 65 instead 60 to avoid circle values - hsv_clr.s = rand_val(); - hsv_clr.v = rand_val(); + hsv hsv_clr = rgb2hsv(color); + hsv_clr.h += 65; // 65 instead 60 to avoid circle values + hsv_clr.s = rand_val(); + hsv_clr.v = rand_val(); - rgb rgb_opp_color = hsv2rgb(hsv_clr); + rgb rgb_opp_color = hsv2rgb(hsv_clr); - wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), (unsigned char)(rgb_opp_color.r * 255), (unsigned char)(rgb_opp_color.g * 255), (unsigned char)(rgb_opp_color.b * 255)); - opp_color = clr_str.ToStdString(); + wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), (unsigned char)(rgb_opp_color.r * 255), (unsigned char)(rgb_opp_color.g * 255), (unsigned char)(rgb_opp_color.b * 255)); + opp_color = clr_str.ToStdString(); - return opp_color; -} + return opp_color; + } -std::string get_opposite_color(const std::string& color_frst, const std::string& color_scnd) -{ - std::string opp_color = ""; + std::string get_opposite_color(const std::string& color_frst, const std::string& color_scnd) + { + std::string opp_color = ""; - hsv hsv_frst = rgb2hsv(color_frst); - hsv hsv_scnd = rgb2hsv(color_scnd); + hsv hsv_frst = rgb2hsv(color_frst); + hsv hsv_scnd = rgb2hsv(color_scnd); - double delta_h = fabs(hsv_frst.h - hsv_scnd.h); - double start_h = delta_h > 180 ? std::min<double>(hsv_scnd.h, hsv_frst.h) : std::max<double>(hsv_scnd.h, hsv_frst.h); - start_h += 5; // to avoid circle change of colors for 120 deg - if (delta_h < 180) - delta_h = 360 - delta_h; + double delta_h = fabs(hsv_frst.h - hsv_scnd.h); + double start_h = delta_h > 180 ? std::min<double>(hsv_scnd.h, hsv_frst.h) : std::max<double>(hsv_scnd.h, hsv_frst.h); + start_h += 5; // to avoid circle change of colors for 120 deg + if (delta_h < 180) + delta_h = 360 - delta_h; - hsv hsv_opp = hsv{ start_h + 0.5 * delta_h, rand_val(), rand_val() }; - rgb rgb_opp_color = hsv2rgb(hsv_opp); + hsv hsv_opp = hsv{ start_h + 0.5 * delta_h, rand_val(), rand_val() }; + rgb rgb_opp_color = hsv2rgb(hsv_opp); - wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), (unsigned char)(rgb_opp_color.r * 255), (unsigned char)(rgb_opp_color.g * 255), (unsigned char)(rgb_opp_color.b * 255)); - opp_color = clr_str.ToStdString(); + wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), (unsigned char)(rgb_opp_color.r * 255), (unsigned char)(rgb_opp_color.g * 255), (unsigned char)(rgb_opp_color.b * 255)); + opp_color = clr_str.ToStdString(); - return opp_color; -}
\ No newline at end of file + return opp_color; + } +};
\ No newline at end of file |