From 85aa6fddfc9e86d9293647763ad47b1bc3d8e4e1 Mon Sep 17 00:00:00 2001 From: "zhou.xu" Date: Mon, 15 Jul 2024 15:13:28 +0800 Subject: [PATCH] FIX:very small face can't be selected in assembly gizmo jira: STUDIO-7594 Change-Id: Ibc2f0e80b9d5ef20de6997527b0dde09aee8d32b --- src/libslic3r/Measure.cpp | 96 +++++++++++++----------- src/libslic3r/Measure.hpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp | 9 ++- src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp | 1 + 4 files changed, 59 insertions(+), 49 deletions(-) diff --git a/src/libslic3r/Measure.cpp b/src/libslic3r/Measure.cpp index 441af3c81..f3939406d 100644 --- a/src/libslic3r/Measure.cpp +++ b/src/libslic3r/Measure.cpp @@ -57,7 +57,7 @@ static std::tuple get_center_and_radius(const std::vector double error = std::numeric_limits::max(); auto circle = Geometry::circle_ransac(out, iter, &error); - + return std::make_tuple(trafo.inverse() * Vec3d(circle.center.x(), circle.center.y(), z), circle.radius, error); } @@ -93,7 +93,7 @@ public: bool features_extracted = false; }; - std::optional get_feature(size_t face_idx, const Vec3d& point, const Transform3d &world_tran); + std::optional get_feature(size_t face_idx, const Vec3d &point, const Transform3d &world_tran,bool only_select_plane); int get_num_of_planes() const; const std::vector& get_plane_triangle_indices(int idx) const; std::vector* get_plane_tri_indices(int idx); @@ -184,7 +184,7 @@ void MeasuringImpl::update_planes() m_planes.back().normal = normal_ptr->cast(); std::sort(m_planes.back().facets.begin(), m_planes.back().facets.end()); } - + // Check that each facet is part of one of the planes. assert(std::none_of(m_face_to_plane.begin(), m_face_to_plane.end(), [](size_t val) { return val == size_t(-1); })); @@ -254,7 +254,7 @@ void MeasuringImpl::update_planes() he = sm.opposite(he); if (he.is_invalid()) goto PLANE_FAILURE; - + Face_index fi = he.face(); auto face_it = std::lower_bound(facets.begin(), facets.end(), int(fi)); if (face_it == facets.end() || *face_it != int(fi)) // This indicates a broken mesh. @@ -526,7 +526,7 @@ void MeasuringImpl::extract_features(int plane_idx) plane.features_extracted = true; } -std::optional MeasuringImpl::get_feature(size_t face_idx, const Vec3d& point, const Transform3d &world_tran) +std::optional MeasuringImpl::get_feature(size_t face_idx, const Vec3d &point, const Transform3d &world_tran,bool only_select_plane) { if (face_idx >= m_face_to_plane.size()) return std::optional(); @@ -544,46 +544,48 @@ std::optional MeasuringImpl::get_feature(size_t face_idx, const assert(plane.surface_features.empty() || plane.surface_features.back().get_type() == SurfaceFeatureType::Plane); - for (size_t i=0; idist; - if (dist < feature_hover_limit && dist < min_dist) { - min_dist = std::min(dist, min_dist); - closest_feature_idx = i; + if (!only_select_plane) { + for (size_t i = 0; i < plane.surface_features.size() - 1; ++i) { + // The -1 is there to prevent measuring distance to the plane itself, + // which is needless and relatively expensive. + res = get_measurement(plane.surface_features[i], point_sf); + if (res.distance_strict) { // TODO: this should become an assert after all combinations are implemented. + double dist = res.distance_strict->dist; + if (dist < feature_hover_limit && dist < min_dist) { + min_dist = std::min(dist, min_dist); + closest_feature_idx = i; + } } } - } - if (closest_feature_idx != size_t(-1)) { - const SurfaceFeature& f = plane.surface_features[closest_feature_idx]; - if (f.get_type() == SurfaceFeatureType::Edge) { - // If this is an edge, check if we are not close to the endpoint. If so, - // we will include the endpoint as well. Close = 10% of the lenghth of - // the edge, clamped between 0.025 and 0.5 mm. - const auto& [sp, ep] = f.get_edge(); - double len_sq = (ep-sp).squaredNorm(); - double limit_sq = std::max(0.025*0.025, std::min(0.5*0.5, 0.1 * 0.1 * len_sq)); - if ((point - sp).squaredNorm() < limit_sq) { - SurfaceFeature local_f(sp); - local_f.origin_surface_feature = std::make_shared(local_f); - local_f.translate(world_tran); - return std::make_optional(local_f); + if (closest_feature_idx != size_t(-1)) { + const SurfaceFeature &f = plane.surface_features[closest_feature_idx]; + if (f.get_type() == SurfaceFeatureType::Edge) { + // If this is an edge, check if we are not close to the endpoint. If so, + // we will include the endpoint as well. Close = 10% of the lenghth of + // the edge, clamped between 0.025 and 0.5 mm. + const auto &[sp, ep] = f.get_edge(); + double len_sq = (ep - sp).squaredNorm(); + double limit_sq = std::max(0.025 * 0.025, std::min(0.5 * 0.5, 0.1 * 0.1 * len_sq)); + if ((point - sp).squaredNorm() < limit_sq) { + SurfaceFeature local_f(sp); + local_f.origin_surface_feature = std::make_shared(local_f); + local_f.translate(world_tran); + return std::make_optional(local_f); + } + + if ((point - ep).squaredNorm() < limit_sq) { + SurfaceFeature local_f(ep); + local_f.origin_surface_feature = std::make_shared(local_f); + local_f.translate(world_tran); + return std::make_optional(local_f); + } } - - if ((point - ep).squaredNorm() < limit_sq) { - SurfaceFeature local_f(ep); - local_f.origin_surface_feature = std::make_shared(local_f); - local_f.translate(world_tran); - return std::make_optional(local_f); - } + SurfaceFeature f_tran(f); + f_tran.origin_surface_feature = std::make_shared(f); + f_tran.translate(world_tran); + return std::make_optional(f_tran); } - SurfaceFeature f_tran(f); - f_tran.origin_surface_feature = std::make_shared(f); - f_tran.translate(world_tran); - return std::make_optional(f_tran); } // Nothing detected, return the plane as a whole. @@ -646,8 +648,12 @@ Measuring::~Measuring() {} -std::optional Measuring::get_feature(size_t face_idx, const Vec3d &point, const Transform3d &world_tran) const { - return priv->get_feature(face_idx, point,world_tran); +std::optional Measuring::get_feature(size_t face_idx, const Vec3d &point, const Transform3d &world_tran, bool only_select_plane) const +{ + if (face_idx == 7516 || face_idx == 7517) { + std::cout << ""; + } + return priv->get_feature(face_idx, point, world_tran, only_select_plane); } @@ -1005,7 +1011,7 @@ MeasurementResult get_measurement(const SurfaceFeature &a, const SurfaceFeature const auto [c0, r0, n0] = f1.get_circle(); const auto [c1, r1, n1] = f2.get_circle(); - // The following code is an adaptation of the algorithm found in: + // The following code is an adaptation of the algorithm found in: // https://github.com/davideberly/GeometricTools/blob/master/GTE/Mathematics/DistCircle3Circle3.h // and described in: // https://www.geometrictools.com/Documentation/DistanceToCircle3.pdf @@ -1224,7 +1230,7 @@ MeasurementResult get_measurement(const SurfaceFeature &a, const SurfaceFeature const double dist = (c0 - c1).norm(); result.distance_strict = std::make_optional(DistAndPoints{dist, c0, c1}); } - + /////////////////////////////////////////////////////////////////////////// } else if (f2.get_type() == SurfaceFeatureType::Plane) { const auto [center, radius, normal1] = f1.get_circle(); @@ -1374,7 +1380,7 @@ void SurfaceFeature::translate(const Vec3d& displacement) { } } -void SurfaceFeature::translate(const Transform3d &tran) +void SurfaceFeature::translate(const Transform3d &tran) { switch (get_type()) { case Measure::SurfaceFeatureType::Point: { diff --git a/src/libslic3r/Measure.hpp b/src/libslic3r/Measure.hpp index 5b0acf1d8..bc6b811e7 100644 --- a/src/libslic3r/Measure.hpp +++ b/src/libslic3r/Measure.hpp @@ -129,7 +129,7 @@ public: // Given a face_idx where the mouse cursor points, return a feature that // should be highlighted (if any). - std::optional get_feature(size_t face_idx, const Vec3d& point, const Transform3d & world_tran) const; + std::optional get_feature(size_t face_idx, const Vec3d& point, const Transform3d & world_tran,bool only_select_plane) const; // Return total number of planes. int get_num_of_planes() const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index 95d2116f8..0e063ada4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -472,6 +472,7 @@ void GLGizmoMeasure::on_set_state() m_mode = EMode::FeatureSelection; m_hover_id = -1; m_show_reset_first_tip = false; + m_only_select_plane = false; m_distance = Vec3d::Zero(); } } @@ -669,7 +670,8 @@ void GLGizmoMeasure::on_render() std::optional curr_feature = std::nullopt; if (m_curr_measuring) { curr_feature = wxGetMouseState().LeftIsDown() ? m_curr_feature : - mouse_on_object ? m_curr_measuring->get_feature(model_facet_idx, position_on_model, m_mesh_raycaster_map[m_last_hit_volume]->world_tran.get_matrix()) : + mouse_on_object ? m_curr_measuring->get_feature(model_facet_idx, position_on_model, + m_mesh_raycaster_map[m_last_hit_volume]->world_tran.get_matrix(), m_only_select_plane) : std::nullopt; } if (m_measure_mode == EMeasureMode::ONLY_ASSEMBLY) { @@ -1802,6 +1804,7 @@ void GLGizmoMeasure::show_selection_ui() const float feature_first_text_length = ImGui::CalcTextSize((_u8L(feature_first_text)).c_str()).x; ImGui::AlignTextToFramePadding(); if (m_measure_mode == EMeasureMode::ONLY_ASSEMBLY) { + m_only_select_plane = m_assembly_mode == AssemblyMode::FACE_FACE ? true : false; if (m_assembly_mode == AssemblyMode::FACE_FACE) { m_imgui->text(_u8L("Select 2 faces on objects and \n make objects assemble together.")); // tip } else if (m_assembly_mode == AssemblyMode::POINT_POINT) { @@ -2441,11 +2444,11 @@ void GLGizmoMeasure::set_distance(bool same_model_object, const Vec3d &displacem m_pending_scale ++; if (same_model_object == false) { auto object_displacement = v->get_instance_transformation().get_matrix_no_offset().inverse() * displacement; - selection->translate(v->object_idx(), v->instance_idx(), object_displacement); + v->set_instance_transformation(v->get_instance_transformation().get_matrix() * Geometry::translation_transform(object_displacement)); } else { Geometry::Transformation tran(v->world_matrix()); auto local_displacement = tran.get_matrix_no_offset().inverse() * displacement; - selection->translate(v->object_idx(), v->instance_idx(), v->volume_idx(), local_displacement); + v->set_volume_transformation(v->get_volume_transformation().get_matrix() * Geometry::translation_transform(local_displacement)); } wxGetApp().plater()->canvas3D()->do_move(""); register_single_mesh_pick(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp index 5d5193657..b8140cb6b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp @@ -297,6 +297,7 @@ protected: float m_space_size; float m_input_size_max; bool m_use_inches; + bool m_only_select_plane{false}; std::string m_units; mutable bool m_same_model_object; mutable unsigned int m_current_active_imgui_id;