diff --git a/Documentation/biblio/cgal_manual.bib b/Documentation/biblio/cgal_manual.bib
index b17a841fdfd..14293923e58 100644
--- a/Documentation/biblio/cgal_manual.bib
+++ b/Documentation/biblio/cgal_manual.bib
@@ -2637,6 +2637,20 @@ pages = "207--221"
publisher={IEEE}
}
+
+@article{degoes:hal-00758019,
+ title = {{An Optimal Transport Approach to Robust Reconstruction and Simplification of 2D Shapes}},
+ author = {De Goes, Fernando and Cohen-Steiner, David and Alliez, Pierre and Desbrun, Mathieu},
+ booktitle = {{Eurographics Symposium on Geometry Processing 2011}},
+ publisher = {Wiley},
+ pages = {1593-1602},
+ journal = {Computer Graphics Forum},
+ volume = {30},
+ number = {5 },
+ year = {2011},
+}
+
+
% ----------------------------------------------------------------------------
% END OF BIBFILE
% ----------------------------------------------------------------------------
diff --git a/Documentation/doc/Documentation/dependencies b/Documentation/doc/Documentation/dependencies
index 017322bea23..1dbf71978de 100644
--- a/Documentation/doc/Documentation/dependencies
+++ b/Documentation/doc/Documentation/dependencies
@@ -80,6 +80,7 @@ Segment_Delaunay_graph_2
Segment_Delaunay_graph_Linf_2
Straight_skeleton_2
Visibility_2
+Reconstruction_simplification_2
Voronoi_diagram_2
Surface_mesh_simplification
Subdivision_method_3
diff --git a/Documentation/doc/Documentation/packages.txt b/Documentation/doc/Documentation/packages.txt
index 51de944091e..71d42a024d4 100644
--- a/Documentation/doc/Documentation/packages.txt
+++ b/Documentation/doc/Documentation/packages.txt
@@ -95,6 +95,7 @@ h1 {
\package_listing{Surface_mesher}
\package_listing{Skin_surface_3}
\package_listing{Mesh_3}
+\package_listing{Reconstruction_simplification_2}
\section PartReconstruction Surface Reconstruction
diff --git a/Installation/changes.html b/Installation/changes.html
index 3e674281d42..120939a93be 100644
--- a/Installation/changes.html
+++ b/Installation/changes.html
@@ -357,6 +357,34 @@ and src/ directories).
+
+
+
+
+
Reconstruction Simplification 2 (new package)
+
+ -
+ This package implements a method to reconstruct and simplify 2D
+ point sets. The input is a set of 2D points with mass attributes,
+ possibly hampered by noise and outliers. The output is a set of
+ line segments and isolated points which approximate the input points.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Approximation of Ridges and Umbilics on Triangulated Surface Meshes
- This package now supports any model of the
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/CMakeLists.txt b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/CMakeLists.txt
new file mode 100644
index 00000000000..25f6c465aea
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/CMakeLists.txt
@@ -0,0 +1,132 @@
+# This is the CMake script for compiling the Reconstruction_simplification_2 demo.
+
+project(Reconstruction_simplification_2_demo)
+
+cmake_minimum_required(VERSION 2.8.11)
+if(POLICY CMP0043)
+ cmake_policy(SET CMP0043 OLD)
+endif()
+
+set( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true )
+
+# Include this package's headers first
+include_directories( BEFORE ./ ./include ../../include )
+
+# Find CGAL and CGAL Qt5
+find_package(CGAL COMPONENTS Qt5)
+include( ${CGAL_USE_FILE} )
+
+# Find Qt5 itself
+find_package(Qt5 COMPONENTS OpenGL)
+
+# Find OpenGL
+#find_package(OpenGL)
+
+# Find QGLViewer
+if(Qt5_FOUND)
+ add_definitions(-DQT_NO_KEYWORDS)
+ find_package(QGLViewer)
+endif(Qt5_FOUND)
+
+# Find CImg
+find_path(CIMG_INCLUDE_DIR
+ NAMES CImg.h
+ HINTS ENV CIMG_INC_DIR
+ DOC "Path to the header of the CImg library")
+
+if (CIMG_INCLUDE_DIR)
+ add_definitions(-DCGAL_USE_CIMG)
+ include_directories(${CIMG_INCLUDE_DIR})
+ MESSAGE(STATUS "CImg library found, the demo can load point set from image files.")
+else()
+ MESSAGE(STATUS "CImg library was not found, the demo will not be able to load point set. "
+ "Try setting the environment variable CIMG_INC_DIR to point to the path of the directory containing CImg.h.")
+endif()
+
+if(CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
+
+ include_directories ( ${QGLVIEWER_INCLUDE_DIR} )
+
+ set(
+ SRCS
+ glviewer.cpp
+ Reconstruction_simplification_2_demo.cpp
+ window.cpp
+ render.cpp
+ )
+
+ set(
+ MOCS
+ moc_dialog_options.cxx
+ moc_glviewer.cxx
+ moc_window.cxx
+ )
+
+ set(
+ UIS
+ pwsrec.ui
+ options.ui
+ )
+
+ qt5_wrap_ui( UI_FILES ${UIS} )
+
+ include(AddFileDependencies)
+
+ qt5_generate_moc( "window.h" "${CMAKE_CURRENT_BINARY_DIR}/moc_window.cxx" )
+ add_file_dependencies( moc_window.cxx "${CMAKE_CURRENT_SOURCE_DIR}/window.h" )
+
+ qt5_generate_moc( "glviewer.h" "${CMAKE_CURRENT_BINARY_DIR}/moc_glviewer.cxx" )
+ add_file_dependencies( moc_glviewer.cxx "${CMAKE_CURRENT_SOURCE_DIR}/glviewer.h" )
+
+ qt5_generate_moc( "dialog_options.h" "${CMAKE_CURRENT_BINARY_DIR}/moc_dialog_options.cxx" )
+ add_file_dependencies( moc_dialog_options.cxx "${CMAKE_CURRENT_SOURCE_DIR}/dialog_options.h" )
+
+ qt5_add_resources ( RESOURCE_FILES pwsrec.qrc )
+
+ add_executable ( Reconstruction_simplification_2_demo ${SRCS} ${MOCS} ${UI_FILES} ${RESOURCE_FILES} ${CGAL_ADDITIONAL_FILES} ${CGAL_RESOURCE_FILES})
+
+ qt5_use_modules(Reconstruction_simplification_2_demo OpenGL)
+
+ # Link with Qt libraries
+ target_link_libraries( Reconstruction_simplification_2_demo ${QT_LIBRARIES} )
+
+ # Link with CGAL
+ target_link_libraries( Reconstruction_simplification_2_demo ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} )
+
+ # Link with libQGLViewer, OpenGL
+ target_link_libraries( Reconstruction_simplification_2_demo ${QGLVIEWER_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} )
+
+ # Link with CImg dependencies
+ if( NOT WIN32 )
+ target_link_libraries( Reconstruction_simplification_2_demo -L/usr/X11R6/lib -lm -lpthread -lX11 )
+ endif()
+
+ add_to_cached_list( CGAL_EXECUTABLE_TARGETS Reconstruction_simplification_2_demo )
+
+else (CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
+
+ set(RS2_MISSING_DEPS "")
+
+ if(NOT CGAL_FOUND)
+ set(RS2_MISSING_DEPS "the CGAL library, ${RS2_MISSING_DEPS}")
+ endif()
+
+ if(NOT CGAL_Qt5_FOUND)
+ set(RS2_MISSING_DEPS "the CGAL Qt5 library, ${RS2_MISSING_DEPS}")
+ endif()
+
+ if(NOT Qt5_FOUND)
+ set(RS2_MISSING_DEPS "Qt5, ${RS2_MISSING_DEPS}")
+ endif()
+
+ if(NOT OPENGL_FOUND)
+ set(RS2_MISSING_DEPS "OpenGL, ${RS2_MISSING_DEPS}")
+ endif()
+
+ if(NOT QGLVIEWER_FOUND)
+ set(RS2_MISSING_DEPS "QGLViewer, ${RS2_MISSING_DEPS}")
+ endif()
+
+ message(STATUS "NOTICE: This demo requires ${RS2_MISSING_DEPS}and will not be compiled.")
+
+endif (CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/Reconstruction_simplification_2_demo.cpp b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/Reconstruction_simplification_2_demo.cpp
new file mode 100644
index 00000000000..4b5f439bf9e
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/Reconstruction_simplification_2_demo.cpp
@@ -0,0 +1,12 @@
+#include
+#include "window.h"
+
+int main(int argv, char **args)
+{
+ srand(1);
+ QApplication app(argv, args);
+ app.setApplicationName("Reconstruction_simplification_2 Demo");
+ MainWindow window;
+ window.show();
+ return app.exec();
+}
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/Reconstruction_simplification_kerneled_2.h b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/Reconstruction_simplification_kerneled_2.h
new file mode 100644
index 00000000000..8b9bfb69d9d
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/Reconstruction_simplification_kerneled_2.h
@@ -0,0 +1,153 @@
+#ifndef RECONSTRUCTION_SIMPLIFICATION_KERNEL_2_H_
+#define RECONSTRUCTION_SIMPLIFICATION_KERNEL_2_H_
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include // std::pair
+#include
+
+//Qt
+#include
+
+typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
+typedef K::Point_2 Point;
+typedef K::FT FT;
+
+typedef std::pair PointMassPair;
+typedef std::vector PointMassList;
+typedef PointMassList::const_iterator InputIterator;
+
+typedef CGAL::value_type_traits::type MassPoint;
+
+typedef CGAL::First_of_pair_property_map Point_property_map;
+typedef CGAL::Second_of_pair_property_map Mass_property_map;
+
+typedef CGAL::Reconstruction_simplification_2 Rs_2;
+
+class Reconstruction_simplification_kerneled_2:
+ public Rs_2 {
+
+public:
+
+ template
+ Reconstruction_simplification_kerneled_2(const InputRange& input_range,
+ Point_property_map point_pmap, Mass_property_map mass_pmap) :
+ Rs_2(input_range, point_pmap,
+ mass_pmap) {
+ }
+
+ Reconstruction_simplification_kerneled_2() :
+ Rs_2() {
+ }
+
+ // RENDER //
+ void print_stats() const;
+
+ QColor get_color(float value) const;
+
+ void draw_point(const Point& point);
+
+ void draw_segment(const Point& s, const Point& t);
+
+ void draw_edge(const Edge& edge);
+
+ void draw_face(Face_handle face);
+
+ void draw_edge_with_arrow(const Point& s, const Point& t);
+
+ void draw_vertices(const float point_size, const float red,
+ const float green, const float blue);
+
+ void draw_edges(const float line_width, const float red, const float green,
+ const float blue);
+
+ void draw_footpoints(const float line_width, const float red,
+ const float green, const float blue);
+
+ void draw_mesh_footpoints(const Triangulation& mesh, const float line_width,
+ const float red, const float green, const float blue);
+
+ void draw_edge_footpoints(const Triangulation& mesh, const Edge& edge,
+ const float red, const float green, const float blue);
+
+ void draw_pedges(const float line_width);
+
+ void draw_one_pedge(const Edge& edge, const FT value, const FT min_value,
+ const FT max_value, const float line_width);
+
+ void draw_costs(const float line_width, const bool view_ghost);
+
+ void draw_one_cost(const Edge& edge, const FT min_value, const FT max_value,
+ const bool view_ghost);
+
+ void draw_relevance(const float line_width, const int nb);
+
+ void draw_bins(const float thickness);
+
+ void draw_bins_plan0(const Edge& edge);
+
+ void draw_bins_plan1(const Edge& edge);
+
+ void draw_relocation();
+
+ void draw_bezier_curves(const unsigned int nb);
+
+ void draw_one_bezier_curve(const Edge& edge, const unsigned int nb);
+
+ bool locate_edge(const Point& query, Edge& edge);
+
+ void draw_one_ring(const float point_size, const float line_width,
+ const Point& query);
+
+ void draw_mesh_one_ring(const float point_size, const float line_width,
+ const Triangulation& mesh, const Edge& edge);
+
+ void draw_blocking_edges(const float point_size, const float line_width,
+ const Point& query);
+
+ void draw_mesh_blocking_edges(const float point_size,
+ const float line_width, const Triangulation& mesh,
+ const Edge& edge);
+
+ void draw_collapsible_edge(const float point_size, const float line_width,
+ const Point& query);
+
+ void draw_cost_stencil(const float point_size, const float line_width,
+ const Point& query);
+
+ void draw_remove_queue_stencil(const float point_size,
+ const float line_width, const Point& query);
+
+ void draw_push_queue_stencil(const float point_size, const float line_width,
+ const Point& query);
+
+ void draw_bg_faces(const Triangulation& mesh, const float red,
+ const float green, const float blue, const float alpha);
+
+ void draw_bg_edges(const Triangulation& mesh, const float ri,
+ const float gi, const float bi, const float ro, const float go,
+ const float bo);
+
+ void draw_bg_vertices(const Triangulation& mesh, const float red,
+ const float green, const float blue);
+
+ void draw_vertex_faces(Vertex_handle vertex, const Triangulation& mesh,
+ const float red, const float green, const float blue,
+ const float alpha);
+
+ void draw_vertex_edges(Vertex_handle vertex, const Triangulation& mesh,
+ const float ri, const float gi, const float bi, const float ro,
+ const float go, const float bo);
+
+ void save_edges(std::ofstream& ofs, const int nb);
+
+ void save_one_edge(std::ofstream& ofs, const Edge& edge);
+
+};
+#endif
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/blob00.xy b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/blob00.xy
new file mode 100644
index 00000000000..648acc40927
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/blob00.xy
@@ -0,0 +1,320 @@
+0.21658 0.688199
+0.225464 0.697612
+0.234416 0.706629
+0.243414 0.71525
+0.25244 0.723472
+0.261474 0.731295
+0.270497 0.738718
+0.279488 0.745738
+0.28843 0.752355
+0.297301 0.758568
+0.306083 0.764374
+0.314756 0.769774
+0.3233 0.774765
+0.331697 0.779347
+0.339925 0.783517
+0.347967 0.787275
+0.355802 0.79062
+0.363411 0.79355
+0.370775 0.796064
+0.377873 0.798161
+0.384686 0.799839
+0.391196 0.801097
+0.397381 0.801934
+0.403224 0.802348
+0.408703 0.802339
+0.4138 0.801904
+0.418496 0.801044
+0.42277 0.799755
+0.426603 0.798038
+0.429976 0.795891
+0.432869 0.793312
+0.435263 0.790301
+0.437137 0.786855
+0.438474 0.782974
+0.43931 0.778689
+0.439685 0.774028
+0.439636 0.769024
+0.439204 0.763707
+0.438424 0.758106
+0.437338 0.752252
+0.435982 0.746177
+0.434395 0.739909
+0.432617 0.73348
+0.430684 0.72692
+0.428636 0.720259
+0.426511 0.713529
+0.424348 0.706758
+0.422185 0.699978
+0.420061 0.69322
+0.418013 0.686513
+0.416081 0.679888
+0.414303 0.673375
+0.412718 0.667006
+0.411363 0.660809
+0.410278 0.654817
+0.4095 0.649058
+0.409069 0.643564
+0.409022 0.638366
+0.409399 0.633492
+0.410238 0.628975
+0.411576 0.624843
+0.413454 0.621129
+0.415908 0.617862
+0.418978 0.615072
+0.422702 0.61279
+0.427118 0.611047
+0.432186 0.609809
+0.437863 0.609043
+0.444108 0.608716
+0.45088 0.608795
+0.458138 0.609247
+0.465839 0.610037
+0.473943 0.611135
+0.482408 0.612505
+0.491193 0.614115
+0.500256 0.615932
+0.509556 0.617923
+0.519051 0.620054
+0.5287 0.622293
+0.538462 0.624605
+0.548295 0.626958
+0.558157 0.62932
+0.568008 0.631655
+0.577805 0.633933
+0.587508 0.636118
+0.597075 0.638179
+0.606464 0.640081
+0.615635 0.641793
+0.624545 0.64328
+0.633154 0.644509
+0.641419 0.645448
+0.6493 0.646062
+0.656755 0.64632
+0.663742 0.646187
+0.670221 0.645631
+0.676149 0.644619
+0.681485 0.643117
+0.686188 0.641091
+0.690293 0.638571
+0.693832 0.635583
+0.696841 0.632154
+0.699353 0.628314
+0.701403 0.624088
+0.703024 0.619505
+0.704252 0.614592
+0.705119 0.609377
+0.70566 0.603888
+0.70591 0.598152
+0.705902 0.592197
+0.70567 0.58605
+0.705249 0.579739
+0.704673 0.573291
+0.703976 0.566734
+0.703192 0.560097
+0.702355 0.553405
+0.7015 0.546688
+0.70066 0.539972
+0.69987 0.533285
+0.699163 0.526655
+0.698575 0.52011
+0.698138 0.513676
+0.697888 0.507382
+0.697858 0.501255
+0.698082 0.495323
+0.698595 0.489613
+0.699431 0.484153
+0.700624 0.478971
+0.702208 0.474094
+0.704217 0.469549
+0.706685 0.465365
+0.709587 0.46152
+0.712898 0.457993
+0.716593 0.454762
+0.720646 0.451807
+0.725032 0.449105
+0.729725 0.446635
+0.734701 0.444376
+0.739935 0.442308
+0.7454 0.440407
+0.751072 0.438654
+0.756925 0.437026
+0.762935 0.435503
+0.769075 0.434063
+0.775321 0.432684
+0.781648 0.431346
+0.788029 0.430027
+0.794441 0.428706
+0.800857 0.427361
+0.807252 0.425972
+0.813602 0.424516
+0.81988 0.422972
+0.826062 0.42132
+0.832122 0.419537
+0.838035 0.417603
+0.843776 0.415496
+0.849319 0.413195
+0.85464 0.410678
+0.859712 0.407924
+0.864511 0.404912
+0.869012 0.40162
+0.873189 0.398028
+0.877017 0.394113
+0.880496 0.389894
+0.883627 0.385387
+0.88641 0.380611
+0.888846 0.375582
+0.890935 0.37032
+0.892678 0.36484
+0.894074 0.35916
+0.895126 0.353299
+0.895832 0.347273
+0.896193 0.341101
+0.89621 0.334799
+0.895883 0.328385
+0.895213 0.321877
+0.894201 0.315292
+0.892845 0.308648
+0.891148 0.301962
+0.889109 0.295252
+0.886729 0.288536
+0.884008 0.28183
+0.880947 0.275153
+0.877547 0.268521
+0.873807 0.261954
+0.869727 0.255467
+0.86531 0.249079
+0.860554 0.242807
+0.855461 0.236669
+0.850031 0.230681
+0.844264 0.224863
+0.838161 0.219231
+0.831722 0.213802
+0.824947 0.208595
+0.817838 0.203627
+0.81041 0.198897
+0.802681 0.194407
+0.794667 0.190157
+0.786386 0.186146
+0.777853 0.182375
+0.769085 0.178845
+0.7601 0.175555
+0.750913 0.172505
+0.741543 0.169696
+0.732004 0.167128
+0.722315 0.164802
+0.712492 0.162717
+0.702552 0.160874
+0.692511 0.159272
+0.682386 0.157913
+0.672194 0.156796
+0.661951 0.155922
+0.651675 0.155291
+0.641382 0.154902
+0.631089 0.154757
+0.620812 0.154855
+0.610569 0.155197
+0.600376 0.155783
+0.590249 0.156614
+0.580206 0.157688
+0.570263 0.159007
+0.560437 0.160571
+0.550745 0.16238
+0.541204 0.164434
+0.531829 0.166734
+0.522639 0.169279
+0.513649 0.17207
+0.504849 0.17509
+0.496229 0.178322
+0.487776 0.181749
+0.479481 0.185355
+0.471332 0.189121
+0.463319 0.193031
+0.455431 0.197069
+0.447657 0.201217
+0.439987 0.205458
+0.432409 0.209776
+0.424913 0.214153
+0.417487 0.218572
+0.410121 0.223017
+0.402805 0.22747
+0.395527 0.231915
+0.388277 0.236334
+0.381043 0.240711
+0.373816 0.245028
+0.366583 0.249269
+0.359335 0.253417
+0.35206 0.257455
+0.344747 0.261365
+0.337387 0.265132
+0.329968 0.268737
+0.322478 0.272164
+0.314908 0.275396
+0.307247 0.278416
+0.299483 0.281208
+0.291607 0.283753
+0.283606 0.286035
+0.27547 0.288038
+0.267189 0.289744
+0.258785 0.29118
+0.250279 0.292376
+0.241694 0.293357
+0.233052 0.294152
+0.224375 0.294789
+0.215686 0.295294
+0.207005 0.295697
+0.198356 0.296024
+0.189761 0.296302
+0.181241 0.296561
+0.172819 0.296827
+0.164517 0.297128
+0.156358 0.297491
+0.148362 0.297945
+0.140553 0.298517
+0.132952 0.299234
+0.125581 0.300124
+0.118464 0.301215
+0.111621 0.302535
+0.105075 0.304111
+0.0988486 0.305971
+0.0929632 0.308142
+0.087441 0.310653
+0.0823044 0.31353
+0.0775753 0.316801
+0.0732759 0.320494
+0.0694284 0.324638
+0.0660549 0.329258
+0.0631774 0.334384
+0.0608182 0.340042
+0.0589994 0.34626
+0.057743 0.353066
+0.0570342 0.36043
+0.0568581 0.36832
+0.0571998 0.376706
+0.0580445 0.385557
+0.0593773 0.394842
+0.0611832 0.404531
+0.0634474 0.414593
+0.066155 0.424998
+0.0692912 0.435714
+0.072841 0.446711
+0.0767896 0.457959
+0.081122 0.469426
+0.0858234 0.481082
+0.090879 0.492896
+0.0962737 0.504838
+0.101993 0.516876
+0.108021 0.528981
+0.114345 0.541121
+0.120947 0.553266
+0.127815 0.565385
+0.134933 0.577447
+0.142285 0.589422
+0.149858 0.601278
+0.157636 0.612986
+0.165604 0.624515
+0.173748 0.635833
+0.182053 0.646911
+0.190503 0.657717
+0.199085 0.668221
+0.207782 0.678392
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/maple_leaf_embroidery.bmp b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/maple_leaf_embroidery.bmp
new file mode 100644
index 00000000000..385ccb11a48
Binary files /dev/null and b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/maple_leaf_embroidery.bmp differ
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/round_rect00.xy b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/round_rect00.xy
new file mode 100644
index 00000000000..5bb7f3c39d0
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/round_rect00.xy
@@ -0,0 +1,288 @@
+0.117614 0.576166
+0.119993 0.581164
+0.122674 0.586089
+0.125649 0.590936
+0.128908 0.595702
+0.132444 0.600382
+0.136246 0.604972
+0.140307 0.609469
+0.144618 0.613869
+0.149169 0.618167
+0.153953 0.622359
+0.15896 0.626442
+0.164182 0.630412
+0.16961 0.634264
+0.175235 0.637995
+0.181049 0.6416
+0.187042 0.645075
+0.193207 0.648417
+0.199533 0.651622
+0.206013 0.654685
+0.212638 0.657603
+0.219399 0.660371
+0.226287 0.662985
+0.233294 0.665442
+0.24041 0.667738
+0.247628 0.669868
+0.254937 0.671828
+0.262331 0.673616
+0.269799 0.675225
+0.277333 0.676653
+0.284925 0.677896
+0.292565 0.678949
+0.300245 0.679808
+0.307956 0.68047
+0.315696 0.680947
+0.323466 0.681251
+0.331264 0.681394
+0.339088 0.681388
+0.346937 0.681246
+0.35481 0.68098
+0.362707 0.680601
+0.370626 0.680124
+0.378565 0.679558
+0.386524 0.678918
+0.394502 0.678215
+0.402496 0.677461
+0.410508 0.676668
+0.418534 0.675849
+0.426574 0.675016
+0.434627 0.674181
+0.442692 0.673357
+0.450767 0.672555
+0.458851 0.671788
+0.466944 0.671068
+0.475044 0.670408
+0.48315 0.669819
+0.49126 0.669313
+0.499375 0.668904
+0.507491 0.668603
+0.515609 0.668423
+0.523728 0.668375
+0.531845 0.668472
+0.539961 0.668726
+0.548073 0.66915
+0.556181 0.669755
+0.564283 0.670555
+0.572369 0.671529
+0.580427 0.672659
+0.588447 0.673926
+0.596417 0.675311
+0.604327 0.676796
+0.612164 0.678361
+0.619919 0.679988
+0.627581 0.681657
+0.635137 0.683349
+0.642578 0.685046
+0.649892 0.68673
+0.657069 0.688379
+0.664096 0.689977
+0.670963 0.691504
+0.67766 0.692941
+0.684174 0.694269
+0.690496 0.69547
+0.696613 0.696523
+0.702516 0.697412
+0.708192 0.698115
+0.713632 0.698616
+0.718823 0.698894
+0.723755 0.69893
+0.728416 0.698707
+0.732797 0.698205
+0.736885 0.697404
+0.74067 0.696287
+0.744141 0.694834
+0.747286 0.693026
+0.750095 0.690845
+0.752557 0.688271
+0.75466 0.685285
+0.756424 0.681902
+0.757869 0.678134
+0.759015 0.673994
+0.759882 0.669497
+0.760489 0.664656
+0.760855 0.659484
+0.761001 0.653994
+0.760947 0.6482
+0.760711 0.642116
+0.760314 0.635754
+0.759776 0.629129
+0.759115 0.622253
+0.758353 0.615141
+0.757508 0.607805
+0.7566 0.600259
+0.75565 0.592516
+0.754676 0.584591
+0.753699 0.576495
+0.752738 0.568244
+0.751813 0.559849
+0.750943 0.551325
+0.750149 0.542685
+0.749449 0.533942
+0.748865 0.52511
+0.748415 0.516203
+0.748119 0.507233
+0.747997 0.498214
+0.748069 0.48916
+0.748354 0.480084
+0.748872 0.470999
+0.749642 0.46192
+0.750686 0.452858
+0.751974 0.443823
+0.753479 0.434822
+0.755172 0.425865
+0.757027 0.416958
+0.759016 0.408111
+0.761109 0.39933
+0.763281 0.390626
+0.765502 0.382005
+0.767745 0.373475
+0.769983 0.365046
+0.772187 0.356725
+0.774329 0.348521
+0.776382 0.34044
+0.778318 0.332493
+0.780108 0.324686
+0.781726 0.317029
+0.783144 0.309529
+0.784333 0.302194
+0.785265 0.295032
+0.785914 0.288053
+0.78625 0.281263
+0.786247 0.274671
+0.785876 0.268286
+0.785109 0.262115
+0.783919 0.256167
+0.782278 0.250449
+0.780159 0.244971
+0.777532 0.239739
+0.774371 0.234763
+0.770647 0.23005
+0.766333 0.225609
+0.761401 0.221447
+0.755874 0.217555
+0.749779 0.213923
+0.743138 0.210538
+0.735975 0.207392
+0.728316 0.204474
+0.720184 0.201773
+0.711603 0.199279
+0.702598 0.196981
+0.693193 0.19487
+0.683413 0.192935
+0.67328 0.191165
+0.662821 0.18955
+0.652058 0.188079
+0.641016 0.186743
+0.62972 0.18553
+0.618193 0.184431
+0.60646 0.183435
+0.594546 0.182532
+0.582473 0.18171
+0.570267 0.180961
+0.557951 0.180273
+0.545551 0.179635
+0.53309 0.179039
+0.520592 0.178472
+0.508082 0.177926
+0.495584 0.177388
+0.483121 0.17685
+0.47072 0.1763
+0.458402 0.175729
+0.446194 0.175125
+0.434119 0.174478
+0.422201 0.173779
+0.410446 0.173037
+0.398859 0.172265
+0.387448 0.171472
+0.376218 0.17067
+0.365173 0.16987
+0.354321 0.169082
+0.343667 0.168319
+0.333217 0.16759
+0.322977 0.166907
+0.312952 0.166281
+0.303149 0.165722
+0.293573 0.165242
+0.28423 0.164852
+0.275125 0.164562
+0.266266 0.164383
+0.257657 0.164328
+0.249304 0.164405
+0.241214 0.164628
+0.233392 0.165005
+0.225843 0.165549
+0.218575 0.166271
+0.211591 0.167181
+0.204899 0.16829
+0.198505 0.169609
+0.192413 0.17115
+0.18663 0.172923
+0.181162 0.174939
+0.176014 0.17721
+0.171193 0.179745
+0.166703 0.182557
+0.162552 0.185656
+0.158744 0.189053
+0.155266 0.192737
+0.152101 0.196696
+0.149236 0.200921
+0.146654 0.205398
+0.144342 0.210119
+0.142284 0.21507
+0.140466 0.220242
+0.138872 0.225622
+0.137487 0.2312
+0.136297 0.236965
+0.135287 0.242906
+0.134442 0.24901
+0.133747 0.255268
+0.133186 0.261668
+0.132746 0.268199
+0.132411 0.27485
+0.132166 0.28161
+0.131997 0.288467
+0.131887 0.29541
+0.131824 0.302428
+0.131791 0.309511
+0.131773 0.316646
+0.131757 0.323824
+0.131726 0.331031
+0.131666 0.338259
+0.131562 0.345494
+0.131399 0.352727
+0.131162 0.359946
+0.130837 0.36714
+0.130408 0.374298
+0.12986 0.381408
+0.129179 0.38846
+0.128378 0.395453
+0.127471 0.402386
+0.126473 0.40926
+0.125397 0.416075
+0.124256 0.422829
+0.123066 0.429522
+0.121839 0.436154
+0.120589 0.442726
+0.119332 0.449235
+0.118079 0.455683
+0.116846 0.462068
+0.115646 0.468391
+0.114493 0.474651
+0.113401 0.480847
+0.112384 0.48698
+0.111455 0.493049
+0.110629 0.499053
+0.10992 0.504993
+0.109341 0.510868
+0.108906 0.516677
+0.108629 0.522421
+0.108524 0.528098
+0.108605 0.533709
+0.108886 0.539254
+0.109381 0.544731
+0.110103 0.550141
+0.111067 0.555483
+0.112286 0.560757
+0.113774 0.565962
+0.115545 0.571099
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/skyline_noisy00.xy b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/skyline_noisy00.xy
new file mode 100644
index 00000000000..ee61170ab1b
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/skyline_noisy00.xy
@@ -0,0 +1,430 @@
+-0.00122166 -0.00773919
+0.0183746 0.00256813
+0.0257372 0.00893185
+0.0313877 0.00746208
+0.0402316 -0.00500961
+0.053375 -0.00536058
+0.0583786 0.00420576
+0.0666756 -0.00384259
+0.0767904 -0.00160924
+0.080896 0.00804865
+0.102811 -0.000804773
+0.100045 0.0114237
+0.0936988 0.0130573
+0.100168 0.0220594
+0.100379 0.0424473
+0.108123 0.0565801
+0.101391 0.0665227
+0.0921094 0.0633638
+0.102654 0.084326
+0.0945808 0.0863143
+0.108688 0.103644
+0.0981637 0.109591
+0.100887 0.128656
+0.095212 0.131452
+0.108508 0.149497
+0.0916187 0.155325
+0.107963 0.166861
+0.105509 0.176219
+0.0960659 0.174764
+0.0914405 0.190623
+0.0928504 0.194605
+0.0907416 0.208006
+0.0995773 0.223629
+0.0985995 0.23203
+0.107564 0.230937
+0.108538 0.249637
+0.103462 0.264162
+0.104897 0.27609
+0.106605 0.279925
+0.103956 0.294133
+0.104045 0.301213
+0.094297 0.315367
+0.0989206 0.314798
+0.0970699 0.321979
+0.0977609 0.331805
+0.0967513 0.356959
+0.0923615 0.364591
+0.103043 0.360892
+0.10186 0.383019
+0.0945277 0.383511
+0.0906269 0.403283
+0.104707 0.408077
+0.107607 0.412389
+0.101042 0.436739
+0.102723 0.441435
+0.0976382 0.455005
+0.105984 0.450792
+0.0921784 0.463431
+0.104911 0.480336
+0.107742 0.494669
+0.1059 0.507837
+0.100127 0.493978
+0.115167 0.508639
+0.131321 0.501357
+0.144884 0.499756
+0.149705 0.49338
+0.160131 0.501503
+0.177664 0.502911
+0.172299 0.499796
+0.187188 0.494765
+0.194559 0.502235
+0.204116 0.495498
+0.225035 0.491108
+0.221635 0.495403
+0.233281 0.50643
+0.24366 0.500873
+0.25572 0.502142
+0.268722 0.505225
+0.275647 0.50861
+0.294994 0.496143
+0.293419 0.504528
+0.307066 0.497833
+0.302486 0.471365
+0.30511 0.466037
+0.296839 0.453476
+0.297052 0.454022
+0.305558 0.436998
+0.29437 0.427669
+0.30003 0.410664
+0.292164 0.407791
+0.309504 0.401659
+0.294089 0.397803
+0.290587 0.389628
+0.302815 0.374862
+0.306305 0.351988
+0.296607 0.342618
+0.300362 0.343648
+0.302669 0.33369
+0.302228 0.324261
+0.30787 0.319981
+0.308656 0.29615
+0.297473 0.298987
+0.297284 0.286021
+0.302508 0.274198
+0.297926 0.253585
+0.306388 0.257729
+0.29718 0.240226
+0.291417 0.233297
+0.301991 0.220826
+0.295808 0.20768
+0.297772 0.191886
+0.311828 0.198778
+0.326733 0.199057
+0.335699 0.208398
+0.342018 0.197207
+0.359893 0.207891
+0.363299 0.206163
+0.37842 0.204762
+0.389431 0.195227
+0.395761 0.198392
+0.393806 0.199621
+0.400052 0.202976
+0.398032 0.221961
+0.391155 0.225816
+0.409545 0.241894
+0.40423 0.259094
+0.398803 0.267038
+0.409451 0.263238
+0.401676 0.288315
+0.408467 0.280029
+0.402643 0.292844
+0.408256 0.313541
+0.404447 0.317483
+0.392981 0.337074
+0.399816 0.336164
+0.394484 0.34418
+0.39088 0.36415
+0.39203 0.371914
+0.391907 0.372317
+0.401941 0.394448
+0.400987 0.394615
+0.417735 0.405143
+0.416278 0.401803
+0.421395 0.405243
+0.442464 0.404613
+0.446405 0.397278
+0.463014 0.39944
+0.473157 0.401332
+0.483901 0.399705
+0.497374 0.392277
+0.504382 0.406005
+0.51216 0.396118
+0.52048 0.398171
+0.524319 0.403554
+0.536782 0.402375
+0.545539 0.398904
+0.552183 0.396395
+0.569099 0.392493
+0.575202 0.406169
+0.592704 0.39466
+0.59449 0.396764
+0.608074 0.389467
+0.600166 0.370886
+0.597923 0.366287
+0.601587 0.358051
+0.600937 0.347348
+0.597195 0.347548
+0.605395 0.329387
+0.602064 0.328311
+0.59204 0.31753
+0.608754 0.308838
+0.606836 0.289521
+0.607122 0.280267
+0.604228 0.268436
+0.598703 0.255744
+0.601548 0.241982
+0.591276 0.249206
+0.595159 0.236543
+0.609262 0.226699
+0.599003 0.204057
+0.605558 0.193364
+0.596138 0.18989
+0.590449 0.189215
+0.603921 0.179793
+0.603214 0.15682
+0.603442 0.154098
+0.602044 0.134035
+0.593844 0.127262
+0.597918 0.114888
+0.602149 0.100883
+0.608039 0.0917652
+0.609219 0.0883285
+0.594468 0.0820023
+0.602469 0.0790759
+0.603586 0.0520185
+0.595973 0.0409149
+0.591989 0.0421134
+0.608567 0.0281289
+0.594461 0.0250548
+0.600593 0.0137657
+0.599639 0.00157628
+0.599895 -0.00585589
+0.609005 -0.0140797
+0.597701 -0.0362877
+0.604811 -0.0354598
+0.605016 -0.0516227
+0.602587 -0.0589084
+0.590137 -0.0645576
+0.593835 -0.0891583
+0.607939 -0.091738
+0.594551 -0.102387
+0.611534 -0.106239
+0.625184 -0.103605
+0.636941 -0.109081
+0.637672 -0.105261
+0.651393 -0.0916382
+0.655172 -0.103922
+0.675896 -0.100824
+0.680108 -0.101927
+0.692671 -0.0989151
+0.696164 -0.0908692
+0.698107 -0.0999176
+0.699853 -0.0837907
+0.691846 -0.0743095
+0.707274 -0.0529615
+0.702629 -0.0440761
+0.691692 -0.0401254
+0.691509 -0.0298807
+0.697568 -0.0160726
+0.693099 -0.0122629
+0.706651 0.00356731
+0.695429 0.0112607
+0.701771 0.0294537
+0.699069 0.0313291
+0.703952 0.0496973
+0.69614 0.0522159
+0.708468 0.0641917
+0.699825 0.0657888
+0.695468 0.0752284
+0.705016 0.092067
+0.700804 0.0975295
+0.690721 0.114507
+0.702671 0.120819
+0.70485 0.128139
+0.709694 0.148057
+0.702008 0.148686
+0.706089 0.162461
+0.69493 0.160769
+0.699519 0.186452
+0.690159 0.19336
+0.707262 0.205622
+0.718621 0.190568
+0.726335 0.20088
+0.731698 0.205912
+0.743185 0.201885
+0.753439 0.20819
+0.768572 0.20488
+0.779528 0.207082
+0.773272 0.208088
+0.793631 0.206596
+0.790237 0.207751
+0.801759 0.204492
+0.798805 0.227969
+0.795254 0.225817
+0.796624 0.24745
+0.80304 0.248654
+0.794884 0.256301
+0.793752 0.260228
+0.802505 0.285979
+0.80838 0.281491
+0.794885 0.305537
+0.804035 0.318303
+0.792846 0.327277
+0.809482 0.337347
+0.80741 0.334948
+0.793053 0.344887
+0.796001 0.357606
+0.793567 0.37651
+0.805741 0.382263
+0.794882 0.395962
+0.809418 0.408449
+0.794707 0.41122
+0.809794 0.417814
+0.808296 0.425908
+0.797844 0.441896
+0.797649 0.454191
+0.800572 0.461172
+0.806847 0.477273
+0.804025 0.478534
+0.794143 0.489622
+0.807117 0.50029
+0.801441 0.513039
+0.791911 0.527842
+0.791773 0.526715
+0.805963 0.533142
+0.795421 0.551382
+0.802361 0.561075
+0.795285 0.575691
+0.79309 0.571865
+0.792141 0.582944
+0.801339 0.606662
+0.800409 0.606302
+0.808378 0.629401
+0.795045 0.630595
+0.800627 0.648091
+0.800197 0.648853
+0.792557 0.668632
+0.800245 0.6717
+0.79102 0.684302
+0.803844 0.697712
+0.796665 0.694028
+0.811602 0.692884
+0.828034 0.692578
+0.838018 0.707326
+0.843995 0.705784
+0.858299 0.697298
+0.850106 0.693934
+0.870688 0.70074
+0.884555 0.696456
+0.884922 0.694385
+0.909299 0.701009
+0.897453 0.690613
+0.902015 0.670114
+0.904041 0.662144
+0.894504 0.668457
+0.890369 0.652726
+0.893162 0.64397
+0.901281 0.631899
+0.907147 0.625835
+0.909279 0.612008
+0.899858 0.592522
+0.902907 0.585558
+0.909383 0.572996
+0.895638 0.561044
+0.893485 0.554201
+0.895898 0.555388
+0.90481 0.537979
+0.908845 0.531096
+0.891901 0.520505
+0.890527 0.516273
+0.891665 0.497401
+0.915065 0.505611
+0.928901 0.50764
+0.93544 0.500482
+0.948531 0.499346
+0.958566 0.506247
+0.956153 0.490662
+0.975229 0.504936
+0.972534 0.508754
+0.985539 0.50138
+0.997672 0.500121
+0.990516 0.490971
+0.990056 0.475313
+0.990432 0.467124
+0.996754 0.461194
+1.00053 0.456609
+0.99993 0.443855
+0.994772 0.430845
+0.995444 0.415335
+1.00819 0.401313
+1.00914 0.407238
+1.0085 0.387177
+1.00648 0.384405
+1.00765 0.363267
+1.00105 0.36174
+1.00379 0.356538
+0.997746 0.337323
+0.994447 0.329128
+0.996059 0.324951
+0.9914 0.316145
+1.00923 0.299199
+0.998003 0.296301
+1.00485 0.276163
+0.999457 0.26353
+1.00249 0.262979
+1.00675 0.2577
+0.994071 0.239261
+1.00483 0.222556
+1.00256 0.223583
+1.00569 0.209015
+1.00454 0.208112
+0.996931 0.191932
+0.992461 0.174545
+1.00648 0.178477
+1.00196 0.154454
+0.994058 0.156229
+1.00012 0.147162
+0.990015 0.139125
+1.0001 0.118295
+0.99221 0.119393
+0.997846 0.0921192
+1.01149 0.0935713
+1.01652 0.100792
+1.03643 0.0907672
+1.03424 0.103647
+1.04798 0.0912647
+1.06076 0.0996512
+1.0746 0.103602
+1.0787 0.106149
+1.09854 0.10826
+1.09504 0.107013
+1.09384 0.0860707
+1.09834 0.0833482
+1.10677 0.0794806
+1.10749 0.069845
+1.09925 0.0447871
+1.10746 0.0499304
+1.09588 0.0334837
+1.09782 0.0128309
+1.09528 0.000820948
+1.1095 0.00567797
+1.10628 -0.000269173
+1.09555 -0.0162337
+1.10959 -0.0217853
+1.09146 -0.0478845
+1.10567 -0.0416535
+1.09068 -0.0585604
+1.09931 -0.0750066
+1.09092 -0.0883508
+1.10159 -0.0976098
+1.09694 -0.0939674
+1.10991 -0.10331
+1.11541 -0.0907923
+1.12653 -0.0973824
+1.14744 -0.107995
+1.15653 -0.107649
+1.15443 -0.10362
+1.16549 -0.0952522
+1.18291 -0.096512
+1.19779 -0.106942
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/stair-noise00.xy b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/stair-noise00.xy
new file mode 100644
index 00000000000..3d6f2434d85
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/data/stair-noise00.xy
@@ -0,0 +1,160 @@
+0.00605396 0.00360027
+0.0117095 0.00496933
+0.00292489 -0.0056444
+0.018654 -0.00345866
+0.0208731 -0.00712699
+0.0349622 0.00520127
+0.0226514 0.00273598
+0.0443469 0.00641652
+0.0320264 -0.00785089
+0.0536853 -0.00492172
+0.0477706 0.00445479
+0.0639807 0.00509629
+0.0673864 -0.000544755
+0.068878 0.00636891
+0.0786834 -0.00880306
+0.0838299 0.00977294
+0.087326 -0.0021897
+0.079062 0.000772423
+0.0984893 0.00905454
+0.0994487 -0.00770074
+0.100736 0.00717826
+0.0994229 0.00250389
+0.100252 0.0167278
+0.0960604 0.00802011
+0.103545 0.0289233
+0.108446 0.0183656
+0.106763 0.0262313
+0.106452 0.0420934
+0.0997256 0.0427598
+0.107064 0.0403298
+0.0928101 0.0560955
+0.10136 0.0583232
+0.104819 0.0562105
+0.0902899 0.0706163
+0.10994 0.0770702
+0.0923621 0.0704878
+0.0919434 0.0865538
+0.0963674 0.0842679
+0.103725 0.0803259
+0.102273 0.101166
+0.100319 0.0952791
+0.108403 0.0942299
+0.113529 0.0981625
+0.108027 0.103066
+0.126272 0.0950435
+0.133506 0.0939314
+0.124776 0.107205
+0.131076 0.107853
+0.136759 0.109119
+0.15444 0.102357
+0.143707 0.104111
+0.160272 0.0974776
+0.165379 0.103348
+0.173751 0.0916309
+0.174657 0.0937715
+0.167267 0.0980068
+0.170889 0.0905988
+0.185414 0.102092
+0.189813 0.10002
+0.199397 0.0909473
+0.198222 0.107717
+0.198974 0.099872
+0.201479 0.108827
+0.205074 0.107075
+0.202 0.124977
+0.191185 0.121976
+0.206848 0.134009
+0.196679 0.137767
+0.19255 0.148035
+0.190151 0.143856
+0.195263 0.155428
+0.20595 0.148822
+0.204421 0.152387
+0.191967 0.169495
+0.197981 0.169699
+0.191872 0.176798
+0.207398 0.170317
+0.194859 0.178978
+0.190444 0.183389
+0.196073 0.192833
+0.200019 0.190352
+0.205824 0.198579
+0.217043 0.198723
+0.210708 0.208976
+0.225591 0.209213
+0.224774 0.208331
+0.228376 0.201784
+0.233852 0.192014
+0.230703 0.196273
+0.241172 0.192107
+0.241027 0.203219
+0.257393 0.199803
+0.266244 0.190504
+0.263176 0.1902
+0.279822 0.191442
+0.267419 0.200092
+0.270919 0.209937
+0.294279 0.199399
+0.292596 0.208336
+0.302111 0.206854
+0.297261 0.193606
+0.302447 0.195568
+0.307461 0.217454
+0.302133 0.219113
+0.300152 0.216012
+0.296763 0.223723
+0.302571 0.234727
+0.298522 0.237272
+0.307834 0.234066
+0.296568 0.250613
+0.298385 0.251664
+0.29308 0.261943
+0.295426 0.266549
+0.293096 0.259791
+0.292439 0.271056
+0.291263 0.275271
+0.300944 0.286063
+0.308624 0.284206
+0.306603 0.285177
+0.302574 0.289769
+0.303807 0.303483
+0.308102 0.301263
+0.316854 0.306492
+0.313448 0.299638
+0.325862 0.304911
+0.328301 0.305416
+0.335535 0.300855
+0.327652 0.299601
+0.334895 0.301131
+0.339451 0.303238
+0.356128 0.293215
+0.359167 0.306227
+0.350648 0.309557
+0.359385 0.291005
+0.360515 0.305818
+0.377582 0.301763
+0.373333 0.308693
+0.375172 0.299768
+0.398744 0.298911
+0.390985 0.295462
+0.39465 0.305079
+0.397266 0.302934
+0.391293 0.303944
+0.401355 0.307406
+0.391301 0.312749
+0.401141 0.331346
+0.403843 0.339273
+0.397447 0.32984
+0.401007 0.345187
+0.401435 0.350856
+0.404534 0.358367
+0.40019 0.350997
+0.401021 0.359769
+0.398586 0.362409
+0.403735 0.370503
+0.400571 0.381428
+0.409145 0.374727
+0.402981 0.379619
+0.406312 0.38398
+0.405032 0.387826
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/dialog_options.h b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/dialog_options.h
new file mode 100644
index 00000000000..1a4160a8267
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/dialog_options.h
@@ -0,0 +1,89 @@
+#ifndef DIAL_OPT_H_
+#define DIAL_OPT_H_
+
+#include "ui_options.h"
+
+class Dialog_options : public QDialog, private Ui::Dialog_options
+{
+ Q_OBJECT
+
+public Q_SLOTS:
+ void on_multiple_choice_checkbox_toggled(bool checked)
+ {
+ if (checked && get_mchoice() == 0)
+ set_random_sample_size(10);
+ else if (checked == false)
+ set_random_sample_size(0);
+ }
+
+ void on_mchoice_spinbox_valueChanged(int new_v)
+ {
+ set_multiple_choice_checkbox(new_v != 0);
+ }
+
+public:
+ Dialog_options(QWidget * = 0)
+ {
+ setupUi(this);
+ }
+
+ void set_all_ranges()
+ {
+ verbose_spinbox->setRange(0, 2);
+ mchoice_spinbox->setRange(0, 500);
+ percent_spinbox->setRange(0, 100);
+ norm_tol_spinbox->setRange(0., 500.);
+ tang_tol_spinbox->setRange(0., 500.);
+ alpha_spinbox->setRange(0., 100.);
+ relocation_spinbox->setRange(0, 50);
+ ghost_spinbox->setRange(0., 100000.);
+ }
+
+ int get_verbose() const { return verbose_spinbox->value(); }
+ void set_verbose(int verbose) { verbose_spinbox->setValue(verbose); }
+
+ int get_mchoice() const { return mchoice_spinbox->value(); }
+ void set_random_sample_size(const int mchoice) { mchoice_spinbox->setValue(mchoice); }
+
+ double get_percent() const { return percent_spinbox->value(); }
+ void set_percent(const double percent) { percent_spinbox->setValue(percent); }
+
+ double get_norm_tol() const { return norm_tol_spinbox->value(); }
+ void set_norm_tol(const double tol) { norm_tol_spinbox->setValue(tol); }
+
+ double get_tang_tol() const { return tang_tol_spinbox->value(); }
+ void set_tang_tol(const double tol) { tang_tol_spinbox->setValue(tol); }
+
+ double get_alpha() const { return alpha_spinbox->value(); }
+ void set_alpha(const double alpha) { alpha_spinbox->setValue(alpha); }
+
+ int get_relocation() const { return relocation_spinbox->value(); }
+ void set_relocation(const int value) {
+ return relocation_spinbox->setValue(value);
+ }
+
+ double get_ghost() const { return ghost_spinbox->value(); }
+ void set_relevance(double ghost) { ghost_spinbox->setValue(ghost); }
+
+ bool get_use_flip() const { return use_flip_checkbox->isChecked(); }
+ void set_use_flip(const bool flip) {
+ return use_flip_checkbox->setChecked(flip);
+ }
+
+ bool get_multiple_choice_checkbox() const {
+ return multiple_choice_checkbox->isChecked(); }
+ void set_multiple_choice_checkbox(const bool mc) {
+ return multiple_choice_checkbox->setChecked(mc);
+ }
+
+ double get_line_thickness() const { return thickness_spinbox->value(); }
+ void set_line_thickness(const double t) { thickness_spinbox->setValue(t); }
+
+ double get_point_size() const { return point_size_spinbox->value(); }
+ void set_point_size(const double t) { point_size_spinbox->setValue(t); }
+
+ double get_vertex_size() const { return vertex_size_spinbox->value(); }
+ void set_vertex_size(const double t) { vertex_size_spinbox->setValue(t); }
+};
+
+#endif
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/glviewer.cpp b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/glviewer.cpp
new file mode 100644
index 00000000000..dc6d8322897
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/glviewer.cpp
@@ -0,0 +1,171 @@
+// Qt
+#include
+
+// local
+#include "glviewer.h"
+
+GlViewer::GlViewer(QWidget *pParent)
+: QGLWidget(QGLFormat(QGL::SampleBuffers), pParent)
+{
+ m_scene = NULL;
+
+ m_view_points = true;
+ m_view_vertices = true;
+ m_view_edges = false;
+ m_view_ghost_edges = false;
+ m_view_edge_cost = false;
+ m_view_edge_priority = false;
+ m_view_bins = false;
+ m_view_foot_points = false;
+ m_view_relocation = false;
+ m_view_tolerance = false;
+ m_view_edge_relevance = true;
+ m_insert_points = false;
+
+ m_line_thickness = 2.0;
+ m_point_size = 2.0;
+ m_vertex_size = 2.0;
+
+ m_scale = 1.0;
+ m_center_x = m_center_y = 0.5;
+
+ setAutoFillBackground(false);
+}
+
+void GlViewer::resizeGL(int width, int height)
+{
+ glViewport(0, 0, width, height);
+ double aspect_ratio = double(height) / double(width);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-1.0, 1.0, -aspect_ratio, aspect_ratio, -1.0, 1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+void GlViewer::initializeGL()
+{
+ glClearColor(1., 1., 1., 0.);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_SMOOTH);
+}
+
+void GlViewer::paintGL()
+{
+ glClear(GL_COLOR_BUFFER_BIT);
+ if (!m_scene) return;
+
+ glPushMatrix();
+ glScaled(m_scale, m_scale, m_scale);
+ glTranslated(-m_center_x, -m_center_y, 0.0);
+
+ m_scene->render(m_view_points,
+ m_view_vertices,
+ m_view_edges,
+ m_view_ghost_edges,
+ m_view_edge_cost,
+ m_view_edge_priority,
+ m_view_bins,
+ m_view_foot_points,
+ m_view_relocation,
+ m_view_tolerance,
+ m_view_edge_relevance,
+ float(m_point_size),
+ float(m_vertex_size),
+ float(m_line_thickness));
+
+ glPopMatrix();
+}
+
+void GlViewer::wheelEvent(QWheelEvent *event)
+{
+ if (!m_scene) return;
+ m_scale += 0.05 * (event->delta() / 120);
+ if (m_scale <= 0.0) m_scale = 0.0;
+ updateGL();
+}
+
+void GlViewer::mousePressEvent(QMouseEvent *event)
+{
+ if (!m_scene) return;
+ m_mouse_click = event->pos();
+
+ if (event->button() == Qt::LeftButton)
+ {
+ setCursor(QCursor(Qt::PointingHandCursor));
+ sample_mouse_path(m_mouse_click);
+ }
+ else
+ {
+ setCursor(QCursor(Qt::ClosedHandCursor));
+ }
+}
+
+void GlViewer::mouseMoveEvent(QMouseEvent *event)
+{
+ if(!m_scene) return;
+ m_mouse_move = event->pos();
+
+ if (event->buttons() == Qt::LeftButton)
+ {
+ if (m_mouse_move != m_mouse_click)
+ sample_mouse_path(m_mouse_move);
+ }
+ else
+ {
+ move_camera(m_mouse_click, m_mouse_move);
+ }
+
+ m_mouse_click = m_mouse_move;
+ updateGL();
+}
+
+void GlViewer::mouseReleaseEvent(QMouseEvent *event)
+{
+ if (!m_scene) return;
+ m_mouse_move = event->pos();
+
+ if (event->button() == Qt::LeftButton)
+ {
+ if (m_mouse_move != m_mouse_click)
+ sample_mouse_path(m_mouse_move);
+ }
+ else
+ {
+ move_camera(m_mouse_click, m_mouse_move);
+ }
+
+ m_mouse_click = m_mouse_move;
+ setCursor(QCursor(Qt::ArrowCursor));
+ updateGL();
+}
+
+void GlViewer::sample_mouse_path(const QPoint& point)
+{
+ double x, y;
+ convert_to_world_space(point, x, y);
+
+ if (m_insert_points)
+ m_scene->add_sample(Point(x, y));
+}
+
+void GlViewer::move_camera(const QPoint& p0, const QPoint& p1)
+{
+ m_center_x -= double(p1.x() - p0.x()) / double(width());
+ m_center_y += double(p1.y() - p0.y()) / double(height());
+}
+
+void GlViewer::convert_to_world_space(const QPoint& point, double &x, double &y)
+{
+ double aspect_ratio = double(height()) / double(width());
+
+ x = double(point.x()) / double(width());
+ x = (2.0*x - 1.0) / m_scale;
+ x += m_center_x;
+
+ y = 1.0 - double(point.y()) / double(height());
+ y = (2.0*y - 1.0) * aspect_ratio / m_scale;
+ y += m_center_y;
+}
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/glviewer.h b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/glviewer.h
new file mode 100644
index 00000000000..50f8d3dc1c0
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/glviewer.h
@@ -0,0 +1,116 @@
+#ifndef GLWIDGET_H
+#define GLWIDGET_H
+
+// Qt
+#include
+#include
+
+// local
+#include "scene.h"
+
+class GlViewer : public QGLWidget
+{
+ Q_OBJECT
+
+private:
+ Scene* m_scene;
+
+ // toggles
+ bool m_view_points;
+ bool m_view_vertices;
+ bool m_view_edges;
+ bool m_view_ghost_edges;
+ bool m_view_edge_cost;
+ bool m_view_edge_priority;
+ bool m_view_bins;
+ bool m_view_foot_points;
+ bool m_view_relocation;
+ bool m_view_tolerance;
+ bool m_view_edge_relevance;
+
+ // interactive modes
+ bool m_insert_points;
+
+ // rendering options
+ double m_line_thickness;
+ double m_point_size;
+ double m_vertex_size;
+
+ // camera
+ double m_scale;
+ double m_center_x, m_center_y;
+
+ // mouse
+ QPoint m_mouse_click;
+ QPoint m_mouse_move;
+ Point m_mouse_pick;
+
+public:
+ GlViewer(QWidget *parent);
+
+ void set_scene(Scene* pScene) { m_scene = pScene; }
+
+ void set_camera(const double x, const double y, const double s)
+ {
+ m_center_x = x;
+ m_center_y = y;
+ m_scale = s;
+ }
+
+ // options
+ double& line_thickness() { return m_line_thickness; }
+ const double& line_thickness() const { return m_line_thickness; }
+
+ double& point_size() { return m_point_size; }
+ const double& point_size() const { return m_point_size; }
+
+ double& vertex_size() { return m_vertex_size; }
+ const double& vertex_size() const { return m_vertex_size; }
+
+ // toggles
+ void toggle_view_points() { m_view_points = !m_view_points; }
+
+ void toggle_view_vertices() { m_view_vertices = !m_view_vertices; }
+
+ void toggle_view_edges() { m_view_edges = !m_view_edges; }
+
+ void toggle_view_ghost_edges() { m_view_ghost_edges = !m_view_ghost_edges; }
+
+ void toggle_view_edge_cost() { m_view_edge_cost = !m_view_edge_cost; }
+
+ void toggle_view_edge_priority() {
+ m_view_edge_priority = !m_view_edge_priority;
+ }
+
+ void toggle_view_bins () { m_view_bins = !m_view_bins; }
+
+ void toggle_view_foot_points() { m_view_foot_points = !m_view_foot_points; }
+
+ void toggle_view_relocation() { m_view_relocation = !m_view_relocation; }
+
+ void toggle_view_tolerance() { m_view_tolerance = !m_view_tolerance; }
+
+ void toggle_view_edge_relevance() {
+ m_view_edge_relevance = !m_view_edge_relevance;
+ }
+
+ void toggle_insert_points() { m_insert_points = !m_insert_points; }
+
+protected:
+ // GL
+ void paintGL();
+ void initializeGL();
+ void resizeGL(int width, int height);
+
+ // mouse
+ void wheelEvent(QWheelEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+
+ void sample_mouse_path(const QPoint& point);
+ void move_camera(const QPoint& p0, const QPoint& p1);
+ void convert_to_world_space(const QPoint& point, double &x, double &y);
+};
+
+#endif
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/Voronoi_diagram_2.png b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/Voronoi_diagram_2.png
new file mode 100644
index 00000000000..62437e6bfc9
Binary files /dev/null and b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/Voronoi_diagram_2.png differ
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/fileNew.png b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/fileNew.png
new file mode 100644
index 00000000000..af5d1221412
Binary files /dev/null and b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/fileNew.png differ
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/fileOpen.png b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/fileOpen.png
new file mode 100644
index 00000000000..fc6f17e9774
Binary files /dev/null and b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/fileOpen.png differ
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/fileSave.png b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/fileSave.png
new file mode 100644
index 00000000000..8feec99bee8
Binary files /dev/null and b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/fileSave.png differ
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/fit-page-32.png b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/fit-page-32.png
new file mode 100644
index 00000000000..98bc12d3ed6
Binary files /dev/null and b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/fit-page-32.png differ
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/inputPoint.png b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/inputPoint.png
new file mode 100644
index 00000000000..e9d53a20571
Binary files /dev/null and b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/inputPoint.png differ
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/snapshot.png b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/snapshot.png
new file mode 100644
index 00000000000..9b5b9efe722
Binary files /dev/null and b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/snapshot.png differ
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/triangulation.png b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/triangulation.png
new file mode 100644
index 00000000000..ce082a6e08f
Binary files /dev/null and b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/triangulation.png differ
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/until.png b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/until.png
new file mode 100644
index 00000000000..82cdcecf034
Binary files /dev/null and b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/until.png differ
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/vertex.png b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/vertex.png
new file mode 100644
index 00000000000..6a8fff61701
Binary files /dev/null and b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/icons/vertex.png differ
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/options.ui b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/options.ui
new file mode 100644
index 00000000000..df559725272
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/options.ui
@@ -0,0 +1,319 @@
+
+
+ Dialog_options
+
+
+
+ 0
+ 0
+ 354
+ 415
+
+
+
+
+ 0
+ 0
+
+
+
+ Options
+
+
+
+
+ 20
+ 20
+ 311
+ 385
+
+
+
+
-
+
+
+ Use Flip
+
+
+
+ -
+
+
-
+
+
+ Multiple Choice, with number of samples:
+
+
+
+ -
+
+
+ 100
+
+
+ 100
+
+
+
+
+
+ -
+
+
-
+
+
+ Verbose
+
+
+
+ -
+
+
+ 2
+
+
+
+
+
+ -
+
+
-
+
+
+ Init with %
+
+
+
+ -
+
+
+ 100
+
+
+ 100
+
+
+
+
+
+ -
+
+
-
+
+
+ Normal Tol.
+
+
+
+ -
+
+
+ 3
+
+
+ 100.000000000000000
+
+
+ 0.050000000000000
+
+
+ 100.000000000000000
+
+
+
+
+
+ -
+
+
-
+
+
+ Tangential Tol.
+
+
+
+ -
+
+
+ 3
+
+
+ 100.000000000000000
+
+
+ 0.050000000000000
+
+
+ 100.000000000000000
+
+
+
+
+
+ -
+
+
-
+
+
+ Alpha
+
+
+
+ -
+
+
+ 3
+
+
+ 100.000000000000000
+
+
+ 0.050000000000000
+
+
+ 100.000000000000000
+
+
+
+
+
+ -
+
+
-
+
+
+ Relocation
+
+
+
+ -
+
+
+
+
+ -
+
+
-
+
+
+ Ghost vs solid
+
+
+
+ -
+
+
+ 3
+
+
+ 100.000000000000000
+
+
+ 0.050000000000000
+
+
+ 100.000000000000000
+
+
+
+
+
+ -
+
+
-
+
+
+ Line thickness
+
+
+
+ -
+
+
+
+
+ -
+
+
-
+
+
+ Point size
+
+
+
+ -
+
+
+
+
+ -
+
+
-
+
+
+ Vertex size
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+ 252
+ 0
+
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+ layoutWidget
+ use_flip_checkbox
+
+
+
+
+ buttonBox
+ accepted()
+ Dialog_options
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ Dialog_options
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/pwsrec.qrc b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/pwsrec.qrc
new file mode 100644
index 00000000000..04068c6b8db
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/pwsrec.qrc
@@ -0,0 +1,14 @@
+
+
+ icons/Voronoi_diagram_2.png
+ icons/fileNew.png
+ icons/fileOpen.png
+ icons/fileSave.png
+ icons/fit-page-32.png
+ icons/inputPoint.png
+ icons/snapshot.png
+ icons/triangulation.png
+ icons/until.png
+ icons/vertex.png
+
+
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/pwsrec.ui b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/pwsrec.ui
new file mode 100644
index 00000000000..41f90b6ceda
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/pwsrec.ui
@@ -0,0 +1,643 @@
+
+
+ Pierre Alliez
+ MainWindow
+
+
+
+ 0
+ 0
+ 680
+ 680
+
+
+
+ PWS Rec 2D
+
+
+
+ -
+
+
+ QLayout::SetDefaultConstraint
+
+
-
+
+
+ Qt::StrongFocus
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Min. mass
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksBelow
+
+
+ 10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ toolBar
+
+
+
+
+
+ TopToolBarArea
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+ Quit
+
+
+ Ctrl+Q
+
+
+
+
+ true
+
+
+ false
+
+
+
+ :/icons/inputPoint.png:/icons/inputPoint.png
+
+
+ Insert mode
+
+
+ Insert Point
+
+
+ Insert Point
+
+
+
+
+
+ :/icons/fileNew.png:/icons/fileNew.png
+
+
+ Clear
+
+
+ Clear
+
+
+ Space
+
+
+
+
+
+ :/icons/fileOpen.png:/icons/fileOpen.png
+
+
+ Load point set
+
+
+ Load point set
+
+
+ Ctrl+O
+
+
+
+
+
+ :/icons/fileSave.png:/icons/fileSave.png
+
+
+ Save point set
+
+
+ Save point set
+
+
+ Ctrl+S
+
+
+
+
+ Circle...
+
+
+
+
+ Half circle...
+
+
+
+
+ Box...
+
+
+ B
+
+
+
+
+ Line...
+
+
+
+
+ Re-init
+
+
+ I
+
+
+
+
+ Run 1 step
+
+
+ R
+
+
+
+
+ true
+
+
+ false
+
+
+ Foot points
+
+
+ View foot points
+
+
+ F
+
+
+
+
+ true
+
+
+ true
+
+
+ Points
+
+
+ View points
+
+
+ P
+
+
+
+
+ true
+
+
+ false
+
+
+ Triangulation
+
+
+ View edges of the triangulation
+
+
+ T
+
+
+
+
+
+ :/icons/fit-page-32.png:/icons/fit-page-32.png
+
+
+ Recenter
+
+
+
+
+ true
+
+
+ true
+
+
+ Vertices
+
+
+ V
+
+
+
+
+ Two boxes...
+
+
+
+
+ Stair...
+
+
+
+
+ Skyline...
+
+
+
+
+ true
+
+
+ false
+
+
+ Edge priority
+
+
+ Z
+
+
+
+
+ Run 10 steps
+
+
+ 1
+
+
+
+
+ Run 100 steps
+
+
+ 2
+
+
+
+
+ Run 1000 steps
+
+
+ 3
+
+
+
+
+ Add outliers
+
+
+ O
+
+
+
+
+
+ :/icons/snapshot.png:/icons/snapshot.png
+
+
+ Snapshot
+
+
+ Ctrl+C
+
+
+
+
+ Increasingly sharp angles...
+
+
+
+
+ Box with boundaries...
+
+
+
+
+ Box with missing corners...
+
+
+
+
+ Star...
+
+
+
+
+ Spiral...
+
+
+
+
+ true
+
+
+ false
+
+
+ Edge cost
+
+
+ C
+
+
+
+
+ Run until...
+
+
+ U
+
+
+
+
+ Parallel lines...
+
+
+
+
+ Noise
+
+
+ N
+
+
+
+
+ Relocate
+
+
+ L
+
+
+
+
+ true
+
+
+ Relocation
+
+
+ Shift+L
+
+
+
+
+ true
+
+
+ false
+
+
+ Ghost edges
+
+
+ G
+
+
+
+
+ Invert mass
+
+
+ Shift+I
+
+
+
+
+ true
+
+
+ true
+
+
+ Relevance
+
+
+ Shift+R
+
+
+
+
+ true
+
+
+ Tolerance
+
+
+ Shift+T
+
+
+
+
+ Clamp mass
+
+
+
+
+ true
+
+
+ Bins
+
+
+ Shift+B
+
+
+
+
+ Subdivide
+
+
+
+
+ Widely variable sampling
+
+
+
+
+ Decimate
+
+
+
+
+ One point out of n
+
+
+
+
+ true
+
+
+ Multiple Choice
+
+
+ M
+
+
+
+
+ Options
+
+
+ Ctrl+P
+
+
+
+
+
+ GlViewer
+ QWidget
+
+ 1
+
+
+
+
+
+
+
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/random.h b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/random.h
new file mode 100644
index 00000000000..b8886e54b7c
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/random.h
@@ -0,0 +1,26 @@
+#ifndef _RANDOM_
+#define _RANDOM_ 1
+
+inline
+double random_double(const double min, const double max)
+{
+ double range = max - min;
+ return min + (double(rand()) / double(RAND_MAX)) * range;
+}
+
+inline
+int random_int(const int min, const int max)
+{
+ int range = max - min;
+ return min + int((double(rand())/double(RAND_MAX)) * range);
+}
+
+template
+Vector random_vec(const double scale)
+{
+ double dx = random_double(-scale, scale);
+ double dy = random_double(-scale, scale);
+ return Vector(dx, dy);
+}
+
+#endif
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/render.cpp b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/render.cpp
new file mode 100644
index 00000000000..80b16fd9d39
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/render.cpp
@@ -0,0 +1,894 @@
+#include
+
+// Qt
+#include
+
+// local
+#include "Reconstruction_simplification_kerneled_2.h"
+#include
+
+typedef Reconstruction_simplification_kerneled_2::Rec_edge_2 PEdge;
+typedef Reconstruction_simplification_kerneled_2 R_s_k_2;
+
+void R_s_k_2::print_stats() const
+{
+ int nb_solid = 0;
+ int nb_ghost = 0;
+ for (Finite_edges_iterator ei = m_dt.finite_edges_begin();
+ ei != m_dt.finite_edges_end(); ++ei)
+ {
+ Edge edge = *ei;
+ if (m_dt.is_ghost(edge)) nb_ghost++;
+ else nb_solid++;
+ }
+
+ std::cerr << "STATS" << std::endl;
+ std::cerr << "# vertices : " << m_dt.number_of_vertices()-4 << std::endl;
+ std::cerr << "# triangles: " << m_dt.number_of_faces() << std::endl;
+ std::cerr << "# edges: " << m_dt.tds().number_of_edges() << std::endl;
+ std::cerr << "# solid: " << nb_solid << std::endl;
+ std::cerr << "# ghost: " << nb_ghost << std::endl;
+}
+
+QColor R_s_k_2::get_color(float value) const
+{
+ float hue = 240.0*(1.0 - value);
+ QColor color;
+ color.setHsv(hue, 255, 255);
+ return color;
+}
+
+void R_s_k_2::draw_point(const Point& point)
+{
+ ::glBegin(GL_POINTS);
+ ::glVertex2f(point.x(), point.y());
+ ::glEnd();
+}
+
+void R_s_k_2::draw_segment(const Point& s, const Point& t)
+{
+ ::glBegin(GL_LINES);
+ ::glVertex2d(s.x(), s.y());
+ ::glVertex2d(t.x(), t.y());
+ ::glEnd();
+}
+
+void R_s_k_2::draw_edge(const Edge& edge)
+{
+ int i = edge.second;
+ Face_handle face = edge.first;
+ Point a = face->vertex((i+1)%3)->point();
+ Point b = face->vertex((i+2)%3)->point();
+ draw_segment(a, b);
+}
+
+void R_s_k_2::draw_face(Face_handle face)
+{
+ ::glBegin(GL_TRIANGLES);
+ for (int i = 0; i < 3; ++i)
+ {
+ Point p = face->vertex(i)->point();
+ ::glVertex2f(p.x(), p.y());
+ }
+ ::glEnd();
+}
+
+void R_s_k_2::draw_edge_with_arrow(const Point& s, const Point& t)
+{
+ Vector vec = t - s;
+ Vector vec90(-vec.y(),vec.x());
+
+ // draw edge
+ draw_segment(s, t);
+
+ // draw an arrow toward merged vertex
+ Point a = t - 0.4 * vec;
+ Point b = a - 0.2 * vec - 0.1 * vec90;
+ Point c = a - 0.2 * vec + 0.1 * vec90;
+ ::glBegin(GL_TRIANGLES);
+ ::glVertex2d(a.x(), a.y());
+ ::glVertex2d(b.x(), b.y());
+ ::glVertex2d(c.x(), c.y());
+ ::glEnd();
+}
+
+void R_s_k_2::draw_vertices(const float point_size,
+ const float red,
+ const float green,
+ const float blue)
+{
+ for (Finite_vertices_iterator vi = m_dt.finite_vertices_begin();
+ vi != m_dt.finite_vertices_end(); vi++)
+ {
+ Vertex_handle vertex = vi;
+ if (vertex->pinned())
+ {
+ ::glPointSize(point_size);
+ ::glColor3f(0.0f, 0.0f, 0.0f);
+ }
+ else
+ {
+ ::glPointSize(3*point_size);
+ ::glColor3f(red,green,blue);
+ }
+ draw_point(vertex->point());
+ }
+}
+
+void R_s_k_2::draw_edges(const float line_width,
+ const float red,
+ const float green,
+ const float blue)
+{
+ ::glLineWidth(line_width);
+ for (Finite_edges_iterator ei = m_dt.finite_edges_begin();
+ ei != m_dt.finite_edges_end(); ei++)
+ {
+ Edge edge = *ei;
+ Edge twin = m_dt.twin_edge(edge);
+ if (m_dt.is_pinned(edge) && m_dt.is_pinned(twin))
+ ::glColor3f(0.9f,0.9f,0.75f);
+ else
+ ::glColor3f(red,green,blue);
+ draw_edge(edge);
+ }
+}
+
+void R_s_k_2::draw_footpoints(const float line_width,
+ const float red,
+ const float green,
+ const float blue)
+{
+ draw_mesh_footpoints(m_dt, line_width, red, green, blue);
+}
+
+void R_s_k_2::draw_mesh_footpoints(const Triangulation& mesh,
+ const float line_width,
+ const float red,
+ const float green,
+ const float blue)
+{
+ ::glLineWidth(line_width);
+ for (Finite_edges_iterator ei = mesh.finite_edges_begin(); ei != mesh.finite_edges_end(); ei++)
+ {
+ Edge edge = *ei;
+ draw_edge_footpoints(mesh, edge, red, green, blue);
+ draw_edge_footpoints(mesh, mesh.twin_edge(edge), red, green, blue);
+ }
+}
+
+void R_s_k_2::draw_edge_footpoints(const Triangulation& mesh,
+ const Edge& edge,
+ const float red,
+ const float green,
+ const float blue)
+{
+ const Point& a = mesh.source_vertex(edge)->point();
+ const Point& b = mesh.target_vertex(edge)->point();
+ const Sample_vector& samples = edge.first->samples(edge.second);
+
+ Sample_vector::const_iterator it;
+ for (it = samples.begin(); it != samples.end(); ++it)
+ {
+ Sample_* sample = *it;
+ Point p = sample->point();
+ FT m = 0.5*(1.0 - sample->mass());
+
+ Point q;
+ if (mesh.get_plan(edge) == 0)
+ {
+ ::glColor3f(0.8f + m, m, m);
+ FT Da = CGAL::squared_distance(p, a);
+ FT Db = CGAL::squared_distance(p, b);
+ if (Da < Db) q = a;
+ else q = b;
+ }
+ else
+ {
+ ::glColor3f(red + m, green + m, blue + m);
+ FT t = sample->coordinate();
+ q = CGAL::ORIGIN + (1.0 - t)*(a - CGAL::ORIGIN) + t*(b - CGAL::ORIGIN);
+ }
+ draw_segment(p, q);
+ }
+}
+
+void R_s_k_2::draw_pedges(const float line_width)
+{
+ int nb_edges = 0;
+ int nb_pinned = 0;
+ int nb_cyclic = 0;
+ int nb_discart = 0;
+ FT min_value = (std::numeric_limits::max)();
+ FT max_value = -(std::numeric_limits::max)();
+ std::vector values;
+ std::vector edges;
+ for (Finite_edges_iterator ei = m_dt.finite_edges_begin(); ei != m_dt.finite_edges_end(); ++ei)
+ {
+ Edge edge = *ei;
+ for (unsigned int i = 0; i < 2; ++i)
+ {
+ if (m_dt.is_pinned(edge))
+ {
+ nb_pinned++;
+ continue;
+ }
+
+ if (m_dt.is_target_cyclic(edge))
+ {
+ nb_cyclic++;
+ continue;
+ }
+
+ PEdge pedge;
+ bool ok = create_pedge(edge, pedge);
+ if (ok)
+ {
+ edges.push_back(edge);
+ values.push_back(pedge.priority());
+ min_value = (std::min)(min_value, values.back());
+ max_value = (std::max)(max_value, values.back());
+ }
+ else
+ {
+ nb_discart++;
+ ::glColor3f(1.0, 0.0, 1.0);
+ draw_edge(edge);
+ }
+ edge = m_dt.twin_edge(edge);
+ nb_edges++;
+ }
+ }
+ if (min_value == max_value) max_value += 1.0;
+
+ std::size_t N = values.size();
+ for (unsigned int i = 0; i < N; ++i)
+ draw_one_pedge(edges[i], values[i], min_value, max_value, line_width);
+
+ std::cout << "There are: " << N << " pedges"
+ << " x " << nb_discart << " discarted"
+ << " x " << nb_pinned << " pinned"
+ << " x " << nb_cyclic << " cyclic"
+ << " = " << nb_edges << " edges"
+ << std::endl;
+}
+
+void R_s_k_2::draw_one_pedge(const Edge& edge,
+ const FT value,
+ const FT min_value,
+ const FT max_value,
+ const float line_width)
+{
+ if (value == min_value)
+ {
+ ::glLineWidth(2*line_width);
+ ::glColor3f(0.0f, 0.0f, 0.0f);
+ }
+ else
+ {
+ ::glLineWidth(line_width);
+ FT color = (value - min_value) / (max_value - min_value);
+ QColor qcolor = get_color(color);
+ ::glColor3f(qcolor.redF(), qcolor.greenF(), qcolor.blueF());
+ }
+
+ Point s = m_dt.source_vertex(edge)->point();
+ Point t = m_dt.target_vertex(edge)->point();
+ Point c = CGAL::midpoint(s, t);
+ draw_edge_with_arrow(c, t);
+}
+
+void R_s_k_2::draw_costs(const float line_width, const bool view_ghost)
+{
+ FT min_value = (std::numeric_limits::max)();
+ FT max_value = -(std::numeric_limits::max)();
+ for (Finite_edges_iterator ei = m_dt.finite_edges_begin(); ei != m_dt.finite_edges_end(); ++ei)
+ {
+ Edge edge = *ei;
+ if (m_dt.is_ghost(edge)) continue;
+ FT value = m_dt.get_cost(edge).finalize(m_alpha);
+ min_value = (std::min)(min_value, value);
+ max_value = (std::max)(max_value, value);
+ }
+ if (min_value == max_value) max_value += 1.0;
+
+ ::glLineWidth(line_width);
+ for (Finite_edges_iterator ei = m_dt.finite_edges_begin(); ei != m_dt.finite_edges_end(); ++ei)
+ {
+ Edge edge = *ei;
+ draw_one_cost(edge, min_value, max_value, view_ghost);
+ }
+}
+
+void R_s_k_2::draw_one_cost(const Edge& edge,
+ const FT min_value,
+ const FT max_value,
+ const bool view_ghost)
+{
+ FT mass = m_dt.get_mass(edge);
+ if (mass == 0.0)
+ {
+ if (!view_ghost) return;
+ ::glColor3f(0.5f, 0.5f, 0.5f);
+ draw_edge(edge);
+ return;
+ }
+
+ if (m_dt.is_ghost(edge))
+ {
+ if (!view_ghost) return;
+ ::glColor3f(0.5f, 0.5f, 0.5f);
+ draw_edge(edge);
+ return;
+ }
+
+ FT value = m_dt.get_cost(edge).finalize(m_alpha);
+ FT color = (value - min_value) / (max_value - min_value);
+ ::glColor3d(0.0, 1.0-color, color); // [green, blue]
+ draw_edge(edge);
+}
+
+void R_s_k_2::draw_relevance(const float line_width, const int nb)
+{
+ MultiIndex mindex;
+ FT min_value = (std::numeric_limits::max)();
+ FT max_value = -(std::numeric_limits::max)();
+ unsigned nb_initial = 0;
+ for (Finite_edges_iterator ei = m_dt.finite_edges_begin(); ei != m_dt.finite_edges_end(); ++ei)
+ {
+ Edge edge = *ei;
+ if (m_dt.is_ghost(edge)) continue;
+ FT value = m_dt.get_edge_relevance(edge); // >= 0
+
+ nb_initial++;
+ min_value = (std::min)(min_value, value);
+ max_value = (std::max)(max_value, value);
+ mindex.insert(PEdge(edge, value));
+ }
+ if (min_value == max_value) max_value += 1.0;
+
+ ::glLineWidth(line_width);
+ int nb_remove = (std::min)(nb, int(mindex.size()));
+
+ ::glColor3d(0.5, 0.1, 0.1);
+ for (int i = 0; i < nb_remove; ++i)
+ {
+
+ PEdge pedge = *(mindex.get<1>()).begin();
+ (mindex.get<0>()).erase(pedge);
+ }
+
+ ::glColor3d(0.0, 0.5, 0.0);
+ while (!mindex.empty())
+ {
+ PEdge pedge = *(mindex.get<1>()).begin();
+ (mindex.get<0>()).erase(pedge);
+ draw_edge(pedge.edge());
+ }
+}
+
+void R_s_k_2::draw_bins(const float thickness)
+{
+ ::glLineWidth(thickness);
+ for (Finite_edges_iterator ei = m_dt.finite_edges_begin(); ei != m_dt.finite_edges_end(); ++ei)
+ {
+ Edge edge = *ei;
+ if (m_dt.get_plan(edge) == 0)
+ draw_bins_plan0(edge);
+ else
+ draw_bins_plan1(edge);
+ }
+}
+
+void R_s_k_2::draw_bins_plan0(const Edge& edge)
+{
+ Edge twin = m_dt.twin_edge(edge);
+ const Point& pa = m_dt.source_vertex(edge)->point();
+ const Point& pb = m_dt.target_vertex(edge)->point();
+
+ Sample_vector samples;
+ m_dt.collect_samples_from_edge(edge, samples);
+ m_dt.collect_samples_from_edge(twin, samples);
+
+ ::glColor3f(0.0f, 1.0f, 0.0f);
+ Sample_vector_const_iterator it;
+ for (it = samples.begin(); it != samples.end(); ++it)
+ {
+ Sample_* sample = *it;
+ const Point& ps = sample->point();
+
+ Point q = pa;
+ FT Da = CGAL::squared_distance(ps, pa);
+ FT Db = CGAL::squared_distance(ps, pb);
+ if (Da > Db) q = pb;
+
+ draw_segment(ps, q);
+ }
+}
+
+void R_s_k_2::draw_bins_plan1(const Edge& edge)
+{
+ FT M = m_dt.get_mass(edge);
+ Vector va = m_dt.source_vertex(edge)->point() - CGAL::ORIGIN;
+ Vector vb = m_dt.target_vertex(edge)->point() - CGAL::ORIGIN;
+
+ ::glColor3f(1.0f, 0.0f, 0.0f);
+ SQueue queue;
+ FT start = 0.0;
+ m_dt.sort_samples_from_edge(edge, queue);
+ while (!queue.empty())
+ {
+ PSample psample = queue.top();
+ queue.pop();
+
+ const FT m = psample.sample()->mass();
+ const Point& ps = psample.sample()->point();
+
+ FT bin = m/M;
+ FT alpha = start + 0.5*bin;
+ Point q = CGAL::ORIGIN + (1.0-alpha)*va + alpha*vb;
+ start += bin;
+
+ draw_segment(ps, q);
+ }
+}
+
+void R_s_k_2::draw_relocation()
+{
+ for (Finite_vertices_iterator v = m_dt.finite_vertices_begin(); v != m_dt.finite_vertices_end(); ++v)
+ {
+ Vertex_handle vertex = v;
+ if (vertex->pinned()) continue;
+
+ const Point& pv = vertex->point();
+ v->relocated() = compute_relocation(vertex);
+
+ Vector move(0.0, 0.0);
+ Edge_circulator ecirc = m_dt.incident_edges(vertex);
+ Edge_circulator eend = ecirc;
+ CGAL_For_all(ecirc, eend)
+ {
+ Edge edge = *ecirc;
+ if (m_dt.source_vertex(edge) != vertex)
+ edge = m_dt.twin_edge(edge);
+
+ Vector grad(0.0, 0.0);
+ if (m_dt.get_plan(edge) == 0)
+ grad = compute_gradient_for_plan0(edge);
+ else
+ grad = compute_gradient_for_plan1(edge);
+
+ move = move + grad;
+ ::glLineWidth(2.0f);
+ ::glColor3f(1.0f, 1.0f, 0.0f);
+ draw_edge_with_arrow(pv, pv-grad);
+ }
+
+ ::glLineWidth(1.0f);
+ ::glColor3f(1.0f, 0.0f, 0.0f);
+ draw_edge_with_arrow(pv, pv-move);
+ }
+
+ ::glBegin(GL_LINES);
+ ::glLineWidth(3.0f);
+ ::glColor3f(0.1f, 1.0f, 1.0f);
+ for (Finite_edges_iterator ei = m_dt.finite_edges_begin(); ei != m_dt.finite_edges_end(); ++ei)
+ {
+ Edge edge = *ei;
+ Edge twin = m_dt.twin_edge(edge);
+ if (m_dt.is_pinned(edge) || m_dt.is_pinned(twin)) continue;
+
+ const Point& pa = m_dt.source_vertex(edge)->relocated();
+ const Point& pb = m_dt.target_vertex(edge)->relocated();
+ ::glVertex2d(pa.x(), pa.y());
+ ::glVertex2d(pb.x(), pb.y());
+ }
+ ::glEnd();
+}
+
+bool R_s_k_2::locate_edge(const Point& query, Edge& edge)
+{
+ if (m_dt.number_of_faces() == 0) return false;
+
+ Face_handle face = m_dt.locate(query);
+ if (face == Face_handle()) return false;
+ if (m_dt.is_infinite(face)) return false;
+
+ edge = m_dt.find_nearest_edge(query, face);
+ if (edge.first == Face_handle()) return false;
+
+ if (m_dt.is_pinned(edge) || m_dt.is_target_cyclic(edge))
+ return false;
+
+ return true;
+}
+
+void R_s_k_2::draw_one_ring(const float point_size, const float line_width, const Point& query)
+{
+ Edge edge;
+ bool ok = locate_edge(query, edge);
+ if (!ok) return;
+
+ Triangulation copy;
+ Edge copy_edge = copy_star(edge, copy);
+ draw_mesh_one_ring(point_size, line_width, copy, copy_edge);
+}
+
+void R_s_k_2::draw_mesh_one_ring(const float point_size,
+ const float line_width,
+ const Triangulation& mesh,
+ const Edge& edge)
+{
+ Vertex_handle s = mesh.source_vertex(edge);
+ Vertex_handle t = mesh.target_vertex(edge);
+
+ draw_bg_faces(mesh, 1.0f, 0.7f, 0.7f, 0.5f);
+ draw_vertex_faces(s, mesh, 0.7f, 0.7f, 1.0f, 1.0f);
+
+ ::glLineWidth(line_width);
+ draw_bg_edges(mesh, 0.7f, 0.3f, 0.7f, 1.f, 0.f, 0.f);
+ draw_vertex_edges(s, mesh, 0.f, 0.8f, 0.f, 0.f, 0.2f, 0.2f);
+
+ ::glLineWidth(2.0f*line_width);
+ ::glColor3f(0., 0., 1.);
+ draw_edge_with_arrow(s->point(), t->point());
+
+ ::glPointSize(0.5*point_size);
+ draw_bg_vertices(mesh, 0.f, 0.f, 0.f);
+ ::glPointSize(point_size);
+ ::glColor3f(0., 1., 0.);
+ draw_point(s->point());
+ ::glColor3f(1., 1., 0.);
+ draw_point(t->point());
+}
+
+void R_s_k_2::draw_blocking_edges(const float point_size, const float line_width, const Point& query)
+{
+ Edge edge;
+ bool ok = locate_edge(query, edge);
+ if (!ok) return;
+
+ Triangulation copy;
+ Edge copy_edge = copy_star(edge, copy);
+ draw_mesh_blocking_edges(point_size, line_width, copy, copy_edge);
+}
+
+void R_s_k_2::draw_mesh_blocking_edges(const float point_size,
+ const float line_width,
+ const Triangulation& mesh,
+ const Edge& edge)
+{
+ Vertex_handle s = mesh.source_vertex(edge);
+ Vertex_handle t = mesh.target_vertex(edge);
+
+ draw_mesh_one_ring(point_size, line_width, mesh, edge);
+
+ ::glColor3f(0.0f, 0.0f, 0.0f);
+ ::glLineWidth(2.0f*line_width);
+ Face_circulator fcirc = mesh.incident_faces(s);
+ Face_circulator fend = fcirc;
+ CGAL_For_all(fcirc, fend)
+ {
+ Face_handle f = fcirc;
+ Edge ab(f, f->index(s));
+ Vertex_handle a = mesh.source_vertex(ab);
+ Vertex_handle b = mesh.target_vertex(ab);
+ if (!mesh.is_triangle_ccw(a, b, t))
+ {
+ draw_segment(a->point(), b->point());
+ }
+ }
+}
+
+void R_s_k_2::draw_collapsible_edge(const float point_size,
+ const float line_width,
+ const Point& query)
+{
+ Edge edge;
+ bool ok = locate_edge(query, edge);
+ if (!ok) return;
+
+ Triangulation copy;
+ Edge copy_edge = copy_star(edge, copy);
+ Vertex_handle copy_src = copy.source_vertex(copy_edge);
+
+ Edge_vector copy_hull;
+ copy.get_edges_from_star_minus_link(copy_src, copy_hull, true);
+ ok = copy.make_collapsible(copy_edge, copy_hull.begin(), copy_hull.end(), m_verbose);
+
+ if (ok)
+ draw_mesh_one_ring(point_size, line_width, copy, copy_edge);
+ else
+ draw_mesh_blocking_edges(point_size, line_width, copy, copy_edge);
+}
+
+void R_s_k_2::draw_cost_stencil(const float point_size,
+ const float line_width,
+ const Point& query)
+{
+ Edge edge;
+ bool ok = locate_edge(query, edge);
+ if (!ok) return;
+
+ Triangulation copy;
+ Edge copy_edge = copy_star(edge, copy);
+ Vertex_handle copy_src = copy.source_vertex(copy_edge);
+ Vertex_handle copy_dst = copy.target_vertex(copy_edge);
+
+ Edge_vector copy_hull;
+ copy.get_edges_from_star_minus_link(copy_src, copy_hull, true);
+ ok = copy.make_collapsible(copy_edge, copy_hull.begin(), copy_hull.end(), m_verbose);
+ if (!ok) return;
+ copy.collapse(copy_edge, m_verbose);
+
+ draw_bg_faces(copy, 0.7f, 0.7f, 1.0f, 1.0f);
+
+ ::glLineWidth(line_width);
+ ::glPointSize(point_size);
+
+ Edge_vector stencil;
+ collect_cost_stencil(copy, copy_hull.begin(), copy_hull.end(), stencil);
+ for (Edge_vector::const_iterator it = stencil.begin(); it != stencil.end(); ++it)
+ {
+ Edge e = *it;
+ ::glColor3f(0.7f, 0.4f, 0.0f);
+ draw_edge(e);
+ ::glColor3f(0.0f, 0.0f, 0.0f);
+ draw_point(copy.source_vertex(e)->point());
+ draw_point(copy.target_vertex(e)->point());
+ }
+}
+
+void R_s_k_2::draw_remove_queue_stencil(const float point_size,
+ const float line_width,
+ const Point& query)
+{
+ Edge edge;
+ bool ok = locate_edge(query, edge);
+ if (!ok) return;
+
+ Edge_vector hull;
+ Edge_vector stencil;
+ Edge_vector::const_iterator it;
+ Vertex_handle src = m_dt.source_vertex(edge);
+ m_dt.get_edges_from_star_minus_link(src, hull, true);
+ collect_pqueue_stencil(m_dt, hull.begin(), hull.end(), stencil);
+
+ draw_vertex_faces(src, m_dt, 0.7f, 0.7f, 1.0f, 1.0f);
+
+ ::glLineWidth(0.5*line_width);
+ for (it = stencil.begin(); it != stencil.end(); ++it)
+ {
+ Edge ab = *it;
+ ::glColor3f(1.0f, 0.6f, 1.0f);
+ draw_edge(ab);
+ }
+
+ ::glLineWidth(line_width);
+ ::glPointSize(point_size);
+ for (it = stencil.begin(); it != stencil.end(); ++it)
+ {
+ Edge ab = *it;
+ Vertex_handle va = ab.first->vertex( (ab.second+1)%3 );
+ Vertex_handle vb = ab.first->vertex( (ab.second+2)%3 );
+ const Point& pa = va->point();
+ const Point& pb = vb->point();
+ Point pc = CGAL::midpoint(pa, pb);
+ ::glColor3f(0.8f, 0.2f, 0.8f);
+ draw_edge_with_arrow(pc, pb);
+ ::glColor3f(0.0f, 0.0f, 0.0f);
+ draw_point(pa);
+ draw_point(pb);
+ }
+}
+
+void R_s_k_2::draw_push_queue_stencil(const float point_size,
+ const float line_width,
+ const Point& query)
+{
+ Edge edge;
+ bool ok = locate_edge(query, edge);
+ if (!ok) return;
+
+ Edge_vector hull;
+ Edge_vector stencil;
+ Vertex_handle src = m_dt.source_vertex(edge);
+ m_dt.get_edges_from_star_minus_link(src, hull, true);
+ collect_pqueue_stencil(m_dt, hull.begin(), hull.end(), stencil);
+
+ Edge_vector::iterator it = stencil.begin();
+ while (it != stencil.end())
+ {
+ Edge edge = *it;
+ if (m_dt.source_vertex(edge) == src)
+ it = stencil.erase(it);
+ else if (m_dt.target_vertex(edge) == src)
+ it = stencil.erase(it);
+ else
+ it++;
+ }
+
+ Triangulation copy;
+ Edge_vector copy_hull;
+ Edge_vector copy_stencil;
+ Edge copy_edge = copy_star(edge, copy);
+ Vertex_handle copy_src = copy.source_vertex(copy_edge);
+ Vertex_handle copy_dst = copy.target_vertex(copy_edge);
+ copy.get_edges_from_star_minus_link(copy_src, copy_hull, true);
+ ok = copy.make_collapsible(copy_edge, copy_hull.begin(), copy_hull.end(), m_verbose);
+ if (!ok) return;
+ copy.collapse(copy_edge, m_verbose);
+ collect_cost_stencil(copy, copy_hull.begin(), copy_hull.end(), copy_stencil);
+
+ for (it = copy_stencil.begin(); it != copy_stencil.end(); ++it)
+ {
+ Edge edge = *it;
+ Edge twin = copy.twin_edge(edge);
+ if (!copy.is_pinned(edge)) stencil.push_back(edge);
+ if (!copy.is_pinned(twin)) stencil.push_back(twin);
+ }
+
+ draw_bg_faces(copy, 0.7f, 0.7f, 1.0f, 1.0f);
+
+ ::glLineWidth(0.5*line_width);
+ for (it = stencil.begin(); it != stencil.end(); ++it)
+ {
+ Edge ab = *it;
+ ::glColor3f(1.0f, 0.6f, 1.0f);
+ draw_edge(ab);
+ }
+
+ ::glLineWidth(line_width);
+ ::glPointSize(point_size);
+ for (it = stencil.begin(); it != stencil.end(); ++it)
+ {
+ Edge ab = *it;
+ Vertex_handle va = ab.first->vertex( (ab.second+1)%3 );
+ Vertex_handle vb = ab.first->vertex( (ab.second+2)%3 );
+ const Point& pa = va->point();
+ const Point& pb = vb->point();
+ Point pc = CGAL::midpoint(pa, pb);
+ ::glColor3f(0.8f, 0.2f, 0.8f);
+ draw_edge_with_arrow(pc, pb);
+ ::glColor3f(0.0f, 0.0f, 0.0f);
+ draw_point(pa);
+ draw_point(pb);
+ }
+}
+
+void R_s_k_2::draw_bg_faces(const Triangulation& mesh,
+ const float red,
+ const float green,
+ const float blue,
+ const float alpha)
+{
+ ::glEnable(GL_BLEND);
+ ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ ::glColor4f(red, green, blue, alpha);
+ for (Finite_faces_iterator fi = mesh.finite_faces_begin(); fi != mesh.finite_faces_end(); ++fi)
+ {
+ Face_handle f = fi;
+ draw_face(f);
+ }
+ ::glDisable(GL_BLEND);
+}
+
+void R_s_k_2::draw_bg_edges(const Triangulation& mesh,
+ const float ri,
+ const float gi,
+ const float bi,
+ const float ro,
+ const float go,
+ const float bo)
+{
+ for (Finite_faces_iterator fi = mesh.finite_faces_begin(); fi != mesh.finite_faces_end(); ++fi)
+ {
+ Face_handle f = fi;
+ for (unsigned int i = 0; i < 3; ++i)
+ {
+ Edge e(f, i);
+ e = mesh.twin_edge(e);
+ if (mesh.is_infinite(e.first))
+ ::glColor3f(ro, go, bo);
+ else
+ ::glColor3f(ri, gi, bi);
+ draw_edge(e);
+ }
+ }
+}
+
+void R_s_k_2::draw_bg_vertices(const Triangulation& mesh,
+ const float red,
+ const float green,
+ const float blue)
+{
+ ::glColor3f(red, green, blue);
+ for (Finite_vertices_iterator vi = mesh.finite_vertices_begin(); vi != mesh.finite_vertices_end(); ++vi)
+ {
+ Vertex_handle v = vi;
+ draw_point(v->point());
+ }
+}
+
+void R_s_k_2::draw_vertex_faces(Vertex_handle vertex,
+ const Triangulation& mesh,
+ const float red,
+ const float green,
+ const float blue,
+ const float alpha)
+{
+ ::glEnable(GL_BLEND);
+ ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ ::glColor4f(red, green, blue, alpha);
+ Face_circulator fcirc = mesh.incident_faces(vertex);
+ Face_circulator fend = fcirc;
+ CGAL_For_all(fcirc, fend)
+ {
+ Face_handle f = fcirc;
+ if (mesh.is_infinite(f)) continue;
+ draw_face(f);
+ }
+ ::glDisable(GL_BLEND);
+}
+
+void R_s_k_2::draw_vertex_edges(Vertex_handle vertex,
+ const Triangulation& mesh,
+ const float ri,
+ const float gi,
+ const float bi,
+ const float ro,
+ const float go,
+ const float bo)
+{
+ Face_circulator fcirc = mesh.incident_faces(vertex);
+ Face_circulator fend = fcirc;
+ CGAL_For_all(fcirc, fend)
+ {
+ Face_handle f = fcirc;
+ int index = f->index(vertex);
+ for (unsigned int i = 0; i < 3; ++i)
+ {
+ Edge e(f, i);
+ if (mesh.is_infinite(e)) continue;
+ if (static_cast(i) == index) ::glColor3f(ro, go, bo);
+ else ::glColor3f(ri, gi, bi);
+ draw_edge(e);
+ }
+ }
+}
+
+void R_s_k_2::save_edges(std::ofstream& ofs, const int nb)
+{
+ MultiIndex mindex;
+ for (Finite_edges_iterator ei = m_dt.finite_edges_begin(); ei != m_dt.finite_edges_end(); ++ei)
+ {
+ Edge edge = *ei;
+ if (m_dt.is_ghost(edge)) continue;
+ FT value = m_dt.get_edge_relevance(edge); // >= 0
+ mindex.insert(PEdge(edge, value));
+ }
+
+ int nb_remove = (std::min)(nb, int(mindex.size()));
+ for (int i = 0; i < nb_remove; ++i)
+ {
+ PEdge pedge = *(mindex.get<1>()).begin();
+ (mindex.get<0>()).erase(pedge);
+
+ }
+
+ while (!mindex.empty())
+ {
+ PEdge pedge = *(mindex.get<1>()).begin();
+ (mindex.get<0>()).erase(pedge);
+ save_one_edge(ofs, pedge.edge());
+ }
+}
+
+void R_s_k_2::save_one_edge(std::ofstream& ofs, const Edge& edge)
+{
+ int i = edge.second;
+ Face_handle face = edge.first;
+ Point const& a = face->vertex((i+1)%3)->point();
+ Point const& b = face->vertex((i+2)%3)->point();
+ ofs << a << " - " << b << std::endl;
+}
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/scene.h b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/scene.h
new file mode 100644
index 00000000000..d617087dc28
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/scene.h
@@ -0,0 +1,1113 @@
+#ifndef SCENE_H_
+#define SCENE_H_
+
+// STL
+#include
+
+//Qt
+#include
+#include
+
+// local
+#include
+#include "Reconstruction_simplification_kerneled_2.h"
+#include
+
+
+#ifdef CGAL_USE_CIMG
+#include
+#endif
+#include "random.h"
+#include // std::pair
+#include
+#include
+#include
+
+class Scene {
+
+public:
+ typedef std::pair PointMassPair;
+
+ typedef std::vector PointMassList;
+ typedef PointMassList::const_iterator InputIterator;
+
+ typedef CGAL::value_type_traits::type MassPoint;
+
+ typedef CGAL::First_of_pair_property_map Point_property_map;
+ typedef CGAL::Second_of_pair_property_map Mass_property_map;
+
+ typedef CGAL::Reconstruction_simplification_2 R_s_2;
+
+ typedef K::Segment_2 Segment;
+
+ typedef R_s_2::Vector Vector;
+
+ typedef R_s_2::Vertex Vertex;
+ typedef R_s_2::Vertex_handle Vertex_handle;
+ typedef R_s_2::Vertex_iterator Vertex_iterator;
+ typedef R_s_2::Vertex_circulator Vertex_circulator;
+ typedef R_s_2::Finite_vertices_iterator Finite_vertices_iterator;
+
+ typedef R_s_2::Edge Edge;
+ typedef R_s_2::Edge_circulator Edge_circulator;
+ typedef R_s_2::Finite_edges_iterator Finite_edges_iterator;
+
+ typedef R_s_2::Face_handle Face_handle;
+ typedef R_s_2::Face_circulator Face_circulator;
+ typedef R_s_2::Finite_faces_iterator Finite_faces_iterator;
+
+ typedef R_s_2::Vertex_handle_map Vertex_handle_map;
+ typedef R_s_2::Face_handle_map Face_handle_map;
+
+ typedef R_s_2::Vertex_handle_set Vertex_handle_set;
+ typedef R_s_2::Edge_set Edge_set;
+
+ typedef R_s_2::Edge_vector Edge_vector;
+
+ typedef R_s_2::Sample_ Sample_;
+ typedef R_s_2::Sample_vector Sample_vector;
+ typedef R_s_2::Sample_vector_const_iterator Sample_vector_const_iterator;
+
+ typedef R_s_2::PSample PSample;
+ typedef R_s_2::SQueue SQueue;
+
+ typedef R_s_2::Rec_edge_2 PEdge;
+
+
+private:
+ // data
+ std::vector m_samples;
+ double m_min_mass;
+ double m_max_mass;
+
+ Reconstruction_simplification_kerneled_2* m_pwsrec;
+ int m_ignore;
+ bool m_init_done;
+ double m_percentage;
+
+ // bbox
+ double m_bbox_x;
+ double m_bbox_y;
+ double m_bbox_size;
+
+public:
+ Scene() {
+ srand(0); // for sake of repeatability
+ m_min_mass = 0.0;
+ m_max_mass = 0.0;
+ m_ignore = 0;
+ m_init_done = false;
+ m_percentage = 100.;
+ m_bbox_x = 0.0;
+ m_bbox_y = 0.0;
+ m_bbox_size = 1.0;
+
+ m_pwsrec = new Reconstruction_simplification_kerneled_2();
+ }
+
+ ~Scene() {
+ clear();
+ }
+
+ void clear() {
+ m_pwsrec->clear();
+ m_samples.clear();
+ m_max_mass = 0.0;
+ }
+
+ void set_min_mass(const double min_value) {
+ m_min_mass = min_value;
+ }
+
+ void set_percentage(double percentage) {
+ m_percentage = percentage;
+ }
+
+ void invert_mass() {
+ double new_max_mass = 0.0;
+ std::vector::iterator it;
+ for (it = m_samples.begin(); it != m_samples.end(); ++it) {
+ Sample_& sample = *it;
+ sample.mass() = m_max_mass - sample.mass();
+ new_max_mass = (std::max)(new_max_mass, sample.mass());
+ }
+ m_max_mass = new_max_mass;
+ }
+
+ void clamp_mass() {
+ std::vector new_samples;
+ std::vector::iterator it;
+ for (it = m_samples.begin(); it != m_samples.end(); ++it) {
+ Sample_& sample = *it;
+ if (sample.mass() > m_min_mass) {
+ sample.mass() = 1.0;
+ new_samples.push_back(sample);
+ }
+ }
+ m_samples = new_samples;
+ m_max_mass = 1.0;
+ }
+
+ void subdivide() {
+ if (m_samples.size() < 3)
+ return;
+
+ std::vector new_samples;
+ std::vector::const_iterator it = m_samples.begin();
+ std::vector::const_iterator last = it++;
+ while (it != m_samples.end()) {
+ Point p = CGAL::midpoint(last->point(), it->point());
+ FT m = 0.5 * (last->mass() + it->mass());
+ new_samples.push_back(Sample_(p, m));
+ last = it++;
+ }
+ it = m_samples.begin();
+ Point p = CGAL::midpoint(last->point(), it->point());
+ FT m = 0.5 * (last->mass() + it->mass());
+ new_samples.push_back(Sample_(p, m));
+
+ std::vector final_samples;
+ std::vector::const_iterator it2 = new_samples.begin();
+ while (it != m_samples.end() && it2 != new_samples.end()) {
+ final_samples.push_back(*it);
+ final_samples.push_back(*it2);
+ it++;
+ it2++;
+ }
+
+ m_samples = final_samples;
+ }
+
+ // SAMPLE //
+
+ void add_sample(const Point& point, const FT mass = 1.0) {
+ m_samples.push_back(Sample_(point, mass));
+ m_max_mass = (std::max)(m_max_mass, mass);
+ m_init_done = false;
+ }
+
+ void add_outliers(const unsigned int nb) {
+ std::cerr << "add " << nb << " outliers...";
+ for (unsigned int i = 0; i < nb; i++) {
+ Point outlier = CGAL::ORIGIN + random_vec(1.3);
+ m_samples.push_back(outlier);
+ }
+ m_init_done = false;
+ std::cerr << "done" << std::endl;
+ }
+
+ void noise(const FT scale) {
+ std::cerr << "noise by " << scale << "...";
+ std::vector::iterator it;
+ for (it = m_samples.begin(); it != m_samples.end(); it++) {
+ Sample_& sample = *it;
+ Point& point = sample.point();
+ point = point + random_vec(scale);
+ }
+ std::cerr << "done" << std::endl;
+ }
+
+ void normalize_points() {
+ noise(1e-5);
+ compute_bbox(m_bbox_x, m_bbox_y, m_bbox_size);
+ if (m_bbox_size == 0.0)
+ return;
+
+ Point center(m_bbox_x, m_bbox_y);
+ std::vector::iterator it;
+ for (it = m_samples.begin(); it != m_samples.end(); ++it) {
+ Sample_& sample = *it;
+ Vector vec = (sample.point() - center) / m_bbox_size;
+ sample.point() = CGAL::ORIGIN + vec;
+ }
+ m_bbox_x = m_bbox_y = 0.0;
+ m_bbox_size = 1.0;
+ }
+
+ void compute_bbox(double &x, double &y, double &scale) {
+ if (m_samples.empty()) {
+ x = y = 0.0;
+ scale = 1.0;
+ return;
+ }
+
+ FT x_min, x_max, y_min, y_max;
+ std::vector::const_iterator it = m_samples.begin();
+ Point p = it->point();
+ x_min = x_max = p.x();
+ y_min = y_max = p.y();
+ ++it;
+ for (; it != m_samples.end(); ++it) {
+ p = it->point();
+ x_min = (std::min)(x_min, p.x());
+ x_max = (std::max)(x_max, p.x());
+ y_min = (std::min)(y_min, p.y());
+ y_max = (std::max)(y_max, p.y());
+ }
+
+ x = 0.5 * (x_min + x_max);
+ y = 0.5 * (y_min + y_max);
+ scale = (std::max)(x_max - x_min, y_max - y_min);
+ if (scale == 0.0)
+ scale = 1.0;
+ }
+
+ // IO SAMPLES //
+
+ void load(const QString& filename, QWidget* qw) {
+ // TODO: load xml
+
+ if (filename.contains(".xy", Qt::CaseInsensitive)) {
+ load_xy_file(filename);
+ normalize_points();
+ return;
+ }
+
+ if (filename.contains(".txt", Qt::CaseInsensitive)) {
+ load_xy_file(filename);
+ normalize_points();
+ return;
+ }
+
+ if (filename.contains(".gtn", Qt::CaseInsensitive)) {
+ load_gathan_file(filename);
+ normalize_points();
+ return;
+ }
+
+ if (filename.contains(".dat", Qt::CaseInsensitive)) {
+ load_dat_file(filename);
+ normalize_points();
+ return;
+ }
+
+#ifdef CGAL_USE_CIMG
+ if (filename.contains(".bmp", Qt::CaseInsensitive)) {
+ bool use_gradient = false;
+
+ QMessageBox::StandardButton reply;
+ reply = QMessageBox::question(qw, QString("Open BMP"), "Use gradient?",
+ QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
+ if (reply == QMessageBox::Yes)
+ use_gradient = true;
+ else if (reply == QMessageBox::No)
+ use_gradient = false;
+ else
+ return;
+
+ if (use_gradient)
+ load_gradient(filename);
+ else
+ load_image(filename);
+ normalize_points();
+ return;
+ }
+
+ std::cerr << "Invalid file (try .xy, .txt, .gtn, .dat, .bmp)" << std::endl;
+#else
+ CGAL_USE(qw);
+ std::cerr << "Invalid file (try .xy, .txt, .gtn, .dat)" << std::endl;
+#endif
+ }
+
+ void load_xy_file(const QString& fileName) {
+
+ std::cout << "FILENAME " << fileName.toUtf8().constData() << std::endl;
+ std::ifstream ifs(qPrintable(fileName));
+ std::cerr << "read xy...";
+ Point point;
+ unsigned int nb = 0;
+ while (ifs >> point) {
+ add_sample(point, 1.0);
+ nb++;
+ }
+ std::cerr << "done (" << nb << " points)" << std::endl;
+ ifs.close();
+ }
+
+ void load_gathan_file(const QString& fileName) {
+ std::ifstream ifs(qPrintable(fileName));
+ std::cerr << "read gathan...";
+ Point point;
+ unsigned nb, x, y, z;
+ ifs >> nb >> x >> y >> z;
+ for (unsigned int i = 0; i < nb; ++i) {
+ ifs >> x >> point;
+ add_sample(point, 1.0);
+ }
+ std::cerr << "done (" << nb << " points)" << std::endl;
+ ifs.close();
+ }
+
+ void load_dat_file(const QString& fileName) {
+ std::ifstream ifs(qPrintable(fileName));
+ std::cerr << "read dat...";
+ Point point;
+ unsigned int n, m, nb = 0;
+ ifs >> n;
+ for (unsigned int i = 0; i < n; ++i) {
+ ifs >> m;
+ for (unsigned int j = 0; j < m; ++j) {
+ ifs >> point;
+ add_sample(point, 1.0);
+ }
+ nb += m;
+ }
+ std::cerr << "done (" << nb << " points)" << std::endl;
+ ifs.close();
+ }
+
+#ifdef CGAL_USE_CIMG
+ void load_image(const QString& fileName) {
+ std::cerr << "read image...";
+ cimg_library::CImg image(qPrintable(fileName));
+ std::cerr << "done" << std::endl;
+
+ std::cerr << "compute grayscale...";
+ cimg_library::CImg grayscale =
+ image.RGBtoHSV().get_channel(2).normalize(0.0f, 1.0f);
+ std::cerr << "done" << std::endl;
+
+ // turn pixels into weighted samples
+ std::cerr << "add samples...";
+ for (int i = 0; i < grayscale.width(); i++) {
+ for (int j = 0; j < grayscale.height(); j++) {
+ float mass = 1.0f - grayscale.atXY(i, j);
+ double x = double(i) / grayscale.width();
+ double y = 1.0 - double(j) / grayscale.height();
+ if (mass > 0.f)
+ add_sample(Point(x, y), mass);
+ }
+ }
+ std::cerr << "done (" << m_samples.size() << ")" << std::endl;
+ }
+
+ void load_gradient(const QString& fileName) {
+ std::cerr << "read image...";
+ cimg_library::CImg image(qPrintable(fileName));
+ std::cerr << "done" << std::endl;
+
+ std::cerr << "compute gradient...";
+ cimg_library::CImgList grad = image.get_gradient();
+ cimg_library::CImg normgrad = sqrt(
+ grad[0].pow(2) + grad[1].pow(2)).normalize(0.0f, 1.0f);
+ std::cerr << "done" << std::endl;
+
+ // turn pixels into weighted samples
+ std::cerr << "add samples...";
+ for (int i = 0; i < normgrad.width(); i++) {
+ for (int j = 0; j < normgrad.height(); j++) {
+ float mass = normgrad.atXY(i, j);
+ double x = double(i) / normgrad.width();
+ double y = 1.0 - double(j) / normgrad.height();
+ add_sample(Point(x, y), mass);
+ }
+ }
+ std::cerr << "done (" << m_samples.size() << ")" << std::endl;
+ }
+#endif
+
+ void print_vertex(Vertex vertex) {
+ std::cout <<"vertex " << vertex << std::endl;
+ }
+
+
+ void print_edge(PEdge edge) {
+ int i = ((edge).edge()).second;
+ Point a = ((edge).edge()).first->vertex((i+1)%3)->point();
+ Point b = ((edge).edge()).first->vertex((i+2)%3)->point();
+ std::cout <<"( " << (edge).priority() << ") ( " << a
+ << " , " << b << " )" << std::endl;
+ }
+
+
+ void debug_print()
+ {
+ std::vector isolated_points;
+ std::vector edges;
+
+ m_pwsrec->list_output (std::back_inserter(isolated_points), std::back_inserter(edges));
+
+ int vertex_count = 0;
+ for (std::vector::iterator it = isolated_points.begin();
+ it != isolated_points.end(); it++) {
+ vertex_count++;
+ std::cout << *it << std::endl;
+ }
+ CGAL_assertion(vertex_count == 18);
+
+ int edge_count = 0;
+ for (std::vector::iterator it = edges.begin();
+ it != edges.end(); it++) {
+ std::cout << *it << std::endl;
+ edge_count++;
+ }
+ }
+
+ void save(const QString& filename)
+ {
+ std::cout << "SAVE-------------" << std::endl;
+ //debug_print();
+
+ /*if (filename.contains(".edges", Qt::CaseInsensitive)) {
+ std::ofstream ofs(qPrintable(filename));
+ m_pwsrec->save_edges(ofs, m_ignore);
+ ofs.close();
+ return;
+ }*/
+
+ Sample_vector samples;
+ for (std::vector::iterator it = m_samples.begin();
+ it != m_samples.end(); ++it) {
+ Sample_& s = *it;
+ if (s.mass() < m_min_mass)
+ continue;
+ samples.push_back(&s);
+ }
+
+ if (filename.contains(".xy", Qt::CaseInsensitive)) {
+ save_xy(filename, samples);
+ return;
+ }
+
+ std::cerr << "Error: not an XY file." << std::endl;
+
+ /*if (filename.contains(".poff", Qt::CaseInsensitive)) {
+ save_poff(filename, samples);
+ return;
+ }
+
+ if (filename.contains(".gtn", Qt::CaseInsensitive)) {
+ save_gtn(filename, samples);
+ return;
+ }
+
+ if (filename.contains(".pwn", Qt::CaseInsensitive)) {
+ save_pwn(filename, samples);
+ return;
+ }*/
+ }
+
+ void save_pwn(const QString& filename, const Sample_vector& samples) {
+ std::vector normals;
+ compute_normals(samples, normals);
+ std::ofstream ofs(qPrintable(filename));
+ std::vector::const_iterator ni = normals.begin();
+ for (Sample_vector_const_iterator it = samples.begin();
+ it != samples.end(); ++it) {
+ Sample_* sample = *it;
+ ofs << sample->point() << " " << *ni << std::endl;
+ ni++;
+ }
+ ofs.close();
+ }
+
+ void compute_normals(const Sample_vector& samples,
+ std::vector& normals) {
+ normals.clear();
+ Point last = samples.back()->point();
+ Sample_vector_const_iterator si = samples.begin();
+ while (si != samples.end()) {
+ Point p = (*si)->point();
+ si++;
+ Point next = samples.front()->point();
+ if (si != samples.end())
+ next = (*si)->point();
+
+ Vector ab = p - last;
+ Vector bc = next - p;
+ Vector ab90(ab.y(), -ab.x());
+ Vector bc90(bc.y(), -bc.x());
+
+ Vector ni = ab90 + bc90;
+ FT norm = std::sqrt(ni * ni);
+ if (norm != 0.0)
+ ni = ni / norm;
+ normals.push_back(ni);
+
+ last = p;
+ }
+ }
+
+ void save_xy(const QString& filename, const Sample_vector& samples) {
+ std::ofstream ofs(qPrintable(filename));
+ for (Sample_vector_const_iterator it = samples.begin();
+ it != samples.end(); ++it) {
+ Sample_* sample = *it;
+ ofs << sample->point() << std::endl;
+ }
+ ofs.close();
+ }
+
+ void save_poff(const QString& filename, const Sample_vector& samples) {
+ std::ofstream ofs(qPrintable(filename));
+ ofs << "POFF " << samples.size() << " 0 0" << std::endl;
+ for (Sample_vector_const_iterator it = samples.begin();
+ it != samples.end(); ++it) {
+ Sample_* sample = *it;
+ ofs << sample->point() << std::endl;
+ }
+ ofs.close();
+ }
+
+ void save_gtn(const QString& filename, const Sample_vector& samples) {
+ std::ofstream ofs(qPrintable(filename));
+ ofs << samples.size() << " 2 0 0" << std::endl;
+ unsigned int i = 0;
+ for (Sample_vector_const_iterator it = samples.begin();
+ it != samples.end(); ++it, ++i) {
+ Sample_* sample = *it;
+ ofs << i << " " << sample->point() << std::endl;
+ }
+ ofs.close();
+ }
+
+ // RECONSTRUCTION //
+
+ void set_options(const int verbose, const int mchoice,
+ const bool use_flip, const double alpha, const double norm_tol,
+ const double tang_tol, const unsigned int relocation,
+ const double ghost) {
+
+ m_pwsrec->set_verbose(verbose);
+ m_pwsrec->set_random_sample_size(mchoice);
+ m_pwsrec->set_use_flip(use_flip);
+ m_pwsrec->set_alpha(alpha);
+ m_pwsrec->set_tang_tol(tang_tol * m_bbox_size);
+ m_pwsrec->set_norm_tol(norm_tol * m_bbox_size);
+ m_pwsrec->set_relocation(relocation);
+ m_pwsrec->set_relevance(ghost);
+ }
+
+ bool init_reconstruction(const double percentage) {
+ std::cout << " init_reconstruction " << std::endl;
+
+ if (m_samples.empty()) {
+ std::cerr << "initialization failed (empty point set)" << std::endl;
+ return false;
+ }
+
+ Sample_vector vertices, samples;
+ select_samples(percentage, vertices, samples);
+
+ PointMassList point_mass_list;
+ Sample_vector_const_iterator it;
+ for (it = vertices.begin(); it != vertices.end(); it++) {
+ point_mass_list.push_back(
+ std::make_pair((*it)->point(), (*it)->mass()));
+ }
+
+ Point_property_map point_pmap;
+ Mass_property_map mass_pmap;
+ MassPoint mp;
+
+ m_pwsrec->initialize(point_mass_list.begin(), point_mass_list.end(),
+ point_pmap, mass_pmap);
+
+ m_init_done = true;
+
+ return true;
+ }
+
+ void decimate(const double percentage) {
+ std::cout << "Decimate from " << m_samples.size() << " to...";
+ std::vector selected;
+
+ std::vector::iterator it;
+ for (it = m_samples.begin(); it != m_samples.end(); it++) {
+ const double rd = random_double(0.0, 1.0);
+ if (rd >= percentage)
+ selected.push_back(*it);
+ }
+
+ m_samples.clear();
+ std::copy(selected.begin(), selected.end(),
+ std::back_inserter(m_samples));
+ std::cout << m_samples.size() << std::endl;
+ }
+
+ void keep_one_point_out_of(const int n) {
+ std::cout << "Decimate from " << m_samples.size() << " to...";
+ std::vector selected;
+
+ int index = 0;
+ std::vector::iterator it;
+ for (it = m_samples.begin(); it != m_samples.end(); it++, index++) {
+ if (index % n == 0)
+ selected.push_back(*it);
+ }
+
+ m_samples.clear();
+ std::copy(selected.begin(), selected.end(),
+ std::back_inserter(m_samples));
+ std::cout << m_samples.size() << std::endl;
+ }
+
+ void select_samples(const double percentage, Sample_vector& vertices,
+ Sample_vector& samples) {
+ std::vector::iterator it;
+ for (it = m_samples.begin(); it != m_samples.end(); ++it) {
+ Sample_& s = *it;
+ if (s.mass() <= m_min_mass)
+ continue;
+
+ samples.push_back(&s);
+ FT rv = random_double(0.0, 1.0);
+ if (rv <= percentage)
+ vertices.push_back(&s);
+ }
+ }
+
+ void reconstruct_until(const unsigned int nv) {
+ std::cout << "reconstruct_until" << std::endl;
+ if (!m_init_done)
+ init_reconstruction(m_percentage);
+ m_pwsrec->run_until(nv);
+ }
+
+ void reconstruct(const unsigned int steps) {
+ std::cout << "reconstruct" << std::endl;
+ if (!m_init_done)
+ init_reconstruction(m_percentage);
+ m_pwsrec->run(steps);
+ }
+
+ void relocate_all_points() {
+ std::cout << "relocate_all_points" << std::endl;
+ m_pwsrec->relocate_all_points();
+ }
+
+ // RENDER //
+
+ void render(const bool view_points, const bool view_vertices,
+ const bool view_edges, const bool view_ghost_edges,
+ const bool view_edge_cost, const bool view_edge_priority,
+ const bool view_bins, const bool view_foot_points,
+ const bool view_relocation, const bool view_tolerance,
+ const bool view_edge_relevance, const float point_size,
+ const float vertex_size, const float line_thickness)
+ {
+ if (m_pwsrec == NULL) {
+ return;
+ }
+
+ if (view_edges)
+ m_pwsrec->draw_edges(0.5f * line_thickness, 0.9f, 0.9f, 0.9f);
+
+ if (view_edge_cost)
+ m_pwsrec->draw_costs(line_thickness, view_ghost_edges);
+
+ if (view_edge_priority)
+ m_pwsrec->draw_pedges(line_thickness);
+
+ if (view_edge_relevance)
+ m_pwsrec->draw_relevance(line_thickness, m_ignore);
+
+ if (view_relocation)
+ m_pwsrec->draw_relocation();
+
+ if (view_vertices)
+ m_pwsrec->draw_vertices(vertex_size, 0.0f, 0.0f, 0.5f);
+
+ if (view_bins)
+ m_pwsrec->draw_bins(0.5f * line_thickness);
+
+ if (view_foot_points)
+ m_pwsrec->draw_footpoints(line_thickness, 0.2f, 0.8f, 0.2f);
+
+ if (view_tolerance)
+ draw_circles();
+
+ if (view_points)
+ draw_samples(point_size);
+ }
+
+ void draw_samples(const float point_size) {
+ double max_value = m_max_mass;
+ if (max_value == 0.0)
+ max_value = 1.0;
+
+ ::glPointSize(point_size);
+ ::glBegin(GL_POINTS);
+ std::vector::const_iterator it;
+ for (it = m_samples.begin(); it != m_samples.end(); it++) {
+ double mass = it->mass();
+ if (mass <= m_min_mass)
+ continue;
+
+ float value = mass / m_max_mass;
+ float grey = 0.9 * (1.0f - value);
+ ::glColor3f(grey, grey, grey);
+ const Point& p = it->point();
+ ::glVertex2d(p.x(), p.y());
+ }
+ ::glEnd();
+ }
+
+ void draw_circles() {
+ Sample_vector vertices, samples;
+ select_samples(1.0, vertices, samples);
+ double percentage = 500.0 / double(vertices.size());
+ percentage = (std::min)(percentage, 1.0);
+
+ samples.clear();
+ vertices.clear();
+ select_samples(percentage, vertices, samples);
+
+ ::glEnable(GL_BLEND);
+ ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ ::glColor4f(1.0f, 1.0f, 0.2f, 0.25f);
+ for (Sample_vector_const_iterator it = samples.begin();
+ it != samples.end(); it++) {
+ Sample_* sample = *it;
+ draw_one_circle(sample->point());
+ }
+ ::glDisable(GL_BLEND);
+ }
+
+ void draw_one_circle(const Point& center) {
+ unsigned int N = 10;
+ const double r = std::sqrt(m_pwsrec->norm_tol());
+ const double x = center.x();
+ const double y = center.y();
+ ::glBegin (GL_POLYGON);
+ for (unsigned int i = 0; i < N; ++i) {
+ double angle = 2.0 * M_PI * (double(i) / double(N));
+ double u = r * std::cos(angle) + x;
+ double v = r * std::sin(angle) + y;
+ ::glVertex2d(u, v);
+ }
+ ::glEnd();
+ }
+
+ // PREDEFINED EXAMPLES //
+
+ void make_line(const unsigned int nb, const Point& start,
+ const Point& end) {
+ Point curr = start;
+ Vector incr = (end - start) / nb;
+ for (unsigned int i = 0; i < nb; i++) {
+ add_sample(curr);
+ curr = curr + incr;
+ }
+ }
+
+ void make_circle_arc(const unsigned int nb, const Point& c,
+ const double radius, const double min_angle = 0.0,
+ const double max_angle = 360.0) {
+ const double range = max_angle - min_angle;
+ const double incr = range / double(nb);
+ for (double angle = min_angle; angle < max_angle; angle += incr) {
+ double angle_rad = (angle / 360.0) * 6.2831853;
+ double x = c.x() + radius * cos(angle_rad);
+ double y = c.y() + radius * sin(angle_rad);
+ Point point(x, y);
+ add_sample(point);
+ }
+ }
+
+ void append_widely_variable_sampling(const float d1, const float d2) {
+ double angle;
+ double incr = d1;
+ Point c = Point(0.5, 0.5);
+ const double radius = 0.5;
+ // 0-90 deg -> d1
+ for (angle = 0.0; angle < 90.0; angle += incr) {
+ double angle_rad = (angle / 360.0) * 6.2831853;
+ double x = c.x() + radius * cos(angle_rad);
+ double y = c.y() + radius * sin(angle_rad);
+ Point point(x, y);
+ add_sample(point);
+ }
+ // 90-180 deg -> d1 -> d2
+ for (angle = 90.0; angle < 180.0; angle += incr) {
+ double angle_rad = (angle / 360.0) * 6.2831853;
+ double x = c.x() + radius * cos(angle_rad);
+ double y = c.y() + radius * sin(angle_rad);
+ Point point(x, y);
+ add_sample(point);
+ incr = d1 + (d2 - d1) / 90.0 * (angle - 90);
+ }
+ // 180-270 deg -> d2
+ incr = d2;
+ for (angle = 180.0; angle < 270.0; angle += incr) {
+ double angle_rad = (angle / 360.0) * 6.2831853;
+ double x = c.x() + radius * cos(angle_rad);
+ double y = c.y() + radius * sin(angle_rad);
+ Point point(x, y);
+ add_sample(point);
+ }
+ // 270-360 deg -> d2 -> d1
+ incr = d2;
+ for (angle = 270.0; angle < 360.0; angle += incr) {
+ double angle_rad = (angle / 360.0) * 6.2831853;
+ double x = c.x() + radius * cos(angle_rad);
+ double y = c.y() + radius * sin(angle_rad);
+ Point point(x, y);
+ add_sample(point);
+ incr = d2 + (d1 - d2) / 90.0 * (angle - 270.0);
+ }
+ }
+
+ void append_predefined_line(const int density) {
+ std::cerr << "append line...";
+ Point start(0.0, 0.5);
+ Point end(1.0, 0.5);
+ make_line(density, start, end);
+ std::cerr << "done" << std::endl;
+ }
+
+ void append_predefined_parallel_lines(const int nb_lines, const float space,
+ const int density) {
+ std::cerr << "append parallel lines...";
+ FT x[4];
+ x[0] = 0.0;
+ x[1] = 0.75;
+ x[2] = 1.0;
+ x[3] = 1.75;
+ FT y = 0.0;
+ for (int i = 0; i < nb_lines; ++i) {
+ int j = i % 2;
+ Point start(x[j], y);
+ Point end(x[j + 2], y);
+ make_line(density, start, end);
+ y += space;
+ }
+ std::cerr << "done" << std::endl;
+ }
+
+ void append_predefined_circle(const int density, const float x,
+ const float y, const float radius) {
+ std::cerr << "append circle...";
+ Point center(x, y);
+ make_circle_arc(density, center, radius);
+ std::cerr << "done" << std::endl;
+ }
+
+ void append_predefined_spiral(const int nb_loops, const int density) {
+ std::cerr << "append spiral...";
+ Point center(0.5, 0.5);
+ const FT max_radius = 0.5;
+ const FT spacing = 10. / density; // target spacing
+ double radius = max_radius;
+ const double max_angle = nb_loops * 360.0;
+ for (double angle = max_angle; angle > 0.0; /**/) {
+ double angle_rad = (angle / 360.0) * 6.2831853;
+ double x = center.x() + radius * cos(angle_rad);
+ double y = center.y() + radius * sin(angle_rad);
+ Point point(x, y);
+ add_sample(point);
+
+ const double angle_incr = atan(spacing / radius);
+ angle -= angle_incr;
+ radius = max_radius * angle / max_angle;
+ }
+ std::cerr << "done" << std::endl;
+ }
+
+ void append_predefined_half_circle(const int density) {
+ std::cerr << "append half circle...";
+ Point center(0.5, 0.5);
+ make_circle_arc(density, center, 0.5, 0.0, 180.0);
+ std::cerr << "done" << std::endl;
+ }
+
+ void append_predefined_box(const int density, const float x, const float y,
+ const float size_x, const float size_y) {
+ std::cerr << "append box...";
+ Point a(x - size_x / 2, y - size_y / 2);
+ Point b(x + size_x / 2, y - size_y / 2);
+ Point c(x + size_x / 2, y + size_y / 2);
+ Point d(x - size_x / 2, y + size_y / 2);
+ make_line(density, a, b);
+ make_line(density, b, c);
+ make_line(density, c, d);
+ make_line(density, d, a);
+ std::cerr << "done" << std::endl;
+ }
+
+ void append_predefined_box_with_boundaries(const int density) {
+ std::cerr << "append box with boundaries...";
+
+ Point a(0.1, 0.1);
+ Point b(0.4, 0.1);
+ Point c(0.6, 0.1);
+ Point d(0.9, 0.1);
+ Point e(0.9, 0.4);
+ Point f(0.9, 0.6);
+ Point g(0.9, 0.9);
+ Point h(0.6, 0.9);
+ Point i(0.4, 0.9);
+ Point j(0.1, 0.9);
+ Point k(0.1, 0.6);
+ Point l(0.1, 0.4);
+
+ make_line(density, a, b);
+ make_line(density, c, d);
+ make_line(density, d, e);
+ make_line(density, f, g);
+ make_line(density, g, h);
+ make_line(density, i, j);
+ make_line(density, j, k);
+ make_line(density, l, a);
+
+ std::cerr << "done" << std::endl;
+ }
+
+ void append_predefined_box_with_missing_corners(const int density) {
+ std::cerr << "append box with missing corners...";
+ Point a(0.12, 0.1);
+ Point b(0.88, 0.1);
+ Point c(0.9, 0.12);
+ Point d(0.9, 0.88);
+ Point e(0.88, 0.9);
+ Point f(0.12, 0.9);
+ Point g(0.1, 0.88);
+ Point h(0.1, 0.12);
+ make_line(density, a, b);
+ make_line(density, c, d);
+ make_line(density, e, f);
+ make_line(density, g, h);
+ std::cerr << "done" << std::endl;
+ }
+
+ void append_predefined_boxes(const int density) {
+ std::cerr << "append two boxes...";
+ Point a(0.0, 0.0);
+ Point b(0.2, 0.0);
+ Point c(0.2, 1.0);
+ Point d(0.0, 1.0);
+ make_line(2 * density, a, b);
+ make_line(10 * density, b, c);
+ make_line(2 * density, c, d);
+ make_line(10 * density, d, a);
+
+ Point e(0.3, 0.0);
+ Point f(0.4, 0.0);
+ Point g(0.4, 0.3);
+ Point h(0.3, 0.3);
+ make_line(1 * density, e, f);
+ make_line(3 * density, f, g);
+ make_line(1 * density, g, h);
+ make_line(3 * density, h, e);
+ std::cerr << "done" << std::endl;
+ }
+
+ void append_predefined_stair(const int density) {
+ std::cerr << "append stair...";
+ Point a(0.0, 0.0);
+ Point b(0.1, 0.0);
+ Point c(0.1, 0.1);
+ Point d(0.2, 0.1);
+ Point e(0.2, 0.2);
+ Point f(0.3, 0.2);
+ Point g(0.3, 0.3);
+ Point h(0.4, 0.3);
+ Point i(0.4, 0.4);
+
+ make_line(density, a, b);
+ make_line(density, b, c);
+ make_line(density, c, d);
+ make_line(density, d, e);
+ make_line(density, e, f);
+ make_line(density, f, g);
+ make_line(density, g, h);
+ make_line(density, h, i);
+ std::cerr << "done" << std::endl;
+ }
+
+ void append_predefined_skyline(const int density) {
+ std::cerr << "append skyline...";
+ Point a(0.0, 0.0);
+ Point b(0.1, 0.0);
+ Point c(0.1, 0.5);
+ Point d(0.3, 0.5);
+ Point e(0.3, 0.2);
+ Point f(0.4, 0.2);
+ Point g(0.4, 0.4);
+ Point h(0.6, 0.4);
+ Point i(0.6, -0.1);
+ Point j(0.7, -0.1);
+ Point k(0.7, 0.2);
+ Point l(0.8, 0.2);
+ Point m(0.8, 0.7);
+ Point n(0.9, 0.7);
+ Point o(0.9, 0.5);
+ Point p(1.0, 0.5);
+ Point q(1.0, 0.1);
+ Point r(1.1, 0.1);
+ Point s(1.1, -0.1);
+ Point t(1.2, -0.1);
+
+ make_line(1 * density, a, b);
+ make_line(5 * density, b, c);
+ make_line(2 * density, c, d);
+ make_line(3 * density, d, e);
+ make_line(1 * density, e, f);
+ make_line(2 * density, f, g);
+ make_line(2 * density, g, h);
+ make_line(5 * density, h, i);
+ make_line(1 * density, i, j);
+ make_line(3 * density, j, k);
+ make_line(1 * density, k, l);
+ make_line(5 * density, l, m);
+ make_line(1 * density, m, n);
+ make_line(2 * density, n, o);
+ make_line(1 * density, o, p);
+ make_line(4 * density, p, q);
+ make_line(1 * density, q, r);
+ make_line(2 * density, r, s);
+ make_line(1 * density, s, t);
+ std::cerr << "done" << std::endl;
+ }
+
+ void append_star(const int nb_branches, const int density) {
+ std::cerr << "append star...";
+ const double deg_in_rad = 3.1415926535897932384626 / 180.0;
+ const double incr = 180.0 / nb_branches;
+ double angle = 0.0;
+ const Point center(0.5, 0.5);
+ for (int i = 0; i < nb_branches; i++) {
+ const double angle_rad = angle * deg_in_rad;
+ Vector v(sin(angle_rad), cos(angle_rad));
+ Point a = center + v;
+ Point b = center - v;
+ make_line(density, a, b);
+ angle += incr;
+ }
+ std::cerr << "done" << std::endl;
+ }
+
+ void append_predefined_increasingly_sharp_angles(const int density,
+ const double min_angle) {
+ const double deg_in_rad = 3.1415926535897932384626 / 180.0;
+ double prev_angle = 0.0;
+ double curr_angle = min_angle;
+ double incr = min_angle;
+ const double r1 = 0.5;
+ const Point center(0.5, 0.5);
+ while (curr_angle < 360.0) {
+ Vector va(r1 * cos(prev_angle * deg_in_rad),
+ r1 * sin(prev_angle * deg_in_rad));
+ Vector vb(r1 * cos(curr_angle * deg_in_rad),
+ r1 * sin(curr_angle * deg_in_rad));
+ const double average_angle = 0.5 * (prev_angle + curr_angle);
+ Vector vc(r1 * cos(average_angle * deg_in_rad),
+ r1 * sin(average_angle * deg_in_rad));
+ Point a = center + va;
+ Point b = center + vb;
+ Point c = center + 2 * vc;
+
+ make_line(density, a, c);
+ make_line(density, b, c);
+
+ prev_angle = curr_angle;
+ curr_angle += incr;
+ incr += 2.0;
+ }
+ noise(1e-5);
+ }
+};
+
+#endif // SCENE_H_
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/window.cpp b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/window.cpp
new file mode 100644
index 00000000000..33dd8ebd910
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/window.cpp
@@ -0,0 +1,682 @@
+// STL
+#include
+
+// Qt
+#include
+#include
+#include
+#include
+#include
+#include
+
+// local
+#include "window.h"
+#include "ui_options.h"
+#include "dialog_options.h"
+
+MainWindow::MainWindow() :
+QMainWindow(), Ui_MainWindow(),
+maxNumRecentFiles(15), recentFileActs(15)
+{
+ setupUi(this);
+
+ // init scene
+ m_scene = new Scene;
+ viewer->set_scene(m_scene);
+
+ // options
+ m_verbose = 0;
+ m_mchoice = 0;
+ m_ghost = 1.0;
+ m_alpha = 50.0;
+ m_use_flip = true;
+ m_percent = 100.0;
+ m_norm_tol = 100.0;
+ m_tang_tol = 100.0;
+ m_relocation = 0;
+
+ // accepts drop events
+ setAcceptDrops(true);
+
+ // Handling actions
+ addRecentFiles(menuFile, actionQuit);
+ connect(actionQuit, SIGNAL(triggered()), this, SLOT(close()));
+ connect(min_mass_slider, SIGNAL(valueChanged(int)), this, SLOT(update()));
+ connect(this, SIGNAL(openRecentFile(QString)), this, SLOT(open(QString)));
+}
+
+MainWindow::~MainWindow()
+{
+ delete m_scene;
+}
+
+void MainWindow::addToRecentFiles(QString fileName)
+{
+ QSettings settings;
+ QStringList files = settings.value("recentFileList").toStringList();
+ files.removeAll(fileName);
+ files.prepend(fileName);
+ while (files.size() > (int)maxNumRecentFiles)
+ files.removeLast();
+ settings.setValue("recentFileList", files);
+ updateRecentFileActions();
+}
+
+void MainWindow::dropEvent(QDropEvent *event)
+{
+ Q_FOREACH(QUrl url, event->mimeData()->urls())
+ {
+ QString filename = url.toLocalFile();
+ if (!filename.isEmpty())
+ {
+ QTextStream(stderr) << QString("dropEvent(\"%1\")\n").arg(filename);
+ open(filename);
+ }
+ }
+ event->acceptProposedAction();
+}
+
+void MainWindow::closeEvent(QCloseEvent *event)
+{
+ event->accept();
+}
+
+void MainWindow::dragEnterEvent(QDragEnterEvent *event)
+{
+ if (event->mimeData()->hasFormat("text/uri-list"))
+ event->acceptProposedAction();
+}
+
+void MainWindow::openRecentFile_aux()
+{
+ QAction* action = qobject_cast(sender());
+ if (action)
+ Q_EMIT openRecentFile(action->data().toString());
+}
+
+void MainWindow::updateRecentFileActions()
+{
+ QSettings settings;
+ QStringList files = settings.value("recentFileList").toStringList();
+
+ int numRecentFiles = qMin(files.size(), (int)maxNumberOfRecentFiles());
+ for (int i = 0; i < numRecentFiles; ++i) {
+ QString strippedName = QFileInfo(files[i]).fileName();
+ QString text = tr("&%1 %2").arg(i).arg(strippedName);
+ recentFileActs[i]->setText(text);
+ recentFileActs[i]->setData(files[i]);
+ recentFileActs[i]->setVisible(true);
+ }
+ for (unsigned int j = numRecentFiles; j < maxNumberOfRecentFiles(); ++j)
+ recentFileActs[j]->setVisible(false);
+
+ recentFilesSeparator->setVisible(numRecentFiles > 0);
+}
+
+void MainWindow::addRecentFiles(QMenu* menu, QAction* insertBeforeAction)
+{
+ if (insertBeforeAction)
+ recentFilesSeparator = menu->insertSeparator(insertBeforeAction);
+ else
+ recentFilesSeparator = menu->addSeparator();
+ recentFilesSeparator->setVisible(false);
+
+ for (unsigned int i = 0; i < maxNumberOfRecentFiles(); ++i) {
+ recentFileActs[i] = new QAction(this);
+ recentFileActs[i]->setVisible(false);
+ connect(recentFileActs[i], SIGNAL(triggered()), this, SLOT(openRecentFile_aux()));
+ if (insertBeforeAction)
+ menu->insertAction(insertBeforeAction, recentFileActs[i]);
+ else
+ menu->addAction(recentFileActs[i]);
+ }
+ updateRecentFileActions();
+}
+
+void MainWindow::open(const QString& filename)
+{
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ m_scene->load(filename, this);
+ QApplication::restoreOverrideCursor();
+ addToRecentFiles(filename);
+ update();
+}
+
+void MainWindow::save(const QString& filename)
+{
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ m_scene->save(filename);
+ QApplication::restoreOverrideCursor();
+ std::cout << "File " << filename.toStdString() << " saved" << std::endl;
+}
+
+void MainWindow::update()
+{
+ m_scene->set_min_mass(min_mass());
+ m_scene->set_percentage(percentage());
+ viewer->repaint();
+}
+
+void MainWindow::on_actionClear_triggered()
+{
+ m_scene->clear();
+ update();
+}
+
+void MainWindow::on_actionLoadPoints_triggered()
+{
+ QString fileName =
+ QFileDialog::getOpenFileName(this, tr("Open point set"), ".");
+ if (fileName.isEmpty()) return;
+ open(fileName);
+}
+
+void MainWindow::on_actionSave_triggered()
+{
+ QString filename =
+ QFileDialog::getSaveFileName(this, tr("Save point set"), ".", tr("*.xy"));
+ if (filename.isEmpty()) return;
+ save(filename);
+}
+
+void MainWindow::on_actionSnapshot_triggered()
+{
+ std::cout << "snapshot...";
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ QClipboard *qb = QApplication::clipboard();
+ viewer->makeCurrent();
+ viewer->raise();
+ QImage snapshot = viewer->grabFrameBuffer(true);
+ qb->setImage(snapshot);
+ QApplication::restoreOverrideCursor();
+ std::cout << "done" << std::endl;
+}
+
+void MainWindow::on_actionInsertPoint_toggled()
+{
+ viewer->toggle_insert_points();
+ update();
+}
+
+void MainWindow::on_actionRecenter_triggered()
+{
+ double center_x, center_y, scale;
+ m_scene->compute_bbox(center_x, center_y, scale);
+ viewer->set_camera(center_x, center_y, 1. / scale);
+ update();
+}
+
+void MainWindow::on_actionInvert_mass_triggered()
+{
+ m_scene->invert_mass();
+ update();
+}
+
+void MainWindow::on_actionClamp_mass_triggered()
+{
+ m_scene->clamp_mass();
+ update();
+}
+
+///////////////////////////
+// PREDEFINED POINT SETS //
+///////////////////////////
+
+void MainWindow::on_actionCircle_triggered()
+{
+ bool ok;
+ int density = QInputDialog::getInt(
+ this, tr("Density"), tr("Density:"), 300, 10, 10000, 1, &ok);
+ if (!ok) return;
+
+ float x = QInputDialog::getDouble(
+ this, tr("Center x"), tr("Center x:"), 0.0, 0.0, 10, 1, &ok);
+ if (!ok) return;
+
+ float y = QInputDialog::getDouble(
+ this, tr("Center y"), tr("Center y:"), 0.0, 0.0, 10, 1, &ok);
+ if (!ok) return;
+
+ float radius = QInputDialog::getDouble(
+ this, tr("Radius"), tr("Radius:"), 0.5, 0.1, 10, 1, &ok);
+ if (!ok) return;
+
+ m_scene->append_predefined_circle(density, x, y, radius);
+ update();
+}
+
+void MainWindow::on_actionHalf_circle_triggered()
+{
+ bool ok;
+ unsigned int density = QInputDialog::getInt(
+ this, tr("Density"), tr("Density:"), 150, 10, 10000, 1, &ok);
+ if (!ok) return;
+
+ m_scene->append_predefined_half_circle(density);
+ update();
+}
+
+void MainWindow::on_actionSpiral_triggered()
+{
+ bool ok;
+
+ int loops = QInputDialog::getInt(
+ this, tr("Loops"), tr("Number:"), 3, 1, 10000, 1, &ok);
+ if (!ok) return;
+
+ int density = QInputDialog::getInt(
+ this, tr("Density"), tr("Density:"), 10, 1, 10000, 1, &ok);
+ if (!ok) return;
+
+ m_scene->append_predefined_spiral(loops,density);
+ update();
+}
+
+
+void MainWindow::on_actionLine_triggered()
+{
+ bool ok;
+ unsigned int density = QInputDialog::getInt(
+ this, tr("Density"), tr("Density:"), 50, 1, 10000, 1, &ok);
+ if (!ok) return;
+
+ m_scene->append_predefined_line(density);
+ update();
+}
+
+void MainWindow::on_actionBox_triggered()
+{
+ bool ok;
+ int density = QInputDialog::getInt(
+ this, tr("Density"), tr("Density:"), 100, 1, 10000, 1, &ok);
+ if (!ok) return;
+
+ float x = QInputDialog::getDouble(
+ this, tr("x"), tr("x:"), 0.0, 0.0, 10.0, 1, &ok);
+ if (!ok) return;
+
+ float y = QInputDialog::getDouble(
+ this, tr("y"), tr("y:"), 0.0, 0.0, 10.0, 1, &ok);
+ if (!ok) return;
+
+ float sx = QInputDialog::getDouble(
+ this, tr("size x"), tr("size x:"), 1.0, 0.1, 10.0, 1, &ok);
+ if (!ok) return;
+
+ float sy = QInputDialog::getDouble(
+ this, tr("size y"), tr("size y:"), 1.0, 0.1, 10.0, 1, &ok);
+ if (!ok) return;
+
+ m_scene->append_predefined_box(density, x, y, sx, sy);
+ update();
+}
+
+void MainWindow::on_actionBoxes_triggered()
+{
+ bool ok;
+ unsigned int density = QInputDialog::getInt(
+ this, tr("Density"), tr("Density:"), 10, 1, 10000, 1, &ok);
+ if (!ok) return;
+
+ m_scene->append_predefined_boxes(density);
+ update();
+}
+
+void MainWindow::on_actionParallel_lines_triggered()
+{
+ bool ok;
+
+ int lines = QInputDialog::getInt(
+ this, tr("Lines"), tr("Number:"), 3, 1, 10000, 1, &ok);
+ if(!ok) return;
+
+ float space = QInputDialog::getDouble(
+ this, tr("Space"), tr("Space:"), 0.2, 0.1, 10, 1, &ok);
+ if (!ok) return;
+
+ int density = QInputDialog::getInt(
+ this, tr("Density"), tr("Density:"), 10, 1, 10000, 1, &ok);
+ if(!ok) return;
+
+ m_scene->append_predefined_parallel_lines(lines, space, density);
+ update();
+}
+
+void MainWindow::on_actionBox_with_boundaries_triggered()
+{
+ bool ok;
+ unsigned int density = QInputDialog::getInt(
+ this, tr("Density"), tr("Density:"), 10, 1, 10000, 1, &ok);
+ if (!ok) return;
+
+ m_scene->append_predefined_box_with_boundaries(density);
+ update();
+}
+
+void MainWindow::on_actionBox_with_missing_corners_triggered()
+{
+ bool ok;
+ unsigned int density = QInputDialog::getInt(
+ this, tr("Density"), tr("Density:"), 10, 1, 10000, 1, &ok);
+ if (!ok) return;
+
+ m_scene->append_predefined_box_with_missing_corners(density);
+ update();
+}
+
+void MainWindow::on_actionStar_triggered()
+{
+ bool ok;
+ int nb_branches = QInputDialog::getInt(
+ this, tr("Branches"), tr("Branches:"), 20, 2, 10000, 1, &ok);
+ if(!ok) return;
+
+ int density = QInputDialog::getInt(
+ this, tr("Density"), tr("Density:"), 100, 10, 10000, 1, &ok);
+ if(!ok) return;
+
+ m_scene->append_star(nb_branches,density);
+ update();
+}
+
+
+void MainWindow::on_actionStair_triggered()
+{
+ bool ok;
+ unsigned int density = QInputDialog::getInt(
+ this, tr("Density"), tr("Density:"), 30, 2, 10000, 1, &ok);
+ if (!ok) return;
+
+ m_scene->append_predefined_stair(density);
+ on_actionRecenter_triggered();
+ update();
+}
+
+void MainWindow::on_actionSkyline_triggered()
+{
+ bool ok;
+ unsigned int density = QInputDialog::getInt(
+ this, tr("Density"), tr("Density:"), 10, 1, 10000, 1, &ok);
+ if (!ok) return;
+
+ m_scene->append_predefined_skyline(density);
+ on_actionRecenter_triggered();
+ update();
+}
+
+void MainWindow::on_actionIncreasingly_sharp_angles_triggered()
+{
+ bool ok;
+ unsigned int density = QInputDialog::getInt(
+ this, tr("Density"), tr("Density:"), 100, 1, 10000, 1, &ok);
+ if (!ok) return;
+
+ double min_angle = QInputDialog::getDouble(
+ this, tr("Min Angle"), tr("Min Angle:"), 1.0, 1.0, 360.0, 1.0, &ok);
+ if (!ok) return;
+
+ m_scene->append_predefined_increasingly_sharp_angles(density, min_angle);
+ on_actionRecenter_triggered();
+ update();
+}
+
+void MainWindow::on_actionWidely_variable_sampling_triggered()
+{
+ bool ok;
+ float d1 = QInputDialog::getDouble(
+ this, tr("Delta-angle"), tr("Delta-angle:"), 1, 0.01, 20.0, 2, &ok);
+ if (!ok) return;
+
+ float d2 = QInputDialog::getDouble(
+ this, tr("Delta-angle"), tr("Delta-angle:"), 10, 0.01, 30.0, 2, &ok);
+ if (!ok) return;
+
+ m_scene->append_widely_variable_sampling(d1, d2);
+ update();
+}
+
+void MainWindow::on_actionNoise_triggered()
+{
+ bool ok;
+ double noise = QInputDialog::getDouble(
+ this, tr("Noise"), tr("Amount:"), 0.003, 0.0, 1000.0, 8, &ok);
+ if (!ok) return;
+
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ m_scene->noise(noise);
+ QApplication::restoreOverrideCursor();
+ update();
+}
+
+void MainWindow::on_actionAdd_outliers_triggered()
+{
+ bool ok;
+ unsigned int nb = (unsigned)
+ QInputDialog::getInt(
+ this, tr("Outliers"), tr("How many:"), 10, 1, 100000, 1, &ok);
+ if (!ok) return;
+
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ m_scene->add_outliers(nb);
+ QApplication::restoreOverrideCursor();
+ update();
+}
+
+void MainWindow::on_actionSubdivide_triggered()
+{
+ m_scene->subdivide();
+ update();
+}
+
+void MainWindow::on_actionDecimate_triggered()
+{
+ bool ok;
+ int percent = QInputDialog::getInt(
+ this, tr("Decimate"), tr("Percentage:"), 50, 1, 100, 1, &ok);
+ if (!ok) return;
+
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ const double percentage = double(percent) / 100.0;
+ m_scene->decimate(percentage);
+ QApplication::restoreOverrideCursor();
+ update();
+}
+
+void MainWindow::on_actionKeep_one_point_out_of_n_triggered()
+{
+ bool ok;
+ int n = QInputDialog::getInt(
+ this, tr("Keep one point out of"), tr("n:"), 2, 2, 1000, 1, &ok);
+ if (!ok) return;
+
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ m_scene->keep_one_point_out_of(n);
+ QApplication::restoreOverrideCursor();
+ update();
+}
+
+////////////////////
+// RECONSTRUCTION //
+////////////////////
+
+void MainWindow::set_scene_options()
+{
+ m_scene->set_options(m_verbose, m_mchoice, m_use_flip,
+ alpha(), norm_tol(), tang_tol(),
+ m_relocation, m_ghost);
+}
+
+void MainWindow::on_actionReconstruction_reinit_triggered()
+{
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ set_scene_options();
+ m_scene->init_reconstruction(percentage());
+ QApplication::restoreOverrideCursor();
+ update();
+}
+
+void MainWindow::on_actionReconstruction_one_step_triggered()
+{
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ set_scene_options();
+ m_scene->reconstruct(1);
+ QApplication::restoreOverrideCursor();
+ update();
+}
+
+void MainWindow::on_actionReconstruction_10_steps_triggered()
+{
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ set_scene_options();
+ m_scene->reconstruct(10);
+ QApplication::restoreOverrideCursor();
+ update();
+}
+
+void MainWindow::on_actionReconstruction_100_steps_triggered()
+{
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ set_scene_options();
+ m_scene->reconstruct(100);
+ QApplication::restoreOverrideCursor();
+ update();
+}
+
+void MainWindow::on_actionReconstruction_1000_steps_triggered()
+{
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ set_scene_options();
+ m_scene->reconstruct(1000);
+ QApplication::restoreOverrideCursor();
+ update();
+}
+
+void MainWindow::on_actionReconstruction_until_triggered()
+{
+ bool ok;
+ int nb_points = QInputDialog::getInt(
+ this, tr("Number of Points"), tr("Nb:"), 4, 1, 1000000, 1, &ok);
+ if (!ok) return;
+
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ set_scene_options();
+ m_scene->reconstruct_until(nb_points);
+ QApplication::restoreOverrideCursor();
+ update();
+}
+
+void MainWindow::on_actionRelocate_vertices_triggered()
+{
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ m_scene->relocate_all_points();
+ QApplication::restoreOverrideCursor();
+ update();
+}
+
+//////////
+// VIEW //
+//////////
+
+void MainWindow::on_actionView_points_toggled()
+{
+ viewer->toggle_view_points();
+ update();
+}
+
+void MainWindow::on_actionView_vertices_toggled()
+{
+ viewer->toggle_view_vertices();
+ update();
+}
+
+void MainWindow::on_actionView_edges_toggled()
+{
+ viewer->toggle_view_edges();
+ update();
+}
+
+void MainWindow::on_actionView_ghost_toggled()
+{
+ viewer->toggle_view_ghost_edges();
+ update();
+}
+
+void MainWindow::on_actionView_edge_cost_toggled()
+{
+ viewer->toggle_view_edge_cost();
+ update();
+}
+
+void MainWindow::on_actionView_edge_priority_toggled()
+{
+ viewer->toggle_view_edge_priority();
+ update();
+}
+
+void MainWindow::on_actionView_bins_toggled()
+{
+ viewer->toggle_view_bins();
+ update();
+}
+
+void MainWindow::on_actionView_foot_points_toggled()
+{
+ viewer->toggle_view_foot_points();
+ update();
+}
+
+void MainWindow::on_actionView_relocation_toggled()
+{
+ viewer->toggle_view_relocation();
+ update();
+}
+
+void MainWindow::on_actionView_tolerance_toggled()
+{
+ viewer->toggle_view_tolerance();
+ update();
+}
+
+void MainWindow::on_actionView_relevance_toggled()
+{
+ viewer->toggle_view_edge_relevance();
+ update();
+}
+
+void MainWindow::on_actionSet_options_triggered()
+{
+ Dialog_options dlg;
+ dlg.set_all_ranges();
+ dlg.set_verbose(m_verbose);
+ dlg.set_random_sample_size(m_mchoice);
+ dlg.set_percent(m_percent);
+ dlg.set_norm_tol(m_norm_tol);
+ dlg.set_tang_tol(m_tang_tol);
+ dlg.set_alpha(m_alpha);
+ dlg.set_relocation(m_relocation);
+ dlg.set_relevance(m_ghost);
+ dlg.set_use_flip(m_use_flip);
+ dlg.set_multiple_choice_checkbox(m_mchoice != 0);
+ dlg.set_line_thickness(viewer->line_thickness());
+ dlg.set_point_size(viewer->point_size());
+ dlg.set_vertex_size(viewer->vertex_size());
+
+ if (dlg.exec() == QDialog::Accepted)
+ {
+ m_verbose = dlg.get_verbose();
+ m_mchoice = dlg.get_mchoice();
+ m_percent = dlg.get_percent();
+ m_norm_tol = dlg.get_norm_tol();
+ m_tang_tol = dlg.get_tang_tol();
+ m_alpha = dlg.get_alpha();
+ m_relocation = dlg.get_relocation();
+ m_ghost = dlg.get_ghost();
+ m_use_flip = dlg.get_use_flip();
+
+ set_scene_options();
+ viewer->line_thickness() = dlg.get_line_thickness();
+ viewer->point_size() = dlg.get_point_size();
+ viewer->vertex_size() = dlg.get_vertex_size();
+ update();
+ }
+}
diff --git a/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/window.h b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/window.h
new file mode 100644
index 00000000000..40dc43976cf
--- /dev/null
+++ b/Reconstruction_simplification_2/demo/Reconstruction_simplification_2/window.h
@@ -0,0 +1,139 @@
+#ifndef WINDOW_
+#define WINDOW_
+
+// SLT
+#include
+
+// Qt
+#include
+#include
+
+// local
+#include "scene.h"
+#include "ui_pwsrec.h"
+
+class MainWindow : public QMainWindow, public Ui_MainWindow
+{
+ Q_OBJECT
+
+private:
+ Scene* m_scene;
+
+ // main options
+ int m_verbose;
+ int m_mchoice;
+ bool m_use_flip;
+ double m_alpha;
+ double m_ghost;
+ double m_percent;
+ double m_norm_tol;
+ double m_tang_tol;
+ double m_relocation;
+
+ unsigned int maxNumRecentFiles;
+ QAction* recentFilesSeparator;
+ QVector recentFileActs;
+
+public:
+ MainWindow();
+ ~MainWindow();
+
+ // Parameters
+ void set_scene_options();
+
+ double percentage() const { return m_percent / 100.0; }
+
+ double norm_tol() const { return m_norm_tol / 100.0; }
+
+ double tang_tol() const { return m_tang_tol / 100.0; }
+
+ double alpha() const { return m_alpha / 100.0; }
+
+ double min_mass() const
+ {
+ double value = double(min_mass_slider->value());
+ double max_value = double(min_mass_slider->maximum());
+ return value / max_value;
+ }
+
+ protected Q_SLOTS:
+ // drag and drop
+ void dropEvent(QDropEvent *event);
+ void closeEvent(QCloseEvent *event);
+ void dragEnterEvent(QDragEnterEvent *event);
+
+ // recent files
+ void openRecentFile_aux();
+ void updateRecentFileActions();
+ void addToRecentFiles(QString fileName);
+ void addRecentFiles(QMenu* menu, QAction* insertBefore = 0);
+ unsigned int maxNumberOfRecentFiles() const {return maxNumRecentFiles;}
+
+ // io
+ void open(const QString& file);
+ void save(const QString& file);
+
+ public Q_SLOTS:
+ // render
+ void update();
+ void on_actionRecenter_triggered();
+
+ // io
+ void on_actionClear_triggered();
+ void on_actionLoadPoints_triggered();
+ void on_actionSave_triggered();
+ void on_actionInsertPoint_toggled();
+ void on_actionSnapshot_triggered();
+ void on_actionInvert_mass_triggered();
+ void on_actionClamp_mass_triggered();
+ void on_actionSubdivide_triggered();
+ void on_actionDecimate_triggered();
+ void on_actionKeep_one_point_out_of_n_triggered();
+
+ // data
+ void on_actionStar_triggered();
+ void on_actionBox_triggered();
+ void on_actionLine_triggered();
+ void on_actionStair_triggered();
+ void on_actionBoxes_triggered();
+ void on_actionNoise_triggered();
+ void on_actionSpiral_triggered();
+ void on_actionCircle_triggered();
+ void on_actionSkyline_triggered();
+ void on_actionHalf_circle_triggered();
+ void on_actionAdd_outliers_triggered();
+ void on_actionParallel_lines_triggered();
+ void on_actionBox_with_boundaries_triggered();
+ void on_actionBox_with_missing_corners_triggered();
+ void on_actionIncreasingly_sharp_angles_triggered();
+ void on_actionWidely_variable_sampling_triggered();
+
+ // reconstruction
+ void on_actionSet_options_triggered();
+ void on_actionReconstruction_one_step_triggered();
+ void on_actionReconstruction_10_steps_triggered();
+ void on_actionReconstruction_100_steps_triggered();
+ void on_actionReconstruction_1000_steps_triggered();
+ void on_actionReconstruction_until_triggered();
+ void on_actionRelocate_vertices_triggered();
+ void on_actionReconstruction_reinit_triggered();
+
+ // view
+ void on_actionView_points_toggled();
+ void on_actionView_vertices_toggled();
+ void on_actionView_edges_toggled();
+ void on_actionView_ghost_toggled();
+ void on_actionView_edge_cost_toggled();
+ void on_actionView_edge_priority_toggled();
+ void on_actionView_relevance_toggled();
+
+ void on_actionView_bins_toggled();
+ void on_actionView_foot_points_toggled();
+ void on_actionView_relocation_toggled();
+ void on_actionView_tolerance_toggled();
+
+ Q_SIGNALS:
+ void openRecentFile(QString filename);
+};
+
+#endif // WINDOW_
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/Concepts/ReconstructionSimplificationTraits_2.h b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/Concepts/ReconstructionSimplificationTraits_2.h
new file mode 100644
index 00000000000..c79d102d2c1
--- /dev/null
+++ b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/Concepts/ReconstructionSimplificationTraits_2.h
@@ -0,0 +1,166 @@
+
+/*!
+\ingroup PkgReconstructionSimplification2Concepts
+\cgalConcept
+
+The concept `ReconstructionSimplificationTraits_2` describes the requirements
+for the traits class of `CGAL::Reconstruction_simplification_2`.
+
+\cgalRefines `DelaunayTriangulationTraits_2`
+
+\cgalHasModel Any model of the `Kernel` concept
+\cgalHasModel `CGAL::Exact_predicates_inexact_constructions_kernel` (recommended)
+
+\sa `CGAL::Reconstruction_simplification_2`
+
+*/
+
+class ReconstructionSimplificationTraits_2 {
+public:
+
+ /// \name Types
+ /// @{
+
+ /*!
+ A coordinate type.
+ The type must provide a copy constructor, assignment, comparison
+ operators, negation, multiplication, division and allow the
+ declaration and initialization with a small integer and double constant
+ (cf. requirements for number types).
+ An obvious choice would be coordinate type of the point class.
+ */
+ typedef unspecified_type FT;
+
+ /*!
+ The vector type.
+ */
+ typedef unspecified_type Vector_2;
+
+ /*!
+ A function object to construct a `Point_2`.
+
+ Must provides:
+ `Point_2 operator()(FT x, FT y)`,
+ which constructs a 2D point from its coordinates.
+ */
+ typedef unspecified_type Construct_point_2;
+
+ /*!
+ A function object to construct a `Vector_2`.
+
+ Must provides:
+ `Vector_2 operator()(FT x, FT y)`,
+ which constructs a 2D vector from its coordinates,
+ and `Vector_2 operator()(Point p0, Point p1)`,
+ which constructs a 2D vector from 2 points.
+ */
+ typedef unspecified_type Construct_vector_2;
+
+ /*!
+ A function object to construct a `Line_2`.
+
+ Must provides:
+ `Line_2 operator()(Point p, Vector v)`,
+ which constructs a 2D line from a point and a vector.
+ */
+ typedef unspecified_type Construct_line_2;
+
+ /*!
+ Must provides:
+ `Point_2 operator()(Point_2 p, Vector_2 v)`
+ that computes the point `p + v`.
+ */
+ typedef unspecified_type Construct_translated_point_2;
+
+ /*!
+ Must provides:
+ `Vector_2 operator()(Vector_2 v, FT c)`
+ that computes the vector `c * v`.
+ */
+ typedef unspecified_type Construct_scaled_vector_2;
+
+ /*!
+ Must provides:
+ `Vector_2 operator()(Vector_2 v1, Vector_2 v2)`
+ that computes the vector `v1 + v2`.
+ */
+ typedef unspecified_type Construct_sum_of_vectors_2;
+
+ /*!
+ Must provides:
+ `Point_2 operator()(Line_2 l, Point_2 p)`
+ that computes the projection of the point `p` on the line `l`.
+ */
+ typedef unspecified_type Construct_projected_point_2;
+
+ /*!
+ Must provides:
+ `bool operator()(Line_2 l, Point_2 p)`
+ that returns `true` iff `p` lies on `l`.
+ */
+ typedef unspecified_type Has_on_2;
+
+ /*!
+ Must provides:
+ `FT operator()(Vector_2 v1, Vector_2 v2)`
+ that computes the scalar product between `v1` and `v2`.
+ */
+ typedef unspecified_type Compute_scalar_product_2;
+
+ /*!
+ Must provides:
+ `FT operator()(Vector_2 v)`
+ that computes the squared length of `v`.
+ */
+ typedef unspecified_type Compute_squared_length_2;
+
+ /*!
+ Must provides:
+ `FT operator()(Point p1, Point p2)`
+ that computes the squared distance between `p1` and `p2`.
+ */
+ typedef unspecified_type Compute_squared_distance_2;
+
+ /// @}
+
+ /// \name Creation
+ /// @{
+
+ /*!
+ %Default constructor.
+ */
+ ReconstructionSimplificationTraits_2();
+
+ /*!
+ Copy constructor.
+ */
+ ReconstructionSimplificationTraits_2 (
+ const ReconstructionSimplificationTraits_2& );
+
+ /*!
+ Assignment operator.
+ */
+ ReconstructionSimplificationTraits_2& operator=
+ (const ReconstructionSimplificationTraits_2& );
+
+ /// @}
+
+ /// \name Access to Predicate and Constructors Objects
+ /// @{
+ Construct_point_2 construct_point_2_object();
+ Construct_vector_2 construct_vector_2_object();
+ Construct_vector_2 construct_vector_2_object();
+ Construct_line_2 construct_line_2_object();
+ Construct_translated_point_2 construct_translated_point_2_object();
+ Construct_scaled_vector_2 construct_scaled_vector_2_object();
+ Construct_sum_of_vectors_2 construct_sum_of_vectors_2_object();
+ Construct_projected_point_2 construct_projected_point_2_object();
+ Has_on_2 has_on_2_object();
+ Compute_scalar_product_2 compute_scalar_product_2_object();
+ Compute_squared_length_2 compute_squared_length_2_object();
+ Compute_squared_distance_2 compute_squared_distance_2_object();
+
+ /// @}
+
+}; /* end ReconstructionSimplificationTraits_2 */
+
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/Doxyfile.in b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/Doxyfile.in
new file mode 100644
index 00000000000..f4a99f5c506
--- /dev/null
+++ b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/Doxyfile.in
@@ -0,0 +1,9 @@
+@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS}
+
+PROJECT_NAME = "CGAL ${CGAL_CREATED_VERSION_NUM} - 2D Reconstruction and Simplification from Point Set"
+
+INPUT = ${CMAKE_SOURCE_DIR}/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/ \
+ ${CMAKE_SOURCE_DIR}/Reconstruction_simplification_2/include
+EXTRACT_ALL = false
+HIDE_UNDOC_CLASSES = true
+WARN_IF_UNDOCUMENTED = false
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/PackageDescription.txt b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/PackageDescription.txt
new file mode 100644
index 00000000000..47c936f2ed3
--- /dev/null
+++ b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/PackageDescription.txt
@@ -0,0 +1,37 @@
+/// \defgroup PkgReconstructionSimplification2 2D Reconstruction Simplification Reference
+
+/// \defgroup PkgReconstructionSimplification2Concepts Concepts
+/// \ingroup PkgReconstructionSimplification2
+
+/// \defgroup PkgReconstructionSimplification2Classes Classes
+/// \ingroup PkgReconstructionSimplification2
+
+
+/*!
+\addtogroup PkgReconstructionSimplification2
+\cgalPkgDescriptionBegin{2D Reconstruction Simplification, PkgReconstructionSimplification2Summary}
+\cgalPkgPicture{overview.png}
+\cgalPkgSummaryBegin
+\cgalPkgAuthor{Pierre Alliez, Fernando de Goes, Clement Jamin, Ivo Vigan}
+\cgalPkgDesc{This package provides an algorithm to reconstruct and simplify a shape from a point set in the plane, possibly hampered with noise and outliers. It generates as output a set of line segments and isolated points, which approximate the input point set.}
+\cgalPkgManuals{Chapter_2D_Reconstruction_Simplification, PkgReconstructionSimplification2}
+\cgalPkgSummaryEnd
+\cgalPkgShortInfoBegin
+\cgalPkgSince{4.x}
+\cgalPkgDependsOn{\ref PkgTriangulation2Summary}
+\cgalPkgBib{cgal:gavj-rs}
+\cgalPkgLicense{\ref licensesGPL "GPL"}
+\cgalPkgShortInfoEnd
+\cgalPkgDescriptionEnd
+
+
+\cgalClassifedRefPages
+
+## Concepts ##
+- `ReconstructionSimplificationTraits_2`
+
+## Classes ##
+- `CGAL::Reconstruction_simplification_2`
+
+*/
+
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/Reconstruction_Simplification_2.txt b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/Reconstruction_Simplification_2.txt
new file mode 100644
index 00000000000..14b7663e8c3
--- /dev/null
+++ b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/Reconstruction_Simplification_2.txt
@@ -0,0 +1,206 @@
+namespace CGAL {
+/*!
+
+\mainpage User Manual
+\anchor Chapter_2D_Reconstruction_Simplification
+\cgalAutoToc
+
+\authors Pierre Alliez, Fernando de Goes, Clement Jamin and Ivo Vigan
+
+\section Reconstruction_simplification_2Introduction Introduction
+
+This package implements a method to reconstruct and simplify 2D point sets \cgalCite{degoes:hal-00758019}. The input is a set of 2D points with mass attributes, possibly hampered by noise and outliers. The output is a set of line segments and isolated points which approximate the input points, as illustrated in \cgalFigureRef{2D_Reconstruction_Simplification_summary}. The mass attribute relates to the importance given to each point for approximation.
+
+\cgalFigureBegin{2D_Reconstruction_Simplification_summary,summary.png}
+Left: input point set hampered by noise. Right: The corresponding reconstructed shape consisting of line segments.
+\cgalFigureEnd
+
+Internally, the algorithm constructs an initial 2D Delaunay triangulation from all the input points, then simplifies the triangulation so that a subset of the edges and vertices of the triangulation approximate well the input points. Approximate herein refers to a robust distance based on optimal transportation (see section \ref Reconstruction_simplification_2HowDoesItWork for more details). The triangulation is simplified using a combination of half edge collapse, edge flips and vertex relocation operators. The triangulation remains valid during simplification, i.e., with neither overlaps nor fold-overs.
+
+The output of the reconstruction algorithm is a subset of edges and vertices of the triangulation. \cgalFigureRef{2D_Reconstruction_Simplification_algorithm} depicts an example where the output is composed of green edges and one isolated vertex. The green edges are considered relevant as they approximate well many of the input points. The edges depicted in grey, referred to as ghost edges and discarded, approximate none of the input points. The edges depicted in red, referred to as irrelevant and also discarded, approximate some of the input points but not enough to be considered relevant.
+
+\cgalFigureBegin{2D_Reconstruction_Simplification_algorithm,algorithm.png}
+(a) Input points. (b) Delaunay triangulation of the input points. (c) After simplification, with ghost edges in grey, relevant edges in green, and irrelevant edges in red. (d) Final reconstruction made up of several edges and one isolated vertex.
+\cgalFigureEnd
+
+
+\subsection Reconstruction_simplification_2Simplest_example Simplest Example
+The following example first generates a set of input points on a square. The points, with no mass attribute, are then passed to the Reconstruction_simplification_2 object. After initialization, 100 iterations of the reconstruction process are performed.
+\cgalExample{Reconstruction_simplification_2/rs2_simplest_example.cpp}
+
+\subsection Reconstruction_simplification_2Output_example Output Examples
+The output of the reconstruction can be obtained in two ways: either as a sequence of 2D points and segments, or as an indexed format where the connectivity of the segments is encoded, hence the terms vertices and edges. The indexed format records a list of points, then pairs of point indices in the said list for the edges, and point indices for the isolated vertices.
+\cgalExample{Reconstruction_simplification_2/rs2_list_output_example.cpp}
+\cgalExample{Reconstruction_simplification_2/rs2_indexed_output_example.cpp}
+
+\subsection Reconstruction_simplification_2Mass_example Example with Mass Attributes
+The following example first reads a set of input points and masses from an ASCII file. Using two property maps, the points and their initial mass are passed to the Reconstruction_simplification_2 object. After initialization 100 iterations of the reconstruction process are performed, then the segments and isolated points of the reconstructed shape are extracted and printed to the console.
+\cgalExample{Reconstruction_simplification_2/rs2_mass_example.cpp}
+
+
+\section Reconstruction_simplification_2API API
+
+The only class exposed to the user is the Reconstruction_simplification_2 class.
+
+\subsection Reconstruction_simplification_2Sample Sample Call
+
+\code{.cpp}
+/*
+K : a geometric kernel.
+*/
+
+Reconstruction_simplification_2
+ rs2(points.begin(), points.end());
+
+rs2.run(100); // perform 100 edge collapse operators
+\endcode
+
+In case the input is not just points without masses, one can provide
+a property map that matches this input.
+\code{.cpp}
+/*
+K : a geometric kernel.
+Point_property_map : a PropertyMap for accessing the input points.
+Mass_property_map : a PropertyMap for accessing the mass attributes of the
+ input points.
+*/
+
+Reconstruction_simplification_2
+ rs2(points.begin(), points.end(), point_pmap, mass_pmap);
+
+rs2.run(100); // perform 100 edge collapse operators
+\endcode
+
+Alternatively to calling \link Reconstruction_simplification_2::run `run()`\endlink,
+one can call \link Reconstruction_simplification_2::run_until `run_until()` \endlink
+and specify the number of output vertices one wants to keep as illustrated in
+ \cgalFigureRef{2D_Reconstruction_Simplification_twenty_vertices}.
+\code{.cpp}
+ rs2.run_until(20); // perform edge collapse operators until 20 vertices remain.
+\endcode
+
+\cgalFigureBegin{2D_Reconstruction_Simplification_twenty_vertices,twenty_vertices.png}
+Examples of 20-vertex reconstructions from datasets consisting of 2000, 400
+and 200 input points respectively. These examples illustrate the behavior of
+the algorithm when the input point density decreases.
+\cgalFigureEnd
+
+
+\subsection Reconstruction_simplification_2Global_relocation Global Point Relocation
+
+As noise and missing data may prevent the reconstructed shape to have sharp
+corners at the correct places, the algorithm offers a function to relocate
+all points of the reconstruction:
+\code{.cpp}
+ rs2.relocate_all_points();
+\endcode
+Note that these points coincide with the vertices of the underlying triangulation. This function can be called either after one run of simplification, or interleaved with several runs of simplification.
+
+The new point locations are chosen such that the approximation of the output segments and isolated points to the input points is improved. More specifically, the relocation process iterates between computing the best transport plan given the current reconstruction, and relocating the triangulation vertices while keeping the current transport plan unchanged. The vertices are relocated so as to minimize the transport cost induced by the current transport plan \cgalCite{degoes:hal-00758019}.
+
+\cgalFigureBegin{2D_Reconstruction_Simplification_relocation,relocation.png}
+Left: before point relocation. Right: after point relocation.
+\cgalFigureEnd
+
+
+\section Reconstruction_simplification_2Parameters User Parameters
+
+The behavior of the algorithm is controlled via the following parameters.
+
+\subsection Reconstruction_simplification_2Flip Edge Flipping
+
+During simplification of the internal triangulation some recursive edge flip operators are required to guarantee that the triangulation remain valid when applying a half edge collapse operator (see \cgalFigureRef{2D_Reconstruction_Simplification_edgeflip}). Calling set_use_flip(false) prevents the algorithm from using edge flips, yielding shorter computational times at the price of suboptimal results as not all edges can be considered for being collapsible.
+
+\cgalFigureBegin{2D_Reconstruction_Simplification_edgeflip,edgeflip.jpg}
+Edge flipping. Left: the blue edge creates fold-overs because of blocking edges shown in black. Middle: after running the recursive edge flipping procedure the blue edge is collapsible. Right: triangulation after edge collapse.
+\cgalFigureEnd
+
+\subsection Reconstruction_simplification_2Relevance Edge Relevance
+
+An edge is relevant from the approximation point of view if (1) it is long, (2) approximates a large number of points (or a large amount of mass when points have mass attributes), and (3) has a small approximation error. More specifically, the notion of relevance is defined as \f$ m(e) * |e|^2 / cost(e) \f$, where \f$ m(e) \f$ denotes the mass of the points approximated by the edge, \f$ |e| \f$ denotes the edge length and \f$ cost(e) \f$ its approximation error. As the error is defined by mass time squared distance the relevance is unitless.
+The default value is 0, so that all edges approximating some input points are considered relevant. A larger relevance value provides us with a means to increase resilience to outliers.
+
+
+\subsection Reconstruction_simplification_2Random Random Sample Size
+
+By default the simplification relies upon an exhaustive priority queue of half edge collapse operators during decimation. For improved efficiency, a parameter sample size strictly greater than 0 switches to a multiple choice approach, i.e., a best-choice selection in a random sample of edge collapse operators, of size sample size. A typical value for the sample size is 15, but this value must be enlarged when targeting a very coarse simplification.
+
+\subsection Reconstruction_simplification_2Local_relocation Local Point Relocation
+
+In addition to the global relocation function described above, an optional parameter of the constructor of the Reconstruction_simplification_2 class provides a means to relocate the points locally after each edge collapse operator (possibly combined with edge flips). Locally herein means that only the vertices of a local stencil in the triangulation around the each edge collapse operator are relocated, with a process similar to the one described above in the global relocation function. The local stencil is chosen as the one-ring neighborhood of the vertex remaining after collapsing an edge. The relocation process being iterative, one parameter controls the number of relocation steps.
+
+
+\subsection Reconstruction_simplification_2Verbose Verbose Output
+
+The verbose parameter, between 0 and 2, determines how much console output the algorithm generates. A 0 value generates no output to the standard output. A value greater than 0 generates output to the standard output `std::cerr`.
+
+
+\section Reconstruction_simplification_2Robustness Robustness
+A virtue of the algorithm is its robustness to noise and outliers.
+\cgalFigureRef{2D_Reconstruction_Simplification_robustness} shows that
+the output of the algorithm is robust in the sense that it is hardly affected by noise and/or outliers, as long as the density of outliers is small compared to the density of the input points.
+
+\cgalFigureBegin{2D_Reconstruction_Simplification_robustness,robustness.png}
+Robustness to noise and outliers. Left: noise-free point set. Middle: noisy point set. Right: point set hampered by noise and outliers.
+\cgalFigureEnd
+
+\section Reconstruction_simplification_2Density Variable Density
+\cgalFigureRef{2D_Reconstruction_Simplification_density} illustrates the behavior of the algorithm on a point set with uniform mass attributes, versus variable density. As the algorithm gives more importance to densely sampled areas, this translates into smaller edges on densely sampled areas. On sparsely sampled areas the algorithm initially approximates each point by one isolated vertex, then progressively approximates the points with edges.
+\cgalFigureBegin{2D_Reconstruction_Simplification_density,density.png}
+Variable density. Left: input point set. The three other pictures show
+how the approximation evolves when pushing the simplification forward.
+\cgalFigureEnd
+
+\section Reconstruction_simplification_2Mixed Mixed Dimension
+\cgalFigureRef{2D_Reconstruction_Simplification_mixed} depicts an input point set sampling a set of line segments and a solid area. Depending on the targeted number of points in the output, the solid area is approximated by a set of evenly sampled isolated vertices.
+
+\cgalFigureBegin{2D_Reconstruction_Simplification_mixed,mixed.png}
+Mixed dimension. Left: input point set. Middle: Isolated vertices in blue, relevant edges in green and irrelevant edges in red. Right: final output.
+\cgalFigureEnd
+
+\section Reconstruction_simplification_2Variable_mass Variable Mass
+
+The mass attributes provides a means to adjust the importance given to each point for approximation. \cgalFigureRef{2D_Reconstruction_Simplification_variable} depicts a reconstruction from a gray level image after thresholding, where the gray level of the pixels are used as mass attribute.
+
+\cgalFigureBegin{2D_Reconstruction_Simplification_variable,variable.png}
+Variable mass. Left: input gray level image. Middle: image after thresholding to reduce the number of pixels used as points with non-zero mass. Right: final reconstruction.
+\cgalFigureEnd
+
+\section Reconstruction_simplification_2HowDoesItWork How Does It Work?
+
+The task addressed here is to reconstruct a shape from a noisy point set \f$ S \f$ in \f$ \mathbb{R}^2 \f$, i.e., given a set of points in the plane, find a set of points and segments (more formally, a 0-1 simplicial complex ) which best approximates \f$ S \f$.
+
+The approximation error is derived from the theory of optimal transportation between geometric measures \cgalCite{degoes:hal-00758019}. More specifically, the input point set is seen as a discrete measure, i.e., a set of pointwise masses. The goal is to find a 0-1 simplicial complex where the edges are the support of a piecewise uniform continuous measure (i.e., a line density of masses) and the vertices are the support of a discrete measure. Approximating the input point set in our context translates into approximating the input discrete measure by another measure composed of line segments and points.
+
+\subsection Reconstruction_simplification_2Wasserstein Wasserstein Distance
+
+Intuitively, the optimal transportation distance (Wasserstein-2 distance in our context) measures the amount of work that it takes to transport the input measure onto the vertices and edges of the triangulation, where the measure is constrained to be uniform (and greater or equal to zero) on each edge, and just greater or equal to zero on each vertex. Note that the Wasserstein distance is symmetric.
+
+When all vertices of the triangulation coincide with the input points (after full initialization) the total transport cost is zero as each input point relocates to a vertex at no cost, and the reconstruction is made of isolated vertices only.
+
+Assume for now that the input point set is composed of 10 points (each with mass 1) uniformly sampled on a line segment, and that the triangulation contains a single edge coinciding with the line segment. Although the (one-sided Euclidean) distance from the points to the edge is zero (the converse being not zero), the Wasserstein distance from the points to the edge is non zero, as we constrain the mass density of the edge to be uniform, and the total mass (integral of density) of the edge to equal 10, i.e., the total mass of the input points. The input points should hence be transported tangentially on the edge in order to match the uniform density, the optimal transport plan for the input points being described as smaller line segments with equal lengths, covering the edge.
+
+If one now samples uniformly 20 points on the same edge (each with mass 0.5) the Wasserstein distance is smaller (albeit the total mass is 10 as before), as the transport plan is described by smaller line segments.
+In a slightly different configuration where the 20 input points have different masses, the optimal transport plan is described by small line segments whose length is proportional to the mass of the associated input point.
+When the input points are not strictly on the edge, the transport plan has both tangential and normal components.
+
+In other words, one approximates well the input points by a single edge when the input points are densely and uniformly sampling that edge. Beyond symmetry, one virtue of the Wasserstein distance is thus to quantize both the deviation from the points to the edge, and the non-uniformity of the points on that edge. This distance is also resilient to outliers (points far from the edge) when the mass of these outliers is small compared to the total mass of the input points.
+
+\subsection Reconstruction_simplification_2Reconstruction Reconstruction
+
+The algorithm performs a fine to coarse simplification of a triangulation. It starts by constructing a box around the input points \f$S\f$ and computes the Delaunay Triangulation \f$ T_0 \f$ on all or a subset of \f$ S \f$. \f$ T_0 \f$ is the first output simplex, which is simplified in subsequent iterations by repeated edge collapses. To chose the next edge, an edge collapse operator is simulated for all feasible edges, i.e., for edges which introduce neither overlaps nor fold-overs in the triangulation. The next edge \f$ e \f$ for collapse is chosen according to the overall cost of the transportation plan for \f$ T \setminus e \f$, where the cheapest overall cost is preferred. Since disregarding edges which do not preserve the embedding of the triangulation can severely affect the performance of the greedy approach to optimal transport, the collapse operator is modified by adding a local flip procedure which makes every edge collapsible.
+
+The transportation plan is approximated by assigning each input point temporarily to the closest simplex edge. After this partitioning of the input points w.r.t. the edges, all the points temporarily assigned to a given edge are being assigned to it permanently if and only if the corresponding transportation costs are less than the transportation cost for each of the two end vertices of the edge. Otherwise each of the points is assigned to the cheapest of the two vertices. This process of edge collapse and transportation plan update is repeated until the desired number of vertices, specified by the users, has been reached.
+
+At the end of the process, the edges which carry little mass can be filtered out and the remaining relevant edges and isolated vertices are reported as reconstructing the input shape.
+
+\section Reconstruction_simplification_2History Design and Implementation History
+This package is the result of the work of Ivo Vigan during the 2014 season
+of the Google Summer of Code. He has been mentored by Clement Jamin,
+Pierre Alliez and Fernando de Goes. The code is based on an initial research
+code written by Pierre Alliez and Fernando de Goes in 2010, for a paper published
+at the EUROGRAPHICS Symposium on Geometry Processing 2011 \cgalCite{degoes:hal-00758019}.
+
+*/
+} /* namespace CGAL */
+
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/dependencies b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/dependencies
new file mode 100644
index 00000000000..8ee9839e7bd
--- /dev/null
+++ b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/dependencies
@@ -0,0 +1,4 @@
+Manual
+Kernel_23
+STL_Extension
+Triangulation_2
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/examples.txt b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/examples.txt
new file mode 100644
index 00000000000..f0c1f6ced7d
--- /dev/null
+++ b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/examples.txt
@@ -0,0 +1,6 @@
+/*!
+\example Reconstruction_simplification_2/rs2_simplest_example.cpp
+\example Reconstruction_simplification_2/rs2_list_output_example.cpp
+\example Reconstruction_simplification_2/rs2_indexed_output_example.cpp
+\example Reconstruction_simplification_2/rs2_mass_example.cpp
+*/
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/algorithm.png b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/algorithm.png
new file mode 100644
index 00000000000..63e97d28bc9
Binary files /dev/null and b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/algorithm.png differ
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/density.png b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/density.png
new file mode 100644
index 00000000000..be23b800c50
Binary files /dev/null and b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/density.png differ
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/edgeflip.jpg b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/edgeflip.jpg
new file mode 100644
index 00000000000..73a5b832b98
Binary files /dev/null and b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/edgeflip.jpg differ
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/mixed.png b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/mixed.png
new file mode 100644
index 00000000000..cce44337e53
Binary files /dev/null and b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/mixed.png differ
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/relocation.png b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/relocation.png
new file mode 100644
index 00000000000..ddbe117e202
Binary files /dev/null and b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/relocation.png differ
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/robustness.png b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/robustness.png
new file mode 100644
index 00000000000..d0adb935618
Binary files /dev/null and b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/robustness.png differ
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/summary.png b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/summary.png
new file mode 100644
index 00000000000..b59e4f0b8cb
Binary files /dev/null and b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/summary.png differ
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/twenty_vertices.png b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/twenty_vertices.png
new file mode 100644
index 00000000000..09bf27e8e5f
Binary files /dev/null and b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/twenty_vertices.png differ
diff --git a/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/variable.png b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/variable.png
new file mode 100644
index 00000000000..da0d4d42d78
Binary files /dev/null and b/Reconstruction_simplification_2/doc/Reconstruction_simplification_2/fig/variable.png differ
diff --git a/Reconstruction_simplification_2/dont_submit b/Reconstruction_simplification_2/dont_submit
new file mode 100644
index 00000000000..1549b67ca59
--- /dev/null
+++ b/Reconstruction_simplification_2/dont_submit
@@ -0,0 +1 @@
+demo
diff --git a/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/CMakeLists.txt b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/CMakeLists.txt
new file mode 100644
index 00000000000..43b24c9717b
--- /dev/null
+++ b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/CMakeLists.txt
@@ -0,0 +1,34 @@
+project( Reconstruction_simplification_2_example )
+
+cmake_minimum_required(VERSION 2.6.2)
+if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6)
+ if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3)
+ cmake_policy(VERSION 2.8.4)
+ else()
+ cmake_policy(VERSION 2.6)
+ endif()
+endif()
+
+find_package(CGAL QUIET COMPONENTS Core )
+
+if ( CGAL_FOUND )
+
+ include( ${CGAL_USE_FILE} )
+
+ include( CGAL_CreateSingleSourceCGALProgram )
+
+ include_directories (BEFORE "../../include")
+
+ include_directories (BEFORE "include")
+
+ create_single_source_cgal_program( "rs2_simplest_example.cpp" )
+ create_single_source_cgal_program( "rs2_list_output_example.cpp" )
+ create_single_source_cgal_program( "rs2_indexed_output_example.cpp" )
+ create_single_source_cgal_program( "rs2_mass_example.cpp" )
+
+else()
+
+ message(STATUS "This program requires the CGAL library, and will not be compiled.")
+
+endif()
+
diff --git a/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/data/stair.xy b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/data/stair.xy
new file mode 100644
index 00000000000..3d6f2434d85
--- /dev/null
+++ b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/data/stair.xy
@@ -0,0 +1,160 @@
+0.00605396 0.00360027
+0.0117095 0.00496933
+0.00292489 -0.0056444
+0.018654 -0.00345866
+0.0208731 -0.00712699
+0.0349622 0.00520127
+0.0226514 0.00273598
+0.0443469 0.00641652
+0.0320264 -0.00785089
+0.0536853 -0.00492172
+0.0477706 0.00445479
+0.0639807 0.00509629
+0.0673864 -0.000544755
+0.068878 0.00636891
+0.0786834 -0.00880306
+0.0838299 0.00977294
+0.087326 -0.0021897
+0.079062 0.000772423
+0.0984893 0.00905454
+0.0994487 -0.00770074
+0.100736 0.00717826
+0.0994229 0.00250389
+0.100252 0.0167278
+0.0960604 0.00802011
+0.103545 0.0289233
+0.108446 0.0183656
+0.106763 0.0262313
+0.106452 0.0420934
+0.0997256 0.0427598
+0.107064 0.0403298
+0.0928101 0.0560955
+0.10136 0.0583232
+0.104819 0.0562105
+0.0902899 0.0706163
+0.10994 0.0770702
+0.0923621 0.0704878
+0.0919434 0.0865538
+0.0963674 0.0842679
+0.103725 0.0803259
+0.102273 0.101166
+0.100319 0.0952791
+0.108403 0.0942299
+0.113529 0.0981625
+0.108027 0.103066
+0.126272 0.0950435
+0.133506 0.0939314
+0.124776 0.107205
+0.131076 0.107853
+0.136759 0.109119
+0.15444 0.102357
+0.143707 0.104111
+0.160272 0.0974776
+0.165379 0.103348
+0.173751 0.0916309
+0.174657 0.0937715
+0.167267 0.0980068
+0.170889 0.0905988
+0.185414 0.102092
+0.189813 0.10002
+0.199397 0.0909473
+0.198222 0.107717
+0.198974 0.099872
+0.201479 0.108827
+0.205074 0.107075
+0.202 0.124977
+0.191185 0.121976
+0.206848 0.134009
+0.196679 0.137767
+0.19255 0.148035
+0.190151 0.143856
+0.195263 0.155428
+0.20595 0.148822
+0.204421 0.152387
+0.191967 0.169495
+0.197981 0.169699
+0.191872 0.176798
+0.207398 0.170317
+0.194859 0.178978
+0.190444 0.183389
+0.196073 0.192833
+0.200019 0.190352
+0.205824 0.198579
+0.217043 0.198723
+0.210708 0.208976
+0.225591 0.209213
+0.224774 0.208331
+0.228376 0.201784
+0.233852 0.192014
+0.230703 0.196273
+0.241172 0.192107
+0.241027 0.203219
+0.257393 0.199803
+0.266244 0.190504
+0.263176 0.1902
+0.279822 0.191442
+0.267419 0.200092
+0.270919 0.209937
+0.294279 0.199399
+0.292596 0.208336
+0.302111 0.206854
+0.297261 0.193606
+0.302447 0.195568
+0.307461 0.217454
+0.302133 0.219113
+0.300152 0.216012
+0.296763 0.223723
+0.302571 0.234727
+0.298522 0.237272
+0.307834 0.234066
+0.296568 0.250613
+0.298385 0.251664
+0.29308 0.261943
+0.295426 0.266549
+0.293096 0.259791
+0.292439 0.271056
+0.291263 0.275271
+0.300944 0.286063
+0.308624 0.284206
+0.306603 0.285177
+0.302574 0.289769
+0.303807 0.303483
+0.308102 0.301263
+0.316854 0.306492
+0.313448 0.299638
+0.325862 0.304911
+0.328301 0.305416
+0.335535 0.300855
+0.327652 0.299601
+0.334895 0.301131
+0.339451 0.303238
+0.356128 0.293215
+0.359167 0.306227
+0.350648 0.309557
+0.359385 0.291005
+0.360515 0.305818
+0.377582 0.301763
+0.373333 0.308693
+0.375172 0.299768
+0.398744 0.298911
+0.390985 0.295462
+0.39465 0.305079
+0.397266 0.302934
+0.391293 0.303944
+0.401355 0.307406
+0.391301 0.312749
+0.401141 0.331346
+0.403843 0.339273
+0.397447 0.32984
+0.401007 0.345187
+0.401435 0.350856
+0.404534 0.358367
+0.40019 0.350997
+0.401021 0.359769
+0.398586 0.362409
+0.403735 0.370503
+0.400571 0.381428
+0.409145 0.374727
+0.402981 0.379619
+0.406312 0.38398
+0.405032 0.387826
diff --git a/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/data/stair.xym b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/data/stair.xym
new file mode 100644
index 00000000000..f78a3acdf6b
--- /dev/null
+++ b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/data/stair.xym
@@ -0,0 +1,160 @@
+0.00605396 0.00360027 1.0
+0.0117095 0.00496933 1.0
+0.00292489 -0.0056444 1.0
+0.018654 -0.00345866 1.0
+0.0208731 -0.00712699 1.0
+0.0349622 0.00520127 1.0
+0.0226514 0.00273598 1.0
+0.0443469 0.00641652 1.0
+0.0320264 -0.00785089 1.0
+0.0536853 -0.00492172 1.0
+0.0477706 0.00445479 1.0
+0.0639807 0.00509629 1.0
+0.0673864 -0.000544755 1.0
+0.068878 0.00636891 1.0
+0.0786834 -0.00880306 1.0
+0.0838299 0.00977294 1.0
+0.087326 -0.0021897 1.0
+0.079062 0.000772423 1.0
+0.0984893 0.00905454 1.0
+0.0994487 -0.00770074 1.0
+0.100736 0.00717826 1.0
+0.0994229 0.00250389 1.0
+0.100252 0.0167278 1.0
+0.0960604 0.00802011 1.0
+0.103545 0.0289233 1.0
+0.108446 0.0183656 1.0
+0.106763 0.0262313 1.0
+0.106452 0.0420934 1.0
+0.0997256 0.0427598 1.0
+0.107064 0.0403298 1.0
+0.0928101 0.0560955 1.0
+0.10136 0.0583232 1.0
+0.104819 0.0562105 1.0
+0.0902899 0.0706163 1.0
+0.10994 0.0770702 1.0
+0.0923621 0.0704878 1.0
+0.0919434 0.0865538 1.0
+0.0963674 0.0842679 1.0
+0.103725 0.0803259 1.0
+0.102273 0.101166 1.0
+0.100319 0.0952791 1.0
+0.108403 0.0942299 1.0
+0.113529 0.0981625 1.0
+0.108027 0.103066 1.0
+0.126272 0.0950435 1.0
+0.133506 0.0939314 1.0
+0.124776 0.107205 1.0
+0.131076 0.107853 1.0
+0.136759 0.109119 1.0
+0.15444 0.102357 1.0
+0.143707 0.104111 1.0
+0.160272 0.0974776 1.0
+0.165379 0.103348 1.0
+0.173751 0.0916309 1.0
+0.174657 0.0937715 1.0
+0.167267 0.0980068 1.0
+0.170889 0.0905988 1.0
+0.185414 0.102092 1.0
+0.189813 0.10002 1.0
+0.199397 0.0909473 1.0
+0.198222 0.107717 1.0
+0.198974 0.099872 1.0
+0.201479 0.108827 1.0
+0.205074 0.107075 1.0
+0.202 0.124977 1.0
+0.191185 0.121976 1.0
+0.206848 0.134009 1.0
+0.196679 0.137767 1.0
+0.19255 0.148035 1.0
+0.190151 0.143856 1.0
+0.195263 0.155428 1.0
+0.20595 0.148822 1.0
+0.204421 0.152387 1.0
+0.191967 0.169495 1.0
+0.197981 0.169699 1.0
+0.191872 0.176798 1.0
+0.207398 0.170317 1.0
+0.194859 0.178978 1.0
+0.190444 0.183389 1.0
+0.196073 0.192833 1.0
+0.200019 0.190352 1.0
+0.205824 0.198579 1.0
+0.217043 0.198723 1.0
+0.210708 0.208976 1.0
+0.225591 0.209213 1.0
+0.224774 0.208331 1.0
+0.228376 0.201784 1.0
+0.233852 0.192014 1.0
+0.230703 0.196273 1.0
+0.241172 0.192107 1.0
+0.241027 0.203219 1.0
+0.257393 0.199803 1.0
+0.266244 0.190504 1.0
+0.263176 0.1902 1.0
+0.279822 0.191442 1.0
+0.267419 0.200092 1.0
+0.270919 0.209937 1.0
+0.294279 0.199399 1.0
+0.292596 0.208336 1.0
+0.302111 0.206854 1.0
+0.297261 0.193606 1.0
+0.302447 0.195568 1.0
+0.307461 0.217454 1.0
+0.302133 0.219113 1.0
+0.300152 0.216012 1.0
+0.296763 0.223723 1.0
+0.302571 0.234727 1.0
+0.298522 0.237272 1.0
+0.307834 0.234066 1.0
+0.296568 0.250613 1.0
+0.298385 0.251664 1.0
+0.29308 0.261943 1.0
+0.295426 0.266549 1.0
+0.293096 0.259791 1.0
+0.292439 0.271056 1.0
+0.291263 0.275271 1.0
+0.300944 0.286063 1.0
+0.308624 0.284206 1.0
+0.306603 0.285177 1.0
+0.302574 0.289769 1.0
+0.303807 0.303483 1.0
+0.308102 0.301263 1.0
+0.316854 0.306492 1.0
+0.313448 0.299638 1.0
+0.325862 0.304911 1.0
+0.328301 0.305416 1.0
+0.335535 0.300855 1.0
+0.327652 0.299601 1.0
+0.334895 0.301131 1.0
+0.339451 0.303238 1.0
+0.356128 0.293215 1.0
+0.359167 0.306227 1.0
+0.350648 0.309557 1.0
+0.359385 0.291005 1.0
+0.360515 0.305818 1.0
+0.377582 0.301763 1.0
+0.373333 0.308693 1.0
+0.375172 0.299768 1.0
+0.398744 0.298911 1.0
+0.390985 0.295462 1.0
+0.39465 0.305079 1.0
+0.397266 0.302934 1.0
+0.391293 0.303944 1.0
+0.401355 0.307406 1.0
+0.391301 0.312749 1.0
+0.401141 0.331346 1.0
+0.403843 0.339273 1.0
+0.397447 0.32984 1.0
+0.401007 0.345187 1.0
+0.401435 0.350856 1.0
+0.404534 0.358367 1.0
+0.40019 0.350997 1.0
+0.401021 0.359769 1.0
+0.398586 0.362409 1.0
+0.403735 0.370503 1.0
+0.400571 0.381428 1.0
+0.409145 0.374727 1.0
+0.402981 0.379619 1.0
+0.406312 0.38398 1.0
+0.405032 0.387826 1.0
diff --git a/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/rs2_indexed_output_example.cpp b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/rs2_indexed_output_example.cpp
new file mode 100644
index 00000000000..210d50a06a3
--- /dev/null
+++ b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/rs2_indexed_output_example.cpp
@@ -0,0 +1,68 @@
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
+typedef K::FT FT;
+typedef K::Point_2 Point;
+
+typedef CGAL::Reconstruction_simplification_2 Rs_2;
+
+void load_xy_file(const std::string& filename, std::vector& points)
+{
+ std::ifstream ifs(filename.c_str());
+ Point point;
+ while (ifs >> point)
+ points.push_back(point);
+
+ ifs.close();
+}
+
+void indexed_output(Rs_2& rs2)
+{
+ std::cout << "(-------------Off output---------- )" << std::endl;
+
+ std::vector points;
+ std::vector isolated_vertices;
+ std::vector > edges;
+
+ rs2.indexed_output(
+ std::back_inserter(points),
+ std::back_inserter(isolated_vertices),
+ std::back_inserter(edges));
+
+ std::cout << "OFF " << points.size() << " 0 " << edges.size() << std::endl;
+
+ // points
+ std::vector::iterator pit;
+ for (pit = points.begin(); pit != points.end(); pit++)
+ std::cout << *pit << std::endl;
+
+ // isolated vertices
+ std::vector::iterator vit;
+ for (vit = isolated_vertices.begin(); vit != isolated_vertices.end(); vit++)
+ std::cout << "1 " << *vit << std::endl;
+
+ // edges
+ std::vector >::iterator eit;
+ for (eit = edges.begin(); eit != edges.end(); eit++)
+ std::cout << "2 " << eit->first << " " << eit->second << std::endl;
+}
+
+int main ()
+{
+ std::vector points;
+
+ load_xy_file("data/stair-noise00.xy", points);
+
+ Rs_2 rs2(points);
+ rs2.run(100); // 100 steps
+ indexed_output(rs2);
+
+ return 0;
+}
diff --git a/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/rs2_list_output_example.cpp b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/rs2_list_output_example.cpp
new file mode 100644
index 00000000000..0ddc8e6322e
--- /dev/null
+++ b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/rs2_list_output_example.cpp
@@ -0,0 +1,57 @@
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
+typedef K::FT FT;
+typedef K::Point_2 Point;
+typedef K::Segment_2 Segment;
+
+typedef CGAL::Reconstruction_simplification_2 Rs_2;
+
+void load_xy_file(const std::string& filename, std::vector& points)
+{
+ std::ifstream ifs(filename.c_str());
+ Point point;
+ while (ifs >> point)
+ points.push_back(point);
+
+ ifs.close();
+}
+
+void list_output(Rs_2& rs2)
+{
+ std::cout << "(-------------List output---------- )" << std::endl;
+
+ std::vector isolated_points;
+ std::vector segments;
+
+ rs2.list_output(
+ std::back_inserter(isolated_points), std::back_inserter(segments));
+
+ std::vector::iterator pit;
+ for (pit = isolated_points.begin(); pit != isolated_points.end(); pit++)
+ std::cout << *pit << std::endl;
+
+ std::vector::iterator sit;
+ for (sit = segments.begin(); sit != segments.end(); sit++)
+ std::cout << *sit << std::endl;
+}
+
+int main ()
+{
+ std::vector points;
+
+ load_xy_file("data/stair-noise00.xy", points);
+
+ Rs_2 rs2(points);
+ rs2.run(100); // 100 steps
+ list_output(rs2);
+
+ return 0;
+}
diff --git a/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/rs2_mass_example.cpp b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/rs2_mass_example.cpp
new file mode 100644
index 00000000000..d6b6790c5ac
--- /dev/null
+++ b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/rs2_mass_example.cpp
@@ -0,0 +1,70 @@
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include // std::pair
+#include
+
+#include
+
+typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
+typedef K::FT FT;
+typedef K::Point_2 Point;
+typedef K::Segment_2 Segment;
+
+typedef std::pair PointMassPair;
+typedef std::vector PointMassList;
+
+typedef CGAL::First_of_pair_property_map Point_property_map;
+typedef CGAL::Second_of_pair_property_map Mass_property_map;
+
+typedef CGAL::Reconstruction_simplification_2<
+ K, Point_property_map, Mass_property_map> Rs_2;
+
+void load_xym_file(const std::string& filename, PointMassList& points)
+{
+ std::ifstream ifs(filename.c_str());
+
+ Point point;
+ FT mass;
+
+ while (ifs >> point && ifs >> mass)
+ points.push_back(std::make_pair(point, mass));
+
+ ifs.close();
+}
+
+int main ()
+{
+ PointMassList points;
+
+ load_xym_file("data/stair.xym", points);
+
+ Point_property_map point_pmap;
+ Mass_property_map mass_pmap;
+
+ Rs_2 rs2(points, point_pmap, mass_pmap);
+
+ rs2.run(100); // 100 steps
+
+ std::vector isolated_vertices;
+ std::vector edges;
+
+ rs2.list_output(
+ std::back_inserter(isolated_vertices), std::back_inserter(edges));
+
+ std::cout << "Isolated vertices:" << std::endl;
+ std::vector::iterator vit;
+ for (vit = isolated_vertices.begin(); vit != isolated_vertices.end(); vit++)
+ std::cout << *vit << std::endl;
+
+ std::cerr << "Edges:" << std::endl;
+ std::vector::iterator eit;
+ for (eit = edges.begin(); eit != edges.end(); eit++)
+ std::cout << *eit << std::endl;
+
+ return 0;
+}
diff --git a/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/rs2_simplest_example.cpp b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/rs2_simplest_example.cpp
new file mode 100644
index 00000000000..f9edecfc39e
--- /dev/null
+++ b/Reconstruction_simplification_2/examples/Reconstruction_simplification_2/rs2_simplest_example.cpp
@@ -0,0 +1,28 @@
+// Simplest example for Reconstruction_simplification_2, with no mass
+// attributes for the input points
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
+typedef K::Point_2 Point;
+
+typedef CGAL::Reconstruction_simplification_2 Rs;
+
+int main ()
+{
+ // Generate a set of random points on the boundary of a square.
+ std::vector points;
+ CGAL::Random_points_on_square_2 point_generator(1.);
+ CGAL::cpp11::copy_n(point_generator, 100, std::back_inserter(points));
+
+ Rs rs(points);
+ rs.run(100); // 100 steps
+
+ return 0;
+}
diff --git a/Reconstruction_simplification_2/include/CGAL/Cost.h b/Reconstruction_simplification_2/include/CGAL/Cost.h
new file mode 100644
index 00000000000..c7eda0d760a
--- /dev/null
+++ b/Reconstruction_simplification_2/include/CGAL/Cost.h
@@ -0,0 +1,105 @@
+// Copyright (c) 2014 INRIA Sophia-Antipolis (France), INRIA Lorraine LORIA.
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// 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.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Fernando de Goes, Pierre Alliez, Ivo Vigan, Clément Jamin
+
+#ifndef COST_H_
+#define COST_H_
+
+#include
+
+template
+class Cost
+{
+private:
+ FT m_norm;
+ FT m_tang;
+ FT m_max_norm;
+ FT m_max_tang;
+
+public:
+ Cost()
+ : m_norm(0),
+ m_tang(0),
+ m_max_norm(0),
+ m_max_tang(0)
+ {}
+
+ Cost(const FT norm, const FT tang)
+ : m_norm(norm),
+ m_tang(tang),
+ m_max_norm(norm),
+ m_max_tang(tang)
+ {}
+
+ ~Cost() {}
+
+ Cost& operator= (const Cost& cost)
+ {
+ m_norm = cost.norm();
+ m_tang = cost.tang();
+ m_max_norm = cost.max_norm();
+ m_max_tang = cost.max_tang();
+ return *this;
+ }
+
+ const FT norm() const { return m_norm; }
+
+ const FT tang() const { return m_tang; }
+
+ const FT max_norm() const { return m_max_norm; }
+
+ const FT max_tang() const { return m_max_tang; }
+
+ FT finalize(const FT alpha = FT(0.5)) const
+ {
+ return FT(2) * (alpha * m_norm + (FT(1) - alpha) * m_tang);
+ }
+
+ void divide(const FT ratio)
+ {
+ CGAL_assertion(ratio != FT(0));
+ m_norm /= ratio;
+ m_tang /= ratio;
+ }
+
+ void add(const Cost& cost, const FT mass = FT(1))
+ {
+ m_norm += mass * cost.norm();
+ m_tang += mass * cost.tang();
+ }
+
+ void reset_max()
+ {
+ m_max_norm = FT(0);
+ m_max_tang = FT(0);
+ }
+
+ void update_max(const Cost& cost)
+ {
+ m_max_norm = (std::max)(m_max_norm, cost.max_norm());
+ m_max_tang = (std::max)(m_max_tang, cost.max_tang());
+ }
+
+ void compute_max(const FT norm, const FT tang)
+ {
+ m_max_norm = (std::max)(m_max_norm, norm);
+ m_max_tang = (std::max)(m_max_tang, tang);
+ }
+};
+
+#endif // COST_H_
diff --git a/Reconstruction_simplification_2/include/CGAL/Reconstruction_edge_2.h b/Reconstruction_simplification_2/include/CGAL/Reconstruction_edge_2.h
new file mode 100644
index 00000000000..67bd15259f8
--- /dev/null
+++ b/Reconstruction_simplification_2/include/CGAL/Reconstruction_edge_2.h
@@ -0,0 +1,139 @@
+// Copyright (c) 2014 INRIA Sophia-Antipolis (France), INRIA Lorraine LORIA.
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// 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.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Fernando de Goes, Pierre Alliez, Ivo Vigan, Clément Jamin
+
+#ifndef RECONSTRUCTION_EDGE_2_H_
+#define RECONSTRUCTION_EDGE_2_H_
+
+template
+class Reconstruction_edge_2 {
+protected:
+ Edge m_edge;
+ Vertex_handle m_source;
+ Vertex_handle m_target;
+
+ FT m_before_cost;
+ FT m_after_cost;
+
+public:
+ Reconstruction_edge_2()
+ : m_edge(Face_handle(), 0),
+ m_before_cost(0),
+ m_after_cost(0)
+ {}
+
+ Reconstruction_edge_2(const Reconstruction_edge_2& pedge)
+ : m_edge(pedge.edge()),
+ m_source(pedge.source()),
+ m_target(pedge.target()),
+ m_before_cost(pedge.before()),
+ m_after_cost(pedge.after())
+ {}
+
+ Reconstruction_edge_2(const Edge& edge, const FT before, const FT after)
+ : m_edge(edge),
+ m_before_cost(before),
+ m_after_cost(after)
+ {
+ get_vertices();
+ }
+
+ Reconstruction_edge_2(const Edge& edge, const FT priority = FT(0))
+ : m_edge(edge),
+ m_before_cost(0),
+ m_after_cost(priority)
+ {
+ get_vertices();
+ }
+
+ Reconstruction_edge_2(Vertex_handle source, Vertex_handle target)
+ : m_edge(Face_handle(), 0),
+ m_source(source),
+ m_target(target),
+ m_before_cost(0),
+ m_after_cost(0)
+ {}
+
+ Reconstruction_edge_2& operator= (const Reconstruction_edge_2& pedge)
+ {
+ m_edge = pedge.edge();
+ m_source = pedge.source();
+ m_target = pedge.target();
+ m_before_cost = pedge.before();
+ m_after_cost = pedge.after();
+
+ return *this;
+ }
+
+ bool operator== (const Reconstruction_edge_2& pedge) const
+ {
+ return (m_source->id() == pedge.source()->id()
+ && m_target->id() == pedge.target()->id());
+ }
+
+ bool operator< (const Reconstruction_edge_2& pedge) const
+ {
+ if (m_source->id() < pedge.source()->id())
+ return true;
+ if (m_source->id() > pedge.source()->id())
+ return false;
+ if (m_target->id() < pedge.target()->id())
+ return true;
+ return false;
+ }
+
+ const Edge& edge() const
+ {
+ return m_edge;
+ }
+
+ const Vertex_handle& source() const
+ {
+ return m_source;
+ }
+
+ const Vertex_handle& target() const
+ {
+ return m_target;
+ }
+
+ const FT before() const
+ {
+ return m_before_cost;
+ }
+
+ const FT after() const
+ {
+ return m_after_cost;
+ }
+
+ const FT priority() const
+ {
+ return after() - before();
+ }
+
+protected:
+ void get_vertices()
+ {
+ int index = m_edge.second;
+ m_source = m_edge.first->vertex((index + 1) % 3);
+ m_target = m_edge.first->vertex((index + 2) % 3);
+ }
+};
+
+#endif // RECONSTRUCTION_EDGE_2_H_
diff --git a/Reconstruction_simplification_2/include/CGAL/Reconstruction_face_base_2.h b/Reconstruction_simplification_2/include/CGAL/Reconstruction_face_base_2.h
new file mode 100644
index 00000000000..8cd0fe57403
--- /dev/null
+++ b/Reconstruction_simplification_2/include/CGAL/Reconstruction_face_base_2.h
@@ -0,0 +1,265 @@
+// Copyright (c) 2014 INRIA Sophia-Antipolis (France), INRIA Lorraine LORIA.
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// 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.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Fernando de Goes, Pierre Alliez, Ivo Vigan, Clément Jamin
+
+#ifndef RECONSTRUCTION_FACE_BASE_2_H_
+#define RECONSTRUCTION_FACE_BASE_2_H_
+
+#include
+#include
+#include
+
+#include
+
+/// \cond SKIP_IN_MANUAL
+
+
+/// The Reconstruction_face_base_2 class is the default
+/// vertex class of the Reconstruction_face_base_2 class.
+///
+/// - Each vertex stores a CSample as well as the corresponding relocated point
+///
+namespace CGAL {
+/// @param Traits_ Traits class
+/// @param Vb Vertex base class, model of TriangulationFaceBase_2.
+template < class Traits_, class Fb = Triangulation_face_base_2 >
+class Reconstruction_face_base_2 : public Fb
+{
+public:
+ typedef Fb Base;
+ typedef typename Base::Vertex_handle Vertex_handle;
+ typedef typename Base::Face_handle Face_handle;
+
+ template < typename TDS2 >
+ struct Rebind_TDS
+ {
+ typedef typename Base::template Rebind_TDS::Other Fb2;
+ typedef Reconstruction_face_base_2 Other;
+ };
+
+ typedef typename Traits_::FT FT;
+ typedef Cost Cost_;
+ typedef Sample Sample_;
+ typedef std::vector Sample_vector;
+
+private:
+ Sample_vector m_samples[3];
+ FT m_mass[3];
+
+ Cost_ m_cost0[3];
+ Cost_ m_cost1[3];
+ int m_plan[3];
+
+ FT m_relevance[3];
+
+public:
+ Reconstruction_face_base_2()
+ {
+ init();
+ }
+
+ Reconstruction_face_base_2(
+ Vertex_handle v1, Vertex_handle v2, Vertex_handle v3)
+ : Base(v1, v2, v3)
+ {
+ init();
+ }
+
+ Reconstruction_face_base_2(
+ Vertex_handle v1, Vertex_handle v2, Vertex_handle v3,
+ Face_handle f1, Face_handle f2, Face_handle f3)
+ : Base(v1, v2, v3, f1, f2, f3)
+ {
+ init();
+ }
+
+ Reconstruction_face_base_2(Face_handle f)
+ : Base(f)
+ {
+ m_samples[0] = f->samples(0);
+ m_samples[1] = f->samples(1);
+ m_samples[2] = f->samples(2);
+
+ m_mass[0] = f->mass(0);
+ m_mass[1] = f->mass(1);
+ m_mass[2] = f->mass(2);
+
+ m_cost0[0] = f->vertex_cost(0);
+ m_cost0[1] = f->vertex_cost(1);
+ m_cost0[2] = f->vertex_cost(2);
+
+ m_cost1[0] = f->edge_cost(0);
+ m_cost1[1] = f->edge_cost(1);
+ m_cost1[2] = f->edge_cost(2);
+
+ m_plan[0] = f->plan(0);
+ m_plan[1] = f->plan(1);
+ m_plan[2] = f->plan(2);
+
+ m_relevance[0] = f->relevance(0);
+ m_relevance[1] = f->relevance(1);
+ m_relevance[2] = f->relevance(2);
+ }
+
+ ~Reconstruction_face_base_2()
+ {
+ clean_all_samples();
+ }
+
+ void init()
+ {
+ m_mass[0] = FT(0);
+ m_mass[1] = FT(0);
+ m_mass[2] = FT(0);
+
+ m_cost0[0] = Cost_();
+ m_cost0[1] = Cost_();
+ m_cost0[2] = Cost_();
+
+ m_cost1[0] = Cost_();
+ m_cost1[1] = Cost_();
+ m_cost1[2] = Cost_();
+
+ m_plan[0] = 0;
+ m_plan[1] = 0;
+ m_plan[2] = 0;
+
+ m_relevance[0] = 0;
+ m_relevance[1] = 0;
+ m_relevance[2] = 0;
+
+ }
+
+ int plan(int edge) const { return m_plan[edge]; }
+ int& plan(int edge) { return m_plan[edge]; }
+
+ const FT& mass(int edge) const { return m_mass[edge]; }
+ FT& mass(int edge) { return m_mass[edge]; }
+
+ const Cost_& vertex_cost(int edge) const { return m_cost0[edge]; }
+ Cost_& vertex_cost(int edge) { return m_cost0[edge]; }
+
+ const Cost_& edge_cost(int edge) const { return m_cost1[edge]; }
+ Cost_& edge_cost(int edge) { return m_cost1[edge]; }
+
+ const FT& relevance(int edge) const { return m_relevance[edge]; }
+ FT& relevance(int edge) { return m_relevance[edge]; }
+
+
+ const Cost_& cost(int edge) const
+ {
+ if (plan(edge) == 0)
+ return vertex_cost(edge);
+ return edge_cost(edge);
+ }
+
+ bool ghost(int edge) const
+ {
+ if (mass(edge) == FT(0))
+ return true;
+ if (plan(edge) == 0)
+ return true;
+ return false;
+ }
+
+ const Sample_vector& samples(int edge) const { return m_samples[edge]; }
+ Sample_vector& samples(int edge) { return m_samples[edge]; }
+
+ void add_sample(int edge, Sample_* sample)
+ {
+ m_samples[edge].push_back(sample);
+ }
+
+ void clean_samples(int edge)
+ {
+ m_samples[edge].clear();
+ }
+
+ void clean_all_samples()
+ {
+ for (int i = 0; i < 3; ++i)
+ clean_samples(i);
+ }
+};
+
+//---------------STRUCT LESS FACE_HANDLE---------------------
+template
+struct less_Face_handle
+{
+ void get_vertices_id(const T& face, int& a, int& b, int& c) const
+ {
+ a = face->vertex(0)->id();
+ b = face->vertex(1)->id();
+ c = face->vertex(2)->id();
+ }
+
+ bool operator() (const T& a, const T& b) const
+ {
+ int a0, a1, a2;
+ get_vertices_id(a, a0, a1, a2);
+
+ int b0, b1, b2;
+ get_vertices_id(b, b0, b1, b2);
+
+ if (a0 < b0) return true;
+ if (a0 > b0) return false;
+
+ if (a1 < b1) return true;
+ if (a1 > b1) return false;
+
+ if (a2 < b2) return true;
+
+ return false;
+ }
+};
+
+
+//---------------STRUCT LESS EDGE---------------------
+template
+struct less_Edge
+{
+ void get_vertices_id(const T& a, int& i, int& j) const
+ {
+ i = a.first->vertex( (a.second+1)%3 )->id();
+ j = a.first->vertex( (a.second+2)%3 )->id();
+ if (i > j) std::swap(i, j);
+ }
+
+ bool operator() (const T& a, const T& b) const
+ {
+ int a0, a1;
+ get_vertices_id(a, a0, a1);
+
+ int b0, b1;
+ get_vertices_id(b, b0, b1);
+
+ if (a0 < b0) return true;
+ if (a0 > b0) return false;
+ if (a1 < b1) return true;
+
+ return false;
+ }
+
+
+ /// \endcond
+
+};
+
+} //end namespace
+
+#endif /* RECONSTRUCTION_FACE_BASE_2_H_ */
diff --git a/Reconstruction_simplification_2/include/CGAL/Reconstruction_simplification_2.h b/Reconstruction_simplification_2/include/CGAL/Reconstruction_simplification_2.h
new file mode 100644
index 00000000000..05187faed72
--- /dev/null
+++ b/Reconstruction_simplification_2/include/CGAL/Reconstruction_simplification_2.h
@@ -0,0 +1,1714 @@
+// Copyright (c) 2014 INRIA Sophia-Antipolis (France), INRIA Lorraine LORIA.
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// 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.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Fernando de Goes, Pierre Alliez, Ivo Vigan, Clément Jamin
+
+#ifndef RECONSTRUCTION_SIMPLIFICATION_2_H_
+#define RECONSTRUCTION_SIMPLIFICATION_2_H_
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include // std::pair
+
+#include
+#include
+#include
+#include
+#include
+
+namespace CGAL {
+
+
+/*!
+\ingroup PkgReconstructionSimplification2Classes
+
+This class provides a means to reconstruct a 1-dimensional shape from a set of 2D points with masses.
+The algorithm computes an initial 2D Delaunay triangulation from the input points,
+and performs a simplification of the triangulation by performing half edge collapses, edge flips and vertex relocations.
+
+The edges are either processed in the order imposed by an priority queue, or
+in an order based on random selection of edge collapse operators.
+As the exhaustive priority queue guarantees a higher quality it is the default.
+The user can switch to the other method, for example for an initial
+simplification round, by calling `set_random_sample_size()`.
+
+By default edge flip operators are applied to ensure that every edge of the
+triangulation are candidate to be collapsed, while preserving a valid embedding
+of the triangulation. This option can be disabled by calling
+\link set_use_flip() `set_use_flip(false)`\endlink to reduce the running times.
+
+By default the vertices are not relocated after each half edge collapse.
+This option can be changed by setting the number of vertex relocation steps
+performed between two edge collapse operators.
+
+The simplification is performed by calling either
+\link run_until() `run_until(n)`\endlink or \link run() `run(steps)`\endlink.
+The former simplifies the triangulation until n points remain, while the latter
+stops after `steps` edge collapse operators have been performed.
+Furthermore, we can relocate the vertices by calling `relocate_all_points()`.
+
+\tparam Traits a model of the concept `ReconstructionSimplificationTraits_2`.
+
+\tparam PointPMap a model of `ReadablePropertyMap` with value type `Traits::Point_2`.
+ Defaults to `boost::typed_identity_property_map`
+ (for the case the input is points without mass).
+
+\tparam MassPMap a model of `ReadablePropertyMap` with value type `Traits::FT`
+ Defaults to `boost::static_property_map`
+ (for the case the input is points without mass).
+
+ */
+template<
+ class Traits,
+ class PointPMap = boost::typed_identity_property_map ,
+ class MassPMap = boost::static_property_map >
+class Reconstruction_simplification_2
+{
+public:
+
+ /// \name Types
+ /// @{
+ /*!
+ Number type.
+ */
+ typedef typename Traits::FT FT;
+
+ /*!
+ Point type.
+ */
+ typedef typename Traits::Point_2 Point;
+
+ /*!
+ Segment type.
+ */
+ typedef typename Traits::Segment_2 Segment;
+
+ /// \cond SKIP_IN_MANUAL
+ /*!
+ Vector type.
+ */
+ typedef typename Traits::Vector_2 Vector;
+
+ typedef typename std::pair PointMassPair;
+ typedef typename std::vector PointMassList;
+
+
+ /*!
+ The Output simplex.
+ */
+ typedef Reconstruction_triangulation_2 Triangulation;
+
+ typedef typename Triangulation::Vertex Vertex;
+ typedef typename Triangulation::Vertex_handle Vertex_handle;
+ typedef typename Triangulation::Vertex_iterator Vertex_iterator;
+ typedef typename Triangulation::Vertex_circulator Vertex_circulator;
+ typedef typename Triangulation::Finite_vertices_iterator
+ Finite_vertices_iterator;
+
+ typedef typename Triangulation::Edge Edge;
+ typedef typename Triangulation::Edge_circulator Edge_circulator;
+ typedef typename Triangulation::Finite_edges_iterator Finite_edges_iterator;
+
+ typedef typename Triangulation::Face_handle Face_handle;
+ typedef typename Triangulation::Face_circulator Face_circulator;
+ typedef typename Triangulation::Finite_faces_iterator Finite_faces_iterator;
+
+ typedef typename Triangulation::Vertex_handle_map Vertex_handle_map;
+ typedef typename Triangulation::Face_handle_map Face_handle_map;
+
+ typedef typename Triangulation::Vertex_handle_set Vertex_handle_set;
+ typedef typename Triangulation::Edge_set Edge_set;
+
+ typedef typename Triangulation::Edge_vector Edge_vector;
+ typedef std::list Edge_list;
+
+ typedef typename Triangulation::Cost_ Cost_;
+ typedef typename Triangulation::Sample_ Sample_;
+ typedef typename Triangulation::Sample_vector Sample_vector;
+ typedef typename Triangulation::Sample_vector_const_iterator
+ Sample_vector_const_iterator;
+
+ typedef typename Triangulation::PSample PSample;
+ typedef typename Triangulation::SQueue SQueue;
+
+ typedef typename Triangulation::Rec_edge_2 Rec_edge_2;
+
+ typedef typename Triangulation::MultiIndex MultiIndex;
+
+ /// @}
+
+protected:
+ Triangulation m_dt;
+ Traits const& m_traits;
+ MultiIndex m_mindex;
+ int m_ignore;
+ int m_verbose;
+ std::size_t m_mchoice; // # Edges
+ bool m_use_flip;
+ FT m_alpha; // [0, 1]
+ FT m_norm_tol; // [0,BBOX]
+ FT m_tang_tol; // [0,BBOX]
+ FT m_ghost; // ghost vs solid
+ unsigned int m_relocation; // # relocations
+
+ // bbox
+ FT m_bbox_x;
+ FT m_bbox_y;
+ FT m_bbox_size;
+
+ PointPMap point_pmap;
+ MassPMap mass_pmap;
+
+ /// \endcond
+
+public:
+
+ /// \name Initialization
+ /// @{
+
+ /*!
+ Constructor of the reconstruction simplification class.
+ It builds an initial simplicial complex
+ for a given range of point-mass pairs.
+
+ \tparam InputRange is a model of `Range` with forward iterators,
+ providing input points and point masses through the
+ `PointPMap` and `MassPMap` property maps.
+
+ \param input_range Range of input data.
+ \param point_map A `ReadablePropertyMap` used to access the input points.
+ \param mass_map A `ReadablePropertyMap` used to access the input
+ points' masses.
+ \param sample_size If `sample_size != 0`, the size of the random sample
+ which replaces the exhaustive priority queue.
+ \param use_flip If `true` the edge flipping procedure is used to ensure
+ that every edge can be made collapsible.
+ \param relocation The number of point relocations that are performed
+ between two edge collapses.
+ \param verbose Controls how much console output is produced by
+ the algorithm. The values are 0, 1, or > 1.
+ \param traits The traits class.
+ */
+ template
+ Reconstruction_simplification_2(
+ const InputRange& input_range,
+ PointPMap point_map = PointPMap(),
+ MassPMap mass_map = MassPMap(1),
+ std::size_t sample_size = 0,
+ bool use_flip = true,
+ unsigned int relocation = 0,
+ int verbose = 0,
+ Traits traits = Traits())
+ : m_dt(traits),
+ m_traits(m_dt.geom_traits()),
+ m_ignore(0),
+ m_verbose(verbose),
+ m_mchoice(sample_size),
+ m_use_flip(use_flip),
+ m_alpha(0.5),
+ m_norm_tol(1.0),
+ m_tang_tol(1.0),
+ m_ghost(1.0),
+ m_relocation(relocation),
+ m_bbox_x(0.0),
+ m_bbox_y(0.0),
+ m_bbox_size(1.0),
+ point_pmap(point_map),
+ mass_pmap(mass_map)
+ {
+ initialize(input_range.begin(), input_range.end());
+ }
+
+ /// @}
+
+ /// \name Settting Parameters
+ /// @{
+ /*!
+ If `sample_size == 0`, the simplification is performed using an exhaustive priority queue.
+ If `sample_size` is stricly positive the simplification is performed using a
+ multiple choice approach, ie, a best-choice selection in a random sample of
+ edge collapse operators, of size `sample_size`. A typical value for the sample
+ size is 15, but this value must be enlarged when targeting a very coarse simplification.
+ \param sample_size If `sample_size != 0`, the size of the random sample replaces the priority queue.
+ */
+ void set_random_sample_size(std::size_t sample_size) {
+ m_mchoice = sample_size;
+ }
+
+ /*!
+ Determines how much console output the algorithm generates.
+ If set to a value larger than 0
+ details about the reconstruction process are written to `std::cerr`.
+
+ \param verbose The verbosity level.
+ */
+ void set_verbose(int verbose) {
+ m_verbose = verbose;
+ }
+
+
+ /// \cond SKIP_IN_MANUAL
+ void set_alpha(const FT alpha) {
+ m_alpha = alpha;
+ }
+ /// \endcond
+
+
+ /*!
+ The use_flip parameter determines whether the edge flipping procedure
+ is used for the half-edge collapse.
+ */
+ void set_use_flip(const bool use_flip) {
+ m_use_flip = use_flip;
+ }
+
+
+ /// \cond SKIP_IN_MANUAL
+ void set_norm_tol(const FT norm_tol) {
+ m_norm_tol = norm_tol;
+ }
+
+
+ FT norm_tol() const {
+ return m_norm_tol;
+ }
+
+
+ void set_tang_tol(const FT tang_tol) {
+ m_tang_tol = tang_tol;
+ }
+
+
+ FT tang_tol() const {
+ return m_tang_tol;
+ }
+ /// \endcond
+
+
+ /*!
+ Sets the number of vertex relocations
+ that are performed between two edge collapses.
+ */
+ void set_relocation(unsigned int relocation) {
+ m_relocation = relocation;
+ }
+
+ /// \cond SKIP_IN_MANUAL
+ unsigned int relocation() const {
+ return m_relocation;
+ }
+ /// \endcond
+
+
+ /*!
+ \param relevance The relevance threshold used for filtering the edges.
+ An edge is relevant from the approximation point of view
+ if it is long, covers a large mass (or equivalently the
+ number of points when all masses are equal), and has a
+ small transport cost. This notion is defined as
+ \f$ m(e) * |e|^2 / cost(e) \f$, where \f$ m(e) \f$
+ denotes the mass of the points approximated by the edge,
+ \f$ |e| \f$ denotes the edge length and \f$ cost(e) \f$
+ its approximation error.
+ As the cost is defined by mass time squared distance the
+ relevance is unitless.
+
+ The default value is 0, so that all edges receiving some mass
+ are considered relevant.
+ Setting a large relevance value is used to get robustness to a
+ large amount of outliers.
+ */
+ void set_relevance(const FT relevance) {
+ m_ghost = relevance;
+ m_dt.ghost_factor() = m_ghost;
+ }
+
+
+ /// \cond SKIP_IN_MANUAL
+ FT ghost() {
+ return m_ghost;
+ }
+
+ /// @}
+
+ /// \cond SKIP_IN_MANUAL
+
+ Reconstruction_simplification_2()
+ : m_traits(m_dt.geom_traits())
+ {
+ initialize_parameters();
+ }
+
+
+ ~Reconstruction_simplification_2() {
+ clear();
+ }
+
+ void initialize_parameters() {
+ m_verbose = 0;
+ m_mchoice = 0;
+ m_use_flip = true;
+ m_alpha = FT(0.5);
+ m_norm_tol = FT(1);
+ m_tang_tol = FT(1);
+ m_ghost = FT(1);
+ m_relocation = 0;
+
+ m_bbox_x = FT(0);
+ m_bbox_y = FT(0);
+ m_bbox_size = FT(1);
+
+ m_ignore = 0;
+ }
+
+ //Function if one wants to create a Reconstruction_simplification_2
+ //without yet specifying the input in the constructor.
+ template
+ void initialize(
+ InputIterator start_itr,
+ InputIterator beyond_itr,
+ PointPMap point_map,
+ MassPMap mass_map)
+ {
+ point_pmap = point_map;
+ mass_pmap = mass_map;
+
+ initialize(start_itr, beyond_itr);
+ }
+
+
+ template
+ void initialize(InputIterator start, InputIterator beyond) {
+
+ clear();
+ insert_loose_bbox(m_bbox_x, m_bbox_y, 2 * m_bbox_size);
+ init(start, beyond);
+
+ std::vector m_samples;
+ for (InputIterator it = start; it != beyond; it++) {
+#ifdef CGAL_USE_PROPERTY_MAPS_API_V1
+ Point point = get(point_pmap, it);
+ FT mass = get( mass_pmap, it);
+#else
+ Point point = get(point_pmap, *it);
+ FT mass = get( mass_pmap, *it);
+#endif
+ Sample_* s = new Sample_(point, mass);
+ m_samples.push_back(s);
+ }
+ assign_samples(m_samples.begin(), m_samples.end());
+ }
+
+
+ template
+ Vector random_vec(const FT scale) const
+ {
+ FT dx = -scale + (FT(rand()) / FT(RAND_MAX)) * 2* scale;
+ FT dy = -scale + (FT(rand()) / FT(RAND_MAX)) * 2* scale;
+ return m_traits.construct_vector_2_object()(dx, dy);
+ }
+
+ void clear() {
+ Sample_vector samples;
+ m_dt.collect_all_samples(samples);
+ // Deallocate samples
+ for (Sample_vector_const_iterator s_it = samples.begin();
+ s_it != samples.end(); ++s_it)
+ {
+ delete *s_it;
+ }
+
+ m_dt.clear();
+ m_mindex.clear();
+ }
+
+
+ // INIT //
+ void insert_loose_bbox(const FT x, const FT y, const FT size) {
+ CGAL::Real_timer timer;
+ std::cerr << "insert loose bbox" << "...";
+
+ timer.start();
+ int nb = static_cast(m_dt.number_of_vertices());
+ insert_point(m_traits.construct_point_2_object()(x - size, y - size), true, nb++);
+ insert_point(m_traits.construct_point_2_object()(x - size, y + size), true, nb++);
+ insert_point(m_traits.construct_point_2_object()(x + size, y + size), true, nb++);
+ insert_point(m_traits.construct_point_2_object()(x + size, y - size), true, nb++);
+
+ std::cerr << "done" << " (" << nb << " vertices, "
+ << timer.time() << " s)" << std::endl;
+ }
+
+ template // value_type = Point*
+ void init(Iterator begin, Iterator beyond) {
+ CGAL::Real_timer timer;
+ std::cerr << "init" << "...";
+
+ timer.start();
+ int nb = static_cast(m_dt.number_of_vertices());
+ m_dt.infinite_vertex()->pinned() = true;
+ for (Iterator it = begin; it != beyond; it++) {
+#ifdef CGAL_USE_PROPERTY_MAPS_API_V1
+ Point point = get(point_pmap, it);
+#else
+ Point point = get(point_pmap, *it);
+#endif
+ insert_point(point, false, nb++);
+ }
+
+ std::cerr << "done" << " (" << nb << " vertices, "
+ << timer.time() << " s)"
+ << std::endl;
+ }
+
+ Vertex_handle insert_point(
+ const Point& point, const bool pinned, const int id)
+ {
+ Vertex_handle v = m_dt.insert(point);
+ v->pinned() = pinned;
+ v->id() = id;
+ return v;
+ }
+
+ // ASSIGNMENT //
+
+ void cleanup_assignments() {
+ m_dt.cleanup_assignments();
+ }
+
+ template // value_type = Sample_*
+ void assign_samples(Iterator begin, Iterator end) {
+ CGAL::Real_timer timer;
+ std::cerr << "assign samples" << "...";
+
+ timer.start();
+ m_dt.assign_samples(begin, end);
+ m_dt.reset_all_costs();
+
+ std::cerr << "done" << " (" << timer.time() << " s)" << std::endl;
+ }
+
+ void reassign_samples() {
+ Sample_vector samples;
+ m_dt.collect_all_samples(samples);
+ m_dt.cleanup_assignments();
+ m_dt.assign_samples(samples.begin(), samples.end());
+ m_dt.reset_all_costs();
+ }
+
+ void reassign_samples_around_vertex(Vertex_handle vertex) {
+ Sample_vector samples;
+ m_dt.collect_samples_from_vertex(vertex, samples, true);
+ m_dt.assign_samples(samples.begin(), samples.end());
+
+ Edge_vector hull;
+ m_dt.get_edges_from_star_minus_link(vertex, hull, true);
+ update_cost(hull.begin(), hull.end());
+ }
+
+
+ bool do_collapse(Edge edge) {
+ Vertex_handle s = m_dt.source_vertex(edge);
+ Vertex_handle t = m_dt.target_vertex(edge);
+
+ if (m_verbose > 0) {
+ std::cerr << std::endl << "do collapse " << "("
+ << s->id() << "->" << t->id() << ") ... " << std::endl;
+ }
+
+ Sample_vector samples;
+ m_dt.collect_samples_from_vertex(s, samples, true);
+
+ Edge_vector hull;
+ m_dt.get_edges_from_star_minus_link(s, hull, true);
+
+ if (m_mchoice == 0)
+ remove_stencil_from_pqueue(hull.begin(), hull.end());
+
+ if (m_use_flip)
+ m_dt.make_collapsible(edge, hull.begin(), hull.end(), m_verbose);
+
+ // debug test
+ bool ok = m_dt.check_kernel_test(edge);
+ if (!ok) {
+ std::cerr << "do_collapse: kernel test failed: " << std::endl;
+ return false;
+ }
+ //
+
+ m_dt.collapse(edge, m_verbose);
+
+ m_dt.assign_samples(samples.begin(), samples.end());
+
+ update_cost(hull.begin(), hull.end());
+
+ if (m_mchoice == 0)
+ push_stencil_to_pqueue(hull.begin(), hull.end());
+
+ for (unsigned int i = 0; i < m_relocation; ++i) {
+ relocate_one_ring(hull.begin(), hull.end());
+ }
+
+ if (m_verbose > 0) {
+ std::cerr << "done" << std::endl;
+ }
+
+ return true;
+ }
+
+ bool simulate_collapse(const Edge& edge, Cost_& cost) {
+ bool ok;
+ Vertex_handle s = m_dt.source_vertex(edge);
+ Vertex_handle t = m_dt.target_vertex(edge);
+
+ if (m_verbose > 1) {
+ std::cerr << "simulate collapse " << "("
+ << s->id() << "->" << t->id() << ") ... " << std::endl;
+ }
+
+ Triangulation copy;
+ Edge copy_edge = copy_star(edge, copy);
+ Vertex_handle copy_source = copy.source_vertex(copy_edge);
+
+ if (m_use_flip) {
+ Edge_vector copy_hull;
+ copy.get_edges_from_star_minus_link(copy_source, copy_hull, true);
+ ok = copy.make_collapsible(copy_edge, copy_hull.begin(),
+ copy_hull.end(), m_verbose);
+ if (!ok) {
+ std::cerr << "simulation: failed (make collapsible)"
+ << std::endl;
+ return false;
+ }
+ }
+
+ ok = copy.check_kernel_test(copy_edge);
+ if (!ok) {
+ std::cerr << "simulation: failed (kernel test)" << std::endl;
+ return false;
+ }
+
+ copy.collapse(copy_edge, m_verbose);
+
+ Sample_vector samples;
+ m_dt.collect_samples_from_vertex(s, samples, false);
+
+ backup_samples(samples.begin(), samples.end());
+ copy.assign_samples_brute_force(samples.begin(), samples.end());
+ copy.reset_all_costs();
+ cost = copy.compute_total_cost();
+ restore_samples(samples.begin(), samples.end());
+
+ if (m_verbose > 1) {
+ std::cerr << "done" << std::endl;
+ }
+
+ return true;
+ }
+
+ template // value_type = Sample_*
+ void backup_samples(Iterator begin, Iterator end) const {
+ for (Iterator it = begin; it != end; ++it) {
+ Sample_* sample = *it;
+ sample->backup();
+ }
+ }
+
+ template // value_type = Sample_*
+ void restore_samples(Iterator begin, Iterator end) const {
+ for (Iterator it = begin; it != end; ++it) {
+ Sample_* sample = *it;
+ sample->restore();
+ }
+ }
+
+ // PEDGE //
+
+ bool decimate() {
+ bool ok;
+ Rec_edge_2 pedge;
+ ok = pick_edge(m_mchoice, pedge);
+ if (!ok)
+ return false;
+
+ ok = do_collapse(pedge.edge());
+ if (!ok)
+ return false;
+ return true;
+ }
+
+ bool create_pedge(const Edge& edge, Rec_edge_2& pedge) {
+ Cost_ after_cost;
+ bool ok = simulate_collapse(edge, after_cost);
+ if (!ok)
+ return false;
+
+ bool within_tol = is_within_tol(after_cost);
+ if (!within_tol)
+ return false;
+
+ Vertex_handle source = m_dt.source_vertex(edge);
+ Cost_ before_cost = m_dt.compute_cost_around_vertex(source);
+
+ FT before = before_cost.finalize(m_alpha);
+ FT after = after_cost.finalize(m_alpha);
+ pedge = Rec_edge_2(edge, before, after);
+ return true;
+ }
+
+ bool is_within_tol(const Cost_& cost) const {
+ return cost.max_norm() <= m_norm_tol && cost.max_tang() <= m_tang_tol;
+ }
+
+ // COST //
+
+ void init_cost() {
+ m_dt.reset_all_costs();
+ }
+
+ template // value_type = Edge
+ void update_cost(Iterator begin, Iterator end) {
+ Edge_vector edges;
+ collect_cost_stencil(m_dt, begin, end, edges);
+
+ typename Edge_vector::iterator ei;
+ for (ei = edges.begin(); ei != edges.end(); ++ei) {
+ Edge edge = *ei;
+ m_dt.update_cost(edge);
+ }
+ }
+
+ template // value_type = Edge
+ void collect_cost_stencil(
+ const Triangulation& mesh, Iterator begin, Iterator end,
+ Edge_vector& edges) const
+ {
+ Edge_set done;
+ Edge_list fifo;
+ for (Iterator it = begin; it != end; ++it) {
+ Edge edge = *it;
+ fifo.push_back(edge);
+ done.insert(edge);
+ }
+
+ while (!fifo.empty()) {
+ Edge edge = fifo.front();
+ fifo.pop_front();
+
+ edge = mesh.twin_edge(edge);
+ edges.push_back(edge);
+
+ Edge next = mesh.next_edge(edge);
+ if (done.insert(next).second)
+ fifo.push_back(next);
+
+ Edge prev = mesh.prev_edge(edge);
+ if (done.insert(prev).second)
+ fifo.push_back(prev);
+ }
+ }
+
+ // PQUEUE (MCHOICE or EXHAUSTIVE) //
+
+ bool pick_edge(std::size_t nb, Rec_edge_2& best_pedge) {
+ if (m_dt.number_of_faces() < 2)
+ return false;
+
+ std::size_t ne = 2 * m_dt.tds().number_of_edges();
+ if (nb > ne)
+ nb = ne;
+
+ bool ok;
+ if (nb == 0) {
+ ok = pick_edge_from_pqueue(best_pedge);
+ return ok;
+ }
+ m_mindex.clear();
+
+ if (nb == ne) {
+ ok = pick_edge_brute_force(best_pedge);
+ return ok;
+ }
+
+ ok = pick_edge_randomly(nb, best_pedge);
+ return ok;
+ }
+
+ bool pick_edge_from_pqueue(Rec_edge_2& best_pedge) {
+ if (m_mindex.empty())
+ populate_pqueue();
+ if (m_mindex.empty())
+ return false;
+ best_pedge = *(m_mindex.template get<1>()).begin();
+ (m_mindex.template get<0>()).erase(best_pedge);
+ return true;
+ }
+
+ bool pick_edge_brute_force(Rec_edge_2& best_pedge) {
+ MultiIndex mindex;
+ Finite_edges_iterator ei;
+ for (ei = m_dt.finite_edges_begin(); ei != m_dt.finite_edges_end();
+ ++ei) {
+ Edge edge = *ei;
+ push_to_mindex(edge, mindex);
+
+ edge = m_dt.twin_edge(edge);
+ push_to_mindex(edge, mindex);
+ }
+ if (mindex.empty())
+ return false;
+ best_pedge = *(mindex.template get<1>()).begin();
+ return true;
+ }
+
+ bool pick_edge_randomly(std::size_t nb, Rec_edge_2& best_pedge) {
+ MultiIndex mindex;
+ for (std::size_t i = 0; i < nb; ++i) {
+ Rec_edge_2 pedge;
+ if (random_pedge(pedge))
+ mindex.insert(pedge);
+ }
+ if (mindex.empty())
+ return false;
+ best_pedge = *(mindex.template get<1>()).begin();
+ return true;
+ }
+
+ void populate_pqueue() {
+ Finite_edges_iterator ei;
+ for (ei = m_dt.finite_edges_begin(); ei != m_dt.finite_edges_end();
+ ++ei) {
+ Edge edge = *ei;
+ push_to_mindex(edge, m_mindex);
+
+ edge = m_dt.twin_edge(edge);
+ push_to_mindex(edge, m_mindex);
+ }
+ }
+
+
+ bool push_to_mindex(const Edge& edge, MultiIndex& mindex) {
+ if (m_dt.is_pinned(edge))
+ return false;
+ if (m_dt.is_target_cyclic(edge))
+ return false;
+
+ Rec_edge_2 pedge;
+ bool ok = create_pedge(edge, pedge);
+ if (!ok)
+ return false;
+ mindex.insert(pedge);
+ return true;
+ }
+
+
+
+ bool random_pedge(Rec_edge_2& pedge) {
+ for (unsigned i = 0; i < 10; ++i) {
+ Edge edge = m_dt.random_finite_edge();
+ if (m_dt.is_pinned(edge))
+ continue;
+ if (m_dt.is_target_cyclic(edge))
+ continue;
+ bool ok = create_pedge(edge, pedge);
+ if (ok)
+ return true;
+ }
+ return false;
+ }
+
+ template // value_type = Edge
+ void remove_stencil_from_pqueue(Iterator begin, Iterator end)
+ {
+ if (m_mindex.empty())
+ return;
+
+ Edge_vector edges;
+ collect_pqueue_stencil(m_dt, begin, end, edges);
+
+ typename Edge_vector::const_iterator ei;
+ for (ei = edges.begin(); ei != edges.end(); ++ei) {
+ Edge edge = *ei;
+ (m_mindex.template get<0>()).erase(Rec_edge_2(edge));
+ }
+ }
+
+ template // value_type = Edge
+ void push_stencil_to_pqueue(Iterator begin, Iterator end) {
+ Edge_vector edges;
+ collect_pqueue_stencil(m_dt, begin, end, edges);
+
+ typename Edge_vector::const_iterator ei;
+ for (ei = edges.begin(); ei != edges.end(); ++ei) {
+ Edge edge = *ei;
+ push_to_mindex(edge, m_mindex);
+ }
+ }
+
+ template // value_type = Edge
+ void collect_pqueue_stencil(
+ const Triangulation& mesh, Iterator begin, Iterator end,
+ Edge_vector& edges) const
+ {
+ Vertex_handle_set vertex_set;
+ for (Iterator it = begin; it != end; ++it) {
+ Edge edge = *it;
+ Edge twin = mesh.twin_edge(edge);
+
+ Vertex_handle s = mesh.source_vertex(edge);
+ if (!s->pinned())
+ vertex_set.insert(s);
+
+ Vertex_handle t = mesh.target_vertex(edge);
+ if (!t->pinned())
+ vertex_set.insert(t);
+
+ Vertex_handle f = mesh.opposite_vertex(edge);
+ if (!f->pinned())
+ vertex_set.insert(f);
+
+ Vertex_handle b = mesh.opposite_vertex(twin);
+ if (!b->pinned())
+ vertex_set.insert(b);
+ }
+
+ typename Vertex_handle_set::const_iterator vi;
+ for (vi = vertex_set.begin(); vi != vertex_set.end(); ++vi) {
+ Vertex_handle v = *vi;
+ Edge_circulator ecirc = mesh.incident_edges(v);
+ Edge_circulator eend = ecirc;
+ CGAL_For_all(ecirc, eend)
+ {
+ Edge edge = *ecirc;
+ if (mesh.source_vertex(edge) != v)
+ edge = mesh.twin_edge(edge);
+ edges.push_back(edge);
+ }
+ }
+ }
+
+ // COPY STAR //
+
+ // edge must not be pinned or have cyclic target
+ Edge copy_star(const Edge& edge, Triangulation& copy) {
+ copy.tds().set_dimension(2);
+ copy.infinite_vertex()->pinned() = true;
+
+ // copy vertices
+ Vertex_handle_map cvmap;
+
+ Vertex_handle s = m_dt.source_vertex(edge);
+ Vertex_handle cs = copy.tds().create_vertex();
+ cvmap[s] = copy_vertex(s, cs);
+
+ Vertex_circulator vcirc = m_dt.incident_vertices(s);
+ Vertex_circulator vend = vcirc;
+ CGAL_For_all(vcirc, vend)
+ {
+ Vertex_handle v = vcirc;
+ if (cvmap.find(v) == cvmap.end()) {
+ Vertex_handle cv = copy.tds().create_vertex();
+ cvmap[v] = copy_vertex(v, cv);
+ }
+ }
+
+ // copy faces
+ Face_handle_map cfmap;
+ Face_circulator fcirc = m_dt.incident_faces(s);
+ Face_circulator fend = fcirc;
+ CGAL_For_all(fcirc, fend)
+ {
+ Face_handle f = fcirc;
+ Face_handle cf = copy.tds().create_face();
+ cfmap[f] = copy_face(f, cf, cvmap);
+ }
+
+ // set neighbors
+ fcirc = m_dt.incident_faces(s);
+ fend = fcirc;
+ CGAL_For_all(fcirc, fend)
+ {
+ Face_handle f = fcirc;
+ copy_neighbors(f, s, cvmap, cfmap);
+ }
+
+ // make copy homeomorphic to S^2
+ close_copy_mesh(cs, copy);
+
+ // copy samples surrounding star
+ copy_samples(s, cs, cfmap, copy);
+
+ // get copy of edge
+ Edge copy_edge = get_copy_edge(edge, cvmap, cfmap);
+ return copy_edge;
+ }
+
+ Vertex_handle copy_vertex(Vertex_handle v0, Vertex_handle v1) const {
+ v1->id() = v0->id();
+ v1->set_point(v0->point());
+ v1->pinned() = v0->pinned();
+ v1->set_sample(v0->sample());
+ return v1;
+ }
+
+ Face_handle copy_face(
+ Face_handle f0, Face_handle f1, Vertex_handle_map& vmap) const
+ {
+ for (unsigned i = 0; i < 3; ++i) {
+ Vertex_handle v0i = f0->vertex(i);
+ Vertex_handle v1i = vmap[v0i];
+ f1->set_vertex(i, v1i);
+ v1i->set_face(f1);
+ }
+ return f1;
+ }
+
+ void copy_neighbors(
+ Face_handle f, Vertex_handle v, Vertex_handle_map& vmap,
+ Face_handle_map& fmap) const
+ {
+ int i = f->index(v);
+ Face_handle cf = fmap[f];
+ Vertex_handle cv = vmap[v];
+
+ if (fmap.find(f->neighbor(i)) != fmap.end()) {
+ Face_handle fi = f->neighbor(i);
+ Face_handle cfi = fmap[fi];
+ cf->set_neighbor(i, cfi);
+ }
+
+ for (unsigned j = 0; j < 2; ++j) {
+ i = (i + 1) % 3;
+ Face_handle fi = f->neighbor(i);
+ Face_handle cfi = fmap[fi];
+ cf->set_neighbor(i, cfi);
+ }
+ }
+
+ void close_copy_mesh(Vertex_handle vertex, Triangulation& copy) const {
+ std::vector outer_faces;
+
+ Face_circulator fcirc = copy.incident_faces(vertex);
+ Face_circulator fend = fcirc;
+ CGAL_For_all(fcirc, fend)
+ {
+ Face_handle face = fcirc;
+ int i = face->index(vertex);
+
+ if (face->neighbor(i) != Face_handle())
+ continue;
+
+ Vertex_handle v1 = face->vertex((i + 1) % 3);
+ Vertex_handle v2 = face->vertex((i + 2) % 3);
+
+ Face_handle outer = copy.tds().create_face();
+ outer->set_vertex(0, copy.infinite_vertex());
+ outer->set_vertex(1, v2);
+ outer->set_vertex(2, v1);
+
+ face->set_neighbor(i, outer);
+ outer->set_neighbor(0, face);
+
+ outer_faces.push_back(outer);
+ }
+
+ for (unsigned i = 0; i < outer_faces.size(); ++i) {
+ unsigned j = (i + 1) % outer_faces.size();
+ outer_faces[i]->set_neighbor(2, outer_faces[j]);
+ outer_faces[j]->set_neighbor(1, outer_faces[i]);
+ }
+
+ if (!outer_faces.empty())
+ copy.infinite_vertex()->set_face(outer_faces[0]);
+ }
+
+ void copy_samples(
+ Vertex_handle vertex, Vertex_handle copy_vertex,
+ Face_handle_map& fmap, Triangulation& copy) const
+ {
+ Face_circulator fcirc = m_dt.incident_faces(vertex);
+ Face_circulator fend = fcirc;
+ CGAL_For_all(fcirc, fend)
+ {
+ Face_handle face = fcirc;
+ int index = face->index(vertex);
+ Edge twin = m_dt.twin_edge(Edge(face, index));
+
+ Face_handle copy_face = fmap[face];
+ index = copy_face->index(copy_vertex);
+ Edge copy_twin = copy.twin_edge(Edge(copy_face, index));
+
+ Sample_vector samples;
+ m_dt.collect_samples_from_edge(twin, samples);
+ copy_twin.first->samples(copy_twin.second) = samples;
+ }
+ copy_vertex->set_sample(NULL);
+ }
+
+ Edge get_copy_edge(
+ const Edge& edge, Vertex_handle_map& vmap, Face_handle_map& fmap) const
+ {
+ Face_handle f = edge.first;
+ Vertex_handle v = f->vertex(edge.second);
+
+ Face_handle cf = fmap[f];
+ Vertex_handle cv = vmap[v];
+
+ return Edge(cf, cf->index(cv));
+ }
+
+ // RELOCATION //
+
+ void relocate_one_vertex(Vertex_handle vertex) {
+ std::swap(vertex->point(), vertex->relocated());
+ reassign_samples_around_vertex(vertex);
+ }
+
+ template // value_type = Edge
+ void relocate_one_ring(Iterator begin, Iterator end) {
+ Vertex_handle_set vertices;
+ for (Iterator it = begin; it != end; ++it) {
+ Edge edge = *it;
+ vertices.insert(m_dt.source_vertex(edge));
+ vertices.insert(m_dt.target_vertex(edge));
+ }
+
+ typename Vertex_handle_set::const_iterator vi;
+ for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
+ Vertex_handle v = *vi;
+ if (v->pinned())
+ continue;
+ v->relocated() = compute_relocation(v);
+ }
+
+ for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
+ Vertex_handle v = *vi;
+ if (v->pinned())
+ continue;
+ if (v->point() == v->relocated())
+ continue;
+
+ Edge_vector hull;
+ m_dt.get_edges_from_star_minus_link(v, hull, false);
+ bool ok = m_dt.is_in_kernel(v->relocated(), hull.begin(),
+ hull.end());
+
+ if (ok) {
+ // do relocation
+ FT norm_bef = m_dt.compute_cost_around_vertex(v).norm();
+ relocate_one_vertex(v);
+ FT norm_aft = m_dt.compute_cost_around_vertex(v).norm();
+
+ if (norm_bef < norm_aft) {
+ // undo relocation
+ relocate_one_vertex(v);
+ } else if (m_mchoice == 0) {
+ // update queue
+ hull.clear();
+ m_dt.get_edges_from_star_minus_link(v, hull, true);
+ remove_stencil_from_pqueue(hull.begin(), hull.end());
+ push_stencil_to_pqueue(hull.begin(), hull.end());
+ }
+ }
+ }
+ }
+
+ /// \endcond
+
+
+ /// \cond SKIP_IN_MANUAL
+ Vector compute_gradient(Vertex_handle vertex) const {
+ Vector grad = m_traits.construct_vector_2_object()(FT(0), FT(0));
+ Edge_circulator ecirc = m_dt.incident_edges(vertex);
+ Edge_circulator eend = ecirc;
+ CGAL_For_all(ecirc, eend)
+ {
+ Edge edge = *ecirc;
+ if (m_dt.source_vertex(edge) != vertex)
+ edge = m_dt.twin_edge(edge);
+
+ if (m_dt.get_plan(edge) == 0)
+ grad = m_traits.construct_sum_of_vectors_2_object()(
+ grad, compute_gradient_for_plan0(edge));
+ else
+ grad = m_traits.construct_sum_of_vectors_2_object()(
+ grad, compute_gradient_for_plan1(edge));
+ }
+ return grad;
+ }
+
+ Point compute_relocation(Vertex_handle vertex) const {
+ FT coef = FT(0);
+ Vector rhs = m_traits.construct_vector_2_object()(FT(0), FT(0));
+
+ Edge_circulator ecirc = m_dt.incident_edges(vertex);
+ Edge_circulator eend = ecirc;
+ CGAL_For_all(ecirc, eend)
+ {
+ Edge edge = *ecirc;
+ if (m_dt.source_vertex(edge) != vertex)
+ edge = m_dt.twin_edge(edge);
+
+ if (m_dt.get_plan(edge) == 0)
+ compute_relocation_for_plan0(edge, coef, rhs);
+ else
+ compute_relocation_for_plan1(edge, coef, rhs);
+ }
+ compute_relocation_for_vertex(vertex, coef, rhs);
+
+ if (coef == FT(0))
+ return vertex->point();
+
+ return m_traits.construct_translated_point_2_object()(
+ CGAL::ORIGIN,
+ m_traits.construct_scaled_vector_2_object()(rhs, FT(1) / coef));
+ }
+
+ void compute_relocation_for_vertex(
+ Vertex_handle vertex, FT& coef, Vector& rhs) const
+ {
+ Sample_* sample = vertex->sample();
+ if (sample) {
+ const FT m = sample->mass();
+ const Point& ps = sample->point();
+ rhs = m_traits.construct_sum_of_vectors_2_object()(rhs,
+ m_traits.construct_scaled_vector_2_object()(
+ m_traits.construct_vector_2_object()(CGAL::ORIGIN, ps), m));
+ coef += m;
+ }
+ }
+
+ Vector compute_gradient_for_plan0(const Edge& edge) const {
+ Edge twin = m_dt.twin_edge(edge);
+ const Point& pa = m_dt.source_vertex(edge)->point();
+ const Point& pb = m_dt.target_vertex(edge)->point();
+
+ Sample_vector samples;
+ m_dt.collect_samples_from_edge(edge, samples);
+ m_dt.collect_samples_from_edge(twin, samples);
+
+ Vector grad = m_traits.construct_vector_2_object()(FT(0), FT(0));
+ Sample_vector_const_iterator it;
+ for (it = samples.begin(); it != samples.end(); ++it) {
+ Sample_* sample = *it;
+ const FT m = sample->mass();
+ const Point& ps = sample->point();
+
+ FT Da = m_traits.compute_squared_distance_2_object()(ps, pa);
+ FT Db = m_traits.compute_squared_distance_2_object()(ps, pb);
+ if (Da < Db)
+ grad = m_traits.construct_sum_of_vectors_2_object()(
+ grad,
+ m_traits.construct_scaled_vector_2_object()(
+ m_traits.construct_vector_2_object()(ps, pa), m));
+ }
+ return grad;
+ }
+
+ void compute_relocation_for_plan0(
+ const Edge& edge, FT& coef, Vector& rhs) const
+ {
+ Edge twin = m_dt.twin_edge(edge);
+ const Point& pa = m_dt.source_vertex(edge)->point();
+ const Point& pb = m_dt.target_vertex(edge)->point();
+
+ Sample_vector samples;
+ m_dt.collect_samples_from_edge(edge, samples);
+ m_dt.collect_samples_from_edge(twin, samples);
+
+ Sample_vector_const_iterator it;
+ for (it = samples.begin(); it != samples.end(); ++it) {
+ Sample_* sample = *it;
+ const FT m = sample->mass();
+ const Point& ps = sample->point();
+
+ FT Da = m_traits.compute_squared_distance_2_object()(ps, pa);
+ FT Db = m_traits.compute_squared_distance_2_object()(ps, pb);
+
+ if (Da < Db) {
+ rhs = m_traits.construct_sum_of_vectors_2_object()(rhs,
+ m_traits.construct_scaled_vector_2_object()(
+ m_traits.construct_vector_2_object()(CGAL::ORIGIN, ps), m));
+ coef += m;
+ }
+ }
+ }
+
+ Vector compute_gradient_for_plan1(const Edge& edge) const {
+ //FT M = m_dt.get_mass(edge);
+ const Point& pa = m_dt.source_vertex(edge)->point();
+ const Point& pb = m_dt.target_vertex(edge)->point();
+
+ SQueue queue;
+ m_dt.sort_samples_from_edge(edge, queue);
+
+ //FT start = FT(0);
+ Vector grad = m_traits.construct_vector_2_object()(FT(0), FT(0));
+ while (!queue.empty()) {
+ PSample psample = queue.top();
+ queue.pop();
+
+ const FT m = psample.sample()->mass();
+ const Point& ps = psample.sample()->point();
+
+ // normal + tangnetial
+ const FT coord = psample.priority();
+ Point pf = m_traits.construct_translated_point_2_object()(
+ CGAL::ORIGIN,
+ m_traits.construct_sum_of_vectors_2_object()(
+ m_traits.construct_scaled_vector_2_object()(
+ m_traits.construct_vector_2_object()(CGAL::ORIGIN, pa),
+ 1.0 - coord),
+ m_traits.construct_scaled_vector_2_object()(
+ m_traits.construct_vector_2_object()(CGAL::ORIGIN, pb),
+ coord)));
+ grad = m_traits.construct_sum_of_vectors_2_object()(
+ grad,
+ m_traits.construct_scaled_vector_2_object()(
+ m_traits.construct_vector_2_object()(ps, pf), m * (1.0 - coord)));
+
+ /*
+ // only normal
+ FT bin = m/M;
+ FT center = start + 0.5*bin;
+ Point pc = CGAL::ORIGIN + (1.0-center)*(pa - CGAL::ORIGIN) + center*(pb - CGAL::ORIGIN);
+ start += bin;
+ grad = grad + m*(bin*bin/12.0)*(pa - pb);
+ grad = grad + m*(1.0-center)*(pc - pf);
+ */
+ }
+ return grad;
+ }
+
+ void compute_relocation_for_plan1(
+ const Edge& edge, FT& coef, Vector& rhs) const
+ {
+ //FT M = m_dt.get_mass(edge);
+ const Point& pb = m_dt.target_vertex(edge)->point();
+
+ SQueue queue;
+ m_dt.sort_samples_from_edge(edge, queue);
+
+ //FT start = FT(0);
+ while (!queue.empty()) {
+ PSample psample = queue.top();
+ queue.pop();
+
+ const FT m = psample.sample()->mass();
+ const Point& ps = psample.sample()->point();
+
+ const FT coord = psample.priority();
+ const FT one_minus_coord = 1.0 - coord;
+
+ // normal + tangential
+ coef += m * one_minus_coord * one_minus_coord;
+ rhs = m_traits.construct_sum_of_vectors_2_object()(
+ rhs,
+ m_traits.construct_scaled_vector_2_object()(
+ m_traits.construct_sum_of_vectors_2_object()(
+ m_traits.construct_vector_2_object()(CGAL::ORIGIN, ps),
+ m_traits.construct_scaled_vector_2_object()(
+ m_traits.construct_vector_2_object()(CGAL::ORIGIN, pb), -coord)),
+ m * one_minus_coord));
+
+ /*
+ // only normal
+ FT bin = m/M;
+ FT center = start + 0.5*bin;
+ Point pc = CGAL::ORIGIN + (1.0-center)*(pa - CGAL::ORIGIN) + center*(pb - CGAL::ORIGIN);
+ start += bin;
+ grad = grad + m*(bin*bin/12.0)*(pa - pb);
+ grad = grad + m*(1.0-center)*(pc - pf);
+ */
+
+ /*
+ // only normal
+ FT bin = m/M;
+ FT center = start + 0.5*bin;
+ FT one_minus_center = 1.0 - center;
+ start += bin;
+
+ coef += m*bin*bin/12.0;
+ rhs = rhs + m*(bin*bin/12.0)*(pb - CGAL::ORIGIN);
+
+ coef += m*one_minus_center*(coord - center);
+ rhs = rhs + m*one_minus_center*(coord - center)*(pb - CGAL::ORIGIN);
+ */
+ }
+ }
+
+ void print_stats_debug() const
+ {
+ int nb_solid = 0;
+ int nb_ghost = 0;
+ for (Finite_edges_iterator ei = m_dt.finite_edges_begin();
+ ei != m_dt.finite_edges_end(); ++ei)
+ {
+ Edge edge = *ei;
+ if (m_dt.is_ghost(edge))
+ nb_ghost++;
+ else
+ nb_solid++;
+ }
+
+ std::cerr << "STATS" << std::endl;
+ std::cerr << "# vertices : " << m_dt.number_of_vertices()-4 << std::endl;
+ std::cerr << "# triangles: " << m_dt.number_of_faces() << std::endl;
+ std::cerr << "# edges: " << m_dt.tds().number_of_edges() << std::endl;
+ std::cerr << "# solid: " << nb_solid << std::endl;
+ std::cerr << "# ghost: " << nb_ghost << std::endl;
+ }
+
+
+ /*!
+ Returns the number of vertices present in the reconstructed triangulation.
+ */
+ std::size_t number_of_vertices() const {
+ return m_dt.number_of_vertices() - 4;
+
+ }
+
+ /*!
+ Returns the number of (solid) edges present in the reconstructed triangulation.
+ */
+ int number_of_edges() const {
+ int nb_solid = 0;
+ for (Finite_edges_iterator ei = m_dt.finite_edges_begin();
+ ei != m_dt.finite_edges_end(); ++ei)
+ {
+ Edge edge = *ei;
+ if (m_dt.is_ghost(edge))
+ continue;
+ nb_solid++;
+ }
+ return nb_solid;
+ }
+
+
+ /*!
+ Returns the cost of the (solid) edges present in the
+ reconstructed triangulation.
+ */
+ FT total_edge_cost() const {
+ FT total_cost = 0;
+ for (Finite_edges_iterator ei = m_dt.finite_edges_begin();
+ ei != m_dt.finite_edges_end(); ++ei)
+ {
+ Edge edge = *ei;
+ if (m_dt.is_ghost(edge))
+ continue;
+
+ total_cost += m_dt.get_cost(edge).finalize();
+ }
+ return total_cost;
+ }
+
+ /// \endcond
+
+
+ /// \name Simplification
+ /// You can freely mix calls of the following functions.
+ /// @{
+ /*!
+ Computes a shape consisting of `np` points, reconstructing the input
+ points.
+ \param np The number of points which will be present in the output.
+ */
+ void run_until(std::size_t np) {
+ CGAL::Real_timer timer;
+ std::cerr << "reconstruct until " << np << " V";
+
+ timer.start();
+ std::size_t N = np + 4;
+ std::size_t performed = 0;
+ while (m_dt.number_of_vertices() > N) {
+ bool ok = decimate();
+ if (!ok)
+ break;
+ performed++;
+ }
+
+ std::cerr << " done" << " (" << performed
+ << " iters, " << m_dt.number_of_vertices() - 4 << " V "
+ << timer.time() << " s)"
+ << std::endl;
+ }
+
+ /*!
+ Computes a shape, reconstructing the input, by performing `steps`
+ edge collapse operators on the output simplex.
+ \param steps The number of edge collapse operators to be performed.
+ */
+ void run(const unsigned steps) {
+ CGAL::Real_timer timer;
+ std::cerr << "reconstruct " << steps;
+
+ timer.start();
+ unsigned performed = 0;
+ for (unsigned i = 0; i < steps; ++i) {
+ bool ok = decimate();
+ if (!ok)
+ break;
+ performed++;
+ }
+
+ std::cerr << " done" << " (" << performed << "/"
+ << steps << " iters, " << m_dt.number_of_vertices() - 4
+ << " V, " << timer.time() << " s)"
+ << std::endl;
+ }
+
+
+ /*!
+ Since noise and missing data may prevent the reconstructed shape to have sharp corners well located, the algorithm offers the possibility to automatically relocate points after each edge collapse. The new location of the points is chosen such that the fitting of the output segments to the input points is improved.
+ */
+ void relocate_all_points() {
+ CGAL::Real_timer timer;
+ std::cerr << "relocate all points" << "...";
+
+ timer.start();
+ m_mindex.clear(); // pqueue must be recomputed
+
+ for (Finite_vertices_iterator v = m_dt.finite_vertices_begin();
+ v != m_dt.finite_vertices_end(); ++v) {
+ if (v->pinned())
+ continue;
+ v->relocated() = compute_relocation(v);
+ }
+
+ for (Finite_vertices_iterator v = m_dt.finite_vertices_begin();
+ v != m_dt.finite_vertices_end(); ++v) {
+ if (v->pinned())
+ continue;
+ if (v->point() == v->relocated())
+ continue;
+
+ Edge_vector hull;
+ m_dt.get_edges_from_star_minus_link(v, hull, false);
+ bool ok = m_dt.is_in_kernel(v->relocated(), hull.begin(),
+ hull.end());
+
+ if (ok) {
+ // do relocation
+ FT norm_bef = m_dt.compute_cost_around_vertex(v).norm();
+ relocate_one_vertex(v);
+ FT norm_aft = m_dt.compute_cost_around_vertex(v).norm();
+
+ // undo relocation
+ if (norm_bef < norm_aft)
+ relocate_one_vertex(v);
+ }
+ }
+
+ std::cerr << "done" << " (" << timer.time() << " s)" << std::endl;
+ }
+
+ /// @}
+
+ /// \name Output
+ /// @{
+
+ /*!
+ Writes the points and segments of the output simplex in an indexed format into output iterators.
+ \tparam PointOutputIterator An output iterator with value type
+ \link Reconstruction_simplification_2::Point Point \endlink.
+ \tparam IndexOutputIterator An output iterator with value type
+ `std::size_t`.
+ \tparam IndexPairOutputIterator An output iterator with value type
+ `std::pair`.
+
+ \param points The output iterator for all points.
+ \param isolated_points The output iterator for the indices of isolated points.
+ \param segments The output iterator for the pairs of segment indices.
+ */
+ template <
+ typename PointOutputIterator,
+ typename IndexOutputIterator,
+ typename IndexPairOutputIterator>
+ CGAL::cpp11::tuple<
+ PointOutputIterator,
+ IndexOutputIterator,
+ IndexPairOutputIterator>
+ indexed_output(
+ PointOutputIterator points,
+ IndexOutputIterator isolated_points,
+ IndexPairOutputIterator segments) const
+ {
+ std::vector isolated_points_;
+ std::vector edges;
+
+ list_output (
+ std::back_inserter(isolated_points_), std::back_inserter(edges));
+
+ // vertices_of_edges
+ std::set edge_vertices;
+ for (typename std::vector::iterator it = edges.begin();
+ it != edges.end(); it++) {
+
+ Point a = (*it).source();
+ Point b = (*it).target();
+
+ edge_vertices.insert(a);
+ edge_vertices.insert(b);
+ }
+
+ std::size_t count_points = 0;
+ for (typename std::set::iterator it = edge_vertices.begin();
+ it != edge_vertices.end(); it++) {
+
+ *points++ = *it;
+ ++count_points;
+ }
+
+ for (typename std::vector::iterator it = isolated_points_.begin();
+ it != isolated_points_.end(); it++) {
+
+ *isolated_points++ = count_points;
+ *points++ = *it;
+ ++count_points;
+ }
+
+ for (typename std::vector::iterator it = edges.begin();
+ it != edges.end(); it++) {
+
+ Point const& a = it->source();
+ Point const& b = it->target();
+
+ typename std::set::iterator it_a = edge_vertices.find(a);
+ typename std::set::iterator it_b = edge_vertices.find(b);
+
+ std::size_t pos_a = std::distance(edge_vertices.begin(), it_a);
+ std::size_t pos_b = std::distance(edge_vertices.begin(), it_b);
+
+ *segments++ = std::make_pair(pos_a, pos_b);
+ }
+
+ return CGAL::cpp11::make_tuple(points, isolated_points, segments);
+ }
+
+ /*!
+ Returns the solid edges and vertices present after the reconstruction
+ process finished.
+
+ \details It takes two output iterators, one for storing the
+ isolated points and one for storing the edges of the reconstructed shape.
+
+ \tparam PointOutputIterator An output iterator with value type
+ \link Reconstruction_simplification_2::Point Point \endlink.
+ \tparam SegmentOutputIterator An output iterator with value type
+ \link Reconstruction_simplification_2::Segment Segment \endlink.
+ */
+ template
+ void list_output (PointOutputIterator v_it, SegmentOutputIterator e_it) const
+ {
+ for (Vertex_iterator vi = m_dt.vertices_begin();
+ vi != m_dt.vertices_end(); ++vi)
+ {
+ bool incident_edges_have_sample = false;
+ typename Triangulation::Edge_circulator start = m_dt.incident_edges(vi);
+ typename Triangulation::Edge_circulator cur = start;
+
+ do {
+ if (!m_dt.is_ghost(*cur)) {
+ incident_edges_have_sample = true;
+ break;
+ }
+ ++cur;
+ } while (cur != start);
+
+ if (!incident_edges_have_sample) {
+ if ((*vi).has_sample_assigned()) {
+ Point p = (*vi).point();
+ *v_it = p;
+ v_it++;
+ }
+ }
+ }
+
+ for (Finite_edges_iterator ei = m_dt.finite_edges_begin(); ei != m_dt.finite_edges_end(); ++ei)
+ {
+ Edge edge = *ei;
+ if (m_dt.is_ghost(edge))
+ continue;
+
+ int index = edge.second;
+ Vertex_handle source = edge.first->vertex( (index+1)%3 );
+ Vertex_handle target = edge.first->vertex( (index+2)%3 );
+
+ Segment s = m_traits.construct_segment_2_object()(
+ source->point(), target->point());
+ *e_it = s;
+ e_it++;
+ }
+ }
+ /// \endcond
+
+
+ /// \cond SKIP_IN_MANUAL
+ void extract_tds_output(Triangulation& rt2) const {
+ rt2 = m_dt;
+ //mark vertices
+ for (Vertex_iterator vi = rt2.vertices_begin();
+ vi != rt2.vertices_end(); ++vi)
+ {
+ bool incident_edges_have_sample = false;
+ typename Triangulation::Edge_circulator start = rt2.incident_edges(vi);
+ typename Triangulation::Edge_circulator cur = start;
+
+ do {
+ if (!rt2.is_ghost(*cur)) {
+ incident_edges_have_sample = true;
+ break;
+ }
+ ++cur;
+ } while (cur != start);
+
+ if (!incident_edges_have_sample) {
+ if ((*vi).has_sample_assigned())
+ (*vi).set_relevance(1);
+ }
+ }
+
+ // mark edges
+ for (Finite_edges_iterator ei = rt2.finite_edges_begin(); ei != rt2.finite_edges_end(); ++ei)
+ {
+ Edge edge = *ei;
+ FT relevance = 0;
+ if (!rt2.is_ghost(edge)) {
+ relevance = rt2.get_edge_relevance(edge); // >= 0
+ }
+ edge.first->relevance(edge.second) = relevance;
+ }
+ }
+
+
+ /// \endcond
+ /// @}
+
+};
+}
+
+#endif
diff --git a/Reconstruction_simplification_2/include/CGAL/Reconstruction_triangulation_2.h b/Reconstruction_simplification_2/include/CGAL/Reconstruction_triangulation_2.h
new file mode 100644
index 00000000000..434e463b913
--- /dev/null
+++ b/Reconstruction_simplification_2/include/CGAL/Reconstruction_triangulation_2.h
@@ -0,0 +1,1078 @@
+// Copyright (c) 2014 INRIA Sophia-Antipolis (France), INRIA Lorraine LORIA.
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// 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.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Fernando de Goes, Pierre Alliez, Ivo Vigan, Clément Jamin
+
+#ifndef RECONSTRUCTION_TRIANGULATION_2_H
+#define RECONSTRUCTION_TRIANGULATION_2_H
+
+// local
+#include
+#include
+#include
+#include
+#include
+
+// CGAL
+#include
+#include
+#include
+#include
+
+// boost
+#include
+#include
+#include
+#include
+#include
+
+// STL
+#include