From aea32ffe7272186ca20e30c3edea8ff92c1048b7 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 20 Nov 2019 14:06:30 +0100 Subject: [PATCH] ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE -> Added 'keep min' option to smoothing algorithm --- src/libslic3r/Slicing.cpp | 26 +++++++++++++++----------- src/libslic3r/Slicing.hpp | 14 +++++++++++--- src/slic3r/GUI/GLCanvas3D.cpp | 24 +++++++++++++++--------- src/slic3r/GUI/GLCanvas3D.hpp | 10 ++++++---- src/slic3r/GUI/Plater.cpp | 2 +- 5 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/libslic3r/Slicing.cpp b/src/libslic3r/Slicing.cpp index 1badd9b14..81e9bf0c5 100644 --- a/src/libslic3r/Slicing.cpp +++ b/src/libslic3r/Slicing.cpp @@ -346,9 +346,9 @@ std::vector layer_height_profile_adaptive( return layer_height_profile; } -std::vector smooth_height_profile(const std::vector& profile, const SlicingParameters& slicing_params, unsigned int radius) +std::vector smooth_height_profile(const std::vector& profile, const SlicingParameters& slicing_params, const HeightProfileSmoothingParams& smoothing_params) { - auto gauss_blur = [&slicing_params](const std::vector& profile, unsigned int radius) -> std::vector { + auto gauss_blur = [&slicing_params](const std::vector& profile, const HeightProfileSmoothingParams& smoothing_params) -> std::vector { auto gauss_kernel = [] (unsigned int radius) -> std::vector { unsigned int size = 2 * radius + 1; std::vector ret; @@ -374,7 +374,8 @@ std::vector smooth_height_profile(const std::vector& profile, co // not enough data to smmoth if ((int)profile.size() - (int)skip_count < 6) return profile; - + + unsigned int radius = std::max(smoothing_params.radius, (unsigned int)1); std::vector kernel = gauss_kernel(radius); int two_radius = 2 * (int)radius; @@ -388,15 +389,16 @@ std::vector smooth_height_profile(const std::vector& profile, co ret.push_back(profile[i]); } - // smooth the rest of the profile - double med_h = 0.5 * (slicing_params.min_layer_height + slicing_params.max_layer_height); - double half_delta_h = 0.5 * (slicing_params.max_layer_height - slicing_params.min_layer_height); - double inv_half_delta_h = (half_delta_h > 0.0) ? 1.0 / half_delta_h : 1.0; + // smooth the rest of the profile by biasing a gaussian blur + // the bias moves the smoothed profile closer to the min_layer_height + double delta_h = slicing_params.max_layer_height - slicing_params.min_layer_height; + double inv_delta_h = (delta_h != 0.0) ? 1.0 / delta_h : 1.0; double max_dz_band = (double)radius * slicing_params.layer_height; for (size_t i = skip_count; i < size; i += 2) { double zi = profile[i]; + double hi = profile[i + 1]; ret.push_back(zi); ret.push_back(0.0); double& height = ret.back(); @@ -409,20 +411,22 @@ std::vector smooth_height_profile(const std::vector& profile, co double dz = std::abs(zi - profile[j]); if (dz * slicing_params.layer_height <= max_dz_band) { - double dh = std::abs(profile[j + 1] - med_h); - double weight = kernel[kernel_id] * dh * inv_half_delta_h; + double dh = std::abs(slicing_params.max_layer_height - profile[j + 1]); + double weight = kernel[kernel_id] * sqrt(dh * inv_delta_h); height += weight * profile[j + 1]; weight_total += weight; } } - height = clamp(slicing_params.min_layer_height, slicing_params.max_layer_height, (weight_total != 0.0) ? height /= weight_total : profile[i + 1]); + height = clamp(slicing_params.min_layer_height, slicing_params.max_layer_height, (weight_total != 0.0) ? height /= weight_total : hi); + if (smoothing_params.keep_min) + height = std::min(height, hi); } return ret; }; - return gauss_blur(profile, std::max(radius, (unsigned int)1)); + return gauss_blur(profile, smoothing_params); } void adjust_layer_height_profile( diff --git a/src/libslic3r/Slicing.hpp b/src/libslic3r/Slicing.hpp index 8dc0b47e9..03ef7e67d 100644 --- a/src/libslic3r/Slicing.hpp +++ b/src/libslic3r/Slicing.hpp @@ -147,10 +147,18 @@ extern std::vector layer_height_profile_adaptive( const SlicingParameters& slicing_params, const ModelObject& object, float cusp_value); +struct HeightProfileSmoothingParams +{ + unsigned int radius; + bool keep_min; + + HeightProfileSmoothingParams() : radius(5), keep_min(false) {} + HeightProfileSmoothingParams(unsigned int radius, bool keep_min) : radius(radius), keep_min(keep_min) {} +}; + extern std::vector smooth_height_profile( - const std::vector& profile, - const SlicingParameters& slicing_params, - unsigned int radius); + const std::vector& profile, const SlicingParameters& slicing_params, + const HeightProfileSmoothingParams& smoothing_params); #else extern std::vector layer_height_profile_adaptive( const SlicingParameters &slicing_params, diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 818c2ae63..a459a3ec8 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -132,7 +132,6 @@ GLCanvas3D::LayersEditing::LayersEditing() , m_layer_height_profile_modified(false) #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE , m_adaptive_cusp(0.2f) - , m_smooth_radius(5) #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE , state(Unknown) , band_width(2.0f) @@ -283,7 +282,7 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const ImGui::Separator(); if (imgui.button(_(L("Smooth")))) - wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), Event(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, m_smooth_radius)); + wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), HeightProfileSmoothEvent(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, m_smooth_params )); ImGui::SameLine(); ImGui::SetCursorPosX(text_align); @@ -291,9 +290,16 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const ImGui::SameLine(); ImGui::PushItemWidth(120.0f); ImGui::SetCursorPosX(widget_align); - int radius = (int)m_smooth_radius; + int radius = (int)m_smooth_params.radius; if (ImGui::SliderInt("##1", &radius, 1, 10)) - m_smooth_radius = (unsigned int)radius; + m_smooth_params.radius = (unsigned int)radius; + + ImGui::SetCursorPosX(text_align); + imgui.text(_(L("Keep min"))); + ImGui::SameLine(); + ImGui::PushItemWidth(120.0f); + ImGui::SetCursorPosX(widget_align); + imgui.checkbox("##2", m_smooth_params.keep_min); ImGui::Separator(); if (imgui.button(_(L("Reset")))) @@ -609,9 +615,9 @@ void GLCanvas3D::LayersEditing::adaptive_layer_height_profile(GLCanvas3D& canvas canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); } -void GLCanvas3D::LayersEditing::smooth_layer_height_profile(GLCanvas3D& canvas, unsigned int radius) +void GLCanvas3D::LayersEditing::smooth_layer_height_profile(GLCanvas3D& canvas, const HeightProfileSmoothingParams& smoothing_params) { - m_layer_height_profile = smooth_height_profile(m_layer_height_profile, *m_slicing_parameters, radius); + m_layer_height_profile = smooth_height_profile(m_layer_height_profile, *m_slicing_parameters, smoothing_params); const_cast(m_model_object)->layer_height_profile = m_layer_height_profile; m_layers_texture.valid = false; canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); @@ -1245,7 +1251,7 @@ wxDEFINE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE wxDEFINE_EVENT(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event); -wxDEFINE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, Event); +wxDEFINE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent); #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #if ENABLE_THUMBNAIL_GENERATOR @@ -1564,9 +1570,9 @@ void GLCanvas3D::adaptive_layer_height_profile(float cusp) m_dirty = true; } -void GLCanvas3D::smooth_layer_height_profile(unsigned int radius) +void GLCanvas3D::smooth_layer_height_profile(const HeightProfileSmoothingParams& smoothing_params) { - m_layers_editing.smooth_layer_height_profile(*this, radius); + m_layers_editing.smooth_layer_height_profile(*this, smoothing_params); m_layers_editing.state = LayersEditing::Completed; m_dirty = true; } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 4a1859d54..ad35f3909 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -81,6 +81,8 @@ template using Vec2dsEvent = ArrayEvent; using Vec3dEvent = Event; template using Vec3dsEvent = ArrayEvent; +using HeightProfileSmoothEvent = Event; + wxDECLARE_EVENT(EVT_GLCANVAS_INIT, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, RBtnEvent); @@ -107,7 +109,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE wxDECLARE_EVENT(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event); -wxDECLARE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, Event); +wxDECLARE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent); #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE class GLCanvas3D @@ -182,7 +184,7 @@ private: #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE mutable float m_adaptive_cusp; - mutable unsigned int m_smooth_radius; + mutable HeightProfileSmoothingParams m_smooth_params; #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE class LayersTexture @@ -233,7 +235,7 @@ private: void reset_layer_height_profile(GLCanvas3D& canvas); #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE void adaptive_layer_height_profile(GLCanvas3D& canvas, float cusp); - void smooth_layer_height_profile(GLCanvas3D& canvas, unsigned int radius); + void smooth_layer_height_profile(GLCanvas3D& canvas, const HeightProfileSmoothingParams& smoothing_paramsn); #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE static float get_cursor_z_relative(const GLCanvas3D& canvas); @@ -531,7 +533,7 @@ public: #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE void reset_layer_height_profile(); void adaptive_layer_height_profile(float cusp); - void smooth_layer_height_profile(unsigned int radius); + void smooth_layer_height_profile(const HeightProfileSmoothingParams& smoothing_params); #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE bool is_reload_delayed() const; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index faf7a3d69..563bb5133 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2090,7 +2090,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE view3D_canvas->Bind(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, [this](SimpleEvent&) { this->view3D->get_canvas3d()->reset_layer_height_profile(); }); view3D_canvas->Bind(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, [this](Event& evt) { this->view3D->get_canvas3d()->adaptive_layer_height_profile(evt.data); }); - view3D_canvas->Bind(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, [this](Event& evt) { this->view3D->get_canvas3d()->smooth_layer_height_profile(evt.data); }); + view3D_canvas->Bind(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, [this](HeightProfileSmoothEvent& evt) { this->view3D->get_canvas3d()->smooth_layer_height_profile(evt.data); }); #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE // 3DScene/Toolbar: