diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index d52d8be1c5..d8ad080379 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -38,23 +38,12 @@ using GUI::format_wxstr; namespace DoubleSlider { -bool possible_threshold(const double& bottom_area, const double& top_area) -{ - // Check percent of the area decrease. - // This value have to be more than 25 mm2 - return (bottom_area - top_area > min_delta_area()) && - // and more 10% - (top_area / bottom_area < 0.9); -} +constexpr double min_delta_area = scale_(scale_(25)); // equal to 25 mm2 +constexpr double miscalculation = scale_(scale_(1)); // equal to 1 mm2 bool equivalent_areas(const double& bottom_area, const double& top_area) { - return fabs(bottom_area - top_area <= min_threshold()); -} - -bool overhang(const double& bottom_area, const double& top_area) -{ - return top_area > bottom_area && !equivalent_areas(bottom_area, top_area); + return fabs(bottom_area - top_area <= miscalculation); } wxDEFINE_EVENT(wxCUSTOMEVT_TICKSCHANGED, wxEvent); @@ -2053,6 +2042,32 @@ void Control::show_cog_icon_context_menu() GUI::wxGetApp().plater()->PopupMenu(&menu); } +bool check_color_change(PrintObject* object, size_t frst_layer_id, size_t layers_cnt, std::function break_condition) +{ + double prev_area = area(object->get_layer(frst_layer_id)->lslices); + + bool detected = false; + for (size_t i = frst_layer_id+1; i < layers_cnt; i++) { + Layer* layer = object->get_layer(i); + double cur_area = area(layer->lslices); + + // check for overhangs + if (cur_area > prev_area && !equivalent_areas(prev_area, cur_area)) + break; + + // Check percent of the area decrease. + // This value have to be more than min_delta_area and more then 10% + if ((prev_area - cur_area > min_delta_area) && (cur_area / prev_area < 0.9)) { + detected = true; + if (break_condition(layer)) + break; + } + + prev_area = cur_area; + } + return detected; +} + void Control::auto_color_change() { if (!m_ticks.empty()) { @@ -2071,36 +2086,30 @@ void Control::auto_color_change() for (auto object : print.objects()) { if (object->layer_count() == 0) continue; - double prev_area = area(object->get_layer(0)->lslices); - for (size_t i = 1; i < object->layers().size(); i++) { - Layer* layer = object->get_layer(i); - double cur_area = area(layer->lslices); - - if (overhang(prev_area, cur_area)) - break; - - if (possible_threshold(prev_area, cur_area)) { - int tick = get_tick_from_value(layer->print_z); - if (tick >= 0 && !m_ticks.has_tick(tick)) { - if (m_mode == SingleExtruder) { - m_ticks.set_default_colors(true); - m_ticks.add_tick(tick, ColorChange, 1, layer->print_z); - } - else { - m_ticks.add_tick(tick, ToolChange, extruder, layer->print_z); - if (++extruder > extruders_cnt) + check_color_change(object, 1, object->layers().size(), [this, extruders_cnt](Layer* layer) + { + int tick = get_tick_from_value(layer->print_z); + if (tick >= 0 && !m_ticks.has_tick(tick)) { + if (m_mode == SingleExtruder) { + m_ticks.set_default_colors(true); + m_ticks.add_tick(tick, ColorChange, 1, layer->print_z); + } + else { + int extruder = 2; + if (!m_ticks.empty()) { + auto it = m_ticks.ticks.end(); + it--; + extruder = it->extruder + 1; + if (extruder > extruders_cnt) extruder = 1; } + m_ticks.add_tick(tick, ToolChange, extruder, layer->print_z); } - - // allow max 3 auto color changes - if (m_ticks.ticks.size() == 3) - break; } - - prev_area = cur_area; - } + // allow max 3 auto color changes + return m_ticks.ticks.size() > 2; + }); } if (m_ticks.empty()) diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSlider.hpp index 13b7f483d0..5c95d80528 100644 --- a/src/slic3r/GUI/DoubleSlider.hpp +++ b/src/slic3r/GUI/DoubleSlider.hpp @@ -17,6 +17,8 @@ class wxMenu; namespace Slic3r { using namespace CustomGCode; +class PrintObject; +class Layer; namespace DoubleSlider { @@ -25,12 +27,14 @@ namespace DoubleSlider { */ constexpr double epsilon() { return 0.0011; } -constexpr double min_delta_area() { return scale_(scale_(25)); } // equal to 25 mm2 -constexpr double min_threshold() { return scale_(scale_(1)); } // equal to 1 mm2 - -bool possible_threshold(const double& bottom_area, const double& top_area); +// return true when areas are mostly equivalent bool equivalent_areas(const double& bottom_area, const double& top_area); -bool overhang(const double& bottom_area, const double& top_area); + +// return true if color change was detected +bool check_color_change(PrintObject* object, size_t frst_layer_id, size_t layers_cnt, + // what to do with detected color change + // and return true when detection have to be desturbed + std::function break_condition); // custom message the slider sends to its parent to notify a tick-change: wxDECLARE_EVENT(wxCUSTOMEVT_TICKSCHANGED, wxEvent); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 5584350199..8654bed892 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -720,33 +720,23 @@ void Preview::update_layers_slider(const std::vector& layers_z, bool kee if (i < min_solid_height) continue; - // bottom layer have to be a biggest, so control relation between bottom layer and object size - double prev_area = area(object->get_layer(i)->lslices); - for ( i++; i < num_layers; i++) { - double cur_area = area(object->get_layer(i)->lslices); - if (DoubleSlider::overhang(prev_area, cur_area)) - break; - prev_area = cur_area; - } - if (i < num_layers) - continue; - - double top_area = area(object->get_layer(int(object->layers().size()) - 1)->lslices); - if (DoubleSlider::possible_threshold(bottom_area, top_area)) { - NotificationManager *notif_mngr = wxGetApp().plater()->get_notification_manager(); + if (DoubleSlider::check_color_change(object, i, num_layers, [this, object](Layer*) { + NotificationManager* notif_mngr = wxGetApp().plater()->get_notification_manager(); notif_mngr->push_notification( NotificationType::SignDetected, NotificationManager::NotificationLevel::PrintInfoNotificationLevel, - _u8L("NOTE:") + "\n" + _u8L("Sliced object looks like the sign") + "\n", - _u8L("Apply auto color change to print"), + _u8L("NOTE:") + "\n" + + format(_u8L("Sliced object \"%1%\" looks like a logo or a sign"), object->model_object()->name) + "\n", + _u8L("Apply automatic color change"), [this](wxEvtHandler*) { m_layers_slider->auto_color_change(); return true; }); notif_mngr->apply_in_preview(); - + return true; + }) ) + // first object with color chnages is found break; - } } }