summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsalinasd <salinasd@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2015-01-27 10:20:13 +0000
committersalinasd <salinasd@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2015-01-27 10:20:13 +0000
commitf527cde6342c5b8109a20f0a6b483327c6569844 (patch)
tree1c0464b56b21ef7767f814b9a35a6e5c68aa7613
parentdf6c26bdcb28805e8949d08dad5acd012e91ecb8 (diff)
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
-rw-r--r--src/GudhUI/CMakeLists.txt80
-rw-r--r--src/GudhUI/gui/KNearestNeighborsMenu.ui150
-rw-r--r--src/GudhUI/gui/MainWindow.cpp283
-rw-r--r--src/GudhUI/gui/MainWindow.h97
-rw-r--r--src/GudhUI/gui/MenuEdgeContraction.ui118
-rw-r--r--src/GudhUI/gui/Menu_edge_contraction.cpp91
-rw-r--r--src/GudhUI/gui/Menu_edge_contraction.h52
-rw-r--r--src/GudhUI/gui/Menu_k_nearest_neighbors.cpp55
-rw-r--r--src/GudhUI/gui/Menu_k_nearest_neighbors.h39
-rw-r--r--src/GudhUI/gui/Menu_persistence.cpp60
-rw-r--r--src/GudhUI/gui/Menu_persistence.h59
-rw-r--r--src/GudhUI/gui/Menu_uniform_neighbors.cpp59
-rw-r--r--src/GudhUI/gui/Menu_uniform_neighbors.h36
-rw-r--r--src/GudhUI/gui/PersistenceMenu.ui139
-rw-r--r--src/GudhUI/gui/UniformNeighborsMenu.ui150
-rw-r--r--src/GudhUI/gui/Viewer.cpp0
-rw-r--r--src/GudhUI/gui/Viewer_instructor.cpp0
-rw-r--r--src/GudhUI/gui/gudhui.cpp17
-rw-r--r--src/GudhUI/gui/main_window.ui231
-rw-r--r--src/GudhUI/model/Complex_typedefs.h39
-rw-r--r--src/GudhUI/model/Model.h291
-rw-r--r--src/GudhUI/todo.txt22
-rw-r--r--src/GudhUI/utils/Edge_collapsor.h84
-rw-r--r--src/GudhUI/utils/Edge_contractor.h68
-rw-r--r--src/GudhUI/utils/Furthest_point_epsilon_net.h134
-rw-r--r--src/GudhUI/utils/K_nearest_builder.h106
-rw-r--r--src/GudhUI/utils/Lloyd_builder.h78
-rw-r--r--src/GudhUI/utils/MClock.h57
-rw-r--r--src/GudhUI/utils/Persistence_compute.h106
-rw-r--r--src/GudhUI/utils/Rips_builder.h56
-rw-r--r--src/GudhUI/utils/UI_utils.h33
-rw-r--r--src/GudhUI/utils/Vertex_collapsor.h76
-rwxr-xr-xsrc/GudhUI/utils/homsimplbin0 -> 118624 bytes
-rw-r--r--src/GudhUI/view/Color.h21
-rw-r--r--src/GudhUI/view/FirstCoordProjector.h24
-rw-r--r--src/GudhUI/view/Projector3D.h28
-rw-r--r--src/GudhUI/view/View_parameter.h137
-rw-r--r--src/GudhUI/view/Viewer.cpp197
-rwxr-xr-xsrc/GudhUI/view/Viewer.h96
-rw-r--r--src/GudhUI/view/Viewer_instructor.cpp206
-rwxr-xr-xsrc/GudhUI/view/Viewer_instructor.h108
41 files changed, 3683 insertions, 0 deletions
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>KNearestNeighborsMenu</class>
+ <widget class="QDialog" name="KNearestNeighborsMenu">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>298</width>
+ <height>209</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>k-nearest neighbors</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="geometry">
+ <rect>
+ <x>50</x>
+ <y>160</y>
+ <width>171</width>
+ <height>32</height>
+ </rect>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ <widget class="QWidget" name="formLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>30</x>
+ <y>10</y>
+ <width>229</width>
+ <height>84</height>
+ </rect>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>k </string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="spinBoxK">
+ <property name="maximum">
+ <number>10000000</number>
+ </property>
+ <property name="value">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Metric</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="comboBoxMetric">
+ <item>
+ <property name="text">
+ <string>Ambient</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Reduced Space</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="gridLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>30</x>
+ <y>110</y>
+ <width>250</width>
+ <height>40</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="1">
+ <widget class="QPushButton" name="pushButtonCompute">
+ <property name="text">
+ <string>Compute</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="checkBoxAutoUpdate">
+ <property name="text">
+ <string>auto update</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>KNearestNeighborsMenu</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>KNearestNeighborsMenu</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
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 <QWidget>
+#include <QInputDialog>
+#include <QFileDialog>
+
+#include <fenv.h>
+
+
+#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 "<<num_collapses<< " vertices\n";
+ model_.contract_edges(num_collapses);
+ update_view();
+}
+
+
+void
+MainWindow::collapse_edges(){
+ std::cerr <<"Collapse "<<100<< " edges\n";
+ model_.collapse_edges(100);
+ update_view();
+}
+
+
+
+void
+MainWindow::collapse_vertices(){
+ std::cerr <<"Collapse vertices edges\n";
+ model_.collapse_vertices(0);
+ update_view();
+}
+
+
+void
+MainWindow::uniform_noise(){
+ bool ok;
+ double amplitude = QInputDialog::getDouble(this, tr("Uniform noise"),
+ tr("Amplitude:"), 0, 0, 10000, 3, &ok);
+ srand(time(NULL));
+ if (ok)
+ model_.uniform_noise(amplitude);
+}
+
+
+void
+MainWindow::lloyd(){
+ //todo 1 ask lloyd parameters
+ model_.lloyd(0,0);
+ update_view();
+}
+
+void
+MainWindow::show_homology_group(){
+ model_.show_homology_group();
+}
+
+void
+MainWindow::show_euler_characteristic(){
+ model_.show_euler_characteristic();
+}
+
+
+
+void
+MainWindow::persistence_menu(){
+ menu_persistence_->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 <QMainWindow>
+#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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MenuEdgeContraction</class>
+ <widget class="QDialog" name="MenuEdgeContraction">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>362</width>
+ <height>209</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Edge contraction</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="5" column="2">
+ <widget class="QSpinBox" name="spinBox_nb_remaining_vertices">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>999999999</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="2">
+ <widget class="QCheckBox" name="checkBox_link_condition">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Link condition</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2" alignment="Qt::AlignRight">
+ <widget class="QLabel" name="txt_nb_collapses">
+ <property name="text">
+ <string>1</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Policy</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="2">
+ <widget class="QComboBox" name="m_simplificationMethod">
+ <item>
+ <property name="text">
+ <string>Length_midpoint</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="2" alignment="Qt::AlignRight">
+ <widget class="QLabel" name="txt_nb_vertices">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Number of vertices</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Number of contractions</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0" colspan="2">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Number of vertices after </string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QSlider" name="horizontalSlider">
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="pushButton_collapse">
+ <property name="text">
+ <string>Perform collapse</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
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 <QMainWindow>
+#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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifndef MENU_PERSISTENCE_H_
+#define MENU_PERSISTENCE_H_
+
+
+#include <QMainWindow>
+#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 <QMainWindow>
+#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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PersistenceMenu</class>
+ <widget class="QDialog" name="PersistenceMenu">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>354</width>
+ <height>275</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Point cloud persistence</string>
+ </property>
+ <widget class="QWidget" name="">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>23</y>
+ <width>318</width>
+ <height>226</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QSpinBox" name="p_spinBox">
+ <property name="minimum">
+ <number>2</number>
+ </property>
+ <property name="value">
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Coefficient Z/pZ</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QSpinBox" name="maxdimension_spinBox">
+ <property name="maximum">
+ <number>9999</number>
+ </property>
+ <property name="value">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Max dimension</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QDoubleSpinBox" name="threshold_doubleSpinBox">
+ <property name="maximum">
+ <double>9999.000000000000000</double>
+ </property>
+ <property name="value">
+ <double>1.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Max Rips offset</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QDoubleSpinBox" name="minpersistence_doubleSpinBox"/>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Minimum Persistence</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>PersistenceMenu</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>PersistenceMenu</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>UniformMenu</class>
+ <widget class="QDialog" name="UniformMenu">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>292</width>
+ <height>209</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Uniform neighbors (Rips)</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="geometry">
+ <rect>
+ <x>50</x>
+ <y>160</y>
+ <width>171</width>
+ <height>32</height>
+ </rect>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ <widget class="QWidget" name="formLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>30</x>
+ <y>10</y>
+ <width>249</width>
+ <height>84</height>
+ </rect>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>alpha</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Metric</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="comboBoxMetric">
+ <item>
+ <property name="text">
+ <string>Ambient</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Reduced Space</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QDoubleSpinBox" name="doubleSpinBoxAlpha">
+ <property name="maximum">
+ <double>100000000.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.100000000000000</double>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="gridLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>30</x>
+ <y>110</y>
+ <width>250</width>
+ <height>40</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="1">
+ <widget class="QPushButton" name="pushButtonCompute">
+ <property name="text">
+ <string>Compute</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="checkBoxAutoUpdate">
+ <property name="text">
+ <string>auto update</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>UniformMenu</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>UniformMenu</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/GudhUI/gui/Viewer.cpp b/src/GudhUI/gui/Viewer.cpp
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/GudhUI/gui/Viewer.cpp
diff --git a/src/GudhUI/gui/Viewer_instructor.cpp b/src/GudhUI/gui/Viewer_instructor.cpp
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/GudhUI/gui/Viewer_instructor.cpp
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 <QApplication>
+#include <CGAL/Qt/resources.h>
+
+
+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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>861</width>
+ <height>880</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>GudhUI</string>
+ </property>
+ <property name="tabShape">
+ <enum>QTabWidget::Rounded</enum>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="Viewer" name="viewer" native="true">
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>861</width>
+ <height>34</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuFile">
+ <property name="title">
+ <string>File</string>
+ </property>
+ <addaction name="actionLoad_points"/>
+ <addaction name="actionLoad_complex"/>
+ <addaction name="actionSave_points"/>
+ <addaction name="actionSave_complex"/>
+ </widget>
+ <widget class="QMenu" name="menuPoints">
+ <property name="title">
+ <string>Points</string>
+ </property>
+ <addaction name="actionNoise"/>
+ </widget>
+ <widget class="QMenu" name="menuGraph">
+ <property name="title">
+ <string>Graph</string>
+ </property>
+ <addaction name="actionK_nearest_neighbors_graph"/>
+ <addaction name="actionUniform_proximity_graph"/>
+ <addaction name="actionShow_graph_stats"/>
+ </widget>
+ <widget class="QMenu" name="menuComplex">
+ <property name="title">
+ <string>Complex</string>
+ </property>
+ <addaction name="actionContract_edges"/>
+ <addaction name="actionCollapse_vertices"/>
+ <addaction name="actionCollapse_edges"/>
+ <addaction name="actionShow_complex_stats"/>
+ <addaction name="actionShow_complex_dimension"/>
+ </widget>
+ <widget class="QMenu" name="menuView">
+ <property name="title">
+ <string>View</string>
+ </property>
+ <addaction name="actionPoints"/>
+ <addaction name="actionEdges"/>
+ <addaction name="actionTriangles"/>
+ <addaction name="actionChange_projection"/>
+ </widget>
+ <widget class="QMenu" name="menuTopology">
+ <property name="title">
+ <string>Topology</string>
+ </property>
+ <addaction name="actionEuler_characteristic"/>
+ <addaction name="actionShow_homology_group"/>
+ <addaction name="actionPersistence"/>
+ </widget>
+ <addaction name="menuFile"/>
+ <addaction name="menuPoints"/>
+ <addaction name="menuGraph"/>
+ <addaction name="menuComplex"/>
+ <addaction name="menuTopology"/>
+ <addaction name="menuView"/>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ <action name="actionLoad_points">
+ <property name="text">
+ <string>Load points</string>
+ </property>
+ </action>
+ <action name="actionLoad_complex">
+ <property name="text">
+ <string>Load complex</string>
+ </property>
+ </action>
+ <action name="actionSave_points">
+ <property name="text">
+ <string>Save points</string>
+ </property>
+ </action>
+ <action name="actionSave_complex">
+ <property name="text">
+ <string>Save complex</string>
+ </property>
+ </action>
+ <action name="actionNoise">
+ <property name="text">
+ <string>Noise</string>
+ </property>
+ </action>
+ <action name="actionLloyd">
+ <property name="text">
+ <string>Lloyd</string>
+ </property>
+ </action>
+ <action name="actionUniform_proximity_graph">
+ <property name="text">
+ <string>Uniform proximity graph</string>
+ </property>
+ </action>
+ <action name="actionK_nearest_neighbors_graph">
+ <property name="text">
+ <string>k-nearest neighbors graph</string>
+ </property>
+ </action>
+ <action name="actionShow_graph_stats">
+ <property name="text">
+ <string>Show graph stats</string>
+ </property>
+ </action>
+ <action name="actionBuild_complex_from_graph">
+ <property name="text">
+ <string>Graph expansion</string>
+ </property>
+ </action>
+ <action name="actionBuild_Delaunay_from_points">
+ <property name="text">
+ <string>Delaunay from points</string>
+ </property>
+ </action>
+ <action name="actionContract_edges">
+ <property name="text">
+ <string>Contract edges</string>
+ </property>
+ </action>
+ <action name="actionCollapse_vertices">
+ <property name="text">
+ <string>Collapse vertices</string>
+ </property>
+ </action>
+ <action name="actionCollapse_edges">
+ <property name="text">
+ <string>Collapse edges</string>
+ </property>
+ </action>
+ <action name="actionPoints">
+ <property name="text">
+ <string>Points</string>
+ </property>
+ </action>
+ <action name="actionEdges">
+ <property name="text">
+ <string>Edges</string>
+ </property>
+ </action>
+ <action name="actionTriangles">
+ <property name="text">
+ <string>Triangles</string>
+ </property>
+ </action>
+ <action name="actionChange_projection">
+ <property name="text">
+ <string>Change projection</string>
+ </property>
+ </action>
+ <action name="actionShow_complex_stats">
+ <property name="text">
+ <string>Show complex stats</string>
+ </property>
+ </action>
+ <action name="actionShow_complex_dimension">
+ <property name="text">
+ <string>Show complex dimension</string>
+ </property>
+ </action>
+ <action name="actionShow_homology_group">
+ <property name="text">
+ <string>Homology groups</string>
+ </property>
+ </action>
+ <action name="actionPersistence">
+ <property name="text">
+ <string>Point cloud persistence</string>
+ </property>
+ </action>
+ <action name="actionEuler_characteristic">
+ <property name="text">
+ <string>Euler characteristic</string>
+ </property>
+ </action>
+ <action name="actionHomology_groups">
+ <property name="text">
+ <string>Homology groups</string>
+ </property>
+ </action>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Viewer</class>
+ <extends>QWidget</extends>
+ <header>view/Viewer.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
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 <CGAL/Kernel_d/Point_d.h>
+
+#include <CGAL/Cartesian.h>
+#include <CGAL/Cartesian_d.h>
+
+
+struct Geometry_trait : public CGAL::Cartesian_d<double> {
+ typedef CGAL::Cartesian<double>::Point_3 Point_3;
+ typedef CGAL::Cartesian<double>::Vector_3 Vector_3;
+ typedef CGAL::Point_d<Cartesian_d<double>> Point;
+ typedef CGAL::Vector_d<Cartesian_d<double>> Vector;
+};
+
+typedef Geometry_trait::Point Point;
+
+
+using namespace Gudhi;
+using namespace Gudhi::skbl;
+
+typedef Skeleton_blocker_simple_geometric_traits<Geometry_trait> 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 <fstream>
+#include <limits>
+#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 <CGAL/Euclidean_distance.h>
+
+
+template<typename Complex>
+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<double>& coords){
+ Point p(coords.size(),coords.begin(),coords.end());
+ complex_.add_vertex(p);
+ }
+
+ void maximal_face(std::vector<int> vertices){
+ if (!load_only_points_){
+ for (int i = 0; i<vertices.size()-1 ; ++i)
+ for (int j = i+1; j<vertices.size()-1 ; ++j)
+ complex_.add_edge(Vertex_handle(vertices[i]),Vertex_handle(vertices[j]));
+ }
+ }
+ void done() const{}
+};
+
+
+class Model{
+
+public:
+ Complex complex_;
+ typedef typename Complex::Vertex_handle Vertex_handle;
+ typedef typename Complex::CVI CVI;
+
+
+ Model():complex_(){
+ }
+
+public:
+ void off_file_open(const std::string& name_file){
+ UIDBGMSG("load off file",name_file);
+ complex_.clear();
+ CGAL_geometric_flag_complex_wrapper<Complex> 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<Complex> 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<double> 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<Complex> 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<Complex> rips_builder(complex_,alpha);
+ }
+
+ void build_k_nearest_neighbors(unsigned k){
+ UIDBG("build_k_nearest");
+ complex_.keep_only_vertices();
+ K_nearest_builder<Complex> 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<Complex> contractor(complex_,num_contractions);
+ std::cout<<"Time to simplify: "<<c.num_seconds()<<"s"<<std::endl;
+ }
+
+
+ void collapse_vertices(unsigned num_collapses){
+
+ auto old_num_vertices = complex_.num_vertices();
+ Vertex_collapsor<Complex> collapsor(complex_,complex_.num_vertices());
+ UIDBGMSG("num vertices collapsed:",old_num_vertices - complex_.num_vertices());
+ }
+
+ void collapse_edges(unsigned num_collapses){
+ Edge_collapsor<Complex> collapsor(complex_,complex_.num_edges());
+ }
+
+
+ void show_graph_stats(){
+ std::cout << "++++++ Graph stats +++++++"<< std::endl;
+ std::cout << "Num vertices : " << complex_.num_vertices()<<std::endl;
+ std::cout << "Num edges : " << complex_.num_edges()<<std::endl;
+ std::cout << "Num connected components : " << complex_.num_connected_components()<<std::endl;
+ std::cout << "Min/avg/max degree : " << min_degree()<<"/"<<avg_degree()<<"/"<<max_degree()<<std::endl;
+ std::cout << "Num connected components : " << complex_.num_connected_components()<<std::endl;
+ std::cout << "Num connected components : " << complex_.num_connected_components()<<std::endl;
+ std::cout << "+++++++++++++++++++++++++"<< std::endl;
+ }
+
+private:
+ int min_degree() const{
+ int res = std::numeric_limits<int>::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()<<std::endl;
+ std::cout << "Num edges : " << complex_.num_edges()<<std::endl;
+ std::cout << "Num connected components : " << complex_.num_connected_components()<<std::endl;
+ std::cout << "+++++++++++++++++++++++++"<< std::endl;
+
+ }
+
+ void show_complex_dimension(){
+ unsigned num_simplices = 0;
+ int euler = 0;
+ int dimension = 0;
+ Clock clock;
+ for(const auto &s : complex_.simplex_range()){
+ num_simplices++;
+ dimension = std::max(s.dimension(),dimension);
+ if(s.dimension()%2==0)
+ euler+=1;
+ else
+ euler-=1;
+ }
+ clock.end();
+ std::cout << "++++++ Mesh dimension +++++++"<< std::endl;
+ std::cout << "Dimension : " << dimension<<std::endl;
+ std::cout << "Euler characteristic : " << euler<<std::endl;
+ std::cout << "Num simplices : " << num_simplices <<std::endl;
+ std::cout << "Total time: " << clock <<std::endl;
+ std::cout << "Time per simplex: " << clock.num_seconds()/num_simplices <<" s"<<std::endl;
+ std::cout << "+++++++++++++++++++++++++"<< std::endl;
+ }
+
+
+ void show_homology_group(){
+ Clock clock;
+ run_chomp();
+ clock.end();
+ }
+
+ void show_euler_characteristic(){
+ unsigned num_simplices = 0;
+ int euler = 0;
+ int dimension = 0;
+ for(const auto &s : complex_.simplex_range()){
+ num_simplices++;
+ dimension = std::max(s.dimension(),dimension);
+ if(s.dimension()%2==0)
+ euler+=1;
+ else
+ euler-=1;
+ }
+ std::cout << "Saw "<<num_simplices<<" simplices with maximum dimension " << dimension<<std::endl;
+ std::cout << "The euler characteristic is : " << euler<<std::endl;
+ }
+
+ void show_persistence( int p,double threshold,int max_dim,double min_pers){
+ Persistence_compute<Complex> 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 <list>
+#include "utils/Edge_contractor.h"
+
+/**
+ * Iteratively puts every vertex at the center of its neighbors
+ */
+template<typename SkBlComplex> 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<Edge_handle> 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<Edge_handle>& 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<Complex> 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<typename SkBlComplex> 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<EdgeProfile>{
+ public:
+ typedef typename contraction::Cost_policy<EdgeProfile>::Cost_type Cost_type;
+ typedef typename EdgeProfile::Point Point;
+ Cost_type operator()(const EdgeProfile& profile, const boost::optional<Point>& 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<Complex> Profile;
+ num_contractions = (std::min)((int)num_contractions,(int)(complex_.num_vertices()-1));
+ contraction::Skeleton_blocker_contractor<Complex> contractor(
+ complex_,
+ new Length_cost<contraction::Edge_profile<Complex>>(),
+ contraction::make_first_vertex_placement<Profile>(),
+ contraction::make_link_valid_contraction<Profile>(),
+ contraction::make_remove_popable_blockers_visitor<Profile>()
+ );
+ 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 <vector>
+
+/**
+ * Computes an epsilon net with furthest point strategy.
+ */
+template<typename SkBlComplex> 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_vertex> 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="<<v.vertex_handle<<"-> d="<<v.radius<<std::endl;
+ }
+ }
+
+};
+
+
+
+#endif /* FURTHEST_POINT_EPSILON_NET_H_ */
diff --git a/src/GudhUI/utils/K_nearest_builder.h b/src/GudhUI/utils/K_nearest_builder.h
new file mode 100644
index 00000000..4acc0fbf
--- /dev/null
+++ b/src/GudhUI/utils/K_nearest_builder.h
@@ -0,0 +1,106 @@
+/*
+ * K_nearest_builder.h
+ *
+ * Created on: Sep 10, 2014
+ * Author: dsalinas
+ */
+
+#ifndef K_NEAREST_BUILDER_H_
+#define K_NEAREST_BUILDER_H_
+
+#include <unordered_map>
+#include <boost/iterator/iterator_facade.hpp>
+#include <CGAL/Euclidean_distance.h>
+#include <CGAL/Orthogonal_k_neighbor_search.h>
+#include <CGAL/Search_traits_d.h>
+
+#include "utils/UI_utils.h"
+#include "model/Complex_typedefs.h"
+
+template<typename SkBlComplex> 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 <class InputIterator>
+ Point_d_with_id (int d, InputIterator first, InputIterator last)
+ : Base (d, first, last) {}
+ template <class InputIterator>
+
+ 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<K> TreeTraits;
+ typedef typename CGAL::Orthogonal_k_neighbor_search<TreeTraits> 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<Point_d_with_id> 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 <vector>
+
+/**
+ * Iteratively puts every vertex at the center of its neighbors
+ */
+template<typename SkBlComplex> 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<Point> 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<double> 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 <sys/time.h>
+
+
+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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#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<typename SkBlComplex> 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<double> 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<Point_t> );
+ 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 <boost/iterator/iterator_facade.hpp>
+
+#include "utils/UI_utils.h"
+#include "model/Complex_typedefs.h"
+#include <CGAL/Euclidean_distance.h>
+
+#include <CGAL/Orthogonal_k_neighbor_search.h>
+#include <CGAL/Search_traits_d.h>
+
+template<typename SkBlComplex> 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)"<<std::endl
+
+#define UIDBG_VERBOSE
+
+
+#ifdef UIDBG_VERBOSE
+#define UIDBG(a) std::cerr << "UIDBG: " << (a)<<std::endl
+#define UIDBGMSG(a,b) std::cerr << "UIDBG: " << a<<b<<std::endl
+#define UIDBGVALUE(a) std::cerr << "UIDBG: " << #a << ": " << a<<std::endl
+#define UIDBGCONT(a) std::cerr << "UIDBG: container "<< #a<<" -> "; for(auto x:a) std::cerr<< x << ","; std::cerr<<std::endl
+#else
+//#define DBG(a) a
+//#define DBGMSG(a,b) b
+//#define DBGVALUE(a) a
+//#define DBGCONT(a) a
+#define UIDBG(a)
+#define UIDBGMSG(a,b)
+#define UIDBGVALUE(a)
+#define UIDBGCONT(a)
+#endif
+
+
+#endif /* UI_UTILS_H_ */
diff --git a/src/GudhUI/utils/Vertex_collapsor.h b/src/GudhUI/utils/Vertex_collapsor.h
new file mode 100644
index 00000000..d4911a35
--- /dev/null
+++ b/src/GudhUI/utils/Vertex_collapsor.h
@@ -0,0 +1,76 @@
+/*
+ * Vertex_collapsor.h
+ *
+ * Created on: Sep 25, 2014
+ * Author: dsalinas
+ */
+
+#ifndef VERTEX_COLLAPSOR_H_
+#define VERTEX_COLLAPSOR_H_
+
+#include "utils/Edge_contractor.h"
+#include "utils/Furthest_point_epsilon_net.h"
+#include "utils/UI_utils.h"
+/**
+ * Iteratively puts every vertex at the center of its neighbors
+ */
+template<typename SkBlComplex> 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<Vertex_handle> vertices;
+// vertices.insert(vertices.begin(),complex_.vertex_range().begin(),complex_.vertex_range().end());
+// UIDBG("Collapse vertices");
+// collapse_vertices(vertices);
+
+ std::list<Vertex_handle> vertices;
+
+ UIDBG("Compute eps net");
+ Furthest_point_epsilon_net<Complex> 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<Vertex_handle>& 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<Complex> 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
--- /dev/null
+++ b/src/GudhUI/utils/homsimpl
Binary files 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 <iostream>
+
+/**
+ * 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<VERTEX_MODE>(++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<VERTEX_MODE>(new_mode % V_COUNT);
+ }
+
+ void change_edge_mode(){
+ int current_value = edge_mode;
+ edge_mode = static_cast<EDGE_MODE>(++current_value % E_COUNT);
+ }
+
+ void change_edge_mode(int new_mode){
+ edge_mode = static_cast<EDGE_MODE>(new_mode % E_COUNT);
+ }
+
+
+ void change_triangle_mode(){
+ int current_value = triangle_mode;
+ triangle_mode = static_cast<TRIANGLE_MODE>(++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<VERTEX_MODE>(a % V_COUNT);
+ stream>>a;
+ param.edge_mode = static_cast<EDGE_MODE>(a % E_COUNT);
+ stream>>a;
+ param.triangle_mode = static_cast<TRIANGLE_MODE>(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 <QGLViewer/qglviewer.h>
+#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<Point_3*>& 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 <utility>
+#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<Complex::Point,Complex::Point>
+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 <memory>
+
+#include <QFileDialog>
+#include <QKeyEvent>
+#include <QGLViewer/camera.h>
+
+
+#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<Projector3D> projector_;
+
+
+public:
+
+ Viewer_instructor(QWidget* parent,
+ Viewer* viewer,
+ const Complex& mesh
+ );
+
+
+ void initialize_bounding_box();
+
+ std::pair<Point,Point> 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