From 706e7ea81e7e1484b8a4fb7d60f01698e0ee5895 Mon Sep 17 00:00:00 2001 From: denizdiktas Date: Thu, 17 Aug 2023 15:37:33 +0300 Subject: [PATCH] refactor: moved country picking to a separate class --- .../demo/earth/CMakeLists.txt | 11 +- .../demo/earth/GUI_country_pick_handler.cpp | 117 ++++++++++++ .../demo/earth/GUI_country_pick_handler.h | 35 ++++ .../demo/earth/Main_widget.cpp | 167 +++++++++++------- .../demo/earth/Main_widget.h | 15 +- 5 files changed, 272 insertions(+), 73 deletions(-) create mode 100644 Arrangement_on_surface_2/demo/earth/GUI_country_pick_handler.cpp create mode 100644 Arrangement_on_surface_2/demo/earth/GUI_country_pick_handler.h diff --git a/Arrangement_on_surface_2/demo/earth/CMakeLists.txt b/Arrangement_on_surface_2/demo/earth/CMakeLists.txt index d7aee6618ba..3760a72aace 100644 --- a/Arrangement_on_surface_2/demo/earth/CMakeLists.txt +++ b/Arrangement_on_surface_2/demo/earth/CMakeLists.txt @@ -88,11 +88,12 @@ source_group( "Graphics_Geometry" FILES ${source_files_graphics_geometry} ) # GUI file(GLOB source_files_gui - Camera_manip.h Camera_manip.cpp - Camera_manip_rot.h Camera_manip_rot.cpp - Camera_manip_rot_bpa.h Camera_manip_rot_bpa.cpp - Camera_manip_zoom.h Camera_manip_zoom.cpp - GUI_event_handler.h GUI_event_handler.cpp + Camera_manip.h Camera_manip.cpp + Camera_manip_rot.h Camera_manip_rot.cpp + Camera_manip_rot_bpa.h Camera_manip_rot_bpa.cpp + Camera_manip_zoom.h Camera_manip_zoom.cpp + GUI_country_pick_handler.h GUI_country_pick_handler.cpp + GUI_event_handler.h GUI_event_handler.cpp ) source_group( "GUI" FILES ${source_files_gui} ) diff --git a/Arrangement_on_surface_2/demo/earth/GUI_country_pick_handler.cpp b/Arrangement_on_surface_2/demo/earth/GUI_country_pick_handler.cpp new file mode 100644 index 00000000000..9ec6488bc53 --- /dev/null +++ b/Arrangement_on_surface_2/demo/earth/GUI_country_pick_handler.cpp @@ -0,0 +1,117 @@ +// Copyright(c) 2012, 2020 Tel - Aviv University(Israel). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s): Engin Deniz Diktas + +#include "GUI_country_pick_handler.h" + +//#include + + +GUI_country_pick_handler::GUI_country_pick_handler(Main_widget& main_widget) : + m_main_widget(main_widget), + m_camera(main_widget.get_camera()) +{ + +} + +void GUI_country_pick_handler::mouse_press_event(QMouseEvent* e) +{ + // handle country selection + if (e->button() == Qt::RightButton) + { + auto p = e->pos(); + QVector3D sp0(p.x(), m_vp_height - p.y(), 0); + QVector3D sp1(p.x(), m_vp_height - p.y(), 1); + + auto proj = m_camera.get_projection_matrix(); + auto view = m_camera.get_view_matrix(); + auto model_view = view * m_main_widget.get_model_matrix(); + QRect viewport(0, 0, m_vp_width, m_vp_height); + auto wp0 = sp0.unproject(model_view, proj, viewport); + auto wp1 = sp1.unproject(model_view, proj, viewport); + + // ASSERTION!!! + m_main_widget.set_mouse_pos(wp0); + + // define a ray from the camera pos to the world-point + //auto o = m_camera.get_pos(); + //auto u = wp - o; + auto o = wp0; + auto u = wp1 - wp0; + + // solve the quadratic equation to check for intersection of ray with sphere + auto a = QVector3D::dotProduct(u, u); + auto b = 2 * QVector3D::dotProduct(u, o); + auto c = QVector3D::dotProduct(o, o) - 1; + auto d = b * b - 4 * a * c; + + float ti = -1; + if (abs(d) < std::numeric_limits::epsilon()) + { + // single intersection + ti = -b / (2 * a); + } + else + { + if (d < 0) + { + // no intersection + return; + } + else + { + // two intersections + auto sd = sqrt(d); + auto t1 = (-b - sd) / (2 * a); + auto t2 = (-b + sd) / (2 * a); + if (t1 > 0 && t2 > 0) + ti = std::min(t1, t2); + else if (t1 > 0) + ti = t1; + else + ti = t2; + } + } + + //m_mouse_pos = o + ti * u; + auto pos = o + ti * u; + m_main_widget.set_mouse_pos(pos); + static std::string prev_picked_country; + auto& arrh = m_main_widget.get_arr_handle(); + auto picked_country = Aos::locate_country(arrh, pos); + + m_main_widget.hightlight_country(picked_country); + // if (!prev_picked_country.empty()) + // { + // // dim the previous country color + // auto& prev_country = m_country_triangles[prev_picked_country]; + // auto color = prev_country->get_color(); + // color *= s_dimming_factor; + // color.setW(1); + // prev_country->set_color(color); + // } + + // if (!picked_country.empty()) + // { + // // highlight the current country color + // auto& curr_country = m_country_triangles[picked_country]; + // auto color = curr_country->get_color(); + // color /= s_dimming_factor; + // color.setW(1); + // curr_country->set_color(color); + // qDebug() << "SELECTED COUNTRY: " << picked_country; + // } + + // prev_picked_country = picked_country; + } +} +void GUI_country_pick_handler::resize(int w, int h) +{ + m_vp_width = w; + m_vp_height = h; +} diff --git a/Arrangement_on_surface_2/demo/earth/GUI_country_pick_handler.h b/Arrangement_on_surface_2/demo/earth/GUI_country_pick_handler.h new file mode 100644 index 00000000000..5ffb2fac3bb --- /dev/null +++ b/Arrangement_on_surface_2/demo/earth/GUI_country_pick_handler.h @@ -0,0 +1,35 @@ +// Copyright(c) 2012, 2020 Tel - Aviv University(Israel). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s): Engin Deniz Diktas + +#ifndef GUI_COUNTRY_PICK_HANDLER_H +#define GUI_COUNTRY_PICK_HANDLER_H + +#include +#include + +#include "GUI_event_handler.h" +#include "Main_widget.h" + + +class GUI_country_pick_handler : public GUI_event_handler +{ +public: + GUI_country_pick_handler(Main_widget& main_widget); + +protected: + virtual void mouse_press_event(QMouseEvent* e) override; + virtual void resize(int w, int h) override; + + Main_widget& m_main_widget; + Camera& m_camera; + int m_vp_width, m_vp_height; +}; + + +#endif diff --git a/Arrangement_on_surface_2/demo/earth/Main_widget.cpp b/Arrangement_on_surface_2/demo/earth/Main_widget.cpp index 7826f835206..3e2afe24044 100644 --- a/Arrangement_on_surface_2/demo/earth/Main_widget.cpp +++ b/Arrangement_on_surface_2/demo/earth/Main_widget.cpp @@ -43,66 +43,94 @@ Main_widget::~Main_widget() void Main_widget::handle_country_picking(QMouseEvent* e) { - // handle country selection - if (e->button() == Qt::RightButton) - { - auto p = e->pos(); - QVector3D sp0(p.x(), m_vp_height - p.y(), 0); - QVector3D sp1(p.x(), m_vp_height - p.y(), 1); - - auto proj = m_camera.get_projection_matrix(); - auto view = m_camera.get_view_matrix(); - auto model_view = view * m_model; - QRect viewport(0, 0, m_vp_width, m_vp_height); - auto wp0 = sp0.unproject(model_view, proj, viewport); - auto wp1 = sp1.unproject(model_view, proj, viewport); - - // ASSERTION!!! - m_mouse_pos = wp0; - - // define a ray from the camera pos to the world-point - //auto o = m_camera.get_pos(); - //auto u = wp - o; - auto o = wp0; - auto u = wp1 - wp0; - - // solve the quadratic equation to check for intersection of ray with sphere - auto a = QVector3D::dotProduct(u, u); - auto b = 2 * QVector3D::dotProduct(u, o); - auto c = QVector3D::dotProduct(o, o) - 1; - auto d = b * b - 4 * a * c; - - float ti = -1; - if (abs(d) < std::numeric_limits::epsilon()) - { - // single intersection - ti = -b / (2 * a); - } - else - { - if (d < 0) - { - // no intersection - return; - } - else - { - // two intersections - auto sd = sqrt(d); - auto t1 = (-b - sd) / (2 * a); - auto t2 = (-b + sd) / (2 * a); - if (t1 > 0 && t2 > 0) - ti = std::min(t1, t2); - else if (t1 > 0) - ti = t1; - else - ti = t2; - } - } - - m_mouse_pos = o + ti * u; - static std::string prev_picked_country; - auto picked_country = Aos::locate_country(m_arrh, m_mouse_pos); + //// handle country selection + //if (e->button() == Qt::RightButton) + //{ + // auto p = e->pos(); + // QVector3D sp0(p.x(), m_vp_height - p.y(), 0); + // QVector3D sp1(p.x(), m_vp_height - p.y(), 1); + + // auto proj = m_camera.get_projection_matrix(); + // auto view = m_camera.get_view_matrix(); + // auto model_view = view * m_model; + // QRect viewport(0, 0, m_vp_width, m_vp_height); + // auto wp0 = sp0.unproject(model_view, proj, viewport); + // auto wp1 = sp1.unproject(model_view, proj, viewport); + + // // ASSERTION!!! + // m_mouse_pos = wp0; + + // // define a ray from the camera pos to the world-point + // //auto o = m_camera.get_pos(); + // //auto u = wp - o; + // auto o = wp0; + // auto u = wp1 - wp0; + + // // solve the quadratic equation to check for intersection of ray with sphere + // auto a = QVector3D::dotProduct(u, u); + // auto b = 2 * QVector3D::dotProduct(u, o); + // auto c = QVector3D::dotProduct(o, o) - 1; + // auto d = b * b - 4 * a * c; + + // float ti = -1; + // if (abs(d) < std::numeric_limits::epsilon()) + // { + // // single intersection + // ti = -b / (2 * a); + // } + // else + // { + // if (d < 0) + // { + // // no intersection + // return; + // } + // else + // { + // // two intersections + // auto sd = sqrt(d); + // auto t1 = (-b - sd) / (2 * a); + // auto t2 = (-b + sd) / (2 * a); + // if (t1 > 0 && t2 > 0) + // ti = std::min(t1, t2); + // else if (t1 > 0) + // ti = t1; + // else + // ti = t2; + // } + // } + + // m_mouse_pos = o + ti * u; + // static std::string prev_picked_country; + // auto picked_country = Aos::locate_country(m_arrh, m_mouse_pos); + + // if (!prev_picked_country.empty()) + // { + // // dim the previous country color + // auto& prev_country = m_country_triangles[prev_picked_country]; + // auto color = prev_country->get_color(); + // color *= s_dimming_factor; + // color.setW(1); + // prev_country->set_color(color); + // } + + // if (!picked_country.empty()) + // { + // // highlight the current country color + // auto& curr_country = m_country_triangles[picked_country]; + // auto color = curr_country->get_color(); + // color /= s_dimming_factor; + // color.setW(1); + // curr_country->set_color(color); + // qDebug() << "SELECTED COUNTRY: " << picked_country; + // } + + // prev_picked_country = picked_country; + //} +} +void Main_widget::hightlight_country(const std::string& country_name) +{ + static std::string prev_picked_country; if (!prev_picked_country.empty()) { @@ -114,38 +142,40 @@ void Main_widget::handle_country_picking(QMouseEvent* e) prev_country->set_color(color); } - if (!picked_country.empty()) + if (!country_name.empty()) { // highlight the current country color - auto& curr_country = m_country_triangles[picked_country]; + auto& curr_country = m_country_triangles[country_name]; auto color = curr_country->get_color(); color /= s_dimming_factor; color.setW(1); curr_country->set_color(color); - qDebug() << "SELECTED COUNTRY: " << picked_country; + qDebug() << "SELECTED COUNTRY: " << country_name; } - prev_picked_country = picked_country; - } + prev_picked_country = country_name; } void Main_widget::mousePressEvent(QMouseEvent* e) { // forward the event to the camera manipulators m_camera_manip_rot->mousePressEvent(e); m_camera_manip_zoom->mousePressEvent(e); - handle_country_picking(e); + m_pick_handler->mousePressEvent(e); + //handle_country_picking(e); } void Main_widget::mouseMoveEvent(QMouseEvent* e) { // forward the event to the camera manipulator m_camera_manip_rot->mouseMoveEvent(e); m_camera_manip_zoom->mouseMoveEvent(e); + m_pick_handler->mouseMoveEvent(e); } void Main_widget::mouseReleaseEvent(QMouseEvent* e) { // forward the event to the camera manipulator m_camera_manip_rot->mouseReleaseEvent(e); m_camera_manip_zoom->mouseReleaseEvent(e); + m_pick_handler->mouseReleaseEvent(e); } void Main_widget::timerEvent(QTimerEvent*) { @@ -227,9 +257,12 @@ void Main_widget::init_problematic_nodes() m_problematic_vertices = std::make_unique(prob_vertices); } +#include "GUI_country_pick_handler.h" void Main_widget::initializeGL() { + m_pick_handler = std::make_unique(*this); + // verify that the node (180.0, -84.71338) in Antarctica is redundant //Verification::verify_antarctica_node_is_redundant(); @@ -335,7 +368,6 @@ void Main_widget::initializeGL() //m_all_triangles = std::make_unique(triangle_points); } - // initialize rendering of DUPLICATE VERTICES if(1) @@ -478,6 +510,7 @@ float Main_widget::compute_backprojected_error(float pixel_error) void Main_widget::resizeGL(int w, int h) { m_camera_manip_rot->resizeGL(w, h); + m_pick_handler->resizeGL(w, h); m_vp_width = w; m_vp_height = h; diff --git a/Arrangement_on_surface_2/demo/earth/Main_widget.h b/Arrangement_on_surface_2/demo/earth/Main_widget.h index ef89044f09f..781b4b9a4da 100644 --- a/Arrangement_on_surface_2/demo/earth/Main_widget.h +++ b/Arrangement_on_surface_2/demo/earth/Main_widget.h @@ -25,6 +25,7 @@ #include "Camera.h" #include "Camera_manip.h" #include "Common_defs.h" +#include "GUI_event_handler.h" #include "Kml_reader.h" #include "Line_strips.h" #include "Shader_program.h" @@ -43,6 +44,15 @@ class Main_widget : public QOpenGLWidget, protected OpenGLFunctionsBase using QOpenGLWidget::QOpenGLWidget; ~Main_widget(); + + auto& get_camera() { return m_camera; } + auto& get_model_matrix() { return m_model; } + auto& get_arr_handle() { return m_arrh; } + + void set_mouse_pos(const QVector3D mouse_pos) { m_mouse_pos = mouse_pos; } + + void hightlight_country(const std::string& country_name); + protected: void mousePressEvent(QMouseEvent* e) override; void mouseMoveEvent(QMouseEvent* e) override; @@ -79,6 +89,9 @@ class Main_widget : public QOpenGLWidget, protected OpenGLFunctionsBase // ARRANGEMENT Aos::Arr_handle m_arrh; + // GUI: event handler for picking with right mouse button + std::unique_ptr m_pick_handler; + // Objects in the scene std::unique_ptr m_sphere; std::unique_ptr m_world_coord_axes; @@ -117,7 +130,7 @@ class Main_widget : public QOpenGLWidget, protected OpenGLFunctionsBase // Camera & controls Camera m_camera; - std::unique_ptr m_camera_manip_rot; + std::unique_ptr m_camera_manip_rot; std::unique_ptr m_camera_manip_zoom; QMatrix4x4 m_model;