Measuring: Added features selection in GLGizmoMeasure

This commit is contained in:
enricoturri1966 2022-09-02 11:24:06 +02:00
parent c6e6c86627
commit c5532b175e
3 changed files with 297 additions and 130 deletions

View File

@ -107,7 +107,11 @@ struct MeasurementResult {
std::optional<double> angle; std::optional<double> angle;
std::optional<double> distance_infinite; std::optional<double> distance_infinite;
std::optional<double> distance_strict; std::optional<double> distance_strict;
std::optional<Vec3d> distance_xyz; std::optional<Vec3d> distance_xyz;
bool has_any_data() const {
return angle.has_value() || distance_infinite.has_value() || distance_strict.has_value() || distance_xyz.has_value();
}
}; };
// Returns distance/angle between two SurfaceFeatures. // Returns distance/angle between two SurfaceFeatures.

View File

@ -31,9 +31,8 @@ std::string surface_feature_type_as_string(Slic3r::Measure::SurfaceFeatureType t
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
static const Slic3r::ColorRGBA BASIC_HOVER_COLOR = { 0.8f, 0.2f, 0.2f, 1.0f }; static const Slic3r::ColorRGBA SELECTED_1ST_COLOR = { 0.25f, 0.75f, 0.75f, 1.0f };
static const Slic3r::ColorRGBA EXTENDED_HOVER_COLOR = { 0.8f, 0.8f, 0.2f, 1.0f }; static const Slic3r::ColorRGBA SELECTED_2ND_COLOR = { 0.75f, 0.25f, 0.75f, 1.0f };
static const Slic3r::ColorRGBA LOCK_COLOR = { 0.5f, 0.5f, 0.5f, 1.0f };
static const int POINT_ID = 100; static const int POINT_ID = 100;
static const int EDGE_ID = 200; static const int EDGE_ID = 200;
@ -95,7 +94,23 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event)
} }
else if (mouse_event.LeftDown()) { else if (mouse_event.LeftDown()) {
if (m_hover_id != -1) { if (m_hover_id != -1) {
m_mouse_left_down = true; m_mouse_left_down = true;
auto set_item_from_feature = [this]() {
const SelectedFeatures::Item item = { m_mode, (m_mode == EMode::ExtendedSelection) ?
Measure::SurfaceFeature(Measure::SurfaceFeatureType::Point, *m_curr_ex_feature_position, Vec3d::Zero(), std::nullopt, 0.0) :
m_curr_feature };
return item;
};
if (m_selected_features.first.feature.has_value()) {
const SelectedFeatures::Item item = set_item_from_feature();
if (m_selected_features.first != item)
m_selected_features.second = item;
}
else
m_selected_features.first = set_item_from_feature();
return true; return true;
} }
@ -103,7 +118,6 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event)
// take responsibility for left up // take responsibility for left up
if (m_parent.get_first_hover_volume_idx() >= 0) if (m_parent.get_first_hover_volume_idx() >= 0)
m_mouse_left_down = true; m_mouse_left_down = true;
} }
else if (mouse_event.LeftUp()) { else if (mouse_event.LeftUp()) {
if (m_mouse_left_down) { if (m_mouse_left_down) {
@ -133,6 +147,7 @@ void GLGizmoMeasure::data_changed()
m_last_inv_zoom = 0.0f; m_last_inv_zoom = 0.0f;
m_last_plane_idx = -1; m_last_plane_idx = -1;
m_selected_features.reset();
} }
bool GLGizmoMeasure::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) bool GLGizmoMeasure::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down)
@ -321,13 +336,13 @@ void GLGizmoMeasure::on_render()
} }
} }
if (!m_curr_feature.has_value()) if (!m_curr_feature.has_value() && !m_selected_features.first.feature.has_value())
return; return;
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
if (shader == nullptr) if (shader == nullptr)
return; return;
shader->start_using(); shader->start_using();
shader->set_uniform("emission_factor", 0.25f); shader->set_uniform("emission_factor", 0.25f);
shader->set_uniform("projection_matrix", camera.get_projection_matrix()); shader->set_uniform("projection_matrix", camera.get_projection_matrix());
@ -337,13 +352,6 @@ void GLGizmoMeasure::on_render()
const Transform3d& view_matrix = camera.get_view_matrix(); const Transform3d& view_matrix = camera.get_view_matrix();
ColorRGBA feature_color;
switch (m_mode)
{
case EMode::BasicSelection: { feature_color = BASIC_HOVER_COLOR; break; }
case EMode::ExtendedSelection: { feature_color = LOCK_COLOR; break; }
}
auto set_matrix_uniforms = [shader, &view_matrix](const Transform3d& model_matrix) { auto set_matrix_uniforms = [shader, &view_matrix](const Transform3d& model_matrix) {
const Transform3d view_model_matrix = view_matrix * model_matrix; const Transform3d view_model_matrix = view_matrix * model_matrix;
shader->set_uniform("view_model_matrix", view_model_matrix); shader->set_uniform("view_model_matrix", view_model_matrix);
@ -351,76 +359,143 @@ void GLGizmoMeasure::on_render()
shader->set_uniform("view_normal_matrix", view_normal_matrix); shader->set_uniform("view_normal_matrix", view_normal_matrix);
}; };
switch (m_curr_feature->get_type()) auto render_feature = [this, set_matrix_uniforms](const Measure::SurfaceFeature& feature, const std::vector<ColorRGBA>& colors,
{ const Transform3d& model_matrix, float inv_zoom, bool update_raycasters) {
default: { assert(false); break; } switch (feature.get_type())
case Measure::SurfaceFeatureType::Point: {
{ default: { assert(false); break; }
const Vec3d& position = m_curr_feature->get_point(); case Measure::SurfaceFeatureType::Point:
const Transform3d feature_matrix = model_matrix * Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom); {
set_matrix_uniforms(feature_matrix); const Vec3d& position = feature.get_point();
m_sphere.model.set_color(is_hovering_on_extended_selection ? EXTENDED_HOVER_COLOR : feature_color); const Transform3d feature_matrix = model_matrix * Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom);
m_sphere.model.render(); set_matrix_uniforms(feature_matrix);
auto it = m_raycasters.find(POINT_ID); m_sphere.model.set_color(colors.front());
if (it != m_raycasters.end() && it->second != nullptr) m_sphere.model.render();
it->second->set_transform(feature_matrix); if (update_raycasters) {
break; auto it = m_raycasters.find(POINT_ID);
} if (it != m_raycasters.end() && it->second != nullptr)
case Measure::SurfaceFeatureType::Circle: it->second->set_transform(feature_matrix);
{ }
const auto& [center, radius, n] = m_curr_feature->get_circle(); break;
// render center }
const Transform3d center_matrix = model_matrix * Geometry::translation_transform(center) * Geometry::scale_transform(inv_zoom); case Measure::SurfaceFeatureType::Circle:
set_matrix_uniforms(center_matrix); {
m_sphere.model.set_color((is_hovering_on_extended_selection && m_hover_id == POINT_ID) ? EXTENDED_HOVER_COLOR : feature_color); const auto& [center, radius, n] = feature.get_circle();
m_sphere.model.render(); // render center
auto it = m_raycasters.find(POINT_ID); const Transform3d center_matrix = model_matrix * Geometry::translation_transform(center) * Geometry::scale_transform(inv_zoom);
if (it != m_raycasters.end() && it->second != nullptr) set_matrix_uniforms(center_matrix);
it->second->set_transform(center_matrix); m_sphere.model.set_color(colors.front());
m_sphere.model.render();
if (update_raycasters) {
auto it = m_raycasters.find(POINT_ID);
if (it != m_raycasters.end() && it->second != nullptr)
it->second->set_transform(center_matrix);
}
// render circle
const Transform3d circle_matrix = model_matrix * Geometry::translation_transform(center);
set_matrix_uniforms(circle_matrix);
m_circle.model.set_color(colors.back());
m_circle.model.render();
if (update_raycasters) {
auto it = m_raycasters.find(CIRCLE_ID);
if (it != m_raycasters.end() && it->second != nullptr)
it->second->set_transform(circle_matrix);
}
break;
}
case Measure::SurfaceFeatureType::Edge:
{
const auto& [start, end] = feature.get_edge();
auto q = Eigen::Quaternion<double>::FromTwoVectors(Vec3d::UnitZ(), end - start);
const Transform3d feature_matrix = model_matrix * Geometry::translation_transform(start) * q *
Geometry::scale_transform({ (double)inv_zoom, (double)inv_zoom, (end - start).norm() });
set_matrix_uniforms(feature_matrix);
m_cylinder.model.set_color(colors.front());
m_cylinder.model.render();
if (update_raycasters) {
auto it = m_raycasters.find(EDGE_ID);
if (it != m_raycasters.end() && it->second != nullptr)
it->second->set_transform(feature_matrix);
}
break;
}
case Measure::SurfaceFeatureType::Plane:
{
const auto& [idx, normal, pt] = feature.get_plane();
assert(idx < m_plane_models_cache.size());
set_matrix_uniforms(model_matrix);
m_plane_models_cache[idx].set_color(colors.front());
m_plane_models_cache[idx].render();
if (update_raycasters) {
auto it = m_raycasters.find(PLANE_ID);
if (it != m_raycasters.end() && it->second != nullptr)
it->second->set_transform(model_matrix);
}
break;
}
}
};
// render circle auto hover_selection_color = [this]() {
const Transform3d circle_matrix = model_matrix * Geometry::translation_transform(center); return saturate(!m_selected_features.first.feature.has_value() ? SELECTED_1ST_COLOR : SELECTED_2ND_COLOR, 1.5f);
set_matrix_uniforms(circle_matrix); };
m_circle.model.set_color(feature_color);
m_circle.model.render(); auto hovering_color = [this, hover_selection_color, &selection]() {
it = m_raycasters.find(CIRCLE_ID); return (m_mode == EMode::ExtendedSelection) ? selection.get_first_volume()->render_color : hover_selection_color();
if (it != m_raycasters.end() && it->second != nullptr) };
it->second->set_transform(circle_matrix);
break; if (m_curr_feature.has_value()) {
std::vector<ColorRGBA> colors;
if (m_selected_features.first.feature.has_value() && *m_curr_feature == *m_selected_features.first.feature)
colors.emplace_back(SELECTED_1ST_COLOR);
else if (m_selected_features.second.feature.has_value() && *m_curr_feature == *m_selected_features.second.feature)
colors.emplace_back(SELECTED_2ND_COLOR);
else {
switch (m_curr_feature->get_type())
{
default: { assert(false); break; }
case Measure::SurfaceFeatureType::Point:
{
colors.emplace_back(hover_selection_color());
break;
}
case Measure::SurfaceFeatureType::Circle:
{
colors.emplace_back((m_hover_id == POINT_ID) ? hover_selection_color() : hovering_color());
colors.emplace_back(hovering_color());
break;
}
case Measure::SurfaceFeatureType::Edge:
case Measure::SurfaceFeatureType::Plane:
{
colors.emplace_back(hovering_color());
break;
}
}
}
render_feature(*m_curr_feature, colors, model_matrix, inv_zoom, true);
} }
case Measure::SurfaceFeatureType::Edge:
{ if (m_selected_features.first.feature.has_value() && (!m_curr_feature.has_value() || *m_curr_feature != *m_selected_features.first.feature)) {
const auto& [start, end] = m_curr_feature->get_edge(); std::vector<ColorRGBA> colors;
auto q = Eigen::Quaternion<double>::FromTwoVectors(Vec3d::UnitZ(), end - start); colors.emplace_back(SELECTED_1ST_COLOR);
const Transform3d feature_matrix = model_matrix * Geometry::translation_transform(start) * q * render_feature(*m_selected_features.first.feature, colors,
Geometry::scale_transform({ (double)inv_zoom, (double)inv_zoom, (end - start).norm() }); (m_selected_features.first.mode == EMode::BasicSelection) ? model_matrix : Transform3d::Identity(), inv_zoom, false);
set_matrix_uniforms(feature_matrix);
m_cylinder.model.set_color(feature_color);
m_cylinder.model.render();
auto it = m_raycasters.find(EDGE_ID);
if (it != m_raycasters.end() && it->second != nullptr)
it->second->set_transform(feature_matrix);
break;
}
case Measure::SurfaceFeatureType::Plane:
{
const auto& [idx, normal, pt] = m_curr_feature->get_plane();
assert(idx < m_plane_models_cache.size());
set_matrix_uniforms(model_matrix);
m_plane_models_cache[idx].set_color(feature_color);
m_plane_models_cache[idx].render();
auto it = m_raycasters.find(PLANE_ID);
if (it != m_raycasters.end() && it->second != nullptr)
it->second->set_transform(model_matrix);
break;
} }
if (m_selected_features.second.feature.has_value() && (!m_curr_feature.has_value() || *m_curr_feature != *m_selected_features.second.feature)) {
std::vector<ColorRGBA> colors;
colors.emplace_back(SELECTED_2ND_COLOR);
render_feature(*m_selected_features.second.feature, colors,
(m_selected_features.second.mode == EMode::BasicSelection) ? model_matrix : Transform3d::Identity(), inv_zoom, false);
} }
if (is_hovering_on_extended_selection && m_curr_ex_feature_position.has_value()) { if (is_hovering_on_extended_selection && m_curr_ex_feature_position.has_value()) {
if (m_hover_id != POINT_ID) { if (m_hover_id != POINT_ID) {
const Transform3d matrix = Geometry::translation_transform(*m_curr_ex_feature_position) * Geometry::scale_transform(inv_zoom); const Transform3d matrix = Geometry::translation_transform(*m_curr_ex_feature_position) * Geometry::scale_transform(inv_zoom);
set_matrix_uniforms(matrix); set_matrix_uniforms(matrix);
m_sphere.model.set_color(EXTENDED_HOVER_COLOR); m_sphere.model.set_color(hover_selection_color());
// m_sphere.model.set_color(EXTENDED_HOVER_COLOR);
m_sphere.model.render(); m_sphere.model.render();
} }
} }
@ -496,6 +571,7 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
{ {
static std::optional<Measure::SurfaceFeature> last_feature; static std::optional<Measure::SurfaceFeature> last_feature;
static EMode last_mode = EMode::BasicSelection; static EMode last_mode = EMode::BasicSelection;
static SelectedFeatures last_selected_features;
static float last_y = 0.0f; static float last_y = 0.0f;
static float last_h = 0.0f; static float last_h = 0.0f;
@ -515,18 +591,20 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
last_y = y; last_y = y;
} }
auto add_row_to_table = [this](const wxString& label, const std::string& value) { auto add_row_to_table = [this](const std::string& label, const ImVec4& label_color, const std::string& value, const ImVec4& value_color) {
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0); ImGui::TableSetColumnIndex(0);
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, label); m_imgui->text_colored(label_color, label);
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
m_imgui->text(value); m_imgui->text_colored(value_color, value);
}; };
auto format_double = [](double value) { auto format_double = [](double value) {
char buf[1024]; char buf[1024];
sprintf(buf, "%.3f", value); sprintf(buf, "%.3f", value);
return std::string(buf); return std::string(buf);
}; };
auto format_vec3 = [](const Vec3d& v) { auto format_vec3 = [](const Vec3d& v) {
char buf[1024]; char buf[1024];
sprintf(buf, "X: %.3f, Y: %.3f, Z: %.3f", v.x(), v.y(), v.z()); sprintf(buf, "X: %.3f, Y: %.3f, Z: %.3f", v.x(), v.y(), v.z());
@ -534,9 +612,10 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
}; };
if (ImGui::BeginTable("Commands", 2)) { if (ImGui::BeginTable("Commands", 2)) {
add_row_to_table(_u8L("Left mouse button"), (m_mode == EMode::BasicSelection) ? _u8L("Select feature") : _u8L("Select point")); add_row_to_table(_u8L("Left mouse button"), ImGuiWrapper::COL_ORANGE_LIGHT,
(m_mode == EMode::BasicSelection) ? _u8L("Select feature") : _u8L("Select point"), ImGui::GetStyleColorVec4(ImGuiCol_Text));
if (m_mode == EMode::BasicSelection && m_hover_id != -1) if (m_mode == EMode::BasicSelection && m_hover_id != -1)
add_row_to_table(CTRL_STR, _u8L("Enable point selection")); add_row_to_table(CTRL_STR, ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Enable point selection"), ImGui::GetStyleColorVec4(ImGuiCol_Text));
ImGui::EndTable(); ImGui::EndTable();
} }
@ -545,48 +624,49 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
const Measure::SurfaceFeatureType feature_type = m_curr_feature->get_type(); const Measure::SurfaceFeatureType feature_type = m_curr_feature->get_type();
if (m_mode == EMode::BasicSelection) { if (m_mode == EMode::BasicSelection) {
if (feature_type != Measure::SurfaceFeatureType::Undef) { if (feature_type != Measure::SurfaceFeatureType::Undef) {
if (ImGui::CollapsingHeader(surface_feature_type_as_string(feature_type).c_str(), ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::Separator();
if (ImGui::BeginTable("Data", 2)) { m_imgui->text(surface_feature_type_as_string(feature_type) + ":");
switch (feature_type) if (ImGui::BeginTable("Data", 2)) {
{ switch (feature_type)
default: { assert(false); break; } {
case Measure::SurfaceFeatureType::Point: default: { assert(false); break; }
{ case Measure::SurfaceFeatureType::Point:
const Vec3d position = volume_matrix * m_curr_feature->get_point(); {
add_row_to_table(_u8L("Position") + ":", format_vec3(position)); const Vec3d position = volume_matrix * m_curr_feature->get_point();
break; add_row_to_table(_u8L("Position"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(position), ImGui::GetStyleColorVec4(ImGuiCol_Text));
} break;
case Measure::SurfaceFeatureType::Edge:
{
auto [from, to] = m_curr_feature->get_edge();
from = volume_matrix * from;
to = volume_matrix * to;
add_row_to_table(_u8L("From") + ":", format_vec3(from));
add_row_to_table(_u8L("To") + ":", format_vec3(to));
break;
}
case Measure::SurfaceFeatureType::Circle:
{
auto [center, radius, normal] = m_curr_feature->get_circle();
center = volume_matrix * center;
normal = volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal;
add_row_to_table(_u8L("Center") + ":", format_vec3(center));
add_row_to_table(_u8L("Radius") + ":", format_double(radius));
add_row_to_table(_u8L("Normal") + ":", format_vec3(normal));
break;
}
case Measure::SurfaceFeatureType::Plane:
{
auto [idx, normal, origin] = m_curr_feature->get_plane();
origin = volume_matrix * origin;
normal = volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal;
add_row_to_table(_u8L("Origin") + ":", format_vec3(origin));
add_row_to_table(_u8L("Normal") + ":", format_vec3(normal));
break;
}
}
ImGui::EndTable();
} }
case Measure::SurfaceFeatureType::Edge:
{
auto [from, to] = m_curr_feature->get_edge();
from = volume_matrix * from;
to = volume_matrix * to;
add_row_to_table(_u8L("From"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(from), ImGui::GetStyleColorVec4(ImGuiCol_Text));
add_row_to_table(_u8L("To"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(to), ImGui::GetStyleColorVec4(ImGuiCol_Text));
add_row_to_table(_u8L("Length") + _u8L(" (mm)"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double((to - from).norm()), ImGui::GetStyleColorVec4(ImGuiCol_Text));
break;
}
case Measure::SurfaceFeatureType::Circle:
{
auto [center, radius, normal] = m_curr_feature->get_circle();
center = volume_matrix * center;
normal = volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal;
add_row_to_table(_u8L("Center"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(center), ImGui::GetStyleColorVec4(ImGuiCol_Text));
add_row_to_table(_u8L("Radius") + _u8L(" (mm)"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double(radius), ImGui::GetStyleColorVec4(ImGuiCol_Text));
add_row_to_table(_u8L("Normal"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text));
break;
}
case Measure::SurfaceFeatureType::Plane:
{
auto [idx, normal, origin] = m_curr_feature->get_plane();
origin = volume_matrix * origin;
normal = volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal;
add_row_to_table(_u8L("Origin"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(origin), ImGui::GetStyleColorVec4(ImGuiCol_Text));
add_row_to_table(_u8L("Normal"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text));
break;
}
}
ImGui::EndTable();
} }
} }
} }
@ -601,20 +681,68 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
default: { assert(false); break; } default: { assert(false); break; }
} }
if (ImGui::CollapsingHeader(header.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::Separator();
if (ImGui::BeginTable("Data", 2)) { m_imgui->text(header + ":");
add_row_to_table(_u8L("Position") + ":", format_vec3(*m_curr_ex_feature_position)); if (ImGui::BeginTable("Data", 2)) {
ImGui::EndTable(); add_row_to_table(_u8L("Position"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(*m_curr_ex_feature_position),
} ImGui::GetStyleColorVec4(ImGuiCol_Text));
ImGui::EndTable();
} }
} }
} }
} }
if (last_feature != m_curr_feature || last_mode != m_mode) { ImGui::Separator();
m_imgui->text(_u8L("Selection"));
if (ImGui::BeginTable("Selection", 2)) {
add_row_to_table("1", ImGuiWrapper::to_ImVec4(SELECTED_1ST_COLOR), m_selected_features.first.feature.has_value() ?
surface_feature_type_as_string(m_selected_features.first.feature->get_type()) : _u8L("None"), ImGuiWrapper::to_ImVec4(SELECTED_1ST_COLOR));
add_row_to_table("2", ImGuiWrapper::to_ImVec4(SELECTED_2ND_COLOR), m_selected_features.second.feature.has_value() ?
surface_feature_type_as_string(m_selected_features.second.feature->get_type()) : _u8L("None"), ImGuiWrapper::to_ImVec4(SELECTED_2ND_COLOR));
ImGui::EndTable();
}
if (m_selected_features.first.feature.has_value()) {
if (m_imgui->button(_u8L("Restart"))) {
m_selected_features.reset();
m_imgui->set_requires_extra_frame();
}
}
if (m_selected_features.second.feature.has_value()) {
const Measure::MeasurementResult measure = Measure::get_measurement(*m_selected_features.first.feature, *m_selected_features.second.feature);
ImGui::Separator();
if (measure.has_any_data()) {
m_imgui->text(_u8L("Measure"));
if (ImGui::BeginTable("Measure", 2)) {
if (measure.angle.has_value()) {
add_row_to_table(_u8L("Angle") + _u8L(" (°)"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double(Geometry::rad2deg(*measure.angle)),
ImGui::GetStyleColorVec4(ImGuiCol_Text));
}
if (measure.distance_infinite.has_value()) {
add_row_to_table(_u8L("Distance Infinite") + _u8L(" (mm)"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double(*measure.distance_infinite),
ImGui::GetStyleColorVec4(ImGuiCol_Text));
}
if (measure.distance_strict.has_value()) {
add_row_to_table(_u8L("Distance Strict") + _u8L(" (mm)"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double(*measure.distance_strict),
ImGui::GetStyleColorVec4(ImGuiCol_Text));
}
if (measure.distance_xyz.has_value()) {
add_row_to_table(_u8L("Distance XYZ") + _u8L(" (mm)"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(*measure.distance_xyz),
ImGui::GetStyleColorVec4(ImGuiCol_Text));
}
ImGui::EndTable();
}
}
else
m_imgui->text(_u8L("No measure available"));
}
if (last_feature != m_curr_feature || last_mode != m_mode || last_selected_features != m_selected_features) {
// the dialog may have changed its size, ask for an extra frame to render it properly // the dialog may have changed its size, ask for an extra frame to render it properly
last_feature = m_curr_feature; last_feature = m_curr_feature;
last_mode = m_mode; last_mode = m_mode;
last_selected_features = m_selected_features;
m_imgui->set_requires_extra_frame(); m_imgui->set_requires_extra_frame();
} }

View File

@ -23,14 +23,47 @@ enum class SLAGizmoEventType : unsigned char;
class GLGizmoMeasure : public GLGizmoBase class GLGizmoMeasure : public GLGizmoBase
{ {
// This gizmo does not use grabbers. The m_hover_id relates to polygon managed by the class itself.
enum class EMode : unsigned char enum class EMode : unsigned char
{ {
BasicSelection, BasicSelection,
ExtendedSelection ExtendedSelection
}; };
struct SelectedFeatures
{
struct Item
{
EMode mode{ EMode::BasicSelection };
std::optional<Measure::SurfaceFeature> feature;
bool operator == (const Item& other) const {
if (this->mode != other.mode) return false;
return this->feature == other.feature;
}
bool operator != (const Item& other) const {
return !operator == (other);
}
};
Item first;
Item second;
void reset() {
first.feature.reset();
second.feature.reset();
}
bool operator == (const SelectedFeatures& other) const {
if (this->first != other.first) return false;
return this->second == other.second;
}
bool operator != (const SelectedFeatures& other) const {
return !operator == (other);
}
};
EMode m_mode{ EMode::BasicSelection }; EMode m_mode{ EMode::BasicSelection };
std::unique_ptr<Measure::Measuring> m_measuring; std::unique_ptr<Measure::Measuring> m_measuring;
@ -60,6 +93,8 @@ class GLGizmoMeasure : public GLGizmoBase
KeyAutoRepeatFilter m_ctrl_kar_filter; KeyAutoRepeatFilter m_ctrl_kar_filter;
SelectedFeatures m_selected_features;
void update_if_needed(); void update_if_needed();
public: public: