FIX:very small face can't be selected in assembly gizmo

jira: STUDIO-7594
Change-Id: Ibc2f0e80b9d5ef20de6997527b0dde09aee8d32b
This commit is contained in:
zhou.xu 2024-07-15 15:13:28 +08:00 committed by Lane.Wei
parent 2a7ee65e8b
commit 85aa6fddfc
4 changed files with 59 additions and 49 deletions

View File

@ -93,7 +93,7 @@ public:
bool features_extracted = false;
};
std::optional<SurfaceFeature> get_feature(size_t face_idx, const Vec3d& point, const Transform3d &world_tran);
std::optional<SurfaceFeature> 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<int>& get_plane_triangle_indices(int idx) const;
std::vector<int>* get_plane_tri_indices(int idx);
@ -526,7 +526,7 @@ void MeasuringImpl::extract_features(int plane_idx)
plane.features_extracted = true;
}
std::optional<SurfaceFeature> MeasuringImpl::get_feature(size_t face_idx, const Vec3d& point, const Transform3d &world_tran)
std::optional<SurfaceFeature> 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<SurfaceFeature>();
@ -544,46 +544,48 @@ std::optional<SurfaceFeature> 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; 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 (!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<SurfaceFeature>(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<SurfaceFeature>(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<SurfaceFeature>(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<SurfaceFeature>(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<SurfaceFeature>(f);
f_tran.translate(world_tran);
return std::make_optional(f_tran);
}
SurfaceFeature f_tran(f);
f_tran.origin_surface_feature = std::make_shared<SurfaceFeature>(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<SurfaceFeature> 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<SurfaceFeature> 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);
}

View File

@ -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<SurfaceFeature> get_feature(size_t face_idx, const Vec3d& point, const Transform3d & world_tran) const;
std::optional<SurfaceFeature> 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;

View File

@ -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<Measure::SurfaceFeature> 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();

View File

@ -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;