From 38c5c25cdd699c25e592471b6ba37cec99245bfc Mon Sep 17 00:00:00 2001 From: Mack Date: Fri, 13 Sep 2024 16:32:50 +0800 Subject: [PATCH] ENH:add brim ear invalid warning 1.fix dragging causes wrong orientation 2.clean up useless include jira:nojira Change-Id: Ia723da626ac5434a1675e4a1b781579057f1403a (cherry picked from commit 252ff6f0247546761ac9660e04ecf1bb2951d80e) --- src/libslic3r/ExPolygon.cpp | 9 ++ src/libslic3r/ExPolygon.hpp | 1 + src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp | 138 ++++++++++++++++------ src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp | 21 ++-- 4 files changed, 126 insertions(+), 43 deletions(-) diff --git a/src/libslic3r/ExPolygon.cpp b/src/libslic3r/ExPolygon.cpp index f2b952627..df996e7df 100644 --- a/src/libslic3r/ExPolygon.cpp +++ b/src/libslic3r/ExPolygon.cpp @@ -185,6 +185,15 @@ bool overlaps(const ExPolygons& expolys1, const ExPolygons& expolys2) return false; } +bool overlaps(const ExPolygons& expolys, const ExPolygon& expoly) +{ + for (const ExPolygon& el : expolys) { + if (el.overlaps(expoly)) + return true; + } + return false; +} + Point projection_onto(const ExPolygons& polygons, const Point& from) { Point projected_pt; diff --git a/src/libslic3r/ExPolygon.hpp b/src/libslic3r/ExPolygon.hpp index 4515d8a0d..0807bfa01 100644 --- a/src/libslic3r/ExPolygon.hpp +++ b/src/libslic3r/ExPolygon.hpp @@ -457,6 +457,7 @@ inline ExPolygons expolygons_simplify(const ExPolygons &expolys, double toleranc bool expolygons_match(const ExPolygon &l, const ExPolygon &r); bool overlaps(const ExPolygons& expolys1, const ExPolygons& expolys2); +bool overlaps(const ExPolygons& expolys, const ExPolygon& expoly); Point projection_onto(const ExPolygons& expolys, const Point& pt); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp index 1c7945c1c..987bd7c6a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp @@ -1,30 +1,19 @@ -// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. #include "GLGizmoBrimEars.hpp" +#include #include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" -#include "slic3r/GUI/MainFrame.hpp" -#include "slic3r/Utils/UndoRedo.hpp" -#include "slic3r/GUI/Gizmos/GLGizmoSimplify.hpp" - -#include - -#include -#include -#include - #include "slic3r/GUI/GUI_App.hpp" -#include "slic3r/GUI/GUI.hpp" -#include "slic3r/GUI/GUI_ObjectSettings.hpp" -#include "slic3r/GUI/GUI_ObjectList.hpp" #include "slic3r/GUI/Plater.hpp" -#include "slic3r/GUI/NotificationManager.hpp" -#include "slic3r/GUI/MsgDialog.hpp" -#include "libslic3r/PresetBundle.hpp" -#include "libslic3r/SLAPrint.hpp" +#include "libslic3r/ExPolygon.hpp" namespace Slic3r { namespace GUI { +static const ColorRGBA DEF_COLOR = {0.7f, 0.7f, 0.7f, 1.f}; +static const ColorRGBA SELECTED_COLOR = {0.0f, 0.5f, 0.5f, 1.0f}; +static const ColorRGBA ERR_COLOR = {1.0f, 0.3f, 0.3f, 0.5f}; +static const ColorRGBA HOVER_COLOR = {0.7f, 0.7f, 0.7f, 0.5f}; + static ModelVolume *get_model_volume(const Selection &selection, Model &model) { const Selection::IndicesList &idxs = selection.get_volume_idxs(); @@ -83,8 +72,7 @@ void GLGizmoBrimEars::on_render() const Selection &selection = m_parent.get_selection(); // If current m_c->m_model_object does not match selection, ask GLCanvas3D to turn us off - if (m_state == On && (mo != selection.get_model()->objects[selection.get_object_idx()] - || m_c->selection_info()->get_active_instance() != selection.get_instance_idx())) { + if (m_state == On && (mo != selection.get_model()->objects[selection.get_object_idx()] || m_c->selection_info()->get_active_instance() != selection.get_instance_idx())) { m_parent.post_event(SimpleEvent(EVT_GLCANVAS_RESETGIZMOS)); return; } @@ -131,18 +119,19 @@ void GLGizmoBrimEars::render_points(const Selection &selection, bool picking) co glsafe(::glPushMatrix()); glsafe(::glMultMatrixd(instance_matrix.data())); - std::array render_color; + ColorRGBA render_color; for (size_t i = 0; i < cache_size; ++i) { const BrimPoint &brim_point = editing_cache[i].brim_point; const bool &point_selected = editing_cache[i].selected; const bool &hover = editing_cache[i].is_hover; + const bool &error = editing_cache[i].is_error; // keep show brim ear // if (is_mesh_point_clipped(brim_point.pos.cast())) // continue; // First decide about the color of the point. if (hover) { - render_color = {0.7f, 0.7f, 0.7f, 0.5f}; + render_color = HOVER_COLOR; } else { if (picking) render_color = picking_color_component(i); @@ -151,14 +140,18 @@ void GLGizmoBrimEars::render_points(const Selection &selection, bool picking) co render_color = {0.f, 1.f, 1.f, 1.f}; else { // neigher hover nor picking if (point_selected) - render_color = {1.f, 0.3f, 0.3f, 1.f}; - else - render_color = {0.7f, 0.7f, 0.7f, 1.f}; + render_color = SELECTED_COLOR; + else { + if (error) + render_color = ERR_COLOR; + else + render_color = DEF_COLOR; + } } } } - const_cast(&m_cylinder)->set_color(-1, render_color); + const_cast(&m_cylinder)->set_color(render_color); if (shader && !picking) shader->set_uniform("emission_factor", 0.5f); // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. @@ -336,6 +329,7 @@ bool GLGizmoBrimEars::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_p add_point_to_cache(object_pos.cast(), m_new_point_head_diameter / 2.f, false, (inverse_trsf * m_world_normal).cast()); m_parent.set_as_dirty(); m_wait_for_up_event = true; + find_single(); } else return false; } else @@ -411,6 +405,7 @@ bool GLGizmoBrimEars::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_p select_point(NoPoints); select_point(m_hover_id); delete_selected_points(); + find_single(); return true; } return false; @@ -460,10 +455,12 @@ void GLGizmoBrimEars::on_update(const UpdateData &data) { if (m_hover_id != -1) { std::pair pos_and_normal; - if (!unproject_on_mesh(data.mouse_pos.cast(), pos_and_normal)) return; + if (!unproject_on_mesh2(data.mouse_pos.cast(), pos_and_normal)) return; m_editing_cache[m_hover_id].brim_point.pos[0] = pos_and_normal.first.x(); m_editing_cache[m_hover_id].brim_point.pos[1] = pos_and_normal.first.y(); - m_editing_cache[m_hover_id].normal = pos_and_normal.second; + //m_editing_cache[m_hover_id].normal = pos_and_normal.second; + m_editing_cache[m_hover_id].normal = Vec3f(0, 0, 1); + find_single(); } } @@ -544,14 +541,19 @@ void GLGizmoBrimEars::on_render_input_window(float x, float y, float bottom_limi m_imgui->text(m_desc["head_diameter"]); ImGui::SameLine(caption_size); ImGui::PushItemWidth(slider_width); + auto update_cache_radius = [this]() { + for (auto &cache_entry : m_editing_cache) + if (cache_entry.selected) { + cache_entry.brim_point.head_front_radius = m_new_point_head_diameter / 2.f; + find_single(); + } + }; m_imgui->bbl_slider_float_style("##head_diameter", &m_new_point_head_diameter, 5, 10, "%.1f", 1.0f, true); if (m_imgui->get_last_slider_status().clicked) { if (m_old_point_head_diameter == 0.f) m_old_point_head_diameter = initial_value; } - if (m_imgui->get_last_slider_status().edited) { - for (auto &cache_entry : m_editing_cache) - if (cache_entry.selected) cache_entry.brim_point.head_front_radius = m_new_point_head_diameter / 2.f; - } + if (m_imgui->get_last_slider_status().edited) + update_cache_radius(); if (m_imgui->get_last_slider_status().deactivated_after_edit) { // momentarily restore the old value to take snapshot for (auto &cache_entry : m_editing_cache) @@ -560,8 +562,7 @@ void GLGizmoBrimEars::on_render_input_window(float x, float y, float bottom_limi m_new_point_head_diameter = m_old_point_head_diameter; Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Change point head diameter"); m_new_point_head_diameter = backup; - for (auto &cache_entry : m_editing_cache) - if (cache_entry.selected) cache_entry.brim_point.head_front_radius = m_new_point_head_diameter / 2.f; + update_cache_radius(); m_old_point_head_diameter = 0.f; } ImGui::SameLine(drag_left_width); @@ -617,9 +618,13 @@ void GLGizmoBrimEars::on_render_input_window(float x, float y, float bottom_limi delete_selected_points(); } } - ImGui::PopStyleVar(1); + if (!m_single_brim.empty()) { + wxString out = _L("Warning") + ": " + std::to_string(m_single_brim.size()) + _L(" invalid brim ears"); + m_imgui->warning_text(out); + } + GizmoImguiEnd(); ImGui::PopStyleVar(2); ImGuiWrapper::pop_toolbar_style(); @@ -841,6 +846,7 @@ void GLGizmoBrimEars::auto_generate() for (Point &p : inner_points) { add_point(p); } } } + find_single(); } bool GLGizmoBrimEars::add_point_to_cache(Vec3f pos, float head_radius, bool selected, Vec3f normal) @@ -884,7 +890,67 @@ void GLGizmoBrimEars::reset_all_pick() { std::mapprints.get_edited_preset().config; + const DynamicPrintConfig &pring_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config; return pring_cfg.get_abs_value("initial_layer_line_width") * 16.0f; } + +ExPolygon GLGizmoBrimEars::make_polygon(BrimPoint point, const Geometry::Transformation &trsf) +{ + ExPolygon point_round; + Transform3d model_trsf = trsf.get_matrix(); + Vec3f world_pos = point.transform(trsf.get_matrix()); + coord_t size_ear = scale_(point.head_front_radius); + for (size_t i = 0; i < POLY_SIDE_COUNT; i++) { + double angle = (2.0 * PI * i) / POLY_SIDE_COUNT; + point_round.contour.points.emplace_back(size_ear * cos(angle), size_ear * sin(angle)); + } + Vec3f pos = point.transform(model_trsf); + int32_t pt_x = scale_(pos.x()); + int32_t pt_y = scale_(pos.y()); + point_round.translate(Point(pt_x, pt_y)); + return point_round; +} + +void GLGizmoBrimEars::find_single() +{ + if (m_editing_cache.size() == 0) { + m_single_brim.clear(); + return; + } + const Selection &selection = m_parent.get_selection(); + const GLVolume *volume = selection.get_volume(*selection.get_volume_idxs().begin()); + Geometry::Transformation trsf = volume->get_instance_transformation(); + ExPolygons model_pl = m_first_layer; + + m_single_brim.clear(); + for (int i = 0; i < m_editing_cache.size(); i++) + m_single_brim[i] = m_editing_cache[i]; + unsigned int index = 0; + bool cyc = true; + while (cyc) { + index++; + if (index > 99999999) break; // cycle protection + if (m_single_brim.empty()) { + break; + } + auto end = --m_single_brim.end(); + for (auto it = m_single_brim.begin(); it != m_single_brim.end(); ++it) { + ExPolygon point_pl = make_polygon(it->second.brim_point, trsf); + if (overlaps(model_pl, point_pl)) { + model_pl.emplace_back(point_pl); + model_pl = union_ex(model_pl); + it = m_single_brim.erase(it); + break; + } else { + if (it == end) cyc = false; + } + } + } + for (auto& it : m_editing_cache) { + it.is_error = false; + } + for (auto &it : m_single_brim) { + m_editing_cache[it.first].is_error = true; + } +} }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp index f11a34ee4..8e1db12c3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp @@ -3,12 +3,8 @@ #include "GLGizmoBase.hpp" #include "slic3r/GUI/GLSelectionRectangle.hpp" - #include "libslic3r/BrimEarsPoint.hpp" #include "libslic3r/ObjectID.hpp" -#include - -#include namespace Slic3r { @@ -31,10 +27,16 @@ private: class CacheEntry { public: CacheEntry() : - brim_point(BrimPoint()), selected(false), normal(Vec3f(0, 0, 1)), is_hover(false) {} + brim_point(BrimPoint()), + selected(false), + normal(Vec3f(0, 0, 1)), + is_hover(false), + is_error(false) + {} - CacheEntry(const BrimPoint &point, bool sel = false, const Vec3f &norm = Vec3f(0, 0, 1), bool hover = false) - :brim_point(point), selected(sel), normal(norm), is_hover(hover) {} + CacheEntry(const BrimPoint &point, bool sel = false, const Vec3f &norm = Vec3f(0, 0, 1), bool hover = false, bool error = false) + : brim_point(point), selected(sel), normal(norm), is_hover(hover), is_error(error) + {} bool operator==(const CacheEntry& rhs) const { return (brim_point == rhs.brim_point); @@ -53,11 +55,13 @@ private: selected = false; normal.setZero(); is_hover = false; + is_error = false; } BrimPoint brim_point; bool selected; // whether the point is selected bool is_hover; // show mouse hover cylinder + bool is_error; Vec3f normal; template @@ -96,6 +100,7 @@ private: CacheEntry m_point_before_drag; // undo/redo - so we know what state was edited float m_old_point_head_diameter = 0.; // the same mutable std::vector m_editing_cache; // a support point and whether it is currently selectedchanges or undo/redo + std::map m_single_brim; ObjectID m_old_mo_id; const Vec3d m_world_normal = {0, 0, 1}; std::map> m_mesh_raycaster_map; @@ -156,6 +161,8 @@ protected: void reset_all_pick(); bool add_point_to_cache(Vec3f pos, float head_radius, bool selected, Vec3f normal); float get_brim_default_radius() const; + ExPolygon make_polygon(BrimPoint point, const Geometry::Transformation &trsf); + void find_single(); }; } // namespace GUI