From f527cde6342c5b8109a20f0a6b483327c6569844 Mon Sep 17 00:00:00 2001 From: salinasd Date: Tue, 27 Jan 2015 10:20:13 +0000 Subject: Merge GudhUI, a UI for gudhi based on Qt git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@427 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 17fedd974f14a8225b27d94361e835964eeb5cba --- src/GudhUI/CMakeLists.txt | 80 +++++++ src/GudhUI/gui/KNearestNeighborsMenu.ui | 150 +++++++++++++ src/GudhUI/gui/MainWindow.cpp | 283 +++++++++++++++++++++++++ src/GudhUI/gui/MainWindow.h | 97 +++++++++ src/GudhUI/gui/MenuEdgeContraction.ui | 118 +++++++++++ src/GudhUI/gui/Menu_edge_contraction.cpp | 91 ++++++++ src/GudhUI/gui/Menu_edge_contraction.h | 52 +++++ src/GudhUI/gui/Menu_k_nearest_neighbors.cpp | 55 +++++ src/GudhUI/gui/Menu_k_nearest_neighbors.h | 39 ++++ src/GudhUI/gui/Menu_persistence.cpp | 60 ++++++ src/GudhUI/gui/Menu_persistence.h | 59 ++++++ src/GudhUI/gui/Menu_uniform_neighbors.cpp | 59 ++++++ src/GudhUI/gui/Menu_uniform_neighbors.h | 36 ++++ src/GudhUI/gui/PersistenceMenu.ui | 139 ++++++++++++ src/GudhUI/gui/UniformNeighborsMenu.ui | 150 +++++++++++++ src/GudhUI/gui/Viewer.cpp | 0 src/GudhUI/gui/Viewer_instructor.cpp | 0 src/GudhUI/gui/gudhui.cpp | 17 ++ src/GudhUI/gui/main_window.ui | 231 ++++++++++++++++++++ src/GudhUI/model/Complex_typedefs.h | 39 ++++ src/GudhUI/model/Model.h | 291 ++++++++++++++++++++++++++ src/GudhUI/todo.txt | 22 ++ src/GudhUI/utils/Edge_collapsor.h | 84 ++++++++ src/GudhUI/utils/Edge_contractor.h | 68 ++++++ src/GudhUI/utils/Furthest_point_epsilon_net.h | 134 ++++++++++++ src/GudhUI/utils/K_nearest_builder.h | 106 ++++++++++ src/GudhUI/utils/Lloyd_builder.h | 78 +++++++ src/GudhUI/utils/MClock.h | 57 +++++ src/GudhUI/utils/Persistence_compute.h | 106 ++++++++++ src/GudhUI/utils/Rips_builder.h | 56 +++++ src/GudhUI/utils/UI_utils.h | 33 +++ src/GudhUI/utils/Vertex_collapsor.h | 76 +++++++ src/GudhUI/utils/homsimpl | Bin 0 -> 118624 bytes src/GudhUI/view/Color.h | 21 ++ src/GudhUI/view/FirstCoordProjector.h | 24 +++ src/GudhUI/view/Projector3D.h | 28 +++ src/GudhUI/view/View_parameter.h | 137 ++++++++++++ src/GudhUI/view/Viewer.cpp | 197 +++++++++++++++++ src/GudhUI/view/Viewer.h | 96 +++++++++ src/GudhUI/view/Viewer_instructor.cpp | 206 ++++++++++++++++++ src/GudhUI/view/Viewer_instructor.h | 108 ++++++++++ 41 files changed, 3683 insertions(+) create mode 100644 src/GudhUI/CMakeLists.txt create mode 100644 src/GudhUI/gui/KNearestNeighborsMenu.ui create mode 100644 src/GudhUI/gui/MainWindow.cpp create mode 100644 src/GudhUI/gui/MainWindow.h create mode 100644 src/GudhUI/gui/MenuEdgeContraction.ui create mode 100644 src/GudhUI/gui/Menu_edge_contraction.cpp create mode 100644 src/GudhUI/gui/Menu_edge_contraction.h create mode 100644 src/GudhUI/gui/Menu_k_nearest_neighbors.cpp create mode 100644 src/GudhUI/gui/Menu_k_nearest_neighbors.h create mode 100644 src/GudhUI/gui/Menu_persistence.cpp create mode 100644 src/GudhUI/gui/Menu_persistence.h create mode 100644 src/GudhUI/gui/Menu_uniform_neighbors.cpp create mode 100644 src/GudhUI/gui/Menu_uniform_neighbors.h create mode 100644 src/GudhUI/gui/PersistenceMenu.ui create mode 100644 src/GudhUI/gui/UniformNeighborsMenu.ui create mode 100644 src/GudhUI/gui/Viewer.cpp create mode 100644 src/GudhUI/gui/Viewer_instructor.cpp create mode 100644 src/GudhUI/gui/gudhui.cpp create mode 100644 src/GudhUI/gui/main_window.ui create mode 100644 src/GudhUI/model/Complex_typedefs.h create mode 100644 src/GudhUI/model/Model.h create mode 100644 src/GudhUI/todo.txt create mode 100644 src/GudhUI/utils/Edge_collapsor.h create mode 100644 src/GudhUI/utils/Edge_contractor.h create mode 100644 src/GudhUI/utils/Furthest_point_epsilon_net.h create mode 100644 src/GudhUI/utils/K_nearest_builder.h create mode 100644 src/GudhUI/utils/Lloyd_builder.h create mode 100644 src/GudhUI/utils/MClock.h create mode 100644 src/GudhUI/utils/Persistence_compute.h create mode 100644 src/GudhUI/utils/Rips_builder.h create mode 100644 src/GudhUI/utils/UI_utils.h create mode 100644 src/GudhUI/utils/Vertex_collapsor.h create mode 100755 src/GudhUI/utils/homsimpl create mode 100644 src/GudhUI/view/Color.h create mode 100644 src/GudhUI/view/FirstCoordProjector.h create mode 100644 src/GudhUI/view/Projector3D.h create mode 100644 src/GudhUI/view/View_parameter.h create mode 100644 src/GudhUI/view/Viewer.cpp create mode 100755 src/GudhUI/view/Viewer.h create mode 100644 src/GudhUI/view/Viewer_instructor.cpp create mode 100755 src/GudhUI/view/Viewer_instructor.h (limited to 'src') diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt new file mode 100644 index 00000000..4c0c2087 --- /dev/null +++ b/src/GudhUI/CMakeLists.txt @@ -0,0 +1,80 @@ +cmake_minimum_required(VERSION 2.8) +project(GudhUI) + +#Specify Gudhi's path here +#for instance +SET(Gudhi_Path "/home/dsalinas/Documents/CodeSVN/gudhi/src/include") + +set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE}) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -frounding-math -Wall -pedantic") + +find_package(Boost REQUIRED COMPONENTS) +find_package(CGAL COMPONENTS Qt4) +find_package(Qt4) +find_package(OpenGL) +find_package(QGLViewer) + +if ( CGAL_FOUND AND CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND ) + + set( QT_USE_QTXML TRUE ) + set( QT_USE_QTMAIN TRUE ) + set( QT_USE_QTSCRIPT TRUE ) + set( QT_USE_QTOPENGL TRUE ) + SET(Boost_USE_STATIC_LIBS ON) + SET(Boost_USE_MULTITHREAD OFF) + + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) + LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) + + include(${QT_USE_FILE}) + include(${CGAL_USE_FILE}) + + include_directories (${QGLVIEWER_INCLUDE_DIR}) + include_directories(.) + include_directories(${Gudhi_Path}) + + + # qt : ui file, created wih Qt Designer ############### + set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/gui") + qt4_wrap_ui( uis + gui/main_window.ui + gui/MenuEdgeContraction.ui + gui/KNearestNeighborsMenu.ui + gui/UniformNeighborsMenu.ui + gui/PersistenceMenu.ui + ) + + set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/gui") + qt4_automoc( + gui/MainWindow.cpp + gui/Menu_k_nearest_neighbors.cpp + gui/Menu_uniform_neighbors.cpp + gui/Menu_edge_contraction.cpp + gui/Menu_persistence.cpp + ) + + set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/view") + qt4_automoc(view/Viewer_instructor.cpp + view/Viewer.cpp + ) + ##################################################################### + + add_executable ( GudhUI + gui/gudhui.cpp + gui/MainWindow.cpp + gui/Menu_k_nearest_neighbors.cpp + gui/Menu_uniform_neighbors.cpp + gui/Menu_edge_contraction.cpp + gui/Menu_persistence.cpp + view/Viewer_instructor.cpp + view/Viewer.cpp + ${uis} + ) + + target_link_libraries( GudhUI ${QT_LIBRARIES} ${QGLVIEWER_LIBRARIES} ) + target_link_libraries( GudhUI ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) + +else() + message(STATUS "NOTICE: This demo requires CGAL, the QGLViewer, OpenGL and Qt4, and will not be compiled.") +endif() diff --git a/src/GudhUI/gui/KNearestNeighborsMenu.ui b/src/GudhUI/gui/KNearestNeighborsMenu.ui new file mode 100644 index 00000000..472db48b --- /dev/null +++ b/src/GudhUI/gui/KNearestNeighborsMenu.ui @@ -0,0 +1,150 @@ + + + KNearestNeighborsMenu + + + + 0 + 0 + 298 + 209 + + + + k-nearest neighbors + + + + + 50 + 160 + 171 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 30 + 10 + 229 + 84 + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + k + + + + + + + 10000000 + + + 0 + + + + + + + Metric + + + + + + + + Ambient + + + + + Reduced Space + + + + + + + + + + 30 + 110 + 250 + 40 + + + + + + + Compute + + + + + + + auto update + + + true + + + + + + + + + + buttonBox + accepted() + KNearestNeighborsMenu + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + KNearestNeighborsMenu + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/GudhUI/gui/MainWindow.cpp b/src/GudhUI/gui/MainWindow.cpp new file mode 100644 index 00000000..85745e93 --- /dev/null +++ b/src/GudhUI/gui/MainWindow.cpp @@ -0,0 +1,283 @@ +#include "MainWindow.h" + +#include +#include +#include + +#include + + +#include "gui/Menu_k_nearest_neighbors.h" +#include "gui/Menu_uniform_neighbors.h" +#include "gui/Menu_edge_contraction.h" +#include "gui/Menu_persistence.h" + + +MainWindow::MainWindow(QWidget* parent): +menu_k_nearest_neighbors_(new Menu_k_nearest_neighbors(this)), +menu_uniform_neighbors_(new Menu_uniform_neighbors(this)), +menu_edge_contraction_(new Menu_edge_contraction(this,model_)), +menu_persistence_(new Menu_persistence(this)) +{ +#ifndef NDEBUG // catch nan +feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); +#endif + + setupUi(this); + + viewer_instructor_ = new Viewer_instructor( + this, + this->viewer, + model_.complex_ + ); + + connectActions(); + + update_view(); +} + +void +MainWindow::closeEvent(QCloseEvent *event){ + exit(0); +} + + +void +MainWindow::connectActions(){ + QObject::connect(this->actionLoad_complex, SIGNAL(triggered()), this, + SLOT(off_file_open())); + QObject::connect(this->actionLoad_points, SIGNAL(triggered()), this, + SLOT(off_points_open())); + QObject::connect(this->actionSave_complex, SIGNAL(triggered()), this, + SLOT(off_file_save())); + QObject::connect(this->actionSave_points, SIGNAL(triggered()), this, + SLOT(off_points_save())); + + QObject::connect(this->actionShow_graph_stats, SIGNAL(triggered()), this, + SLOT(show_graph_stats())); + QObject::connect(this->actionShow_complex_stats, SIGNAL(triggered()), this, + SLOT(show_complex_stats())); + QObject::connect(this->actionShow_complex_dimension, SIGNAL(triggered()), this, + SLOT(show_complex_dimension())); + + QObject::connect(this->actionUniform_proximity_graph, SIGNAL(triggered()), this, + SLOT(build_rips_menu())); + QObject::connect(this->actionK_nearest_neighbors_graph, SIGNAL(triggered()), this, + SLOT(build_k_nearest_neighbors_menu())); + + + QObject::connect(this->actionContract_edges, SIGNAL(triggered()), this, + SLOT(contract_edge_menu())); + + QObject::connect(this->actionCollapse_vertices, SIGNAL(triggered()), this, + SLOT(collapse_vertices())); + + QObject::connect(this->actionCollapse_edges, SIGNAL(triggered()), this, + SLOT(collapse_edges())); + + QObject::connect(this->actionNoise, SIGNAL(triggered()), this, + SLOT(uniform_noise())); + QObject::connect(this->actionLloyd, SIGNAL(triggered()), this, + SLOT(lloyd())); + + + //view + QObject::connect(this->actionPoints, SIGNAL(triggered()), this->viewer_instructor_, + SLOT(change_draw_vertices())); + QObject::connect(this->actionEdges, SIGNAL(triggered()), this->viewer_instructor_, + SLOT(change_draw_edges())); + QObject::connect(this->actionTriangles, SIGNAL(triggered()), this->viewer_instructor_, + SLOT(change_draw_triangles())); + + //topology + QObject::connect(this->actionShow_homology_group, SIGNAL(triggered()), this, + SLOT(show_homology_group())); + QObject::connect(this->actionEuler_characteristic, SIGNAL(triggered()), this, + SLOT(show_euler_characteristic())); + QObject::connect(this->actionPersistence, SIGNAL(triggered()), this, + SLOT(persistence_menu())); + + + + QObject::connect(this, SIGNAL(sceneChanged()), this->viewer_instructor_, + SLOT(sceneChanged())); + +} + +void +MainWindow::init_view() const{ + viewer_instructor_->initialize_bounding_box(); + viewer_instructor_->show_entire_scene(); + update_view(); +} + + +void +MainWindow::update_view() const{ + emit (sceneChanged()); +} + + + +/** + * open a file chooser to choose an off to load + */ +void +MainWindow::off_file_open(){ + QString fileName = QFileDialog::getOpenFileName(this, tr("Open off File"), + "~/", tr("off files (*.off)")); + if (!fileName.isEmpty()){ + model_.off_file_open(fileName.toStdString()); + init_view(); + } +} + +void +MainWindow::off_points_open(){ + QString fileName = QFileDialog::getOpenFileName(this, tr("Open points in a off file"), + "~/", tr("off files (*.off)")); + if (!fileName.isEmpty()){ + model_.off_points_open(fileName.toStdString()); + init_view(); + } +} + + +/** + * open a file chooser to choose an off to save + */ +void +MainWindow::off_file_save(){ + QString fileName = QFileDialog::getOpenFileName(this, tr("Save to off File"), + "~/", tr("off files (*.off)")); + if (!fileName.isEmpty()) + { + model_.off_file_save(fileName.toStdString()); + } +} + +/** + * open a file chooser to choose an off to save + */ +void +MainWindow::off_points_save(){ + QString fileName = QFileDialog::getOpenFileName(this, tr("Save to off File"), + "~/", tr("off files (*.off)")); + if (!fileName.isEmpty()) + { + model_.off_points_save(fileName.toStdString()); + } +} + + +void +MainWindow::show_graph_stats(){ + model_.show_graph_stats(); +} + +void +MainWindow::show_complex_stats(){ + model_.show_complex_stats(); +} + +void +MainWindow::show_complex_dimension(){ + model_.show_complex_dimension(); +} + + +void +MainWindow::build_rips_menu(){ + menu_uniform_neighbors_->show(); +} + +void +MainWindow::build_rips(double alpha){ + model_.build_rips(alpha); + update_view(); +} + +void +MainWindow::build_k_nearest_neighbors_menu(){ + menu_k_nearest_neighbors_->show(); +} + +void +MainWindow::build_k_nearest_neighbors(unsigned k){ + model_.build_k_nearest_neighbors(k); + update_view(); +} + +void +MainWindow::contract_edge_menu(){ + menu_edge_contraction_->show(); +} + +void +MainWindow::contract_edges(unsigned num_collapses){ + std::cerr <<"Collapse "<show(); +} + +void +MainWindow::compute_persistence(int p,double threshold,int max_dim,double min_pers){ + model_.show_persistence(p,threshold,max_dim,min_pers); +} + + + +#include "MainWindow.moc" diff --git a/src/GudhUI/gui/MainWindow.h b/src/GudhUI/gui/MainWindow.h new file mode 100644 index 00000000..0eef29ed --- /dev/null +++ b/src/GudhUI/gui/MainWindow.h @@ -0,0 +1,97 @@ +#ifndef MAIN_WINDOW_H +#define MAIN_WINDOW_H + + +#include +#include "ui_main_window.h" +#include "model/Model.h" +#include "view/Viewer_instructor.h" + + +class Menu_k_nearest_neighbors; +class Menu_uniform_neighbors; +class Menu_edge_contraction; +class Menu_persistence; + +class MainWindow : public QMainWindow,public Ui::MainWindow{ + Q_OBJECT + +private: + Model model_; + Viewer_instructor* viewer_instructor_; + Menu_k_nearest_neighbors* menu_k_nearest_neighbors_; + Menu_uniform_neighbors* menu_uniform_neighbors_; + Menu_edge_contraction* menu_edge_contraction_; + Menu_persistence* menu_persistence_; + +public: + MainWindow(QWidget* parent = 0); + void connectActions(); + + /** + * compute the bounding box and calls update view + */ + void init_view() const; + void update_view() const; + + +protected: + void closeEvent(QCloseEvent *event); + void keyPressEvent(QKeyEvent *event){} + +public: + + public slots: + + + /** + * open a file chooser to choose an off to load + */ + void off_file_open(); + + void off_points_open(); + + /** + * open a file chooser to choose an off to save + */ + void off_file_save(); + void off_points_save(); + + void show_graph_stats(); + void show_complex_stats(); + void show_complex_dimension(); + + + void build_rips_menu(); + void build_rips(double alpha); + void build_k_nearest_neighbors_menu(); + void build_k_nearest_neighbors(unsigned k); + + + void contract_edge_menu(); + void contract_edges(unsigned num_collapses); + + + void collapse_vertices(); + void collapse_edges(); + + + void uniform_noise(); + void lloyd(); + + void show_homology_group(); + void show_euler_characteristic(); + void persistence_menu(); + void compute_persistence(int p,double threshold,int max_dim,double min_pers); + + + +public: + signals: + void sceneChanged() const; + + +}; + + +#endif diff --git a/src/GudhUI/gui/MenuEdgeContraction.ui b/src/GudhUI/gui/MenuEdgeContraction.ui new file mode 100644 index 00000000..da2e5c82 --- /dev/null +++ b/src/GudhUI/gui/MenuEdgeContraction.ui @@ -0,0 +1,118 @@ + + + MenuEdgeContraction + + + + 0 + 0 + 362 + 209 + + + + Edge contraction + + + + + + 1 + + + 999999999 + + + 1 + + + + + + + false + + + Link condition + + + true + + + + + + + 1 + + + + + + + Policy + + + + + + + + Length_midpoint + + + + + + + + 0 + + + + + + + Number of vertices + + + + + + + Number of contractions + + + + + + + Number of vertices after + + + + + + + 0 + + + 100 + + + Qt::Horizontal + + + + + + + Perform collapse + + + + + + + + diff --git a/src/GudhUI/gui/Menu_edge_contraction.cpp b/src/GudhUI/gui/Menu_edge_contraction.cpp new file mode 100644 index 00000000..dd2621be --- /dev/null +++ b/src/GudhUI/gui/Menu_edge_contraction.cpp @@ -0,0 +1,91 @@ +/* + * Menu_edge_contraction.cpp + * + * Created on: Sep 11, 2014 + * Author: dsalinas + */ + +#ifndef MENU_EDGE_CONTRACTION_CPP_ +#define MENU_EDGE_CONTRACTION_CPP_ + + +#include "Menu_edge_contraction.h" + +Menu_edge_contraction::Menu_edge_contraction(MainWindow* parent,const Model& model): +parent_(parent),model_(model) +{ + setupUi(this); + connectActions(parent_); +} + +void Menu_edge_contraction::connectActions(MainWindow* parent) +{ + QObject::connect( + this->horizontalSlider, + SIGNAL(valueChanged(int)), + this, + SLOT(slider_value_changed(int)) + ); + + + QObject::connect(this, SIGNAL(contract_edges(unsigned)), parent, SLOT(contract_edges(unsigned))); + + QObject::connect(this->pushButton_collapse, SIGNAL(clicked()), this, SLOT(send_contract_edges())); + +} + +void Menu_edge_contraction::slider_value_changed(int new_slider_value){ + int num_collapses = + (horizontalSlider->value()==1)? 1 : horizontalSlider->value() * model_.num_vertices() / 100 ; + this->txt_nb_vertices->setNum((int)model_.num_vertices()); + this->txt_nb_collapses->setNum(num_collapses); + this->spinBox_nb_remaining_vertices->setValue(model_.num_vertices()-num_collapses); +} + + +void +Menu_edge_contraction::update_slider_value(){ + int num_vertices = model_.num_vertices(); + int num_collapses = (horizontalSlider->value()==1)? 1 : horizontalSlider->value() * num_vertices / 100 ; + int horizontal_slider_position = num_vertices>0? num_collapses/(double)num_vertices * 100 : 1 ; + horizontalSlider->setValue(horizontal_slider_position); +} + + +void +Menu_edge_contraction::update_gui_numbers(){ + update_slider_value(); + bool ok; + int num_collapses = this->txt_nb_collapses->text().toInt(&ok,10); + if(!ok) return; + this->txt_nb_vertices->setNum((int)model_.num_vertices()); + this->txt_nb_collapses->setNum(num_collapses); + this->spinBox_nb_remaining_vertices->setValue(model_.num_vertices()-num_collapses); +} + +void +Menu_edge_contraction::update_gui_numbers(int new_value){ + update_gui_numbers(); +} + + +void +Menu_edge_contraction::send_contract_edges(){ + emit(contract_edges(num_collapses())); + update_gui_numbers(); +} + +unsigned +Menu_edge_contraction::num_vertices(){ + return model_.num_vertices(); +} + +unsigned +Menu_edge_contraction::num_collapses(){ + return (horizontalSlider->value()==1)? 1 : horizontalSlider->value() * num_vertices() / 100 ; +} + + +#include "Menu_edge_contraction.moc" + +#endif /* MENU_EDGE_CONTRACTION_CPP_ */ diff --git a/src/GudhUI/gui/Menu_edge_contraction.h b/src/GudhUI/gui/Menu_edge_contraction.h new file mode 100644 index 00000000..e497a90f --- /dev/null +++ b/src/GudhUI/gui/Menu_edge_contraction.h @@ -0,0 +1,52 @@ +/* + * Menu_edge_contraction.h + * + * Created on: Sep 11, 2014 + * Author: dsalinas + */ + +#ifndef MENU_EDGE_CONTRACTION_H_ +#define MENU_EDGE_CONTRACTION_H_ + + +#include "gui/MainWindow.h" +#include "gui/ui_MenuEdgeContraction.h" + +#include "model/Model.h" + + +class Menu_edge_contraction : public QDialog,public Ui::MenuEdgeContraction{ + Q_OBJECT +private: + MainWindow* parent_; + const Model& model_; + + + void update_slider_value(); +public: + + Menu_edge_contraction(MainWindow* parent,const Model& model); + + void connectActions(MainWindow* parent); + + +private: + unsigned num_vertices(); + unsigned num_collapses(); + + public slots: + + void slider_value_changed(int new_slider_value); + void update_gui_numbers(); + void update_gui_numbers(int); + + void send_contract_edges(); + signals: + + void contract_edges(unsigned num_collapses); + +}; + + + +#endif /* MENU_EDGE_CONTRACTION_H_ */ diff --git a/src/GudhUI/gui/Menu_k_nearest_neighbors.cpp b/src/GudhUI/gui/Menu_k_nearest_neighbors.cpp new file mode 100644 index 00000000..21c67b2a --- /dev/null +++ b/src/GudhUI/gui/Menu_k_nearest_neighbors.cpp @@ -0,0 +1,55 @@ +/* + * Menu_k_nearest_neighbors.cpp + * + * Created on: Sep 11, 2014 + * Author: dsalinas + */ + + +#include "Menu_k_nearest_neighbors.h" + +Menu_k_nearest_neighbors::Menu_k_nearest_neighbors(QMainWindow* parent_): +parent(parent_) +{ + setupUi(this); + connectActions(parent_); +} + +void Menu_k_nearest_neighbors::connectActions(QMainWindow* parent){ + + QObject::connect( + this->pushButtonCompute, + SIGNAL(clicked()), + this, + SLOT(send_compute_k_nearest_neighbors()) + ); + QObject::connect( + this->spinBoxK, + SIGNAL(valueChanged(int)), + this, + SLOT(update_k(int)) + ); + QObject::connect( + this, + SIGNAL(compute_k_nearest_neighbors(unsigned)), + parent, + SLOT(build_k_nearest_neighbors(unsigned)) + ); + +} + +void Menu_k_nearest_neighbors::send_compute_k_nearest_neighbors(){ + emit(compute_k_nearest_neighbors((unsigned)spinBoxK->value())); +} + +void Menu_k_nearest_neighbors::accept(){ + send_compute_k_nearest_neighbors(); +} + +void Menu_k_nearest_neighbors::update_k(int new_k_value){ + if(checkBoxAutoUpdate->isChecked()) + emit(compute_k_nearest_neighbors((unsigned)spinBoxK->value())); +} + + +#include "Menu_k_nearest_neighbors.moc" diff --git a/src/GudhUI/gui/Menu_k_nearest_neighbors.h b/src/GudhUI/gui/Menu_k_nearest_neighbors.h new file mode 100644 index 00000000..d72b0074 --- /dev/null +++ b/src/GudhUI/gui/Menu_k_nearest_neighbors.h @@ -0,0 +1,39 @@ +/* + * Menu_k_nearest_neighbors.h + * + * Created on: Sep 11, 2014 + * Author: dsalinas + */ + +#ifndef MENU_K_NEAREST_NEIGHBORS_H_ +#define MENU_K_NEAREST_NEIGHBORS_H_ + +#include +#include "gui/ui_KNearestNeighborsMenu.h" + +class QWidget; + + +class Menu_k_nearest_neighbors : public QDialog,public Ui::KNearestNeighborsMenu{ + Q_OBJECT +private: + QMainWindow* parent; + +public: + + Menu_k_nearest_neighbors(QMainWindow* parent_); + + void connectActions(QMainWindow* parent); + + public slots: + void send_compute_k_nearest_neighbors(); + void update_k(int); + void accept(); + + signals: + void compute_k_nearest_neighbors(unsigned k); + +}; + + +#endif /* MENU_K_NEAREST_NEIGHBORS_H_ */ diff --git a/src/GudhUI/gui/Menu_persistence.cpp b/src/GudhUI/gui/Menu_persistence.cpp new file mode 100644 index 00000000..fae3a0e6 --- /dev/null +++ b/src/GudhUI/gui/Menu_persistence.cpp @@ -0,0 +1,60 @@ +/* + * Menu_persistence.cpp + * Created on: Jan 27, 2015 + * This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): David Salinas + * + * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#include "Menu_persistence.h" + +Menu_persistence::Menu_persistence(QMainWindow* parent_):parent(parent_) +{ + setupUi(this); + connectActions(parent_); +} + +void Menu_persistence::connectActions(QMainWindow* parent){ + QObject::connect( + this, + SIGNAL(compute_persistence(int,double,int,double)), + parent, + SLOT(compute_persistence(int,double,int,double)) + ); +} + +void Menu_persistence::send_compute_persistence(){ + emit(compute_persistence(p_spinBox->value(),threshold_doubleSpinBox->value(), + maxdimension_spinBox->value(),minpersistence_doubleSpinBox->value())); +} + +void Menu_persistence::accept(){ + send_compute_persistence(); +} + +//void Menu_persistence::compute_persistence(int p_fied,double threshold,int dim_max,double min_persistence){ +//// if(checkBoxAutoUpdate->isChecked()) +//// emit(compute_k_nearest_neighbors((unsigned)spinBoxK->value())); +//} + + +#include "Menu_persistence.moc" diff --git a/src/GudhUI/gui/Menu_persistence.h b/src/GudhUI/gui/Menu_persistence.h new file mode 100644 index 00000000..67b64afa --- /dev/null +++ b/src/GudhUI/gui/Menu_persistence.h @@ -0,0 +1,59 @@ +/* + * Menu_persistence.h + * Created on: Jan 27, 2015 + * This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): David Salinas + * + * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#ifndef MENU_PERSISTENCE_H_ +#define MENU_PERSISTENCE_H_ + + +#include +#include "gui/ui_PersistenceMenu.h" + +class QWidget; + + +class Menu_persistence : public QDialog,public Ui::PersistenceMenu{ + Q_OBJECT +private: + QMainWindow* parent; + +public: + + Menu_persistence(QMainWindow* parent_); + + void connectActions(QMainWindow* parent); + + public slots: + void send_compute_persistence(); + void accept(); + signals: + void compute_persistence(int p_fied,double threshold,int dim_max,double min_persistence); + +}; + + + +#endif /* MENU_PERSISTENCE_H_ */ diff --git a/src/GudhUI/gui/Menu_uniform_neighbors.cpp b/src/GudhUI/gui/Menu_uniform_neighbors.cpp new file mode 100644 index 00000000..86e2593e --- /dev/null +++ b/src/GudhUI/gui/Menu_uniform_neighbors.cpp @@ -0,0 +1,59 @@ +/* + * Menu_uniform_neighbors.cpp + * + * Created on: Sep 11, 2014 + * Author: dsalinas + */ + + + + + +#include "Menu_uniform_neighbors.h" + +Menu_uniform_neighbors::Menu_uniform_neighbors(QMainWindow* parent_): +parent(parent_) +{ + setupUi(this); + connectActions(parent_); +} + +void Menu_uniform_neighbors::connectActions(QMainWindow* parent){ + + QObject::connect( + this->pushButtonCompute, + SIGNAL(clicked()), + this, + SLOT(send_compute_uniform_neighbors()) + ); + QObject::connect( + this->doubleSpinBoxAlpha, + SIGNAL(valueChanged(double)), + this, + SLOT(update_alpha(double)) + ); + QObject::connect( + this, + SIGNAL(compute_uniform_neighbors(double)), + parent, + SLOT(build_rips(double)) + ); + +} + +void Menu_uniform_neighbors::send_compute_uniform_neighbors(){ + emit(compute_uniform_neighbors(doubleSpinBoxAlpha->value())); +} + +void Menu_uniform_neighbors::accept(){ + send_compute_uniform_neighbors(); +} + +void Menu_uniform_neighbors::update_alpha(double alpha){ + if(checkBoxAutoUpdate->isChecked()) + emit(compute_uniform_neighbors(doubleSpinBoxAlpha->value())); +} + + + +#include "Menu_uniform_neighbors.moc" diff --git a/src/GudhUI/gui/Menu_uniform_neighbors.h b/src/GudhUI/gui/Menu_uniform_neighbors.h new file mode 100644 index 00000000..cb90cc88 --- /dev/null +++ b/src/GudhUI/gui/Menu_uniform_neighbors.h @@ -0,0 +1,36 @@ +/* + * Menu_uniform_neighbors.h + * + * Created on: Sep 11, 2014 + * Author: dsalinas + */ + +#ifndef MENU_UNIFORM_NEIGHBORS_H_ +#define MENU_UNIFORM_NEIGHBORS_H_ + +#include +#include "gui/ui_UniformNeighborsMenu.h" + +class Menu_uniform_neighbors : public QDialog,public Ui::UniformMenu { + Q_OBJECT +private: + QMainWindow* parent; + +public: + + Menu_uniform_neighbors(QMainWindow* parent_); + + void connectActions(QMainWindow* parent); + + public slots: + void send_compute_uniform_neighbors(); + void update_alpha(double); + void accept(); + + signals: + void compute_uniform_neighbors(double alpha); + +}; + + +#endif /* MENU_UNIFORM_NEIGHBORS_H_ */ diff --git a/src/GudhUI/gui/PersistenceMenu.ui b/src/GudhUI/gui/PersistenceMenu.ui new file mode 100644 index 00000000..29327db2 --- /dev/null +++ b/src/GudhUI/gui/PersistenceMenu.ui @@ -0,0 +1,139 @@ + + + PersistenceMenu + + + + 0 + 0 + 354 + 275 + + + + Point cloud persistence + + + + + 20 + 23 + 318 + 226 + + + + + + + + + 2 + + + 2 + + + + + + + Coefficient Z/pZ + + + + + + + 9999 + + + 10 + + + + + + + Max dimension + + + + + + + 9999.000000000000000 + + + 1.000000000000000 + + + + + + + Max Rips offset + + + + + + + + + + Minimum Persistence + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + buttonBox + accepted() + PersistenceMenu + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + PersistenceMenu + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/GudhUI/gui/UniformNeighborsMenu.ui b/src/GudhUI/gui/UniformNeighborsMenu.ui new file mode 100644 index 00000000..1f7cf980 --- /dev/null +++ b/src/GudhUI/gui/UniformNeighborsMenu.ui @@ -0,0 +1,150 @@ + + + UniformMenu + + + + 0 + 0 + 292 + 209 + + + + Uniform neighbors (Rips) + + + + + 50 + 160 + 171 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 30 + 10 + 249 + 84 + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + alpha + + + + + + + Metric + + + + + + + + Ambient + + + + + Reduced Space + + + + + + + + 100000000.000000000000000 + + + 0.100000000000000 + + + + + + + + + 30 + 110 + 250 + 40 + + + + + + + Compute + + + + + + + auto update + + + true + + + + + + + + + + buttonBox + accepted() + UniformMenu + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + UniformMenu + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/GudhUI/gui/Viewer.cpp b/src/GudhUI/gui/Viewer.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/GudhUI/gui/Viewer_instructor.cpp b/src/GudhUI/gui/Viewer_instructor.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/GudhUI/gui/gudhui.cpp b/src/GudhUI/gui/gudhui.cpp new file mode 100644 index 00000000..8d90270f --- /dev/null +++ b/src/GudhUI/gui/gudhui.cpp @@ -0,0 +1,17 @@ +#include "MainWindow.h" +#include +#include + + +int main(int argc, char** argv) +{ + QApplication application(argc,argv); + application.setOrganizationDomain("inria.fr"); + application.setOrganizationName("INRIA"); + application.setApplicationName("GudhUI"); + + MainWindow mw; + application.setQuitOnLastWindowClosed(false); + mw.show(); + return application.exec(); +} diff --git a/src/GudhUI/gui/main_window.ui b/src/GudhUI/gui/main_window.ui new file mode 100644 index 00000000..ac3caf41 --- /dev/null +++ b/src/GudhUI/gui/main_window.ui @@ -0,0 +1,231 @@ + + + MainWindow + + + + 0 + 0 + 861 + 880 + + + + GudhUI + + + QTabWidget::Rounded + + + + + + + + + false + + + + + + + + + + + 0 + 0 + 861 + 34 + + + + + File + + + + + + + + + Points + + + + + + Graph + + + + + + + + Complex + + + + + + + + + + View + + + + + + + + + Topology + + + + + + + + + + + + + + + + Load points + + + + + Load complex + + + + + Save points + + + + + Save complex + + + + + Noise + + + + + Lloyd + + + + + Uniform proximity graph + + + + + k-nearest neighbors graph + + + + + Show graph stats + + + + + Graph expansion + + + + + Delaunay from points + + + + + Contract edges + + + + + Collapse vertices + + + + + Collapse edges + + + + + Points + + + + + Edges + + + + + Triangles + + + + + Change projection + + + + + Show complex stats + + + + + Show complex dimension + + + + + Homology groups + + + + + Point cloud persistence + + + + + Euler characteristic + + + + + Homology groups + + + + + + Viewer + QWidget +
view/Viewer.h
+
+
+ + +
diff --git a/src/GudhUI/model/Complex_typedefs.h b/src/GudhUI/model/Complex_typedefs.h new file mode 100644 index 00000000..b6404d62 --- /dev/null +++ b/src/GudhUI/model/Complex_typedefs.h @@ -0,0 +1,39 @@ +/* + * Complex_typedefs.h + * + * Created on: Aug 26, 2014 + * Author: dsalinas + */ + +#ifndef COMPLEX_TYPEDEFS_H_ +#define COMPLEX_TYPEDEFS_H_ + + + +#include "gudhi/Skeleton_blocker/Skeleton_blocker_simple_geometric_traits.h" +#include "gudhi/Skeleton_blocker_geometric_complex.h" + +#include + +#include +#include + + +struct Geometry_trait : public CGAL::Cartesian_d { + typedef CGAL::Cartesian::Point_3 Point_3; + typedef CGAL::Cartesian::Vector_3 Vector_3; + typedef CGAL::Point_d> Point; + typedef CGAL::Vector_d> Vector; +}; + +typedef Geometry_trait::Point Point; + + +using namespace Gudhi; +using namespace Gudhi::skbl; + +typedef Skeleton_blocker_simple_geometric_traits Complex_geometric_traits; +typedef Skeleton_blocker_geometric_complex< Complex_geometric_traits > Complex; + + +#endif /* COMPLEX_TYPEDEFS_H_ */ diff --git a/src/GudhUI/model/Model.h b/src/GudhUI/model/Model.h new file mode 100644 index 00000000..0d0f91e6 --- /dev/null +++ b/src/GudhUI/model/Model.h @@ -0,0 +1,291 @@ +/* + * Model.h + * + * Created on: Aug 25, 2014 + * Author: david + */ + +#ifndef MODEL_H_ +#define MODEL_H_ + +#include +#include +#include "gudhi/Clock.h" +#include "utils/UI_utils.h" +#include "utils/Lloyd_builder.h" +#include "utils/Rips_builder.h" +#include "utils/K_nearest_builder.h" +#include "utils/Vertex_collapsor.h" +#include "utils/Edge_collapsor.h" +#include "utils/Edge_contractor.h" +#include "utils/Persistence_compute.h" + +#include "gudhi/Skeleton_blocker/Skeleton_blocker_simple_geometric_traits.h" +#include "gudhi/Skeleton_blocker_geometric_complex.h" + +#include "gudhi/Off_reader.h" + +#include "Complex_typedefs.h" + + +#include + + +template +class CGAL_geometric_flag_complex_wrapper{ + Complex& complex_; + typedef typename Complex::Vertex_handle Vertex_handle; + typedef typename Complex::Point Point; + + const bool load_only_points_; + +public: + CGAL_geometric_flag_complex_wrapper(Complex& complex,bool load_only_points = false): + complex_(complex), + load_only_points_(load_only_points){ + } + + void init(int dim,int num_vertices,int num_max_faces,int num_edges) const{ + } + + void point(const std::vector& coords){ + Point p(coords.size(),coords.begin(),coords.end()); + complex_.add_vertex(p); + } + + void maximal_face(std::vector vertices){ + if (!load_only_points_){ + for (int i = 0; i read_wraper(complex_); + Gudhi::read_off(name_file,read_wraper); + } + + void off_points_open(const std::string& name_file){ + UIDBGMSG("load off points",name_file); + complex_.clear(); + CGAL_geometric_flag_complex_wrapper read_wraper(complex_); + Gudhi::read_off(name_file,read_wraper); + } + + void off_file_save(const std::string& name_file){ + UIDBG("save off file"); + } + + void off_points_save(const std::string& name_file){ + UIDBG("save off off_points_save"); + } + + // point sets operations + void uniform_noise(double amplitude){ + UIDBG("unif noise"); + for (auto v : complex_.vertex_range()) + complex_.point(v) = add_uniform_noise(complex_.point(v),amplitude); + } + +private: + Point add_uniform_noise(const Point& point,double amplitude){ + std::vector new_point(point.dimension()); + for(int i = 0 ; i < point.dimension();++i){ + new_point[i] = point[i] + (rand() % 2 - .5) * amplitude; + } + return Point(point.dimension(), new_point.begin(),new_point.end()); + } + +public: + + void lloyd(int num_iterations,int num_closest_neighbors){ + UIDBG("lloyd"); + Lloyd_builder lloyd_builder(complex_,1); + } + + double squared_eucl_distance(const Point& p1,const Point& p2) const{ + return Geometry_trait::Squared_distance_d()(p1,p2); + } + + // complex operations from points + void build_rips(double alpha){ + UIDBG("build_rips"); + Rips_builder rips_builder(complex_,alpha); + } + + void build_k_nearest_neighbors(unsigned k){ + UIDBG("build_k_nearest"); + complex_.keep_only_vertices(); + K_nearest_builder k_nearest_builder(complex_,k); + } + + void build_delaunay(){ + UIDBG("build_delaunay"); + complex_.keep_only_vertices(); + } + + + + void contract_edges(unsigned num_contractions){ + Clock c; + Edge_contractor contractor(complex_,num_contractions); + std::cout<<"Time to simplify: "< collapsor(complex_,complex_.num_vertices()); + UIDBGMSG("num vertices collapsed:",old_num_vertices - complex_.num_vertices()); + } + + void collapse_edges(unsigned num_collapses){ + Edge_collapsor collapsor(complex_,complex_.num_edges()); + } + + + void show_graph_stats(){ + std::cout << "++++++ Graph stats +++++++"<< std::endl; + std::cout << "Num vertices : " << complex_.num_vertices()<::max(); + for(auto v : complex_.vertex_range()) + res= std::min(res,complex_.degree(v)); + return res; + } + + int max_degree() const{ + int res = 0; + for(auto v : complex_.vertex_range()) + res= std::max(res,complex_.degree(v)); + return res; + } + + int avg_degree() const{ + int res = 0; + for(auto v : complex_.vertex_range()) + res+= complex_.degree(v); + return res / complex_.num_vertices(); + } + +public: + + + + void show_complex_stats(){ + std::cout << "++++++ Mesh stats +++++++"<< std::endl; + std::cout << "Num vertices : " << complex_.num_vertices()< persistence(complex_,std::cout,Persistence_params(p,threshold,max_dim,min_pers)); + } + + +private: + void run_chomp(){ + save_complex_in_file_for_chomp(); + system("../src/utils/homsimpl chomp.sim"); + } + + void save_complex_in_file_for_chomp(){ + std::ofstream file; + file.open("chomp.sim"); + for(const auto &s : complex_.simplex_range()){ + bool first = true; + file<<"("; + for(auto x : s){ + if(first) first = false; + else file<<","; + file << x; + } + file<<")\n"; + } + } +public: + + + unsigned num_vertices() const{ + return complex_.num_vertices(); + } +}; + +#endif /* MODEL_H_ */ diff --git a/src/GudhUI/todo.txt b/src/GudhUI/todo.txt new file mode 100644 index 00000000..19d99a77 --- /dev/null +++ b/src/GudhUI/todo.txt @@ -0,0 +1,22 @@ +-- general + +o bug avec kreanrest neighbors lorsqu on baisse k après contraction après collapse vertices + +o clarify visitor sk_bl + + + +-- ui + +x points dimension arbitraire +x contractions + + +x faire le lien MainWindow - Model + + + + +-- bug +x bug ordre contraction -> just that first vertex placement dont work great +x pb construction rips diff --git a/src/GudhUI/utils/Edge_collapsor.h b/src/GudhUI/utils/Edge_collapsor.h new file mode 100644 index 00000000..9cf880e0 --- /dev/null +++ b/src/GudhUI/utils/Edge_collapsor.h @@ -0,0 +1,84 @@ +/* + * Collapsor.h + * + * Created on: Sep 25, 2014 + * Author: dsalinas + */ + +#ifndef COLLAPSOR_H_ +#define COLLAPSOR_H_ + +#include +#include "utils/Edge_contractor.h" + +/** + * Iteratively puts every vertex at the center of its neighbors + */ +template class Edge_collapsor{ +private: + SkBlComplex& complex_; + unsigned num_collapses_; +public: + typedef typename SkBlComplex::Vertex_handle Vertex_handle; + typedef typename SkBlComplex::Edge_handle Edge_handle; + + /** + * @brief Modify complex to be the expansion of the k-nearest neighbor + * symetric graph. + */ + Edge_collapsor(SkBlComplex& complex,unsigned num_collapses): + complex_(complex),num_collapses_(num_collapses) + { + std::list edges; + edges.insert(edges.begin(),complex_.edge_range().begin(),complex_.edge_range().end()); + + edges.sort( + [&](Edge_handle e1,Edge_handle e2){ + return squared_edge_length(e1) < squared_edge_length(e2); + }); + + collapse_edges(edges); + + } + +private: + + + void collapse_edges(std::list& edges){ + while(!edges.empty() && num_collapses_--){ + Edge_handle current_edge = edges.front(); + edges.pop_front(); + if(is_link_reducible(current_edge)) + complex_.remove_edge(current_edge); + } + + } + + bool is_link_reducible(Edge_handle e){ + auto link = complex_.link(e); + + if(link.empty()) return false; + + if(link.is_cone()) return true; + + if(link.num_connected_components()>1) return false; + + Edge_contractor contractor(link,link.num_vertices()-1); + + return (link.num_vertices()==1); + } + + + double squared_edge_length(Edge_handle e) const{ + return squared_eucl_distance(complex_.point(complex_.first_vertex(e)),complex_.point(complex_.second_vertex(e))); + } + + double squared_eucl_distance(const Point& p1,const Point& p2) const{ + return Geometry_trait::Squared_distance_d()(p1,p2); + } + +}; + + + +#endif /* COLLAPSOR_H_ */ diff --git a/src/GudhUI/utils/Edge_contractor.h b/src/GudhUI/utils/Edge_contractor.h new file mode 100644 index 00000000..c7a86e0b --- /dev/null +++ b/src/GudhUI/utils/Edge_contractor.h @@ -0,0 +1,68 @@ +/* + * Contractor.h + * + * Created on: Sep 25, 2014 + * Author: dsalinas + */ + +#ifndef EDGE_CONTRACTOR_H_ +#define EDGE_CONTRACTOR_H_ + + +#include "gudhi/Skeleton_blocker_contractor.h" + +#include "gudhi/Contraction/Edge_profile.h" +#include "gudhi/Contraction/policies/Cost_policy.h" + + +/** + * Iteratively puts every vertex at the center of its neighbors + */ +template class Edge_contractor{ +private: + SkBlComplex& complex_; + unsigned num_contractions_; + + /** + * @brief return a cost corresponding to the squared length of the edge + */ + template< typename EdgeProfile> class Length_cost : public contraction::Cost_policy{ + public: + typedef typename contraction::Cost_policy::Cost_type Cost_type; + typedef typename EdgeProfile::Point Point; + Cost_type operator()(const EdgeProfile& profile, const boost::optional& placement) const override{ + Cost_type res; + if(!placement) return res; + return Geometry_trait::Squared_distance_d()(profile.p0(),profile.p1()); //not working?? + } + }; + + public: + typedef typename SkBlComplex::Vertex_handle Vertex_handle; + typedef typename SkBlComplex::Edge_handle Edge_handle; + + /** + * @brief Modify complex to be the expansion of the k-nearest neighbor + * symetric graph. + */ + Edge_contractor(SkBlComplex& complex,unsigned num_contractions): + complex_(complex),num_contractions_(num_contractions) + { + typedef typename contraction::Edge_profile Profile; + num_contractions = (std::min)((int)num_contractions,(int)(complex_.num_vertices()-1)); + contraction::Skeleton_blocker_contractor contractor( + complex_, + new Length_cost>(), + contraction::make_first_vertex_placement(), + contraction::make_link_valid_contraction(), + contraction::make_remove_popable_blockers_visitor() + ); + contractor.contract_edges(num_contractions); + } + + +}; + + + +#endif /* EDGE_CONTRACTOR_H_ */ diff --git a/src/GudhUI/utils/Furthest_point_epsilon_net.h b/src/GudhUI/utils/Furthest_point_epsilon_net.h new file mode 100644 index 00000000..590b65c4 --- /dev/null +++ b/src/GudhUI/utils/Furthest_point_epsilon_net.h @@ -0,0 +1,134 @@ +/* + * Furthest_point_epsilon_net.h + * + * Created on: Sep 26, 2014 + * Author: dsalinas + */ + +#ifndef FURTHEST_POINT_EPSILON_NET_H_ +#define FURTHEST_POINT_EPSILON_NET_H_ + +#include "utils/UI_utils.h" +#include + +/** + * Computes an epsilon net with furthest point strategy. + */ +template class Furthest_point_epsilon_net{ +private: + SkBlComplex& complex_; + typedef typename SkBlComplex::Vertex_handle Vertex_handle; + typedef typename SkBlComplex::Edge_handle Edge_handle; + + /** + * Let V be the set of vertices. + * Initially v0 is one arbitrarly vertex and the set V0 is {v0}. + * Then Vk is computed as follows. + * First we compute the vertex pk that is the furthest from Vk + * then Vk = Vk \cup pk. + * The radius of pk is its distance to Vk and its meeting vertex + * is the vertex of Vk for which this distance is achieved. + */ + struct Net_filtration_vertex{ + Vertex_handle vertex_handle; + Vertex_handle meeting_vertex; + double radius; + + + Net_filtration_vertex( + Vertex_handle vertex_handle_, + Vertex_handle meeting_vertex_, + double radius_): + vertex_handle(vertex_handle_),meeting_vertex(meeting_vertex_),radius(radius_) + {} + + bool operator<(const Net_filtration_vertex& other ) const{ + return radius < other.radius; + } + + }; + +public: + + + std::vector net_filtration_; + + /** + * @brief Modify complex to be the expansion of the k-nearest neighbor + * symetric graph. + */ + Furthest_point_epsilon_net(SkBlComplex& complex): + complex_(complex) + { + if(!complex.empty()){ + init_filtration(); + for(int k = 2; k < net_filtration_.size(); ++k){ + update_radius_value(k); + } + } + } + + //xxx does not work if complex not full + double radius(Vertex_handle v){ + return net_filtration_[v.vertex].radius; + } + + + + +private: + + void init_filtration(){ + Vertex_handle v0 = *(complex_.vertex_range().begin()); + net_filtration_.reserve(complex_.num_vertices()); + for(auto v : complex_.vertex_range()){ + if(v != v0) + net_filtration_.push_back( + Net_filtration_vertex(v, + Vertex_handle(-1), + squared_eucl_distance(v,v0)) + ); + } + net_filtration_.push_back(Net_filtration_vertex(v0,Vertex_handle(-1),1e10)); + auto n = net_filtration_.size(); + sort_filtration(n-1); + } + + void update_radius_value(int k){ + int n = net_filtration_.size(); + int index_to_update = n-k; + for(int i = 0; i< index_to_update; ++i){ + net_filtration_[i].radius = (std::min)(net_filtration_[i].radius , + squared_eucl_distance( + net_filtration_[i].vertex_handle, + net_filtration_[index_to_update].vertex_handle + ) + ); + } + sort_filtration(n-k); + } + + /** + * sort all i first elements. + */ + void sort_filtration(int i){ + std::sort(net_filtration_.begin(),net_filtration_.begin()+ i); + } + + double squared_eucl_distance(Vertex_handle v1,Vertex_handle v2) const{ + return std::sqrt(Geometry_trait::Squared_distance_d()( + complex_.point(v1),complex_.point(v2)) + ); + } + + void print_filtration() const{ + for(auto v : net_filtration_){ + std::cerr <<"v="< d="< +#include +#include +#include +#include + +#include "utils/UI_utils.h" +#include "model/Complex_typedefs.h" + +template class K_nearest_builder{ +private: + + //todo uggh no virtual delete operator in Point + // so do a composition asap + class Point_d_with_id : public Point{ + typedef Point Base; + public: + Complex::Vertex_handle vertex_handle; + Point_d_with_id(int d=0) : Point(d) {} +// Point_d_with_id(int d, const Origin &o) : Base(d,o) {} + + Point_d_with_id(int a, int b, int c = 1) : + Base(RT(a),RT(b),RT(c)) {} + Point_d_with_id(int a, int b, int c, int d) : + Base(RT(a),RT(b),RT(c),RT(d)) {} + + template + Point_d_with_id (int d, InputIterator first, InputIterator last) + : Base (d, first, last) {} + template + + Point_d_with_id(const Point_d_with_id &p) : Base(p) {} + Point_d_with_id(const Base& p) : Base(p) {} + Point_d_with_id(const Base& p,Complex::Vertex_handle v) : Base(p),vertex_handle(v) {} + + }; + + struct Kernel_with_id : public Geometry_trait{ + typedef Point_d_with_id Point_d; + }; + + + /** + * TODO wrap vertex handle in class passed to tree + */ + typedef Kernel_with_id K; + typedef typename K::Point_d Point_d; + typedef typename CGAL::Search_traits_d TreeTraits; + typedef typename CGAL::Orthogonal_k_neighbor_search Neighbor_search; + typedef typename Neighbor_search::Tree Tree; + + SkBlComplex& complex_; +public: + + /** + * @brief Modify complex to be the expansion of the k-nearest neighbor + * symetric graph. + */ + K_nearest_builder(SkBlComplex& complex,unsigned k):complex_(complex){ + complex.keep_only_vertices(); + compute_edges(k); + } + +private: + + + + double squared_eucl_distance(const Point& p1,const Point& p2) const{ + return Geometry_trait::Squared_distance_d()(p1,p2); + } + + void compute_edges(unsigned k){ + + std::list points_with_id; + for(auto v: complex_.vertex_range()){ + Point_d_with_id point_v(complex_.point(v),v); + points_with_id.push_back(point_v); + } + + Tree tree(points_with_id.begin(),points_with_id.end()); + + + for (auto p : complex_.vertex_range()){ + Neighbor_search search(tree, complex_.point(p),k+1); + for(auto it = ++search.begin(); it != search.end(); ++it){ + auto q = it->first.vertex_handle; + if (p != q && complex_.contains_vertex(p) && complex_.contains_vertex(q)) + complex_.add_edge(p,q); + } + } + } + + +}; + +#endif /* K_NEAREST_BUILDER_H_ */ diff --git a/src/GudhUI/utils/Lloyd_builder.h b/src/GudhUI/utils/Lloyd_builder.h new file mode 100644 index 00000000..db2a7973 --- /dev/null +++ b/src/GudhUI/utils/Lloyd_builder.h @@ -0,0 +1,78 @@ +/* + * Lloyd.h + * + * Created on: Sep 25, 2014 + * Author: dsalinas + */ + +#ifndef LLOYD_H_ +#define LLOYD_H_ + + +#include + +/** + * Iteratively puts every vertex at the center of its neighbors + */ +template class Lloyd_builder{ +private: + SkBlComplex& complex_; + int dim; +public: + typedef typename SkBlComplex::Vertex_handle Vertex_handle; + /** + * @brief Modify complex to be the expansion of the k-nearest neighbor + * symetric graph. + */ + Lloyd_builder(SkBlComplex& complex,unsigned num_iterations):complex_(complex),dim(-1){ + if(!complex_.empty()){ + dim = get_dimension(); + while(num_iterations--){ + std::list new_points; + for(auto v : complex.vertex_range()) + new_points.push_back(barycenter_neighbors(v)); + + auto new_points_it = new_points.begin(); + for(auto v : complex.vertex_range()) + complex_.point(v) = *(new_points_it++); + } + } + } + +private: + + int get_dimension(){ + assert(!complex_.empty()); + for(auto v : complex_.vertex_range()) + return complex_.point(v).dimension(); + return -1; + } + + Point barycenter_neighbors(Vertex_handle v) const{ + if(complex_.degree(v)==0) + return complex_.point(v); + + std::vector res(dim,0); + unsigned num_points = 0; + for(auto nv : complex_.vertex_range(v)){ + ++num_points; + const Point& point = complex_.point(nv); + assert(point.dimension() == dim); + for(int i = 0; i < point.dimension() ; ++i) + res[i] += point[i]; + } + for(auto& x : res) + x/= num_points; + return Point(dim,res.begin(),res.end()); + } + + + + double squared_eucl_distance(const Point& p1,const Point& p2) const{ + return Geometry_trait::Squared_distance_d()(p1,p2); + } + +}; + + +#endif /* LLOYD_H_ */ diff --git a/src/GudhUI/utils/MClock.h b/src/GudhUI/utils/MClock.h new file mode 100644 index 00000000..b5c7d191 --- /dev/null +++ b/src/GudhUI/utils/MClock.h @@ -0,0 +1,57 @@ +/* + * Clock.h + * + * Created on: Jun 17, 2014 + * Author: dsalinas + */ + +#ifndef CLOCK_H_ +#define CLOCK_H_ + +#include + + +class MClock{ + +public: + MClock(){ + end_called = false; + begin(); + } + + void begin() const{ + end_called = false; + gettimeofday(&startTime, NULL); + } + + void end() const{ + end_called = true; + gettimeofday(&endTime, NULL); + } + + friend std::ostream& operator<< (std::ostream& stream,const MClock& clock){ + // if(!clock.end_called) clock.end(); + if(!clock.end_called) stream << "end not called"; + else{ + long totalTime = (clock.endTime.tv_sec - clock.startTime.tv_sec) * 1000000L; + totalTime += (clock.endTime.tv_usec - clock.startTime.tv_usec); + stream << clock.num_seconds() <<"s"; + } + return stream; + + } + + double num_seconds() const{ + if(!end_called) end(); + long totalTime = (endTime.tv_sec - startTime.tv_sec) * 1000000L; + totalTime += (endTime.tv_usec - startTime.tv_usec); + return (totalTime / 1000L)/(double) 1000; + } + +private: + mutable struct timeval startTime, endTime; + mutable bool end_called; +}; + + +#endif /* CLOCK_H_ */ diff --git a/src/GudhUI/utils/Persistence_compute.h b/src/GudhUI/utils/Persistence_compute.h new file mode 100644 index 00000000..f7974287 --- /dev/null +++ b/src/GudhUI/utils/Persistence_compute.h @@ -0,0 +1,106 @@ +/* + * Persistence_compute.h + * Created on: Jan 26, 2015 + * This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): David Salinas + * + * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#ifndef PERSISTENCE_COMPUTE_H_ +#define PERSISTENCE_COMPUTE_H_ + + +#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Simplex_tree.h" +#include "gudhi/distance_functions.h" +#include "gudhi/Persistent_cohomology.h" +#include "gudhi/Persistent_cohomology/Multi_field.h" + + +struct Persistence_params{ + int p; + double threshold; + int max_dim; + double min_pers; + + Persistence_params(int p_,double th_,int max_dim_=10,double min_pers_=0) + :p(p_),threshold(th_),max_dim(max_dim_),min_pers(min_pers_){} +}; + + +/** + * Show persistence into output stream + */ +template class Persistence_compute{ +private: + SkBlComplex& complex_; + std::ostream& stream_; +public: + typedef typename SkBlComplex::Vertex_handle Vertex_handle; + typedef typename SkBlComplex::Edge_handle Edge_handle; + + /** + * @brief Compute persistence + * parameters : + * unsigned dim_max + * double threshold + * int p for Z_p + */ + Persistence_compute(SkBlComplex& complex,std::ostream& stream,const Persistence_params& params): +// +// double threshold = 0.5,unsigned dim_max = 8): + complex_(complex),stream_(stream){ + + //for now everything is copied, todo boost adapt iterators to points of SkBlComplex instead of copying to an intial vector + typedef std::vector Point_t; + std::vector< Point_t > points; + points.reserve(complex.num_vertices()); + for(auto v : complex.vertex_range()){ + const auto & pt = complex.point(v); + Point_t pt_to_add(pt.cartesian_begin(),pt.cartesian_end()); + points.emplace_back(std::move(pt_to_add)); + } + + + Graph_t prox_graph = compute_proximity_graph( points, params.threshold, euclidean_distance ); + Gudhi::Simplex_tree<> st; + st.insert_graph(prox_graph); + st.expansion( params.max_dim ); + + Gudhi::persistent_cohomology::Persistent_cohomology< Gudhi::Simplex_tree<>,Gudhi::persistent_cohomology::Field_Zp > pcoh (st); + pcoh.init_coefficients( params.p ); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology( INFINITY ); //put params.min_persistence + stream_<<"persistence: \n"; + pcoh.output_diagram(stream_); + } + +private: + + +}; + + + + + + +#endif /* PERSISTENCE_COMPUTE_H_ */ diff --git a/src/GudhUI/utils/Rips_builder.h b/src/GudhUI/utils/Rips_builder.h new file mode 100644 index 00000000..9484f9ab --- /dev/null +++ b/src/GudhUI/utils/Rips_builder.h @@ -0,0 +1,56 @@ +/* + * Rips_builder.h + * + * Created on: Sep 10, 2014 + * Author: dsalinas + */ + +#ifndef RIPS_BUILDER_H_ +#define RIPS_BUILDER_H_ + +#include + +#include "utils/UI_utils.h" +#include "model/Complex_typedefs.h" +#include + +#include +#include + +template class Rips_builder{ +private: + SkBlComplex& complex_; +public: + + /** + * @brief Modify complex to be the Rips complex + * of its points with offset alpha. + */ + Rips_builder(SkBlComplex& complex,double alpha):complex_(complex){ + complex.keep_only_vertices(); + if (alpha<=0) return; + compute_edges(alpha); + } + +private: + + + double squared_eucl_distance(const Point& p1,const Point& p2) const{ + return Geometry_trait::Squared_distance_d()(p1,p2); + } + + void compute_edges(double alpha){ + auto vertices = complex_.vertex_range(); + for(auto p = vertices.begin(); p!= vertices.end(); ++p){ + std::cout << *p << " "; std::cout.flush(); + for (auto q = p; ++q != vertices.end(); /**/) + if (squared_eucl_distance(complex_.point(*p),complex_.point(*q)) < 4*alpha*alpha) + complex_.add_edge(*p,*q); + } + std::cout << std::endl; + } + +}; + + +#endif /* RIPS_BUILDER_H_ */ diff --git a/src/GudhUI/utils/UI_utils.h b/src/GudhUI/utils/UI_utils.h new file mode 100644 index 00000000..a7c0689f --- /dev/null +++ b/src/GudhUI/utils/UI_utils.h @@ -0,0 +1,33 @@ +/* + * UI_utils.h + * + * Created on: Aug 25, 2014 + * Author: david + */ + +#ifndef UI_UTILS_H_ +#define UI_UTILS_H_ + +#define PRINT(a) std::cerr << #a << ": " << (a) << " (DISP)"< "; for(auto x:a) std::cerr<< x << ","; std::cerr< class Vertex_collapsor{ +private: + SkBlComplex& complex_; + size_t num_collapses_; +public: + typedef typename SkBlComplex::Vertex_handle Vertex_handle; + typedef typename SkBlComplex::Edge_handle Edge_handle; + + /** + * @brief Modify complex to be the expansion of the k-nearest neighbor + * symetric graph. + */ + Vertex_collapsor(SkBlComplex& complex, size_t num_collapses) : + complex_(complex),num_collapses_(num_collapses) + { +// std::list vertices; +// vertices.insert(vertices.begin(),complex_.vertex_range().begin(),complex_.vertex_range().end()); +// UIDBG("Collapse vertices"); +// collapse_vertices(vertices); + + std::list vertices; + + UIDBG("Compute eps net"); + Furthest_point_epsilon_net eps_net(complex_); + + for(auto vh : eps_net.net_filtration_) + vertices.push_back(vh.vertex_handle); + + UIDBG("Collapse vertices"); + collapse_vertices(vertices); + + + + } + +private: + + + void collapse_vertices(std::list& vertices){ + while(!vertices.empty() && num_collapses_--){ + Vertex_handle current_vertex = vertices.front(); + vertices.pop_front(); + if(is_link_reducible(current_vertex)) + complex_.remove_vertex(current_vertex); + } + } + + bool is_link_reducible(Vertex_handle v){ + auto link = complex_.link(v); + if(link.empty()) return false; + if(link.is_cone()) return true; + if(link.num_connected_components()>1) return false; + Edge_contractor contractor(link,link.num_vertices()-1); + return (link.num_vertices()==1); + } + +}; + + +#endif /* VERTEX_COLLAPSOR_H_ */ diff --git a/src/GudhUI/utils/homsimpl b/src/GudhUI/utils/homsimpl new file mode 100755 index 00000000..12227502 Binary files /dev/null and b/src/GudhUI/utils/homsimpl differ diff --git a/src/GudhUI/view/Color.h b/src/GudhUI/view/Color.h new file mode 100644 index 00000000..a63456cb --- /dev/null +++ b/src/GudhUI/view/Color.h @@ -0,0 +1,21 @@ +/* + * Color.h + * + * Created on: Aug 26, 2014 + * Author: dsalinas + */ + +#ifndef COLOR_H_ +#define COLOR_H_ + + + +struct Color{ + double r; + double g; + double b; + Color(double r_,double g_,double b_):r(r_),g(g_),b(b_){} +}; + + +#endif /* COLOR_H_ */ diff --git a/src/GudhUI/view/FirstCoordProjector.h b/src/GudhUI/view/FirstCoordProjector.h new file mode 100644 index 00000000..2659eef1 --- /dev/null +++ b/src/GudhUI/view/FirstCoordProjector.h @@ -0,0 +1,24 @@ +/* + * FirstCoordProjector.h + * + * Created on: Aug 27, 2014 + * Author: dsalinas + */ + +#ifndef FIRSTCOORDPROJECTOR_H_ +#define FIRSTCOORDPROJECTOR_H_ + +#include "utils/UI_utils.h" +#include "Projector3D.h" + +class FirstCoordProjector3D : public Projector3D{ + typedef Projector3D::Point Point; + typedef Projector3D::Point_3 Point_3; + + Point_3 operator()(const Point& p) const{ + assert(p.dimension()>=3); + return Point_3(p.x(),p.y(),p.z()); + } +}; + +#endif /* FIRSTCOORDPROJECTOR_H_ */ diff --git a/src/GudhUI/view/Projector3D.h b/src/GudhUI/view/Projector3D.h new file mode 100644 index 00000000..503b35c5 --- /dev/null +++ b/src/GudhUI/view/Projector3D.h @@ -0,0 +1,28 @@ +/* + * Projector.h + * + * Created on: Aug 27, 2014 + * Author: dsalinas + */ + +#ifndef PROJECTOR3D_H_ +#define PROJECTOR3D_H_ + +#include "model/Complex_typedefs.h" + + +class Projector3D{ +public: + typedef Geometry_trait::Point Point; + typedef Geometry_trait::Point_3 Point_3; + + virtual Point_3 operator()(const Point&) const = 0; + + virtual ~Projector3D(){ + } + +}; + + + +#endif /* PROJECTOR3D_H_ */ diff --git a/src/GudhUI/view/View_parameter.h b/src/GudhUI/view/View_parameter.h new file mode 100644 index 00000000..39c5d7dd --- /dev/null +++ b/src/GudhUI/view/View_parameter.h @@ -0,0 +1,137 @@ +/* + * View_parameter.h + * + * Created on: Mar 10, 2014 + * Author: David Salinas + * Copyright 2013 INRIA. All rights reserved + */ + +#ifndef VIEW_PARAMETER_H_ +#define VIEW_PARAMETER_H_ + +#include + +/** + * Different parameters for the view such as the camera angle, + * the light, options for vertices/edges/triangles. + */ +class View_parameter{ +public: + bool light; + bool relative_light; + + double size_vertices; + double size_edges; + double light_edges; // in 0-1 + double light_triangles;// in 0-1 + + /** + * light angle + */ + double theta; + double phi; + + enum VERTEX_MODE{ V_NONE,V_SIMPLE,V_COUNT}; + enum EDGE_MODE{ E_NONE,E_SIMPLE,E_COUNT}; + enum TRIANGLE_MODE{ T_NONE,T_SIMPLE,T_COUNT}; + + + + + VERTEX_MODE vertex_mode; + EDGE_MODE edge_mode; + TRIANGLE_MODE triangle_mode; + + void change_vertex_mode(){ + int current_value = vertex_mode; + vertex_mode = static_cast(++current_value % V_COUNT); + std::cout<<"Vertex mode : "; + switch (vertex_mode) { + case V_NONE: + std::cout<<"empty\n"; + break; + case V_SIMPLE: + std::cout<<"simple\n"; + break; + default: + break; + } + } + + void change_vertex_mode(int new_mode){ + vertex_mode = static_cast(new_mode % V_COUNT); + } + + void change_edge_mode(){ + int current_value = edge_mode; + edge_mode = static_cast(++current_value % E_COUNT); + } + + void change_edge_mode(int new_mode){ + edge_mode = static_cast(new_mode % E_COUNT); + } + + + void change_triangle_mode(){ + int current_value = triangle_mode; + triangle_mode = static_cast(++current_value % T_COUNT); + } + + + + + + View_parameter(){ + light = true; + relative_light = true; + vertex_mode = V_SIMPLE; + edge_mode = E_SIMPLE; + triangle_mode = T_NONE; + + size_vertices = 3; + size_edges = 2; + + light_edges = 0.3; + light_triangles = 0.85; + theta = 0; + phi = 0; + } + + friend std::ostream& operator<<(std::ostream& stream, const View_parameter& param){ + stream << param.light<< " "; + stream << param.relative_light<< " "; + stream << param.vertex_mode<< " "; + stream << param.edge_mode<< " "; + stream << param.triangle_mode<< " "; + stream << param.size_vertices<< " "; + stream << param.size_edges<< " "; + stream << param.light_edges<< " "; + stream << param.light_triangles<< " "; + stream << param.theta<< " "; + stream << param.phi<< " "; + return stream; + } + + friend std::istream& operator>>(std::istream& stream, View_parameter& param){ + stream >> param.light; + stream >> param.relative_light; + int a; + stream>>a; + param.vertex_mode = static_cast(a % V_COUNT); + stream>>a; + param.edge_mode = static_cast(a % E_COUNT); + stream>>a; + param.triangle_mode = static_cast(a % T_COUNT); + stream>>a; + stream >> param.size_vertices; + stream >> param.size_edges; + stream >> param.light_edges; + stream >> param.light_triangles; + stream >> param.theta; + stream >> param.phi; + return stream; + } + +}; + +#endif /* VIEW_PARAMETER_H_ */ diff --git a/src/GudhUI/view/Viewer.cpp b/src/GudhUI/view/Viewer.cpp new file mode 100644 index 00000000..d8a35faf --- /dev/null +++ b/src/GudhUI/view/Viewer.cpp @@ -0,0 +1,197 @@ +/* + * Viewer.cpp + * + * Created on: Aug 26, 2014 + * Author: dsalinas + */ + +#include "Viewer.h" +#include "utils/UI_utils.h" + +Viewer::Viewer(QWidget* parent): QGLViewer(QGLFormat(QGL::SampleBuffers),parent),instructor(0),theta(0),phi(0){ +} + +void +Viewer::set_instructor(Viewer_instructor* instructor_){ + instructor = instructor_; +} + +void +Viewer::show_entire_scene(){ + this->showEntireScene(); +} + +void +Viewer::draw(){ + instructor->give_instructions(); +} + + +void +Viewer::set_bounding_box(const Point_3 & lower_left,const Point_3 & upper_right){ + this->camera()->setSceneBoundingBox( + qglviewer::Vec(lower_left[0], lower_left[1], lower_left[2]), + qglviewer::Vec(upper_right[0], upper_right[1], upper_right[2]) + ); +} + +void +Viewer::update_GL(){ + this->updateGL(); + +} + +void +Viewer::init_scene(){ + this->setBackgroundColor(Qt::white); + ::glEnable(GL_LINE_SMOOTH); + init_light(); +} + +void +Viewer::init_light(){ + ::glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); +} + +void +Viewer::set_light(){ + if(theta>=0 && phi >=0){ + const GLfloat pos[4] = {(float)(sin(phi)*cos(theta)),(float)(sin(phi)*sin(theta)),(float)(cos(phi)),0.}; + glLightfv(GL_LIGHT0, GL_POSITION, pos); + } +} + +void +Viewer::set_light_direction(double theta_,double phi_){ + theta = theta_; + phi = phi_; +} + +/** + * set the light in the direction of the observer + */ +void +Viewer::set_light_direction(){ + theta = -1; + phi = -1; +} + + +void +Viewer::postSelection(const QPoint& point){ + bool found; + + auto vec = this->camera()->pointUnderPixel(point,found); + + if(found){ + Point_3 position(vec[0],vec[1],vec[2]); + emit(click(position)); + } +} + +//////////////////////// +// draw +//////////////////////// +void +Viewer::set_size_point(double size_points){ + ::glPointSize(size_points); +} + +void +Viewer::draw_point(const Point_3& p,const Color& color,double size_points){ + ::glColor3f(color.r,color.g,color.b); + ::glDisable(GL_LIGHTING); + ::glEnable(GL_POINT_SMOOTH); + ::glPointSize(size_points); + ::glBegin(GL_POINTS); + ::glVertex3d(p.x(), p.y(), p.z()); + ::glEnd(); + ::glDisable(GL_POINT_SMOOTH); +} + +void +Viewer::begin_draw_points(double size,bool light){ + light?glEnable(GL_LIGHTING):glDisable(GL_LIGHTING); + ::glEnable(GL_POINT_SMOOTH); + ::glPointSize(size); + ::glBegin(GL_POINTS); +} + +void +Viewer::set_color(const Color& color){ + ::glColor3f(color.r,color.g,color.b); +} + +void +Viewer::draw_points(const Point_3 & point){ + ::glVertex3d(point.x(),point.y(),point.z()); +} + +void +Viewer::end_draw_points(){ + ::glEnd(); + ::glDisable(GL_POINT_SMOOTH); +} + +void +Viewer::draw_edge(const Point_3 &a,const Point_3 &b,const Color& color,double size){ + ::glColor3f(color.r,color.g,color.b); + ::glPointSize(3.0); + ::glLineWidth(size); + ::glBegin(GL_LINES); + ::glVertex3f(a.x(),a.y(),a.z()); + ::glVertex3f(b.x(),b.y(),b.z()); + ::glEnd(); +} + +void +Viewer::begin_draw_edges(double size,bool light){ + ::glLineWidth(size); + ::glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + ::glEnable(GL_POLYGON_OFFSET_LINE); + ::glPolygonOffset(3.0f,-3.0f); + light?glEnable(GL_LIGHTING):glDisable(GL_LIGHTING); + ::glBegin(GL_LINES); +} + +void +Viewer::draw_edges(const Point_3 &a,const Point_3 &b){ + ::glVertex3f(a.x(),a.y(),a.z()); + ::glVertex3f(b.x(),b.y(),b.z()); +} + +void +Viewer::end_draw_edges(){ + ::glEnd(); +} + +void +Viewer::begin_draw_triangles(double size,bool light,bool transparent){ + if(transparent){ + ::glEnable (GL_BLEND); + ::glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + ::glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + ::glEnable(GL_POLYGON_OFFSET_FILL); + ::glPolygonOffset(3.0f,-3.0f); + light?glEnable(GL_LIGHTING):glDisable(GL_LIGHTING); + ::glBegin(GL_TRIANGLES); +} + +void +Viewer::draw_triangles(const Point_3& p1,const Point_3& p2,const Point_3& p3){ + if(!CGAL::collinear(p1,p2,p3)){ + auto triangle_normal = CGAL::unit_normal(p1,p2,p3); + ::glNormal3d(triangle_normal.x(),triangle_normal.y(),triangle_normal.z()); + ::glVertex3d(p1.x(),p1.y(),p1.z()); + ::glVertex3d(p2.x(),p2.y(),p2.z()); + ::glVertex3d(p3.x(),p3.y(),p3.z()); + } +} + +void +Viewer::end_draw_triangles(){ + ::glEnd(); +} + +#include "Viewer.moc" diff --git a/src/GudhUI/view/Viewer.h b/src/GudhUI/view/Viewer.h new file mode 100755 index 00000000..5639aa56 --- /dev/null +++ b/src/GudhUI/view/Viewer.h @@ -0,0 +1,96 @@ +#ifndef VIEWER_H +#define VIEWER_H + +#include +#include "View_parameter.h" +#include "model/Complex_typedefs.h" +#include "Color.h" +#include "Viewer_instructor.h" + +class Viewer_instructor; + +class Viewer : public QGLViewer { + Q_OBJECT + + Viewer_instructor * instructor; + + /** + * light angles + */ + double theta,phi; + typedef Complex::GT Gudhi_kernel; + typedef Gudhi_kernel::Point_3 Point_3; +public: + Viewer(QWidget* parent); + + void set_instructor(Viewer_instructor* instructor_); + + void show_entire_scene(); + + void draw(); + + + void set_bounding_box(const Point_3 & lower_left,const Point_3 & upper_right); + + void update_GL(); + + void init_scene(); + + void init_light(); + + void set_light(); + + void set_light_direction(double theta,double phi); + + /** + * set the light in the direction of the observer + */ + void set_light_direction(); + + +protected: + virtual void postSelection(const QPoint& point); + + +public: + + //////////////////////// + // draw + //////////////////////// + void set_size_point(double size_points); + + void set_color(const Color& color); + + void draw_point(const Point_3& p,const Color& color,double size_points); + + void begin_draw_points(double size,bool light=false); + + void draw_points(const Point_3 & point); + + void end_draw_points(); + + void draw_edge(const Point_3 &a,const Point_3 &b,const Color& color,double size); + + void begin_draw_edges(double size,bool light=false); + + void draw_edges(const Point_3 &a,const Point_3 &b); + + void end_draw_edges(); + + void begin_draw_triangles(double size,bool light,bool transparent = false); + + void draw_triangles(const Point_3& p1,const Point_3& p2,const Point_3& p3); + + //todo remove + void draw_triangles(const std::vector& points); + + void end_draw_triangles(); + + + signals: + void click(const Point_3& position); +}; + + + +#endif diff --git a/src/GudhUI/view/Viewer_instructor.cpp b/src/GudhUI/view/Viewer_instructor.cpp new file mode 100644 index 00000000..3cb8f152 --- /dev/null +++ b/src/GudhUI/view/Viewer_instructor.cpp @@ -0,0 +1,206 @@ +/* + * Viewer_instructor.cpp + * + * Created on: Aug 26, 2014 + * Author: dsalinas + */ + +#include +#include "Viewer_instructor.h" +#include "utils/UI_utils.h" +#include "FirstCoordProjector.h" + + +Viewer_instructor::Viewer_instructor(QWidget* parent, + Viewer* viewer, + const Complex& mesh +):viewer_(viewer),mesh_(mesh),projector_(new FirstCoordProjector3D()){ + viewer_->set_instructor(this); +} + + +void +Viewer_instructor::initialize_bounding_box(){ + auto pair_bounding_box = compute_bounding_box_corners(); + viewer_->set_bounding_box(proj(pair_bounding_box.first),proj(pair_bounding_box.second)); + viewer_->init_scene(); +} + +std::pair +Viewer_instructor::compute_bounding_box_corners(){ + if(mesh_.empty()){ + return std::make_pair(Point(-1,-1,-1,1),Point(1,1,1,1)); + } + else{ + double x_min = 1e10; + double y_min = 1e10; + double z_min = 1e10; + double x_max = -1e10; + double y_max = -1e10; + double z_max = -1e10; + for( auto vi : mesh_.vertex_range()) + { + auto pt = proj(mesh_.point(vi)); + x_min = (std::min)(x_min,pt.x()); + y_min = (std::min)(y_min,pt.y()); + z_min = (std::min)(z_min,pt.z()); + + x_max = (std::max)(x_max,pt.x()); + y_max = (std::max)(y_max,pt.y()); + z_max = (std::max)(z_max,pt.z()); + + } + return std::make_pair( + Point(x_min,y_min,z_min,1.), + Point(x_max,y_max,z_max,1.) + ); + } +} + +void +Viewer_instructor::show_entire_scene(){ + viewer_->show_entire_scene(); +} + +const qglviewer::Camera* +Viewer_instructor::camera() const{ + return viewer_->camera(); +} + +int +Viewer_instructor::width() const{ + return viewer_->width(); +} +int +Viewer_instructor::height() const{ + return viewer_->height(); +} + +/** + * to change display parameters + */ +View_parameter& +Viewer_instructor::view_params(){ + return view_params_; +} + + +void +Viewer_instructor::give_instructions(){ + if(view_params_.relative_light) + viewer_->set_light_direction(); + else + viewer_->set_light_direction(view_params_.theta,view_params_.phi); + viewer_->set_light(); + + if (view_params_.edge_mode) draw_edges(); + if (view_params_.triangle_mode) draw_triangles(); + if (view_params_.vertex_mode) draw_points(); + +} + +void +Viewer_instructor::draw_edges(){ + viewer_->begin_draw_edges(view_params_.size_edges,false); + + for(auto edge : mesh_.edge_range()){ + set_color_edge(edge); + const Point& a = mesh_.point(mesh_.first_vertex(edge)); + const Point& b = mesh_.point(mesh_.second_vertex(edge)) ; + viewer_->draw_edges(proj(a),proj(b)); + } + + viewer_->end_draw_edges(); +} + +void +Viewer_instructor::draw_triangles(){ + const double size_triangles = 1.0; + viewer_->begin_draw_triangles(size_triangles,view_params_.light); + + for(const auto& fit : mesh_.triangle_range()) { + set_color_triangle(fit); + if(view_params_.triangle_mode){ + auto fit_it = fit.begin(); + const Point& p1 = mesh_.point(*fit_it); + const Point& p2 = mesh_.point(*(++fit_it)); + const Point& p3 = mesh_.point(*(++fit_it)); + viewer_->draw_triangles(proj(p1),proj(p2),proj(p3)); + } + } + viewer_->end_draw_triangles(); +} + +void +Viewer_instructor::draw_points(){ + viewer_->begin_draw_points( view_params_.size_vertices); + for( auto vi : mesh_.vertex_range()) + { + viewer_->set_size_point(view_params_.size_vertices); + set_color_vertex(vi); + viewer_->draw_points(proj(mesh_.point(vi))); + } + viewer_->end_draw_points(); +} + + +void +Viewer_instructor::draw_edge(const Point&,const Point&){ + +} + +void +Viewer_instructor::draw_point(const Point&){ + +} + + +/** + * set the right color of vertex/edge/triangle considering the view_params choice + */ +void +Viewer_instructor::set_color_vertex(Vertex_handle vh){ + viewer_->set_color(Color(view_params_.light_edges,view_params_.light_edges,view_params_.light_edges)); +} + +void +Viewer_instructor::set_color_edge(Edge_handle eh) { + viewer_->set_color(Color(view_params_.light_edges,view_params_.light_edges,view_params_.light_edges)); +} + +void +Viewer_instructor::set_color_triangle(const Simplex_handle& triangle){ + viewer_->set_color(Color(view_params_.light_triangles,view_params_.light_triangles,view_params_.light_triangles)); +} + + +Viewer_instructor::Point_3 +Viewer_instructor::proj(const Point& p) const{ + return (*projector_)(p); +} + + +void +Viewer_instructor::sceneChanged(){ + UIDBG("sceneChanged"); + viewer_->update_GL(); +} + +void +Viewer_instructor::change_draw_vertices(){ + view_params_.change_vertex_mode(); +} +void +Viewer_instructor::change_draw_edges(){ + view_params_.change_edge_mode(); +} +void +Viewer_instructor::change_draw_triangles(){ + view_params_.change_triangle_mode(); +} +void +Viewer_instructor::change_light(){ + view_params_.light =! view_params_.light ; +} + +#include "Viewer_instructor.moc" diff --git a/src/GudhUI/view/Viewer_instructor.h b/src/GudhUI/view/Viewer_instructor.h new file mode 100755 index 00000000..9a2a236b --- /dev/null +++ b/src/GudhUI/view/Viewer_instructor.h @@ -0,0 +1,108 @@ +#ifndef VIEWER_INSTRUCTOR_H +#define VIEWER_INSTRUCTOR_H + +// todo do a viewer instructor that have directely a pointer to a QGLviewer and buffer ot not triangles + + +#include + +#include +#include +#include + + +#include "model/Complex_typedefs.h" + +#include "Projector3D.h" +#include "View_parameter.h" +#include "Viewer.h" + +class Viewer; +class Viewer_parameter; + +class Viewer_instructor : public QWidget{ + Q_OBJECT + + typedef Geometry_trait::Point_3 Point_3; + typedef Complex::Point Point; + typedef Complex::Vertex_handle Vertex_handle; + typedef Complex::Edge_handle Edge_handle; + typedef Complex::Simplex_handle Simplex_handle; + + + Viewer* viewer_; + View_parameter view_params_; + const Complex& mesh_; + std::unique_ptr projector_; + + +public: + + Viewer_instructor(QWidget* parent, + Viewer* viewer, + const Complex& mesh + ); + + + void initialize_bounding_box(); + + std::pair compute_bounding_box_corners(); + + void show_entire_scene(); + + const qglviewer::Camera* camera() const; + + int width() const; + int height() const; + + /** + * to change display parameters + */ + View_parameter& view_params(); + + +public: + + /** + * gives instructions to the viewer + */ + void give_instructions(); + + void draw_edges(); + void draw_triangles(); + void draw_points(); + + + void draw_edge(const Point&,const Point&); + + void draw_point(const Point&); + + + /** + * set the right color of vertex/edge/triangle considering the view_params choice + */ + void set_color_vertex(Vertex_handle vh); + void set_color_edge(Edge_handle eh); + + void set_color_triangle(const Simplex_handle& triangle); + +private: + /** + * Projection to 3D needed for the viewer. + */ + Point_3 proj(const Point& p) const; + + public slots : + + void sceneChanged(); + + void change_draw_vertices(); + void change_draw_edges(); + void change_draw_triangles(); + void change_light(); + + + +}; + +#endif //VIEWER_INSTRUCTOR_H -- cgit v1.2.3