diff --git a/CMakeLists.txt b/CMakeLists.txt
index bac90b2f401e47057d9d9be876ba1e1e65b689a6..2b70fa85e1f592ab7614696e6976269a540da98a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -81,6 +81,7 @@ opt(PLUGINS "Enable post-processing plugins" ${DEFAULT})
 opt(POST "Enable post-processing module (required by GUI)" ${DEFAULT})
 opt(POPPLER "Enable Poppler for displaying PDF documents (experimental)" OFF)
 opt(QT "Enable dummy QT graphical interface proof-of-concept (experimental)" OFF)
+opt(REVOROPT "Enable Revoropt (used for CVT remeshing)" OFF)
 opt(SALOME "Enable Salome routines for CAD healing" ${DEFAULT})
 opt(SGEOM "Enable SGEOM interface to OCC (experimental)" OFF)
 opt(SLEPC "Enable SLEPc eigensolvers (required for conformal compounds)" ${DEFAULT})
@@ -1297,6 +1298,27 @@ if(NOOPT)
   endforeach(FILE)
 endif(NOOPT)
 
+#enable Revoropt and set compile flags for the corresponding plugin
+if(ENABLE_REVOROPT)
+  find_path(EIGEN3_INC "eigen3/Eigen/Dense")
+  if(EIGEN3_INC AND HAVE_MESH AND HAVE_PLUGINS AND HAVE_ANN AND HAVE_BFGS)
+    list(APPEND EXTERNAL_INCLUDES ${EIGEN3_INC} contrib/Revoropt/include)
+    message(STATUS "using contrib/Revoropt")
+    set_config_option(HAVE_REVOROPT "Revoropt")
+    add_definitions(-DUSE_ANN)
+    get_source_file_property(PROP Plugin/CVTRemesh.cpp COMPILE_FLAGS)
+    if(PROP)
+      set_source_files_properties(Plugin/CVTRemesh.cpp PROPERTIES
+                                  COMPILE_FLAGS "${PROP} -std=c++11")
+    else(PROP)
+      set_source_files_properties(Plugin/CVTRemesh.cpp PROPERTIES
+                                  COMPILE_FLAGS "-std=c++11")
+    endif(PROP)
+  else(EIGEN3_INC AND HAVE_MESH AND HAVE_PLUGINS AND HAVE_ANN AND HAVE_BFGS)
+    message(WARNING "Revoropt requires Eigen3, Mesh, Plugins, Ann and BFGS")
+  endif(EIGEN3_INC AND HAVE_MESH AND HAVE_PLUGINS AND HAVE_ANN AND HAVE_BFGS)
+endif(ENABLE_REVOROPT)
+
 list(SORT CONFIG_OPTIONS)
 set(GMSH_CONFIG_OPTIONS "")
 foreach(OPT ${CONFIG_OPTIONS})
diff --git a/Common/GmshConfig.h.in b/Common/GmshConfig.h.in
index 10de2ab6b57309f3116853ca88b196abca375504..325b01a5a02908e024aa86352b384b7296e0a5b8 100644
--- a/Common/GmshConfig.h.in
+++ b/Common/GmshConfig.h.in
@@ -60,6 +60,7 @@
 #cmakedefine HAVE_POST
 #cmakedefine HAVE_POPPLER
 #cmakedefine HAVE_QT
+#cmakedefine HAVE_REVOROPT
 #cmakedefine HAVE_SALOME
 #cmakedefine HAVE_SGEOM
 #cmakedefine HAVE_SLEPC
diff --git a/Fltk/onelabGroup.cpp b/Fltk/onelabGroup.cpp
index d3c1c0957907de5b0ba212f1f4ba73a6bcc4ac2b..2f5e92b5f99cd9eba8ad8227fa02e56fd5e5860e 100644
--- a/Fltk/onelabGroup.cpp
+++ b/Fltk/onelabGroup.cpp
@@ -59,7 +59,7 @@ void onelab_cb(Fl_Widget *w, void *data)
 
   if(action == "refresh"){
     updateGraphs();
-    FlGui::instance()->rebuildTree(false); // FIXME: true would be better
+    FlGui::instance()->rebuildTree(true); // FIXME: true would be better
     return;
   }
 
diff --git a/Plugin/CMakeLists.txt b/Plugin/CMakeLists.txt
index fbace74ab943be9e5fe5e554ccbf08c72e4ddc08..4f3eb01bdd3903e28f7b0d0cd0a5deaed7b44553 100644
--- a/Plugin/CMakeLists.txt
+++ b/Plugin/CMakeLists.txt
@@ -35,6 +35,7 @@ set(SRC
   SimplePartition.cpp Crack.cpp DuplicateBoundaries.cpp
   FaultZone.cpp
   MeshSubEntities.cpp
+  CVTRemesh.cpp
 )
 
 file(GLOB HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h)
diff --git a/Plugin/CVTRemesh.cpp b/Plugin/CVTRemesh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e09877c565f886fee3fda80a8c93934d4ec4daef
--- /dev/null
+++ b/Plugin/CVTRemesh.cpp
@@ -0,0 +1,326 @@
+// Gmsh - Copyright (C) 1997-2014 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to the public mailing list <gmsh@geuz.org>.
+
+#include "GmshConfig.h"
+
+#if defined(HAVE_REVOROPT)
+
+#include "CVTRemesh.h"
+
+#include "Revoropt/Mesh/builder_def.hpp"
+#include "Revoropt/Mesh/sampling_def.hpp"
+#include "Revoropt/Mesh/normals_def.hpp"
+
+#include "Revoropt/RVD/rvd.hpp"
+#include "Revoropt/RVD/rdt.hpp"
+
+#include "Revoropt/CVT/minimizer.hpp"
+
+#include "Revoropt/Solver/alglib_lbfgs.hpp"
+
+#include "GModel.h"
+#include "MTriangle.h"
+#include "discreteFace.h"
+
+#include <vector>
+#include <iostream>
+
+StringXNumber CVTRemeshOptions_Number[] = {
+  {GMSH_FULLRC, "Sites", NULL, 20000.},
+  {GMSH_FULLRC, "Iterations", NULL, 20.},
+  {GMSH_FULLRC, "Anisotropy", NULL, 0.03},
+  {GMSH_FULLRC, "Variable density", NULL, 0.3},
+  {GMSH_FULLRC, "Feature sensitivity", NULL, 5.},
+  {GMSH_FULLRC, "Normal computation radius", NULL, 0.005}
+};
+
+extern "C"
+{
+  GMSH_Plugin *GMSH_RegisterCVTRemeshPlugin()
+  {
+    return new GMSH_CVTRemeshPlugin();
+  }
+}
+
+std::string GMSH_CVTRemeshPlugin::getHelp() const
+{
+  return "Plugin(CVTRemesh) triangulates an input geometry using"
+    "centroïdal Voronoï tesselations. The STL mesh of the geometry"
+    "is generated and randomly sampled. An objective function derived"
+    "from centroïdal Voronoï tesselations is then defined on the"
+    "generated sampling, and optimized through LBFGS to obtain a"
+    "regular sampling of the surface. The triangulation is extracted"
+    "as the restricted Delaunay triangulation of the samples and the"
+    "STL mesh.\n\n"
+    "If `View' < 0, the plugin is run on the current view.\n\n"
+    "Plugin(Triangulate) creates one new view.";
+}
+
+int GMSH_CVTRemeshPlugin::getNbOptions() const
+{
+  return sizeof(CVTRemeshOptions_Number) / sizeof(StringXNumber);
+}
+
+StringXNumber *GMSH_CVTRemeshPlugin::getOption(int iopt)
+{
+  return &CVTRemeshOptions_Number[iopt];
+}
+
+//solver callback
+class SolverCallback {
+
+  public :
+
+    template<typename Data>
+    void operator()( Data* data ) {
+      //Output current iteration data
+      Msg::Info("[CVTRemesh] : iteration %d, objective function value is %f", data->k, data->fx) ;
+    }
+
+} ;
+
+PView *GMSH_CVTRemeshPlugin::execute(PView *v)
+{
+  //TODO normalization
+
+  GModel* m = GModel::current() ;
+
+  std::vector<double> vertices ;
+  std::vector<unsigned int> faces ;
+
+  unsigned int offset = 0 ;
+  for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it) {
+    (*it)->buildSTLTriangulation() ;
+    for(unsigned int i = 0; i < (*it)->stl_vertices.size(); ++i) {
+      GPoint p = (*it)->point((*it)->stl_vertices[i]) ;
+      vertices.push_back(p.x()) ;
+      vertices.push_back(p.y()) ;
+      vertices.push_back(p.z()) ;
+    }
+    for(unsigned int i = 0; i < (*it)->stl_triangles.size(); ++i) {
+      faces.push_back((*it)->stl_triangles[i]+offset) ;
+    }
+    offset += (*it)->stl_vertices.size() ;
+  }
+
+  Revoropt::MeshBuilder<3> mesh ;
+  mesh.swap_vertices(vertices) ;
+  mesh.swap_faces(faces) ;
+
+  double mesh_center[3] ;
+  double mesh_scale ;
+  Revoropt::normalize_mesh(&mesh, mesh_center, &mesh_scale) ;
+
+  double nradius = (double)CVTRemeshOptions_Number[5].def ;
+
+  //normals
+  std::vector<double> normals(3*mesh.vertices_size()) ;
+  Revoropt::full_robust_vertex_normals(&mesh,nradius,normals.data()) ;
+
+  //lifted vertices
+  std::vector<double> lifted_vertices(6*mesh.vertices_size(), 0) ;
+  for(unsigned int vertex = 0; vertex < mesh.vertices_size(); ++vertex) {
+    std::copy( mesh.vertex(vertex),
+               mesh.vertex(vertex)+3,
+               lifted_vertices.data()+6*vertex
+             ) ;
+    std::copy( normals.data()+3*vertex,
+               normals.data()+3*vertex+3,
+               lifted_vertices.data()+6*vertex+3
+             ) ;
+  }
+
+  //setup lifted mesh
+  Revoropt::ROMeshWrapper<3,6> lifted_mesh(
+    lifted_vertices.data(),
+    lifted_vertices.size()/6,
+    &mesh
+  ) ;
+
+  //triangle weight factor
+  double twfactor = (double)CVTRemeshOptions_Number[3].def ;
+
+  //face ratios
+  std::vector<double> triangle_weights(lifted_mesh.faces_size()) ;
+  if(twfactor > 0) {
+    for(unsigned int f = 0; f < lifted_mesh.faces_size(); ++f) {
+      //vertices of the initial triangle
+      const unsigned int* fverts = mesh.face(f) ;
+
+      //positions
+      const double* x[3] ;
+      for(int i=0; i<3; ++i) {
+        x[i] = lifted_mesh.vertex(fverts[i]) ;
+      }
+
+      //ratio
+      double ratio = 1 ;
+
+      //vectors
+      typedef Eigen::Matrix<double,3,1> Vector3 ;
+
+      Eigen::Map<const Vector3> v0(x[0]) ;
+      Eigen::Map<const Vector3> v1(x[1]) ;
+      Eigen::Map<const Vector3> v2(x[2]) ;
+
+      //triangle frame
+      Vector3 U = (v1-v0) ;
+      const double U_len = U.norm() ;
+      if(U_len > 0) {
+        U /= U_len ;
+        Vector3 H = (v2-v0) ;
+        H = H - H.dot(U)*U ;
+        const double H_len = H.norm() ;
+        if(H_len > 0) {
+          //we know that the triangle is not flat
+          H /= H_len ;
+
+          //gradient of the barycentric weights in the triangle
+          Eigen::Matrix<double,3,2> bar_grads ;
+          bar_grads(2,0) = 0 ;
+          bar_grads(2,1) = 1/H_len ;
+
+          //gradient norms of every normal component
+          for(int i = 0; i < 2; ++i) {
+            //reference frame for the vertex
+            Eigen::Map<const Vector3> vi0(x[(i+1)%3]) ;
+            Eigen::Map<const Vector3> vi1(x[(i+2)%3]) ;
+            Eigen::Map<const Vector3> vi2(x[ i     ]) ;
+
+            Vector3 Ui = (vi1-vi0) ;
+            Ui /= Ui.norm() ;
+            Vector3 Hi = (vi2-vi0) ;
+            Hi = Hi - Hi.dot(Ui)*Ui ;
+            const double Hi_invlen = 1/Hi.norm() ;
+            Hi *= Hi_invlen ;
+            bar_grads(i,0) = Hi.dot(U)*Hi_invlen ;
+            bar_grads(i,1) = Hi.dot(H)*Hi_invlen ;
+          }
+
+          //gradient of each component of the normal
+          Eigen::Map<const Vector3> n0(x[0]+3) ;
+          Eigen::Map<const Vector3> n1(x[1]+3) ;
+          Eigen::Map<const Vector3> n2(x[2]+3) ;
+
+          Eigen::Matrix<double,3,2> n_grads = Eigen::Matrix<double,3,2>::Zero() ;
+
+          n_grads = n0*bar_grads.row(0) ;
+          n_grads += n1*bar_grads.row(1) ;
+          n_grads += n2*bar_grads.row(2) ;
+
+          //maximal gradient norm
+          double g_max = n_grads.row(0).dot(n_grads.row(0)) ;
+          double g_other = n_grads.row(1).dot(n_grads.row(1)) ;
+          g_max = g_max > g_other ? g_max : g_other ;
+          g_other = n_grads.row(2).dot(n_grads.row(2)) ;
+          g_max = g_max > g_other ? g_max : g_other ;
+
+          if(g_max == g_max) { //prevent nan
+            ratio += g_max ;
+          }
+        }
+      }
+      triangle_weights[f] = pow(ratio,twfactor) ;
+    }
+  }
+
+  //normal factor
+  double nfactor = (double)CVTRemeshOptions_Number[2].def ; ;
+
+  //weight the normal component by the provided factor
+  for(unsigned int i = 0; i<lifted_mesh.vertices_size(); ++i) {
+    double* v = lifted_vertices.data() + 6*i ;
+    v[3]*= nfactor ;
+    v[4]*= nfactor ;
+    v[5]*= nfactor ;
+  }
+
+  //number of sites
+  unsigned int nsites = (unsigned int)CVTRemeshOptions_Number[0].def ;
+
+  //lifted sites
+  std::vector<double> lifted_sites(6*nsites) ;
+  if(twfactor > 0) {
+    Revoropt::generate_random_sites< Revoropt::ROMesh<3,6> >(
+      &lifted_mesh, nsites, lifted_sites.data(), triangle_weights.data()
+    ) ;
+  } else {
+    Revoropt::generate_random_sites< Revoropt::ROMesh<3,6> >(
+      &lifted_mesh, nsites, lifted_sites.data()
+    ) ;
+  }
+
+  //setup the cvt minimizer
+  Revoropt::CVT::DirectMinimizer< Revoropt::ROMesh<3,6> > cvt ;
+  cvt.set_sites(lifted_sites.data(), nsites) ;
+  cvt.set_mesh(&lifted_mesh) ;
+  if(twfactor > 0) {
+    cvt.set_triangle_weights(triangle_weights.data()) ;
+  }
+
+  //setup the callback
+  SolverCallback callback ;
+
+  //number of iterations
+  unsigned int niter = (unsigned int)CVTRemeshOptions_Number[1].def ; ;
+  unsigned int aniso_niter = std::min<unsigned int>(10,niter) ;
+
+  //solver status
+  int status = 0 ;
+
+  //isotropic iterations
+  if(niter > 10) {
+    aniso_niter = std::max(aniso_niter,niter*10/100) ;
+    cvt.set_anisotropy(1) ;
+    status = cvt.minimize<Revoropt::Solver::AlgLBFGS>(niter-aniso_niter, &callback) ;
+  }
+
+  //anisotropic iterations
+  if(niter > 0) {
+    //tangent space anisotropy
+    double tanisotropy = (double)CVTRemeshOptions_Number[4].def ; ;
+
+    //anisotropic iterations
+    cvt.set_anisotropy(tanisotropy) ;
+    status = cvt.minimize<Revoropt::Solver::AlgLBFGS>(aniso_niter, &callback) ;
+  }
+
+  //rdt
+  std::vector<unsigned int> rdt_triangles ;
+  Revoropt::RDTBuilder< Revoropt::ROMesh<3,6> > build_rdt(rdt_triangles) ;
+  Revoropt::RVD< Revoropt::ROMesh<3,6> > rvd ;
+  rvd.set_sites(lifted_sites.data(), nsites) ;
+  rvd.set_mesh(&lifted_mesh) ;
+  rvd.compute(build_rdt) ;
+
+  GFace* res_face = new discreteFace(m, m->getMaxElementaryNumber(2)+1) ;
+  m->add(res_face) ;
+
+  //scale back and transfer to gmsh
+  std::vector<MVertex*> m_verts(nsites) ;
+  for(unsigned int i = 0; i < nsites; ++i) {
+    m_verts[i] = new MVertex(
+        lifted_sites[6*i  ]*mesh_scale + mesh_center[0],
+        lifted_sites[6*i+1]*mesh_scale + mesh_center[1],
+        lifted_sites[6*i+2]*mesh_scale + mesh_center[2]
+        ) ;
+    res_face->addMeshVertex(m_verts[i]) ;
+  }
+  for(unsigned int i = 0; i < rdt_triangles.size()/3; ++i) {
+    res_face->addTriangle(
+      new MTriangle(
+        m_verts[rdt_triangles[3*i  ]],
+        m_verts[rdt_triangles[3*i+1]],
+        m_verts[rdt_triangles[3*i+2]]
+        )
+    ) ;
+  }
+
+  res_face->setAllElementsVisible(true) ;
+
+  return v ;
+}
+
+#endif
diff --git a/Plugin/CVTRemesh.h b/Plugin/CVTRemesh.h
new file mode 100644
index 0000000000000000000000000000000000000000..41bfd1894cc1c6e0f0e65c8531995a30329b391b
--- /dev/null
+++ b/Plugin/CVTRemesh.h
@@ -0,0 +1,31 @@
+// Gmsh - Copyright (C) 1997-2014 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to the public mailing list <gmsh@geuz.org>.
+
+#ifndef _CVT_REMESH_H_
+#define _CVT_REMESH_H_
+
+#include "Plugin.h"
+
+extern "C"
+{
+  GMSH_Plugin *GMSH_RegisterCVTRemeshPlugin();
+}
+
+class GMSH_CVTRemeshPlugin : public GMSH_PostPlugin
+{
+ public:
+  GMSH_CVTRemeshPlugin(){}
+  std::string getName() const { return "CVTRemesh"; }
+  std::string getShortHelp() const
+  {
+    return "Remesh an object using Centroïdal Voronoï Tesslation";
+  }
+  std::string getHelp() const;
+  int getNbOptions() const;
+  StringXNumber* getOption(int iopt);  
+  PView *execute(PView *);
+};
+
+#endif
diff --git a/Plugin/PluginManager.cpp b/Plugin/PluginManager.cpp
index b9e2508e291245e416a412350c789f40e17e9ef2..9cd3a9e0c5d2091837f2b24cd4a9dfe1e26591c9 100644
--- a/Plugin/PluginManager.cpp
+++ b/Plugin/PluginManager.cpp
@@ -63,6 +63,7 @@
 #include "NewView.h"
 #include "FaultZone.h"
 #include "MeshSubEntities.h"
+#include "CVTRemesh.h"
 
 // for testing purposes only :-)
 #undef HAVE_DLOPEN
@@ -261,6 +262,10 @@ void PluginManager::registerDefaultPlugins()
                       ("DuplicateBoundaries", GMSH_RegisterDuplicateBoundariesPlugin()));
     allPlugins.insert(std::pair<std::string, GMSH_Plugin*>
                       ("MeshSubEntities", GMSH_RegisterMeshSubEntitiesPlugin()));
+#if defined(HAVE_REVOROPT)
+    allPlugins.insert(std::pair<std::string, GMSH_Plugin*>
+                      ("CVTRemesh", GMSH_RegisterCVTRemeshPlugin()));
+#endif
 #if defined(HAVE_TETGEN)
     allPlugins.insert(std::pair<std::string, GMSH_Plugin*>
                       ("Tetrahedralize", GMSH_RegisterTetrahedralizePlugin()));
@@ -336,4 +341,3 @@ void PluginManager::addPlugin(std::string fileName)
   Msg::Info("Loaded Plugin '%s' (%s)", p->getName().c_str(), p->getAuthor().c_str());
 #endif
 }
-
diff --git a/contrib/Revoropt/include/Revoropt/CVT/.gitignore b/contrib/Revoropt/include/Revoropt/CVT/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..fd37e1c2dd9d4edc729987fa2887958785f5728c
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/CVT/.gitignore
@@ -0,0 +1,7 @@
+main.o
+objectview.o
+viewer.o
+utils.os
+cvt
+.qglviewer.xml
+.sconsign.dblite
diff --git a/contrib/Revoropt/include/Revoropt/CVT/computer.hpp b/contrib/Revoropt/include/Revoropt/CVT/computer.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..2fc9fffd6d13f72d48f4604cd48695f25996631f
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/CVT/computer.hpp
@@ -0,0 +1,560 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_CVT_COMPUTER_H_
+#define _REVOROPT_CVT_COMPUTER_H_
+
+#include <stddef.h>
+#include <eigen3/Eigen/Dense>
+
+#include <Revoropt/RVD/rvd.hpp>
+#include <Revoropt/RVD/polygon.hpp>
+#include <Revoropt/Mesh/all_def.hpp>
+#include <Revoropt/Mesh/measure_def.hpp>
+
+namespace Revoropt {
+namespace CVT {
+
+template<typename _Triangulation>
+class BaseComputer {// : public RVD::Action<_Triangulation> {
+
+  public :
+
+  /* Typedefs and template arguments */
+  typedef _Triangulation Triangulation ;
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef Eigen::Matrix<double,Dim,1> Vector ;
+
+  BaseComputer() : g_(NULL), fx_(0),
+                   mesh_(NULL), sites_(NULL),
+                   triangle_weights_(NULL),
+                   mesh_area_(0), mesh_boundary_length_(0),
+                   factor_(1), anisotropy_(1), 
+                   border_anisotropy_(1), border_weight_(0),
+                   tolerance_(0) {
+  }
+
+  /* LBFGS variables to compute */
+  void set_g( double* g ) { g_ = g ; }
+  void set_fx( double val ) { fx_ = val ; }
+  double get_fx() { return fx_ ; }
+
+  /* Mesh and sites */
+  void set_mesh( const Triangulation* mesh ) {
+    mesh_ = mesh ;
+    mesh_area_ = mesh_area(mesh) ;
+    //FIXME
+    //mesh_boundary_length_ = mesh->boundary_length() ;
+  }
+
+  const Triangulation* get_mesh() {
+   return mesh_ ;
+  }
+  void set_sites( const double* sites ) {
+    sites_ = sites ;
+  }
+  void set_triangle_weights( const double* triangle_weights ) {
+    triangle_weights_ = triangle_weights ;
+  }
+
+  /* Parameter setting */
+  void set_factor( double factor ) { 
+    factor_ = factor ; 
+  }
+
+  void set_anisotropy( double anisotropy ) { 
+    anisotropy_ = anisotropy ; 
+  }
+
+  void set_border_anisotropy( double border_anisotropy ) { 
+    border_anisotropy_ = border_anisotropy ; 
+  }
+
+  void set_border_weight( double border_weight ) {
+    border_weight_ = border_weight ;
+  }
+
+  void set_tolerance( double tolerance ) {
+    tolerance_ = tolerance ;
+  }
+
+  protected :
+
+  /* LBFGS variables to compute */
+  double* g_ ;
+  double fx_ ;
+
+  /* Mesh and sites */
+  const Triangulation* mesh_ ;
+  const double* sites_ ;
+  const double* triangle_weights_ ;
+
+  double mesh_area_ ;
+  double mesh_boundary_length_ ;
+
+  /* Parameter variables */
+
+  double factor_ ;
+  double anisotropy_ ;
+  double border_anisotropy_ ;
+  double border_weight_ ;
+  double tolerance_ ;
+} ;
+
+/** Direct computer **/
+
+/* Compute the value and gradient of the direct CVT objective function when
+ * passed to the corresponding RVD computer. The direct CVT objective function
+ * optimizes a set of samples to sample uniformly a mesh. */
+
+template<typename _Triangulation>
+class DirectComputer : public BaseComputer<_Triangulation> {
+
+  public :
+
+  /* Typedefs and template arguments */
+  typedef _Triangulation Triangulation ;
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef Eigen::Matrix<double,Dim,1> Vector ;
+  typedef BaseComputer<Triangulation> Base ;
+
+  typedef RVDEdge<Triangulation> Edge ;
+
+  DirectComputer() : BaseComputer<Triangulation>() {}
+
+  void operator()( unsigned int site,
+                   unsigned int face,
+                   const RVDPolygon<Triangulation>& polygon
+                 ) {
+    //number of vertices of the polygon
+    const unsigned int size = polygon.size() ;
+
+    if(size < 3) return ;
+
+    //send triangles to the triangle backend
+    for(unsigned int i=1; i<size-1; ++i) {
+      triangle_compute( site, 
+                        face, 
+                        polygon[0], 
+                        polygon[i], 
+                        polygon[i+1]
+                      ) ;
+    }
+
+    //std::cout << "after triangle " << fx_ << std::endl ;
+
+    //compute a point inside the polygon for boundary normal computations
+    Vector bar ;
+    bar.setZero() ;
+    for(unsigned int i=0; i<size; ++i) {
+      bar += polygon[i].vertex ;
+    }
+    bar /= size ;
+
+    //send bisector edges to the edge backend
+    for(unsigned int i=0; i<size; ++i) {
+      if(polygon[i].config == Edge::BISECTOR_EDGE) {
+        edge_compute( site, 
+                      face, 
+                      polygon[i], 
+                      polygon[(i+1)%size], 
+                      bar
+                    ) ;
+      }
+
+/* FIXME
+      if(border_weight_ != 0 && mesh_boundary_length_ != 0) {
+        //one dimensional CVT of the boundary of the mesh
+        if(polygon[i].config == RVD::FACE_EDGE) {
+          //get edge index
+          const unsigned int edge_index = polygon[i].combinatorics ;
+          //get the neighbours of the triangle 
+          const unsigned int* triangle_neighbours 
+            = mesh_->face_neighbours(triangle) ;
+          //check whether the edge is a boundary edge
+          if( triangle_neighbours[edge_index] 
+              == Triangulation::NO_NEIGHBOUR
+            ) {
+            border_compute(site, polygon[i], polygon[(i+1)%size]) ;
+          }
+        }
+      }
+*/
+    }
+
+    //std::cout << "after edges " << fx_ << std::endl ;
+  }
+
+  private :
+
+  using Base::factor_ ;
+  using Base::anisotropy_ ;
+  using Base::tolerance_ ;
+  using Base::mesh_area_ ;
+  using Base::fx_ ;
+  using Base::g_ ;
+  using Base::sites_ ;
+  using Base::mesh_ ;
+  using Base::triangle_weights_ ;
+
+  void triangle_compute( const unsigned int site,
+                         const unsigned int triangle,
+                         const RVDEdge<Triangulation>& e1,
+                         const RVDEdge<Triangulation>& e2,
+                         const RVDEdge<Triangulation>& e3
+                       ) {
+    //vertices of the triangle
+    const Vector& c1 = e1.vertex ;
+    const Vector& c2 = e2.vertex ;
+    const Vector& c3 = e3.vertex ;
+  
+    //Triangle basis and area
+    const Vector base = (c2-c1) ;
+    const double base_len = base.norm() ;
+    if(base_len <= tolerance_) return ;
+    const Vector tb1 = base/base_len ;
+  
+    Vector height = (c3-c1)  ;
+    height -= height.dot(tb1)*tb1 ;
+    const double height_len = height.norm() ;
+    if(height_len <= tolerance_) return ;
+    const Vector tb2 = height/height_len ;
+  
+    //triangle weighting
+    const double tweight = triangle_weights_ == NULL ? 
+      1 : 
+      triangle_weights_[triangle] ;
+    const double area = 0.5*base_len*height_len*tweight ;
+  
+    if(area <= tolerance_) return ;
+  
+    //site position
+    Eigen::Map<const Vector> v(sites_ + Dim*site) ;
+  
+    //function value
+  
+    //site vectors
+    Vector sv[3] ;
+    sv[0] = v-c1 ;
+    sv[1] = v-c2 ;
+    sv[2] = v-c3 ;
+  
+    //compute value
+    double local_fx = 0;
+    for (int i = 0; i < 3; ++i) {
+      for (int j = 0; j <= i; ++j) {
+        local_fx += sv[i].dot(sv[j]) ;
+      }
+    }
+    local_fx /= 6 ;
+  
+    //compute gradient
+  
+    //centroid vector
+    Vector g_vect = (c1+c2+c3)/3. ;
+    g_vect = (v-g_vect) ;
+
+    //anisotropy
+    if(anisotropy_ > 1) {
+      //normal component of the face-site vectors
+      Vector normal_component = v-c1 ;
+      normal_component -= normal_component.dot(tb1)*tb1 ;
+      normal_component -= normal_component.dot(tb2)*tb2 ;
+      ////FIXME keep component in normal space ?
+      //for(int i = 3; i < Dim; ++i) {
+      //  normal_component[i] = 0 ;
+      //}
+
+      //value modification
+      local_fx += (anisotropy_*anisotropy_-1)
+                * normal_component.dot(normal_component) ;
+
+      //gradient modification
+      g_vect += (anisotropy_*anisotropy_-1)
+              * normal_component ;
+    }
+  
+    //store result, normalize by mesh area
+    fx_ += (factor_/mesh_area_)*area*local_fx ;
+    Eigen::Map<Vector> grad(g_ + Dim*site) ;
+    grad += factor_*area*2*g_vect/mesh_area_ ;
+  }
+
+  void edge_compute( const unsigned int site,
+                     const unsigned int face,
+                     const RVDEdge<Triangulation>& e1,
+                     const RVDEdge<Triangulation>& e2,
+                     const Vector& inner_point
+                   ) {
+    if(anisotropy_<=1) return ;
+
+    //bisector containing the edge
+    const unsigned int neighbour = e1.combinatorics ;
+
+    //handling edges only once
+    if (neighbour<site) return ;
+
+    //sites
+    Eigen::Map<const Vector> v1(sites_ + Dim*site) ;
+    Eigen::Map<const Vector> v2(sites_ + Dim*neighbour) ;
+
+    //vertices of the edge
+    const Vector& c1 = e1.vertex ;
+    const Vector& c2 = e2.vertex ;
+
+    //edge vector
+    Vector edge = c2-c1 ;
+    double edge_len = edge.norm() ;
+    if(edge_len <= tolerance_) return ;
+    edge /= edge_len ;
+  
+    //triangle weighting
+    const double tweight = triangle_weights_ == NULL ? 
+      1 : 
+      triangle_weights_[face] ;
+    edge_len *= tweight ;
+
+    //edge normal
+    Vector edge_normal = c1-inner_point ;
+    edge_normal -= edge_normal.dot(edge)*edge ;
+    const double edge_normal_len = edge_normal.norm() ;
+    if(edge_normal_len <= tolerance_) return ;
+    edge_normal /= edge_normal_len ;
+
+    const double boundary_speed_denom = edge_normal.dot(v1-v2) ;
+    const double abs_bsd = boundary_speed_denom < 0 ? 
+                           - boundary_speed_denom :
+                           boundary_speed_denom ;
+    if(abs_bsd <= tolerance_) return ;
+
+    //site vector normal component
+    Vector nc1 = v1-c1 ;
+    nc1 -= nc1.dot(edge)*edge ;
+    nc1 -= nc1.dot(edge_normal)*edge_normal ;
+    Vector nc2 = v2-c1 ;
+    nc2 -= nc2.dot(edge)*edge ;
+    nc2 -= nc2.dot(edge_normal)*edge_normal ;
+    ////FIXME keep component in normal space ?
+    //for(int i = 3; i < Dim; ++i) {
+    //  nc1[i] = 0 ;
+    //  nc2[i] = 0 ;
+    //}
+    
+    //gradient common part
+    const double tmp = (anisotropy_*anisotropy_-1)
+                     * (nc1.dot(nc1)-nc2.dot(nc2))
+                     / boundary_speed_denom
+                     * edge_len
+                     //normalize by the mesh area FIXME for triangle weights
+                     * factor_/mesh_area_ ;
+    
+    //edge center
+    const Vector edge_center = 0.5*(c1+c2) ;
+
+    //gradient for v1
+    Eigen::Map<Vector> grad1(g_ + Dim*site) ;
+    grad1 += tmp*(v1-edge_center) ;
+
+    //gradient for v2
+    Eigen::Map<Vector> grad2(g_ + Dim*neighbour) ;
+    grad2 -= tmp*(v2-edge_center) ;
+  }
+
+/* FIXME
+  void border_compute( const unsigned int site,
+                       const RVD::RVDEdge& e1,
+                       const RVD::RVDEdge& e2
+                     ) ;
+
+  void border_vertex_compute( const unsigned int site,
+                              const RVD::RVDVertex& c,
+                              const Vector3d& edge
+                            ) ;
+*/
+} ;
+
+/** Inverse computer **/
+
+/* Compute the value and gradient of the inverse CVT objective function when
+ * passed to the corresponding RVD computer. The inverse CVT objective function
+ * optimizes a mesh such that a given sampling regularly samples it.*/
+
+template<typename _Triangulation>
+class InverseComputer : public BaseComputer<_Triangulation> {
+
+  public :
+
+  /* Typedefs and template arguments */
+  typedef _Triangulation Triangulation ;
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef Eigen::Matrix<double,Dim,1> Vector ;
+  typedef Eigen::Matrix<double,Dim,Dim> Matrix ;
+
+  typedef RVDVertex<Triangulation> Vertex ;
+
+  typedef BaseComputer<Triangulation> Base ;
+
+  InverseComputer() : BaseComputer<Triangulation>() {}
+
+  void operator()( unsigned int site,
+                   unsigned int face,
+                   const RVDPolygon<Triangulation>& polygon
+                 ) {
+    //number of vertices of the polygon
+    const unsigned int size = polygon.size() ;
+
+    if(size < 3) return ;
+
+    //send triangles to the triangle backend
+    for(unsigned int i=1; i<size-1; ++i) {
+      triangle_compute(site, face, polygon[0], polygon[i], polygon[i+1]) ;
+    }
+  }
+
+  void add_mesh_area_gradient() {
+    //add the contribution of the mesh area gradient
+    mesh_area_gradient(mesh_, g_, -fx_ / mesh_area_) ;
+  }
+
+  void finalize() {
+    add_mesh_area_gradient() ;
+  }
+
+  private :
+
+  using Base::factor_ ;
+  using Base::anisotropy_ ;
+  using Base::tolerance_ ;
+  using Base::mesh_area_ ;
+  using Base::fx_ ;
+  using Base::g_ ;
+  using Base::sites_ ;
+  using Base::mesh_ ;
+
+  std::vector<double> area_gradient_ ;
+
+  void triangle_compute( const unsigned int site,
+                         const unsigned int face,
+                         const RVDEdge<Triangulation>& e1,
+                         const RVDEdge<Triangulation>& e2,
+                         const RVDEdge<Triangulation>& e3
+                       ) {
+    //vertices of the triangle
+    const RVDVertex<Triangulation>* c[3] ;
+    c[0] = &e1.vertex ;
+    c[1] = &e2.vertex ;
+    c[2] = &e3.vertex ;
+
+    //normalized edges of the triangle
+    Vector ed[3] ;
+    double ed_len[3] ;
+    for(int i=0; i<3; ++i) {
+      ed[i] = *(c[(i+2)%3]) - *(c[(i+1)%3]) ;
+      ed_len[i] = ed[i].norm() ;
+      if(ed_len[i] <= tolerance_) return ;
+      ed[i] /= ed_len[i] ;
+    }
+
+    //normalized heights of the triangle
+    Vector h[3] ;
+    double h_len[3] ;
+    for(int i=0; i<3; ++i) {
+      h[i] = (ed[(i+1)%3] - (ed[(i+1)%3].dot(ed[i])*ed[i]))*ed_len[(i+1)%3] ;
+      h_len[i] = h[i].norm() ;
+      if(h_len[i] <= tolerance_) return ;
+      h[i] /= h_len[i] ;
+    }
+
+    //area of the triangle
+    double area = 0.5*h_len[0]*ed_len[0] ;
+    if(area <= tolerance_) return ;
+
+    //site
+    Eigen::Map<const Vector> v(sites_ + Dim*site) ;
+
+    //site vectors
+    Vector sv[3] ;
+    for(int i = 0; i < 3; ++i) {
+      sv[i] = v-*(c[i]) ;
+    }
+
+    //unweighted objective function value
+    double local_fx = 0 ;
+    for(int i=0; i<3; ++i) {
+      for(int j=0; j<=i; ++j) {
+        local_fx += sv[i].dot(sv[j]) ;
+      }
+    }
+    local_fx /= 6. ;
+
+    //normal component of the site vector
+    const Vector nv = *(c[0]) - v - v.dot(ed[0])*ed[0] - v.dot(h[0])*h[0] ;
+
+    if(anisotropy_ > 1) {
+      local_fx += (anisotropy_*anisotropy_ - 1)*nv.dot(nv) ;
+    }
+
+    //weighted should add local_fx *= area which is done later to use this
+    //intermediate result for gradient computations.
+
+    //gradient of the objective function
+    Vector vertex_gradient ;
+    const Vector g = *(c[0]) + *(c[1]) + *(c[2]) - 4*v ;
+    for(int i=0; i<3; ++i) {
+      //gradient wrt. the vertex c[i] of the triangle
+
+      //variations of the integrand wrt. c[i]
+      vertex_gradient = *(c[i]) + g ;
+
+      if(anisotropy_ > 1) {
+        vertex_gradient -= 
+          12*(anisotropy_*anisotropy_-1)/h_len[i]*(*(c[(i+1)%3])-v).dot(h[i])*nv ;
+      }
+
+      vertex_gradient *= area/6. ;
+
+      //variation of the triangle area wrt. c[i]
+      vertex_gradient += 0.5*ed_len[i]*h[i]*local_fx ;
+
+      //composing to get the gradient wrt. the mesh vertices
+      //number of mesh vertices involved in this RVD vertex
+      if(c[i]->config() == Vertex::ORIGINAL) {
+        //original vertex of the mesh
+        //grab the portion of the gradient wrt. the mesh vertex
+        Eigen::Map<Vector> vert_g(g_ + Dim*c[i]->combinatorics()[0]) ;
+        vert_g += factor_ * vertex_gradient / mesh_area_ ;
+      } else {
+        //get the number of mesh vertices involved
+        int comb_size = (c[i]->config() == Vertex::FACE_VERTEX) ? 3 : 2 ; 
+
+        //for each vertex in the combinatorics, get the derivative of the RVD
+        //Vertex wrt. the mesh vertex, and compose the derivatives.
+        Matrix diff_compose ;
+        for(int j=0; j<comb_size; ++j) {
+          //get the derivative
+          c[i]->derivative(j, mesh_, sites_, diff_compose.data()) ;
+          //grab the portion of the gradient wrt. the mesh vertex
+          Eigen::Map<Vector> vert_g(g_ + Dim*c[i]->combinatorics()[j]) ;
+          //compose the gradient
+          vert_g += factor_*diff_compose.transpose()*vertex_gradient / mesh_area_ ;
+        }
+      }
+    }
+
+    //finishing the objective function value computation
+    fx_ += factor_ * area * local_fx / mesh_area_ ;
+  }
+} ;
+
+} //end of namespace CVT
+} //end of namespace Revoropt
+
+#endif
+
diff --git a/contrib/Revoropt/include/Revoropt/CVT/minimizer.hpp b/contrib/Revoropt/include/Revoropt/CVT/minimizer.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..88d2754874043e5352ddf75caee3b6a194a3ba2a
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/CVT/minimizer.hpp
@@ -0,0 +1,292 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_CVT_MINIMIZER_H_
+#define _REVOROPT_CVT_MINIMIZER_H_
+
+#include "computer.hpp"
+
+#include <Revoropt/RVD/rvd.hpp>
+#include <Revoropt/Mesh/wrapper_def.hpp>
+
+namespace Revoropt {
+namespace CVT {
+
+/* Minimization of the direct CVT objective function */
+
+template<typename _Mesh>
+class DirectObjFun {
+
+  public :
+  //typedefs and template information
+  typedef _Mesh Mesh ;
+  typedef typename Mesh::Scalar Scalar ;
+  enum { Dim = Mesh::VertexDim } ;
+  typedef ROTriangulationWrapper<
+    Dim, 
+    typename Mesh::Scalar, 
+    Mesh::VertexOffset
+  > Triangulation ;
+
+  /* Initialization */
+
+  DirectObjFun( bool reset_gradient = true ) :
+    reset_gradient_(reset_gradient) {
+  }
+
+  void set_vertices( const Scalar* vertices, unsigned int vertices_size ) {
+    triangulation_.set_vertices(vertices, vertices_size) ;
+    rvd_.set_mesh(&triangulation_) ;
+    computer_.set_mesh(&triangulation_) ;
+  }
+
+  void set_mesh( const Mesh* mesh ) {
+    triangulation_.wrap(mesh) ;
+    rvd_.set_mesh(&triangulation_) ;
+    computer_.set_mesh(&triangulation_) ;
+  }
+
+  void set_sites(const double* sites, unsigned int sites_size ) {
+    sites_ = sites ;
+    sites_size_ = sites_size ;
+    set_inner_sites(sites, sites_size) ;
+  }
+
+  /* Computing the gradient and value of the CVT objective function with respect
+   * to the site positions */
+  
+  /* given the mesh and the set of sites */
+
+  double operator() ( 
+                      const Mesh* mesh,
+                      const double* sites, 
+                      unsigned int site_size,
+                      double* grad
+                    ) {
+    set_mesh(mesh) ;
+    set_sites(sites, site_size) ;
+
+    return operator()(grad) ;
+  }
+
+  /* using the sites and mesh provided using set_mesh and set_sites */
+
+  double operator() ( double* grad ) {
+    if(reset_gradient_) {
+      std::fill(grad, grad+Dim*sites_size_,0) ;
+    }
+    computer_.set_g(grad) ;
+    computer_.set_fx(0) ;
+
+    rvd_.compute(computer_) ;
+
+    return computer_.get_fx() ;
+  }
+
+  /* Solver callback, using the provided variables as site positions */
+  template<typename Data>
+  double operator()( Data* data ) {
+    set_inner_sites(data->x, data->n/Dim) ;
+    return operator()(data->g) ;
+  }
+
+  /* Parameters */
+
+  void set_factor( double factor ) {
+    computer_.set_factor(factor) ;
+  }
+  void set_anisotropy( double anisotropy ) {
+    computer_.set_anisotropy(anisotropy) ;
+  }
+  void set_border_anisotropy( double border_anisotropy ) {
+    computer_.set_border_anisotropy(border_anisotropy) ;
+  }
+  void set_tolerance( double tolerance ) {
+    computer_.set_tolerance(tolerance) ;
+  }
+  void set_border_weight( double border_weight ) {
+    computer_.set_border_weight(border_weight) ;
+  }
+  void set_triangle_weights( const double* triangle_weights) {
+    computer_.set_triangle_weights(triangle_weights) ;
+  }
+
+  protected :
+
+  void set_inner_sites( const double* sites, unsigned int sites_size ) {
+    rvd_.set_sites(sites, sites_size) ;
+    computer_.set_sites(sites) ;
+  }
+
+  //sites
+  const double* sites_ ;
+  unsigned int sites_size_ ;
+
+  //objective function computation
+  DirectComputer<Triangulation> computer_ ;
+  bool reset_gradient_ ;
+
+  //Restricted Voronoï diagram
+  RVD<Triangulation> rvd_ ;
+
+  //Triangulation wrapper
+  Triangulation triangulation_ ;
+
+} ;
+
+template<typename _Mesh>
+class DirectMinimizer : public DirectObjFun<_Mesh> {
+
+  public :
+    enum { Dim = _Mesh::VertexDim } ;
+
+    DirectMinimizer() : DirectObjFun<_Mesh>(true) {}
+  
+    void set_sites(double* sites, unsigned int sites_size ) {
+      var_sites_ = sites ;
+      DirectObjFun<_Mesh>::set_sites(sites, sites_size) ;
+    }
+
+    /* minimization */
+    template<typename Solver>
+    int minimize( unsigned int iterations ) {
+      Solver solver ;
+      return solver.solve(var_sites_, Dim*sites_size_, this, iterations) ;
+    }
+
+    template<typename Solver, typename IterCallback>
+    int minimize( unsigned int iterations, IterCallback* iter_callback ) {
+      Solver solver ;
+      return solver.solve(var_sites_, Dim*sites_size_, this, iterations, iter_callback) ;
+    }
+
+  private :
+
+    using DirectObjFun<_Mesh>::sites_size_ ;
+    double* var_sites_ ;
+} ;
+
+/* LBFGS callback for the minimization of the inverse CVT objective function */
+
+template<typename _Mesh>
+class InverseObjFun {
+
+  public :
+  //typedefs and template information
+  typedef _Mesh Mesh ;
+  enum { Dim = Mesh::VertexDim } ;
+  typedef typename Mesh::Scalar Scalar ;
+  typedef ROTriangulationWrapper<
+    Dim, 
+    typename Mesh::Scalar, 
+    Mesh::VertexOffset
+  > Triangulation ;
+
+  /* Initialization */
+
+  InverseObjFun( bool reset_gradient = true ) : 
+    reset_gradient_(reset_gradient) {
+  }
+
+  void set_vertices( const Scalar* vertices, unsigned int vertices_size ) {
+    triangulation_.set_vertices(vertices, vertices_size) ;
+    rvd_.set_mesh(&triangulation_) ;
+    computer_.set_mesh(&triangulation_) ;
+  }
+
+  void set_mesh( Mesh* mesh ) {
+    triangulation_.wrap(mesh) ;
+    rvd_.set_mesh(&triangulation_) ;
+    computer_.set_mesh(&triangulation_) ;
+  }
+
+  void set_sites( const Scalar* sites, unsigned int sites_size ) {
+    rvd_.set_sites(sites, sites_size) ;
+    computer_.set_sites(sites) ;
+  }
+
+  /* Computing the gradient and value of the CVT objective function with respect
+   * to the mesh vertex positions */
+  
+  /* given the mesh and the set of sites */
+
+  double operator() ( 
+                      const Mesh* mesh,
+                      const Scalar* sites, 
+                      unsigned int site_size,
+                      double* grad
+                    ) {
+    set_mesh(mesh) ;
+    set_sites(sites, site_size) ;
+
+    return operator()(grad) ;
+  }
+
+  /* using the sites and mesh provided using set_mesh, set_sites or set_rvd */
+
+  double operator() ( double* grad ) {
+    if(reset_gradient_) {
+      std::fill(grad, grad+Dim*rvd_.mesh()->vertices_size(),0) ;
+    }
+    computer_.set_g(grad) ;
+    computer_.set_fx(0) ;
+
+    rvd_.compute(computer_) ;
+
+    return computer_.get_fx() ;
+  }
+
+  /* Solver callback using the provided variables as mesh vertex positions */                  
+  template<typename Data>
+  double operator()( Data* data ) {
+    set_vertices(data->x, data->n/Dim) ;
+    return operator()(data->g) ;
+  }
+
+  /* Parameters */
+
+  void set_factor( double factor ) {
+    computer_.set_factor(factor) ;
+  }
+  void set_anisotropy( double anisotropy ) {
+    computer_.set_anisotropy(anisotropy) ;
+  }
+  void set_border_anisotropy( double border_anisotropy ) {
+    computer_.set_border_anisotropy(border_anisotropy) ;
+  }
+  void set_tolerance( double tolerance ) {
+    computer_.set_tolerance(tolerance) ;
+  }
+  void set_border_weight( double border_weight ) {
+    computer_.set_border_weight(border_weight) ;
+  }
+  void set_triangle_weights( const double* triangle_weights) {
+    computer_.set_triangle_weights(triangle_weights) ;
+  }
+
+  private :
+
+  //triangulation wrapper
+  Triangulation triangulation_ ;
+
+  //objective function computation
+  InverseComputer<Triangulation> computer_ ;
+  bool reset_gradient_ ;
+
+  //restricted Voronoï diagram
+  RVD<Triangulation> rvd_ ;
+
+} ;
+
+} //end of namespace CVT
+} //end of namespace Revoropt
+
+#endif
+
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/all_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/all_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3d6fc2bf4d076578f60880491f26b014be82ff89
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/all_def.hpp
@@ -0,0 +1,21 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+
+#ifndef _REVOROPT_MESH_ALL_DEF_HPP_
+#define _REVOROPT_MESH_ALL_DEF_HPP_
+
+#include "base_def.hpp"
+#include "wrapper_def.hpp"
+#include "assembler_def.hpp"
+#include "builder_def.hpp"
+#include "connectivity_def.hpp"
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/all_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/all_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f9ec6cdc80afb382984e0a20cd5ba7498d03e00e
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/all_fwd.hpp
@@ -0,0 +1,21 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+
+#ifndef _REVOROPT_MESH_ALL_FWD_HPP_
+#define _REVOROPT_MESH_ALL_FWD_HPP_
+
+#include "base_fwd.hpp"
+#include "wrapper_fwd.hpp"
+#include "assembler_fwd.hpp"
+#include "builder_fwd.hpp"
+#include "connectivity_fwd.hpp"
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/assembler_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/assembler_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..0f0e45b5d08b0e9300955a82c182f1a25b3ee0bc
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/assembler_def.hpp
@@ -0,0 +1,16 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_ASSEMBLER_DEF_HPP_
+#define _REVOROPT_MESH_ASSEMBLER_DEF_HPP_
+
+#include "assembler_fwd.hpp"
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/assembler_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/assembler_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..964aa0bc708ae66ee3a7f0945ac1d09368e77b92
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/assembler_fwd.hpp
@@ -0,0 +1,305 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_ASSEMBLER_H_
+#define _REVOROPT_MESH_ASSEMBLER_H_
+
+#include "base_def.hpp"
+#include "connectivity_def.hpp"
+
+namespace Revoropt {
+
+/*** Mesh assembler, computes and internally holds face neighbourhoods ***/
+
+/** Read only version **/
+
+/** Fixed face size case **/
+
+template<
+  int _FaceSize = 3, 
+  int _VertexDim = 3, 
+  typename _Scalar = double, 
+  int _VertexOffset = 0
+>
+class ROMeshAssembler : 
+  public ROMesh<_FaceSize,_VertexDim,_Scalar,_VertexOffset>
+{
+  public:
+  
+    typedef ROMesh<_FaceSize,_VertexDim,_Scalar,_VertexOffset> Base ;
+
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = _FaceSize,
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+
+    /** Construction **/
+    ROMeshAssembler() : Base(), c_computer_(this) {} ;
+
+    /*  From raw arrays */
+
+    ROMeshAssembler( const Scalar* vertices, 
+                     unsigned int vertices_size,
+                     const unsigned int* faces,
+                     unsigned int faces_size
+                   ) : Base( vertices, vertices_size, 
+                             faces, NULL, faces_size
+                           ),
+                       c_computer_(this) {
+      c_computer_.compute_connectivity() ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+    };
+
+    /** Changing pointers **/
+
+    /* Vertex pointer */
+    void set_vertices( const Scalar* vertices, 
+                       unsigned int vertices_size
+                     ) {
+      Base::vertices_ = vertices ;
+      Base::vertices_size_ = vertices_size ;
+      Base::set_dirty() ;
+    }
+
+    /* Face pointers */
+    void set_faces( const unsigned int* faces,
+                    unsigned int faces_size
+                  ) {
+      Base::faces_ = faces ;
+      Base::faces_size_ = faces_size ;
+      c_computer_.compute_connectivity() ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+      Base::set_dirty() ;
+    }
+  private:
+
+    ConnectivityComputer<Base> c_computer_ ;
+
+} ;
+
+/** Variable face size case **/
+
+template<
+  int _VertexDim, 
+  typename _Scalar, 
+  int _VertexOffset
+>
+class ROMeshAssembler<Variable,_VertexDim,_Scalar,_VertexOffset> : 
+  public ROMesh<Variable,_VertexDim,_Scalar,_VertexOffset>
+{
+  public:
+  
+    typedef ROMesh<Variable,_VertexDim,_Scalar,_VertexOffset> Base ;
+
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = Variable,
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+
+    /** Construction **/
+    ROMeshAssembler() : Base(), c_computer_(this) {} ;
+
+    /*  From raw arrays */
+
+    ROMeshAssembler( const Scalar* vertices, 
+                     unsigned int vertices_size,
+                     const unsigned int* faces,
+                     const unsigned int* face_ends,
+                     unsigned int faces_size
+                   ) : Base( vertices, vertices_size, 
+                             faces, face_ends, NULL, faces_size
+                           ),
+                       c_computer_(this) {
+      c_computer_.compute_connectivity() ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+    };
+
+    /** Changing pointers **/
+
+    /* Vertex pointer */
+    void set_vertices( const Scalar* vertices, 
+                       unsigned int vertices_size
+                     ) {
+      Base::vertices_ = vertices ;
+      Base::vertices_size_ = vertices_size ;
+      Base::set_dirty() ;
+    }
+
+    /* Face pointers */
+    void set_faces( const unsigned int* faces,
+                    const unsigned int* face_ends,
+                    unsigned int faces_size
+                  ) {
+      Base::faces_ = faces ;
+      Base::face_ends_ = face_ends ;
+      Base::faces_size_ = faces_size ;
+      c_computer_.compute_connectivity() ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+      Base::set_dirty() ;
+    }
+  private:
+
+    ConnectivityComputer<Base> c_computer_ ;
+
+} ;
+
+/** Read write version **/
+
+/** Fixed face size case **/
+
+template<
+  int _FaceSize = 3, 
+  int _VertexDim = 3, 
+  typename _Scalar = double, 
+  int _VertexOffset = 0
+>
+class MeshAssembler : public Mesh<_FaceSize,_VertexDim,_Scalar,_VertexOffset>
+{
+  public:
+  
+    typedef Mesh<_FaceSize,_VertexDim,_Scalar,_VertexOffset> Base ;
+
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = _FaceSize,
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+
+    /** Construction **/
+    MeshAssembler() : Base(), c_computer_(this) {} ;
+
+    /*  From raw arrays */
+
+    MeshAssembler( Scalar* vertices, 
+                   unsigned int vertices_size,
+                   unsigned int* faces,
+                   unsigned int faces_size
+                 ) : Base( vertices, vertices_size, 
+                           faces, NULL, faces_size
+                         ),
+                     c_computer_(this) {
+      c_computer_.compute_connectivity() ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+    };
+
+    /** Changing pointers **/
+
+    /* Vertex pointer */
+    void set_vertices( Scalar* vertices, 
+                       unsigned int vertices_size
+                     ) {
+      Base::vertices_ = vertices ;
+      Base::vertices_size_ = vertices_size ;
+      Base::set_dirty() ;
+    }
+
+    /* Face pointers */
+    void set_faces( unsigned int* faces,
+                    unsigned int faces_size
+                  ) {
+      Base::faces_ = faces ;
+      Base::faces_size_ = faces_size ;
+      c_computer_.compute_connectivity() ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+      Base::set_dirty() ;
+    }
+  private:
+
+    ConnectivityComputer<Base> c_computer_ ;
+
+} ;
+
+/** Variable face size case **/
+
+template<
+  int _VertexDim, 
+  typename _Scalar, 
+  int _VertexOffset
+>
+class MeshAssembler<Variable,_VertexDim,_Scalar,_VertexOffset> : 
+  public Mesh<Variable,_VertexDim,_Scalar,_VertexOffset>
+{
+  public:
+  
+    typedef Mesh<Variable,_VertexDim,_Scalar,_VertexOffset> Base ;
+
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = Variable,
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+
+    /** Construction **/
+    MeshAssembler() : Base(), c_computer_(this) {} ;
+
+    /*  From raw arrays */
+    MeshAssembler( Scalar* vertices, 
+                   unsigned int vertices_size,
+                   unsigned int* faces,
+                   unsigned int* face_ends,
+                   unsigned int faces_size
+                 ) : Base( vertices, vertices_size, 
+                           faces, face_ends, NULL, faces_size
+                         ),
+                     c_computer_(this) {
+      c_computer_.compute_connectivity() ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+    };
+
+    /** Changing pointers **/
+
+    /* Vertex pointer */
+    void set_vertices( Scalar* vertices, 
+                       unsigned int vertices_size
+                     ) {
+      Base::vertices_ = vertices ;
+      Base::vertices_size_ = vertices_size ;
+      Base::set_dirty() ;
+    }
+
+    /* Face pointers */
+    void set_faces( unsigned int* faces,
+                    unsigned int* face_ends,
+                    unsigned int faces_size
+                  ) {
+      Base::faces_ = faces ;
+      Base::face_ends_ = face_ends ;
+      Base::faces_size_ = faces_size ;
+      c_computer_.compute_connectivity() ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+      Base::set_dirty() ;
+    }
+  private:
+
+    ConnectivityComputer<Base> c_computer_ ;
+
+} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/base_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/base_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..e83551721d85fbe8e99eb429c132459bcf4e29cd
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/base_def.hpp
@@ -0,0 +1,66 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_BASE_DEF_HPP_
+#define _REVOROPT_MESH_BASE_DEF_HPP_
+
+#include "base_fwd.hpp"
+
+namespace Revoropt {
+
+/* Basic mesh with constant face size */
+
+template< int FaceSize, int VertexDim, typename Scalar, int VertexOffset >
+unsigned int ROMesh<FaceSize, VertexDim, Scalar, VertexOffset
+                   >::edge_face_index( unsigned int face_index, 
+                                       unsigned int v1, 
+                                       unsigned int v2 
+                                     ) const {
+  //vertices of the face
+  const unsigned int* verts = face(face_index) ;
+  //loop over the vertices
+  for(unsigned int i = 0; i < FaceSize; ++i) {
+    unsigned int vi = verts[ i            ] ;
+    unsigned int vj = verts[(i+1)%FaceSize] ;
+    if(((vi==v1)&&(vj==v2))||((vi==v2)&&(vj==v1))) {
+      return i ;
+    }
+  }
+  //if no return was issued before, the edge was not found
+  return NO_INDEX ;
+}
+
+/* Basic mesh with variable face size */
+
+template< int VertexDim, typename Scalar, int VertexOffset >
+unsigned int ROMesh<Variable, VertexDim, Scalar, VertexOffset
+                   >::edge_face_index( unsigned int face_index, 
+                                       unsigned int v1, 
+                                       unsigned int v2 
+                                     ) const {
+  //vertices of the face
+  const unsigned int* verts = face(face_index) ;
+  //size of the face
+  unsigned int fsize = face_size(face_index) ;
+  //loop over the vertices
+  for(unsigned int i = 0; i < fsize; ++i) {
+    unsigned int vi = verts[ i         ] ;
+    unsigned int vj = verts[(i+1)%fsize] ;
+    if(((vi==v1)&&(vj==v2))||((vi==v2)&&(vj==v1))) {
+      return i ;
+    }
+  }
+  //if no return was issued before, the edge was not found
+  return NO_INDEX ;
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/base_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/base_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f1687ea8b1468833c27b96d2d5eab1cd84d086b6
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/base_fwd.hpp
@@ -0,0 +1,677 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_BASE_FWD_HPP_
+#define _REVOROPT_MESH_BASE_FWD_HPP_
+
+#include <eigen3/Eigen/Dense>
+
+#include <type_traits>
+
+namespace Revoropt {
+
+const int Variable = -1 ;
+
+/***{{{ Forward declarations for friendship ***/
+template<
+  int _VertexDim = 3,
+  typename _Scalar = double,
+  int _VertexOffset = 0
+>
+class ROTriangulationWrapper ;
+
+template<
+  int _FaceSize = 3,
+  int _VertexDim = 3,
+  typename _Scalar = double,
+  int _VertexOffset = 0
+>
+class ROMeshWrapper ;
+
+template<
+  int _FaceSize = 3,
+  int _VertexDim = 3,
+  typename _Scalar = double,
+  int _VertexOffset = 0
+>
+class MeshWrapper ;
+
+template<
+  int _FaceSize = 3,
+  int _VertexDim = 3,
+  typename _Scalar = double
+>
+class MeshBuilder ;
+
+/*
+template<
+  int _VertexDim = 3,
+  typename _Scalar = double,
+  int _VertexOffset = 0
+>
+class TriangulationWrapper ;
+*/
+
+//}}}
+
+/***{{{ Base for all meshes, not for classical use ***/
+
+template<
+  int _VertexDim = 3, /* Dimension of the vertices */
+  typename _Scalar = double, /* Type of coordinates */
+  int _VertexOffset = 0 /* Offset between vertices for easy projection */
+>
+class ROMeshBase
+{
+
+  public:
+
+    friend class ROTriangulationWrapper<_VertexDim,_Scalar,_VertexOffset> ;
+  
+    typedef _Scalar Scalar ;
+
+    enum {
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    typedef Eigen::Matrix<Scalar,VertexDim,1> Vector ;
+
+    static const unsigned int NO_NEIGHBOUR ;
+
+    virtual ~ROMeshBase() {} ;
+
+  /** Protected construction this class is only meant to be derived **/
+  protected:
+    ROMeshBase() : 
+      vertices_(NULL),
+      vertices_size_(0),
+      faces_(NULL),
+      face_neighbourhoods_(NULL),
+      faces_size_(0),
+      dirty_(false)
+    {}
+
+    ROMeshBase( const Scalar* vertices, 
+                unsigned int vertices_size, 
+                const unsigned int* faces, 
+                const unsigned int* face_neighbourhoods,
+                unsigned int faces_size
+              ) : 
+      vertices_(vertices),
+      vertices_size_(vertices_size),
+      faces_(faces),
+      face_neighbourhoods_(face_neighbourhoods),
+      faces_size_(faces_size),
+      dirty_(false)
+    {}
+
+  public:
+
+    /** Vertices **/
+    /* coordinate array of a vertex */
+    const Scalar* vertex( unsigned int vertex_index ) const {
+      return vertices_ + (_VertexDim + _VertexOffset) * vertex_index ;
+    }
+
+    /* number of vertices */
+    unsigned int vertices_size() const {
+      return vertices_size_ ;
+    }
+
+    /* vertex access when no offset */
+    template< typename T = const Scalar* >
+    typename std::enable_if<
+      _VertexOffset == 0 && std::is_same<T,const Scalar*>::value,
+      T
+    >::type vertices() const { 
+      return vertices_ ;
+    }
+
+    /** Data status **/
+    bool is_dirty() const { return dirty_ ; }
+    void set_dirty() { dirty_ = true ; }
+    void set_clean() { dirty_ = false ; }
+
+  protected:
+
+    /** Data pointers **/
+    /* Note : these pointers do not really point to const data, and writable
+     * meshes cast these to non const data. */
+
+    /* vertex array */
+    const Scalar* vertices_ ;
+
+    unsigned int vertices_size_ ;
+
+    /* face array */
+    const unsigned int* faces_ ;
+
+    /* face neighbourhoods */
+    const unsigned int* face_neighbourhoods_ ;
+
+    unsigned int faces_size_ ;
+
+    /** Notification of data change **/
+    bool dirty_ ;
+
+} ;
+
+template<
+  int _VertexDim,
+  typename _Scalar,
+  int _VertexOffset
+>
+const unsigned int ROMeshBase<_VertexDim, _Scalar, _VertexOffset>::NO_NEIGHBOUR = -1 ;
+
+//}}}
+
+/***{{{ Read only mesh, a mesh that cannot be modified ***/
+
+/*{{{ Default template parameters is triangulated 3D mesh. */
+
+template<
+  int _FaceSize = 3, /* Vertices per face, use Variable if non constant */
+  int _VertexDim = 3, /* Dimension of the vertices */
+  typename _Scalar = double, /* Type of coordinates */
+  int _VertexOffset = 0 /* Offset between vertices for easy projection */
+>
+class ROMesh : public ROMeshBase<_VertexDim,_Scalar,_VertexOffset>
+{
+  public:
+
+    friend class ROTriangulationWrapper<_VertexDim,_Scalar,_VertexOffset> ;
+
+    template<
+      int _OtherSize, 
+      int _OtherDim, 
+      typename _OtherScalar, 
+      int _OtherOffset
+    >
+    friend class ROMeshWrapper ;
+
+    template<
+      int _OtherSize, 
+      int _OtherDim, 
+      typename _OtherScalar, 
+      int _OtherOffset
+    >
+    friend class MeshWrapper ;
+
+    template<
+      int _OtherSize, 
+      int _OtherDim, 
+      typename _OtherScalar
+    >
+    friend class MeshBuilder ;
+
+    typedef ROMeshBase<_VertexDim,_Scalar,_VertexOffset> Base ;
+
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = _FaceSize,
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+    static const unsigned int NO_INDEX = -1 ;
+
+  /** Protected construction this class is only meant to be derived **/
+  protected:
+    ROMesh() : Base() {}
+
+    ROMesh( const Scalar* vertices, 
+            unsigned int vertices_size, 
+            const unsigned int* faces, 
+            const unsigned int* face_neighbourhoods,
+            unsigned int faces_size
+          ) : Base( vertices, vertices_size, 
+                    faces, face_neighbourhoods, faces_size
+                  ) {
+    }
+
+  public:
+
+    /** Faces **/
+
+    /* vertex arrays of all faces */
+    const unsigned int* faces() const {
+      return Base::faces_ ;
+    }
+
+    /* position of a face in the face array */
+    unsigned int face_offset( unsigned int face_index ) const {
+      return FaceSize*face_index ;
+    }
+
+    /* vertex index array of a face */
+    const unsigned int* face( unsigned int face_index ) const {
+      return Base::faces_+face_offset(face_index)  ;
+    }
+
+    /* number of vertices of a face */
+    unsigned int face_size( unsigned int face_index ) const {
+      return FaceSize ;
+    }
+
+    /* number of faces */
+    unsigned int faces_size() const {
+      return Base::faces_size_ ;
+    }
+
+    /* number of faces */
+    unsigned int face_vertices_size() const {
+      return FaceSize*Base::faces_size_ ;
+    }
+
+    /** Edges **/
+
+    /* vertices of an edge */
+    void face_edge_vertices( unsigned int face_index, 
+                             unsigned int edge,
+                             unsigned int* v0,
+                             unsigned int* v1
+                           ) const {
+      //size of the face
+      const unsigned int fsize = face_size(face_index) ;
+      //face vertices
+      const unsigned int* fverts = face(face_index) ;
+      //edge vertices
+      *v0 = fverts[ edge         ] ;
+      *v1 = fverts[(edge+1)%fsize] ;
+    }
+
+    unsigned int face_edge_end_vertex( unsigned int face_index, 
+                                       unsigned int edge
+                                     ) const {
+      //edge vertices
+      return face(face_index)[(edge+1)%face_size(face_index)] ;
+    }
+
+    unsigned int face_edge_start_vertex( unsigned int face_index, 
+                                         unsigned int edge
+                                       ) const {
+      //face vertices
+      const unsigned int* fverts = face(face_index) ;
+      return fverts[edge] ;
+    }
+
+    /** Neighbourhoods **/
+
+    /* neighbouring face index array of a face */
+    /* the neighbouring face of index i is aside the given face along the edge
+     * starting at the vertex with index i within the face. */
+    const unsigned int* face_neighbours( unsigned int face_index ) const {
+      return Base::face_neighbourhoods_ + face_offset(face_index)  ;
+    }
+
+    /* index of an edge given by its vertices in a face (NO_INDEX if none) */
+    unsigned int edge_face_index( unsigned int face_index, 
+                                  unsigned int v1, 
+                                  unsigned int v2 
+                                ) const ;
+
+} ;
+
+//}}}
+
+/*{{{ Specialization for meshes with irregular face sizes */
+
+template<
+  int _VertexDim,
+  typename _Scalar,
+  int _VertexOffset
+>
+class ROMesh<Variable,_VertexDim,_Scalar,_VertexOffset> : 
+  public ROMeshBase<_VertexDim,_Scalar,_VertexOffset>
+{
+  public:
+
+    friend class ROTriangulationWrapper<_VertexDim,_Scalar,_VertexOffset> ;
+
+    template<
+      int _OtherSize, 
+      int _OtherDim, 
+      typename _OtherScalar, 
+      int _OtherOffset
+    >
+    friend class ROMeshWrapper ;
+
+    template<
+      int _OtherSize, 
+      int _OtherDim, 
+      typename _OtherScalar, 
+      int _OtherOffset
+    >
+    friend class MeshWrapper ;
+
+    template<
+      int _OtherSize, 
+      int _OtherDim, 
+      typename _OtherScalar
+    >
+    friend class MeshBuilder ;
+
+    typedef ROMeshBase<_VertexDim,_Scalar,_VertexOffset> Base ;
+  
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = Variable,
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+    static const unsigned int NO_INDEX = -1 ;
+
+  /** Protected construction this class is only meant to be derived **/
+  protected:
+    ROMesh() : Base() {}
+
+    ROMesh( const Scalar* vertices, 
+            unsigned int vertices_size, 
+            const unsigned int* faces, 
+            const unsigned int* face_ends, 
+            const unsigned int* face_neighbourhoods,
+            unsigned int faces_size
+          ) : Base( vertices, vertices_size, 
+                    faces, face_neighbourhoods, faces_size
+                  ),
+              face_ends_(face_ends) {
+    }
+
+  public:
+
+    /** Faces **/
+
+    /* vertex arrays of all faces */
+    const unsigned int* faces() const {
+      return Base::faces_ ;
+    }
+    const unsigned int* face_ends() const {
+      return face_ends_ ;
+    }
+
+    /* position of a face in the face array */
+    unsigned int face_offset( unsigned int face_index ) const {
+      return face_index == 0 ? 
+        0 : 
+        face_ends_[face_index-1]  ;
+    }
+
+    /* vertex index array of a face */
+    const unsigned int* face( unsigned int face_index ) const {
+      return  Base::faces_+face_offset(face_index)  ;
+    }
+
+    /* number of vertices of a face */
+    unsigned int face_size( unsigned int face_index ) const {
+      return face_index == 0 ? 
+        face_ends_[face_index] : 
+        face_ends_[face_index] - face_ends_[face_index-1] ;
+    }
+
+    /* number of faces */
+    unsigned int faces_size() const {
+      return Base::faces_size_ ;
+    }
+
+    /* number of faces */
+    unsigned int face_vertices_size() const {
+      return Base::faces_size_ > 0 ?
+        face_ends_[Base::faces_size_-1] :
+        0 ;
+    }
+
+    /** Edges **/
+
+    /* vertices of an edge */
+    void face_edge_vertices( unsigned int face_index, 
+                             unsigned int edge,
+                             unsigned int* v0,
+                             unsigned int* v1
+                           ) const {
+      //size of the face
+      const unsigned int fsize = face_size(face_index) ;
+      //face vertices
+      const unsigned int* fverts = face(face_index) ;
+      //edge vertices
+      *v0 = fverts[ edge         ] ;
+      *v1 = fverts[(edge+1)%fsize] ;
+    }
+
+    unsigned int face_edge_end_vertex( unsigned int face_index, 
+                                       unsigned int edge
+                                     ) const {
+      //size of the face
+      const unsigned int fsize = face_size(face_index) ;
+      //face vertices
+      const unsigned int* fverts = face(face_index) ;
+      //edge vertices
+      return fverts[(edge+1)%fsize] ;
+    }
+
+    unsigned int face_edge_start_vertex( unsigned int face_index, 
+                                         unsigned int edge
+                                       ) const {
+      //face vertices
+      const unsigned int* fverts = face(face_index) ;
+      return fverts[edge] ;
+    }
+
+    /** Neighbourhoods **/
+
+    /* neighbouring face index array of a face */
+    /* the neighbouring face of index i is aside the given face along the edge
+     * starting at the vertex with index i within the face. */
+    const unsigned int* face_neighbours( unsigned int face_index ) const {
+      return Base::face_neighbourhoods_ + face_offset(face_index) ; 
+    }
+
+    /* index of an edge given by its vertices in a face (NO_INDEX if none) */
+    unsigned int edge_face_index( unsigned int face_index, 
+                                  unsigned int v1, 
+                                  unsigned int v2 
+                                ) const ;
+
+  protected:
+
+    /* face positions in face array, null unless variable case */
+    const unsigned int* face_ends_ ;
+
+} ;
+
+//}}}
+
+//}}}
+
+/***{{{ Read Write mesh, allowing the vertices and faces to be modified ***/
+
+/**{{{ Fixed size faces case **/
+
+template<
+  int _FaceSize = 3, 
+  int _VertexDim = 3, 
+  typename _Scalar = double, 
+  int _VertexOffset = 0
+>
+class Mesh : public ROMesh<_FaceSize,_VertexDim,_Scalar,_VertexOffset>
+{
+  public:
+
+    typedef ROMesh<_FaceSize,_VertexDim,_Scalar,_VertexOffset> Base ;
+  
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = _FaceSize,
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+
+  /** Protected construction this class is only meant to be derived **/
+  /* Initialization from const is disabled */
+  protected:
+    Mesh() : Base() {}
+
+    Mesh( Scalar* vertices, 
+          unsigned int vertices_size, 
+          unsigned int* faces, 
+          unsigned int* face_neighbourhoods,
+          unsigned int faces_size
+        ) : Base( vertices, vertices_size, 
+                  faces, face_neighbourhoods, faces_size
+                ) {
+    }
+
+  public:
+  
+    /** Vertices **/
+
+    using Base::vertices ;
+    /* editable full vertex array when offset is 0 */
+    template< typename T = Scalar* >
+    typename std::enable_if<
+      _VertexOffset == 0 && std::is_same<T,Scalar*>::value,
+      T
+    >::type vertices() { 
+      return const_cast<T>(Base::vertices()) ; 
+    }
+
+    using Base::vertex ;
+    /* editable coordinate array of a vertex */
+    Scalar* vertex( unsigned int vertex_index ) {
+      return const_cast<_Scalar*>(Base::vertex(vertex_index)) ;
+    }
+
+    /** Faces **/
+    using Base::faces ;
+    /* editable faces array */
+    unsigned int* faces() {
+      return const_cast<unsigned int*>(Base::faces()) ;
+    }
+
+    using Base::face ;
+    /* editable vertex index array of a face */
+    unsigned int* face( unsigned int face_index ) {
+      return const_cast<unsigned int*>(Base::face(face_index)) ;
+    }
+
+    /** Neighbourhoods **/
+
+    using Base::face_neighbours ;
+    /* editable neighbouring face index array of a face */
+    unsigned int* face_neighbours( unsigned int face_index ) {
+      return const_cast<unsigned int*>(Base::face_neighbours(face_index)) ;
+    }
+} ;
+
+//}}}
+
+/**{{{ Variable size faces case **/
+
+template<
+  int _VertexDim, 
+  typename _Scalar, 
+  int _VertexOffset
+>
+class Mesh<Variable,_VertexDim,_Scalar,_VertexOffset> : 
+  public ROMesh<Variable,_VertexDim,_Scalar,_VertexOffset>
+{
+  public:
+
+    typedef ROMesh<Variable,_VertexDim,_Scalar,_VertexOffset> Base ;
+  
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = Variable,
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+
+  /** Protected construction this class is only meant to be derived **/
+  /* Initialization from const is disabled */
+  protected:
+    Mesh() : Base() {}
+
+    Mesh( Scalar* vertices, 
+          unsigned int vertices_size, 
+          unsigned int* faces, 
+          unsigned int* face_ends, 
+          unsigned int* face_neighbourhoods,
+          unsigned int faces_size
+        ) : Base( vertices, vertices_size, 
+                  faces, face_ends, face_neighbourhoods, faces_size
+                ) {
+    }
+
+  public:
+  
+    /** Vertices **/
+
+    using Base::vertices ;
+    /* editable full vertex array when offset is 0 */
+    template< typename T = Scalar* >
+    typename std::enable_if<
+      _VertexOffset == 0 && std::is_same<T,Scalar*>::value,
+      T
+    >::type vertices() { 
+      return const_cast<T>(Base::vertices()) ; 
+    }
+
+    using Base::vertex ;
+    /* editable coordinate array of a vertex */
+    Scalar* vertex( unsigned int vertex_index ) {
+      return const_cast<_Scalar*>(Base::vertex(vertex_index)) ;
+    }
+
+    /** Faces **/
+    using Base::faces ;
+    unsigned int* faces() {
+      return const_cast<unsigned int*>(Base::faces()) ;
+    }
+
+    using Base::face_ends ;
+    unsigned int* face_ends() {
+      return const_cast<unsigned int*>(Base::face_ends()) ;
+    }
+
+    using Base::face ;
+
+    /* editable vertex index array of a face */
+    unsigned int* face( unsigned int face_index ) {
+      return const_cast<unsigned int*>(Base::face(face_index)) ;
+    }
+
+    /** Neighbourhoods **/
+
+    using Base::face_neighbours ;
+
+    /* editable neighbouring face index array of a face */
+    unsigned int* face_neighbours( unsigned int face_index ) {
+      return const_cast<unsigned int*>(Base::face_neighbours(face_index)) ;
+    }
+} ;
+
+//}}}
+
+//}}}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/builder_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/builder_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..b64869cbda464e41623d890dc471aee4f00fd842
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/builder_def.hpp
@@ -0,0 +1,373 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_BUILDER_DEF_HPP_
+#define _REVOROPT_MESH_BUILDER_DEF_HPP_
+
+#include "builder_fwd.hpp"
+#include "connectivity_def.hpp"
+
+namespace Revoropt {
+
+/*** {{{ constant face size case ***/
+
+template< int _FaceSize, int _VertexDim, typename _Scalar >
+template< int OtherDim, int OtherOffset >
+void MeshBuilder<_FaceSize,_VertexDim,_Scalar>::init( const ROMesh< _FaceSize,
+                                                                    OtherDim,
+                                                                    _Scalar,
+                                                                    OtherOffset
+                                                                  >* rhs) {
+  //vertex copy
+  //automatic projection if dimensions do not match
+  if(OtherDim + OtherOffset == VertexDim) {
+    //linear copy
+    v_vector_.assign( rhs->vertices(),
+                      rhs->vertices()+VertexDim*rhs->vertices_size()
+                    ) ;
+    //reset vertex pointer and size
+    Base::vertices_ = v_vector_.data() ;
+    Base::vertices_size_ = rhs->vertices_size() ;
+  } else {
+    //number of coordinates that can be copied
+    const int copy_size = std::min((int)VertexDim,OtherDim+OtherOffset) ;
+    //resize vertex vector
+    v_vector_.resize(VertexDim*rhs->vertices_size()) ;
+    //reset vertex pointer and size
+    Base::vertices_ = v_vector_.data() ;
+    Base::vertices_size_ = rhs->vertices_size() ;
+    for(unsigned int vertex = 0; vertex < rhs->vertices_size(); ++vertex) {
+      //copy vertex positions
+      std::copy( rhs->vertex(vertex), 
+                 rhs->vertex(vertex)+copy_size,
+                 Base::vertex(vertex)
+               ) ;
+      //add zeros if necessary
+      std::fill( Base::vertex(vertex)+copy_size, 
+                 Base::vertex(vertex)+VertexDim,
+                 0
+               ) ;
+    }
+  }
+  //face copy
+  f_vector_.assign(rhs->faces(),rhs->faces() + rhs->face_vertices_size()) ;
+  //reset face pointer and size
+  Base::faces_ = f_vector_.data() ;
+  Base::faces_size_ = rhs->faces_size() ;
+  //recompute neighbourhoods
+  c_computer_.compute_connectivity() ;
+  Base::face_neighbourhoods_ = c_computer_.data() ;
+  Base::set_dirty() ;
+}
+
+template< int FaceSize, int VertexDim, typename Scalar >
+unsigned int MeshBuilder<FaceSize,VertexDim,Scalar>::push_vertices( 
+  const Scalar* vertices, unsigned int size
+) {
+  //resize the vertex container
+  const unsigned int start = v_vector_.size() ;
+  v_vector_.resize(start + VertexDim*size) ;
+  //copy he provided vertices
+  std::copy(vertices, vertices+VertexDim*size, v_vector_.begin() + start) ;
+  //update pointer and size
+  Base::vertices_ = v_vector_.data() ;
+  Base::vertices_size_ += size ;
+  Base::set_dirty() ;
+  //return a pointer to the first vertex pushed
+  return start/VertexDim ;
+}
+
+template< int FaceSize, int VertexDim, typename Scalar >
+unsigned int MeshBuilder<FaceSize,VertexDim,Scalar>::extend_vertices( 
+  unsigned int size
+) {
+  //resize the vertex container
+  const unsigned int start = v_vector_.size() ;
+  v_vector_.resize(start + VertexDim*size) ;
+  //update pointer and size
+  Base::vertices_ = v_vector_.data() ;
+  Base::vertices_size_ += size ;
+  Base::set_dirty() ;
+  //return a pointer to the first vertex pushed
+  return start/VertexDim ;
+}
+
+template< int FaceSize, int VertexDim, typename Scalar >
+void MeshBuilder<FaceSize,VertexDim,Scalar>::erase_vertices( unsigned int start,
+                                                             unsigned int end
+                                                           ) {
+  if(end > start) {
+    v_vector_.erase( v_vector_.begin() + VertexDim*start,
+                     v_vector_.begin() + VertexDim*end
+                   ) ;
+    Base::vertices_ = v_vector_.data() ;
+    Base::vertices_size_ -= end - start ;
+    Base::set_dirty() ;
+  }
+}
+
+template< int FaceSize, int VertexDim, typename Scalar >
+unsigned int MeshBuilder<FaceSize,VertexDim,Scalar>::push_faces( 
+  const unsigned int* faces, unsigned int size
+) {
+  //starting index of the new faces
+  const unsigned int start = Base::faces_size_ ;
+  //original face vertices size
+  const unsigned int fv_start = FaceSize*start ;
+  //append the faces
+  f_vector_.resize(fv_start + FaceSize*size) ;
+  std::copy(faces, faces + FaceSize*size, f_vector_.begin() + fv_start) ;
+  //reset face pointer and size
+  Base::faces_ = f_vector_.data() ;
+  Base::faces_size_ += size ;
+  //glue the new faces
+  c_computer_.resize(fv_start + FaceSize*size) ;
+  glue_faces(start,start+size) ;
+  Base::set_dirty() ;
+  //return pointer to the first face added
+  return start ;
+}
+
+template< int _FaceSize, int _VertexDim, typename _Scalar >
+unsigned int MeshBuilder<_FaceSize,_VertexDim,_Scalar>::extend_faces( 
+  unsigned int size, unsigned int fsize
+) {
+  assert( (fsize == FaceSize) && 
+          "Trying to extend a fixed face size mesh "
+           "with a face of the wrong size."
+        ) ;
+  //starting index of the new faces
+  const unsigned int start = f_vector_.size() ;
+  //append the faces
+  f_vector_.resize(start + FaceSize*size) ;
+  //reset face pointer and size
+  Base::faces_ = f_vector_.data() ;
+  Base::faces_size_ += size ;
+  //extend neighbourhoods for the new faces
+  c_computer_.resize(start + FaceSize*size) ;
+  Base::face_neighbourhoods_ = c_computer_.data() ;
+  Base::set_dirty() ;
+  //return pointer to the first face added
+  return start/FaceSize ;
+}
+
+template< int _FaceSize, int _VertexDim, typename _Scalar >
+void MeshBuilder<_FaceSize,_VertexDim,_Scalar>::erase_faces( unsigned int start,
+                                                             unsigned int end
+                                                           ) {
+  if(end > start) {
+    c_computer_.erase_neighbourhoods(start,end) ;
+    Base::face_neighbourhoods_ = c_computer_.data() ;
+    f_vector_.erase( f_vector_.begin() + FaceSize*start,
+                     f_vector_.begin() + FaceSize*end
+                   ) ;
+    Base::faces_ = f_vector_.data() ;
+    Base::faces_size_ -= end - start ;
+    Base::set_dirty() ;
+  }
+}
+
+//}}}
+
+/*** {{{ variable face size case ***/
+
+template< int _VertexDim, typename _Scalar >
+template< int OtherDim, int OtherOffset >
+void MeshBuilder<Variable,_VertexDim,_Scalar>::init( const ROMesh< Variable,
+                                                                   OtherDim,
+                                                                   _Scalar,
+                                                                   OtherOffset
+                                                                 >* rhs) {
+  //vertex copy
+  //automatic projection if dimensions do not match
+  if(OtherDim + OtherOffset == VertexDim) {
+    //linear copy
+    v_vector_.assign( rhs->vertices(),
+                      rhs->vertices() + VertexDim*rhs->vertices_size()) ;
+    //reset vertex pointer and size
+    Base::vertices_ = v_vector_.data() ;
+    Base::vertices_size_ = rhs->vertices_size() ;
+  } else {
+    //number of coordinates that can be copied
+    const int copy_size = std::min((int)VertexDim,OtherDim+OtherOffset) ;
+    //resize vertex vector
+    v_vector_.resize(VertexDim*rhs->vertices_size()) ;
+    //reset vertex pointer and size
+    Base::vertices_ = v_vector_.data() ;
+    Base::vertices_size_ = rhs->vertices_size() ;
+    for(unsigned int vertex = 0; vertex < rhs->vertices_size(); ++vertex) {
+      Scalar* v = Base::vertex(vertex) ;
+      //copy vertex positions
+      std::copy( rhs->vertex(vertex), 
+                 rhs->vertex(vertex)+copy_size,
+                 v
+               ) ;
+      //add zeros if necessary
+      std::fill( v+copy_size, 
+                 v+VertexDim,
+                 0
+               ) ;
+    }
+  }
+  //face copy
+  f_vector_.assign(rhs->faces_,rhs->faces_ + rhs->face_vertices_size()) ;
+  fe_vector_.assign(rhs->face_ends_,rhs->face_ends_ + rhs->faces_size_) ;
+  //reset face pointer and size
+  Base::faces_ = f_vector_.data() ;
+  Base::face_ends_ = fe_vector_.data() ;
+  Base::faces_size_ = rhs->faces_size_ ;
+  //recompute neighbourhoods
+  c_computer_.compute_connectivity() ;
+  Base::face_neighbourhoods_ = c_computer_.data() ;
+  Base::set_dirty() ;
+}
+
+template< int _VertexDim, typename _Scalar >
+unsigned int MeshBuilder<Variable,_VertexDim,_Scalar>::push_vertices( 
+  const Scalar* vertices, unsigned int size
+) {
+  //resize the vertex container
+  const unsigned int start = v_vector_.size() ;
+  v_vector_.resize(start + VertexDim*size) ;
+  //copy he provided vertices
+  std::copy(vertices, vertices+VertexDim*size, v_vector_.begin() + start) ;
+  //update pointer and size
+  Base::vertices_ = v_vector_.data() ;
+  Base::vertices_size_ += size ;
+  Base::set_dirty() ;
+  //return a pointer to the first vertex pushed
+  return start/VertexDim ;
+}
+
+template< int _VertexDim, typename _Scalar >
+unsigned int MeshBuilder<Variable,_VertexDim,_Scalar>::extend_vertices( 
+  unsigned int size
+) {
+  //resize the vertex container
+  const unsigned int start = v_vector_.size() ;
+  v_vector_.resize(start + VertexDim*size) ;
+  //update pointer and size
+  Base::vertices_ = v_vector_.data() ;
+  Base::vertices_size_ += size ;
+  Base::set_dirty() ;
+  //return a pointer to the first vertex pushed
+  return start/VertexDim ;
+}
+
+template< int _VertexDim, typename _Scalar >
+void MeshBuilder<Variable,_VertexDim,_Scalar>::erase_vertices( 
+  unsigned int start, unsigned int end
+) {
+  if(end > start) {
+    v_vector_.erase( v_vector_.begin() + VertexDim*start,
+                     v_vector_.begin() + VertexDim*end
+                   ) ;
+    Base::vertices_ = v_vector_.data() ;
+    Base::vertices_size_ -= end - start ;
+    Base::set_dirty() ;
+  }
+}
+
+template< int _VertexDim, typename _Scalar >
+unsigned int MeshBuilder<Variable,_VertexDim,_Scalar>::push_faces( 
+  const unsigned int* faces, const unsigned int* face_ends, unsigned int size
+) {
+  //starting index of the new faces
+  const unsigned int f_start = f_vector_.size() ;
+  const unsigned int fe_start = fe_vector_.size() ;
+  //number of vertex indices to add to the faces
+  const unsigned int fv_size = face_ends[size-1] ;
+  //append the faces and face_ends
+  f_vector_.resize(f_start + fv_size) ;
+  fe_vector_.resize(fe_start + size) ;
+  std::copy(faces, faces + fv_size, f_vector_.begin() + f_start) ;
+  std::copy(face_ends, face_ends + size, fe_vector_.begin() + fe_start) ;
+  //shift the face ends to account for the previous faces of the mesh
+  for(unsigned int f = fe_start; f < fe_start + size; ++f) {
+    fe_vector_[f] += f_start ;
+  }
+  //reset face pointers and size
+  Base::faces_ = f_vector_.data() ;
+  Base::face_ends_ = fe_vector_.data() ;
+  Base::faces_size_ += size ;
+  //glue the new faces
+  c_computer_.resize(f_start + fv_size) ;
+  glue_faces(fe_start,fe_start+size) ;
+  Base::face_neighbourhoods_ = c_computer_.data() ;
+  Base::set_dirty() ;
+  //return the index of the first face
+  return fe_start ;
+}
+
+template< int _VertexDim, typename _Scalar >
+unsigned int MeshBuilder<Variable,_VertexDim,_Scalar>::extend_faces( 
+  unsigned int size, unsigned int face_size
+) {
+  //starting index of the new faces
+  const unsigned int f_start = f_vector_.size() ;
+  const unsigned int fe_start = fe_vector_.size() ;
+  //append the faces and face_ends
+  f_vector_.resize(f_start + size*face_size) ;
+  fe_vector_.resize(fe_start + size) ;
+  //set the face ends of the new faces
+  for(unsigned int face = fe_start; face < fe_vector_.size(); ++face) {
+    fe_vector_[face] = face==0 ? face_size : fe_vector_[face-1]+face_size ;
+    ;
+  }
+  //reset face pointers and size
+  Base::faces_ = f_vector_.data() ;
+  Base::face_ends_ = fe_vector_.data() ;
+  Base::faces_size_ += size ;
+  //allocate neighbours for the new faces
+  c_computer_.resize(f_start + size*face_size) ;
+  Base::face_neighbourhoods_ = c_computer_.data() ;
+  Base::set_dirty() ;
+  //return the index of the first face
+  return fe_start ;
+}
+
+template< int _VertexDim, typename _Scalar >
+void MeshBuilder<Variable,_VertexDim,_Scalar>::erase_faces( unsigned int start, 
+                                                            unsigned int end
+                                                          ) {
+  if(end > start) {
+    //update neighbourhoods
+    c_computer_.erase_neighbourhoods(start,end) ;
+    Base::face_neighbourhoods_ = c_computer_.data() ;
+    //number of face vertices to remove
+    const unsigned int fv_start = Base::face_offset(start) ;
+    const unsigned int fv_end = end < Base::faces_size_ ?
+      Base::face_offset(end) :
+      Base::face_vertices_size()
+    ;
+    //remove faces and face_ends
+    f_vector_.erase( f_vector_.begin() + fv_start,
+                     f_vector_.begin() + fv_end
+                   ) ;
+    fe_vector_.erase( fe_vector_.begin() + start,
+                      fe_vector_.begin() + end
+                    ) ;
+    //shift the face_ends after the end
+    const unsigned int offset = fv_end - fv_start ;
+    for(unsigned int f = start; f < fe_vector_.size(); ++f) {
+      fe_vector_[f] -= offset ;
+    }
+    Base::faces_ = f_vector_.data() ;
+    Base::face_ends_ = fe_vector_.data() ;
+    Base::faces_size_ -= end - start ;
+    Base::set_dirty() ;
+  }
+}
+
+//}}}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/builder_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/builder_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..40d1e2a4985507e196f508e597a40c896f476067
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/builder_fwd.hpp
@@ -0,0 +1,348 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_BUILDER_H_
+#define _REVOROPT_MESH_BUILDER_H_
+
+#include "base_fwd.hpp"
+#include "connectivity_fwd.hpp"
+
+namespace Revoropt {
+
+/*** Mesh builder, managing the vertices and faces arrays ***/
+
+/** Fixed face size case **/
+
+template<
+  int _FaceSize, 
+  int _VertexDim, 
+  typename _Scalar 
+>
+class MeshBuilder : public Mesh<_FaceSize,_VertexDim,_Scalar,0>
+{
+  public:
+  
+    typedef Mesh<_FaceSize,_VertexDim,_Scalar,0> Base ;
+
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = _FaceSize,
+      VertexDim = _VertexDim
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+
+    /** Construction **/
+    MeshBuilder() : Base(), c_computer_(this) {} ;
+
+    void clear() {
+      //vertices
+      v_vector_.resize(0) ;
+      Base::vertices_size_ = 0 ;
+      Base::vertices_ = NULL ;
+      f_vector_.resize(0) ;
+      Base::faces_size_ = 0 ;
+      Base::faces_ = NULL ;
+      Base::face_neighbourhoods_ = NULL ;
+      Base::set_dirty() ;
+    }
+
+    /* init from another mesh */
+    template<int _OtherDim, int _OtherOffset>
+    void init( const ROMesh< _FaceSize,
+                             _OtherDim,
+                             _Scalar,
+                             _OtherOffset
+                           >* rhs
+             ) ;
+
+    template<int _OtherDim, int _OtherOffset>
+    void operator=( const ROMesh< _FaceSize,
+                                  _OtherDim,
+                                  _Scalar,
+                                  _OtherOffset
+                                >& rhs
+                  ) {
+      init(&rhs) ;
+      Base::set_dirty() ;
+    }
+
+    /** Edition **/
+
+
+    /* Adding vertices, returns the index of the first vertex */
+    unsigned int push_vertices( const Scalar* vertices, unsigned int size ) ;
+
+    unsigned int push_vertex( const Scalar* vertex ) {
+      return push_vertices(vertex,1) ;
+    }
+
+    /* Adding unitialized vertices */
+    unsigned int extend_vertices( unsigned int size ) ;
+
+    /* Removing vertices */
+    void erase_vertices( unsigned int start, unsigned int end ) ;
+
+    /* Adding faces, returns the index of the first face added */
+    unsigned int push_faces( const unsigned int* faces, unsigned int size ) ;
+
+
+    unsigned int push_face( const unsigned int* face, unsigned int size = 3 ) {
+      assert(size == 3 && "trying to push a face with wrong size.") ;
+      return push_face(face,1) ;
+    }
+
+    /* Adding unitialized faces */
+    //second argument is provided for compatibility with the variable face
+    //size case, and should always be the face size of the mesh
+    unsigned int extend_faces( unsigned int size, 
+                               unsigned int fsize = FaceSize //compatibility
+                             ) ;
+
+    /* Removing faces */
+    void erase_faces( unsigned int start, unsigned int end ) ;
+
+    /* Connecting faces (connecting twice leads to inconsistancy) */
+
+    void glue_faces( unsigned int start, unsigned int end ) {
+      c_computer_.glue_faces(start,end) ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+      Base::set_dirty() ;
+    }
+
+    void glue_face( unsigned int face ) {
+      glue_faces(face, face+1) ;
+    }
+
+    /* Disconnecting faces (disconnecting twice leads to inconsistancy) */
+
+    void unglue_faces( unsigned int start, unsigned int end ) {
+      c_computer_.unglue_faces(start,end) ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+      Base::set_dirty() ;
+    }
+
+    void unglue_face( unsigned int face ) {
+      unglue_faces(face, face+1) ;
+    }
+
+    /* Swaps */
+    void swap( MeshBuilder& rhs ) {
+      std::swap(Base::vertices_, rhs.vertices_) ;
+      std::swap(Base::vertices_size_, rhs.vertices_size_) ;
+      v_vector_.swap(rhs.v_vector_) ;
+      std::swap(Base::faces_, rhs.faces_) ;
+      std::swap(Base::face_neighbourhoods_, rhs.face_neighbourhoods_) ;
+      std::swap(Base::faces_size_, rhs.faces_size_) ;
+      f_vector_.swap(rhs.f_vector_) ;
+      c_computer_.swap(rhs.c_computer_) ;
+      Base::set_dirty() ;
+    }
+
+    void swap_vertices( std::vector<Scalar>& other  ) {
+      unsigned int size = other.size() / VertexDim ;
+      v_vector_.swap(other) ;
+      Base::vertices_ = v_vector_.data() ;
+      Base::vertices_size_ = size ;
+      Base::set_dirty() ;
+    }
+
+    void swap_faces( std::vector<unsigned int>& other  ) {
+      unsigned int size = other.size() / FaceSize ;
+      f_vector_.swap(other) ;
+      Base::faces_ = f_vector_.data() ;
+      Base::faces_size_ = size ;
+      c_computer_.compute_connectivity() ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+      Base::set_dirty() ;
+    }
+
+  private:
+
+  /* Vertices */
+  std::vector<Scalar> v_vector_ ;
+
+  /* Faces */
+  std::vector<unsigned int> f_vector_ ;
+
+  /* Neighbourhoods */
+  ConnectivityComputer<Base> c_computer_ ;
+
+} ;
+
+/** Variable face size case **/
+
+template<
+  int _VertexDim,
+  typename _Scalar
+>
+class MeshBuilder<Variable,_VertexDim,_Scalar> : 
+  public Mesh<Variable,_VertexDim,_Scalar,0>
+{
+  public:
+  
+    typedef Mesh<Variable,_VertexDim,_Scalar,0> Base ;
+
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = Variable,
+      VertexDim = _VertexDim
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+
+    /** Construction **/
+    MeshBuilder() : Base(), c_computer_(this) {} ;
+
+    void clear() {
+      //vertices
+      v_vector_.resize(0) ;
+      Base::vertices_size_ = 0 ;
+      Base::vertices_ = NULL ;
+      f_vector_.resize(0) ;
+      fe_vector_.resize(0) ;
+      Base::faces_size_ = 0 ;
+      Base::faces_ = NULL ;
+      Base::face_neighbourhoods_ = NULL ;
+      Base::face_ends_ = NULL ;
+      Base::set_dirty() ;
+    }
+
+    /* init from another mesh */
+    template<int _OtherDim, int _OtherOffset>
+    void init( const ROMesh< Variable,
+                             _OtherDim,
+                             Scalar,
+                             _OtherOffset
+                           >* rhs
+             ) ;
+
+    template<int _OtherDim, int _OtherOffset>
+    void operator=( const ROMesh< Variable,
+                                  _OtherDim,
+                                  _Scalar,
+                                  _OtherOffset
+                                >& rhs
+                  ) {
+      init(&rhs) ;
+      Base::set_dirty() ;
+    }
+
+    /** Edition **/
+
+    /* Adding vertices, returns the index of the first vertex */
+    unsigned int push_vertices( const Scalar* vertices, unsigned int size ) ;
+
+    unsigned int push_vertex( const Scalar* vertex ) {
+      return push_vertices(vertex,1) ;
+    }
+
+    /* Adding unitialized vertices */
+    unsigned int extend_vertices( unsigned int size ) ;
+
+    /* Removing vertices */
+    void erase_vertices( unsigned int start, unsigned int end ) ;
+
+    /* Adding faces, returns the index of the first face created */
+    unsigned int push_faces( const unsigned int* faces, 
+                             const unsigned int* face_ends,
+                             unsigned int size 
+                           ) ;
+
+    unsigned int push_face( const unsigned int* face, unsigned int face_size ) {
+      return push_faces(face,&face_size,1) ;
+    }
+
+    /* Adding unitialized faces, all the faces must have the same size */
+    unsigned int extend_faces( unsigned int size, unsigned int face_size ) ;
+
+    /* Removing faces */
+    void erase_faces( unsigned int start, unsigned int end ) ;
+
+    /* Connecting faces (connecting twice leads to inconsistancy) */
+
+    void glue_faces( unsigned int start, unsigned int end ) {
+      c_computer_.glue_faces(start,end) ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+      Base::set_dirty() ;
+    }
+
+    void glue_face( unsigned int face ) {
+      glue_faces(face, face+1) ;
+    }
+
+    /* Disconnecting faces (disconnecting twice leads to inconsistancy) */
+
+    void unglue_faces( unsigned int start, unsigned int end ) {
+      c_computer_.unglue_faces(start,end) ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+      Base::set_dirty() ;
+    }
+
+    void unglue_face( unsigned int face ) {
+      unglue_faces(face, face+1) ;
+    }
+
+    /* Swaps */
+    void swap( MeshBuilder& rhs ) {
+      std::swap(Base::vertices_, rhs.vertices_) ;
+      std::swap(Base::vertices_size_, rhs.vertices_size_) ;
+      v_vector_.swap(rhs.v_vector_) ;
+      std::swap(Base::faces_, rhs.faces_) ;
+      std::swap(Base::face_ends_, rhs.face_ends_) ;
+      std::swap(Base::face_neighbourhoods_, rhs.face_neighbourhoods_) ;
+      std::swap(Base::faces_size_, rhs.faces_size_) ;
+      f_vector_.swap(rhs.f_vector_) ;
+      fe_vector_.swap(rhs.fe_vector_) ;
+      c_computer_.swap(rhs.c_computer_) ;
+      Base::set_dirty() ;
+    }
+
+    void swap_vertices( std::vector<Scalar>& other  ) {
+      unsigned int size = other.size() / VertexDim ;
+      v_vector_.swap(other) ;
+      Base::vertices_ = v_vector_.data() ;
+      Base::vertices_size_ = size ;
+      Base::set_dirty() ;
+    }
+
+    void swap_faces( std::vector<unsigned int>& other_faces,
+                     std::vector<unsigned int>& other_face_ends
+                   ) {
+      unsigned int size = other_face_ends.size() ;
+      f_vector_.swap(other_faces) ;
+      fe_vector_.swap(other_face_ends) ;
+      Base::faces_ = f_vector_.data() ;
+      Base::face_ends_ = fe_vector_.data() ;
+      Base::faces_size_ = size ;
+      c_computer_.compute_connectivity() ;
+      Base::face_neighbourhoods_ = c_computer_.data() ;
+      Base::set_dirty() ;
+    }
+
+  private:
+
+  /* Vertices */
+  std::vector<Scalar> v_vector_ ;
+
+  /* Faces */
+  std::vector<unsigned int> f_vector_ ;
+  std::vector<unsigned int> fe_vector_ ;
+
+  /* Neighbourhoods */
+  ConnectivityComputer<Base> c_computer_ ;
+
+} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/connectivity_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/connectivity_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..342d4c7c98896f8bd7fa45ab6b5f33afd1581bbc
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/connectivity_def.hpp
@@ -0,0 +1,268 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_CONNECTIVITY_DEF_HPP_
+#define _REVOROPT_MESH_CONNECTIVITY_DEF_HPP_
+
+#include "connectivity_fwd.hpp"
+
+namespace Revoropt {
+
+/***{{{ Connectivity computer ***/
+
+template<typename MeshType>
+void ConnectivityComputer<MeshType>::glue_face( unsigned int face_index ) {
+  //number of edges of the face
+  const unsigned int face_size = mesh_->face_size(face_index) ;
+  //vertex indices of the face
+  const unsigned int* face_vertices = mesh_->face(face_index) ;
+
+  //iterate on edges
+  for(unsigned int edge_index = 0; edge_index<face_size; ++edge_index) {
+    //vertices of the edge
+    const unsigned int v0 = face_vertices[ edge_index             ] ;
+    const unsigned int v1 = face_vertices[(edge_index+1)%face_size] ;
+
+    //build the edge
+    EdgeKey edge(v0, v1) ;
+
+    //info relative to this edge
+    EdgeInfo edge_info(face_index,edge_index) ;
+
+    //try to insert the edge in the border edges
+    bedge_iterator it = border_edges_.find(edge) ;
+
+    //connect the triangles if an other edge was already present
+    if(it != border_edges_.end()) {
+      //the edge is a border edge, connect the triangles
+      //index of the neighbouring face
+      const unsigned int n_face_index = it->second.first ;
+      //edge index of the current edge in the neighbouring face
+      const unsigned int n_edge_index = it->second.second ;
+      //assign the neighbour of the current face
+      face_neighbours(face_index)[edge_index] = n_face_index ;
+      //assign the neighbour of the neighbouring face
+      face_neighbours(n_face_index)[n_edge_index] = face_index ;
+      //delete the edge from border edges
+      border_edges_.erase(it) ;
+    } else {
+      border_edges_[edge] = edge_info ;
+      //assign the edge as a border edge 
+      face_neighbours(face_index)[edge_index] = NO_NEIGHBOUR ;
+    }
+  }
+}
+
+template<typename MeshType>
+void ConnectivityComputer<MeshType>::glue_faces( unsigned int face_start,
+                                                 unsigned int face_end
+                                               ) {
+  //iterate over the faces to glue
+  for( unsigned int face_index = face_start; 
+       face_index < face_end; 
+       ++face_index
+     ) {
+    //glue the face
+    glue_face(face_index) ;
+  }
+}
+
+template<typename MeshType>
+void ConnectivityComputer<MeshType>::unglue_face( unsigned int face_index ) {
+  //number of edges of the face
+  const unsigned int face_size = mesh_->face_size(face_index) ;
+  //vertex indices of the face
+  const unsigned int* face_vertices = mesh_->face(face_index) ;
+
+  //iterate on edges
+  for(unsigned int edge_index = 0; edge_index<face_size; ++edge_index) {
+    //vertices of the edge
+    const unsigned int v0 = face_vertices[ edge_index             ] ;
+    const unsigned int v1 = face_vertices[(edge_index+1)%face_size] ;
+
+    //build the edge
+    EdgeKey edge(v0, v1) ;
+
+    //get the neighbouring face information
+    const unsigned int n_face_index = 
+      face_neighbours(face_index)[edge_index] ;
+
+    if(n_face_index == NO_NEIGHBOUR) {
+      //if the edge is a border edge, remove it from the border edges
+      border_edges_.erase(edge) ;
+    } else {
+      //corresponding edge index in the neighbouring face
+      unsigned int n_edge_index = 
+        mesh_->edge_face_index(n_face_index,v0,v1) ;
+      assert( n_edge_index!=MeshType::NO_INDEX && 
+              "error : connectivity mismatch."
+            ) ;
+      //info relative to the neighbouring edge
+      EdgeInfo edge_info(n_face_index,n_edge_index) ;
+
+      //try to insert the edge in the border edges
+      bedge_iterator it = border_edges_.find(edge) ;
+
+      //connect the triangles if an other edge was already present
+      if(it != border_edges_.end()) {
+        //the edge is a border edge, connect the triangles
+        //index of the neighbouring face
+        const unsigned int nn_face_index = it->second.first ;
+        //edge index of the current edge in the neighbouring face
+        const unsigned int nn_edge_index = it->second.second ;
+        //assign the neighbour of the current face
+        face_neighbours(n_face_index)[n_edge_index] = nn_face_index ;
+        //assign the neighbour of the neighbouring face
+        face_neighbours(nn_face_index)[nn_edge_index] = n_face_index ;
+        //delete the edge from border edges
+        border_edges_.erase(it) ;
+      } else {
+        border_edges_[edge] = edge_info ;
+        //assign the edge as a border edge 
+        face_neighbours(n_face_index)[n_edge_index] = NO_NEIGHBOUR ;
+      }
+    }
+  }
+}
+
+template<typename MeshType>
+void ConnectivityComputer<MeshType>::unglue_faces( unsigned int face_start,
+                                                   unsigned int face_end
+                                                 ) {
+  //iterate over the faces to glue
+  for( unsigned int face_index = face_start; 
+       face_index < face_end; 
+       ++face_index
+     ) {
+    //glue the face
+    unglue_face(face_index) ;
+  }
+}
+
+template<typename MeshType>
+void ConnectivityComputer<MeshType>::erase_neighbourhoods( 
+  unsigned int face_start, unsigned int face_end 
+) {
+  //unglue faces
+  unglue_faces(face_start, face_end) ;
+  //remove the corresponding neighbourhoods
+  if(face_end >= mesh_->faces_size()) {
+    //remove all the neighbourhoods up to the end of the array
+    const unsigned int begin_index = mesh_->face_offset(face_start) ;
+    face_neighbourhoods_.erase( face_neighbourhoods_.begin() + begin_index,
+                                face_neighbourhoods_.end()
+                              ) ;
+  } else {
+    //remove the neighbourhoods within the range
+    const unsigned int begin_index = mesh_->face_offset(face_start) ;
+    const unsigned int end_index = mesh_->face_offset(face_end) ;
+    face_neighbourhoods_.erase( face_neighbourhoods_.begin() + begin_index,
+                                face_neighbourhoods_.begin() + end_index
+                              ) ;
+    //shift the indices of the faces after the range
+    const unsigned int offset = face_end - face_start ;
+    for( unsigned int neighbour = 0 ; 
+         neighbour < face_neighbourhoods_.size() ;
+         ++neighbour
+       ) {
+      unsigned int& fneigh = face_neighbourhoods_[neighbour] ;
+      if((fneigh >= face_end) && (fneigh != NO_NEIGHBOUR)) {
+        face_neighbourhoods_[neighbour] -= offset ;
+      }
+    }
+  }
+}
+
+template<typename MeshType>
+void ConnectivityComputer<MeshType>::swap( ConnectivityComputer& rhs ) {
+  std::swap(mesh_, rhs.mesh_) ;
+  face_neighbourhoods_.swap(rhs.face_neighbourhoods_) ;
+  border_edges_.swap(rhs.border_edges_) ;
+}
+
+//}}}
+
+/***{{{ Edge layer : building edges over a mesh ***/
+
+template< typename Mesh >
+void EdgeLayer<Mesh>::update() {
+  //one half edge per face vertex
+  edges_.resize(mesh_->face_vertices_size()) ;
+  //one edge per vertex
+  vertex_edges_.assign(mesh_->vertices_size(),NO_EDGE) ;
+  //assign (vertex_)edge data
+  for(unsigned int face = 0; face < mesh_->faces_size(); ++face) {
+    //size of the face
+    const unsigned int fsize = mesh_->face_size(face) ;
+    //offset of the face
+    const unsigned int foffset = mesh_->face_offset(face) ;
+    //vertices of the face
+    const unsigned int* fverts = mesh_->face(face) ;
+    //neighbouring faces of the face
+    const unsigned int* fneigh = mesh_->face_neighbours(face) ;
+    //edges of the face
+    MeshEdge* fedges = face_edges(face) ;
+    for(unsigned int i = 0; i < fsize; ++i) {
+      //vertices of the edge
+      const unsigned int v1 = fverts[ i         ] ;
+      const unsigned int v2 = fverts[(i+1)%fsize] ;
+      //assign the face of the edge
+      fedges[i].face = face ;
+      //(re)assign the edge of the vertex
+      vertex_edges_[v1] = foffset + i ;
+      //test if the edge is a border edge
+      const unsigned int n_face = fneigh[i] ;
+      if(n_face == Mesh::NO_NEIGHBOUR) {
+        //assign the opposite edge as no edge
+        fedges[i].opposite = NO_EDGE ;
+      } else if(n_face > face) { //to handle ony once pairs of opposite edges
+        //neighbouring face offset
+        const unsigned int n_foffset = mesh_->face_offset(n_face) ;
+        //neighbouring face edges
+        MeshEdge* n_fedges = face_edges(n_face) ;
+        //edge index in the neighbouring face
+        const unsigned int j = mesh_->edge_face_index(n_face, v1, v2) ;
+        assert( (j!=Mesh::NO_INDEX) &&
+                "The neighbouring face has no such edge"
+              ) ;
+        fedges[i].opposite = n_foffset + j ;
+        n_fedges[j].opposite = foffset + i ;
+      }
+    }
+  }
+  //handle border vertices
+  for(unsigned int vertex = 0; vertex < mesh_->vertices_size(); ++vertex) {
+    //assign the vertex edge to the first border found circulating backwards
+    vertex_edges_[vertex] = first_border_vertex_edge(vertex) ;
+  }
+}
+
+template< typename Mesh >
+unsigned int EdgeLayer<Mesh>::first_border_vertex_edge( unsigned int vertex ) {
+  //initial edge
+  unsigned int edge = vertex_edge(vertex) ;
+  //rotate back until a border edge is found
+  unsigned int prev_edge = edge ;
+  if(edge != NO_EDGE) {
+    do {
+      prev_edge = edge ;
+      edge = prev_around_vertex(vertex, edge) ;
+    } while((edge != NO_EDGE) && (edge != vertex_edge(vertex))) ;
+  }
+  //assign the edge vertex to the last non NO_EDGE edge
+  return prev_edge ;
+}
+
+//}}}
+
+} //end of namespace Revoropt
+
+#endif
+
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/connectivity_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/connectivity_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a68c972a20584ab612d4d395c6c9a6b7e043661f
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/connectivity_fwd.hpp
@@ -0,0 +1,446 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_CONNECTIVITY_FWD_HPP_
+#define _REVOROPT_MESH_CONNECTIVITY_FWD_HPP_
+
+#include <Revoropt/Tools/combinatorics.hpp>
+
+#include <assert.h>
+#include <vector>
+#include <unordered_map>
+
+namespace Revoropt {
+
+/***{{{ Connectivity computer ***/
+
+template<typename MeshType>
+class ConnectivityComputer {
+  public:
+
+    static const unsigned int NO_NEIGHBOUR ;
+
+    ConnectivityComputer() : mesh_(NULL) {} ;
+    ConnectivityComputer( const MeshType* mesh ) : mesh_(mesh) {
+      //reset face neighbourhoods
+      face_neighbourhoods_.assign(mesh_->face_vertices_size(),NO_NEIGHBOUR) ;
+    } ;
+
+    /* Resizing */
+    void resize( unsigned int size ) {
+      face_neighbourhoods_.resize(size,NO_NEIGHBOUR) ;
+    }
+
+    /* Provide a pointer to the neighbourhood array */
+    unsigned int* data() {
+      return face_neighbourhoods_.data() ;
+    }
+
+    const unsigned int* data() const {
+      return face_neighbourhoods_.data() ;
+    }
+
+    /* Setting the mesh */
+    void set_mesh(const MeshType* mesh) {
+      mesh_ = mesh ;
+
+      //reset face neighbourhoods
+      face_neighbourhoods_.assign(mesh_->face_vertices_size(),NO_NEIGHBOUR) ;
+
+      //Reset border edges
+      border_edges_.clear() ;
+    }
+
+    /* Incrementally gluing faces  */
+    void glue_face( unsigned int face_index ) ;
+
+    void glue_faces( unsigned int face_start, unsigned int face_end ) ;
+
+    /* Ungluing faces */
+
+    void unglue_face( unsigned int face_index ) ;
+
+    void unglue_faces( unsigned int face_start, unsigned int face_end ) ;
+
+    /* Removing faces */
+
+    void erase_neighbourhoods( unsigned int face_start, unsigned int face_end ) ;
+
+    /* Reset neighbourhoods and glue all the faces from scratch */
+    void compute_connectivity() {
+      //reset border edges
+      border_edges_.clear() ;
+
+      //resize according to the mesh
+      resize(mesh_->face_vertices_size()) ;
+
+      //glue all the faces
+      glue_faces(0,mesh_->faces_size()) ;
+    }
+
+    /* Swapping */
+    void swap( ConnectivityComputer<MeshType>& rhs ) ;
+
+  private:
+
+    /** Mesh holding the face information **/
+    const MeshType* mesh_ ;
+
+    /** Computing the face neighbourhoods **/
+
+    /* Neighbourhood storage */
+    std::vector<unsigned int> face_neighbourhoods_ ;
+
+    /* Face neighbours from an index */
+    unsigned int* face_neighbours( unsigned int face_index ) {
+      const unsigned int offset = mesh_->face_offset(face_index) ;
+      return data() + offset ;
+    }
+
+    /* Border edges */
+    typedef tuplekey<2> EdgeKey ;
+    typedef std::pair<unsigned int, unsigned int> EdgeInfo ;
+    typedef tuple_hash<2> EdgeHash ;
+    typedef std::unordered_map<EdgeKey, EdgeInfo, EdgeHash>::iterator bedge_iterator ;
+    std::unordered_map<EdgeKey, EdgeInfo, EdgeHash> border_edges_ ;
+} ;
+
+template<typename MeshType>
+const unsigned int ConnectivityComputer<MeshType>::NO_NEIGHBOUR = MeshType::NO_NEIGHBOUR ;
+
+//}}}
+
+/***{{{ Edge layer : building edges over a mesh ***/
+
+class MeshEdge {
+
+  public :
+  /* other classical half edge data like next, prev, vertex 
+   * are available via the mesh on which these edges are built*/
+
+  /* face corresponding to this edge */
+  unsigned int face ;
+
+  /* opposite edge index */
+  unsigned int opposite ;
+} ;
+
+template< typename Mesh >
+class EdgeLayer {
+
+  public :
+
+  static const unsigned int NO_EDGE ;
+
+  //TODO boundary
+
+  /** Construction **/
+
+  EdgeLayer( const Mesh* mesh ) : mesh_(mesh) {
+    update() ;
+  }
+
+  void update() ;
+
+  /* Resize edges according to the faces without initializing them */
+  void fit_to_faces() {
+    //resize
+    edges_.resize(mesh_->face_vertices_size()) ;
+  }
+
+  /* Commented since the complexity was nearly that of an update */
+  /* Erase edges corresponding to faces. Do it BEFORE erasing faces *//*
+  void erase_face_edges( unsigned int start, unsigned int end ) {
+    //first edge to remove
+    const unsigned int start_edge = mesh_->face_offset(start) ;
+    //first edge to keep above range
+    const unsigned int end_edge = end >= mesh_->faces_size() ?
+      mesh_->face_vertices_size() :
+      mesh_->face_offset(end) ;
+    //disconnect opposite edges
+    for(unsigned int face = start; face < end; ++face) {
+      //face size
+      const unsigned int fsize = mesh_->face_size(face) ;
+      //face edges
+      MeshEdge* fedges = face_edges(face) ;
+      //iterate over opposite edges
+      for(unsigned int edge = 0; edge < fsize; ++edge) {
+        //assign opposite edge opposite to NO_EDGE
+        if(fedges[edge].opposite != NO_EDGE) {
+          edges_[fedges[edge].opposite].opposite = NO_EDGE ;
+        }
+      }
+    }
+    //erase edges
+    edges_.erase(edges_.begin() + start_edge, edges_.begin() + end_edge) ;
+    //number of edges removed
+    const unsigned int erase_size = end_edge - start_edge ;
+    //number of faces removed
+    const unsigned int face_erase_size = end - start ;
+    //shift edge indices
+    for(unsigned int edge = 0; edge < edges_.size(); ++edge) {
+      unsigned int& opp_edge = edges_[edge].opposite ;
+      if((opp_edge != NO_EDGE) && (opp_edge > start_edge)) {
+        opp_edge -= erase_size ;
+      }
+      unsigned int& face = edges_[edge].face ;
+      if(face >= start) {
+        face -= face_erase_size ;
+      }
+    }
+    //reset vertex edges
+    for(unsigned int face = 0; face < mesh_->faces_size(); ++face) {
+      if((face < start) || (face >= end)) {
+        //size of the face
+        const unsigned int fsize = mesh_->face_size(face) ;
+        //offset of the face
+        const unsigned int foffset = mesh_->face_offset(face) ;
+        //vertices of the face
+        const unsigned int* fverts = mesh_->face(face) ;
+        for(unsigned int i = 0; i < fsize; ++i) {
+          //vertices of the edge
+          const unsigned int v1 = fverts[i] ;
+          //(re)assign the edge of the vertex
+          vertex_edges_[v1] = foffset + i ;
+        }
+      }
+    }
+    for(unsigned int vertex = 0; vertex < mesh_->vertices_size(); ++vertex) {
+      //assign the vertex edge to the first border found circulating backwards
+      vertex_edges_[vertex] = first_border_vertex_edge(vertex) ;
+      //shift if necessary
+      unsigned int& vedge = vertex_edges_[vertex] ;
+      if((vedge != NO_EDGE) && (vedge > start_edge)) {
+        vedge -= erase_size ;
+      }
+    }
+  }
+  */
+
+  /** Access **/
+
+  /* edge from its index */
+  MeshEdge* edge_info( unsigned int index ) {
+    return edges_.data() + index ;
+  }
+
+  /* edge array of a face */
+  MeshEdge* face_edges( unsigned int index ) {
+    return edges_.data() + mesh_->face_offset(index) ;
+  }
+
+  /* edge of a vertex */
+  unsigned int vertex_edge( unsigned int vertex ) {
+    if(vertex >= mesh_->vertices_size()) return NO_EDGE ;
+    return vertex_edges_[vertex] ;
+  }
+
+  /** Tools **/
+
+  /* opposite edge */
+  unsigned int edge_opposite( unsigned int edge ) {
+    if(edge == NO_EDGE) return NO_EDGE ;
+    return edge_info(edge)->opposite ;
+  }
+
+  /* face of an edge */
+  unsigned int edge_face( unsigned int edge ) {
+    if(edge == NO_EDGE) return Mesh::NO_NEIGHBOUR ;
+    return edge_info(edge)->face ;
+  }
+
+  /* index of an edge from its pointer */
+  unsigned int edge_index( MeshEdge* edge ) {
+    if((edge >= edges_.data()) && (edge < edges_.data() + edges_.size())) {
+      return (unsigned int) (edge - edges_.data()) ;
+    } else {
+      return NO_EDGE ;
+    }
+  }
+
+  /* index of an edge within its face */
+  unsigned int edge_face_index( unsigned int edge ) {
+    return edge - mesh_->face_offset(edges_[edge].face) ;
+  }
+
+  /* vertex at the start of the edge */
+  unsigned int edge_start_vertex( unsigned int edge ) {
+    //face of the edge
+    const unsigned int face = edge_face(edge) ;
+    //offset of the face
+    const unsigned int foffset = mesh_->face_offset(face) ;
+    //edge index within the face
+    const unsigned int efindex = edge - foffset ;
+    //face vertices
+    const unsigned int* fverts = mesh_->face(face) ;
+    //output
+    return fverts[efindex] ;
+  }
+
+  /* vertex at the start of the edge */
+  unsigned int edge_end_vertex( unsigned int edge ) {
+    //face of the edge
+    const unsigned int face = edge_face(edge) ;
+    //size of the face
+    const unsigned int fsize = mesh_->face_size(face) ;
+    //offset of the face
+    const unsigned int foffset = mesh_->face_offset(face) ;
+    //edge index within the face
+    const unsigned int efindex = edge - foffset ;
+    //face vertices
+    const unsigned int* fverts = mesh_->face(face) ;
+    //output
+    return fverts[(efindex+1)%fsize] ;
+  }
+
+  /* vertex of the edge different from the provided one */
+  unsigned int edge_other_vertex( unsigned int edge, unsigned int vertex ) {
+    //face of the edge
+    const unsigned int face = edge_face(edge) ;
+    //size of the face
+    const unsigned int fsize = mesh_->face_size(face) ;
+    //offset of the face
+    const unsigned int foffset = mesh_->face_offset(face) ;
+    //edge index within the face
+    const unsigned int efindex = edge - foffset ;
+    //face vertices
+    const unsigned int* fverts = mesh_->face(face) ;
+    //output
+    if(fverts[efindex] == vertex) {
+      return fverts[(efindex+1)%fsize] ;
+    } else {
+      return fverts[ efindex         ] ;
+    }
+  }
+
+  /* test if the opposite edge has a lower index */
+  bool is_resp( unsigned int edge ) {
+    unsigned int opp_edge = edge_opposite(edge) ;
+    //implicitly works for NO_EDGE since it is the biggest unsigned int
+    return (edge < opp_edge) ;
+  }
+
+  /* test if the edge is on the boundary */
+  bool is_border( unsigned int edge ) {
+    unsigned int opp_edge = edge_opposite(edge) ;
+    //implicitly works for NO_EDGE since it is the biggest unsigned int
+    return (opp_edge == NO_EDGE) ;
+  }
+
+  /** Circulation **/
+
+  /* Around faces */
+
+  /* next edge around a face */
+  unsigned int next_around_face( unsigned int edge ) {
+    //face of the edge
+    const unsigned int face = edge_face(edge) ;
+    //size of the face
+    const unsigned int fsize = mesh_->face_size(face) ;
+    //offset of the face
+    const unsigned int foffset = mesh_->face_offset(face) ;
+    //edge index within the face
+    const unsigned int efindex = edge - foffset ;
+    //next edge index within the face
+    const unsigned int next_efindex = (efindex+1)%fsize ;
+    //output
+    return foffset + next_efindex ;
+  }
+
+  /* previous edge around a face */
+  unsigned int prev_around_face( unsigned int edge ) {
+    //face of the edge
+    const unsigned int face = edge_face(edge) ;
+    //size of the face
+    const unsigned int fsize = mesh_->face_size(face) ;
+    //offset of the face
+    const unsigned int foffset = mesh_->face_offset(face) ;
+    //edge index within the face
+    const unsigned int efindex = edge - foffset ;
+    //previous edge index within the face
+    const unsigned int prev_efindex = (efindex+fsize-1)%fsize ;
+    //output
+    return foffset + prev_efindex ;
+  }
+
+  /* Around vertices */
+
+  /* circulation direction : given an edge, next searches the other edge sharing
+   * the vertex in the same face, and returns the edge opposite to this other
+   * edge. This ensures circulation. If the mesh is consistently oriented, the
+   * circulation direction is positive if the provided edge starts at the
+   * vertex, and negative otherwise. */
+
+  /* next edge around a vertex */
+  unsigned int next_around_vertex( unsigned int vertex, unsigned int edge ) {
+    //if NO_EDGE is provided, circulation is finished
+    if(edge == NO_EDGE) {
+      return NO_EDGE ;
+    }
+    //find the other edge in the face pointing at this edge
+    unsigned int other_edge = other_face_edge_for_vertex(vertex, edge) ;
+    //return its opposite
+    return edge_opposite(other_edge) ;
+  }
+
+  /* previous edge around a vertex */
+  unsigned int prev_around_vertex( unsigned int vertex, unsigned int edge ) {
+    //if NO_EDGE is provided, circulation is finished
+    if(edge == NO_EDGE) {
+      return NO_EDGE ;
+    }
+    //opposite edge
+    const unsigned int opp_edge = edge_opposite(edge) ;
+    //if no opposite edge exists, circulation is finished
+    if(opp_edge == NO_EDGE) {
+      return NO_EDGE ;
+    }
+    //find the other edge pointing at this vertex
+    return other_face_edge_for_vertex(vertex,opp_edge) ;
+  }
+
+  /* other edge in the same face using a vertex */
+  unsigned int other_face_edge_for_vertex( unsigned int vertex, 
+                                           unsigned int edge 
+                                         ) {
+    if(edge_start_vertex(edge) == vertex) {
+      return prev_around_face(edge) ;
+    } else {
+      if(edge_end_vertex(edge) == vertex) {
+        return next_around_face(edge) ;
+      } else {
+        return NO_EDGE ;
+      }
+    }
+  }
+
+  private :
+
+  /* Rotate around a vertex to set the vertex edge to a border edge if any */
+  unsigned int first_border_vertex_edge( unsigned int vertex ) ;
+
+  /* Mesh */
+  const Mesh* mesh_ ;
+
+  /* Half edges, stored per face with the same layout as the vertices */
+  std::vector<MeshEdge> edges_ ;
+
+  /* One edge per vertex */
+  std::vector<unsigned int> vertex_edges_ ;
+} ;
+
+template<typename Mesh>
+const unsigned int EdgeLayer<Mesh>::NO_EDGE = -1 ;
+
+//}}}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/debug_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/debug_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..496431ab45077421d32e911514a2fead8cbac553
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/debug_def.hpp
@@ -0,0 +1,42 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_DEBUG_DEF_HPP_
+#define _REVOROPT_MESH_DEBUG_DEF_HPP_
+
+#include <iostream>
+#include "debug_fwd.hpp"
+
+namespace Revoropt {
+
+/* Printing the information relative to a face */
+template< typename Mesh >
+void print_face( const Mesh* mesh, unsigned int face ) {
+  std::cout << "=== face " << face << " ===" << std::endl ;
+  if(face == Mesh::NO_NEIGHBOUR) return ;
+  //face size
+  const unsigned int fsize = mesh->face_size(face) ;
+  //face vertices
+  const unsigned int* fverts = mesh->face(face) ;
+  //face neighbours
+  const unsigned int* fneigh = mesh->face_neighbours(face) ;
+  //display edge information
+  for(unsigned int edge = 0; edge < fsize; ++edge) {
+    //vertices of the edge
+    const unsigned int v0 = fverts[ edge         ] ;
+    const unsigned int v1 = fverts[(edge+1)%fsize] ;
+    //display the edge vertices and neighbours
+    std::cout << " * (" << v0 << "," << v1 << ") : " << fneigh[edge] << std::endl ;
+  }
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/debug_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/debug_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d31e91502825d4c7c756fa7d215074f71238b02
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/debug_fwd.hpp
@@ -0,0 +1,22 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_DEBUG_H_
+#define _REVOROPT_MESH_DEBUG_H_
+
+namespace Revoropt {
+
+/* Printing the information relative to a face */
+template< typename Mesh >
+void print_face( const Mesh* mesh, unsigned int face ) ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/export_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/export_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..1ef669dfa02279ca710af9ddc2fad18188121a0b
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/export_def.hpp
@@ -0,0 +1,139 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_EXPORT_DEF_HPP_
+#define _REVOROPT_MESH_EXPORT_DEF_HPP_
+
+#include "export_fwd.hpp"
+
+#include <fstream>
+#include <sstream>
+#include <vector>
+#include <map>
+
+namespace Revoropt {
+
+template<typename Mesh>
+void export_obj( const Mesh* mesh, const std::string& filename ) {
+  //typedefs
+  enum { Dim = Mesh::VertexDim } ;
+  typedef typename Mesh::Scalar Scalar ;
+
+  //open file
+  std::ofstream file ;
+  file.open(filename) ;
+
+  //output vertices
+  for(unsigned int v = 0; v < mesh->vertices_size(); ++v) {
+    file << "v " ;
+    const Scalar* vertex = mesh->vertex(v) ;
+    for(int d = 0; d < Dim; ++d) {
+      file << vertex[d] << " " ;
+    }
+    file << std::endl ;
+  }
+
+  //output faces
+  for(unsigned int f = 0; f < mesh->faces_size(); ++f) {
+    file << "f " ;
+    const unsigned int* face = mesh->face(f) ;
+    for(unsigned int v = 0; v < mesh->face_size(f); ++v) {
+      file << face[v]+1 << " " ;
+    }
+    file << std::endl ;
+  }
+
+  //close file
+  file.close() ;
+}
+
+template<typename Mesh>
+void export_colored_obj( const Mesh* mesh, 
+                         const unsigned int* color_indices,
+                         const double* colormap,
+                         const std::string& basename 
+                       ) {
+  //typedefs
+  enum { Dim = Mesh::VertexDim } ;
+  typedef typename Mesh::Scalar Scalar ;
+
+  //file names
+  std::stringstream objfilename ;
+  objfilename << basename << ".obj" ;
+  std::stringstream mtlfilename ;
+  mtlfilename << basename << ".mtl" ;
+
+  //open obj file
+  std::ofstream objfile ;
+  objfile.open(objfilename.str().c_str()) ;
+
+  //provide material file name
+  objfile << "mtllib " << mtlfilename.str() << std::endl ;
+
+  //output vertices
+  for(unsigned int v = 0; v < mesh->vertices_size(); ++v) {
+    objfile << "v " ;
+    const Scalar* vertex = mesh->vertex(v) ;
+    for(int d = 0; d < Dim; ++d) {
+      objfile << vertex[d] << " " ;
+    }
+    objfile << std::endl ;
+  }
+
+  //sorting faces by color index
+  typedef std::map< unsigned int, std::vector<unsigned int> > FaceMap ;
+  FaceMap groups ;
+ 
+  for(unsigned int f = 0; f < mesh->faces_size(); ++f) {
+    groups[color_indices[f]].push_back(f) ;
+  }
+
+  //output faces by groups
+  for(FaceMap::iterator it = groups.begin(); it != groups.end(); ++it) {
+    objfile << "g " << basename << "_material_" << it->first << std::endl ;
+    objfile << "usemtl material_" << it->first << std::endl ;
+    std::vector<unsigned int>& f_indices = it->second ;
+    for(unsigned int f = 0; f < f_indices.size(); ++f) {
+      objfile << "f " ;
+      const unsigned int* face = mesh->face(f_indices[f]) ;
+      for(unsigned int v = 0; v < mesh->face_size(f_indices[f]); ++v) {
+        objfile << face[v]+1 << " " ;
+      }
+      objfile << std::endl ;
+    }
+  }
+
+  //close obj file
+  objfile.close() ;
+
+  //open mtl file
+  std::ofstream mtlfile ;
+  mtlfile.open(mtlfilename.str().c_str()) ;
+
+  //output materials
+  for(FaceMap::iterator it = groups.begin(); it != groups.end(); ++it) {
+    mtlfile << "newmtl material_" << it->first << std::endl ;
+    mtlfile << "Ns 100" << std::endl ;
+    mtlfile << "Ka 0.000000 0.000000 0.000000" << std::endl ;
+    //color
+    mtlfile << "Kd " 
+            << colormap[3*it->first  ] << " "
+            << colormap[3*it->first+1] << " "
+            << colormap[3*it->first+2] << std::endl ;
+    mtlfile << "Ks 0.000000 0.000000 0.000000" << std::endl ;
+    mtlfile << "Ni 1.000000" << std::endl ;
+    //mtlfile << "d 1.000000" << std::endl ;
+    mtlfile << "illum 1" << std::endl ;
+  }
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/export_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/export_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c3a6b98c51b31e2e5eb3de1d03db2cdcc4afdc05
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/export_fwd.hpp
@@ -0,0 +1,32 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_EXPORT_H_
+#define _REVOROPT_MESH_EXPORT_H_
+
+#include <string>
+
+namespace Revoropt {
+
+/* write an obj file to describe the mesh */
+template<typename Mesh>
+void export_obj( const Mesh* mesh, const std::string& filename ) ;
+
+/* write an obj file to describe the mesh and a mtl file for colors*/
+template<typename Mesh>
+void export_colored_obj( const Mesh* mesh, 
+                         const unsigned int* color_indices,
+                         const double* colormap,
+                         const std::string& basename 
+                       ) ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/import_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/import_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f746fcd44699c9e170aeb49434c52c264b44082f
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/import_def.hpp
@@ -0,0 +1,85 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_IMPORT_DEF_HPP_
+#define _REVOROPT_MESH_IMPORT_DEF_HPP_
+
+#include "import_fwd.hpp"
+
+#include <vector>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
+namespace Revoropt {
+
+//loading obj meshes
+template< typename MeshBuilder >
+void import_obj(const std::string& filename, MeshBuilder* builder) {
+  //vertex dimension
+  enum { Dim = MeshBuilder::VertexDim } ;
+
+  //open the file
+  std::ifstream file(filename) ;
+  if(!file.is_open()) {
+    std::cerr << "Mesh file could not be opened" << std::endl ;
+    return ;
+  }
+
+  //array used to store face indices for each face
+  std::vector<unsigned int> face_indices ;
+
+  //read the vertices and faces
+  unsigned int fcount = 0 ;
+  std::string line ;
+  while(file.good()) {
+    //get a new line
+    std::getline(file,line) ;
+
+    //get the line type
+    std::stringstream line_stream(line) ;
+    std::string elemtype ;
+    std::getline(line_stream,elemtype,' ') ;
+    if(elemtype == "v") {
+      //line contains a vertex
+      //append the coordinates to the vertex array
+      double coord[Dim] ;
+      for(int i=0; i<Dim; ++i) {
+        line_stream >> coord[i] ;
+      }
+      builder->push_vertex(coord) ;
+    } else if (elemtype == "f") {
+      //line contains a face
+      ++fcount ;
+      //append the vertex indices to the array
+      face_indices.resize(0) ;
+      while(true) {
+        std::string indices ;
+        std::getline(line_stream,indices,' ') ;
+        std::stringstream indices_stream(indices) ;
+        std::string vertex_index ;
+        std::getline(indices_stream,vertex_index,'/') ;
+        std::stringstream vertex_index_stream(vertex_index) ;
+        unsigned int index ;
+        vertex_index_stream >> index ;
+        if(line_stream.fail()) break ;
+        face_indices.push_back(index-1) ;
+      }
+      builder->push_face(face_indices.data(), face_indices.size()) ;
+    }
+  }
+
+  //close the file
+  file.close() ;
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/import_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/import_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fd48dcacc0a6cfd434c6d20d54506da2731b0a0e
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/import_fwd.hpp
@@ -0,0 +1,24 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_IMPORT_FWD_HPP_
+#define _REVOROPT_MESH_IMPORT_FWD_HPP_
+
+#include <string>
+
+namespace Revoropt {
+
+//loading obj meshes
+template< typename MeshBuilder >
+void import_obj(const std::string& filename, MeshBuilder* builder) ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/measure_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/measure_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..77050f8741dbec950ff218ade5deb381e8236246
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/measure_def.hpp
@@ -0,0 +1,402 @@
+#ifndef _REVOROPT_MESH_MEASURE_DEF_HPP_
+#define _REVOROPT_MESH_MEASURE_DEF_HPP_
+
+#include "measure_fwd.hpp"
+
+#include <Revoropt/Tools/measure_def.hpp>
+#include <Revoropt/Neighbours/neighbourhood_def.hpp>
+
+#include <eigen3/Eigen/Dense>
+
+namespace Revoropt {
+
+/*{{{ Area */
+
+/* Area of a face of a mesh */
+template<typename Mesh>
+typename Mesh::Scalar mesh_face_area(const Mesh* mesh, unsigned int face) {
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  
+  //result
+  double area = 0 ;
+
+  //iterate over the faces
+  unsigned int fsize = mesh->face_size(face) ;
+  const unsigned int* fverts = mesh->face(face) ;
+  for(unsigned int v = 1; v < fsize-1; ++v) {
+    area += triangle_area<Mesh::VertexDim,Scalar>( 
+              mesh->vertex(fverts[0]),
+              mesh->vertex(fverts[v]),
+              mesh->vertex(fverts[v+1])
+            ) ;
+  }
+
+  return area ;
+}
+
+/* Area of a mesh */
+template<typename Mesh>
+typename Mesh::Scalar mesh_area(const Mesh* mesh) {
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+
+  //the area will be stored here
+  Scalar area = 0 ;
+
+  //iterate over the faces
+  for(unsigned int face = 0; face < mesh->faces_size(); ++face) {
+    area += mesh_face_area(mesh, face) ;
+  }
+
+  return area ;
+}
+
+//}}}
+
+/*{{{ Edge length */
+
+template< typename Mesh >
+typename Mesh::Scalar edge_length_from_vertices( const Mesh* mesh, 
+                                                 unsigned int v0, 
+                                                 unsigned int v1 
+                                               ) {
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //vector type
+  typedef Eigen::Matrix<Scalar,Mesh::VertexDim,1> Vector ;
+  //vertex positions
+  Eigen::Map<const Vector> v0_pos(mesh->vertex(v0)) ;
+  Eigen::Map<const Vector> v1_pos(mesh->vertex(v1)) ;
+  //length
+  return (v1_pos-v0_pos).norm() ;
+}
+
+template< typename Mesh >
+typename Mesh::Scalar edge_length_from_face_index( const Mesh* mesh, 
+                                                   unsigned int face, 
+                                                   unsigned int edge 
+                                                 ) {
+  //edge vertex indices
+  const unsigned int v0 = mesh->face_edge_start_vertex(face, edge) ;
+  const unsigned int v1 = mesh->face_edge_end_vertex(face, edge) ;
+  return edge_length_from_vertices(mesh,v0,v1) ;
+}
+
+/* Longest edge of a face */
+
+template< typename Mesh >
+unsigned int face_longest_edge( const Mesh* mesh,
+                                unsigned int face,
+                                typename Mesh::Scalar* output_length
+                              ) {
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //size of the face
+  const unsigned int face_size = mesh->face_size(face) ;
+  //initialization
+  unsigned int longest_edge = 0 ;
+  Scalar longest_length = 0 ;
+  //iterate over the edges
+  for(unsigned int edge = 0; edge < face_size; ++edge) {
+    //length
+    Scalar length = edge_length_from_face_index(mesh, face, edge) ;
+    //update
+    if(length == longest_length) {
+      //decide depending on edge vertices in lexicographic order
+      const unsigned int v0 = mesh->face_edge_start_vertex(face, edge) ;
+      const unsigned int v1 = mesh->face_edge_end_vertex(face, edge) ;
+      const unsigned int v2 = mesh->face_edge_start_vertex(face, longest_edge) ;
+      const unsigned int v3 = mesh->face_edge_end_vertex(face, longest_edge) ;
+      const unsigned int v0_min = v0 < v1 ? v0 : v1 ;
+      const unsigned int v0_max = v0 < v1 ? v1 : v0 ;
+      const unsigned int v1_min = v2 < v3 ? v2 : v3 ;
+      const unsigned int v1_max = v2 < v3 ? v3 : v2 ;
+      if(v0_max == v1_max) {
+        if(v0_min > v1_min) {
+          longest_edge = edge ;
+          longest_length = length ;
+        }
+      } else if(v0_max > v1_max){
+        longest_edge = edge ;
+        longest_length = length ;
+      }
+
+    } else if(length > longest_length) {
+      longest_edge = edge ;
+      longest_length = length ;
+    }
+  }
+  //result
+  if(output_length != NULL) {
+    *output_length = longest_length ;
+  }
+  return longest_edge ;
+}
+
+/* Longest edge of a mesh */
+template< typename Mesh >
+void mesh_longest_edge_vertices( const Mesh* mesh,
+                                 unsigned int* v0,
+                                 unsigned int* v1,
+                                 typename Mesh::Scalar* output_length
+                               ) {
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //initialization
+  unsigned int longest_face = 0 ;
+  unsigned int longest_edge = 0 ;
+  Scalar longest_length = 0 ;
+  //variables  to store edges and lengths
+  unsigned int edge ;
+  Scalar length ;
+  for(unsigned int face = 0; face < mesh->faces_size(); ++face) {
+    //longest edge of the face
+    edge = face_longest_edge(mesh, face, &length) ;
+    if(length > longest_length) {
+      longest_face = face ;
+      longest_edge = edge ;
+      longest_length = length ;
+    }
+  }
+  //result
+  if(output_length != NULL) {
+    *output_length = longest_length ;
+  }
+  return mesh->face_edge_vertices(longest_face,longest_edge,v0,v1) ;
+}
+
+//}}}
+
+/*{{{ Angles */
+
+template<typename Mesh>
+typename Mesh::Scalar face_angle_cos( const Mesh* mesh, 
+                                      unsigned int face, 
+                                      unsigned int vertex 
+                                    ) {
+  //size of the face
+  const unsigned int fsize = mesh->face_size(face) ;
+  //vertices of the face
+  const unsigned int* fverts = mesh->face(face) ;
+  //previous and next vertex
+  const unsigned int prev = fverts[(vertex+fsize-1) % fsize] ;
+  const unsigned int next = fverts[(vertex      +1) % fsize] ;
+  //angle cosine
+  return angle_cos<Mesh::VertexDim>( mesh->vertex(vertex), 
+                                     mesh->vertex(prev), 
+                                     mesh->vertex(next)
+                                   ) ;
+}
+
+//}}}
+
+/*{{{ Normalization */
+
+template<typename Mesh>
+void normalize_mesh( Mesh* mesh, double* out_center, double* out_scale ) {
+  //typedefs
+  typedef typename Mesh::Scalar Scalar ;
+  typedef Eigen::Matrix<Scalar,Mesh::VertexDim,1> Vector ;
+  //compute the new center
+  Vector center = Vector::Zero() ;
+  for(unsigned int i=0; i<mesh->vertices_size(); ++i) {
+    Eigen::Map<const Vector> x(mesh->vertex(i)) ;
+    center += x ;
+  }
+  center /= mesh->vertices_size() ;
+
+  if(out_center) {
+    for(int i = 0; i < 3; ++i) {
+      out_center[i] = center[i] ;
+    }
+  }
+
+  //center the mesh
+  for(unsigned int i=0; i<mesh->vertices_size(); ++i) {
+    Eigen::Map<Vector> x(mesh->vertex(i)) ;
+    x -= center ;
+  }
+
+  //compute the scene radius
+  Scalar radius = 0 ;
+  for(unsigned int i=0; i<mesh->vertices_size(); ++i) {
+    Eigen::Map<const Vector> x(mesh->vertex(i)) ;
+    radius = std::max(radius,(center - x).norm()) ;
+  }
+
+  //scale the mesh
+  for(unsigned int i=0; i<mesh->vertices_size(); ++i) {
+    Eigen::Map<Vector> x(mesh->vertex(i)) ;
+    x /= radius ;
+  }
+
+  if(out_scale) {
+    *out_scale = radius ;
+  }
+
+  mesh->set_dirty() ;
+}
+
+//}}}
+
+/*{{{ Distance to a mesh */
+
+/* Action passed to a neighbourhood computer to compute normals */
+template<typename Triangulation>
+class NeighDistanceCompute {
+
+  public :
+
+  //scalar type, dimension and vector
+  typedef typename Triangulation::Scalar Scalar ;
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+
+  NeighDistanceCompute( const Triangulation* mesh, 
+                        const Scalar* queries,
+                        const unsigned int* indices, 
+                        Scalar* output,
+                        bool translate_queries = true
+                      ) : mesh_(mesh), 
+                          queries_(queries),
+                          indices_(indices), 
+                          output_(output),
+                          translate_queries_(translate_queries) {} ;
+
+  NeighDistanceCompute( const Triangulation* mesh,
+                        const Scalar* queries,
+                        Scalar* output 
+                      ) : mesh_(mesh), 
+                          queries_(queries),
+                          indices_(NULL), 
+                          output_(output),
+                          translate_queries_(false) {} ;
+
+  void operator()( unsigned int query,
+                   unsigned int triangle
+                 ) {
+    //position of the query
+    const unsigned int q_in_index = 
+      translate_queries_ ? indices_[query] : query ;
+    const Scalar* qp = queries_ +Dim*q_in_index ;
+    Eigen::Map<const Vector> qv(qp) ;
+
+    //vertices of the triangle
+    const unsigned int* tverts = mesh_->face(triangle) ;
+    Eigen::Map<const Vector> x0(mesh_->vertex(tverts[0])) ;
+    Eigen::Map<const Vector> x1(mesh_->vertex(tverts[1])) ;
+    Eigen::Map<const Vector> x2(mesh_->vertex(tverts[2])) ;
+
+    //distance of the query to the triangle
+    Scalar uv[2] ;
+    point_in_triangle<Dim, Scalar>( qp, x0.data(), x1.data(), x2.data(), uv ) ;
+    const Scalar distance = (uv[0]*x0+uv[1]*x1+(1-uv[0]-uv[1])*x2 - qv).norm() ;
+
+    //assign the minimum distance
+    const unsigned int q_out_index = 
+      indices_ == NULL ? query : indices_[query] ;
+    output_[q_out_index] = 
+      distance < output_[q_out_index] ? distance : output_[q_out_index] ;
+  }
+
+  private :
+
+  const Triangulation* mesh_ ;
+  const Scalar* queries_ ;
+  const unsigned int* indices_ ;
+  bool translate_queries_ ;
+  Scalar* output_ ;
+
+} ;
+
+template<typename Mesh>
+void mesh_distances( const Mesh* mesh,
+                     typename Mesh::Scalar* queries,
+                     unsigned int queries_size,
+                     typename Mesh::Scalar radius,
+                     typename Mesh::Scalar* output
+                   ) {
+  //typedefs
+  enum { Dim = Mesh::VertexDim, Offset = Mesh::VertexOffset } ;
+  typedef typename Mesh::Scalar Scalar ;
+  typedef ROMesh<3, Dim, Scalar, Offset> Triangulation ;
+
+  //initialize the distance array
+  for(unsigned int i = 0; i < queries_size; ++i) {
+    output[i] = 2*radius ;
+  }
+
+  //wrap the mesh as a triangle mesh
+  ROTriangulationWrapper<Dim, Scalar, Offset> trimesh(mesh) ;
+
+  //use the neighbourhoods of the queries
+  NeighbourhoodComputer<Triangulation> n_computer(
+    &trimesh, queries, queries_size
+  ) ;
+  NeighDistanceCompute<Triangulation> action(&trimesh, queries, output) ;
+  n_computer.compute(radius, action) ;
+}
+
+//}}}
+
+/**{{{ Gradient of the mesh area wrt. its vertices **/
+
+template<typename Triangulation>
+void mesh_area_gradient( 
+    const Triangulation* mesh, 
+    double* output,
+    double factor
+    ) {
+  typedef typename Triangulation::Scalar Scalar ;
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef Eigen::Matrix<Scalar, Dim, 1> Vector ;
+
+  for(unsigned int f = 0; f < mesh->faces_size(); ++f) {
+    //flag for degenerate triangle
+    bool degenerate = false ;
+    //vertices of the triangle
+    const unsigned int* fverts = mesh->face(f) ;
+
+    //edges of the triangle
+    Vector edges[3] ;
+    Scalar e_len[3] ;
+    for(unsigned int v = 0; v < 3; ++v) {
+      Eigen::Map<const Vector> x0(mesh->vertex(fverts[v])) ;
+      Eigen::Map<const Vector> x1(mesh->vertex(fverts[(v+1)%3])) ;
+      edges[v] = x1 - x0 ;
+      e_len[v] = edges[v].norm() ;
+      degenerate |= (e_len[v] == 0) ;
+      if(degenerate) break ;
+    }
+    if(degenerate) continue ;
+
+    //heights of the triangle
+    Vector heights[3] ;
+    Scalar h_len[3] ;
+    for(unsigned int v = 0; v < 3; ++v) {
+      const Scalar& base_len = e_len[(v+1)%3] ;
+      const Vector& base = edges[(v+1)%3] ;
+      heights[v] = edges[(v+2)%3] 
+                 - edges[(v+2)%3].dot(base) * base / (base_len*base_len) ;
+      h_len[v] = heights[v].norm() ;
+      degenerate |= (h_len[v] == 0) ;
+      if(degenerate) break ;
+    }
+    if(degenerate) continue ;
+
+    //fill the gradient for the appropriate variables
+    for(unsigned int v = 0; v < 3; ++v) {
+      Eigen::Map<Vector> g(output + Dim*fverts[v]) ;
+      g += factor * 0.5 * e_len[(v+1)%3] * heights[v] / h_len[v] ;
+    }
+
+  }
+
+}
+
+//}}}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/measure_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/measure_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fc616d21cba046a5d5f8736ae337b62aa5ebbf17
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/measure_fwd.hpp
@@ -0,0 +1,94 @@
+#ifndef _REVOROPT_MESH_MEASURE_FWD_HPP_
+#define _REVOROPT_MESH_MEASURE_FWD_HPP_
+
+#include <cstddef>
+
+namespace Revoropt {
+
+/*{{{ Area */
+
+/* Area of a face of a mesh */
+template<typename Mesh>
+typename Mesh::Scalar mesh_face_area(const Mesh* mesh, unsigned int face) ;
+
+/* Area of a mesh */
+template<typename Mesh>
+typename Mesh::Scalar mesh_area(const Mesh* mesh) ;
+
+//}}}
+
+/*{{{ Edge length */
+
+template< typename Mesh >
+typename Mesh::Scalar edge_length_from_vertices( const Mesh* mesh, 
+                                                 unsigned int v0, 
+                                                 unsigned int v1 
+                                               ) ;
+
+template< typename Mesh >
+typename Mesh::Scalar edge_length_from_face_index( const Mesh* mesh, 
+                                                   unsigned int face, 
+                                                   unsigned int edge 
+                                                 ) ;
+
+/* Longest edge of a face */
+
+template< typename Mesh >
+unsigned int face_longest_edge( const Mesh* mesh,
+                                unsigned int face,
+                                typename Mesh::Scalar* output_length = NULL
+                              ) ;
+
+/* Longest edge of a mesh */
+template< typename Mesh >
+void mesh_longest_edge_vertices( const Mesh* mesh,
+                                 unsigned int* v0,
+                                 unsigned int* v1,
+                                 typename Mesh::Scalar* output_length = NULL
+                               ) ;
+
+//}}}
+
+/*{{{ Angles */
+
+template<typename Mesh>
+typename Mesh::Scalar face_angle_cos( const Mesh* mesh, 
+                                      unsigned int face, 
+                                      unsigned int vertex 
+                                    ) ;
+
+//}}}
+
+/*{{{ Normalization */
+
+template<typename Mesh>
+void normalize_mesh( Mesh* mesh, double* out_center = NULL, double* out_scale = NULL ) ;
+
+//}}}
+
+/**{{{ Distance to a mesh **/
+
+template<typename Mesh>
+void mesh_distances( const Mesh* mesh,
+                     typename Mesh::Scalar* queries,
+                     unsigned int queries_size,
+                     typename Mesh::Scalar radius,
+                     typename Mesh::Scalar* output
+                   ) ;
+
+//}}}
+
+/**{{{ Gradient of the mesh area wrt. its vertices **/
+
+template<typename Triangulation>
+void mesh_area_gradient( 
+    const Triangulation* mesh, 
+    double* output,
+    double factor = 1
+    ) ;
+
+//}}}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/normals_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/normals_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..9dff330da337be0246700275f2055096f69e4b2d
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/normals_def.hpp
@@ -0,0 +1,439 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_NORMALS_FWD_HPP_
+#define _REVOROPT_MESH_NORMALS_FWD_HPP_
+
+#include <Revoropt/Tools/normals_def.hpp>
+#include <Revoropt/Neighbours/neighbourhood_def.hpp>
+
+#include <eigen3/Eigen/Dense>
+#include <cassert>
+#include <cmath>
+#include <vector>
+
+namespace Revoropt {
+
+/* Face normal */
+template<typename Mesh>
+void face_normal ( const Mesh* mesh, 
+                   unsigned int index, 
+                   typename Mesh::Scalar* output 
+                 ) {
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //face_size
+  const unsigned int fsize = mesh->face_size(index) ;
+  //face vertex indices
+  const unsigned int* fverts = mesh->face(index) ;
+
+  //call triangle normal
+  for(unsigned int i = 1; i<fsize-1; ++i) {
+    const Scalar n_len = triangle_normal( mesh->vertex(fverts[0]),
+                                          mesh->vertex(fverts[i]),
+                                          mesh->vertex(fverts[i+1]),
+                                          output
+                                        ) ;
+    if(n_len !=0) return ;
+  }
+}
+
+/* Connected normals (based on the faces connected to the vertex) */
+template<typename Mesh>
+void connected_vertex_normals( const Mesh* mesh, 
+                               typename Mesh::Scalar* output 
+                             ) {
+  assert((Mesh::VertexDim == 3) && "normals are only defined for 3D meshes") ;
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //vector type
+  typedef Eigen::Matrix<Scalar,Mesh::VertexDim,1> Vector ;
+  //average normals on vertices
+  for(unsigned int face; face < mesh->faces_size(); ++face) {
+    //number of vertices for this face
+    const unsigned int fsize = mesh->face_size(face) ;
+    if(fsize < 3) continue ;
+    //get the normal of the face
+    Vector fnormal ;
+    face_normal(mesh,face,fnormal.data()) ;
+    if(fnormal.dot(fnormal) == 0) continue ;
+    //vertex indices of the face
+    const unsigned int* fverts = mesh->face(face) ;
+    //add the weighted normal for each vertex
+    for(unsigned int vertex = 0; vertex < fsize; ++vertex) {
+      const unsigned int previndex = fverts[(vertex+fsize-1)%fsize] ;
+      const unsigned int currindex = fverts[ vertex               ] ;
+      const unsigned int nextindex = fverts[(vertex      +1)%fsize] ;
+      Eigen::Map<const Vector> vprev(mesh->vertex(previndex)) ;
+      Eigen::Map<const Vector> vcurr(mesh->vertex(currindex)) ;
+      Eigen::Map<const Vector> vnext(mesh->vertex(nextindex)) ;
+      //normal weight for this vertex
+      const Vector e1 = (vprev-vcurr) ;
+      const Scalar e1_len = e1.norm() ;
+      const Vector e2 = (vcurr-vnext) ;
+      const Scalar e2_len = e2.norm() ;
+      if(e1_len*e2_len != 0) {
+        Scalar angle_cos = -e1.dot(e2)/(e1_len*e2_len) ;
+        angle_cos = std::min(angle_cos,1.) ;
+        angle_cos = std::max(angle_cos,-1.) ;
+        const Scalar angle = acos(angle_cos) ;
+        //add the face contribution to the vertex
+        Eigen::Map<Vector> vnormal(output + 3*currindex) ;
+        vnormal += angle*fnormal ;
+      }
+    }
+  }
+  //normalize vertex normals
+  for(unsigned int vertex = 0; vertex < mesh->vertices_size(); ++vertex) {
+    Eigen::Map<Vector> vnormal(output + 3*vertex) ;
+    Scalar vnormal_len = vnormal.norm() ;
+    if(vnormal_len != 0) {
+      vnormal /= vnormal_len ;
+    }
+  }
+}
+
+/* Action passed to a neighbourhood computer to compute robust normals */
+template<typename Triangulation>
+class NeighNormalCompute {
+
+  public :
+
+  //normals are only for dimension 3
+  typedef char normals_only_meaningful_for_dimension_3[
+    Triangulation::VertexDim==3 ? 1 : -1
+  ] ;
+
+  //scalar and vector
+  typedef typename Triangulation::Scalar Scalar ;
+  typedef Eigen::Matrix<Scalar,3,1> Vector ;
+
+  NeighNormalCompute( const Triangulation* mesh, 
+                      const Scalar* queries,
+                      const unsigned int* indices, 
+                      Scalar radius,
+                      Scalar* output,
+                      bool translate_queries = true
+                    ) : mesh_(mesh), 
+                        queries_(queries),
+                        indices_(indices), 
+                        translate_queries_(translate_queries),
+                        radius_(radius), 
+                        output_(output) {} ;
+
+  NeighNormalCompute( const Triangulation* mesh,
+                      const Scalar* queries,
+                      Scalar radius,
+                      Scalar* output 
+                    ) : mesh_(mesh), 
+                        queries_(queries),
+                        indices_(NULL), 
+                        translate_queries_(false),
+                        radius_(radius), 
+                        output_(output) {} ;
+
+  void operator()( unsigned int query,
+                   unsigned int triangle
+                 ) {
+    //position of the query
+    const unsigned int q_in_index = translate_queries_ ? indices_[query] : query ;
+    const Scalar* q = queries_ +3*q_in_index ;
+
+    //vertices of the triangle
+    const unsigned int* tverts = mesh_->face(triangle) ;
+
+    //area of the triangle portion within a ball 
+    //of the provided radius around the query
+    const Scalar clip_area = triangle_sphere_intersection_area<3>(
+      mesh_->vertex(tverts[0]), 
+      mesh_->vertex(tverts[1]), 
+      mesh_->vertex(tverts[2]),
+      q,
+      radius_
+    ) ;
+
+    if(clip_area == 0) return ;
+
+    //normal of the mesh triangle
+    Vector normal ;
+    face_normal(mesh_, triangle, normal.data()) ;
+
+    //add the contribution to the normalif the normal is not 0
+    if(normal.dot(normal) != 0) {
+      const unsigned int q_out_index = indices_ == NULL ? query : indices_[query] ;
+      Eigen::Map<Vector> n_out(output_ + 3*q_out_index) ;
+      n_out += clip_area*normal ;
+    }
+  }
+
+  private :
+
+  const Triangulation* mesh_ ;
+  const Scalar* queries_ ;
+  const unsigned int* indices_ ;
+  bool translate_queries_ ;
+  Scalar radius_ ;
+  Scalar* output_ ;
+
+} ;
+
+/* Robust normals on boundary vertices (handling disconnected meshes) */
+template<typename Mesh>
+void robust_vertex_normals( const Mesh* mesh, 
+                            typename Mesh::Scalar radius,
+                            typename Mesh::Scalar* output
+                          ) {
+  assert((Mesh::VertexDim == 3) && "normals are only defined for 3D meshes") ;
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //vector type
+  typedef Eigen::Matrix<Scalar,3,1> Vector ;
+
+  //compute normals based on connectivity
+  connected_vertex_normals(mesh,output) ;
+
+  //for boundary normals, use the geometric neighbourhood instead
+  //get boundary vertices
+  std::vector<unsigned int> boundary_vertices ;
+  std::vector<bool> boundary_flag(mesh->vertices_size(),false) ;
+  //iterate over faces
+  for(unsigned int face = 0; face < mesh->faces_size(); ++face) {
+    //size of the face
+    const unsigned int fsize = mesh->face_size(face) ;
+    //vertices of the face
+    const unsigned int* vertices = mesh->face(face) ;
+    //neighbours of the face
+    const unsigned int* neighbours = mesh->face_neighbours(face) ;
+    //circulate around the face to find border vertices
+    for(unsigned int edge = 0; edge < fsize; ++edge) {
+      //test if the edge is a boundary edge
+      if(neighbours[edge] == Mesh::NO_NEIGHBOUR) {
+        //boundary edge get its vertices
+        const unsigned int v1 = vertices[ edge         ] ;
+        const unsigned int v2 = vertices[(edge+1)%fsize] ;
+        //mark vertices as handled, and add them to the list
+        if(!boundary_flag[v1]) {
+          boundary_vertices.push_back(v1) ;
+        }
+        if(!boundary_flag[v2]) {
+          boundary_vertices.push_back(v2) ;
+        }
+      }
+    }
+  }
+  //cleanup
+  std::vector<bool>().swap(boundary_flag) ;
+
+  //check if any vertex is on the boundary
+  const unsigned int bvsize = boundary_vertices.size() ;
+  if(bvsize > 0) {
+    //get the boundary vertices coordinates
+    std::vector<Scalar> queries(3*bvsize) ;
+    for(unsigned int vertex = 0; vertex < bvsize; ++vertex) {
+      const unsigned int v = boundary_vertices[vertex] ;
+      std::copy(mesh->vertex(v), mesh->vertex(v)+3, queries.data() + 3*vertex) ;
+      for(int i = 0;i < 3; ++i) {
+        output[3*v+i] = 0 ;
+      }
+    }
+
+    //compute normals on geometric neighbourhoods
+    NeighbourhoodComputer<Mesh> n_computer(mesh,queries.data(),bvsize) ;
+    NeighNormalCompute<Mesh> action( mesh, 
+                                     queries.data(), 
+                                     radius,
+                                     output
+                                   ) ;
+    n_computer.compute(radius,action) ;
+
+    //normalize the boundary vertex normals
+    for(unsigned int vertex = 0; vertex < bvsize; ++vertex) {
+      const unsigned int v = boundary_vertices[vertex] ;
+      Eigen::Map<Vector> normal(output + 3*v) ;
+      const Scalar n_len = normal.norm() ;
+      if(n_len != 0) {
+        normal /= n_len ;
+      }
+    }
+  }
+}
+
+/* Robust normals on every vertex */
+template<typename Mesh>
+void full_robust_vertex_normals( const Mesh* mesh, 
+                                 typename Mesh::Scalar radius,
+                                 typename Mesh::Scalar* output
+                               ) {
+  assert((Mesh::VertexDim == 3) && "normals are only defined for 3D meshes") ;
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //vector type
+  typedef Eigen::Matrix<Scalar,3,1> Vector ;
+
+  const Scalar* queries ;
+  std::vector<Scalar> vertex_copy ;
+  if(Mesh::VertexOffset == 0) {
+    queries = mesh->vertices() ;
+  } else {
+    //the vertex array is has an offset, copy the vertices
+    for(unsigned int vertex = 0; vertex < mesh->vertices_size() ; ++vertex) {
+      const Scalar* v = mesh->vertex(vertex) ;
+      vertex_copy.insert(vertex_copy.end(), v, v+3) ;
+    }
+    queries = vertex_copy.data() ;
+  }
+  //compute normals on geometric neighbourhoods
+  NeighbourhoodComputer<Mesh> n_computer( mesh, 
+                                          queries, 
+                                          mesh->vertices_size()
+                                        ) ;
+  NeighNormalCompute<Mesh> action( mesh,
+                                   queries,
+                                   radius,
+                                   output
+                                 ) ;
+  n_computer.compute(radius,action) ;
+
+  //normalize the vertex normals
+  for(unsigned int vertex = 0; vertex < mesh->vertices_size(); ++vertex) {
+    Eigen::Map<Vector> normal(output + 3*vertex) ;
+    const Scalar n_len = normal.norm() ;
+    if(n_len != 0) {
+      normal /= n_len ;
+    }
+  }
+}
+
+/* Connected edge normals based on the mesh connectivty */
+template< typename Mesh >
+void connected_edge_normals( const Mesh* mesh, 
+                             typename Mesh::Scalar* output 
+                           ) {
+  assert((Mesh::VertexDim == 3) && "normals are only defined for 3D meshes") ;
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //vector type
+  typedef Eigen::Matrix<Scalar,Mesh::VertexDim,1> Vector ;
+
+  //face normals
+  std::vector<Scalar> face_normals(3*mesh->faces_size(), 0) ;
+  for(unsigned int face = 0; face < mesh->faces_size(); ++face) {
+    //number of vertices/edges for this face
+    const unsigned int fsize = mesh->face_size(face) ;
+    if(fsize < 3) continue ;
+    face_normal(mesh,face,face_normals.data() + 3*face) ;
+  }
+
+  //edge layer
+  EdgeLayer<Mesh> edge_layer(mesh) ;
+  
+  //edge normals
+  for(unsigned int edge = 0; edge < mesh->face_vertices_size(); ++edge) {
+    Eigen::Map<Vector> enormal(output + 3*edge) ;
+    //face of the edge
+    const unsigned int eface = edge_layer.edge_face(edge) ;
+    //add the face contribution
+    Eigen::Map<const Vector> fnormal(face_normals.data() + 3*eface) ;
+    enormal += fnormal ;
+    //test if the edge is on the boundary
+    if(!edge_layer.is_border(edge)) {
+      //not on boundary, opposite edge and face
+      const unsigned int oedge = edge_layer.edge_opposite(edge) ;
+      const unsigned int oface = edge_layer.edge_face(oedge) ;
+      //add the opposite face contribution
+      Eigen::Map<const Vector> ofnormal(face_normals.data() + 3*oface) ;
+      enormal += ofnormal ;
+      //normalize
+      const Scalar n_len = enormal.norm() ;
+      if(n_len != 0) {
+        enormal /= n_len ;
+      }
+    }
+  }
+}
+
+/* Robust edge normals */
+template<typename Mesh>
+void robust_edge_normals( const Mesh* mesh, 
+                          typename Mesh::Scalar radius,
+                          typename Mesh::Scalar* output
+                        ) {
+  assert((Mesh::VertexDim == 3) && "normals are only defined for 3D meshes") ;
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //vector type
+  typedef Eigen::Matrix<Scalar,3,1> Vector ;
+
+  //compute normals based on connectivity
+  connected_edge_normals(mesh,output) ;
+
+  //for boundary edge normals, use the geometric neighbourhood instead
+  //collect boundary edges, and their midpoint
+  std::vector<unsigned int> boundary_edges ;
+  std::vector<Scalar> edge_midpoints ;
+  //edge layer
+  EdgeLayer<Mesh> edge_layer(mesh) ;
+  for(unsigned int edge = 0; edge < mesh->face_vertices_size(); ++edge) {
+    if(edge_layer.is_border(edge)) {
+      //add the edge to the boundary edges
+      boundary_edges.push_back(edge) ;
+      //vertices of the edge
+      const unsigned int v0 = edge_layer.edge_start_vertex(edge) ;
+      const unsigned int v1 = edge_layer.edge_end_vertex(edge) ;
+      Eigen::Map<const Vector> v0_pos(mesh->vertex(v0)) ;
+      Eigen::Map<const Vector> v1_pos(mesh->vertex(v1)) ;
+      //add its midpoint
+      const unsigned int midpos = edge_midpoints.size() ;
+      edge_midpoints.resize(midpos+3) ;
+      Eigen::Map<Vector> midpoint(edge_midpoints.data() + midpos) ;
+      midpoint = 0.5*(v0_pos + v1_pos) ;
+    }
+  }
+
+  //check if any edge is on the boundary
+  const unsigned int besize = boundary_edges.size() ;
+  if(besize > 0) {
+    //reset the edge normals of the boundary edges
+    for(unsigned int e_index = 0; e_index < boundary_edges.size(); ++e_index) {
+      const unsigned int edge = boundary_edges[e_index] ;
+      for(int i = 0; i < 3; ++i) {
+        output[3*edge+i] = 0 ;
+      }
+    }
+
+    //compute normals on geometric neighbourhoods
+    NeighbourhoodComputer<Mesh> n_computer( mesh,
+                                            edge_midpoints.data(),
+                                            besize
+                                          ) ;
+    NeighNormalCompute<Mesh> action( mesh,
+                                     edge_midpoints.data(),
+                                     boundary_edges.data(),
+                                     radius,
+                                     output,
+                                     false
+                                   ) ;
+    n_computer.compute(radius,action) ;
+
+    //normalize the boundary edge normals
+    for(unsigned int e_index = 0; e_index < boundary_edges.size(); ++e_index) {
+      const unsigned int edge = boundary_edges[e_index] ;
+      Eigen::Map<Vector> normal(output + 3*edge) ;
+      const Scalar n_len = normal.norm() ;
+      if(n_len != 0) {
+        normal /= n_len ;
+      }
+    }
+  }
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/normals_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/normals_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a8807bc34a22f8f0e9a43ada34022daf2549d89f
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/normals_fwd.hpp
@@ -0,0 +1,58 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_NORMALS_FWD_HPP_
+#define _REVOROPT_MESH_NORMALS_FWD_HPP_
+
+namespace Revoropt {
+
+/* Face normal */
+template<typename Mesh>
+void face_normal ( const Mesh* mesh, 
+                   unsigned int index, 
+                   typename Mesh::Scalar* output 
+                 ) ;
+
+/* Connected normals (based on the faces connected to the vertex) */
+template<typename Mesh>
+void connected_vertex_normals( const Mesh* mesh, 
+                               typename Mesh::Scalar* output 
+                             ) ;
+
+/* Robust normals on boundary vertices (handling disconnected meshes) */
+template<typename Mesh>
+void robust_vertex_normals( const Mesh* mesh, 
+                            typename Mesh::Scalar radius,
+                            typename Mesh::Scalar* output
+                          ) ;
+
+/* Robust normals on every vertex */
+template<typename Mesh>
+void full_robust_vertex_normals( const Mesh* mesh, 
+                                 typename Mesh::Scalar radius,
+                                 typename Mesh::Scalar* output
+                               ) ;
+
+/* Connected edge normals baseg on the mesh connectivty */
+template< typename Mesh >
+void connected_edge_normals( const Mesh* mesh, 
+                             typename Mesh::Scalar* output 
+                           ) ;
+
+/* Robust edge normals */
+template<typename Mesh>
+void robust_edge_normals( const Mesh* mesh, 
+                          typename Mesh::Scalar radius,
+                          typename Mesh::Scalar* output
+                        ) ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/sampling_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/sampling_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..42aeee578eadf6cfdb4da58d9c8251a0138d6058
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/sampling_def.hpp
@@ -0,0 +1,97 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_SAMPLING_HPP_
+#define _REVOROPT_MESH_SAMPLING_HPP_
+
+#include <Revoropt/Tools/measure_def.hpp>
+
+#include "sampling_fwd.hpp"
+
+namespace Revoropt {
+
+/* Generate a random set of sites on a mesh */
+template<typename Triangulation>
+void generate_random_sites( const Triangulation* mesh, 
+                            unsigned int sites_size,
+                            typename Triangulation::Scalar* output_sites, 
+                            typename Triangulation::Scalar* triangle_weights,
+                            bool reset_random
+                          ) {
+  //typedefs
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef typename Triangulation::Scalar Scalar ;
+  typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+
+  //initialize random generator if requested
+  if(reset_random) {
+    srand(0) ;
+  }
+
+  //sizes
+  const unsigned int fsize = mesh->faces_size() ;
+
+  //compute the area range of the triangles (without cross products)
+  Scalar area_ranges[fsize] ;
+  for(unsigned int i=0; i<fsize; ++i) {
+    const unsigned int* fverts = mesh->face(i) ;
+    const Scalar* v0 = mesh->vertex(fverts[0]) ;
+    const Scalar* v1 = mesh->vertex(fverts[1]) ;
+    const Scalar* v2 = mesh->vertex(fverts[2]) ;
+
+    const Scalar area = triangle_weights == NULL ?
+      triangle_area<Dim>(v0,v1,v2) :
+      triangle_weights[i]*triangle_area<Dim>(v0,v1,v2) ;
+
+    area_ranges[i] = i==0 ? area : area_ranges[i-1]+area ;
+    if(area_ranges[i] != area_ranges[i]) {
+      std::cout << "nan area range for face " << i << ", area " << area_ranges[i] << std::endl ;
+      for(int j = 0; j < Dim; ++j) { std::cout << v0[j] << " " ; } ;
+      std::cout << std::endl ;
+      for(int j = 0; j < Dim; ++j) { std::cout << v1[j] << " " ; } ;
+      std::cout << std::endl ;
+      for(int j = 0; j < Dim; ++j) { std::cout << v2[j] << " " ; } ;
+      std::cout << std::endl ;
+      if(triangle_weights != NULL) {
+        std::cout << triangle_weights[i] << std::endl ;
+      }
+      assert(false) ;
+    }
+  }
+  const Scalar max_area = area_ranges[fsize-1] ;
+
+  //generate random sites
+  for(unsigned int i=0; i<sites_size; ++i) {
+    //get a random triangle by area
+    Scalar rand_area = ((Scalar) rand() / (Scalar) RAND_MAX) * max_area ;
+    Scalar* pos = std::upper_bound(area_ranges,area_ranges+fsize,rand_area) ;
+    unsigned int tri_index = pos - area_ranges ;
+
+    //get random barycentric coordinates
+    Scalar u = sqrt((Scalar) rand() / (Scalar) RAND_MAX) ;
+    Scalar v = (Scalar) rand() / (Scalar) RAND_MAX ;
+    v *= u ;
+    u = 1-u ;
+    Scalar w = 1-u-v ;
+    
+    const unsigned int* fverts = mesh->face(tri_index) ;
+    Eigen::Map<const Vector> v0(mesh->vertex(fverts[0])) ;
+    Eigen::Map<const Vector> v1(mesh->vertex(fverts[1])) ;
+    Eigen::Map<const Vector> v2(mesh->vertex(fverts[2])) ;
+
+    //add the new site
+    Eigen::Map<Vector> site(output_sites + Dim*i) ;
+    site = u*v0 + v*v1 + w*v2 ;
+  }
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/sampling_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/sampling_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..227caebba7905f6fd21742547862c29cf0445239
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/sampling_fwd.hpp
@@ -0,0 +1,27 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_SAMPLING_FWD_HPP_
+#define _REVOROPT_MESH_SAMPLING_FWD_HPP_
+
+namespace Revoropt {
+
+/* Generate a random set of sites on a mesh */
+template<typename Triangulation>
+void generate_random_sites( const Triangulation* mesh, 
+                            unsigned int sites_size,
+                            typename Triangulation::Scalar* output_sites, 
+                            typename Triangulation::Scalar* triangle_weights = NULL,
+                            bool reset_random = false
+                          ) ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/splitting_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/splitting_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..025b7d45205cd4ff6a4797407ec9ea70e10af017
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/splitting_def.hpp
@@ -0,0 +1,1076 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_SPLITTING_DEF_HPP_
+#define _REVOROPT_MESH_SPLITTING_DEF_HPP_
+
+#include "splitting_fwd.hpp"
+#include "all_def.hpp"
+#include "debug_def.hpp"
+#include "connectivity_def.hpp"
+#include "measure_def.hpp"
+#include "normals_def.hpp"
+
+#include <eigen3/Eigen/Dense>
+#include <queue>
+
+namespace Revoropt {
+
+/**{{{ Splitting edges in halves (decimation) **/
+
+/* Split a face of the mesh in two given an edge index and the index of its
+ * center vertex. The neighbourhoods along the split edge are set to none.
+ * Returns the indices of the two split faces and their sizes. within these
+ * faces, the layout of the vertices is such that :
+ *   - the first face uses the mid vertex and the next one along the edge
+ *   - the second face uses the first vertex of the edge and the mid one
+ *   - the mid vertex is the last vertex in both faces */
+template<typename MeshBuilder>
+void face_split( MeshBuilder* mesh,
+                 unsigned int face,
+                 unsigned int edge_index,
+                 unsigned int mid_vertex_index,
+                 unsigned int* split_face_indices //output
+               ) {
+  //size of the face
+  const unsigned int fsize = mesh->face_size(face) ;
+  //vertices of the face
+  const unsigned int* fverts = mesh->face(face) ;
+  //neighbours of the face
+  const unsigned int* fneigh = mesh->face_neighbours(face) ;
+
+  //copy the face vertices
+  std::vector<unsigned int> fverts_copy(fverts, fverts+fsize) ;
+  //copy the face neighbours
+  std::vector<unsigned int> fneigh_copy(fneigh, fneigh+fsize) ;
+
+  //split face sizes
+  unsigned int split_face_sizes[2] ;
+  split_face_sizes[0] = fsize/2 + 2 ;
+  split_face_sizes[1] = fsize - split_face_sizes[0] + 3 ;
+
+  //allocation
+  if(fsize < 5) {
+    //the first new face exactly has the size of the split face
+    //indices of the new fces
+    split_face_indices[0] = face ;
+    //compatibility of the mesh face size is checked here
+    split_face_indices[1] = mesh->extend_faces(1,split_face_sizes[1]) ; 
+  } else {
+    //translate face vector to remove one face
+    mesh->erase_faces(face, face+1) ;
+    //allocate space for the new faces
+    //indices of the new faces
+    //compatibility of the mesh face size is checked here
+    split_face_indices[0] = mesh->extend_faces(1,split_face_sizes[0]) ;
+    split_face_indices[1] = mesh->extend_faces(1,split_face_sizes[1]) ;
+  }
+
+  //index of the vertex to connect to the mid vertex of the split edge
+  const unsigned int vopp = (edge_index + fsize/2 + 1) % fsize ;
+
+  //fill the first face vertices and neighbours
+  unsigned int* split_verts0 = mesh->face(split_face_indices[0]) ;
+  unsigned int* split_neigh0 = mesh->face_neighbours(split_face_indices[0]) ;
+  for(unsigned int k = 0 ; k < split_face_sizes[0]-1 ; ++k) {
+    //vertex
+    const unsigned int v0 = fverts_copy[(edge_index+1+k)%fsize] ;
+    //set a vertex of the new face
+    split_verts0[k] = v0 ;
+    if(k != split_face_sizes[0]-2) {
+      //neighbouring face
+      const unsigned int n_face = fneigh_copy[(edge_index+1+k)%fsize] ;
+      //next vertex
+      const unsigned int v1 = fverts_copy[(edge_index+2+k)%fsize] ;
+      //set a neighbour of the new face
+      split_neigh0[k] = n_face ;
+      //set the neighbour of the neighbour face
+      if(n_face != MeshBuilder::NO_NEIGHBOUR) {
+        const unsigned int n_edge_index = mesh->edge_face_index(n_face,v0,v1) ;
+        assert( n_edge_index != MeshBuilder::NO_INDEX &&
+                "error : connectivity mismatch"
+              ) ;
+        mesh->face_neighbours(n_face)[n_edge_index] = split_face_indices[0] ;
+      }
+    }
+  }
+  //add the new vertex to the first face
+  split_verts0[split_face_sizes[0]-1] = mid_vertex_index ;
+
+  //fill the second face vertices
+  unsigned int* split_verts1 = mesh->face(split_face_indices[1]) ;
+  unsigned int* split_neigh1 = mesh->face_neighbours(split_face_indices[1]) ;
+  for(unsigned int k = 0 ; k < split_face_sizes[1]-1 ; ++k) {
+    //vertex
+    const unsigned int v0 = fverts_copy[(vopp+k)%fsize] ;
+    //set a vertex of the new face
+    split_verts1[k] = v0 ;
+    if(k != split_face_sizes[1]-2) {
+      //neighbouring face
+      const unsigned int n_face = fneigh_copy[(vopp+k)%fsize] ;
+      //next vertex
+      const unsigned int v1 = fverts_copy[(vopp+k+1)%fsize] ;
+      //set a neighbour of the new face
+      split_neigh1[k] = n_face ;
+      if(n_face != MeshBuilder::NO_NEIGHBOUR) {
+        //set the neighbour of the neighbour face
+        const unsigned int n_edge_index = mesh->edge_face_index(n_face,v0,v1) ;
+        assert( n_edge_index != MeshBuilder::NO_INDEX &&
+                "error : connectivity mismatch"
+              ) ;
+        mesh->face_neighbours(n_face)[n_edge_index] = split_face_indices[1] ;
+      }
+    }
+  }
+  //add the new vertex to the second face
+  split_verts1[split_face_sizes[1]-1] = mid_vertex_index ;
+
+  //set the neighbourhoods along the split edge
+  split_neigh0[split_face_sizes[0]-2] = split_face_indices[1] ;
+  split_neigh1[split_face_sizes[1]-1] = split_face_indices[0] ;
+
+  //set the neighbourhoods along the pieces of the split edge to NO_NEIGHBOUR
+  split_neigh0[split_face_sizes[0]-1] = MeshBuilder::NO_NEIGHBOUR ;
+  split_neigh1[split_face_sizes[1]-2] = MeshBuilder::NO_NEIGHBOUR ;
+
+}
+
+/* Split an edge of a mesh builder. If the provided arrays are not NULL, returns
+ * the indices and sizes of the new faces. The size of the arrays to provide is 
+ * two in case of a border edge, and 4 otherwise.*/
+template<typename MeshBuilder>
+void edge_split( MeshBuilder* mesh, 
+                 unsigned int face, 
+                 unsigned int edge_index,
+                 unsigned int* split_face_indices = NULL //output
+                ) {
+  //types
+  typedef Eigen::Matrix< typename MeshBuilder::Scalar,
+                         MeshBuilder::VertexDim,
+                         1
+                       > Vector ;
+
+  //handle NULL output
+  bool handle_null_input = split_face_indices == NULL ;
+  if(handle_null_input){
+    split_face_indices = new unsigned int[4] ;
+  }
+
+  //size of the face
+  const unsigned int fsize = mesh->face_size(face) ;
+  //vertices of the face
+  const unsigned int* fverts = mesh->face(face) ;
+  //neighbours of the face
+  const unsigned int* fneigh = mesh->face_neighbours(face) ;
+
+  //vertices of the edge
+  const unsigned int v1 = fverts[ edge_index         ] ;
+  const unsigned int v2 = fverts[(edge_index+1)%fsize] ;
+
+  //reserve space for a new vertex
+  const unsigned int vmid = mesh->extend_vertices(1) ;
+
+  //add the edge center to the vertices
+  Eigen::Map<const Vector> v1pos(mesh->vertex(v1)) ;
+  Eigen::Map<const Vector> v2pos(mesh->vertex(v2)) ;
+  Eigen::Map<Vector> vmidpos(mesh->vertex(vmid)) ;
+  vmidpos = 0.5*(v1pos+v2pos) ;
+  
+  //neighbouring face along the edge
+  const unsigned int n_face = fneigh[edge_index] ;
+
+  //check if the face edge is on the buondary
+  if(n_face == MeshBuilder::NO_NEIGHBOUR) {
+    //the edge is on the boundary, no neighbouring face to handle
+    //split the face
+    face_split( mesh, 
+                face, edge_index, vmid, 
+                split_face_indices
+              ) ;
+  } else {
+    //a neighbouring face exists and is to be handled
+    //index of the edge within the neighbouring face
+    unsigned int n_edge_index = mesh->edge_face_index(n_face,v1,v2) ;
+    assert( n_edge_index != MeshBuilder::NO_INDEX &&
+            "error : connectivity mismatch."
+          ) ;
+    //determine orientation
+    const unsigned int shift = mesh->face(n_face)[n_edge_index]==v2 ? 0 : 1 ;
+    //split the face
+    face_split( mesh, 
+                face, edge_index, vmid, 
+                split_face_indices
+              ) ;
+    //split the neighbouring face
+    face_split( mesh, 
+                n_face, n_edge_index, vmid, 
+                split_face_indices + 2
+              ) ;
+
+    //reconnect the split faces along the split edge
+    //neighbourhoods of the split faces
+    unsigned int* split_fneigh[4] ;
+    unsigned int split_fsize[4] ;
+    for(int i=0; i<4; ++i) {
+      split_fneigh[i] = mesh->face_neighbours(split_face_indices[i]) ;
+      split_fsize[i] = mesh->face_size(split_face_indices[i]) ;
+    }
+    //fisrt face from the split of face
+    const unsigned int s_face0 = split_face_indices[0] ;
+    //second face from the split of face
+    const unsigned int s_face1 = split_face_indices[1] ;
+    //face from the split of n_face next to the first split face of face
+    const unsigned int ns_face0 = split_face_indices[3-shift] ;
+    //face from the split of n_face next to the second split face of face
+    const unsigned int ns_face1 = split_face_indices[2+shift] ;
+    //connect
+    split_fneigh[0][split_fsize[0]-1] = ns_face0 ;
+    split_fneigh[3-shift][split_fsize[3-shift]-2+shift] = s_face0 ;
+    split_fneigh[1][split_fsize[1]-2] = ns_face1 ;
+    split_fneigh[2+shift][split_fsize[2+shift]-1-shift] = s_face1 ;
+  }
+
+  //cleanup if necessary
+  if(handle_null_input){
+    delete[] split_face_indices ;
+  }
+}
+
+template<typename Mesh, typename MeshBuilder>
+void split_longest_edge( const Mesh* input, 
+                         unsigned int niter, 
+                         MeshBuilder* mesh
+                       ) {
+  //dimension
+  enum { Dim = Mesh::VertexDim } ;
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //vertex pair
+  typedef std::pair<unsigned int, unsigned int> VertexPair ;
+  //heap edge
+  typedef Decimate::HeapEdge<Scalar> HeapEdge ;
+
+  //initialize the output mesh
+  mesh->init(input) ;
+
+  //the longest edge for each face
+  std::vector<VertexPair> longest_edge(mesh->faces_size()) ;
+
+  //a heap to track the longest edge
+  std::vector<HeapEdge> edge_heap ;
+
+  //initialize the heap and longest edges
+  for(unsigned int face = 0; face < mesh->faces_size(); ++face) {
+    //size of the face
+    const unsigned int fsize = mesh->face_size(face) ;
+    //vertices of the face
+    const unsigned int* fverts = mesh->face(face) ;
+    //neighbours of the face
+    const unsigned int* fneigh = mesh->face_neighbours(face) ;
+    //longest edge of the face
+    Scalar length ;
+    unsigned int edge = face_longest_edge(mesh, face, &length) ;
+    //vertices of the edge
+    const unsigned int v0 = fverts[ edge         ] ;
+    const unsigned int v1 = fverts[(edge+1)%fsize] ;
+    //sort indices
+    const unsigned int vmin = v0 < v1 ? v0 : v1 ;
+    const unsigned int vmax = v0 < v1 ? v1 : v0 ;
+    //add the longest edge for the current face
+    longest_edge[face] = VertexPair(vmin,vmax) ;
+    //check if that edge was already added into the heap
+    const unsigned int n_face = fneigh[edge] ;
+    if((n_face > face) || (longest_edge[n_face] != VertexPair(vmin,vmax))) {
+      //the edge has not been added, add it
+      edge_heap.resize(edge_heap.size()+1) ;
+      HeapEdge& he = edge_heap.back() ;
+      he.face = face ;
+      he.edge = edge ;
+      he.vmin = vmin ;
+      he.vmax = vmax ;
+      he.length = length ;
+    }
+  }
+
+  //sort the heap
+  std::make_heap(edge_heap.begin(), edge_heap.end()) ;
+
+  //TODO erase from longest edge if original face not reused
+
+  //iteratively split the longest edge
+  unsigned int new_faces[4] ;
+  for(unsigned int iter = 0; iter < niter; ++iter) {
+    //get the longest edge
+    const HeapEdge& he = edge_heap.front() ;
+    Scalar ref_len ;
+    //number of faces before the split
+    const unsigned int mesh_size = mesh->faces_size() ;
+    //opposite face split
+    const unsigned int split_nface = mesh->face_neighbours(he.face)[he.edge] ;
+
+    //split the edge
+    edge_split(mesh, he.face, he.edge, new_faces) ;
+
+    //number of faces split (1 or 2 depending on whether the edge is a boundary)
+    const unsigned int nsplits = mesh->faces_size() - mesh_size ;
+
+    //update longest edge array in case of face erase
+    if(mesh->face_size(he.face) > 4) {
+      longest_edge.erase(longest_edge.begin()+he.face) ;
+    }
+    if( (split_nface != Mesh::NO_NEIGHBOUR) && 
+        (mesh->face_size(split_nface) > 4) ) {
+      longest_edge.erase(longest_edge.begin()+split_nface) ;
+    }
+
+    //remove the edge from the heap
+    std::pop_heap(edge_heap.begin(), edge_heap.end()); 
+    edge_heap.pop_back() ;
+
+    //resize longest edge array
+    longest_edge.resize(longest_edge.size()+nsplits) ;
+
+    //add (if necessary) the longest face edges of the new faces
+    for(unsigned int i = 0; i < 2*nsplits; ++i ) {
+      //new face
+      const unsigned int face = new_faces[i] ;
+      //size of the face
+      const unsigned int fsize = mesh->face_size(face) ;
+      //vertices of the face
+      const unsigned int* fverts = mesh->face(face) ;
+      //neighbours of the face
+      const unsigned int* fneigh = mesh->face_neighbours(face) ;
+      //longest edge of the face
+      Scalar length ;
+      unsigned int edge = face_longest_edge(mesh, face, &length) ;
+      //vertices of the edge
+      const unsigned int v0 = fverts[ edge         ] ;
+      const unsigned int v1 = fverts[(edge+1)%fsize] ;
+      //sort indices
+      const unsigned int vmin = v0 < v1 ? v0 : v1 ;
+      const unsigned int vmax = v0 < v1 ? v1 : v0 ;
+      //add the longest edge for the current face
+      longest_edge[face] = VertexPair(vmin,vmax) ;
+      //check if that edge was already added into the heap
+      const unsigned int n_face = fneigh[edge] ;
+      bool n_face_is_new_and_after = false ;
+      for(unsigned int new_face = i+1; new_face < 2*nsplits; ++new_face) {
+        if(new_face < 4 && n_face == new_faces[new_face]) {
+          n_face_is_new_and_after = true ;
+          break ;
+        }
+      }
+      if( n_face_is_new_and_after || (n_face == Mesh::NO_NEIGHBOUR) ||
+          (longest_edge[n_face] != VertexPair(vmin,vmax))
+        ) {
+        //the edge has not been added, add it
+        edge_heap.resize(edge_heap.size()+1) ;
+        HeapEdge& new_he = edge_heap.back() ;
+        new_he.face = face ;
+        new_he.edge = edge ;
+        new_he.vmin = vmin ;
+        new_he.vmax = vmax ;
+        new_he.length = length ;
+        //preserve the heap property
+        std::push_heap(edge_heap.begin(), edge_heap.end()) ;
+      } else {
+      }
+    }
+  }
+}
+
+//}}}
+
+/**{{{ Normal bevel : split triangles to improve normal interpolation **/
+
+namespace Bevel {
+
+/* criterion based on the normal to decide whether an edge needs splitting */
+template<typename Mesh>
+EdgeSplitType NormalSplitCriterion<Mesh>::edge_type( unsigned int face, 
+                                                     unsigned int edge 
+                                                   ) const {
+  //edge index
+  const unsigned int edge_index = mesh_->face_offset(face) + edge ;
+  //face size
+  const unsigned int fsize = mesh_->face_size(face) ;
+  //face vertices
+  const unsigned int* fverts = mesh_->face(face) ;
+  //edge vertices
+  const unsigned int v0 = fverts[edge] ;
+  const unsigned int v1 = fverts[(edge+1)%fsize] ;
+  //in case of boundary restriction, do not split inner edges
+  if(restrict_to_boundary_) {
+    if(!boundary_vertices_[v0] && !boundary_vertices_[v1]) {
+      return SPLIT_NONE ;
+    }
+  }
+  ////other vertices centroid
+  //Vector g = Vector::Zero() ;
+  //for(unsigned int v = 2; v < fsize; ++v) {
+  //  g += Eigen::Map<const Vector>(mesh_->vertex(fverts[(edge+v)%fsize])) ;
+  //}
+  //g /= fsize-2 ;
+  ////opposite angle criterion
+  //const Vector gv0 = g - Eigen::Map<const Vector>(mesh_->vertex(v0)) ;
+  //const Vector gv1 = g - Eigen::Map<const Vector>(mesh_->vertex(v1)) ;
+  //if(gv0.dot(gv1)/(gv0.norm()*gv1.norm()) > cosine_threshold_) {
+  //  return SPLIT_NONE ;
+  //}
+  //normals
+  Eigen::Map<const Vector> enormal(edge_normals_.data() + 3*edge_index) ;
+  Eigen::Map<const Vector> vnormal0(vertex_normals_.data() + 3*v0) ;
+  Eigen::Map<const Vector> vnormal1(vertex_normals_.data() + 3*v1) ;
+  //test
+  int split_type = 0 ;
+  if(enormal.dot(vnormal0) < cosine_threshold_) {
+    split_type += 1 ;
+  } else {
+    //std::cout << enormal.dot(vnormal0) << std::endl ;
+  }
+  if(enormal.dot(vnormal1) < cosine_threshold_) {
+    split_type += 2 ;
+  } else {
+    //std::cout << enormal.dot(vnormal1) << std::endl ;
+  }
+  return (EdgeSplitType) split_type ;
+}
+
+template<typename Mesh>
+void NormalSplitCriterion<Mesh>::init() {
+  //allocate space for normals
+  edge_normals_.resize(3*mesh_->face_vertices_size()) ;
+  vertex_normals_.resize(3*mesh_->vertices_size()) ;
+  boundary_vertices_.assign(mesh_->vertices_size(), false) ;
+  //compute vertex normals
+  full_robust_vertex_normals(mesh_,normal_radius_,vertex_normals_.data()) ;
+  //compute edge normals
+  robust_edge_normals(mesh_,normal_radius_,edge_normals_.data()) ;
+
+  //FIXME
+  EdgeLayer<Mesh> edge_layer(mesh_) ;
+  edge_midpoints_.assign(3*mesh_->face_vertices_size(),0) ;
+  for(unsigned int edge = 0; edge < mesh_->face_vertices_size(); ++edge) {
+    //vertices of the edge
+    const unsigned int v0 = edge_layer.edge_start_vertex(edge) ;
+    const unsigned int v1 = edge_layer.edge_end_vertex(edge) ;
+    if(edge_layer.is_border(edge)) {
+      boundary_vertices_[v0] = true ;
+      boundary_vertices_[v1] = true ;
+    }
+    Eigen::Map<const Vector> v0_pos(mesh_->vertex(v0)) ;
+    Eigen::Map<const Vector> v1_pos(mesh_->vertex(v1)) ;
+    //add its midpoint
+    Eigen::Map<Vector> midpoint(edge_midpoints_.data() + 3*edge) ;
+    midpoint = 0.5*(v0_pos + v1_pos) ;
+  }
+}
+
+/* triangle classification, depending on its edges split types */
+void normalize_triangle_split( const EdgeSplitType edge_types[3],
+                               FaceSplitType* split_type //output
+                             ) {
+  /* precomputed triangle split type translation */
+  static const unsigned char triangle_split_translate[64] = {
+    0 , 1 , 1 , 2 , 1 , 3 , 4 , 5 , 
+    1 , 6 , 3 , 7 , 2 , 7 , 5 , 8 , 
+    1 , 3 , 6 , 7 , 3 , 9 , 10, 11, 
+    4 , 10, 10, 12, 5 , 11, 13, 14, 
+    1 , 4 , 3 , 5 , 6 , 10, 10, 13, 
+    3 , 10, 9 , 11, 7 , 12, 11, 14, 
+    2 , 5 , 7 , 8 , 7 , 11, 12, 14, 
+    5 , 13, 11, 14, 8 , 14, 14, 15
+  } ;
+
+  //initialize minimal index
+  split_type->index = 64 ;
+  //initialize rotation and symetry
+  split_type->rotation = 0 ;
+  split_type->symetry = false ;
+  //loop over the transformations
+  unsigned int cur_index = 0 ;
+  for(int sym = -1; sym < 2; sym += 2) {
+    for(int rot = 0; rot < 3; ++rot) {
+      //reinitialize index
+      cur_index = 0 ;
+      //compute index
+      for(int edge = 0; edge < 3; ++edge) {
+        cur_index *= 4 ;
+        cur_index += sym < 0 ?
+          edge_types[(5 + sym*(rot+edge))%3] :
+          edge_split_type_sym(edge_types[(5 + sym*(rot+edge))%3]) ;
+      }
+      //check if this index is minimal for this configuration
+//      std::cout << "score is " << cur_index << " for rotation " << rot << " and symmetry " << (sym==1) << std::endl ;
+      if(cur_index < split_type->index) {
+        //store the index, rotation and symetry
+        split_type->index = cur_index ;
+        split_type->rotation = rot ;
+        split_type->symetry = (sym == 1) ;
+      }
+    }
+  }
+  //translate type index
+  split_type->index = triangle_split_translate[split_type->index] ;
+}
+
+/* compute the split points of an edge given its type, a radius and length */
+/* returns the split really performed given the radius and edge length */
+
+template<typename Mesh>
+EdgeSplitType edge_split( const Mesh* mesh,
+                          unsigned int face,
+                          unsigned int edge,
+                          typename Mesh::Scalar radius,
+                          EdgeSplitType split_type,
+                          std::vector<typename Mesh::Scalar>& coords, //i/o
+                          std::vector<unsigned int>& edge_split_verts //output
+                        ) {
+  //dimension
+  enum { Dim = Mesh::VertexDim } ;
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //vector type
+  typedef Eigen::Matrix<Scalar,Mesh::VertexDim,1> Vector ;
+
+  if(split_type == SPLIT_NONE) {
+    //edge is not split
+    edge_split_verts.push_back(NO_VERTEX) ;
+    edge_split_verts.push_back(NO_VERTEX) ;
+  } else {
+    //size of the face
+    const unsigned int fsize = mesh->face_size(face) ;
+    //face vertices
+    const unsigned int* fverts = mesh->face(face) ;
+    //vertices of the edge
+    const unsigned int v0 = fverts[ edge         ] ;
+    const unsigned int v1 = fverts[(edge+1)%fsize] ;
+    //cosines of the angles at the extremities
+    const Scalar v0cos = 0 ;//face_angle_cos(mesh, face,  edge         ) ;
+    const Scalar v1cos = 0 ;//face_angle_cos(mesh, face, (edge+1)%fsize) ;
+    //vertex positions
+    Eigen::Map<const Vector> v0_pos(mesh->vertex(v0)) ;
+    Eigen::Map<const Vector> v1_pos(mesh->vertex(v1)) ;
+    //edge vector
+    const Vector edge_vect = (v1_pos - v0_pos) ;
+    //length of the edge
+    const Scalar e_len = edge_vect.norm() ;
+    //lehgths of the cuts at each extremity
+    const Scalar v0len = v0cos == 1 ? e_len : radius/sqrt(1-v0cos*v0cos) ;
+    const Scalar v1len = v1cos == 1 ? e_len : radius/sqrt(1-v1cos*v1cos) ;
+    if(split_type == SPLIT_BOTH) {
+      //edge is split at both ends
+      //handle merging
+      if(e_len > (v0len + v1len + radius)) {
+        //no merging
+        //split vertex indices
+        const unsigned int vsplit0 = coords.size()/Dim ;
+        const unsigned int vsplit1 = vsplit0+1 ;
+        //allocate space for new vertices
+        coords.resize(coords.size() + 2*Dim) ;
+        //split vertex positions
+        Eigen::Map<Vector> vsplit0_pos(coords.data() + Dim*vsplit0) ;
+        Eigen::Map<Vector> vsplit1_pos(coords.data() + Dim*vsplit1) ;
+        vsplit0_pos = v0_pos + v0len/e_len*edge_vect ;
+        vsplit1_pos = v1_pos - v1len/e_len*edge_vect ;
+        //append split vertex indices
+        edge_split_verts.push_back(vsplit0) ;
+        edge_split_verts.push_back(vsplit1) ;
+//        std::cout << "split both at " << vsplit0 << " " << vsplit1 << std::endl ;
+        return SPLIT_BOTH ;
+      } else if(e_len > (v0len + v1len)) {
+        //merging at the edge barycenter with weights v0len and v1len
+        //split vertex index
+        const unsigned int vsplit = coords.size()/Dim ;
+        //allocate space for new vertices
+        coords.resize(coords.size() + Dim) ;
+        //split vertex positions
+        Eigen::Map<Vector> vsplit_pos(coords.data() + Dim*vsplit) ;
+        vsplit_pos = (v1len*v0_pos + v0len*v1_pos) / (v0len + v1len) ;
+        //append split vertex indices, duplicated here because of the merge
+        edge_split_verts.push_back(vsplit) ;
+        edge_split_verts.push_back(vsplit) ;
+        return SPLIT_BOTH ;
+      } else {
+        //splitting canceled
+        edge_split_verts.push_back(NO_VERTEX) ;
+        edge_split_verts.push_back(NO_VERTEX) ;
+        return SPLIT_NONE ;
+      }
+    } else {
+      //one single end is split
+      //handle merging
+      const Scalar cutlen = split_type == SPLIT_FIRST ? v0len : v1len ;
+      if(e_len > (cutlen + radius)) {
+        //no merging
+        //split vertex index
+        const unsigned int vsplit = coords.size()/Dim ;
+        //allocate space for new vertices
+        coords.resize(coords.size() + Dim) ;
+        //split vertex positions
+        Eigen::Map<Vector> vsplit_pos(coords.data() + Dim*vsplit) ;
+        if(split_type == SPLIT_FIRST) {
+          vsplit_pos = v0_pos + cutlen/e_len*edge_vect ;
+          //append split vertex indices
+          edge_split_verts.push_back(vsplit) ;
+          edge_split_verts.push_back(NO_VERTEX) ;
+          return SPLIT_FIRST ;
+        } else {
+          vsplit_pos = v1_pos - cutlen/e_len*edge_vect ;
+          //append split vertex indices
+          edge_split_verts.push_back(NO_VERTEX) ;
+          edge_split_verts.push_back(vsplit) ;
+          return SPLIT_SECOND ;
+        }
+      } else {
+        //splitting canceled
+        edge_split_verts.push_back(NO_VERTEX) ;
+        edge_split_verts.push_back(NO_VERTEX) ;
+        return SPLIT_NONE ;
+      }
+    }
+  }
+  return SPLIT_NONE ;
+}
+
+/* split a face given its split type and the edge split vertices */
+template<typename Mesh>
+void face_split( const Mesh* mesh,
+                 unsigned int face,
+                 typename Mesh::Scalar radius,
+                 const EdgeSplitType edge_types[3],
+                 const unsigned int edge_split_verts[6],
+                 std::vector<typename Mesh::Scalar>& coords, //output
+                 std::vector<unsigned int>& split_faces //output
+               ) {
+  /* predifined triangle split patterns    Ref edge types */
+  static const unsigned char triangle_split_0[3]   = { //0 0 0
+    0,1,2
+  } ;
+  static const unsigned char triangle_split_1[6]   = { //1 0 0 
+    0,1,3,1,2,3
+  } ;
+  static const unsigned char triangle_split_2[9]   = { //3 0 0
+    0,1,4,1,2,4,2,3,4
+  } ;
+  static const unsigned char triangle_split_3[9]   = { //1 1 0
+    0,1,4,1,2,3,1,3,4
+  } ;
+  static const unsigned char triangle_split_4[9]   = { //2 1 0
+    0,1,3,1,2,3,0,3,4
+  } ;
+  static const unsigned char triangle_split_5[12]  = { //3 1 0
+    0,1,5,1,2,4,1,4,5,2,3,4
+  } ;
+  static const unsigned char triangle_split_6[9]   = { //1 2 0
+    0,1,3,0,3,4,1,2,3
+  } ;
+  static const unsigned char triangle_split_7[12]  = { //3 2 0
+    0,4,5,0,1,4,1,2,4,2,3,4
+  } ;
+  static const unsigned char triangle_split_8[15]  = { //3 3 0
+    0,5,6,0,1,5,1,4,5,1,2,4,2,3,4
+  } ;
+  static const unsigned char triangle_split_9[12]  = { //1 1 1
+    0,1,5,1,3,5,1,2,3,5,3,4
+  } ;
+  static const unsigned char triangle_split_10[12] = { //2 1 1
+    0,1,5,1,3,5,1,2,3,5,3,4
+  } ;
+  static const unsigned char triangle_split_11[15] = { //3 1 1
+    0,1,6,1,2,6,2,3,4,2,4,6,4,5,6
+  } ;
+  static const unsigned char triangle_split_12[21] = { //3 2 1
+    0,1,7,0,7,6,1,2,7,2,3,7,7,3,4,6,7,4,6,4,5
+  } ;
+  static const unsigned char triangle_split_13[15] = { //2 3 1
+    0,1,6,1,2,3,1,3,6,6,3,4,6,4,5
+  } ;
+  static const unsigned char triangle_split_14[24] = { //3 3 1
+    0,1,8,0,8,7,1,2,8,2,4,8,2,3,4,8,5,7,8,4,5,7,5,6
+  } ;
+  static const unsigned char triangle_split_15[39] = { //3 3 3
+    0,1,8,1,9,8,1,2,9,2,10,9,2,4,10,2,3,4,9,10,11,
+    8,9,11,8,11,7,10,4,5,10,5,11,11,5,7,6,7,5
+  } ;
+  static const unsigned char triangle_split_sizes[16] = {
+    1,2,3,3,3,4,3,4,5,4,4,5,7,5,8,13
+  } ;
+  static const unsigned char* triangle_patterns[16] = {
+    triangle_split_0,
+    triangle_split_1,
+    triangle_split_2,
+    triangle_split_3,
+    triangle_split_4,
+    triangle_split_5,
+    triangle_split_6,
+    triangle_split_7,
+    triangle_split_8,
+    triangle_split_9,
+    triangle_split_10,
+    triangle_split_11,
+    triangle_split_12,
+    triangle_split_13,
+    triangle_split_14,
+    triangle_split_15
+  } ;
+
+  //dimension
+  enum { Dim = Mesh::VertexDim } ;
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //vector type
+  typedef Eigen::Matrix<Scalar,Mesh::VertexDim,1> Vector ;
+
+  //normalize the triangle split
+  FaceSplitType face_type ;
+  normalize_triangle_split(edge_types, &face_type) ;
+  
+  //collect the triangle boundary vertices
+  std::vector<unsigned int> triangle_vertices ;
+//  std::cout << "face rotation " << face_type.rotation << std::endl ;
+//  std::cout << "face symetry " << std::boolalpha << face_type.symetry << std::endl ;
+  for(int edge = 0; edge < 3; ++edge) {
+    //compute the edge index given the normalization
+    const int edge_face_index = face_type.symetry ? 
+      (4+face_type.rotation-edge)%3 :
+      (3-face_type.rotation+edge)%3 ;
+
+    //add the edge start vertex
+    const unsigned int edge_start_vertex = face_type.symetry ?
+      mesh->face_edge_end_vertex(face, edge_face_index) :
+      mesh->face_edge_start_vertex(face, edge_face_index) ;
+    triangle_vertices.push_back(edge_start_vertex) ;
+
+    //add the edge split vertices
+    const unsigned int* this_edge_split_verts = 
+      edge_split_verts + 2*edge_face_index ;
+    const EdgeSplitType edge_type = edge_types[edge_face_index] ;
+//    std::cout << "edge face index " << edge_face_index << std::endl ;
+//    std::cout << "edge type at collect " << edge_type << std::endl ;
+//    std::cout << "pushing vertex " << edge_start_vertex << std::endl ;
+    if(edge_type == SPLIT_FIRST) {
+      triangle_vertices.push_back(this_edge_split_verts[0]) ;
+    } else if(edge_type == SPLIT_SECOND) {
+      triangle_vertices.push_back(this_edge_split_verts[1]) ;
+    } else if(edge_type == SPLIT_BOTH) {
+      if(face_type.symetry) {
+        triangle_vertices.push_back(this_edge_split_verts[1]) ;
+        triangle_vertices.push_back(this_edge_split_verts[0]) ;
+      } else {
+        triangle_vertices.push_back(this_edge_split_verts[0]) ;
+        triangle_vertices.push_back(this_edge_split_verts[1]) ;
+      }
+    }
+  }
+//  std::cout << "configuration : " << face_type.index << std::endl ;
+//  std::cout << "triangle vertices size : " << triangle_vertices.size() << std::endl ;
+  
+  //add the necessary face split vertices
+  if(face_type.index == 12) {
+    //one face vertex to add
+    //allocate space for the face vertex
+    const unsigned int vsplit = coords.size()/Dim ;
+    coords.resize(coords.size() + Dim) ;
+    Eigen::Map<Vector> vsplit_pos(coords.data() + Dim*vsplit) ;
+    //check the face area to avoid degeneracies
+    if(mesh_face_area(mesh, face) < 8*radius*radius) {
+      //special case
+      //the central vertex becomes the centroid of the vertices it connects to
+      Eigen::Map<const Vector> pos0(coords.data()+Dim*triangle_vertices[0]) ;
+      Eigen::Map<const Vector> pos1(coords.data()+Dim*triangle_vertices[1]) ;
+      Eigen::Map<const Vector> pos2(coords.data()+Dim*triangle_vertices[2]) ;
+      Eigen::Map<const Vector> pos3(coords.data()+Dim*triangle_vertices[3]) ;
+      Eigen::Map<const Vector> pos4(coords.data()+Dim*triangle_vertices[4]) ;
+      Eigen::Map<const Vector> pos6(coords.data()+Dim*triangle_vertices[6]) ;
+      vsplit_pos = (pos0 + pos1 + pos2 + pos3 + pos4 + pos6)/6 ;
+    } else {
+      //compute the vertex position position
+      Eigen::Map<const Vector> pos4(coords.data()+Dim*triangle_vertices[4]) ;
+      Eigen::Map<const Vector> pos5(coords.data()+Dim*triangle_vertices[5]) ;
+      Eigen::Map<const Vector> pos6(coords.data()+Dim*triangle_vertices[6]) ;
+      vsplit_pos = pos4 + pos6 - pos5 ;
+    }
+    //add the vertex to the triangle vertices
+    triangle_vertices.push_back(vsplit) ;
+  } else if(face_type.index == 14) {
+    //one face to add
+    //allocate space for the face vertex
+    const unsigned int vsplit = coords.size()/Dim ;
+    coords.resize(coords.size() + Dim) ;
+    Eigen::Map<Vector> vsplit_pos(coords.data() + Dim*vsplit) ;
+    //check the face area to avoid degeneracies
+    if(mesh_face_area(mesh, face) < 8*radius*radius) {
+      //special case
+      //the central vertex becomes the centroid of the vertices it connects to
+      Eigen::Map<const Vector> pos0(coords.data()+Dim*triangle_vertices[0]) ;
+      Eigen::Map<const Vector> pos1(coords.data()+Dim*triangle_vertices[1]) ;
+      Eigen::Map<const Vector> pos2(coords.data()+Dim*triangle_vertices[2]) ;
+      Eigen::Map<const Vector> pos4(coords.data()+Dim*triangle_vertices[4]) ;
+      Eigen::Map<const Vector> pos5(coords.data()+Dim*triangle_vertices[5]) ;
+      Eigen::Map<const Vector> pos7(coords.data()+Dim*triangle_vertices[7]) ;
+      vsplit_pos = (pos0 + pos1 + pos2 + pos4 + pos5 + pos7)/6 ;
+    } else {
+      //compute its position
+      Eigen::Map<const Vector> pos5(coords.data()+Dim*triangle_vertices[5]) ;
+      Eigen::Map<const Vector> pos6(coords.data()+Dim*triangle_vertices[6]) ;
+      Eigen::Map<const Vector> pos7(coords.data()+Dim*triangle_vertices[7]) ;
+      vsplit_pos = pos5 + pos7 - pos6 ;
+    }
+    //add the vertex to the triangle vertices
+    triangle_vertices.push_back(vsplit) ;
+  } else if(face_type.index == 15) {
+    //three potential face vertices, merged if too close
+    //compute their positions
+    Vector fv[3] ;
+    for(int i = 0; i < 3; ++i) {
+      Eigen::Map<const Vector> v0(coords.data()+Dim*triangle_vertices[(8+3*i)%9]) ;
+      Eigen::Map<const Vector> v1(coords.data()+Dim*triangle_vertices[(0+3*i)%9]) ;
+      Eigen::Map<const Vector> v2(coords.data()+Dim*triangle_vertices[(1+3*i)%9]) ;
+      fv[i] = v0 + v2 - v1 ;
+    }
+    //merge the vertices if necessary
+    int merge_size = 0 ;
+    int last_merge = 0 ;
+    for(int i = 0; i < 3; ++i) {
+      //split vertices of the edge
+      const unsigned int sv0 = triangle_vertices[1+3*i] ;
+      const unsigned int sv1 = triangle_vertices[2+3*i] ;
+      //check whether 
+      //  1/ the edge split vertices were merged
+      //  2/ the inner vertices along this edge are not too close
+      if((sv0 == sv1) || ((fv[i] - fv[(i+1)%3]).norm() < radius)) {
+        ++merge_size ;
+        last_merge = i ;
+      }
+    }
+    if(merge_size > 0) {
+      if(merge_size == 1) {
+        //two new vertices are too close and merged
+        //allocate space for two vertices
+        const unsigned int vsplit0 = coords.size()/Dim ;
+        const unsigned int vsplit1 = vsplit0 + 1 ;
+        coords.resize(coords.size() + 2*Dim) ;
+        Eigen::Map<Vector> vsplit0_pos(coords.data()+Dim*vsplit0) ;
+        Eigen::Map<Vector> vsplit1_pos(coords.data()+Dim*vsplit1) ;
+        //merged vertex
+        vsplit0_pos = 0.5*(fv[last_merge] + fv[(last_merge+1)%3]) ;
+        //other vertex
+        vsplit1_pos = fv[(last_merge+2)%3] ;
+        //add the vertices to the triangle vertices
+        for(int i = 0; i < 3; ++i) {
+          if(i == (last_merge+2)%3) {
+            triangle_vertices.push_back(vsplit1) ;
+          } else {
+            triangle_vertices.push_back(vsplit0) ;
+          }
+        }
+      } else {
+        //the three vertices are merged
+        //allocate space for one vertex
+        const unsigned int vsplit = coords.size()/Dim ;
+        coords.resize(coords.size() + Dim) ;
+        Eigen::Map<Vector> vsplit_pos(coords.data()+Dim*vsplit) ;
+        //merged vertex
+        vsplit_pos = (fv[0] + fv[1] + fv[2])/3 ;
+        //add the vertices to the triangle vertices
+        for(int i = 0; i < 3; ++i) {
+          triangle_vertices.push_back(vsplit) ;
+        }
+      }
+    } else {
+      //no merge
+      //allocate space for three vertices
+      const unsigned int vsplit0 = coords.size()/Dim ;
+      const unsigned int vsplit1 = vsplit0 + 1 ;
+      const unsigned int vsplit2 = vsplit1 + 1 ;
+      coords.resize(coords.size() + 3*Dim) ;
+      Eigen::Map<Vector> vsplit0_pos(coords.data()+Dim*vsplit0) ;
+      Eigen::Map<Vector> vsplit1_pos(coords.data()+Dim*vsplit1) ;
+      Eigen::Map<Vector> vsplit2_pos(coords.data()+Dim*vsplit2) ;
+      //copy vertex positions
+      vsplit0_pos = fv[0] ;
+      vsplit1_pos = fv[1] ;
+      vsplit2_pos = fv[2] ;
+      //add the vertices to the triangle vertices
+      triangle_vertices.push_back(vsplit0) ;
+      triangle_vertices.push_back(vsplit1) ;
+      triangle_vertices.push_back(vsplit2) ;
+    }
+  }
+
+//  std::cout << "Adding split triangles" << std::endl ;
+//  std::cout << "Original size is " << (int) triangle_split_sizes[face_type.index] << std::endl ;
+  
+  //add the new triangles if they are not degenerate
+  //subdivision pattern for this triangle
+  const unsigned char* split_triangles = triangle_patterns[face_type.index] ;
+  //add the triangles
+  for( unsigned char triangle = 0 ; 
+       triangle < triangle_split_sizes[face_type.index] ; 
+       ++triangle
+     ) {
+    //vertices of the triangle
+    const unsigned char* tverts = split_triangles + 3*triangle ;
+    //check if the triangle is degenerate
+    bool regular = true ;
+    for(int i = 0; i < 3; ++i) {
+      if(triangle_vertices[tverts[i]] == triangle_vertices[tverts[(i+1)%3]]) {
+        regular = false ;
+        break ;
+      }
+    }
+    if(regular) {
+      //the triangle is not degenerate, add it
+      if(face_type.symetry) {
+        for(int i = 2; i >= 0; --i) {
+          const unsigned int vertex = triangle_vertices[tverts[i]] ;
+//          std::cout << "triangle vertex " << vertex << std::endl ;
+          split_faces.push_back(vertex) ;
+        }
+      } else {
+        for(int i = 0; i < 3; ++i) {
+          const unsigned int vertex = triangle_vertices[tverts[i]] ;
+//          std::cout << "triangle vertex " << vertex << std::endl ;
+          split_faces.push_back(vertex) ;
+        }
+      }
+    } else {
+//      std::cout << "degenerate triangle !" << std::endl ;
+    }
+  }
+}
+
+} //end of namespace Bevel
+
+template< typename Triangulation, 
+          typename TriangulationBuilder, 
+          typename Criterion >
+void bevel( const Triangulation* mesh, 
+            const Criterion* criterion, 
+            typename Triangulation::Scalar radius,
+            TriangulationBuilder* mesh_builder //output
+          ) {
+  using namespace Bevel ;
+
+  //dimension
+  enum { Dim = Triangulation::VertexDim } ;
+  //scalar type
+  typedef typename Triangulation::Scalar Scalar ;
+
+  //arrays of the new mesh
+  std::vector<Scalar> split_verts ;
+  std::vector<unsigned int> split_faces ;
+
+  //copy the vertices of the original mesh
+  //FIXME problem if mesh has vertex offset
+  split_verts.assign(
+    mesh->vertices(), 
+    mesh->vertices() + Dim*mesh->vertices_size()
+  ) ;
+
+  //split the mesh faces and edges according to the criterion used
+  //edge split types
+  std::vector<EdgeSplitType> edge_types ;
+  edge_types.reserve(mesh->face_vertices_size()) ;
+  //edge split vertices
+  std::vector<unsigned int> edge_split_verts ;
+  edge_split_verts.reserve(2*mesh->face_vertices_size()) ;
+  //iterate over faces
+  //unsigned int set = 1 ;
+  //for(unsigned int face = 125*set; face < 125*(set+1); ++face) {
+  for(unsigned int face = 0; face < mesh->faces_size(); ++face) {
+    //face size
+    const unsigned int fsize = mesh->face_size(face) ;
+    //face vertices
+    const unsigned int* fverts = mesh->face(face) ;
+    //face neighbours
+    const unsigned int* fneigh = mesh->face_neighbours(face) ;
+    //split the edges or recover information from the opposite edge
+//    std::cout << "edge split" << std::endl ;
+    for(unsigned int edge = 0; edge < fsize; ++edge) {
+      //opposite face
+      const unsigned int opp_face = fneigh[edge] ;
+      if(opp_face > face || opp_face == Triangulation::NO_NEIGHBOUR) {
+//        std::cout << "  do split" << std::endl ;
+        //the opposite face is not split, split the edge
+        //get its a priori split type
+        EdgeSplitType edge_type = criterion->edge_type(face, edge) ;
+        //split and update the split type
+        edge_type = edge_split( mesh, face, edge, radius, edge_type, 
+                                split_verts, edge_split_verts ) ;
+        //save the plis type
+        edge_types.push_back(edge_type) ;
+//        std::cout << "  edge type is " << edge_type << std::endl ;
+      } else {
+//        std::cout << "  copy split" << std::endl ;
+        //the opposite face is already split, recover edge type and vertices
+        //edge vertices
+        const unsigned int v0 = fverts[ edge         ] ;
+        const unsigned int v1 = fverts[(edge+1)%fsize] ;
+        //opposite edge index in opposite face
+        const unsigned int opp_edge = mesh->edge_face_index(opp_face, v0, v1) ;
+        //opposite offset
+        const unsigned int opp_offset = mesh->face_offset(opp_face) ;
+        //check orientation
+        if(v1 == mesh->face_edge_start_vertex(opp_face, opp_edge)) {
+          //opposite orientations, switch orientation in copy
+          //edge type
+          edge_types.push_back(
+            edge_split_type_sym(edge_types[opp_offset + opp_edge])
+          ) ;
+          //edge_vertices
+          edge_split_verts.push_back(
+            edge_split_verts[2*(opp_offset + opp_edge) + 1]
+          ) ;
+          edge_split_verts.push_back(
+            edge_split_verts[2*(opp_offset + opp_edge)    ]
+          ) ;
+        } else {
+          //edge type
+          edge_types.push_back(
+            edge_types[opp_offset + opp_edge]
+          ) ;
+          //edge_vertices
+          edge_split_verts.push_back(
+            edge_split_verts[2*(opp_offset + opp_edge)    ]
+          ) ;
+          edge_split_verts.push_back(
+            edge_split_verts[2*(opp_offset + opp_edge) + 1]
+          ) ;
+        }
+      }
+    }
+    //split the face
+//    std::cout << "edge type length " << edge_types.size() << std::endl ;
+//    std::cout << "edge split verts length " << edge_split_verts.size() << std::endl ;
+//    std::cout << "face split" << std::endl ;
+    //face offset
+    const unsigned int foffset = mesh->face_offset(face) ;
+//    std::cout << "face offset " << foffset << std::endl ;
+    face_split( mesh, face, radius, 
+                edge_types.data() + foffset, 
+                edge_split_verts.data() + 2*foffset, 
+                split_verts, split_faces
+              ) ;
+  }
+  
+//  std::cout << "face size " << split_faces.size() << std::endl ;
+//  std::cout << "vert size " << split_verts.size() << std::endl ;
+  //swap content
+  mesh_builder->swap_vertices(split_verts) ;
+  mesh_builder->swap_faces(split_faces) ;
+}
+
+//}}}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/splitting_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/splitting_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..4d07d6e19148bc70355d74ae127b5cdcc3b35483
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/splitting_fwd.hpp
@@ -0,0 +1,273 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_SPLITTING_FWD_HPP_
+#define _REVOROPT_MESH_SPLITTING_FWD_HPP_
+
+#include "all_fwd.hpp"
+#include "debug_fwd.hpp"
+#include "connectivity_fwd.hpp"
+
+namespace Revoropt {
+
+/**{{{ Splitting edges in halves (decimation) **/
+
+/* Split a face of the mesh in two given an edge index and the index of its
+ * center vertex. The neighbourhoods along the split edge are set to none.
+ * Returns the indices of the two split faces and their sizes. within these
+ * faces, the layout of the vertices is such that :
+ *   - the first face uses the mid vertex and the next one along the edge
+ *   - the second face uses the first vertex of the edge and the mid one
+ *   - the mid vertex is the last vertex in both faces */
+template<typename MeshBuilder>
+void face_split( MeshBuilder* mesh,
+                 unsigned int face,
+                 unsigned int edge_index,
+                 unsigned int mid_vertex_index,
+                 unsigned int* split_face_indices //output
+               ) ;
+
+/* Split an edge of a mesh builder. If the provided arrays are not NULL, returns
+ * the indices and sizes of the new faces. The size of the arrays to provide is 
+ * two in case of a border edge, and 4 otherwise.*/
+template<typename MeshBuilder>
+void edge_split( MeshBuilder* mesh, 
+                 unsigned int face, 
+                 unsigned int edge_index,
+                 unsigned int* split_face_indices = NULL //output
+                ) ;
+/* Tools */
+namespace Decimate {
+  
+  /* An edge index with its length, vertices, and face information */
+  template<typename Scalar>
+  class HeapEdge {
+    public :
+  
+    /* A face connected to the edge */
+    unsigned int face ;
+
+    /* The index of the edge in that face */
+    unsigned int edge ;
+
+    /* Sorted vertices of the edge */
+    unsigned int vmin, vmax ;
+
+    /* Length of the edge */
+    Scalar length ;
+  
+    bool operator<(const HeapEdge& rhs) {
+      //in case of equality, use vertex indices
+      if(length == rhs.length) {
+        if(vmax == rhs.vmax) {
+          return vmin < rhs.vmin ;
+        } else {
+          return vmax < rhs.vmax ;
+        }
+      }
+      return length < rhs.length ;
+    }
+  } ;
+
+} //end of namespace Decimate
+
+template<typename Mesh, typename MeshBuilder>
+void split_longest_edge( const Mesh* input, 
+                         unsigned int niter, 
+                         MeshBuilder* mesh
+                       ) ;
+//}}}
+
+/**{{{ Normal bevel : split triangles to improve normal interpolation **/
+
+namespace Bevel {
+
+/* edge split types */
+enum EdgeSplitType { 
+  SPLIT_NONE = 0, 
+  SPLIT_FIRST = 1, 
+  SPLIT_SECOND = 2, 
+  SPLIT_BOTH = 3 
+} ;
+
+/* face split types */
+struct FaceSplitType {
+  unsigned int index ;
+  unsigned int rotation ;
+  bool symetry ;
+} ;
+
+const unsigned int NO_VERTEX = -1 ;
+
+/* criterion based on the normal to decide whether an edge needs splitting */
+template<typename Mesh>
+class NormalSplitCriterion {
+
+  public :
+  /* Typedefs */
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //vector type (dimension 3 since we are dealing with normals)
+  typedef Eigen::Matrix<Scalar,3,1> Vector ;
+
+  /* Construction */
+  NormalSplitCriterion(const Mesh* mesh) : 
+    cosine_threshold_(0.85),
+    bevel_radius_(0.002),
+    normal_radius_(0.001),
+    restrict_to_boundary_(false),
+    mesh_(mesh)
+  {
+    init() ;
+  }
+
+  /* Parameters */
+
+  void set_cosine_threshold( Scalar threshold ) {
+    cosine_threshold_ = threshold ;
+  }
+
+  Scalar cosine_threshold() const {
+    return cosine_threshold_ ;
+  }
+
+  void set_bevel_radius( Scalar in_radius ) {
+    bevel_radius_ = in_radius ;
+  }
+
+  void set_normal_radius( Scalar in_radius ) {
+    normal_radius_ = in_radius ;
+  }
+
+  Scalar bevel_radius() const {
+    return bevel_radius_ ;
+  }
+
+  void set_boundary_restriction( bool status ) {
+    restrict_to_boundary_ = status ;
+  }
+
+  bool restrict_to_boundary() {
+    return restrict_to_boundary_ ;
+  }
+
+  /* Decision */
+
+  EdgeSplitType edge_type( unsigned int face, unsigned int edge ) const ;
+  private :
+
+  /* Initialization */
+  void init() ;
+
+  /* Parameters */
+  Scalar cosine_threshold_ ;
+  Scalar bevel_radius_ ;
+  Scalar normal_radius_ ;
+  bool restrict_to_boundary_ ;
+
+  /* Mesh */
+  const Mesh* mesh_ ;
+
+  //FIXME
+  public :
+  /* Edge midpoints */
+  std::vector<Scalar> edge_midpoints_ ;
+
+  /* Edge normals */
+  std::vector<Scalar> edge_normals_ ;
+
+  /* Vertex normals */
+  std::vector<Scalar> vertex_normals_ ;
+
+  /*Boundary vertices*/
+  std::vector<bool> boundary_vertices_ ;
+
+} ;
+
+/* test criterion based on the triangle and edge indices */
+template<typename Mesh>
+class TestSplitCriterion {
+
+  public:
+
+  EdgeSplitType edge_type( unsigned int face, unsigned int edge ) const {
+    int res = face/150 ;
+    for(int i = 0; i < edge; ++i) {
+      res /= 4 ;
+    }
+    return (EdgeSplitType) (res%4) ;
+  }
+
+} ;
+
+/* criterion always requiring split */
+class TrueSplitCriterion {
+
+  public:
+
+  EdgeSplitType edge_type( unsigned int face, unsigned int edge ) const {
+    return SPLIT_BOTH ;
+  }
+
+} ;
+
+/* given the type of an edge, type of the oppositely oriented edge*/
+EdgeSplitType edge_split_type_sym( EdgeSplitType type ) {
+  static const EdgeSplitType sym[4] = { SPLIT_NONE, 
+                                        SPLIT_SECOND, 
+                                        SPLIT_FIRST, 
+                                        SPLIT_BOTH
+                                      } ;
+  return sym[type] ;
+}
+
+/* triangle classification, depending on its edges split types */
+void normalize_triangle_split( const EdgeSplitType edge_types[3],
+                               FaceSplitType* split_type //output
+                             ) ;
+/* compute the split points of an edge given its type, a radius and length */
+/* returns the split really performed given the radius and edge length */
+
+template<typename Mesh>
+EdgeSplitType edge_split( const Mesh* mesh,
+                          unsigned int face,
+                          unsigned int edge,
+                          typename Mesh::Scalar radius,
+                          EdgeSplitType split_type,
+                          std::vector<typename Mesh::Scalar>& coords, //i/o
+                          std::vector<unsigned int>& edge_split_verts //output
+                        ) ;
+
+/* split a face given its split type and the edge split vertices */
+template<typename Mesh>
+void face_split( const Mesh* mesh,
+                 unsigned int face,
+                 typename Mesh::Scalar radius,
+                 const EdgeSplitType edge_types[3],
+                 const unsigned int edge_split_verts[6],
+                 std::vector<typename Mesh::Scalar>& coords, //output
+                 std::vector<unsigned int>& split_faces //output
+               ) ;
+
+} //end of namespace Bevel
+
+template< typename Triangulation, 
+          typename TriangulationBuilder, 
+          typename Criterion >
+void bevel( const Triangulation* mesh, 
+            const Criterion* criterion, 
+            typename Triangulation::Scalar radius,
+            TriangulationBuilder* mesh_builder //output
+          ) ;
+//}}}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/statistics_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/statistics_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c2e95264f4db9b1bed6063975cd244ace544ec1c
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/statistics_def.hpp
@@ -0,0 +1,149 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_STATISTICS_DEF_HPP_
+#define _REVOROPT_MESH_STATISTICS_DEF_HPP_
+
+#include <vector>
+#include <iostream>
+#include <eigen3/Eigen/Dense>
+
+namespace Revoropt {
+
+/* Angles */
+
+template<typename Mesh>
+void face_angles( const Mesh* mesh, typename Mesh::Scalar* angles ) {
+  //the angles array needs to have size mesh->face_vertices_size()
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //vector type
+  typedef Eigen::Matrix<Scalar,Mesh::VertexDim,1> Vector ;
+  //iterate on faces
+  for(unsigned int f = 0; f < mesh->faces_size(); ++f) {
+    //face size
+    const unsigned int fsize = mesh->face_size(f) ;
+    //vertices
+    const unsigned int* fverts = mesh->face(f) ;
+    //iterate on face vertices
+    for(unsigned int v = 0; v < fsize; ++v) {
+      const unsigned int previndex = fverts[(v+fsize-1)%fsize] ;
+      const unsigned int currindex = fverts[ v               ] ;
+      const unsigned int nextindex = fverts[(v      +1)%fsize] ;
+      Eigen::Map<const Vector> vprev(mesh->vertex(previndex)) ;
+      Eigen::Map<const Vector> vcurr(mesh->vertex(currindex)) ;
+      Eigen::Map<const Vector> vnext(mesh->vertex(nextindex)) ;
+      //normal weight for this vertex
+      const Vector e1 = (vprev-vcurr) ;
+      const Scalar e1_len = e1.norm() ;
+      const Vector e2 = (vcurr-vnext) ;
+      const Scalar e2_len = e2.norm() ;
+      if(e1_len*e2_len != 0) {
+        Scalar angle_cos = -e1.dot(e2)/(e1_len*e2_len) ;
+        angle_cos = std::min(angle_cos,1.) ;
+        angle_cos = std::max(angle_cos,-1.) ;
+        const Scalar angle = acos(angle_cos) ;
+        angles[mesh->face_offset(f)+v] = angle ;
+      } else {
+        angles[mesh->face_offset(f)+v] = 0 ;
+      }
+    }
+  }
+}
+
+template<typename Mesh>
+void triangle_quality( const Mesh* mesh, typename Mesh::Scalar* qualities ) {
+  //the qualities array needs to have size mesh->faces_size()
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //compute angles
+  std::vector<Scalar> angles(mesh->face_vertices_size()) ;
+  face_angles(mesh, angles.data()) ;
+  //compute qualities
+  for(unsigned int f = 0; f < mesh->faces_size(); ++f) {
+    //face angles
+    const Scalar* fangles = angles.data() + mesh->face_offset(f) ;
+    //quality
+    qualities[f] = 4*sin(fangles[0])*sin(fangles[1])*sin(fangles[2]) ;
+    qualities[f] /= sin(fangles[0])+sin(fangles[1])+sin(fangles[2]) ;
+  }
+}
+
+/* Edge lengths */
+//inner edges are twice accounted for
+
+template<typename Mesh>
+void edge_lengths( const Mesh* mesh, typename Mesh::Scalar* lengths ) {
+  //the lengths array needs to have size mesh->face_vertices_size()
+  //scalar type
+  typedef typename Mesh::Scalar Scalar ;
+  //vector type
+  typedef Eigen::Matrix<Scalar,Mesh::VertexDim,1> Vector ;
+  //iterate on faces
+  for(unsigned int f = 0; f < mesh->faces_size(); ++f) {
+    //face size
+    const unsigned int fsize = mesh->face_size(f) ;
+    //vertices
+    const unsigned int* fverts = mesh->face(f) ;
+    //iterate on face vertices
+    for(unsigned int v = 0; v < fsize; ++v) {
+      const unsigned int currindex = fverts[ v         ] ;
+      const unsigned int nextindex = fverts[(v+1)%fsize] ;
+      Eigen::Map<const Vector> vcurr(mesh->vertex(currindex)) ;
+      Eigen::Map<const Vector> vnext(mesh->vertex(nextindex)) ;
+      //normal weight for this vertex
+      const Vector e2 = (vcurr-vnext) ;
+      lengths[mesh->face_offset(f)+v] = e2.norm() ;
+    }
+  }
+}
+
+/* Histogram */
+
+template<typename Scalar>
+void histogram( const Scalar* data, unsigned int size, 
+                Scalar min, Scalar max, unsigned int bins, 
+                unsigned int* output
+              ) {
+  //output must havs size bins
+  const Scalar extent = max - min ;
+  //reset the output
+  std::fill(output, output+bins, 0) ;
+  //fill the bins
+  for(unsigned int i = 0; i < size; ++i) {
+    const unsigned int bin = (unsigned int) ((data[i]-min)/extent*bins) ;
+    ++output[bin] ;
+  }
+}
+
+template<typename Scalar>
+void histogram( const Scalar* data, unsigned int size, 
+                Scalar min, Scalar max, unsigned int bins, 
+                const char* filename
+              ) {
+  std::vector<Scalar> histogram(bins,0) ;
+  const Scalar extent = max - min ;
+  //fill the bins
+  for(unsigned int i = 0; i < size; ++i) {
+    const unsigned int bin = (unsigned int) ((data[i]-min)/extent*bins) ;
+    ++histogram[bin] ;
+  }
+  //write the result
+  std::ofstream file ;
+  file.open(filename) ;
+  for(unsigned int i = 0; i < bins; ++i) {
+    file << min + i/((double)bins)*extent << " " << histogram[i] << std::endl ;
+  }
+  file.close() ;
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/statistics_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/statistics_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..9ee9dbd8678a1e257ac38b09119cc3271bf0d861
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/statistics_fwd.hpp
@@ -0,0 +1,46 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_STATISTICS_H_
+#define _REVOROPT_MESH_STATISTICS_H_
+
+namespace Revoropt {
+
+/* Angles */
+
+template<typename Mesh>
+void face_angles( const Mesh* mesh, typename Mesh::Scalar* angles ) ;
+
+template<typename Mesh>
+void triangle_quality( const Mesh* mesh, typename Mesh::Scalar* qualities ) ;
+
+/* Edge lengths */
+//inner edges are twice accounted for
+
+template<typename Mesh>
+void edge_lengths( const Mesh* mesh, typename Mesh::Scalar* lengths ) ;
+
+/* Histogram */
+
+template<typename Scalar>
+void histogram( const Scalar* data, unsigned int size, 
+                Scalar min, Scalar max, unsigned int bins, 
+                unsigned int* output
+              ) ;
+
+template<typename Scalar>
+void histogram( const Scalar* data, unsigned int size, 
+                Scalar min, Scalar max, unsigned int bins, 
+                const char* filename
+              ) ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/subdivision_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/subdivision_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..1fbd3c24d76b713f2fb2d660e471e86e180739eb
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/subdivision_def.hpp
@@ -0,0 +1,318 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_SUBDIVISION_DEF_HPP_
+#define _REVOROPT_MESH_SUBDIVISION_DEF_HPP_
+
+#include "subdivision_fwd.hpp"
+
+namespace Revoropt {
+
+namespace Subdivision {
+
+template<typename Scalar>
+Stencil<Scalar> Stencil<Scalar>::operator+( const Stencil& rhs ) const {
+  //result
+  Stencil res ;
+
+  //iterator on each stencil
+  unsigned int pos1 = 0 ;
+  unsigned int pos2 = 0 ;
+
+  //fusion
+  while(pos1 != size() && pos2 != rhs.size()) {
+    if((*this)[pos1].index < rhs[pos2].index) {
+      res.contributions_.push_back((*this)[pos1]) ;
+      ++pos1 ;
+    } else if(contributions_[pos1].index > rhs[pos2].index) {
+      res.contributions_.push_back(rhs[pos2]) ;
+      ++pos2 ;
+    } else {
+      res.contributions_.push_back((*this)[pos1] + rhs[pos2]) ;
+      ++pos1 ;
+      ++pos2 ;
+    }
+  }
+
+  //handle remaining contributions
+  if(pos1 == size()) {
+    res.contributions_.insert(
+        res.contributions_.end(),
+        rhs.contributions_.begin() + pos2, 
+        rhs.contributions_.end()
+        ) ;
+  } else {
+    res.contributions_.insert(
+        res.contributions_.end(),
+        contributions_.begin() + pos1, 
+        contributions_.end() 
+        ) ;
+  }
+
+  //finalize
+  return res ;
+}
+
+} //end of namespace Subdivision
+
+template<
+  int _VertexDim,
+  typename _Scalar
+>
+void CatmullClark<_VertexDim, _Scalar>::update() {
+  //vector type
+  typedef Eigen::Matrix<Scalar,VertexDim,1> Vector ;
+
+  vertices_.reserve(VertexDim*stencils_.size()) ;
+  vertices_.resize(VertexDim*stencils_.size()) ;
+
+  for(unsigned int i = 0; i < stencils_.size(); ++i) {
+    //vertex to update
+    Eigen::Map<Vector> x(vertices_.data() + VertexDim*i) ;
+    x = Vector::Zero() ;
+
+    //apply the vertex stencil
+    const Subdivision::Stencil<Scalar>& stencil = stencils_[i] ;
+    for(unsigned int j = 0; j < stencil.size(); ++j) {
+      //control vertex
+      unsigned int index = stencil[j].index ;
+      Scalar factor = stencil[j].factor ;
+      Eigen::Map<const Vector> cv(ctrl_vertices_ + VertexDim*index) ;
+      x += factor*cv ;
+    }
+  }
+}
+
+template<
+  int _VertexDim,
+  typename _Scalar
+>
+template<typename Mesh>
+void CatmullClark<_VertexDim, _Scalar>::subdivide( const Mesh* mesh ) {
+  //setup control vertices if a new mesh is provided
+  if((void*) mesh != (void*) this) {
+    ctrl_vertices_ = mesh->vertices() ;
+  }
+
+  //reserve space for new stencils
+  stencils_.reserve(
+      mesh->vertices_size() //original vertices
+      + mesh->faces_size() //face vertices
+      + mesh->face_vertices_size() / 2 //edge vertices
+      ) ;
+
+  //reinitialize stencils if the mesh is not this
+  if((void*) mesh != (void*) this) {
+    stencils_.resize(0) ;
+    for(unsigned int v = 0; v < mesh->vertices_size(); ++v) {
+      stencils_.emplace_back(v) ;
+    }
+  }
+
+  //face vertices
+  const unsigned int fvstart = stencils_.size() ;
+  for(unsigned int f = 0; f < mesh->faces_size(); ++f) {
+    const unsigned int fsize = mesh->face_size(f) ;
+    const unsigned int* fverts = mesh->face(f) ;
+    Subdivision::Stencil<Scalar> stencil ;
+    for(unsigned int v = 0; v < fsize; ++v) {
+      stencil += stencils_[fverts[v]] ;
+    }
+    stencil.normalize() ;
+    stencils_.push_back(stencil) ;
+  }
+
+  //edge vertices
+  const unsigned int evstart = stencils_.size() ;
+  for(unsigned int f = 0; f < mesh->faces_size(); ++f) {
+    const unsigned int fsize = mesh->face_size(f) ;
+    const unsigned int* fverts = mesh->face(f) ;
+    const unsigned int* fneigh = mesh->face_neighbours(f) ;
+    for(unsigned int v = 0; v < fsize; ++v) {
+      if(f < fneigh[v]) { //avoid handling edges twice
+        Subdivision::Stencil<Scalar> stencil ;
+        stencil += stencils_[fverts[ v         ]] ;
+        stencil += stencils_[fverts[(v+1)%fsize]] ;
+        if(fneigh[v] != Mesh::NO_NEIGHBOUR) {
+          //not considered for border edges
+          stencil += stencils_[fvstart + f        ] ;
+          stencil += stencils_[fvstart + fneigh[v]] ;
+        }
+        stencil.normalize() ;
+        stencils_.push_back(stencil) ;
+      }
+    }
+  }
+
+  //original vertices
+  std::vector< Subdivision::Stencil<Scalar> > contribs(2*mesh->vertices_size()) ;
+  std::vector<int> valence(mesh->vertices_size(), 0) ;
+  unsigned int eindex = 0 ;
+  for(unsigned int f = 0; f < mesh->faces_size(); ++f) {
+    const unsigned int fsize = mesh->face_size(f) ;
+    const unsigned int* fverts = mesh->face(f) ;
+    const unsigned int* fneigh = mesh->face_neighbours(f) ;
+    for(unsigned int v = 0; v < fsize; ++v) {
+      const unsigned ev1 = fverts[ v         ] ;
+      const unsigned ev2 = fverts[(v+1)%fsize] ;
+      //neighbouring face points considered only for non boundary vertices
+      if(valence[ev1] >= 0) {
+        contribs[2*ev1+1] += stencils_[fvstart + f] ;
+        ++valence[ev1] ;
+      }
+      if(f < fneigh[v]) { //avoid handling edges twice
+        if(fneigh[v] == Mesh::NO_NEIGHBOUR) {
+          //border vertices => valence < 0
+          if(valence[ev1] >= 0) {
+            //only inner edges considered so far
+            //reset edge contributions to consider only border edges
+            contribs[2*ev1] = stencils_[evstart + eindex] ;
+            valence[ev1] = -1 ;
+          } else {
+            contribs[2*ev1] += stencils_[evstart + eindex] ;
+          }
+          if(valence[ev2] >= 0) {
+            contribs[2*ev2] = stencils_[evstart + eindex] ;
+            valence[ev2] = -1 ;
+          } else {
+            contribs[2*ev2] += stencils_[evstart + eindex] ;
+          }
+        } else {
+          if(valence[ev1] >= 0) {
+            contribs[2*ev1] += stencils_[evstart + eindex] ;
+          }
+          if(valence[ev2] >= 0) {
+            contribs[2*ev2] += stencils_[evstart + eindex] ;
+          }
+        }
+        ++eindex ;
+      }
+    }
+  }
+  //final mixture for original vertices
+  for(unsigned int v = 0; v < mesh->vertices_size(); ++v) {
+    if(valence[v] > 2) {
+      contribs[2*v  ].normalize() ;
+      contribs[2*v+1].normalize() ;
+      if(valence[v] > 3) {
+        stencils_[v] *= valence[v] - 3 ;
+        stencils_[v] += 2*contribs[2*v] ;
+      } else {
+        stencils_[v] = 2*contribs[2*v] ;
+      }
+      stencils_[v] += contribs[2*v+1] ;
+    } else {
+      contribs[2*v].normalize() ;
+      stencils_[v] += contribs[2*v] ;
+    }
+    stencils_[v].normalize() ;
+  }
+
+  //faces
+  std::vector<unsigned int> new_faces ;
+  std::vector<unsigned int> new_neighbourhoods ;
+  std::vector<unsigned int> new_face_patches ;
+  new_faces.reserve(4*mesh->face_vertices_size()) ;
+  new_neighbourhoods.reserve(4*mesh->face_vertices_size()) ;
+  new_face_patches.reserve(mesh->face_vertices_size()) ;
+  eindex = 0 ;
+  std::vector<unsigned int> boundary_info ;
+  for(unsigned int f = 0; f < mesh->faces_size(); ++f) {
+    const unsigned int fsize = mesh->face_size(f) ;
+    const unsigned int* fverts = mesh->face(f) ;
+    const unsigned int* fneigh = mesh->face_neighbours(f) ;
+    //recover edge neighbouring information
+    boundary_info.resize(4*fsize) ;
+    for(unsigned int v = 0; v < fsize; ++v) {
+      if(fneigh[v] == Mesh::NO_NEIGHBOUR || f < fneigh[v]) {
+        boundary_info[4*v  ] = evstart + eindex ;
+        boundary_info[4*v+1] = Mesh::NO_NEIGHBOUR ;
+        boundary_info[4*v+2] = Mesh::NO_NEIGHBOUR ;
+        ++eindex ;
+      } else {
+        //edge vertices
+        const unsigned int ev1 = fverts[ v         ] ;
+        const unsigned int ev2 = fverts[(v+1)%fsize] ;
+        //neighbouring face info
+        const unsigned int nfsize = mesh->face_size(fneigh[v]) ;
+        const unsigned int* nfverts = mesh->face(fneigh[v]) ;
+        const unsigned int nfoffset = mesh->face_offset(fneigh[v]) ;
+        //index of the edge in the neighbouring face in the old mesh
+        const unsigned int neindex = mesh->edge_face_index(fneigh[v], ev1, ev2) ;
+        //index of the new face containing ev1 from the neighbouring face
+        if(nfverts[neindex] == ev2) {
+          boundary_info[4*v  ] = new_faces[4*(nfoffset + neindex) + 1] ;
+          boundary_info[4*v+1] = nfoffset + ((neindex+1)%nfsize) ;
+          boundary_info[4*v+2] = nfoffset + neindex ;
+          boundary_info[4*v+3] = 0 ;
+        } else {
+          boundary_info[4*v  ] = new_faces[4*(nfoffset + neindex) + 1] ;
+          boundary_info[4*v+1] = nfoffset + neindex ;
+          boundary_info[4*v+2] = nfoffset + ((neindex+1)%nfsize) ;
+          boundary_info[4*v+3] = 1 ;
+        }
+      }
+    }
+    //build the faces
+    const unsigned int fstart = mesh->face_offset(f) ;
+    for(unsigned int v = 0; v < fsize; ++v) {
+      const unsigned int prev_index = (v+fsize-1)%fsize ;
+      //face vertices
+      new_faces.push_back(fverts[v]) ;
+      new_faces.push_back(boundary_info[4*v]) ;
+      new_faces.push_back(fvstart + f) ;
+      new_faces.push_back(boundary_info[4*prev_index]) ;
+      //face patch
+      if((void*) mesh != (void*) this) {
+        new_face_patches[fstart + v] = f ;
+      } else {
+        new_face_patches[fstart + v] = face_patches_[f] ;
+      }
+      //face neighbourhoods
+      if(fneigh[v] == Mesh::NO_NEIGHBOUR || f < fneigh[v]) {
+        new_neighbourhoods.push_back(Mesh::NO_NEIGHBOUR) ;
+      } else {
+        new_neighbourhoods.push_back(boundary_info[4*v+1]) ;
+      }
+      new_neighbourhoods.push_back(fstart + ((v+1)%fsize)) ;
+      new_neighbourhoods.push_back(fstart + prev_index) ;
+      new_neighbourhoods.push_back(boundary_info[4*prev_index+2]) ;
+      if(fneigh[v] != Mesh::NO_NEIGHBOUR && f > fneigh[v]) {
+        if(boundary_info[4*v+3]) {
+          //opposite face is coherently oriented
+          new_neighbourhoods[4*boundary_info[4*v+1]  ] = fstart + v ;
+          new_neighbourhoods[4*boundary_info[4*v+2]+3] = fstart+((v+1)%fsize) ;
+        }
+          //opposite face is flipped
+          new_neighbourhoods[4*boundary_info[4*v+1]+3] = fstart + v ;
+          new_neighbourhoods[4*boundary_info[4*v+2]  ] = fstart+((v+1)%fsize) ;
+      }
+    }
+  }
+
+  faces_.swap(new_faces) ;
+  face_neighbourhoods_.swap(new_neighbourhoods) ;
+  face_patches_.swap(new_face_patches) ;
+
+  //compute vertex positions
+  update() ;
+
+  //finalize pointers
+  Base::vertices_ = vertices_.data() ;
+  Base::vertices_size_ = vertices_.size() / VertexDim ;
+  Base::faces_ = faces_.data() ;
+  Base::faces_size_ = faces_.size() / 4 ;
+  Base::face_neighbourhoods_ = face_neighbourhoods_.data() ;
+  Base::set_dirty() ;
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/subdivision_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/subdivision_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fe93d26b81ea3c8595c279bd42fb48370742015f
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/subdivision_fwd.hpp
@@ -0,0 +1,216 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_SUBDIVISION_FWD_HPP_
+#define _REVOROPT_MESH_SUBDIVISION_FWD_HPP_
+
+#include "base_def.hpp"
+
+#include <eigen3/Eigen/Dense>
+#include <ostream>
+#include <iostream>
+
+namespace Revoropt {
+
+namespace Subdivision {
+
+template<typename Scalar>
+class Contribution {
+  public :
+    /* Data */
+    unsigned int index ;
+    Scalar factor ;
+
+    /* Construction */
+    Contribution() {}
+
+    Contribution(unsigned int _index) :
+      index(_index), factor(1) {}
+
+    Contribution(unsigned int _index, Scalar _factor) :
+      index(_index), factor(_factor) {}
+
+    /* Operations */
+    Contribution operator*( Scalar rhs ) const {
+      return Contribution(index, factor*rhs) ;
+    }
+    Contribution& operator*=( Scalar rhs ) {
+      factor *= rhs ;
+      return *this ;
+    }
+    Contribution operator+( const Contribution& rhs ) const {
+      return Contribution(index, factor + rhs.factor) ;
+    }
+    Contribution& operator+=( const Contribution& rhs ) {
+      factor += rhs.factor ;
+      return *this ;
+    }
+} ;
+
+template<typename Scalar, typename OtherScalar = Scalar>
+Contribution<Scalar> operator*(OtherScalar lhs, const Contribution<Scalar>& rhs) {
+  return rhs*((Scalar) lhs) ;
+}
+
+template<typename Scalar>
+class Stencil {
+  public :
+    /* Construction */
+    Stencil() {}
+
+    Stencil(const Contribution<Scalar>& contrib) {
+      contributions_.push_back(contrib) ;
+    }
+
+    Stencil( unsigned int index ) {
+      contributions_.push_back(index) ;
+    }
+
+    void normalize() {
+      Scalar sum = 0 ;
+      for(unsigned int i = 0; i < size(); ++i) {
+        sum += contributions_[i].factor ;
+      }
+      for(unsigned int i = 0; i < size(); ++i) {
+        contributions_[i].factor /= sum ;
+      }
+    }
+
+    /* Access */
+    Contribution<Scalar>& operator[](unsigned int i) {
+      return contributions_[i] ;
+    }
+
+    const Contribution<Scalar>& operator[](unsigned int i) const {
+      return contributions_[i] ;
+    }
+
+    unsigned int size() const {
+      return contributions_.size() ;
+    }
+
+    /* Operations */
+    Stencil operator*( Scalar rhs ) const {
+      Stencil res ;
+      res.contributions_.reserve(size()) ;
+      for(unsigned int i = 0; i < size(); ++i) {
+        res.contributions_.push_back((*this)[i] * rhs) ;
+      }
+      return res ;
+    }
+
+    Stencil& operator*=( Scalar rhs ) {
+      *this = *this * rhs ;
+      return *this ;
+    }
+
+    Stencil operator+( const Stencil& rhs ) const ;
+
+    Stencil& operator+=(const Stencil& rhs) {
+      *this = *this + rhs ;
+      return *this ;
+    }
+
+    Stencil compose( const Stencil* stencils ) const {
+      Stencil res ;
+      for(unsigned int i = 0; i < size(); ++i) {
+        res += stencils[contributions_[i].index] * contributions_[i].factor ;
+      }
+      return res ;
+    }
+
+  private :
+    /* Data */
+    std::vector< Contribution<Scalar> > contributions_ ;
+} ;
+
+template<typename Scalar, typename OtherScalar = Scalar>
+Stencil<Scalar> operator*(OtherScalar lhs, const Stencil<Scalar>& rhs) {
+  return rhs*((Scalar) lhs) ;
+}
+
+template<typename Scalar>
+std::ostream& operator<<(std::ostream& stream, const Stencil<Scalar>& rhs) {
+  stream << "[ " ;
+  for(unsigned int i = 0; i < rhs.size(); ++i) {
+    stream << rhs[i].index << "(" << rhs[i].factor << ") " ;
+  }
+  stream << "]" ;
+  return stream ;
+}
+
+} //end of namespace Subdivision
+
+template<
+  int _VertexDim = 3,
+  typename _Scalar = double
+>
+class CatmullClark : public ROMesh<4, _VertexDim, _Scalar, 0>
+{
+  public :
+
+    /* Typedefs */
+    typedef ROMesh<4, _VertexDim, _Scalar, 0> Base ;
+    typedef _Scalar Scalar ;
+    enum {
+      FaceSize = 4,
+      VertexDim = _VertexDim
+    } ;
+
+    /* Construction */
+    CatmullClark() : Base() {}
+
+    template<typename Mesh>
+    CatmullClark( const Mesh* mesh ) : Base() {
+      subdivide(mesh) ;
+    }
+
+    /* Access */
+    const unsigned int* face_patches() {
+      return face_patches_.data() ;
+    }
+
+    /* Tools */
+    void set_vertices( 
+        const Scalar* ctrl_vertices, 
+        unsigned int ctrl_vertices_size = 0 //for compatibility
+        ) {
+      ctrl_vertices_ = ctrl_vertices ;
+      update() ;
+      Base::set_dirty() ;
+    }
+
+    void update() ;
+
+    template<typename Mesh>
+    void subdivide( const Mesh* mesh ) ;
+
+    void subdivide() {
+      return subdivide(this) ;
+    }
+
+  private :
+
+    /* Control Vertices */
+    const Scalar* ctrl_vertices_ ;
+
+    /* Subdivided vertices and faces */
+    std::vector<Scalar> vertices_ ;
+    std::vector<unsigned int> faces_ ;
+    std::vector<unsigned int> face_neighbourhoods_ ;
+    std::vector<unsigned int> face_patches_ ;
+
+    /* Stencils */
+    std::vector< Subdivision::Stencil<Scalar> > stencils_ ;
+} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/wrapper_def.hpp b/contrib/Revoropt/include/Revoropt/Mesh/wrapper_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..4ea734ac83198b28570aeda834b3ed9d65a1cf21
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/wrapper_def.hpp
@@ -0,0 +1,100 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_WRAPPER_DEF_HPP_
+#define _REVOROPT_MESH_WRAPPER_DEF_HPP_
+
+#include "wrapper_fwd.hpp"
+#include "base_def.hpp"
+#include "connectivity_def.hpp"
+
+namespace Revoropt {
+
+/*** Triangulation wrapper, triangulating a mesh ***/
+
+/* fixed face size case */
+template< int VertexDim, typename Scalar, int VertexOffset>
+void ROTriangulationWrapper<VertexDim,Scalar,VertexOffset>::set_faces( 
+  const unsigned int* faces, 
+  unsigned int face_size, 
+  unsigned int faces_size
+) {
+  //reset the triangle vector
+  triangles_.resize(0) ;
+
+  //split every single face
+  for( unsigned int face_index = 0; 
+       face_index < faces_size; 
+       ++face_index ) {
+    //face vertex indices
+    const unsigned int* face_vertices = faces + face_size*face_index ;
+    split_polygon(face_vertices, face_size) ;
+  }
+
+  //assign Mesh data fields
+  Base::faces_ = triangles_.data() ;
+  Base::faces_size_ = triangles_.size() / 3 ;
+  c_computer_.compute_connectivity() ;
+  Base::face_neighbourhoods_ = c_computer_.data() ;
+  Base::set_dirty() ;
+}
+
+/* variable face size case */
+template< int VertexDim, typename Scalar, int VertexOffset>
+void ROTriangulationWrapper<VertexDim,Scalar,VertexOffset>::set_faces( 
+  const unsigned int* faces, 
+  const unsigned int* face_ends, 
+  unsigned int faces_size
+) {
+  //reset the triangle vector
+  triangles_.resize(0) ;
+
+  //current face position
+  const unsigned int* current_face = faces ;
+
+  //split every single face
+  for( unsigned int face_index = 0; 
+       face_index < faces_size; 
+       ++face_index ) {
+    //face vertex indices
+    const unsigned int face_size = 
+      (faces + face_ends[face_index]) - current_face ;
+    split_polygon(current_face, face_size) ;
+    current_face = faces + face_ends[face_index] ;
+  }
+
+  //assign Mesh data fields
+  Base::faces_ = triangles_.data() ;
+  Base::faces_size_ = triangles_.size() / 3 ;
+  c_computer_.compute_connectivity() ;
+  Base::face_neighbourhoods_ = c_computer_.data() ;
+  Base::set_dirty() ;
+}
+
+/* naïvely split a polygon into triangles */
+template< int VertexDim, typename Scalar, int VertexOffset>
+void ROTriangulationWrapper<VertexDim,Scalar,VertexOffset>::split_polygon( 
+  const unsigned int* polygon_vertices, 
+  unsigned int polygon_size
+) {
+  //iterate on edges
+  for( unsigned int vertex_index = 1; 
+       vertex_index < polygon_size-1; 
+       ++vertex_index ) {
+    //add a triangle to the triangle vector
+    triangles_.push_back(polygon_vertices[0             ]) ;
+    triangles_.push_back(polygon_vertices[vertex_index  ]) ;
+    triangles_.push_back(polygon_vertices[vertex_index+1]) ;
+  }
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Mesh/wrapper_fwd.hpp b/contrib/Revoropt/include/Revoropt/Mesh/wrapper_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..cd60feb9d46d49246e6efe2ea879fc0084e00876
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Mesh/wrapper_fwd.hpp
@@ -0,0 +1,662 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_MESH_WRAPPER_H_
+#define _REVOROPT_MESH_WRAPPER_H_
+
+#include "base_fwd.hpp"
+#include "connectivity_fwd.hpp"
+
+namespace Revoropt {
+
+/*** Read only wrapper, to build a Read only mesh from given pointers ***/
+
+/** Fixed face size case **/
+
+template<
+  int _FaceSize, 
+  int _VertexDim, 
+  typename _Scalar, 
+  int _VertexOffset
+>
+class ROMeshWrapper : public ROMesh<_FaceSize,_VertexDim,_Scalar,_VertexOffset>
+{
+  public:
+  
+    typedef ROMesh<_FaceSize,_VertexDim,_Scalar,_VertexOffset> Base ;
+
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = _FaceSize,
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+
+    /** Construction **/
+    ROMeshWrapper() : Base() {} ;
+
+    /*  From raw arrays */
+    ROMeshWrapper( const Scalar* vertices, 
+                   unsigned int vertices_size,
+                   const unsigned int* faces,
+                   const unsigned int* face_neighbourhoods,
+                   unsigned int faces_size
+                 ) : Base( vertices, vertices_size, 
+                           faces, face_neighbourhoods, faces_size
+                         ) {
+    };
+
+    /*  From a set of vertices and the faces/neighbourhoods of another mesh */
+    template<int _OtherDim, int _OtherOffset>
+    ROMeshWrapper( const Scalar* vertices, 
+                   unsigned int vertices_size,
+                   const ROMesh< _FaceSize,
+                                 _OtherDim,
+                                 _Scalar,
+                                 _OtherOffset
+                               >* combinatorics
+                 ) : Base( vertices, vertices_size, 
+                           combinatorics->faces_, 
+                           combinatorics->face_neighbourhoods_, 
+                           combinatorics->faces_size_
+                         ) {
+    } ;
+
+    /*  From another mesh */
+    template<int _OtherDim, int _OtherOffset>
+    ROMeshWrapper( const ROMesh< _FaceSize,
+                                 _OtherDim,
+                                 _Scalar,
+                                 _OtherOffset
+                             >* rhs
+                 ) : Base( rhs->vertices_, rhs->vertices_size_,
+                           rhs->faces_, 
+                           rhs->face_neighbourhoods_, 
+                           rhs->faces_size_
+                         ) {
+    } ;
+
+    /** Changing pointers **/
+    /* All pointers */
+    template<int _OtherDim, int _OtherOffset>
+    ROMeshWrapper& operator=( const ROMesh< FaceSize,
+                                            _OtherDim,
+                                            Scalar,
+                                            _OtherOffset
+                                            >& rhs ) { 
+      wrap(&rhs) ;
+      return *this ;
+    }
+
+    template<int _OtherDim, int _OtherOffset>
+    void wrap( const ROMesh< FaceSize,
+                             _OtherDim,
+                             Scalar,
+                             _OtherOffset
+                             >* rhs ) {
+      Base::vertices_ = 
+        const_cast<_Scalar*>(rhs->vertices_) ;
+      Base::vertices_size_ = 
+        rhs->vertices_size_ ;
+      Base::faces_ = 
+        const_cast<unsigned int*>(rhs->faces_) ;
+      Base::face_neighbourhoods_ = 
+        const_cast<unsigned int*>(rhs->face_neighbourhoods_) ;
+      Base::faces_size_ = 
+        rhs->faces_size_ ;
+      Base::set_dirty() ;
+    }
+
+    /* Vertex pointer */
+    void set_vertices( const Scalar* vertices, 
+                       unsigned int vertices_size
+                     ) {
+      Base::vertices_ = const_cast<_Scalar*>(vertices) ;
+      Base::vertices_size_ = vertices_size ;
+      Base::set_dirty() ;
+    }
+
+    /* Face pointers */
+    void set_faces( const unsigned int* faces,
+                    const unsigned int* face_neighbourhoods,
+                    unsigned int faces_size
+                  ) {
+      Base::faces_ = const_cast<unsigned int*>(faces) ;
+      Base::face_neighbourhoods_ = const_cast<unsigned int*>(face_neighbourhoods) ;
+      Base::faces_size_ = faces_size ;
+      Base::set_dirty() ;
+    }
+
+
+} ;
+
+/** Variable face size case **/
+
+template<
+  int _VertexDim, 
+  typename _Scalar, 
+  int _VertexOffset
+>
+class ROMeshWrapper<Variable, _VertexDim, _Scalar, _VertexOffset> : 
+  public ROMesh<Variable,_VertexDim,_Scalar,_VertexOffset> 
+{
+  public:
+
+    typedef ROMesh<Variable,_VertexDim,_Scalar,_VertexOffset> Base ;
+  
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = Variable,
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+
+    /** Construction **/
+    ROMeshWrapper() : Base() {} ;
+
+    /*  From raw arrays */
+    ROMeshWrapper( const Scalar* vertices, 
+                   unsigned int vertices_size,
+                   const unsigned int* faces,
+                   const unsigned int* face_ends,
+                   const unsigned int* face_neighbourhoods,
+                   unsigned int faces_size
+                 ) : Base( vertices, vertices_size, 
+                           faces, face_ends, face_neighbourhoods, faces_size
+                         ) {
+    };
+
+    /*  From a set of vertices and the faces/neighbourhoods of another mesh */
+    template<int _OtherDim, int _OtherOffset>
+    ROMeshWrapper( const Scalar* vertices, 
+                   unsigned int vertices_size,
+                   const ROMesh< Variable,
+                                 _OtherDim,
+                                 Scalar,
+                                 _OtherOffset
+                               >* combinatorics
+                 ) : Base( vertices, vertices_size, 
+                           combinatorics->faces_, 
+                           combinatorics->face_ends_, 
+                           combinatorics->face_neighbourhoods_, 
+                           combinatorics->faces_size_
+                         ) {
+    } ;
+
+    /*  From another mesh */
+    template<int _OtherDim, int _OtherOffset>
+    ROMeshWrapper( const ROMesh< Variable,
+                                 _OtherDim,
+                                 Scalar,
+                                 _OtherOffset
+                             >* rhs
+                 ) : Base( rhs->vertices_, rhs->vertices_size_,
+                           rhs->faces_, 
+                           rhs->face_ends_,
+                           rhs->face_neighbourhoods_, 
+                           rhs->faces_size_
+                         ) {
+    } ;
+
+    /** Changing pointers **/
+    /* All pointers */
+    template<int _OtherDim, int _OtherOffset>
+    ROMeshWrapper& operator=( const ROMesh< Variable,
+                                            _OtherDim,
+                                            Scalar,
+                                            _OtherOffset
+                                            >& rhs ) { 
+      wrap(&rhs) ;
+      return *this ;
+    }
+
+    template<int _OtherDim, int _OtherOffset>
+    void wrap( const ROMesh< Variable,
+                             _OtherDim,
+                             Scalar,
+                             _OtherOffset
+                             >* rhs ) {
+      Base::vertices_ = 
+        const_cast<_Scalar*>(rhs->vertices_) ;
+      Base::vertices_size_ = 
+        rhs->vertices_size_ ;
+      Base::faces_ = 
+        const_cast<unsigned int*>(rhs->faces_) ;
+      Base::face_ends_ = 
+        const_cast<unsigned int*>(rhs->face_ends_) ;
+      Base::face_neighbourhoods_ = 
+        const_cast<unsigned int*>(rhs->face_neighbourhoods_) ;
+      Base::faces_size_ = 
+        rhs->faces_size_ ;
+      Base::set_dirty() ;
+    }
+
+    /* Vertex pointer */
+    void set_vertices( const Scalar* vertices, 
+                       unsigned int vertices_size
+                     ) {
+      Base::vertices_ = const_cast<_Scalar*>(vertices) ;
+      Base::vertices_size_ = vertices_size ;
+      Base::set_dirty() ;
+    }
+
+    /* Face pointers */
+    void set_faces( const unsigned int* faces,
+                    const unsigned int* face_neighbourhoods,
+                    const unsigned int* face_ends,
+                    unsigned int faces_size
+                  ) {
+      Base::faces_ = const_cast<unsigned int*>(faces) ;
+      Base::face_ends_ = const_cast<unsigned int*>(face_ends) ;
+      Base::face_neighbourhoods_ = const_cast<unsigned int*>(face_neighbourhoods) ;
+      Base::faces_size_ = faces_size ;
+      Base::set_dirty() ;
+    }
+
+
+} ;
+
+/*** Read write wrapper, to build a Read write mesh from given pointers ***/
+/* Note, this is not a subclass of ROMeshWrapper, since the set_{vertices|faces} 
+ * methods would allow setting the pointers of a RWMeshWrapper from const data.
+ * */
+
+/** Fixed face size case **/
+
+template<
+  int _FaceSize, 
+  int _VertexDim, 
+  typename _Scalar, 
+  int _VertexOffset
+>
+class MeshWrapper : public Mesh<_FaceSize,_VertexDim,_Scalar,_VertexOffset>
+{
+  public:
+  
+    typedef Mesh<_FaceSize,_VertexDim,_Scalar,_VertexOffset> Base ;
+
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = _FaceSize,
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+
+    /** Construction **/
+    MeshWrapper() : Base() {} ;
+
+    /*  From raw arrays */
+    MeshWrapper( Scalar* vertices, 
+                 unsigned int vertices_size,
+                 unsigned int* faces,
+                 unsigned int* face_neighbourhoods,
+                 unsigned int faces_size
+               ) : Base( vertices, vertices_size, 
+                         faces, face_neighbourhoods, faces_size
+                       ) {
+    };
+
+    /*  From a set of vertices and the faces/neighbourhoods of another mesh */
+    template<int _OtherDim, int _OtherOffset>
+    MeshWrapper( Scalar* vertices, 
+                 unsigned int vertices_size,
+                 Mesh< _FaceSize,
+                       _OtherDim,
+                       _Scalar,
+                       _OtherOffset
+                     >* combinatorics
+               ) : Base( vertices, vertices_size, 
+                         combinatorics->faces_, 
+                         combinatorics->face_neighbourhoods_, 
+                         combinatorics->faces_size_
+                       ) {
+    } ;
+
+    /*  From another mesh */
+    template<int _OtherDim, int _OtherOffset>
+    MeshWrapper( Mesh< _FaceSize,
+                       _OtherDim,
+                       _Scalar,
+                       _OtherOffset
+                   >* rhs
+               ) : Base( rhs->vertices_, rhs->vertices_size_,
+                           rhs->faces_, 
+                           rhs->face_neighbourhoods_, 
+                           rhs->faces_size_
+                         ) {
+    } ;
+
+    /** Changing pointers **/
+    template<int _OtherDim, int _OtherOffset>
+    MeshWrapper& operator=( Mesh< FaceSize,
+                                  _OtherDim,
+                                  Scalar,
+                                  _OtherOffset
+                                  >& rhs ) { 
+      wrap(&rhs) ;
+      return *this ;
+    }
+
+    /* All pointers */
+    template<int _OtherDim, int _OtherOffset>
+    void wrap( Mesh< FaceSize,
+                     _OtherDim,
+                     Scalar,
+                     _OtherOffset
+                     >* rhs ) {
+      Base::vertices_ = rhs->vertices_ ;
+      Base::vertices_size_ = rhs->vertices_size_ ;
+      Base::faces_ = rhs->faces_  ;
+      Base::face_neighbourhoods_ = rhs->face_neighbourhoods_ ;
+      Base::faces_size_ = rhs->faces_size_ ;
+      Base::set_dirty() ;
+    }
+
+    /* Vertex pointer */
+    void set_vertices( Scalar* vertices, 
+                       unsigned int vertices_size
+                     ) {
+      Base::vertices_ = vertices ;
+      Base::vertices_size_ = vertices_size ;
+      Base::set_dirty() ;
+    }
+
+    /* Face pointers */
+    void set_faces( unsigned int* faces,
+                    unsigned int* face_neighbourhoods,
+                    unsigned int faces_size
+                  ) {
+      Base::faces_ = faces ;
+      Base::face_neighbourhoods_ = face_neighbourhoods ;
+      Base::faces_size_ = faces_size ;
+      Base::set_dirty() ;
+    }
+
+
+} ;
+
+/** Variable face size case **/
+
+template<
+  int _VertexDim, 
+  typename _Scalar, 
+  int _VertexOffset
+>
+class MeshWrapper<Variable, _VertexDim, _Scalar, _VertexOffset> : 
+  public Mesh<Variable,_VertexDim,_Scalar,_VertexOffset> 
+{
+  public:
+
+    typedef Mesh<Variable,_VertexDim,_Scalar,_VertexOffset> Base ;
+  
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = Variable,
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+
+    /** Construction **/
+    MeshWrapper() : Base() {} ;
+
+    /*  From raw arrays */
+    MeshWrapper( Scalar* vertices, 
+                 unsigned int vertices_size,
+                 unsigned int* faces,
+                 unsigned int* face_ends,
+                 unsigned int* face_neighbourhoods,
+                 unsigned int faces_size
+               ) : Base( vertices, vertices_size, 
+                         faces, face_ends, face_neighbourhoods, faces_size
+                       ) {
+    };
+
+    /*  From a set of vertices and the faces/neighbourhoods of another mesh */
+    template<int _OtherDim, int _OtherOffset>
+    MeshWrapper( Scalar* vertices, 
+                 unsigned int vertices_size,
+                 Mesh< Variable,
+                       _OtherDim,
+                       Scalar,
+                       _OtherOffset
+                     >* combinatorics
+               ) : Base( vertices, vertices_size, 
+                         combinatorics->faces_, 
+                         combinatorics->face_ends_, 
+                         combinatorics->face_neighbourhoods_, 
+                         combinatorics->faces_size_
+                       ) {
+    } ;
+
+    /*  From another mesh */
+    template<int _OtherDim, int _OtherOffset>
+    MeshWrapper( Mesh< Variable,
+                       _OtherDim,
+                       _Scalar,
+                       _OtherOffset
+                   >* rhs
+               ) : Base( rhs->vertices_, rhs->vertices_size_,
+                           rhs->faces_, 
+                           rhs->face_ends_, 
+                           rhs->face_neighbourhoods_, 
+                           rhs->faces_size_
+                         ) {
+    } ;
+
+    /** Changing pointers **/
+    /* All pointers */
+    template<int _OtherDim, int _OtherOffset>
+    MeshWrapper& operator=( Mesh< Variable,
+                                  _OtherDim,
+                                  Scalar,
+                                  _OtherOffset
+                                  >& rhs ) { 
+      wrap(&rhs) ;
+      return *this ;
+    }
+
+    template<int _OtherDim, int _OtherOffset>
+    void wrap( Mesh< Variable,
+                     _OtherDim,
+                     Scalar,
+                     _OtherOffset
+                     >* rhs ) {
+      Base::vertices_ = rhs->vertices_ ;
+      Base::vertices_size_ = rhs->vertices_size_ ;
+      Base::faces_ = rhs->faces_  ;
+      Base::face_ends_ = rhs->face_ends_  ;
+      Base::face_neighbourhoods_ = rhs->face_neighbourhoods_ ;
+      Base::faces_size_ = rhs->faces_size_ ;
+      Base::set_dirty() ;
+    }
+
+    /* Vertex pointer */
+    void set_vertices( Scalar* vertices, 
+                       unsigned int vertices_size
+                     ) {
+      Base::vertices_ = vertices ;
+      Base::vertices_size_ = vertices_size ;
+      Base::set_dirty() ;
+    }
+
+    /* Face pointers */
+    void set_faces( unsigned int* faces,
+                    unsigned int* face_neighbourhoods,
+                    unsigned int* face_ends,
+                    unsigned int faces_size
+                  ) {
+      Base::faces_ = faces ;
+      Base::face_ends_ = face_ends ;
+      Base::face_neighbourhoods_ = face_neighbourhoods ;
+      Base::faces_size_ = faces_size ;
+      Base::set_dirty() ;
+    }
+
+
+} ;
+
+/*** Triangulation wrapper, triangulating a mesh ***/
+
+template<
+  int _VertexDim, 
+  typename _Scalar, 
+  int _VertexOffset
+>
+class ROTriangulationWrapper : 
+  public ROMesh<3,_VertexDim,_Scalar,_VertexOffset>
+{
+  public:
+  
+    typedef ROMesh<3,_VertexDim,_Scalar,_VertexOffset> Base ;
+
+    typedef _Scalar Scalar ;
+
+    enum {
+      FaceSize = 3,
+      VertexDim = _VertexDim,
+      VertexOffset = _VertexOffset
+    } ;
+
+    using Base::NO_NEIGHBOUR ;
+
+    /** Construction **/
+    ROTriangulationWrapper() : Base(), c_computer_(this) {}
+
+    /*  Wrap other meshes */
+
+    template <int _FaceSize>
+    ROTriangulationWrapper( const ROMesh<_FaceSize,
+                                         VertexDim,
+                                         Scalar,
+                                         VertexOffset
+                                        >* mesh
+                          ) : Base( mesh->vertices_, mesh->vertices_size_, 
+                                    NULL, NULL, 0
+                                  ),
+                              c_computer_(this) {
+      set_faces(mesh->faces_, _FaceSize, mesh->faces_size_) ;
+    } ;
+
+    ROTriangulationWrapper( const ROMesh<3,
+                                         VertexDim,
+                                         Scalar,
+                                         VertexOffset
+                                        >* mesh
+                             ) : Base( mesh->vertices_, mesh->vertices_size_, 
+                                       mesh->faces_, mesh->face_neighbourhoods_,
+                                       mesh->faces_size_
+                                     ),
+                                 c_computer_() {
+    } ;
+
+    ROTriangulationWrapper( const ROMesh<Variable,
+                                         VertexDim,
+                                         Scalar,
+                                         VertexOffset
+                                        >* mesh
+                          ) : Base( mesh->vertices_, mesh->vertices_size_, 
+                                    NULL, NULL, 0
+                                  ),
+                              c_computer_(this) {
+
+      set_faces(mesh->faces_, mesh->face_ends_, mesh->faces_size_) ;
+    } ;
+
+
+
+    /** Changing pointers **/
+    template <int _FaceSize>
+    void wrap( 
+        const ROMesh<_FaceSize, VertexDim, Scalar, VertexOffset>* mesh
+        ) {
+      Base::vertices_ = mesh->vertices_ ;
+      Base::vertices_size_ = mesh->vertices_size_ ;
+      set_faces(mesh->faces, _FaceSize, mesh->faces_size_) ;
+    }
+
+    void wrap( 
+        const ROMesh<Variable, VertexDim, Scalar, VertexOffset>* mesh
+        ) {
+      Base::vertices_ = mesh->vertices_ ;
+      Base::vertices_size_ = mesh->vertices_size_ ;
+      set_faces(mesh->faces_, mesh->face_ends_, mesh->faces_size_) ;
+    }
+
+    void wrap( 
+        const ROMesh<3, VertexDim, Scalar, VertexOffset>* mesh
+        ) {
+      Base::vertices_ = mesh->vertices_ ;
+      Base::vertices_size_ = mesh->vertices_size_ ;
+      Base::faces_ = mesh->faces_ ;
+      Base::face_neighbourhoods_ = mesh->face_neighbourhoods_ ;
+      Base::faces_size_ = mesh->faces_size_ ;
+    }
+
+    /* Vertex pointer */
+    void set_vertices( const Scalar* vertices, 
+                       unsigned int vertices_size
+                     ) {
+      Base::vertices_ = vertices ;
+      Base::vertices_size_ = vertices_size ;
+      Base::set_dirty() ;
+    }
+
+    /** Provide new base faces for the triangles **/
+
+    /* Fixed sized faces */
+    void set_faces( const unsigned int* faces,
+                    unsigned int face_size,
+                    unsigned int faces_size
+                  ) ;
+
+    /* Variable sized faces */
+    void set_faces( const unsigned int* faces,
+                    const unsigned int* face_ends,
+                    unsigned int faces_size
+                  ) ;
+
+    /* Access the triangles array */
+    const unsigned int* triangles() const {
+      if(Base::faces_size_ != 0 && triangles_.size() == 0) {
+        return Base::faces() ;
+      } else {
+        return triangles_.data() ;
+      }
+    }
+
+  private:
+
+    /* Naïvely split a polygon into triangles */
+    void split_polygon( const unsigned int* polygon_vertices, 
+                        unsigned int polygon_size
+                      ) ;
+
+    /* Triangles */
+    std::vector<unsigned int> triangles_ ;
+
+    /* Neighbourhoods */
+    ConnectivityComputer<Base> c_computer_ ;
+} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Neighbours/aabox_def.hpp b/contrib/Revoropt/include/Revoropt/Neighbours/aabox_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3a43f487e70f4f070c35e5202b33612e4dc2a706
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Neighbours/aabox_def.hpp
@@ -0,0 +1,529 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_AABOX_DEF_HPP_
+#define _REVOROPT_AABOX_DEF_HPP_
+
+#include "aabox_fwd.hpp"
+
+#include <algorithm>
+
+namespace Revoropt {
+
+template< int Dim , typename Scalar >
+AABox<Dim,Scalar>::AABox() {
+  //initialize to an empty box
+  if(Dim == 0) return ;
+  bounds_[0] = 1 ;
+  bounds_[1] = 1 ;
+} ;
+
+template< int Dim , typename Scalar >
+AABox<Dim,Scalar>::AABox( Scalar bounds[2*Dim] ) { 
+  set_bounds(bounds) ;
+  std::copy(bounds, bounds+2*Dim, bounds_) ; 
+} ;
+
+/* Setting bounds */
+template< int Dim , typename Scalar >
+void AABox<Dim,Scalar>::set_bounds( Scalar bounds[2*Dim] ) {
+  std::copy(bounds, bounds+2*Dim, bounds_) ; 
+}
+
+//initialize a 0 volume box to a point position
+template< int Dim , typename Scalar >
+void AABox<Dim,Scalar>::init_to( const Scalar point[Dim] ) {
+  for(int axis = 0; axis < Dim; ++axis) {
+    bounds_[2*axis  ] = point[axis] ;
+    bounds_[2*axis+1] = point[axis] ;
+  }
+}
+
+//increase the box size to contain the given point
+template< int Dim , typename Scalar >
+void AABox<Dim,Scalar>::fit_to( const Scalar point[Dim] ) {
+  for(int axis = 0; axis < Dim; ++axis) {
+    bounds_[2*axis  ] = std::min(point[axis],bounds_[2*axis  ]) ;
+    bounds_[2*axis+1] = std::max(point[axis],bounds_[2*axis+1]) ;
+  }
+}
+
+//grow the box (decrease min bounds and increase max bounds) given an offset
+template< int Dim , typename Scalar >
+void AABox<Dim,Scalar>::grow( Scalar offset ) {
+  for(int axis = 0; axis < Dim; ++axis) {
+    bounds_[2*axis  ] -= offset ;
+    bounds_[2*axis+1] += offset ;
+  }
+}
+
+/* Accessing bounds */
+template< int Dim , typename Scalar >
+Scalar* AABox<Dim,Scalar>::axis_bounds( int axis ) { 
+  return bounds_ + 2*axis ; 
+} ;
+template< int Dim , typename Scalar >
+Scalar& AABox<Dim,Scalar>::min_axis_bound( int axis ) { 
+  return bounds_[2*axis  ] ; 
+} ;
+template< int Dim , typename Scalar >
+Scalar& AABox<Dim,Scalar>::max_axis_bound( int axis ) { 
+  return bounds_[2*axis+1] ; 
+} ;
+
+template< int Dim , typename Scalar >
+const Scalar* AABox<Dim,Scalar>::axis_bounds( int axis ) const { 
+  return bounds_ + 2*axis ; 
+} ;
+template< int Dim , typename Scalar >
+const Scalar& AABox<Dim,Scalar>::min_axis_bound( int axis ) const { 
+  return bounds_[2*axis  ] ; 
+} ;
+template< int Dim , typename Scalar >
+const Scalar& AABox<Dim,Scalar>::max_axis_bound( int axis ) const { 
+  return bounds_[2*axis+1] ; 
+} ;
+
+/* Splitting */
+template< int Dim , typename Scalar >
+void AABox<Dim,Scalar>::split_at_pos( int axis, 
+                                      Scalar pos, 
+                                      AABox& b1, 
+                                      AABox& b2 
+                                    ) const {
+  //copy the bounds
+  std::copy(bounds_, bounds_+2*Dim, b1.bounds_) ;
+  std::copy(bounds_, bounds_+2*Dim, b2.bounds_) ;
+  //reduce the split boxes according to the split position
+  b1.bounds_[2*axis] = bounds_[2*axis] ;
+  b1.bounds_[2*axis+1] = std::min(pos,bounds_[2*axis+1]) ;
+  b2.bounds_[2*axis] = std::max(pos,bounds_[2*axis]) ;
+  b2.bounds_[2*axis+1] = bounds_[2*axis+1] ;
+  //note that in case pos is outside the range, one box will be the current
+  //box while the other will be empty (max bound is below min bound)
+}
+
+template< int Dim , typename Scalar >
+void AABox<Dim,Scalar>::split_at_ratio( int axis, 
+                                        Scalar ratio, 
+                                        AABox& b1, 
+                                        AABox& b2 
+                                      ) const {
+  //split position
+  Scalar pos = (1-ratio)*bounds_[2*axis] + ratio*bounds_[2*axis+1] ;
+  //split
+  split_at_pos(axis,pos,b1,b2) ;
+}
+
+/* Point query */
+template< int Dim , typename Scalar >
+bool AABox<Dim,Scalar>::contains( const Scalar point[Dim] ) const {
+  //test for every dimension
+  for(int axis=0; axis<Dim; ++axis) {
+    if((point[axis] < bounds_[2*axis]) || (point[axis] > bounds_[2*axis+1])) {
+      return false ;
+    }
+  }
+  //beware that a box of dimension 0 contains anything
+  return true ;
+}
+
+/* AABox clipping */
+template< int Dim , typename Scalar >
+bool AABox<Dim,Scalar>::clips_aabox( const AABox<Dim,Scalar>& rhs ) const {
+  //for each axis check that the intervals intersect
+  for(int axis=0; axis<Dim; ++axis) {
+    Scalar bmin = std::max(bounds_[2*axis  ],rhs.bounds_[2*axis  ]) ;
+    Scalar bmax = std::min(bounds_[2*axis+1],rhs.bounds_[2*axis+1]) ;
+    if(bmax < bmin) return false ;
+  }
+  return true ;
+}
+
+template< int Dim , typename Scalar >
+bool AABox<Dim,Scalar>::aabox_intersection( const AABox<Dim,Scalar>& rhs, 
+                                            AABox<Dim,Scalar>& output 
+                                          ) const {
+  //for each axis check that the intervals intersect
+  for(int axis=0; axis<Dim; ++axis) {
+    Scalar bmin = std::max(bounds_[2*axis],rhs.bounds_[2*axis]) ;
+    Scalar bmax = std::min(bounds_[2*axis+1],rhs.bounds_[2*axis+1]) ;
+    if(bmax <= bmin) return false ;
+    output.bounds_[2*axis] = bmin ;
+    output.bounds_[2*axis+1] = bmax ;
+  }
+  return true ;
+}
+
+/* Triangle clipping */
+template< int Dim , typename Scalar >
+template< typename Triangulation >
+bool AABox<Dim,Scalar>::clips_triangle_bbox( const unsigned int triangle, 
+                                             const Triangulation* mesh
+                                           ) const {
+  //triangle vertices
+  const unsigned int* tverts = mesh->face(triangle) ;
+  //initialize the bbox of the triangle
+  AABox<Dim,Scalar> bbox ;
+  bbox.init_to(mesh->vertex(tverts[0])) ;
+  //compute the bounds
+  for(int i = 1; i<3; ++i) {
+    bbox.fit_to(mesh->vertex(tverts[i])) ;
+  }
+  return clips_aabox(bbox) ;
+}
+
+template< int Dim , typename Scalar >
+bool AABox<Dim,Scalar>::clips_triangle_bbox( const unsigned int* triangle, 
+                                             const Scalar* vertices
+                                           ) const {
+  //wrap th triangle as a mesh
+  WrapMesh mesh(vertices, 3, triangle, no_neighbours, 1) ;
+  return clips_triangle_bbox(0, &mesh) ;
+}
+
+template< int Dim , typename Scalar >
+template< typename Triangulation >
+bool AABox<Dim,Scalar>::triangle_intersection( const unsigned int triangle, 
+                                               const Triangulation* mesh,
+                                               std::vector<Scalar>& output
+                                             ) const {
+  if(!clips_triangle_bbox(triangle,mesh)) return false ;
+  //initialize clipping polygon
+  Polygon<Triangulation> polygon ;
+  init_intersection(polygon) ;
+  //iterate over the dimensions
+  for(int axis=0; axis<Dim; ++axis) {
+    clip_by_axis(axis,polygon,triangle,mesh) ;
+    if(polygon.size() < 3) return false ;
+  }
+  //compute and output the clipped polygon vertices
+  output.resize(Dim*polygon.size()) ;
+  for(unsigned int vertex = 0; vertex < polygon.size(); ++vertex) {
+    polygon[vertex].position(triangle, mesh, output.data() + Dim*vertex) ;
+  }
+  //beware that a box of dimension 0 always contains any triangle
+  return true ;
+}
+
+template< int Dim , typename Scalar >
+bool AABox<Dim,Scalar>::triangle_intersection( const unsigned int* triangle, 
+                                               const Scalar* vertices,
+                                               std::vector<Scalar>& output
+                                             ) const {
+  //wrap th triangle as a mesh
+  WrapMesh mesh(vertices, 3, triangle, no_neighbours, 1) ;
+  return triangle_intersection(0, &mesh, output);
+}
+
+template< int Dim , typename Scalar >
+template< typename Triangulation >
+bool AABox<Dim,Scalar>::clips_triangle( const unsigned int triangle, 
+                                        const Triangulation* mesh 
+                                      ) const {
+  if(!clips_triangle_bbox(triangle,mesh)) return false ;
+  //initialize clipping polygon
+  Polygon<Triangulation> polygon ;
+  init_intersection(polygon) ;
+  //iterate over the dimensions
+  for(int axis=0; axis<Dim; ++axis) {
+    clip_by_axis(axis,polygon,triangle,mesh) ;
+    if(polygon.size() < 3) return false ;
+  }
+  //beware that a box of dimension 0 always clips any triangle
+  return true ;
+}
+
+template< int Dim , typename Scalar >
+bool AABox<Dim,Scalar>::clips_triangle( const unsigned int* triangle, 
+                                        const Scalar* vertices 
+                                      ) const {
+  //wrap th triangle as a mesh
+  WrapMesh mesh(vertices, 3, triangle, no_neighbours, 1) ;
+  return clips_triangle(0, &mesh);
+}
+
+  /* during intersection, symbolic representation of the polygon vertices */
+template< int Dim , typename Scalar >
+template< typename Tgl>
+int AABox<Dim,Scalar>::ClipVertex<Tgl>::in_bounds( int axis, 
+                                                   const Scalar bounds[2], 
+                                                   const unsigned int triangle, 
+                                                   const Tgl* mesh
+                                                 ) {
+  //vertices of the triangle
+  const Scalar* verts[3] ;
+  for(int i=0; i<3; ++i) {
+    verts[i] = mesh->vertex(mesh->face(triangle)[i]) ;
+  }
+  //coordinate of the vertex to test
+  Scalar coord = 0;
+  if(type == ORIGINAL_V) {
+    //original vertex, return its coordinate
+    coord = verts[symi][axis] ;
+  } else if(type == EDGE_V) {
+    //edge vertex, combine the coordinates of the edge vertices
+    coord =    symd[0]  * verts[symi][axis]
+          + (1-symd[0]) * verts[(symi+1)%3][axis] ;
+  } else if(type == FACE_V) {
+    //face vertex, combine the coordinates of the triangle vertices
+    coord =    symd[0]          * verts[0][axis]
+          +    symd[1]          * verts[1][axis]
+          + (1-symd[0]-symd[1]) * verts[2][axis] ;
+  }
+  //below bounds
+  if(coord < bounds[0]) return -1 ;
+  //above bounds
+  if(coord > bounds[1]) return  1 ;
+  //in bounds
+  return 0 ;
+}
+
+template< int Dim , typename Scalar >
+template< typename Tgl>
+void AABox<Dim,Scalar>::ClipVertex<Tgl>::position( const unsigned int triangle,
+                                                   const Tgl* mesh,
+                                                   Scalar* output 
+                                                 ) {
+  //vertices of the triangle
+  const unsigned int* tverts = mesh->face(triangle) ;
+  if(type == ORIGINAL_V) {
+    //original vertex, copy its coordinate
+    std::copy(mesh->vertex(tverts[symi]), 
+              mesh->vertex(tverts[symi]) + Dim, 
+              output
+    ) ;
+  } else if(type == EDGE_V) {
+    //edge vertex, combine the edge vertices
+    const Scalar* x0 = mesh->vertex(tverts[ symi     ]) ;
+    const Scalar* x1 = mesh->vertex(tverts[(symi+1)%3]) ;
+    for(int axis=0; axis < Dim; ++axis) {
+      output[axis] = symd[0]*x0[axis] + (1-symd[0])*x1[axis] ;
+    }
+  } else if(type == FACE_V) {
+    //face vertex, combine the triangle vertices
+    const Scalar* x0 = mesh->vertex(tverts[0]) ;
+    const Scalar* x1 = mesh->vertex(tverts[1]) ;
+    const Scalar* x2 = mesh->vertex(tverts[2]) ;
+    for(int axis=0; axis < Dim; ++axis) {
+      output[axis] =    symd[0]         *x0[axis] 
+                   +    symd[1]         *x1[axis] 
+                   + (1-symd[0]-symd[1])*x2[axis] ;
+    }
+  }
+}
+
+template< int Dim , typename Scalar >
+template< typename Triangulation >
+void AABox<Dim,Scalar>::fill_edge_vertex( int bound_index,
+                                          int edge_index,
+                                          const unsigned int triangle,
+                                          const Triangulation* mesh,
+                                          ClipVertex<Triangulation>& target
+                                        ) const {
+  //triangle vertices
+  const unsigned int* tverts = mesh->face(triangle) ;
+  //axis corresponding to the vertex
+  target.symi = edge_index ;
+  //bound corresponding to the vertex
+  Scalar x = bounds_[bound_index] ;
+  //corresponding vertex coordinates
+  Scalar x0 = mesh->vertex(tverts[ edge_index     ])[bound_index/2] ;
+  Scalar x1 = mesh->vertex(tverts[(edge_index+1)%3])[bound_index/2] ;
+  //barycentric coordinate of the edge point along the edge
+  if(x0 != x1) {
+    target.symd[0] = (x-x1)/(x0-x1) ;
+  } else {
+    target.symd[0] = 0 ;
+  }
+  target.symd[1] = 0 ;
+  //type of the vertex
+  target.type = EDGE_V ;
+}
+
+template< int Dim , typename Scalar >
+template< typename Triangulation >
+void AABox<Dim,Scalar>::fill_face_vertex( int bound_index1,
+                                          int bound_index2,
+                                          const unsigned int triangle,
+                                          const Triangulation* mesh,
+                                          ClipVertex<Triangulation>& target
+                                        ) const {
+  //triangle vertice
+  const unsigned int* tverts = mesh->face(triangle) ;
+  target.symi = 0 ;
+  //bounds corresponding to the vertex
+  Scalar x = bounds_[bound_index1] ;
+  Scalar y = bounds_[bound_index2] ;
+  //corresponding vertex coordinates
+  Scalar x0 = mesh->vertex(tverts[0])[bound_index1/2] ;
+  Scalar y0 = mesh->vertex(tverts[0])[bound_index2/2] ;
+  Scalar x1 = mesh->vertex(tverts[1])[bound_index1/2] ;
+  Scalar y1 = mesh->vertex(tverts[1])[bound_index2/2] ;
+  Scalar x2 = mesh->vertex(tverts[2])[bound_index1/2] ;
+  Scalar y2 = mesh->vertex(tverts[2])[bound_index2/2] ;
+  //determinant of the system
+  Scalar det = (x0-x2)*(y1-y2) - (x1-x2)*(y0-y2) ;
+  if(det == 0) {
+    target.symd[0] = 0 ;
+    target.symd[1] = 0 ;
+  } else {
+    target.symd[0] = ((x-x2)*(y1-y2)-(x1-x2)*(y-y2))/det ;
+    target.symd[1] = ((x0-x2)*(y-y2)-(x-x2)*(y0-y2))/det ;
+  }
+  //type of the vertex
+  target.type = FACE_V ;
+}
+
+
+/* intersection initialization */
+template< int Dim , typename Scalar >
+template< typename Triangulation >
+void AABox<Dim,Scalar>::init_intersection( Polygon<Triangulation>& polygon 
+                                         ) const {
+  //initialize the polygon as a triangle
+  //since the polygon is symbolic, this does not depend on the triangle
+  polygon.resize(3) ;
+  for(int i=0; i<3; ++i) {
+    polygon[i].type = ORIGINAL_V ;
+    polygon[i].symi = i ;
+    polygon[i].symd[0] = 0 ;
+    polygon[i].symd[1] = 0 ;
+    polygon[i].esym = i ;
+  }
+}
+
+/* clip the polygon along one axis */
+template< int Dim , typename Scalar >
+template< typename Triangulation >
+void AABox<Dim,Scalar>::clip_by_axis( int axis, Polygon<Triangulation>& polygon, 
+                                      const unsigned int triangle, 
+                                      const Triangulation* mesh
+                                    ) const {
+  //size of the input polygon
+  unsigned int size = polygon.size() ;
+  //polygon in which the clipped polygon will be built
+  Polygon<Triangulation> next_polygon ;
+  next_polygon.reserve(size) ;
+  //bounds corresponding to the axis
+  const Scalar* bounds = axis_bounds(axis) ;
+  //sides of the polygon vertices wrt. the bounds
+  int* sides = new int[size] ;
+  for(unsigned int vertex = 0; vertex < size; ++vertex) {
+    sides[vertex] = 
+      polygon[vertex].in_bounds(axis, bounds, triangle, mesh) ;
+  }
+  //build the clipped polygon
+  for(unsigned int vertex = 0; vertex < size; ++vertex) {
+    //sides of two consecutive vertices
+    int my_side = sides[vertex] ;
+    int next_side = sides[(vertex+1)%size] ;
+    //check if the current vertex is to be kept
+    if(my_side == 0) {
+      //the vertex is in, keep it
+      next_polygon.push_back(polygon[vertex]) ;
+    }
+    //test if an intersection has to be inserted
+    if(my_side != next_side) {
+      //test the number of intersections
+      if(my_side*next_side != 0) {
+        //the order of traversal of the bounds
+        int first_bound = my_side < 0 ? 2*axis : 2*axis+1 ;
+        int second_bound = my_side < 0 ? 2*axis+1 : 2*axis ;
+        //two intersections
+        next_polygon.resize(next_polygon.size()+2) ;
+        ClipVertex<Triangulation>& intersection1 = 
+          next_polygon[next_polygon.size()-2] ;
+        intersection1.edge_type = polygon[vertex].edge_type ;
+        intersection1.esym = polygon[vertex].esym ;
+        ClipVertex<Triangulation>& intersection2 = 
+          next_polygon[next_polygon.size()-1] ;
+        intersection2.edge_type = BOUNDARY_E ;
+        intersection2.esym = second_bound ;
+        //types of the intersections
+        if(polygon[vertex].edge_type == ORIGINAL_E) {
+          //the intersection vertices types are EDGE_V
+          fill_edge_vertex( first_bound, 
+                            polygon[vertex].esym, 
+                            triangle, 
+                            mesh, 
+                            intersection1
+                         ) ;
+          fill_edge_vertex( second_bound, 
+                            polygon[vertex].esym, 
+                            triangle, 
+                            mesh, 
+                            intersection2
+                         ) ;
+        } else {
+          //the intersection vertices types are FACE_V
+          fill_face_vertex( first_bound, 
+                            polygon[vertex].esym, 
+                            triangle, 
+                            mesh, 
+                            intersection1
+                         ) ;
+          fill_face_vertex( second_bound, 
+                            polygon[vertex].esym, 
+                            triangle, 
+                            mesh, 
+                            intersection2
+                         ) ;
+        }
+      } else {
+        //crossed bound
+        int bound_index ;
+        //one intersection
+        next_polygon.resize(next_polygon.size()+1) ;
+        ClipVertex<Triangulation>& intersection = 
+          next_polygon[next_polygon.size()-1] ;
+        //edge type of the intersection
+        if(my_side != 0) {
+          //getting in, the edge type is that of the current vertex
+          bound_index = my_side < 0 ? 2*axis : 2*axis+1 ;
+          intersection.edge_type = polygon[vertex].edge_type ;
+          intersection.esym = polygon[vertex].esym ;
+        } else {
+          //going out, the edge corresponds to the current clipping axis
+          bound_index = next_side < 0 ? 2*axis : 2*axis+1 ;
+          intersection.edge_type = BOUNDARY_E ;
+          intersection.esym = bound_index ;
+        }
+        //vertex type of the intersection
+        if(polygon[vertex].edge_type == ORIGINAL_E) {
+          //the vertex type is EDGE_V
+          fill_edge_vertex( bound_index, 
+                            polygon[vertex].esym, 
+                            triangle, 
+                            mesh, 
+                            intersection
+                         ) ;
+        } else {
+          //the vertex type is FACE_V
+          fill_face_vertex( bound_index, 
+                            polygon[vertex].esym, 
+                            triangle, 
+                            mesh, 
+                            intersection
+                         ) ;
+        }
+      }
+    }
+  }
+
+  //swap polygons
+  polygon.swap(next_polygon) ;
+  //cleanup
+  delete [] sides ;
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Neighbours/aabox_fwd.hpp b/contrib/Revoropt/include/Revoropt/Neighbours/aabox_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..8fa6a528cf89d958ac4fd3c8e7fda8388fa8fa29
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Neighbours/aabox_fwd.hpp
@@ -0,0 +1,206 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_AABOX_FWD_HPP_
+#define _REVOROPT_AABOX_FWD_HPP_
+
+#include <Revoropt/Mesh/wrapper_fwd.hpp>
+
+#include <vector>
+
+//TODO bring back potential inline functions
+
+namespace Revoropt {
+
+template< int _Dim = 3, typename _Scalar = double >
+class AABox {
+
+  public :
+
+  /* Typedefs */
+  enum { Dim = _Dim } ;
+  typedef _Scalar Scalar ;
+  typedef Eigen::Matrix<Scalar, Dim, 1> Vector ;
+
+  /* Construction */
+  AABox() ;
+
+  AABox( Scalar bounds[2*Dim] ) ;
+
+  virtual ~AABox() {} ;
+
+  /* Setting bounds */
+  void set_bounds( Scalar bounds[2*Dim] ) ;
+
+  //initialize a 0 volume box to a point position
+  void init_to( const Scalar point[Dim] ) ;
+
+  //increase the box size to contain the given point
+  void fit_to( const Scalar point[Dim] ) ;
+
+  //grow the box (decrease min bounds and increase max bounds) given an offset
+  void grow( Scalar offset ) ;
+
+  /* Accessing bounds */
+  Scalar* axis_bounds( int axis ) ;
+  Scalar& min_axis_bound( int axis ) ;
+  Scalar& max_axis_bound( int axis ) ;
+
+  const Scalar* axis_bounds( int axis ) const  ;
+  const Scalar& min_axis_bound( int axis ) const  ;
+  const Scalar& max_axis_bound( int axis ) const  ;
+
+  /* Splitting */
+  void split_at_pos( int axis, Scalar pos, AABox& b1, AABox& b2 ) const ;
+
+  void split_at_ratio( int axis, Scalar ratio, AABox& b1, AABox& b2 ) const ;
+
+  /* Point query */
+  bool contains( const Scalar point[Dim] ) const ;
+
+  /* AABox clipping */
+  bool clips_aabox( const AABox<Dim,Scalar>& rhs ) const ;
+
+  bool aabox_intersection( const AABox<Dim,Scalar>& rhs, 
+                           AABox<Dim,Scalar>& output 
+                         ) const ;
+
+  /* Triangle clipping */
+  template< typename Triangulation >
+  bool clips_triangle_bbox( const unsigned int triangle, 
+                            const Triangulation* mesh
+                          ) const ;
+
+  bool clips_triangle_bbox( const unsigned int* triangle, 
+                            const Scalar* vertices
+                          ) const ;
+
+  template< typename Triangulation >
+  bool triangle_intersection( const unsigned int triangle, 
+                              const Triangulation* mesh,
+                              std::vector<Scalar>& output
+                            ) const ;
+
+  bool triangle_intersection( const unsigned int* triangle, 
+                              const Scalar* vertices,
+                              std::vector<Scalar>& output
+                            ) const ;
+
+  template< typename Triangulation >
+  bool clips_triangle( const unsigned int triangle, 
+                       const Triangulation* mesh 
+                     ) const ;
+
+  bool clips_triangle( const unsigned int* triangle, 
+                       const Scalar* vertices 
+                     ) const ;
+
+  protected :
+
+  Scalar bounds_[2*Dim] ;
+
+  /** Triangle intersection internals **/
+
+  /* during intersections, vertex types */
+  enum VertexType { 
+    ORIGINAL_V, //an original vertex of a triangle
+    EDGE_V, //intersection between a triangle edge and a box side
+    FACE_V //intersection between a triangle and two box sides
+  } ;
+
+  /* during intersections, edge types */
+  enum EdgeType {
+    ORIGINAL_E, //a piece of a triangle edge
+    BOUNDARY_E //the intersection between a boundary and the triangle
+  } ;
+
+  /* during intersection, symbolic representation of the polygon vertices */
+  template< typename Triangulation>
+  class ClipVertex {
+
+    public :
+
+    VertexType type ;
+
+    //symbolic vertex, depending on the type :
+    // - ORIGINAL_V : the index of the vertex, and 0,0
+    // - EDGE_V : the index of the edge, the offset of the intersection, 0
+    // - FACE_V : 0 as index, barycentric coordinates of the intersection
+    int symi ;
+    Scalar symd[2] ;
+
+    //symbolic edge starting t the vertex
+    EdgeType edge_type ;
+    //depending on the type of symbolic edge :
+    // - ORIGINAL_E : the index of the triangle edge
+    // - BOUNDARY_E : the index of the boundary
+    int esym ;
+
+    // determine if the vertex coordinate determined by axis is in the bounds
+    // returns +1 if over bounds, 0 if in bounds, and -1 is below bounds
+
+    int in_bounds( int axis, const Scalar bounds[2], 
+                   const unsigned int triangle, const Triangulation* mesh
+                 ) ;
+
+    void position( const unsigned int triangle,
+                   const Triangulation* mesh,
+                   Scalar* output 
+                 ) ;
+  } ;
+
+  template< typename Triangulation >
+  void fill_edge_vertex( int bound_index,
+                         int edge_index,
+                         const unsigned int triangle,
+                         const Triangulation* mesh,
+                         ClipVertex<Triangulation>& target
+                       ) const ;
+
+  template< typename Triangulation >
+  void fill_face_vertex( int bound_index1,
+                         int bound_index2,
+                         const unsigned int triangle,
+                         const Triangulation* mesh,
+                         ClipVertex<Triangulation>& target
+                       ) const ;
+
+  /* during intersection, symbolic polygon representing the clipped triangle */
+  /* template typedef would be nicer */
+  template< typename Triangulation >
+  class Polygon : public std::vector< ClipVertex<Triangulation> > {} ;
+
+  /* intersection initialization */
+  template< typename Triangulation >
+  void init_intersection( Polygon<Triangulation>& polygon ) const ;
+
+  /* clip the polygon along one axis */
+  template< typename Triangulation >
+  void clip_by_axis( int axis, Polygon<Triangulation>& polygon, 
+                     const unsigned int triangle, 
+                     const Triangulation* mesh
+                   ) const ;
+
+  //mesh wrapper
+  typedef ROMeshWrapper<3,Dim,Scalar> WrapMesh ;
+
+  static const unsigned int NO_NEIGHBOUR = WrapMesh::NO_NEIGHBOUR ;
+
+  //neighbour array for easy mesh wrapping
+  static const unsigned int no_neighbours[3] ;
+} ;
+
+template< int Dim, typename Scalar>
+const unsigned int AABox<Dim, Scalar>::no_neighbours[3] = 
+  {NO_NEIGHBOUR, NO_NEIGHBOUR, NO_NEIGHBOUR} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Neighbours/neighbourhood_def.hpp b/contrib/Revoropt/include/Revoropt/Neighbours/neighbourhood_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..99b3f8e9ee8b7b72adb46e9675f1006bcdbc3e45
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Neighbours/neighbourhood_def.hpp
@@ -0,0 +1,228 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_NEIGHBOURHOOD_DEF_HPP_
+#define _REVOROPT_NEIGHBOURHOOD_DEF_HPP_
+
+#include "neighbourhood_fwd.hpp"
+#include "aabox_def.hpp"
+
+#include <assert.h>
+#include <algorithm>
+#include <utility>
+#include <vector>
+#include <set>
+
+namespace Revoropt {
+
+template< typename Triangulation >
+bool NeighbourhoodComputer<Triangulation>::CircularLexicoCompare::operator()( 
+  unsigned int i1, unsigned int i2 
+) {
+  const Scalar* q1 = queries_ + Dim*i1 ;
+  const Scalar* q2 = queries_ + Dim*i2 ;
+  for( int i = 0; i<Dim; ++i) {
+    const int coord = (axis_+i)%Dim ;
+    if(q1[coord] != q2[coord]) return (q1[coord] < q2[coord]) ;
+  }
+  return i1 < i2 ;
+}
+
+template< typename Triangulation >
+void NeighbourhoodComputer<Triangulation>::init_sorted_queries() {
+  //create and sort indices arrays for each axis
+  for(int axis = 0; axis < Dim; ++axis) {
+    sorted_indices_[axis].resize(queries_size_) ;
+    for(unsigned int i = 0; i < queries_size_; ++i) {
+      sorted_indices_[axis][i] = i ;
+    }
+    std::sort( sorted_indices_[axis].begin(),
+               sorted_indices_[axis].end(),
+               CircularLexicoCompare(queries_,axis)
+             ) ;
+  }
+}
+
+template< typename Triangulation >
+void NeighbourhoodComputer<Triangulation>::split_sorted_queries( 
+  int axis, unsigned int begin, unsigned int end 
+) {
+  //Split the queries in range [begin,end) in two along the provided axis.
+  //All the lists along other axes are reordered according to the split.
+  //After the reordering, all the lists contain the same sets of sorted
+  //indices between [begin,mid) and [mid,end) with mid = 0.5*(begin + end)
+
+  //index of the medial query point along axis
+  const unsigned int mid_index = sorted_indices_[axis][(begin+end)/2] ;
+  //comparison corresponding to the axis
+  CircularLexicoCompare comp(queries_, axis) ;
+
+  //temporary array to filter the lists
+  std::vector<unsigned int> filtered_indices(end - begin) ;
+  //indices used to fill the filtered_indices_array
+  unsigned int low_index, high_index ;
+  //filter the sorted lists of all the axes
+  for(int i = 0; i < Dim; ++i) {
+    //the splitting axis is already split and sorted correctly
+    if(axis == i) continue ;
+    //initialize filling indices
+    low_index = 0 ;
+    high_index = (end-begin)/2 ;
+    //filter
+    for(unsigned int q = begin; q < end; ++q) {
+      const unsigned int index = sorted_indices_[i][q] ;
+      if(comp(index,mid_index)) {
+        filtered_indices[low_index] = index ;
+        ++low_index ;
+      } else {
+        filtered_indices[high_index] = index ;
+        ++high_index ;
+      }
+    }
+    //overwrite the indices
+    std::copy( filtered_indices.begin(),
+               filtered_indices.end(),
+               sorted_indices_[i].data()+begin
+             ) ;
+  }
+}
+
+template< typename Triangulation >
+void NeighbourhoodComputer<Triangulation>::compute_queries_bbox( 
+  Scalar radius, unsigned int q_begin, unsigned int q_end, Box& bbox_out
+) {
+  //initialize the bounding box
+  const unsigned int init_index = sorted_indices_[0][q_begin] ;
+  const Scalar* init_query = queries_ + Dim*init_index ;
+  bbox_out.init_to(init_query) ;
+  //iterate over the remaining queries
+  for(unsigned int i = q_begin+1; i < q_end; ++i) {
+    const unsigned int index = sorted_indices_[0][i] ;
+    const Scalar* query = queries_ + Dim*index ;
+    bbox_out.fit_to(query) ;
+  }
+  //consider the radius around the query points
+  bbox_out.grow(radius) ;
+}
+
+template< typename Triangulation >
+void NeighbourhoodComputer<Triangulation>::init_triangle_indices() {
+  //allocate space
+  t_indices_.resize(mesh_->faces_size()) ;
+  //initialize the list of indices
+  for(unsigned int i = 0; i < t_indices_.size(); ++i) {
+    t_indices_[i] = i ;
+  }
+}
+
+template< typename Triangulation >
+unsigned int NeighbourhoodComputer<Triangulation>::filter_triangle_indices( 
+  const Box& box, unsigned int t_end 
+) {
+  //sanity check
+  assert((t_end>0) && "the number ot triangles is zero or negative") ;
+  //positions
+  unsigned int t_in = 0 ;
+  unsigned int t_out = t_end-1 ;
+  //iterate over the triantles
+  while(t_in <= t_out) {
+    if(box.clips_triangle_bbox(t_indices_[t_in], mesh_)) {
+      ++t_in ;
+    } else {
+      //std::cout << t_in << " " << t_out << " " << std::endl ;
+      if(t_in != t_out) {
+        std::swap(t_indices_[t_in],t_indices_[t_out]) ;
+      } else {
+        //std::cout << "skip swap" << std::endl ;
+      }
+      if(t_out == 0) break ;
+      --t_out ;
+    }
+  }
+  //return the end of the triangles clipping the box
+  return t_in ;
+}
+
+template< typename Triangulation >
+template < typename Action >
+void NeighbourhoodComputer<Triangulation>::compute_internal( 
+  Scalar radius, 
+  Action& action,
+  unsigned int q_begin,
+  unsigned int q_end,
+  unsigned int t_end
+) {
+  assert((q_end>q_begin) && "the query interval is empty or reversed") ;
+  //test the number of remaining queries
+  if((q_end-q_begin) == 1) { //one single query
+    /*
+    //compute the box around the query
+    Box box ;
+    compute_queries_bbox(radius,q_begin,q_end,box) ;
+    //initialize a polygon to clip the triangles
+    std::vector<Scalar> polygon ;
+    //clip each triangle
+    for(unsigned int t = 0; t < t_end; ++t) {
+      //get the triangle from its index
+      const unsigned int* triangle = mesh_->face(t_indices_[t]) ;
+      //clip it really (not just the bounding box)
+      bool clips = 
+        box.triangle_intersection(triangle,mesh_->vertices(),polygon) ;
+      if(clips) {
+        //perform the action on the clipping
+        action(sorted_indices_[0][q_begin],polygon) ;
+      }
+    }
+    */
+    //perform the action on all the triangles remaining for the unique query
+    for(unsigned int t = 0; t < t_end; ++t) {
+      action(sorted_indices_[0][q_begin], t_indices_[t]) ;
+    }
+  } else { //several queries
+    //compute the bounding box of the queries
+    Box full_box ;
+    compute_queries_bbox(radius,q_begin,q_end,full_box) ;
+    //find the longest axis
+    unsigned int major_axis = 0 ;
+    Scalar major_size = 
+      full_box.max_axis_bound(0) = full_box.min_axis_bound(0) ;
+    for(int axis = 1; axis < Dim; ++axis) {
+      const Scalar len =
+        full_box.max_axis_bound(axis) = full_box.min_axis_bound(axis) ;
+      if(len > major_size) {
+        major_size = len ;
+        major_axis = axis ;
+      }
+    }
+    //split the queries along the longest axis
+    const unsigned int q_mid = (q_begin + q_end)/2 ;
+    split_sorted_queries(major_axis,q_begin,q_end) ;
+    //bounding boxes of the two parts
+    Box b1, b2 ;
+    compute_queries_bbox(radius,q_begin,q_mid,b1) ;
+    compute_queries_bbox(radius,q_mid,q_end,b2) ;
+    //compute the triangle sets of the first box
+    unsigned int t_limit = filter_triangle_indices(b1,t_end) ;
+    //handle the first box
+    if(t_limit != 0) {
+      compute_internal(radius,action,q_begin,q_mid,t_limit) ;
+    }
+    //compute the triangle sets of the second box
+    t_limit = filter_triangle_indices(b2,t_end) ;
+    //handle the second box
+    if(t_limit != 0) {
+      compute_internal(radius,action,q_mid,q_end,t_limit) ;
+    }
+  }
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Neighbours/neighbourhood_fwd.hpp b/contrib/Revoropt/include/Revoropt/Neighbours/neighbourhood_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d6169acc6527deb42e3a3411a425602113c4c9b3
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Neighbours/neighbourhood_fwd.hpp
@@ -0,0 +1,130 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_NEIGHBOURHOOD_FWD_HPP_
+#define _REVOROPT_NEIGHBOURHOOD_FWD_HPP_
+
+#include <Revoropt/Neighbours/aabox_fwd.hpp>
+
+namespace Revoropt {
+
+/** An action performed on a neighbourhood **/
+
+class NeighbourhoodAction {
+
+  public :
+
+  virtual void operator()( unsigned int query, 
+                           unsigned int triangle 
+                         ) = 0 ;
+
+} ;
+
+/** A neighbourhood computer **/
+
+template< typename Triangulation >
+class NeighbourhoodComputer {
+
+  public :
+
+  /* Typedefs and enums */
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef typename Triangulation::Scalar Scalar ;
+  typedef AABox<Dim,Scalar> Box ;
+
+  NeighbourhoodComputer( const Triangulation* mesh,
+                         const Scalar* queries,
+                         unsigned int queries_size
+                       ) : mesh_(mesh), 
+                           queries_(queries), 
+                           queries_size_(queries_size) {
+  }
+
+  /* Computing the neighbourhoods, applying the action on them */
+  template< typename Action >
+  void compute( Scalar radius, Action& action ) {
+    //initialize query indices arrays sorted along each axis
+    init_sorted_queries() ;
+    init_triangle_indices() ;
+    compute_internal(radius,action) ;
+  }
+
+  private :
+
+  /* Mesh */
+  const Triangulation* mesh_ ;
+
+  /* Queries */
+  const Scalar* queries_ ;
+  unsigned int queries_size_ ;
+
+  /* Query indices sorted along all the axis */
+  std::vector<unsigned int> sorted_indices_[Dim] ;
+
+  class CircularLexicoCompare {
+    //lexicographic comparison of queries from their indices
+    public :
+    //construction
+    CircularLexicoCompare( const Scalar* queries, int axis ) 
+      : queries_(queries), axis_(axis) {
+    }
+    //comparison
+    bool operator()( unsigned int i1, unsigned int i2 ) ;
+    private :
+    //query points
+    const Scalar* queries_ ;
+    //first axis for the lexical order
+    unsigned int axis_ ;
+
+  } ;
+
+  void init_sorted_queries() ;
+
+  //Split the queries in range [begin,end) in two along the provided axis.
+  //All the lists along other axes are reordered according to the split.
+  //After the reordering, all the lists contain the same sets of sorted
+  //indices between [begin,mid) and [mid,end) with mid = 0.5*(begin + end)
+  void split_sorted_queries( int axis, unsigned int begin, unsigned int end ) ;
+
+  /* Compute the bounding box of a set of query points */
+  void compute_queries_bbox( Scalar radius, 
+                             unsigned int q_begin, 
+                             unsigned int q_end,
+                             Box& bbox_out
+                           ) ;
+
+  /* Initialize the set of triangle indices */
+  void init_triangle_indices() ;
+
+  /* Filter a set of triangles to keep only the ones intersecting a box */
+  unsigned int filter_triangle_indices( const Box& box, 
+                                        unsigned int t_end 
+                                      ) ;
+
+  /* Recursively compute the robust normals */
+  template< typename Action >
+  void compute_internal( Scalar radius, Action& action) {
+    compute_internal(radius,action,0,queries_size_,mesh_->faces_size()) ;
+  }
+
+  template< typename Action >
+  void compute_internal( Scalar radius, Action& action,
+                         unsigned int q_begin,
+                         unsigned int q_end,
+                         unsigned int t_end
+                       ) ;
+
+  std::vector<unsigned int> t_indices_ ;
+
+} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/RVD/.gitignore b/contrib/Revoropt/include/Revoropt/RVD/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b11d6f45c393633b5ffcaff41f3a68e64b9922a7
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/RVD/.gitignore
@@ -0,0 +1 @@
+utils.os
diff --git a/contrib/Revoropt/include/Revoropt/RVD/action.hpp b/contrib/Revoropt/include/Revoropt/RVD/action.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..12925b37f3de7188fc436940d053eb8d5839c614
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/RVD/action.hpp
@@ -0,0 +1,132 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_RVD_ACTION_HPP_
+#define _REVOROPT_RVD_ACTION_HPP_
+
+#include "polygon.hpp"
+
+namespace Revoropt {
+
+/* An action is triggered during the computation of the RVD, each time a
+ * triangle was clipped by a Voronoi cell, on the resulting polygon. This
+ * prototype is not necessarily to be used, since the action is passed via a
+ * template parameter, but an action has to define the operator() in the same
+ * way. */
+
+template<typename _Triangulation>
+class Action {
+
+  public :
+
+  /* Types and template data */
+  typedef _Triangulation Triangulation ;
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef Eigen::Matrix<double,Dim,1> Vector ;
+
+  /* Each polygon is decomposed into triangles, and the triangle_action is
+   * applied on each of these triangles. */
+  virtual void operator()( unsigned int site, unsigned int triangle,
+                           const RVDPolygon<Triangulation>& polygon
+                         ) = 0 ;
+} ;
+
+/* The action manager takes several actions, and groups them as a single
+ * action, which runs them sequencially. */
+
+template<typename _Triangulation>
+class ActionManager {
+
+  public :
+
+  /* Types and template data */
+  typedef _Triangulation Triangulation ;
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef Eigen::Matrix<double,Dim,1> Vector ;
+
+  /* Call all the actions in sequence */
+  void operator()( unsigned int site, unsigned int triangle,
+                   const RVDPolygon<Triangulation>& polygon
+                 ) {
+    /* Call all the actions in sequence */
+    for(unsigned int i=0; i<actions_.size(); ++i) {
+      (*actions_[i])(site, triangle, polygon) ;
+    }
+  }
+
+  /* Add new actions to be run */
+  void add_action( Action<Triangulation>* action ) {
+    actions_.push_back(action) ;
+  }
+
+  void clear_actions() {
+    actions_.resize(0) ;
+  }
+
+  private :
+
+  /* Storage for the actions */
+  std::vector<Action<Triangulation>*> actions_ ;
+  
+} ;
+
+/* Action finalization : when the RVD is fully computed, the finalize() method
+ * of the action is called if it exists. The following tests whether a class has
+ * a finalize method, and provides a wrapper to call it or not depending on its
+ * existence. */
+
+/* test whether a class has a finalize() method */
+
+template< typename Wrapped >
+class test_finalize {
+
+  private :
+
+    //used to check which of the test methods below is used
+    //in the definition of the value public attribute
+    typedef char yes[1] ;
+    typedef char  no[2] ;
+
+    template<typename C, int dummy = sizeof(&C::finalize)> struct check ;
+
+    //this method can only be instanciated if Tested has void finalize()
+    template <typename C> static yes &test( check<C>* ) ;
+    //this method is always instanciated
+    template <typename C> static no  &test(    ...    ) ;
+
+  public:
+
+    //if the size of the return type of the test function used here is yes
+    //the first test function was instanciated, and therefore *T is legal
+    static bool const value = sizeof(test<Wrapped>(0)) == sizeof(yes) ;
+} ;
+
+template<typename Wrapped, bool b>
+class wrap_finalize_impl {
+  public :
+    static void wrap(Wrapped& wrapped) {}
+} ;
+
+template<typename Wrapped>
+class wrap_finalize_impl<Wrapped, true> {
+  public :
+    static void wrap(Wrapped& wrapped) {
+      wrapped.finalize() ;
+    }
+} ;
+
+template<typename Wrapped>
+void wrap_finalize(Wrapped& wrapped) {
+  return wrap_finalize_impl<Wrapped, test_finalize<Wrapped>::value>::wrap(wrapped) ;
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/RVD/ann_backend.hpp b/contrib/Revoropt/include/Revoropt/RVD/ann_backend.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..0c5641d45266c4eb49cc37c0a66ad07f5d64207c
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/RVD/ann_backend.hpp
@@ -0,0 +1,84 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_RVD_ANN_BACKEND_HPP_
+#define _REVOROPT_RVD_ANN_BACKEND_HPP_
+
+#include <ANN/ANN.h>
+#include <vector>
+#include <iostream>
+
+namespace Revoropt {
+
+/** Nearest neighbour backend for ann **/
+
+template<int _Dim>
+class ANNBackend {
+
+  public :
+
+  /* Types and template data */
+  enum { Dim = _Dim } ;
+
+  /* Initialization, destruction */
+  ANNBackend() : ann_sites_(NULL), ann_tree_(NULL) {
+  }
+
+  ANNBackend( const double* sites, 
+              unsigned int sites_size
+            ) : ann_sites_(NULL), ann_tree_(NULL) {
+    set_sites(sites, sites_size) ;
+  }
+            
+  ~ANNBackend() {
+    delete [] ann_sites_ ;
+    delete ann_tree_ ;
+    //annClose() ; // FIXME : memory leak if not used after all ann trees are
+    //deleted, perhaps use a static counter of instances and close when instances
+    //of clippers fall to 0. Would however break any other ANN tree built in a
+    //program using this code, which is highly undesireable. Memory leak may
+    //therefore be the only solution.
+  }
+
+  /* Nearest site */
+  void knnSearch( const double* query, unsigned int size,
+                  unsigned int* nnsites, double* nndistances
+                ) {
+    ann_tree_->annkSearch( const_cast<double*>(query), 
+                           size,
+                           (int*) nnsites, 
+                           nndistances
+                         ) ;
+  }
+
+  /* Overloading site setting in clipper to update nearest neighbours */
+  void set_sites( const double* sites, unsigned int sites_size ) {
+    //build ann tree
+    delete [] ann_sites_ ;
+    delete ann_tree_ ;
+
+    ann_sites_ = new double*[sites_size] ;
+    for(unsigned int i=0 ; i < sites_size ; ++i) {
+      ann_sites_[i] = const_cast<double*>(sites + Dim*i) ;
+    }
+
+    ann_tree_ = new ANNkd_tree(ann_sites_, sites_size, Dim) ;
+  }
+
+  private :
+
+  /* ANN data */
+  double** ann_sites_ ;
+  ANNkd_tree* ann_tree_ ;
+} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/RVD/clipper.hpp b/contrib/Revoropt/include/Revoropt/RVD/clipper.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ceca842f0bf74d617288c05f8a6ad98ec5c45214
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/RVD/clipper.hpp
@@ -0,0 +1,87 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_RVD_CLIPPER_HPP_
+#define _REVOROPT_RVD_CLIPPER_HPP_
+
+#include "polygon.hpp"
+
+namespace Revoropt {
+
+/** Interface for clipping polygons by Voronoï cells **/
+
+template<typename _Triangulation>
+class Clipper {
+
+  public :
+
+  /* Types and template data */
+  typedef _Triangulation Triangulation ;
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef typename Triangulation::Scalar Scalar ;
+  typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+
+  /* Initialization */
+  Clipper() : sites_(NULL), sites_size_(0), mesh_(NULL) {} ;
+
+  Clipper( const Scalar* sites, unsigned int sites_size,
+           const Triangulation* mesh 
+         ) : sites_(sites), sites_size_(sites_size), mesh_(mesh) {
+  }
+
+  virtual ~Clipper() {}
+
+  /* Given the polygon, the site, the site and vertex positions, update the
+   * polygon by clipping it by the Voronoï cell of the site. Beware that calling
+   * this function several times on the same triangle / site couple without
+   * running the reset method may lead to bad behaviour.*/
+
+  virtual void clip_by_cell( RVDPolygon<Triangulation>& polygon, 
+                             unsigned int triangle,
+                             unsigned int site
+                           ) = 0 ;
+
+  /* Given a query point, provide the nearest site */
+  virtual unsigned int nearest_site( const Scalar* query ) = 0 ;
+
+  /* Updating the sites and mesh */
+  virtual void set_sites( const Scalar* sites, 
+                             unsigned int sites_size 
+                        ) {
+    sites_ = sites ;
+    sites_size_ = sites_size ;
+  }
+
+  virtual void set_mesh( const Triangulation* mesh ) {
+    mesh_ = mesh ;
+  }
+
+  /* Providing sites and mesh */
+  const Scalar* sites() { return sites_ ; }
+  unsigned int sites_size() { return sites_size_ ; }
+  const Triangulation* mesh() {return mesh_ ; }
+
+  /* resetting internal data of the clipper */
+  virtual void reset() {} ;
+
+  protected :
+
+  /* Sites */
+  const Scalar* sites_ ;
+  unsigned int sites_size_ ;
+
+  /* Mesh */
+  const Triangulation* mesh_ ;
+
+} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/RVD/flann_backend.hpp b/contrib/Revoropt/include/Revoropt/RVD/flann_backend.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..de31c70caa01308db3f3ae1ad84bf1265ce16da2
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/RVD/flann_backend.hpp
@@ -0,0 +1,83 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_RVD_FLANN_BACKND_HPP_
+#define _REVOROPT_RVD_FLANN_BACKND_HPP_
+
+#include <flann/flann.hpp>
+#include <vector>
+#include <iostream>
+
+namespace Revoropt {
+
+/** Nearest neighbour backend for flann **/
+
+template<int _Dim>
+class FLANNBackend {
+
+  public :
+
+  /* Types and template data */
+  enum { Dim = _Dim } ;
+
+  /* Initialization, destruction */
+  FLANNBackend() : index_(flann::KDTreeSingleIndexParams(10)),
+                   flann_params_(flann::FLANN_CHECKS_UNLIMITED,0,true) {
+  }
+
+  FLANNBackend( const double* sites, 
+                unsigned int sites_size
+              ) : index_(flann::KDTreeSingleIndexParams(10)),
+                  flann_params_(flann::FLANN_CHECKS_UNLIMITED,0,true) {
+    set_sites(sites, sites_size) ;
+  }
+
+  /* Nearest neighbours */
+  void knnSearch( const double* query, unsigned int size, 
+                  unsigned int* nnsites, double* nndistances 
+                ) {
+    //convert input to flann matrices
+    flann::Matrix<double> flann_query(const_cast<double*>(query), 1, Dim) ;
+    flann::Matrix<int> flann_nnsites((int*) nnsites, 1, size) ;
+    flann::Matrix<double> flann_nndistances(nndistances, 1, size) ;
+
+    //query
+    index_.knnSearch( flann_query, 
+                      flann_nnsites, 
+                      flann_nndistances,
+                      size,
+                      flann_params_
+                    ) ;
+  }
+
+  /* Overloading site setting in clipper to update nearest neighbours */
+  void set_sites( const double* sites, unsigned int sites_size ) {
+    //build flann index
+    flann_points_ = flann::Matrix<double>( 
+      const_cast<double*>(sites), sites_size, Dim
+    ) ;
+    index_.buildIndex(flann_points_) ;
+  }
+
+  private :
+
+  /* FLANN data */
+  flann::Matrix<double> flann_points_ ;
+  flann::Index< flann::L2<double> > index_ ;
+
+  /* Parameters */
+  flann::SearchParams flann_params_ ;
+} ;
+
+//}}}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/RVD/nn_clipper.hpp b/contrib/Revoropt/include/Revoropt/RVD/nn_clipper.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..989a79a19d26a264aed5fb97aae106bc78e88d13
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/RVD/nn_clipper.hpp
@@ -0,0 +1,632 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_RVD_NN_CLIPPER_HPP_
+#define _REVOROPT_RVD_NN_CLIPPER_HPP_
+
+#include "clipper.hpp"
+
+#include <vector>
+#include <iostream>
+
+namespace Revoropt {
+
+/** Base class for clippers using nearest neighbour queries **/
+
+template<typename _Triangulation, typename _NNBackend>
+class NNClipper : public Clipper<_Triangulation> {
+
+  public :
+
+  /* Types and template data */
+  typedef _Triangulation Triangulation ;
+  typedef Clipper<Triangulation> Base ;
+  typedef _NNBackend NNBackend ;
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef typename Triangulation::Scalar Scalar ;
+  typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+
+  typedef RVDEdge<Triangulation> Edge ;
+
+  enum Algo { SITE_NEIGHBOURS, 
+              TRIANGLE_NEIGHBOURS, 
+              MIXED_TRIANGLE_NEIGHBOURS,
+              CORNER_CLIPPING,
+              CENTER_THEN_CORNER_CLIPPING
+            } ;
+
+  /* Initialization, destruction */
+  NNClipper() : Base(), 
+                neighbourhood_size_(10),
+                algorithm_(CORNER_CLIPPING) {
+  }
+
+  NNClipper( const Scalar* sites, unsigned int sites_size,
+             const Triangulation* mesh
+           ) : Base(sites, sites_size, mesh),
+               neighbourhood_size_(10),
+               algorithm_(CORNER_CLIPPING) {
+    set_sites(sites, sites_size) ;
+  }
+
+  virtual ~NNClipper() {}
+            
+  /* Choose algorithm */
+  void set_algorithm( int algorithm ) {
+    int algo = algorithm > 4 ? 4 : algorithm ;
+    algorithm_ = (Algo) algo ;
+  }
+
+  /* Clipping */
+  void clip_by_cell( RVDPolygon<Triangulation>& polygon, 
+                     unsigned int triangle, 
+                     unsigned int site 
+                   ) {
+    //reset max distance between the site and its neighbours so far
+    max_neighbour_distance_ = 0 ;
+
+    //get site position as a vector
+    Eigen::Map<const Vector> site_pos(Base::sites_+Dim*site) ;
+
+    //set current site as handled
+    site_last_opposite_[site] = Couple(triangle, site) ;
+
+    //compute distances between the site and the polygon vertices
+    site_distances_.resize(0) ;
+
+    //resize new_vertices array
+    new_vertices_.assign(polygon.size(), true) ;
+
+    for(unsigned int i=0; i<polygon.size(); ++i) {
+      const Vector d = site_pos - polygon[i].vertex ;
+      site_distances_.push_back(d.dot(d)) ;
+    }
+
+    unsigned int clippings = 0 ;
+    if(algorithm_ == SITE_NEIGHBOURS) {
+      clippings += full_neighbour_clip(polygon, triangle, site, neighbourhood_size_) ;
+      return ;
+    }
+    if(algorithm_ == TRIANGLE_NEIGHBOURS) {
+      clippings += full_radius_clip(polygon, triangle, site, neighbourhood_size_) ;
+      return ;
+    }
+    clippings += neighbour_clip(polygon, triangle, site, neighbourhood_size_) ;
+    if(algorithm_ == MIXED_TRIANGLE_NEIGHBOURS) {
+      clippings += full_radius_clip(polygon, triangle, site, neighbourhood_size_) ;
+      return ;
+    }
+    if(algorithm_ == CORNER_CLIPPING) {
+      clippings += corner_clip(polygon, triangle, site) ;
+      return ;
+    }
+    if(algorithm_ == CENTER_THEN_CORNER_CLIPPING) {
+      clippings += center_then_corner_clip(polygon, triangle, site) ;
+      return ;
+    }
+  }
+
+  /* Nearest site */
+  unsigned int nearest_site( const Scalar* query ) {
+    //storage for the result
+    unsigned int site ;
+    Scalar distance ;
+    //search
+    nnbackend_.knnSearch(query, 1, &site, &distance) ;
+
+    return site ;
+  }
+
+  /* Overloading site setting in clipper to update nearest neighbours */
+  void set_sites( const Scalar* sites, unsigned int sites_size ) {
+    //call parent update
+    Base::set_sites( sites, sites_size ) ;
+
+    //reset the site_last_opposite array
+    reset() ;
+
+    //initialize the nearest neighbour backend
+    nnbackend_.set_sites(sites, sites_size) ;
+  }
+
+  /* set/get parameters */
+  unsigned int neighbourhood_size() {
+    return neighbourhood_size_ ;
+  }
+  void set_neighbourhood_size( unsigned int size ) {
+    neighbourhood_size_ = size ;
+  }
+
+  /* reset */
+  void reset() {
+    site_last_opposite_.assign(
+      Base::sites_size_, 
+      Couple(Triangulation::NO_NEIGHBOUR,0)
+    ) ;
+  }
+
+  private :
+
+  /* Parameters */
+  unsigned int neighbourhood_size_ ;
+
+  /* Prevent multiple clippings by the same opposite site for a given site and
+   * triangle. This array is reset with the reset method. */
+  typedef std::pair<unsigned int, unsigned int> Couple ;
+  std::vector<Couple> site_last_opposite_ ;
+
+  /* Data for nearest neighbour searches */
+  double max_neighbour_distance_ ;
+  std::vector<unsigned int> nn_indices_ ;
+  std::vector<Scalar> nn_distances_ ;
+
+  /* Data for the ongoing clipping */
+  //during clipping, the vertices of the clipped polygon are marked true in this
+  //array and the new vertices of the clipped polygon are marked false.
+  std::vector<bool> new_vertices_ ;
+  std::vector<bool> next_new_vertices_ ;
+
+  //distances between the site and the polygon vertices
+  std::vector<double> site_distances_ ;
+  std::vector<double> site_next_distances_ ;
+
+  //distance between another site and the polygon vertices
+  std::vector<double> opposite_distances_ ;
+
+  /* Clipping by the sites nearest neighbours */
+  unsigned int neighbour_clip( RVDPolygon<Triangulation>& polygon,
+                               unsigned int triangle,
+                               unsigned int site,
+                               unsigned int nneighbours
+                             ) {
+    //query point
+    const Scalar* query = Base::sites_ + Dim*site ;
+
+    //count clippings
+    unsigned int clippings = 0 ;
+
+    //site radius : maximal squared distance to the polygon vertices
+    double site_radius = *std::max_element( site_distances_.begin(), 
+                                            site_distances_.end()
+                                          ) ;
+
+    //number of neighbours neighbours
+    unsigned int neighbour_size = std::min(Base::sites_size_, nneighbours) ;
+    nn_indices_.resize(neighbour_size) ;
+    nn_distances_.resize(neighbour_size) ;
+
+    nnbackend_.knnSearch( query, 
+                         neighbour_size,
+                         nn_indices_.data(), 
+                         nn_distances_.data()
+                       ) ;
+
+    max_neighbour_distance_ = nn_distances_[neighbour_size-1] ;
+
+    //iterate clip by nearest neighbours
+    for(unsigned int i=0 ; i<neighbour_size ; ++i) {
+      ++clippings ;
+      unsigned int opposite_site = nn_indices_[i] ;
+
+      if(opposite_site == site) {
+        continue ;
+      }
+      //check if security readius is reached
+      if(nn_distances_[i] > 4*site_radius) {
+        return clippings-1 ;
+      }
+      //check whether this site was handled before
+      if(site_last_opposite_[opposite_site] != Couple(triangle,site)) {
+        //mark current opposite site as done for this clipping
+        site_last_opposite_[opposite_site] = Couple(triangle,site) ;
+        //perform the clipping
+        clip_by_plane(polygon, triangle, site, opposite_site) ;
+        if(polygon.size() > 0) {
+           site_radius = *std::max_element( site_distances_.begin(), 
+                                            site_distances_.end()
+                                          ) ;
+        } else {
+          site_radius = 0 ;
+        }
+      }
+    }
+    return clippings ;
+  }
+
+  /* iterate neighbour clipping until termination */
+  unsigned int full_neighbour_clip( RVDPolygon<Triangulation>& polygon,
+                                    unsigned int triangle,
+                                    unsigned int site,
+                                    unsigned int nneighbours
+                                  ) {
+    unsigned int current_nneighbours = nneighbours ;
+    unsigned int clippings = 0 ;
+    do{
+      //clip using the current neighbourhood size
+      clippings = neighbour_clip(polygon, triangle, site, current_nneighbours) ;
+      //check for security radius termination of the clipping
+      if(clippings < current_nneighbours) {
+        //in case of early termination, the clipping is correct
+        return clippings ;
+      }
+      //no early termination, increase the size of the neighbourhood
+      current_nneighbours += nneighbours ;
+    } while(clippings < Base::sites_size_ ) ;
+    //return the number of clippings required, all the sites at this point
+    return clippings ;
+  }
+
+  /* Clipping using the nearest neighours of the polygon */
+  unsigned int corner_clip( RVDPolygon<Triangulation>& polygon,
+                            unsigned int triangle,
+                            unsigned int site
+                          ) {
+    //mark all the vertices as new vertices
+    new_vertices_.assign(polygon.size(),true) ;
+
+    //total number of clippings
+    unsigned int clippings = 0 ;
+
+    //marked true if the polygon was clipped during current iteration
+    bool clipped = false ;
+
+    do {
+      clipped = false ;
+
+      //get the nearest neighbours of all the new polygon corners
+      for(unsigned int i = 0; i<polygon.size(); ++i) {
+        if(new_vertices_[i]) {
+          if(site_distances_[i] >= 0.25*max_neighbour_distance_) {
+            //get the nearest neighbour of the corner
+            int opposite_site = nearest_site(polygon[i].vertex.data()) ;
+            //Debug
+            //Vector save = polygon[i].vertex ;
+            if(site_last_opposite_[opposite_site] != Couple(triangle,site)) {
+              //mark current opposite site as done for this clipping
+              site_last_opposite_[opposite_site] = Couple(triangle,site) ;
+              //perform the clipping
+              clipped = clip_by_plane(polygon, triangle, site, opposite_site) ;
+              if(!clipped) {
+              //  for(int k = 0; k < site_next_distances_.size(); ++k) {
+              //    std::cout << opposite_distances_[k] - site_next_distances_[k] << " " << std::flush ;
+              //  }
+              //  std::cout << std::endl ;
+              //  std::cout << site << " " << opposite_site << " " << i << "/" << next_polygon_.size() << std::endl ;
+              //  Eigen::Map<const Vector> spos(Base::sites_+Dim*site) ;
+              //  Eigen::Map<const Vector> opos(Base::sites_+Dim*opposite_site) ;
+              //  std::cout << (spos-save).norm() << " " <<  (opos-save).norm() << std::endl ;
+              //  std::cout << nearest_site(next_polygon_[i].vertex.data()) << std::endl ;
+              //  std::cout << nearest_site(save.data()) << std::endl ;
+              //  std::cout << opposite_site << std::endl ;
+              //  std::cout << opos << std::endl ;
+              //  std::cout << "===" << std::endl ;
+              //  std::cout << spos << std::endl ;
+              //  std::cout << "===" << std::endl ;
+              //  std::cout << save << std::endl ;
+              //  std::cout << "===" << std::endl ;
+              //  std::cout << "Warning, nearest neighbour of corner did not clip." << std::endl ;
+              }
+              ++clippings ;
+              break ;
+            } else {
+              new_vertices_[i] = false ;
+            }
+          } else {
+            new_vertices_[i] = false ;
+          }
+        }
+      }
+    } while( clipped ) ;
+    return clippings ;
+  }
+
+  double compute_center_radius( RVDPolygon<Triangulation>& polygon, 
+                                Vector& center,
+                                double site_radius
+                              ) {
+    double center_radius = 0 ;
+    for(unsigned int i=0; i<polygon.size(); ++i) {
+      Vector d = (polygon[i].vertex - center) ;
+      center_radius = std::max(center_radius, d.dot(d)) ;
+    }
+    center_radius = sqrt(center_radius) ;
+    center_radius += sqrt(site_radius) ;
+    center_radius *= center_radius ;
+    
+    return center_radius*center_radius ;
+  }
+
+  double compute_finer_center_radius( RVDPolygon<Triangulation>& polygon, 
+                                      Vector& center,
+                                      std::vector<double>& site_distances
+                                    ) {
+    double center_radius = 0 ;
+    for(unsigned int i=0; i<polygon.size(); ++i) {
+      Vector d = (polygon[i].vertex - center) ;
+      center_radius = 
+          std::max(center_radius, sqrt(d.dot(d)) + sqrt(site_distances[i])) ;
+    }
+    
+    return center_radius*center_radius ;
+  }
+
+  /* Clipping using sites centered on the barycenter*/
+  unsigned int radius_clip( RVDPolygon<Triangulation>& polygon,
+                            unsigned int triangle,
+                            unsigned int site,
+                            unsigned int nneighbours
+                          ) {
+    if(polygon.size() < 3) return 0 ;
+    //compute the centroid of the polygon
+    Vector center = Vector::Zero() ;
+    for(unsigned int i=0; i<polygon.size(); ++i) {
+      center += polygon[i].vertex ;
+    }
+    center /= polygon.size() ;
+
+
+    //compute the radius of the search
+    double center_radius = 
+      compute_finer_center_radius(polygon, center, site_distances_) ;
+
+    //get nearest neighbours
+    unsigned int neighbour_size = std::min(Base::sites_size_, nneighbours) ;
+    nn_indices_.resize(neighbour_size) ;
+    nn_distances_.resize(neighbour_size) ;
+
+    nnbackend_.knnSearch( center.data(), 
+                         neighbour_size,
+                         nn_indices_.data(), 
+                         nn_distances_.data()
+                       ) ;
+
+    unsigned int clippings = 0 ;
+
+    for( unsigned int i = 0; i < neighbour_size; ++i ) {
+      //increase the number of sites handled
+      ++clippings ;
+
+      //get neighbour index
+      const unsigned int opposite_site = nn_indices_[i] ;
+
+      //check that the neighbour was not previously handled
+      if(site_last_opposite_[opposite_site] != Couple(triangle,site)) {
+
+        site_last_opposite_[opposite_site] = Couple(triangle,site) ;
+
+        //check that the neighbour is within the (updated) center radius
+        if(nn_distances_[i] > center_radius) {
+          return clippings-1 ;
+        }
+
+        //clip curr_polygon_ by the bisector between site and opposite_site
+        clip_by_plane(polygon, triangle, site, opposite_site) ;
+        
+        //update the center radius
+        if(polygon.size() > 0) {
+           center_radius = 
+             compute_finer_center_radius(polygon, center, site_distances_) ;
+        } else {
+          center_radius = 0 ;
+        }
+      }
+    }
+
+    return clippings ;
+  }
+
+  /* iterate radius clipping until termination */
+  unsigned int full_radius_clip( RVDPolygon<Triangulation>& polygon,
+                                    unsigned int triangle,
+                                    unsigned int site,
+                                    unsigned int nneighbours
+                                  ) {
+    unsigned int current_nneighbours = nneighbours ;
+    unsigned int clippings = 0 ;
+    do{
+      //clip using the current neighbourhood size
+      clippings = radius_clip(polygon, triangle, site, current_nneighbours) ;
+      //check for security radius termination of the clipping
+      if(clippings < current_nneighbours) {
+        //in case of early termination, the clipping is correct
+        return clippings ;
+      }
+      //no early termination, increase the size of the neighbourhood
+      current_nneighbours += nneighbours ;
+    } while(clippings < Base::sites_size_) ;
+    //return the number of clippings required, all the sites at this point
+    return clippings ;
+  }
+
+  /* Clipping using the nearest site from the barycenter */
+  unsigned int center_clip( RVDPolygon<Triangulation>& polygon,
+                            unsigned int triangle,
+                            unsigned int site
+                          ) {
+    if(polygon.size() < 3) return 0 ;
+    //compute the centroid of the polygon
+    Vector center = Vector::Zero() ;
+    for(unsigned int i=0; i<polygon.size(); ++i) {
+      center += polygon[i].vertex ;
+    }
+    center /= polygon.size() ;
+
+    nn_indices_.resize(2) ;
+    nn_distances_.resize(2) ;
+
+    nnbackend_.knnSearch( center.data(), 
+                         2,
+                         nn_indices_.data(), 
+                         nn_distances_.data()
+                       ) ;
+
+    unsigned int opposite_site = nn_indices_[0] == site ? 
+      nn_indices_[1] : nn_indices_[0] ;
+
+    //check that the neighbour was not previously handled
+    if(site_last_opposite_[opposite_site] == Couple(triangle,site)) {
+      //no new site handled
+      return 0 ;
+    }
+
+    site_last_opposite_[opposite_site] = Couple(triangle,site) ;
+
+    //clip curr_polygon_ by the bisector between site and opposite_site
+    clip_by_plane(polygon, triangle, site, opposite_site) ;
+
+    //one new site was handled
+    return 1 ;
+  }
+
+  /* iterate center clipping until no new site is handled, then corner clip */
+  unsigned int center_then_corner_clip( RVDPolygon<Triangulation>& polygon,
+                                        unsigned int triangle,
+                                        unsigned int site
+                                      ) {
+    unsigned int clippings = 0 ;
+    unsigned int last_clippings = 0 ;
+    do{
+      //clip using the polygon barycenter nearest neighbour
+      last_clippings = center_clip(polygon, triangle, site) ;
+      //add up potential new clip
+      clippings += last_clippings ;
+    } while(last_clippings == 1) ;
+    //return the number of clippings required, all the sites at this point
+    return clippings + corner_clip(polygon, triangle, site) ;
+  }
+
+  /* Clipping by a bisector */
+  bool clip_by_plane( RVDPolygon<Triangulation>& polygon,
+                      unsigned int triangle,
+                      unsigned int site,
+                      unsigned int opposite_site
+                    ) {
+    //polygon size
+    unsigned int size = polygon.size() ;
+
+    //get the site positions for distance computations
+    Eigen::Map<const Vector> site_pos(Base::sites_ +Dim*site) ;
+    Eigen::Map<const Vector> opp_site_pos(Base::sites_ +Dim*opposite_site) ;
+
+    //compute distances between opposite site and polygon vertices
+    opposite_distances_.resize(0) ;
+    for(unsigned int i=0; i<size; ++i) {
+      const Vector d = opp_site_pos - polygon[i].vertex ;
+      opposite_distances_.push_back(d.dot(d)) ;
+    }
+
+    //reset next information
+    next_new_vertices_.resize(0) ;
+    next_polygon_.resize(0) ;
+    site_next_distances_.resize(0) ;
+
+    //return value, changed to true is some clipping occurs
+    bool clipped = false ;
+
+    //iterate over the vertices of the polygon
+    for(unsigned int i = 0; i<size; ++i) {
+      //get the sides of the current vertex and the next one
+      const double my_side = opposite_distances_[i] - site_distances_[i] ;
+      const double next_side = opposite_distances_[(i+1)%size] 
+                             - site_distances_[(i+1)%size] ;
+      //check whether the vertex is in or out
+      if(my_side > 0) {
+        //vertex is in, keep it and its distance
+        next_new_vertices_.push_back(new_vertices_[i]) ;
+        next_polygon_.push_back(polygon[i]) ;
+        site_next_distances_.push_back(site_distances_[i]) ;
+      }
+
+      if(my_side <= 0) {
+          //the vertex is out, the opposite site owns a piece of this polygon
+          clipped = true ;
+      }
+
+      //check whether the next vertex is on the same side
+      if( my_side*next_side < 0 || 
+          (my_side == 0 && next_side > 0) ||
+          (my_side > 0 && next_side == 0)
+        ) {
+        
+        //different sides, an intersection point must be added
+        const unsigned int* triangle_vertices = Base::mesh_->face(triangle) ;
+
+        //add an uninitialized edge
+        const unsigned int new_edge_index = next_polygon_.size() ;
+        next_polygon_.resize(new_edge_index+1) ;
+        RVDEdge<Triangulation>& new_edge = next_polygon_[new_edge_index] ;
+
+        //build the intersection vertex
+        if(polygon[i].config == Edge::FACE_EDGE) {
+          //the intersection is an EDGE_VERTEX
+          //recover the combinatorics
+          const unsigned int edge_index = polygon[i].combinatorics ;
+
+          const unsigned int x1 = triangle_vertices[(edge_index  )%3] ;
+          const unsigned int x2 = triangle_vertices[(edge_index+1)%3] ;
+
+          new_edge.vertex.reset( x1, x2, 
+                                 site, opposite_site, 
+                                 Base::mesh_, Base::sites_
+                               ) ;
+
+        } else {
+          //the intersection is a FACE_VERTEX
+          //recover the combinatorics
+          const unsigned int x1 = triangle_vertices[0] ;
+          const unsigned int x2 = triangle_vertices[1] ;
+          const unsigned int x3 = triangle_vertices[2] ;
+          const unsigned int other_site = polygon[i].combinatorics ;
+
+          new_edge.vertex.reset( x1, x2, x3,
+                                 site, opposite_site, other_site,
+                                 Base::mesh_, Base::sites_
+                               ) ;
+        }
+
+        //set the edge configuration
+        if(my_side > 0) {
+          new_edge.config = Edge::BISECTOR_EDGE ;
+          new_edge.combinatorics = opposite_site ;
+        } else {
+          new_edge.config = polygon[i].config ;
+          new_edge.combinatorics = polygon[i].combinatorics ;
+        }
+
+        //compute intersection distance with the center site
+        Vector d = site_pos - new_edge.vertex ;
+        //std::cout << "New vertex is at distance " << d.dot(d) << std::endl ;
+        site_next_distances_.push_back(d.dot(d)) ;
+        next_new_vertices_.push_back(true) ;
+      }
+    }
+
+    //update current information
+    new_vertices_.swap(next_new_vertices_) ;
+    polygon.swap(next_polygon_) ;
+    site_distances_.swap(site_next_distances_) ;
+
+    //return clipped status
+    return clipped ;
+  }
+
+  //during clipping the new polygon is built in this one and then swapped
+  RVDPolygon<Triangulation> next_polygon_ ;
+
+  /* Algorithm */
+  Algo algorithm_ ;
+
+  /* Nearest neighbour backend */
+  NNBackend nnbackend_ ;
+} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/RVD/polygon.hpp b/contrib/Revoropt/include/Revoropt/RVD/polygon.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..e05d0fcc5bde2812fe1c56a42978f041f7f3e29a
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/RVD/polygon.hpp
@@ -0,0 +1,519 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_RVD_POLYGON_HPP_
+#define _REVOROPT_RVD_POLYGON_HPP_
+
+#include <eigen3/Eigen/Dense>
+#include <vector>
+#include <iostream>
+
+namespace Revoropt {
+
+/**{{{ Vertices **/
+
+/* A RVD vertex acts as a traditionnal vector equipped with the combinatorial
+ * information which defines it. The vertices of the input mesh and sites of the
+ * diagram wich are involved in this combinatorics are stored, and the position
+ * of the point can be recomputed from thins information. */
+
+template<typename _Triangulation>
+class RVDVertex : public Eigen::Matrix<double,_Triangulation::VertexDim,1> {
+
+  public :
+
+    /** Typedefs **/
+    typedef _Triangulation Triangulation ;
+    enum { Dim = Triangulation::VertexDim } ;
+    typedef Eigen::Matrix<double,Dim,1> Vector ;
+    const static unsigned int NO_COMBINATORICS = -1 ;
+
+    /* The different configurations of the vertices of a restricted Voronoi diagram.
+     * ORIGINAL is an original vertex of the input mesh, EDGE_VERTEX is the
+     * intersection between an edge of the input mesh and a bissector of the Voronoi
+     * diagram, and FACE_VERTEX is the intersection between a face of the input mesh
+     * and a Voronoi edge. */
+    
+    enum Config {
+      UNDEFINED,
+      ORIGINAL,
+      EDGE_VERTEX,
+      FACE_VERTEX
+    } ;
+
+
+    /** Initialization **/
+    /* build an UNDEFINED vertex */
+    RVDVertex() { reset() ; }
+
+    /* build an ORIGINAL vertex */
+    RVDVertex( unsigned int x1_id,
+               const Triangulation* mesh
+             ) {
+      reset(x1_id,mesh) ;
+    }
+    /* build an EDGE_VERTEX */
+    RVDVertex( unsigned int x1_id, unsigned int x2_id, 
+               unsigned int v1_id, unsigned int v2_id,
+               const Triangulation* mesh, const double* sites
+             ) {
+      reset(x1_id,x2_id,v1_id,v2_id,mesh,sites) ;
+    }
+    /* build a FACE_VERTEX */
+    RVDVertex( unsigned int x1_id, unsigned int x2_id, unsigned int x3_id, 
+               unsigned int v1_id, unsigned int v2_id, unsigned int v3_id,
+               const Triangulation* mesh, const double* sites
+             ) {
+      reset(x1_id,x2_id,x3_id,v1_id,v2_id,v3_id,mesh,sites) ;
+    }
+
+    /** Modification **/
+
+    /* change into an UNDEFINED vertex */
+    void reset() {
+      config_ = UNDEFINED ;
+    }
+
+    /* change into an ORIGINAL vertex */
+    void reset( unsigned int x1_id,
+                const Triangulation* mesh
+              ) {
+      //set configuration
+      config_ = ORIGINAL ;
+      //set combinatorics
+      combinatorics_[0] = x1_id ;
+      combinatorics_[1] = NO_COMBINATORICS ;
+      combinatorics_[2] = NO_COMBINATORICS ;
+      combinatorics_[3] = NO_COMBINATORICS ;
+      combinatorics_[4] = NO_COMBINATORICS ;
+      combinatorics_[5] = NO_COMBINATORICS ;
+      //compute corresponding position
+      Eigen::Map<const Vector> x(mesh->vertex(combinatorics_[0])) ;
+      this->array() = x ;
+    }
+
+    /* change into an EDGE_VERTEX */
+    void reset( unsigned int x1_id, unsigned int x2_id, 
+                unsigned int v1_id, unsigned int v2_id,
+                const Triangulation* mesh, const double* sites
+              ) {
+      //set configuration
+      config_ = EDGE_VERTEX ;
+      //set combinatorics
+      combinatorics_[0] = x1_id ;
+      combinatorics_[1] = x2_id ;
+      combinatorics_[2] = NO_COMBINATORICS ;
+      combinatorics_[3] = v1_id ;
+      combinatorics_[4] = v2_id ;
+      combinatorics_[5] = NO_COMBINATORICS ;
+      //compute corresponding position
+      //get the two vertices
+      Eigen::Map<const Vector> x1(mesh->vertex(x1_id)) ;
+      Eigen::Map<const Vector> x2(mesh->vertex(x2_id)) ;
+      //get the two sites
+      Eigen::Map<const Vector> v1(sites+Dim*v1_id) ;
+      Eigen::Map<const Vector> v2(sites+Dim*v2_id) ;
+
+      //compute the intersection between the bissector and the edge
+      const Vector diff_sites = v2-v1 ;
+      const Vector mid_sites = 0.5*(v1+v2) ;
+      const Vector edge = x2-x1 ;
+
+      const Vector pos = x1 
+                       + ( diff_sites.dot(mid_sites - x1)
+                           / diff_sites.dot(edge)
+                         )
+                       * edge ;
+
+      //position becomes the RVDVertex position
+      this->array() = pos ;
+    }
+
+    /* change into a FACE_VERTEX */
+    void reset( unsigned int x1_id, unsigned int x2_id, unsigned int x3_id, 
+                unsigned int v1_id, unsigned int v2_id, unsigned int v3_id,
+                const Triangulation* mesh, const double* sites
+              ) {
+      //set configuration
+      config_ = FACE_VERTEX ;
+      //set combiatorics
+      combinatorics_[0] = x1_id ;
+      combinatorics_[1] = x2_id ;
+      combinatorics_[2] = x3_id ;
+      combinatorics_[3] = v1_id ;
+      combinatorics_[4] = v2_id ;
+      combinatorics_[5] = v3_id ;
+      //compute corresponding position
+      //get the three vertices
+      Eigen::Map<const Vector> x1(mesh->vertex(x1_id)) ;
+      Eigen::Map<const Vector> x2(mesh->vertex(x2_id)) ;
+      Eigen::Map<const Vector> x3(mesh->vertex(x3_id)) ;
+
+      //get the three sites
+      Eigen::Map<const Vector> v1(sites+Dim*v1_id) ;
+      Eigen::Map<const Vector> v2(sites+Dim*v2_id) ;
+      Eigen::Map<const Vector> v3(sites+Dim*v3_id) ;
+
+      //compute the intersection between the bissectors and the face
+      const double c1 = (x2-x1).dot(v2-v1) ;
+      const double c2 = (x3-x1).dot(v2-v1) ;
+      const double c3 = 0.5*(v1+v2-2*x1).dot(v2-v1) ;
+      const double c4 = (x2-x1).dot(v3-v1) ;
+      const double c5 = (x3-x1).dot(v3-v1) ;
+      const double c6 = 0.5*(v1+v3-2*x1).dot(v3-v1) ;
+
+      const double det = (c1*c5-c2*c4) ;
+#ifdef DEBUG
+      if(det == 0) {
+        std::cout << "0 determinant : " 
+                  << c1 << ", " 
+                  << c5 << ", " 
+                  << c2 << ", " 
+                  << c4 << std::endl ;
+        std::cout << "Combinatorics : " 
+                  << combinatorics_[3] << ", "
+                  << combinatorics_[4] << ", "
+                  << combinatorics_[5] << std::endl ;
+        std::cout << "v1 : [" 
+                  << v1[0] << ", "
+                  << v1[1] << ", "
+                  << v1[2] << " ]" << std::endl ;
+        std::cout << "v2 : [ " 
+                  << v2[0] << ", "
+                  << v2[1] << ", "
+                  << v2[2] << " ]" << std::endl ;
+        std::cout << "v3 : [" 
+                  << v3[0] << ", "
+                  << v3[1] << ", "
+                  << v3[2] << " ]" << std::endl ;
+      }
+#endif
+      const double denom = 1/det ;
+      const double bary1 = denom*(c3*c5-c2*c6) ;
+      const double bary2 = denom*(c1*c6-c3*c4) ;
+
+      const Vector pos = x1 + bary1*(x2-x1) + bary2*(x3-x1) ;
+
+      //position becomes the 
+      this->array() = pos ;
+    }
+
+    /* Access to the configuration of the point */
+    Config config() const { return config_ ; } ;
+
+    /* Access to the combinatorics */
+    const unsigned int* combinatorics() const { return combinatorics_ ; } ;
+
+    /** Gradient computation **/
+    /* WARNING : the gradient is filled in the output in COLUMN MAJOR order,
+     * since this is the default behaviour in Eigen. You can probably work
+     * around this by #defining the EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION
+     * to Eigen::RowMajor, which would be dangerous and ugly. */
+    
+    void derivative( const int comb_index, 
+                     const Triangulation* mesh, 
+                     const double* sites, 
+                     double* output
+                   ) const {
+      //fill result with zeros
+      std::fill(output, output+Dim*Dim, 0) ;
+
+      //filter cases
+      switch(config_) {
+        case UNDEFINED: {
+          break ;
+        }
+        case ORIGINAL: {
+          //the vertex only depends on one vertex of the mesh
+          if(comb_index != 0) break ;
+
+          //if the derivative is requested for this vertex, return identity
+          for(int i=0; i<Dim; ++i) {
+            output[Dim*i+i] = 1 ;
+          }
+          break ;
+        } 
+        case EDGE_VERTEX: {
+          //the vertex only depends on two vertices and two sites
+          if((comb_index==2) || (comb_index==5)) break ;
+
+          //check whether the derivative is requested wrt a vertex or a site
+          if(comb_index < 3) {
+            //derivative wrt a vertex
+            e_vertex_derivative(comb_index,mesh,sites,output) ;
+          } else {
+            //derivative wrt a site
+            e_site_derivative(comb_index,mesh,sites,output) ;
+          }
+          break ;
+        } 
+        case FACE_VERTEX: {
+          //check whether the derivative is requested wrt a vertex or a site
+          if(comb_index < 3) {
+            //derivative with respect to a vertex
+            f_vertex_derivative(comb_index,mesh,sites,output) ;
+          } else {
+            //derivative with respect to a site
+            f_site_derivative(comb_index,mesh,sites,output) ;
+          }
+          break ;
+        } 
+      }
+    }
+    
+  private :
+
+    /* Specific gradient computation for every non trivial configuration */
+    void e_vertex_derivative( const int comb_index, 
+                              const Triangulation* mesh,
+                              const double* sites,
+                              double* output
+                            ) const {
+      //get the two sites
+      Eigen::Map<const Vector> v0(sites+Dim*combinatorics_[3]) ;
+      Eigen::Map<const Vector> v1(sites+Dim*combinatorics_[4]) ;
+
+      //get the two vertices
+      Eigen::Map<const Vector> x0(
+        mesh->vertex(combinatorics_[ comb_index     ])
+      ) ;
+      Eigen::Map<const Vector> x1(
+        mesh->vertex(combinatorics_[(comb_index+1)%2])
+      ) ;
+
+      //compute the gradient
+      const Vector edge = x1-x0 ;
+      const Vector site_diff = v1-v0 ;
+      const double k = 2*edge.dot(site_diff) ;
+      const double a = (v0+v1-2*x0).dot(site_diff)/k ;
+
+      Eigen::Map< Eigen::Matrix<double,Dim,Dim> > grad(output) ;
+      grad = edge*site_diff.transpose() ;
+      grad.noalias() = 2*(a-1)/k*grad ;
+      for(int i=0; i<Dim; ++i) {
+        grad(i,i) += (1-a) ;
+      }
+    }
+
+    void e_site_derivative( const int comb_index, 
+                            const Triangulation* mesh,
+                            const double* sites,
+                            double* output
+                          ) const {
+      //get the two sites
+      Eigen::Map<const Vector> v0(
+        sites+Dim*combinatorics_[comb_index]
+      ) ;
+      Eigen::Map<const Vector> v1(
+        sites+Dim*combinatorics_[3+((comb_index-2)%2)]
+      ) ;
+
+      //get the two vertices
+      Eigen::Map<const Vector> x0(mesh->vertex(combinatorics_[0])) ;
+      Eigen::Map<const Vector> x1(mesh->vertex(combinatorics_[1])) ;
+      
+      //compute the gradient
+      const Vector edge = x1-x0 ;
+      const Vector site_diff = v1-v0 ;
+      const double half_k = edge.dot(site_diff) ;
+
+      Eigen::Map< Eigen::Matrix<double,Dim,Dim> > grad(output) ;
+      grad = edge*((*this)-v0).transpose() ;
+      grad.noalias() = grad/half_k ;
+    }
+
+    void f_vertex_derivative( const int comb_index, 
+                              const Triangulation* mesh,
+                              const double* sites,
+                              double* output
+                            ) const {
+      //get the three sites
+      Eigen::Map<const Vector> v0(sites+Dim*combinatorics_[3]) ;
+      Eigen::Map<const Vector> v1(sites+Dim*combinatorics_[4]) ;
+      Eigen::Map<const Vector> v2(sites+Dim*combinatorics_[5]) ;
+
+      //get the three vertices
+      Eigen::Map<const Vector> x0(
+        mesh->vertex(combinatorics_[ comb_index     ])
+      ) ;
+      Eigen::Map<const Vector> x1(
+        mesh->vertex(combinatorics_[(comb_index+1)%3])
+      ) ;
+      Eigen::Map<const Vector> x2(
+        mesh->vertex(combinatorics_[(comb_index+2)%3])
+      ) ;
+
+      //compute the gradient
+      const double c0 = (x0-x2).dot(v1-v0) ;
+      const double c1 = (x0-x2).dot(v2-v0) ;
+      const double c2 = (x2-x1).dot(v1-v0) ;
+      const double c3 = (x2-x1).dot(v2-v0) ;
+
+      const double b0 = (v0+v1-2*x2).dot(v1-v0) ;
+      const double b1 = (v0+v2-2*x2).dot(v2-v0) ;
+
+      const double quarter_k = (c0*c3-c2*c1) ;
+      const double a = (b0*c3-c2*b1)/(2*quarter_k) ;
+
+      //TODO cache the first part of this computation for other gradients
+      Eigen::Map< Eigen::Matrix<double,Dim,Dim> > grad(output) ;
+      grad = x0*(x2-x1).transpose()
+           + x1*(x0-x2).transpose()
+           + x2*(x1-x0).transpose() ;
+      grad = grad * (  v0*(v2-v1).transpose()
+                     + v1*(v0-v2).transpose()
+                     + v2*(v1-v0).transpose() ) ;
+      grad.noalias() = -grad/quarter_k ;
+      for(int i=0; i<Dim; ++i) {
+        grad(i,i) += 1 ;
+      }
+      grad.noalias() = a*grad ;
+    }
+
+    void f_site_derivative( const int comb_index, 
+                            const Triangulation* mesh,
+                            const double* sites,
+                            double* output
+                          ) const {
+      //get the three sites
+      Eigen::Map<const Vector> v0(
+        sites+Dim*combinatorics_[    comb_index      ]
+      ) ;
+      Eigen::Map<const Vector> v1(
+        sites+Dim*combinatorics_[3+((comb_index-2)%3)]
+      ) ;
+      Eigen::Map<const Vector> v2(
+        sites+Dim*combinatorics_[3+((comb_index-1)%3)]
+      ) ;
+
+      //get the three vertices
+      Eigen::Map<const Vector> x0(mesh->vertex(combinatorics_[0])) ;
+      Eigen::Map<const Vector> x1(mesh->vertex(combinatorics_[1])) ;
+      Eigen::Map<const Vector> x2(mesh->vertex(combinatorics_[2])) ;
+
+      //compute the gradient 
+      const double c0 = (x1-x0).dot(v0-v2) ;
+      const double c1 = (x2-x0).dot(v0-v2) ;
+      const double c2 = (x1-x0).dot(v2-v1) ;
+      const double c3 = (x2-x0).dot(v2-v1) ;
+
+      const double quarter_k = (c0*c3-c2*c1) ;
+
+      Eigen::Map< Eigen::Matrix<double,Dim,Dim> > grad(output) ;
+      grad = x0*(x2-x1).transpose()
+           + x1*(x0-x2).transpose()
+           + x2*(x1-x0).transpose() ;
+      grad = grad * (v1-v2) * (v0-(*this)).transpose() ;
+      grad.noalias() = grad/quarter_k ;
+    }
+    
+    /* Configuration */
+    Config config_ ;
+
+    /* Sites and vertices involved. The array is arranged as follows depending
+     * on the verrtex configuration, with the mesh vertices denoted by x_ and
+     * the sites as v_ :
+     *   - ORIGINAL    : [ x0, - , - , - , - , -  ]
+     *   - EDGE_VERTEX : [ x0, x1, - , v0, v1, -  ]
+     *   - FACE_VERTEX : [ x0, x1, x2, v0, v1, v2 ]
+     * */
+    unsigned int combinatorics_[6] ;
+} ;
+
+//}}}
+
+/**{{{ Edges **/
+
+/* A PolygonEdge encodes the vertex it starts from, its configuration, and
+ * depending on its configuration, the corresponding symbolic information :
+ *   -- FACE_EDGE : the index of the edge within the face ;
+ *   -- BISECTOR_EDGE : the index of the site beyound the edge */
+
+template<typename Triangulation>
+class RVDEdge {
+
+  public :
+
+  /* There are two kinds of edges. A FACE_EDGE comes from the initial edges of the
+   * clipped triangle, and a BISECTOR_EDGE results from the intersection between
+   * the triangle and a bisector. */
+  
+  enum Config {
+    FACE_EDGE,
+    BISECTOR_EDGE
+  } ;
+
+  /* Configuration */
+  Config config ;
+
+  /* Origin Vertex */
+  RVDVertex<Triangulation> vertex ;
+
+  /* combinatorics */
+  unsigned int combinatorics ;
+} ;
+
+//}}}
+
+/**{{{ Polygons **/
+
+/* Beware that inheriting from stl vector can be dangerous, since the destructor
+ * of vectors is not declared virtual. This not a problem here, since we do not
+ * need a destructor, and we do not intend to cas RVDPolygon pointers as vector 
+ * pointers.*/
+template<typename _Triangulation>
+class RVDPolygon : public std::vector< RVDEdge<_Triangulation> > {
+
+  public :
+
+  /* Typedefs */
+  typedef _Triangulation Triangulation ;
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef Eigen::Matrix<double,Dim,1> Vector ;
+
+  /* Empty initialization */
+  RVDPolygon() {} ;
+
+  /* Initialization from a triangle of a mesh */
+  RVDPolygon( unsigned int triangle,
+              const Triangulation* mesh
+            ) {
+    reset(triangle, mesh) ;
+  }
+
+  /* Reset to a triangle of a mesh */
+  void reset( unsigned int triangle,
+              const Triangulation* mesh
+            ) {
+    //resize to three vertices
+    (*this).resize(3) ;
+
+    //get the triangle combinatorics from the mesh
+    const unsigned int* triangle_verts = mesh->face(triangle) ;
+
+    //assign the init_polygon
+    for(int i=0; i<3; ++i) {
+      //reset vertex
+      const unsigned int edge_vertex = triangle_verts[i] ;
+      (*this)[i].vertex.reset(edge_vertex,mesh) ;
+
+      //assign edge combinatorics as its index within the triangle 
+      (*this)[i].combinatorics = i ;
+    }
+  }
+} ;
+
+//}}}
+
+
+} //end of namespace Revoropt
+
+#endif
+
diff --git a/contrib/Revoropt/include/Revoropt/RVD/rdt.hpp b/contrib/Revoropt/include/Revoropt/RVD/rdt.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..9f0b801b166c4a05a15182ba33a6229d2a687be9
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/RVD/rdt.hpp
@@ -0,0 +1,91 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_RVD_RDT_HPP_
+#define _REVOROPT_RVD_RDT_HPP_
+
+#include <unordered_set>
+#include <iostream>
+
+#include "rvd.hpp"
+#include "polygon.hpp"
+#include <Revoropt/Tools/combinatorics.hpp>
+#include <Revoropt/Mesh/builder_def.hpp>
+
+namespace Revoropt {
+
+/* Build a restricted Delaunay triangulation */
+
+template<typename _Triangulation>
+class RDTBuilder : public Action<_Triangulation> {
+
+  public :
+
+  /* Types and template data */
+  typedef _Triangulation Triangulation ;
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef Eigen::Matrix<double,Dim,1> Vector ;
+  typedef tuplekey<3> Triangle ;
+  typedef tuple_hash<3> hasher ;
+  typedef RVDVertex<Triangulation> Vertex ;
+
+  RDTBuilder( std::vector<unsigned int>& output_triangles
+            ) : triangles_(output_triangles) {
+  }
+  
+  /* Reset */
+  void reset() {
+    built_triangles_.clear() ;
+  }
+
+  /* Action for to use on the RVD */
+  void operator()( unsigned int site,
+                   unsigned int triangle,
+                   const RVDPolygon<Triangulation>& polygon
+                 ) {
+    //size of the polygon
+    unsigned int size = polygon.size() ;
+    if(size<3) return ;
+
+    //build and add the triangles
+    for(unsigned int i=0; i<size; ++i) {
+      const RVDVertex<Triangulation>& v = polygon[i].vertex ;
+      if(v.config() == Vertex::FACE_VERTEX) {
+        unsigned int v1 = v.combinatorics()[3] ;
+        unsigned int v2 = v.combinatorics()[4] ;
+        unsigned int v3 = v.combinatorics()[5] ;
+
+        Triangle key(v1,v2,v3) ;
+
+        std::unordered_set<Triangle, hasher>::iterator it ;
+        it = built_triangles_.find(key) ;
+        if(it == built_triangles_.end()) {
+          triangles_.push_back(v1) ; 
+          triangles_.push_back(v2) ; 
+          triangles_.push_back(v3) ; 
+          built_triangles_.insert(key) ;
+        }
+      }
+    }
+  }
+
+  private :
+
+  /* Structure to avoid creating twice the same triangle */
+  std::unordered_set<Triangle, hasher> built_triangles_ ;
+
+  /* computed triangles are stored in a vector*/
+  std::vector<unsigned int>& triangles_ ;
+
+} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/RVD/rvd.hpp b/contrib/Revoropt/include/Revoropt/RVD/rvd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..81512dfd09b2a214e8cf05cd477531bd90dd9abc
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/RVD/rvd.hpp
@@ -0,0 +1,364 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_RVD_HPP_
+#define _REVOROPT_RVD_HPP_
+
+#include "polygon.hpp"
+#include "nn_clipper.hpp"
+#include "action.hpp"
+
+#include <Revoropt/Tools/combinatorics.hpp>
+#include <Revoropt/Tools/hash.hpp>
+
+#ifdef USE_ANN
+  #include "ann_backend.hpp"
+#else
+  #include "flann_backend.hpp"
+#endif
+
+#include <eigen3/Eigen/Dense>
+#include <vector>
+#include <stack>
+#include <unordered_map>
+#include <iostream>
+
+namespace Revoropt {
+
+/** Restricted Voronoi Diagram computer **/
+
+template<typename _Triangulation>
+class RVD {
+
+  public :
+
+  /* Types and template data */
+  typedef _Triangulation Triangulation ;
+  enum { Dim = Triangulation::VertexDim } ;
+  typedef Eigen::Matrix<double,Dim,1> Vector ;
+
+  typedef RVDEdge<Triangulation> Edge ;
+  typedef RVDEdge<Triangulation> Vertex ;
+
+  /* Initialization */
+
+  RVD() : mesh_(NULL), clipper_owned_(false), clipper_(NULL) {} ;
+
+  ~RVD() {
+    if(clipper_owned_) {
+      delete clipper_ ;
+    }
+  }
+
+  template<typename _Clipper>
+  void set_clipper( _Clipper* clipper ) {
+    //cleanup if necessary
+    if(clipper_ != NULL && clipper_owned_) {
+      delete clipper_ ;
+    }
+    clipper_owned_ = false ;
+    clipper_ = clipper ;
+  }
+
+  void set_default_clipper() {
+#ifdef USE_ANN
+    typedef NNClipper< Triangulation,ANNBackend<Dim> > DefaultClipper ;
+#else
+    typedef NNClipper< Triangulation,FLANNBackend<Dim> > DefaultClipper ;
+#endif
+    //cleanup if necessary
+    if(clipper_ != NULL && clipper_owned_) {
+      delete clipper_ ;
+    }
+    //allocate
+    DefaultClipper* clipper = new DefaultClipper ;
+    //parameters
+    clipper->set_neighbourhood_size(15) ;
+    clipper->set_algorithm(DefaultClipper::CORNER_CLIPPING) ;
+    //mark the clipper as owned
+    clipper_owned_ = true ;
+    //assign the clipper
+    clipper_ = clipper ;
+  }
+
+  void set_mesh( const Triangulation* mesh  ) {
+    mesh_ = mesh ;
+    if(clipper_ == NULL) {
+      set_default_clipper() ;
+    }
+    clipper_->set_mesh(mesh) ;
+  }
+
+  void set_sites( const double* sites, unsigned int sites_size ) {
+    if(clipper_ == NULL) {
+      set_default_clipper() ;
+    }
+    clipper_->set_sites(sites, sites_size) ;
+  }
+
+  /* Access */
+
+  const double* sites() const { return clipper_->sites() ; }
+
+  unsigned int sites_size() const { return clipper_->sites_size() ; }
+
+  const Triangulation* mesh() const { return clipper_->mesh() ; }
+
+  /* Computing the RVD and applying an action on each polygon */
+
+  template<typename Action_T>
+  void compute(Action_T& action) {
+    //reset markers for triangles
+    triangle_stacked_.assign(mesh_->faces_size(),false) ;
+
+    //reset clipper
+    clipper_->reset() ;
+
+    //create the inner loop data
+    const unsigned int site_size = clipper_->sites_size() ;
+    //assign last triangle for each site to NO_NEIGHBOUR, therefore no triangle.
+    site_last_triangle_.assign(site_size,Triangulation::NO_NEIGHBOUR) ;
+
+    //loop over the connected components
+    for( unsigned int init_triangle = 0;
+         init_triangle<mesh_->faces_size();
+         ++init_triangle
+       ) {
+      //check that the triangle was not previously treated
+      if(!triangle_stacked_[init_triangle]) {
+        //std::cout << "Found a connected component" << std::endl ;
+        //find a site to initialize the propagation
+        unsigned int outer_init_site = get_init_site(init_triangle) ;
+
+        //std::cout << "Initializing site is " << outer_init_site << std::endl ;
+
+        //initialize the outer loop
+        Couple init_couple(init_triangle,outer_init_site) ;
+        triangle_stacked_[init_triangle] = true ;
+        triangle_stack_.push(init_couple) ;
+
+        //launch the outer loop
+        while(!triangle_stack_.empty()) {
+          //get a triangle and a site
+          unsigned int current_triangle = triangle_stack_.top().first ;
+          unsigned int inner_init_site = triangle_stack_.top().second ;
+          triangle_stack_.pop() ;
+
+          //std::cout << "handling triangle " << current_triangle << std::endl ;
+
+          //initialize the inner loop
+          site_stack_.push(inner_init_site) ;
+          site_last_triangle_[inner_init_site] = current_triangle ;
+
+          //launch the inner loop
+          while(!site_stack_.empty()) {
+            //get a site to clip thetriangle
+            unsigned int current_site = site_stack_.top() ;
+            site_stack_.pop() ;
+
+            //Create a polygon corresponding to the face and clip it
+            RVDPolygon<Triangulation> face_polygon(
+              current_triangle, mesh_
+            ) ;
+            clipper_->clip_by_cell(
+              face_polygon, current_triangle, current_site
+            ) ;
+
+            //apply the action
+            action(current_site, current_triangle, face_polygon) ;
+
+            //propagate the computation from the edges of curr_polygon_
+            propagate(face_polygon, current_triangle, current_site) ;
+          }//end inner loop
+        }//end outer loop on triangle--site couples
+      }
+    } //end of loop over connected components
+
+    //call finalize method if it exists
+    wrap_finalize(action) ;
+  }
+
+  private :
+
+  /** Data for the outer loop **/
+
+  typedef std::pair<unsigned int,unsigned int> Couple ;
+
+  /* The triangle_stack_ contains mesh triangle candidates for the splitting,
+   * with a site to initialize the splitting, done in an inner loop using the
+   * site_stack_. A mesh triangle shall not be added twice to this stack.*/
+  std::stack<Couple> triangle_stack_ ;
+
+  /* A boolean encodes for each mesh triangle if it was previously stacked in
+   * the triangle_stack_, to ensure that a mesh triangle is only stacked once in
+   * this stack.  */
+  std::vector<bool> triangle_stacked_ ;
+
+  /** Data for the inner loop **/
+
+  /* The site_stack_ contains new candidate sites for the splitting of a given
+   * triangle of the mesh. This stack is used in a inner loop to split a mesh
+   * triangle betwen Voronoi cells. A site shall not be added twice to this
+   * stack. */
+  std::stack<unsigned int> site_stack_ ;
+
+
+  /* The last mesh triangle clipped for each site is stored, to ensure that a
+   * site is not added twice in the site_stack_. */
+  std::vector<unsigned int> site_last_triangle_ ;
+
+  /** Initialization helpers for the compute method **/
+
+  /* Get the nearest site from the centroid of a triangle */
+  unsigned int get_init_site( unsigned int triangle ) {
+    //compute the centroid of thetriangle
+    const unsigned int* triangle_verts = mesh_->face(triangle) ;
+    Eigen::Map<const Vector> x1(mesh_->vertex(triangle_verts[0])) ;
+    Eigen::Map<const Vector> x2(mesh_->vertex(triangle_verts[1])) ;
+    Eigen::Map<const Vector> x3(mesh_->vertex(triangle_verts[2])) ;
+
+    const Vector g = (x1+x2+x3)/3. ;
+
+    //get the site nearest to the centroid
+    unsigned int nearest_site = clipper_->nearest_site(g.data()) ;
+    return nearest_site ;
+  }
+
+  /** Propagation of the computations **/
+
+  void propagate( RVDPolygon<Triangulation>& polygon,
+                  unsigned int triangle,
+                  unsigned int site
+                ) {
+    //get triangles neighbouring the triangle
+    const unsigned int* triangle_neighbours =
+      mesh_->face_neighbours(triangle) ;
+
+    //iterate over the edges of curr_polygon
+    for(unsigned int i = 0; i<polygon.size(); ++i) {
+      //get the combinatorics of the edge
+      unsigned int combinatorics = polygon[i].combinatorics ;
+      if(polygon[i].config == Edge::BISECTOR_EDGE) {
+        //the edge is the intersection between the triangle and a bisector
+        //propagate the neighbouring site for the current triangle
+        if(site_last_triangle_[combinatorics] != triangle) {
+          //the neighbouring site has not been stacked for this triangle yet
+          site_last_triangle_[combinatorics] = triangle ;
+          site_stack_.push(combinatorics) ;
+
+          //std::cout << "Propagating site " << combinatorics << std::endl ;
+        }
+      } else {
+        //the edge is a portion of an original edge of the triangle
+        //propagate the neighbouring triangle with the same site
+        unsigned int neighbour_triangle = triangle_neighbours[combinatorics] ;
+        if( neighbour_triangle != Triangulation::NO_NEIGHBOUR
+            && !triangle_stacked_[neighbour_triangle]
+          ) {
+          //the triangle has not been stacked yet
+          triangle_stacked_[neighbour_triangle] = true ;
+          triangle_stack_.push(Couple(neighbour_triangle, site)) ;
+
+          //std::cout << "Propagating triangle " << neighbour_triangle << std::endl ;
+        }
+      }
+    }
+    //std::cout << "Done propagating." << std::endl ;
+  }
+
+  /** Mesh **/
+  const Triangulation* mesh_ ;
+
+  /** Clipper **/
+  bool clipper_owned_ ;
+  Clipper<Triangulation>* clipper_ ;
+
+} ;
+
+/* Store a restricted Voronoi diagram */
+
+template<typename Triangulation, int _OutDim = Triangulation::VertexDim>
+class RVDStore {
+
+  //typedefs
+  enum { Dim = Triangulation::VertexDim, OutDim = _OutDim } ;
+  typedef typename Triangulation::Scalar Scalar ;
+  typedef tuplekey<3> CombVertexPart ;
+  typedef tuple_hash<3, unsigned int> CVPHasher ;
+  typedef std::pair<CombVertexPart,CombVertexPart> CombVertex ;
+
+  class CVHasher {
+    public :
+      std::size_t operator()( const CombVertex& comb_vertex ) const {
+        std::size_t seed = 0 ;
+        hash_combine<CombVertexPart, CVPHasher>(seed, comb_vertex.first) ;
+        hash_combine<CombVertexPart, CVPHasher>(seed, comb_vertex.second) ;
+        return seed ;
+      }
+  } ;
+
+  public :
+
+  void operator()( unsigned int site, unsigned int triangle,
+                   const RVDPolygon<Triangulation>& polygon
+                 ) {
+    unsigned int size = polygon.size() ;
+
+    //collect the vertex indices of the polygon vertices
+    std::vector<unsigned int> vert_indices(size) ;
+
+    for(unsigned int vertex = 0; vertex < size; ++vertex) {
+      //Combinatorial vertex
+      const RVDVertex<Triangulation>& v = polygon[vertex].vertex ;
+      //build the key to merge the vertex with any combinatorial equivalent
+      CombVertexPart cv_part_1(v.combinatorics()) ;
+      CombVertexPart cv_part_2(v.combinatorics()+3) ;
+      CombVertex key(cv_part_1,cv_part_2) ;
+      //check whether the combinatorics of this vertex is already existing
+      vmap_iterator it = vmap.find(key) ;
+      if( it == vmap.end() ) {
+        //no such combinatorics in the map
+        //add the vertex to the final mesh
+        vert_indices[vertex] = rvd_mesh.push_vertex(v.data()) ;
+        //associate the index with the combinatorics in the map
+        vmap[key] = vert_indices[vertex] ;
+        //store the combinatorics of the vertex
+        vertex_combinatorics.push_back(key) ;
+      } else {
+        //the combinatorics was previously handled, recover the index
+        vert_indices[vertex] = it->second ;
+      }
+    }
+
+    //add the polygon to the mesh
+    rvd_mesh.push_face(vert_indices.data(), size) ;
+    //store the polygon site
+    face_sites.push_back(site) ;
+  }
+
+  //collecting and merging RVD vertices
+  std::unordered_map<CombVertex, unsigned int, CVHasher> vmap ;
+  typedef typename std::unordered_map<
+    CombVertex,
+    unsigned int,
+    CVHasher
+  >::iterator vmap_iterator ;
+  //output mesh
+  MeshBuilder<Variable,OutDim,Scalar> rvd_mesh ;
+  //recall the site index for every face
+  std::vector<unsigned int> face_sites ;
+  //recall the combinatorics for every vertex
+  std::vector<CombVertex> vertex_combinatorics ;
+} ;
+
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Solver/.gitignore b/contrib/Revoropt/include/Revoropt/Solver/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..6e7133dae36877b13f8788676274b9e0abdc1c32
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Solver/.gitignore
@@ -0,0 +1 @@
+wrapper.os
diff --git a/contrib/Revoropt/include/Revoropt/Solver/alglib_cg.hpp b/contrib/Revoropt/include/Revoropt/Solver/alglib_cg.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..63f92519cb47ab3627617c0b1d69b7b37fe718a0
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Solver/alglib_cg.hpp
@@ -0,0 +1,225 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_SOLVER_ALGLIB_CG_WRAPPER_H_
+#define _REVOROPT_SOLVER_ALGLIB_CG_WRAPPER_H_
+
+#include <libalglib/optimization.h>
+
+namespace Revoropt {
+namespace Solver {
+
+/** Solver encapsulation **/
+
+class AlgCG {
+
+  public :
+
+  /* Types */
+
+  /** Solver parameters **/
+  class SolverParams {
+
+    public :
+
+    SolverParams() : epsg(0), epsf(0), epsx(0), 
+                     max_iterations(10) {}
+
+    double epsg ;
+    double epsf ;
+    double epsx ;
+    alglib::ae_int_t max_iterations ;
+  } ;
+
+  /** Iteration data **/ 
+  
+  typedef struct {
+    const double* x ;      //current variable positions
+    const unsigned int n ; //size of x and g
+    const double fx ;      //objective function value
+    const unsigned int k ; //current iteration count
+  } IterData ;
+  
+  /** Objective function data **/
+
+  typedef struct {
+    const double* x ;      //current variable positions
+    const unsigned int n ; //size of x and g
+    double* g ;            //gradient
+  } EvalData ;
+
+  /* Solver interface */
+  template<typename ObjFun>
+  int solve( double* x, unsigned int size, 
+             ObjFun* objfun, 
+             unsigned int n_iter 
+           ) {
+    //setup
+    iteration_ = 0 ;
+    variables_.setcontent(size,x) ;
+    objfun_ = objfun ;
+    solver_param.max_iterations = n_iter ;
+
+    //build solver and solve
+    alglib::mincgcreate(variables_, state_) ;
+    alglib::mincgsetcond( state_,
+                          solver_param.epsg,
+                          solver_param.epsf,
+                          solver_param.epsx,
+                          solver_param.max_iterations
+                        ) ;
+    solve_wrapper<ObjFun, void>(this) ;
+
+    //copy the result back
+    alglib::mincgreport report ;
+    alglib::mincgresults(state_, variables_, report) ;
+    std::copy( variables_.getcontent(), 
+               variables_.getcontent() + variables_.length(),
+               x
+             ) ;
+    return report.terminationtype ;
+  }
+
+  template<typename ObjFun, typename IterCallback>
+  int solve( double* x, unsigned int size, 
+             ObjFun* objfun, 
+             unsigned int n_iter,
+             IterCallback* callback
+           ) {
+    //setup
+    iteration_ = 0 ;
+    variables_.setcontent(size,x) ;
+    objfun_ = objfun ;
+    iter_callback_ = callback ;
+    solver_param.max_iterations = n_iter ;
+
+    //build solver and solve
+    alglib::mincgcreate(variables_, state_) ;
+    alglib::mincgsetcond( state_,
+                          solver_param.epsg,
+                          solver_param.epsf,
+                          solver_param.epsx,
+                          solver_param.max_iterations
+                        ) ;
+    alglib::mincgsetxrep(state_, true) ;
+    solve_wrapper<ObjFun, IterCallback>(this) ;
+
+    //copy the result back
+    alglib::mincgreport report ;
+    alglib::mincgresults(state_, variables_, report) ;
+    std::copy( variables_.getcontent(), 
+               variables_.getcontent() + variables_.length(),
+               x
+             ) ;
+    return report.terminationtype ;
+  }
+
+  /* Solver parameters */
+
+  SolverParams solver_param ;
+
+  private :
+
+  /* State */
+  alglib::mincgstate state_ ;
+  unsigned int iteration_ ;
+
+  /* Variables */
+
+  alglib::real_1d_array variables_ ;
+
+  /* Callbacks */
+
+  void* objfun_ ;
+  void* iter_callback_ ;
+
+  /* Functions to be passed to lbfgs */
+  template<typename ObjFun, typename IterCallback>
+  static void solve_wrapper( AlgCG* instance ) ;
+
+  template<typename IterCallback>
+  static void iter_wrapper( const alglib::real_1d_array& x,
+                            double f,
+                            void* instance
+                          ) ;
+
+  template<typename ObjFun>
+  static void eval_wrapper( const alglib::real_1d_array& x,
+                            double& f,
+                            alglib::real_1d_array& grad,
+                            void* instance
+                          ) ;
+
+} ;
+
+template<typename ObjFun, typename IterCallback>
+void AlgCG::solve_wrapper( AlgCG* instance ) {
+  //solve
+  return alglib::mincgoptimize( instance->state_, 
+                                AlgCG::eval_wrapper<ObjFun>, 
+                                AlgCG::iter_wrapper<IterCallback>, 
+                                instance
+                              ) ;
+}
+
+template<typename IterCallback>
+void AlgCG::iter_wrapper( const alglib::real_1d_array& x,
+                          double f,
+                          void* instance
+                        ) {
+  //the solver context is provided as the instance
+  AlgCG* s = (AlgCG*) instance ;
+
+  //the iteration callback is a member
+  IterCallback* callback = (IterCallback*) s->iter_callback_ ;
+
+  //call it
+  AlgCG::IterData data = { 
+    x.getcontent(), 
+    (unsigned int)x.length(), 
+    f,
+    ++s->iteration_
+  } ;
+  (*callback)(&data) ;
+}
+
+template<>
+void AlgCG::iter_wrapper<void>( const alglib::real_1d_array& x,
+                                double f,
+                                void* instance
+                              ) {
+}
+
+template<typename ObjFun>
+void AlgCG::eval_wrapper( const alglib::real_1d_array& x,
+                          double& f,
+                          alglib::real_1d_array& grad,
+                          void* instance
+                        ) {
+  //the solver context is provided as the instance
+  AlgCG* s = (AlgCG*) instance ;
+
+  //the objective function is a member
+  ObjFun* objfun = (ObjFun*) s->objfun_ ;
+
+  //call the callback
+  AlgCG::EvalData data = {
+    x.getcontent(),
+    (unsigned int)x.length(),
+    grad.getcontent()
+  } ;
+  f = (*objfun)(&data) ;
+}
+
+} //end of namespace Solver
+} //end of namespace Revoropt
+
+#endif
+
diff --git a/contrib/Revoropt/include/Revoropt/Solver/alglib_lbfgs.hpp b/contrib/Revoropt/include/Revoropt/Solver/alglib_lbfgs.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..125fb1d02e48c1f524dd26827752fccf9ea8f304
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Solver/alglib_lbfgs.hpp
@@ -0,0 +1,227 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_SOLVER_ALGLIB_LBFGS_WRAPPER_HPP_
+#define _REVOROPT_SOLVER_ALGLIB_LBFGS_WRAPPER_HPP_
+
+//#include <libalglib/optimization.h>
+#include <optimization.h>
+
+namespace Revoropt {
+namespace Solver {
+
+/** Solver encapsulation **/
+
+class AlgLBFGS {
+
+  public :
+
+  /* Types */
+
+  /** Solver parameters **/
+  class SolverParams {
+
+    public :
+
+    SolverParams() : epsg(0), epsf(0), epsx(0),
+                     update_size(5), max_iterations(10) {}
+
+    double epsg ;
+    double epsf ;
+    double epsx ;
+    unsigned int update_size ;
+    alglib::ae_int_t max_iterations ;
+  } ;
+
+  /** Iteration data **/
+
+  typedef struct {
+    const double* x ;   //current variable positions
+    const unsigned int n ;       //size of x and g
+    const double fx ;   //objective function value
+    const unsigned int k ;             //current iteration count
+  } IterData ;
+
+  /** Objective function data **/
+
+  typedef struct {
+    const double* x ;   //current variable positions
+    const unsigned int n ;       //size of x and g
+    double* g ;         //gradient
+  } EvalData ;
+
+  /* Solver interface */
+  template<typename ObjFun>
+  int solve( double* x, unsigned int size,
+             ObjFun* objfun,
+             unsigned int n_iter
+           ) {
+    //setup
+    iteration_ = 0 ;
+    variables_.setcontent(size,x) ;
+    objfun_ = objfun ;
+    solver_param.max_iterations = n_iter ;
+
+    //build solver and solve
+    alglib::minlbfgscreate(solver_param.update_size, variables_, state_) ;
+    alglib::minlbfgssetcond( state_,
+                             solver_param.epsg,
+                             solver_param.epsf,
+                             solver_param.epsx,
+                             solver_param.max_iterations
+                           ) ;
+    solve_wrapper<ObjFun, void>(this) ;
+
+    //copy the result back
+    alglib::minlbfgsreport report ;
+    alglib::minlbfgsresults(state_, variables_, report) ;
+    std::copy( variables_.getcontent(),
+               variables_.getcontent() + variables_.length(),
+               x
+             ) ;
+    return report.terminationtype ;
+  }
+
+  template<typename ObjFun, typename IterCallback>
+  int solve( double* x, unsigned int size,
+             ObjFun* objfun,
+             unsigned int n_iter,
+             IterCallback* callback
+           ) {
+    //setup
+    iteration_ = 0 ;
+    variables_.setcontent(size,x) ;
+    objfun_ = objfun ;
+    iter_callback_ = callback ;
+    solver_param.max_iterations = n_iter ;
+
+    alglib::minlbfgsreport report ;
+
+    //build solver and solve
+    alglib::minlbfgscreate(solver_param.update_size, variables_, state_) ;
+    alglib::minlbfgssetcond( state_,
+                             solver_param.epsg,
+                             solver_param.epsf,
+                             solver_param.epsx,
+                             solver_param.max_iterations
+                           ) ;
+    alglib::minlbfgssetxrep(state_, true) ;
+    solve_wrapper<ObjFun, IterCallback>(this) ;
+
+    //copy the result back
+    alglib::minlbfgsresults(state_, variables_, report) ;
+    std::copy( variables_.getcontent(),
+               variables_.getcontent() + variables_.length(),
+               x
+             ) ;
+    return report.terminationtype ;
+  }
+
+  /* Solver parameters */
+
+  SolverParams solver_param ;
+
+  private :
+
+  /* State */
+  alglib::minlbfgsstate state_ ;
+  unsigned int iteration_ ;
+
+  /* Variables */
+
+  alglib::real_1d_array variables_ ;
+
+  /* Callbacks */
+
+  void* objfun_ ;
+  void* iter_callback_ ;
+
+  /* Functions to be passed to lbfgs */
+  template<typename ObjFun, typename IterCallback>
+  static void solve_wrapper( AlgLBFGS* instance ) ;
+
+  template<typename IterCallback>
+  static void iter_wrapper( const alglib::real_1d_array& x,
+                            double f,
+                            void* instance
+                          ) ;
+
+  template<typename ObjFun>
+  static void eval_wrapper( const alglib::real_1d_array& x,
+                            double& f,
+                            alglib::real_1d_array& grad,
+                            void* instance
+                          ) ;
+
+} ;
+
+template<typename ObjFun, typename IterCallback>
+void AlgLBFGS::solve_wrapper( AlgLBFGS* instance ) {
+  //solve
+  return alglib::minlbfgsoptimize( instance->state_,
+                                   AlgLBFGS::eval_wrapper<ObjFun>,
+                                   AlgLBFGS::iter_wrapper<IterCallback>,
+                                   instance
+                                 ) ;
+}
+
+template<typename IterCallback>
+void AlgLBFGS::iter_wrapper( const alglib::real_1d_array& x,
+                             double f,
+                             void* instance
+                           ) {
+  //the solver context is provided as the instance
+  AlgLBFGS* s = (AlgLBFGS*) instance ;
+
+  //the iteration callback is a member
+  IterCallback* callback = (IterCallback*) s->iter_callback_ ;
+
+  //call it
+  AlgLBFGS::IterData data = {
+    x.getcontent(),
+    (unsigned int)x.length(),
+    f,
+    ++s->iteration_
+  } ;
+  (*callback)(&data) ;
+}
+
+template<>
+void AlgLBFGS::iter_wrapper<void>( const alglib::real_1d_array& x,
+                                   double f,
+                                   void* instance
+                                 ) {
+}
+
+template<typename ObjFun>
+void AlgLBFGS::eval_wrapper( const alglib::real_1d_array& x,
+                             double& f,
+                             alglib::real_1d_array& grad,
+                             void* instance
+                           ) {
+  //the solver context is provided as the instance
+  AlgLBFGS* s = (AlgLBFGS*) instance ;
+
+  //the objective function is a member
+  ObjFun* objfun = (ObjFun*) s->objfun_ ;
+
+  //call the callback
+  AlgLBFGS::EvalData data = {
+    x.getcontent(),
+    (unsigned int)x.length(),
+    grad.getcontent()
+  } ;
+  f = (*objfun)(&data) ;
+}
+
+} //end of namespace Solver
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Solver/lbfgs.hpp b/contrib/Revoropt/include/Revoropt/Solver/lbfgs.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c4704499ee8228b111f7878efc57fef83eebbeef
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Solver/lbfgs.hpp
@@ -0,0 +1,205 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_SOLVER_LBFGS_WRAPPER_H_
+#define _REVOROPT_SOLVER_LBFGS_WRAPPER_H_
+
+#include <lbfgs.h>
+
+namespace Revoropt {
+namespace Solver {
+
+/** Solver encapsulation **/
+
+class LBFGS {
+
+  public :
+
+  /* Types */
+
+  typedef lbfgs_parameter_t SolverParams ;
+
+  /** Iteration callback data **/
+  
+  typedef struct {
+    const double* x ;    //current variable positions
+    const double* g ;    //current gradient
+    const double fx ;    //current value of the objective function
+    const double xnorm ; //norm of x
+    const double gnorm ; //norm of g
+    const double step ;  //current step length
+    int n ;        //size of x and g
+    int k ;        //current iteration count
+    int ls ;       //number of evaluations required for last iteration
+  } IterData ;
+  
+  /** Objective function data **/
+  
+  typedef struct {
+    const double* x ;   //current variable positions
+    double* g ;   //output here the gradient of the objective function
+    const int n ;       //size of x and g
+    double step ; //current step length
+  } EvalData ;
+
+  /* Initialization */
+
+  LBFGS() {
+    lbfgs_parameter_init(&solver_param) ;
+    solver_param.epsilon = 0 ;
+    //solver_param.linesearch = LBFGS_LINESEARCH_BACKTRACKING_ARMIJO ;
+    solver_param.max_linesearch = 20 ;
+  }
+
+  /* Solver interface */
+
+  template<typename ObjFun>
+  int solve( double* x, unsigned int size, 
+             ObjFun* objfun, 
+             unsigned int n_iter 
+           ) {
+    variables_ = x ;
+    variables_size_ = size ;
+    objfun_ = objfun ;
+    solver_param.max_iterations = n_iter ;
+    return solve_wrapper<ObjFun, void>(this) ;
+  }
+
+  template<typename ObjFun, typename IterCallback>
+  int solve( double* x, unsigned int size, 
+             ObjFun* objfun, 
+             unsigned int n_iter,
+             IterCallback* callback
+           ) {
+    variables_ = x ;
+    variables_size_ = size ;
+    objfun_ = objfun ;
+    solver_param.max_iterations = n_iter ;
+    iter_callback_ = callback ;
+    return solve_wrapper<ObjFun, IterCallback>(this) ;
+  }
+
+  /* Solver parameters */
+
+  SolverParams solver_param ;
+
+  private :
+
+  /* Variables */
+  double* variables_ ;
+  unsigned int variables_size_ ;
+
+  /* Callbacks */
+
+  void* objfun_ ;
+  void* iter_callback_ ;
+
+  /* Functions to be passed to lbfgs */
+  template<typename ObjFun, typename IterCallback>
+  static int solve_wrapper( LBFGS* instance ) ;
+
+  template<typename IterCallback>
+  static int iter_wrapper( void* instance,
+                           const double* x,
+                           const double* g,
+                           const double fx,
+                           const double xnorm,
+                           const double gnorm,
+                           const double step,
+                           int n,
+                           int k,
+                           int ls
+                         ) ;
+
+  template<typename ObjFun>
+  static double eval_wrapper( void* instance,
+                              const double* x,
+                              double* g,
+                              const int n,
+                              const double step
+                            ) ;
+
+} ;
+
+template<typename ObjFun, typename IterCallback>
+int LBFGS::solve_wrapper( LBFGS* instance ) {
+  //solve
+  return lbfgs( instance->variables_size_, 
+                instance->variables_, 
+                NULL,
+                LBFGS::eval_wrapper<ObjFun>,
+                LBFGS::iter_wrapper<IterCallback>,
+                instance,
+                &(instance->solver_param)
+              ) ;
+}
+
+template<typename IterCallback>
+int LBFGS::iter_wrapper( void* instance,
+                         const double* x,
+                         const double* g,
+                         const double fx,
+                         const double xnorm,
+                         const double gnorm,
+                         const double step,
+                         int n,
+                         int k,
+                         int ls
+                       ) {
+  //the solver context is provided as the instance
+  LBFGS* s = (LBFGS*) instance ;
+
+  //the iteration callback is a member
+  IterCallback* callback = (IterCallback*) s->iter_callback_ ;
+
+  //call it
+  LBFGS::IterData data = {x, g, fx, xnorm, gnorm, step, n, k, ls} ;
+  return (*callback)(&data) ;
+}
+
+template<>
+int LBFGS::iter_wrapper<void>( void* instance,
+                               const double* x,
+                               const double* g,
+                               const double fx,
+                               const double xnorm,
+                               const double gnorm,
+                               const double step,
+                               int n,
+                               int k,
+                               int ls
+                             ) {
+  return 0 ;
+}
+
+template<typename ObjFun>
+double LBFGS::eval_wrapper( void* instance,
+                            const double* x,
+                            double* g,
+                            const int n,
+                            const double step
+                          ) {
+  //the solver context is provided as the instance
+  LBFGS* s = (LBFGS*) instance ;
+
+  //the objective function is a member
+  ObjFun* objfun = (ObjFun*) s->objfun_ ;
+
+  //call the callback
+  LBFGS::EvalData data = {x, g, n, step} ;
+  const double result = (*objfun)(&data) ;
+  return result ;
+}
+
+} //end of namespace Solver
+} //end of namespace Revoropt
+
+#endif
+
diff --git a/contrib/Revoropt/include/Revoropt/Tools/.gitignore b/contrib/Revoropt/include/Revoropt/Tools/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..14ec01aa8f8b5467c00b49e07600ae6180f8fa6b
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/.gitignore
@@ -0,0 +1 @@
+disjoint_sets.os
diff --git a/contrib/Revoropt/include/Revoropt/Tools/color.hpp b/contrib/Revoropt/include/Revoropt/Tools/color.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..e801d67caf3d33d590c72a9212ef72e6b670c6a8
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/color.hpp
@@ -0,0 +1,73 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_TOOLS_COLOR_HPP_
+#define _REVOROPT_TOOLS_COLOR_HPP_
+
+#include <cstdlib>
+
+namespace Revoropt {
+
+//generate random bright colors
+template<typename Scalar>
+void random_bright_color(Scalar* output) {
+  //random hsv with value 1
+  Scalar h = (Scalar) rand() / (Scalar) RAND_MAX ;
+  h *= 6 ;
+  Scalar s = (Scalar) rand() / (Scalar) RAND_MAX ;
+  s = 0.5*s + 0.5 ;
+  Scalar v = (Scalar) rand() / (Scalar) RAND_MAX ;
+  v = 0.5*v+0.5 ;
+
+  int hi = (int) h ;
+  Scalar hr = h - hi ;
+
+  Scalar l = v*(1-s) ;
+  Scalar m = v*(1-hr*s);
+  Scalar n = v*(1-(1-hr)*s);
+
+  if(h<1) {
+    output[0] = v ;
+    output[1] = n ;
+    output[2] = l ;
+  } else if(h<2) {
+    output[0] = m ;
+    output[1] = v ;
+    output[2] = l ;
+  } else if(h<3) {
+    output[0] = l ;
+    output[1] = v ;
+    output[2] = n ;
+  } else if(h<4) {
+    output[0] = l ;
+    output[1] = m ;
+    output[2] = v ;
+  } else if(h<5) {
+    output[0] = n ;
+    output[1] = l ;
+    output[2] = v ;
+  } else {
+    output[0] = v ;
+    output[1] = l ;
+    output[2] = m ;
+  }
+}
+
+//generate bright colormaps
+template<typename Scalar>
+void generate_bright_colormap(unsigned int size, Scalar* output) {
+  for(unsigned int i = 0; i < size; ++i) {
+    random_bright_color(output + 3*i) ;
+  }
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/combinatorics.hpp b/contrib/Revoropt/include/Revoropt/Tools/combinatorics.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..cec40053601b657ecfd82fb7aca2453ae6a1ddd6
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/combinatorics.hpp
@@ -0,0 +1,201 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_TOOLS_COMBINATORICS_HPP_
+#define _REVOROPT_TOOLS_COMBINATORICS_HPP_
+
+#include "meta.hpp"
+#include "hash.hpp"
+
+#include <algorithm>
+#include <iostream>
+#include <type_traits>
+#include <functional>
+
+namespace Revoropt {
+
+namespace tuplekey_impl {
+
+//Dummy class and operator << to declare a friend function for 
+//tuplekey_base when the provided type has no operator<<
+
+struct dummy {} ;
+
+template<int size, typename T>
+std::ostream& operator<<(std::ostream&, const dummy&) ;
+
+//Forward declarations
+
+template<int size, typename T>
+class tuplekey_base ;
+
+template<int size, typename T>
+typename std::enable_if<is_printable<T>::value,std::ostream>::type& operator<<(
+  std::ostream&, const tuplekey_base<size,T>&
+) ;
+
+//Base class for tuple keys (elements in the tuple are sorted)
+template<int _size, typename _T>
+class tuplekey_base {
+  public :
+
+    /* Typedefs */
+    enum { size = _size } ;
+    typedef _T T ;
+
+    /* Construction */
+    tuplekey_base() {} ; //only here to allocate arrays of tuplekeys
+
+    tuplekey_base(const T data[size]) {
+      std::copy(data, data+size, vals) ;
+      std::sort(vals, vals+size) ;
+    }
+
+    /* Printing if operator<< is defined for T */
+    friend std::ostream& operator<<<size,T>( 
+      std::ostream& os, 
+      const typename std::conditional< 
+          is_printable<T>::value,
+          tuplekey_base<size,T>,
+          dummy
+        >::type& key 
+    ) ; 
+
+    /* Comparison */
+    bool operator<(const tuplekey_base& rhs) const {
+      for(unsigned int i = 0; i < size; ++i) {
+        if((vals[i] < rhs.vals[i]) || (rhs.vals[i] < vals[i])) {
+          return vals[i] < rhs.vals[i] ;
+        }
+      }
+      return false ;
+    }
+
+    bool operator==(const tuplekey_base& rhs) const {
+      return !((rhs < *this) || (*this < rhs)) ;
+    }
+
+    /* Values */
+    const T& operator[]( unsigned int i ) const { return vals[i] ; }
+
+    const T* values() const { return vals ; }
+
+    T vals[size] ;
+} ;
+
+
+/* Printing tuples */
+template<int size, typename T>
+typename std::enable_if<is_printable<T>::value,std::ostream>::type& operator<<( 
+  std::ostream& os, 
+  const tuplekey_base<size,T>& key 
+) {
+  os << "[ " ;
+  for(int i = 0; i < size; ++i) {
+    os << key.vals[i] << " " ;
+  }
+  os << "]" ;
+}
+
+} //end of namespace tuplekey_impl
+
+
+/* General tuple key (for any number of elements) */
+template<int size, typename T=unsigned int>
+class tuplekey : public tuplekey_impl::tuplekey_base<size,T> {
+  typedef tuplekey_impl::tuplekey_base<size,T> Base ;
+  public:
+  tuplekey() : Base() {}
+  tuplekey(const T data[size]) : Base(data) {}
+} ;
+
+/* Specialization for couples */
+template<typename T>
+class tuplekey<2,T> : public tuplekey_impl::tuplekey_base<2,T> {
+  /* Typedefs */
+  typedef tuplekey_impl::tuplekey_base<2,T> Base ;
+  using Base::vals ;
+
+  public:
+
+  /* Basic construction */
+  tuplekey() : Base() {}
+  tuplekey(const T data[2]) : Base(data) {}
+
+  /* Construction from a pair of values */
+  tuplekey(const T &v1, const T &v2) {
+    vals[0] = v1 < v2 ? v1 : v2 ;
+    vals[1] = v1 < v2 ? v2 : v1 ;
+  }
+
+  /* Values */
+  const T& min() const { return vals[0] ; }
+  const T& max() const { return vals[1] ; }
+
+} ;
+
+/* Specialization for triples */
+template<typename T>
+class tuplekey<3,T> : public tuplekey_impl::tuplekey_base<3,T> {
+  /* Typedefs */
+  typedef tuplekey_impl::tuplekey_base<3,T> Base ;
+  using Base::vals ;
+
+  public:
+
+  /* Basic construction */
+  tuplekey() : Base() {}
+  tuplekey(const T data[3]) : Base(data) {}
+
+  /* Construction from a triplet of values */
+  tuplekey(const T &v1, const T &v2, const T &v3) {
+    if(v1 < v2) {
+      vals[0] = v1 ;
+      vals[1] = v2 ;
+    } else {
+      vals[0] = v2 ;
+      vals[1] = v1 ;
+    }
+    if(vals[1] < v3) {
+      vals[2] = v3 ;
+    } else if (vals[0] < v3) {
+      vals[2] = vals[1] ;
+      vals[1] = v3 ;
+    } else {
+      vals[2] = vals[1] ;
+      vals[1] = vals[0] ;
+      vals[0] = v3 ;
+    }
+  }
+
+  /* Values */
+  const T& min() const { return vals[0] ; }
+  const T& mid() const { return vals[1] ; }
+  const T& max() const { return vals[2] ; }
+} ;
+
+/* Hashing */
+
+template <int size, typename T = unsigned int>
+class tuple_hash {
+  public :
+
+  std::size_t operator()( const tuplekey<size, T>& tuple ) const {
+    std::size_t seed = 0 ;
+    for(int i = 0; i < size; ++i) {
+      hash_combine(seed, tuple[i])  ;
+    }
+    return seed ;
+  }
+} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/command_line.h b/contrib/Revoropt/include/Revoropt/Tools/command_line.h
new file mode 100644
index 0000000000000000000000000000000000000000..e12f96a85d5355d9789d219c115fb7e4b249a3b5
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/command_line.h
@@ -0,0 +1,60 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+
+#ifndef _REVOROPT_COMMAND_LINE_H_
+#define _REVOROPT_COMMAND_LINE_H_
+
+#include <algorithm>
+#include <string>
+#include <sstream>
+
+namespace Revoropt {
+
+char* get_cmd_option( char ** begin, char ** end, 
+                      const std::string & option
+                    ) {
+    char ** itr = std::find(begin, end, "--" + option);
+    if (itr != end && ++itr != end)
+    {
+        return *itr;
+    }
+    return 0;
+}
+
+bool cmd_option_exists( char** begin, char** end, 
+                        const std::string& option
+                      ) {
+    return std::find(begin, end, "--" + option) != end;
+}
+
+template<typename T>
+bool get_cmd_value(
+    char ** begin, 
+    char** end, 
+    const std::string& option,
+    T* output
+    ) {
+  if(cmd_option_exists(begin, end, option)) {
+    std::stringstream ss ;
+    ss << get_cmd_option(begin, end, option) ;
+    T t ;
+    ss >> t ;
+    if(!ss.fail()) {
+      *output = t ;
+      return true ;
+    }
+  }
+  return false ;
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/container_wrapper.hpp b/contrib/Revoropt/include/Revoropt/Tools/container_wrapper.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..81a43531ef313f26f4c035c2d79650978a199c78
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/container_wrapper.hpp
@@ -0,0 +1,1227 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_TOOLS_CONTAINER_WRAPPER_HPP_
+#define _REVOROPT_TOOLS_CONTAINER_WRAPPER_HPP_
+
+#include "meta.hpp"
+
+#include <iterator>
+#include <cassert>
+#include <list>
+#include <type_traits>
+
+namespace Revoropt {
+
+/* This is nasty stuff to be used with caution */
+
+/* Base class to be able to merge various similar iterators */
+
+/* The idea of this class is that it does not fulfill the requirements of
+ * iterators, but that real iterators can be built from it. First, we wrap the
+ * comparison between iterators using the address of the thing pointed to. This
+ * will allow us to compare different iterator types. By convention, this
+ * address will be NULL for past-the-end iterators Beware however that two
+ * iterators pointing to the same object will be equal once wrapped. The return
+ * type of incr is void, which allows it to be easily virtual, whereas classical
+ * operator++ for iterators return instances of the class itself which makes it
+ * difficult for virtual functions. The copy_to method will be used to be able
+ * to implement operator= on iterators built upon this class. */
+
+template<typename T>
+class SimiliIterator ;
+
+//case of iterators pointing to const values
+template<typename T>
+class SimiliIterator<const T> {
+
+  public :
+
+    /* Construction */
+    SimiliIterator() : address_(NULL) {} ;
+    SimiliIterator( const T* address ) : address_(address) {} ;
+
+    /* Destruction */
+    virtual ~SimiliIterator() {} ;
+    
+    /* Incrementation */
+    /* has to be implemented and update the protected fields */
+
+    virtual void incr() = 0 ;
+
+    /* Deep copy */
+    
+    virtual void copy_to( SimiliIterator<const T>** target ) const = 0 ;
+
+    /* Comparison */ 
+    /* only compares addresses, therefore any two iterators pointing to the same
+     * element are identical. */
+
+    bool operator==(const SimiliIterator& rhs) const {
+      return address_ == rhs.address_ ;
+    }; 
+    bool operator==(const SimiliIterator<T>& rhs) const {
+      return address_ == rhs.address_ ;
+    }; 
+    bool operator!=(const SimiliIterator& rhs) const {
+      return address_ != rhs.address_ ;
+    };
+    bool operator!=(const SimiliIterator<T>& rhs) const {
+      return address_ != rhs.address_ ;
+    };
+
+    /* Dereferencement */
+    /* Beware not to dereference past_the_end iterators */
+    const T& operator*() const {
+      return *address_ ;
+    };
+
+  protected :
+
+    /* address to the element pointed to. NULL if past_the_end */
+    const T* address_ ;
+    
+} ;
+
+/* inheritance allows conversion from values to const values */
+template<typename T>
+class SimiliIterator : public SimiliIterator<const T> {
+
+  public :
+
+    /* Construction */
+    SimiliIterator() : SimiliIterator<const T>() {} ;
+    SimiliIterator( T* address ) : SimiliIterator<const T>(address) {} ;
+
+    /* Destruction */
+    virtual ~SimiliIterator() {} ;
+
+    /* Deep copy */
+    
+    virtual void copy_to( SimiliIterator<T>** target ) const = 0 ;
+    virtual void copy_to( SimiliIterator<const T>** target ) const = 0 ;
+
+    /* Dereferencement */
+    /* Beware not to dereference past_the_end iterators */
+    T& operator*() {
+      return *const_cast<T*>(SimiliIterator<const T>::address_) ;
+    };
+} ;
+
+/* End iterator, use to check the past_the_end status */
+
+/* Since SimiliIterators store a pointer to the value pointed to, and that this
+ * pointer is NULL for past-the-end iterators, all wrapped past the end iterators 
+ * will compare equal to that one. */
+template<typename T>
+class EndIterator : public SimiliIterator<T> {
+
+  public :
+
+    /* Construction */
+    EndIterator() : SimiliIterator<T>() {} ;
+
+    /* Incrementation */
+    void incr() {} ;
+
+    /* Deep copy */
+    void copy_to(SimiliIterator<T>** target) const {
+      *target = new EndIterator() ;
+    }
+    void copy_to(SimiliIterator<const T>** target) const {
+      *target = new EndIterator<const T>() ;
+    }
+} ;
+
+template<typename T>
+class EndIterator<const T> : public SimiliIterator<const T> {
+
+  public :
+
+    /* Construction */
+    EndIterator() : SimiliIterator<const T>() {} ;
+
+    /* Incrementation */
+    void incr() {} ;
+
+    /* Deep copy */
+    void copy_to(SimiliIterator<const T>** target) const {
+      *target = new EndIterator() ;
+    }
+} ;
+
+/* Wrapping container iterators */
+
+/* We now describe how to generate SimiliIterators from usual InputIterators. */
+
+template<typename InputIterator, typename Enable = void>
+class IteratorWrapper ;
+
+/* This enable_if ensures that this class only gets instantiated whenever the
+ * provided iterator is not on a const type. Without doing this trick, the
+ * problem is that we have to instantiate the two versions of the copy_to
+ * function, one to copy to a SimiliIterator<const T>, and one to copy to a
+ * SimiliIterator<T>. However, since const const T is const T, the two function
+ * prototypes end up identical, which fails as an invalid overload. */
+template<typename InputIterator>
+class IteratorWrapper<
+  InputIterator,
+  typename std::enable_if<
+    !std::is_const<typename one_deref_type<InputIterator>::type>::value
+  >::type
+> : 
+  public SimiliIterator<
+    typename one_deref_type<InputIterator>::type
+  > 
+{
+
+    /* Backend iterator type */
+    typedef InputIterator iterator ;
+    /* Iterator dereference type */
+    typedef typename one_deref_type<iterator>::type T ;
+ 
+  protected :
+ 
+    /* Iterator references */
+    iterator it_ ;
+    iterator end_ ;
+
+  public :
+
+    /* Construction */
+
+    IteratorWrapper( const iterator& it, const iterator& end ) : 
+      it_(it), end_(end) {
+      if(it_ != end_) {
+        SimiliIterator<T>::address_ = &(*it_) ;
+      }
+    }
+    IteratorWrapper( 
+      const IteratorWrapper<iterator>& rhs 
+    ) : it_(rhs.it_), end_(rhs.end_) {
+      if(it_ != end_) {
+        SimiliIterator<T>::address_ = &(*it_) ;
+      }
+    }
+
+    /* Incrementation */
+
+    void incr() {
+      if(it_ != end_) {
+        if(++it_ != end_) {
+          SimiliIterator<T>::address_ = &(*it_) ;
+        } else {
+          SimiliIterator<T>::address_ = NULL ;
+        }
+      }
+    }
+
+    /* Copy */
+
+    void copy_to( SimiliIterator<T>** target ) const {
+      *target = new IteratorWrapper<iterator>(*this) ;
+    }
+
+    void copy_to( SimiliIterator<const T>** target ) const {
+      *target = new IteratorWrapper<iterator>(*this) ;
+    }
+
+} ;
+
+/* This one only gets instantiated if InputIterator is on a const type. */
+template<typename InputIterator>
+class IteratorWrapper<
+  InputIterator,
+  typename std::enable_if<
+    std::is_const<typename one_deref_type<InputIterator>::type>::value
+  >::type
+> : 
+  public SimiliIterator<
+    typename one_deref_type<InputIterator>::type
+  > 
+{
+
+    /* Backend iterator type */
+    typedef InputIterator iterator ;
+    /* Iterator dereference type */
+    typedef typename one_deref_type<iterator>::type T ;
+ 
+  protected :
+ 
+    /* Iterator references */
+    iterator it_ ;
+    iterator end_ ;
+
+  public :
+
+    /* Construction */
+
+    IteratorWrapper( const iterator& it, const iterator& end ) : 
+      it_(it), end_(end) {
+      if(it_ != end_) {
+        SimiliIterator<T>::address_ = &(*it_) ;
+      }
+    }
+    IteratorWrapper( 
+      const IteratorWrapper<iterator>& rhs 
+    ) : it_(rhs.it_), end_(rhs.end_) {
+      if(it_ != end_) {
+        SimiliIterator<T>::address_ = &(*it_) ;
+      }
+    }
+
+    /* Incrementation */
+
+    void incr() {
+      if(it_ != end_) {
+        if(++it_ != end_) {
+          SimiliIterator<T>::address_ = &(*it_) ;
+        } else {
+          SimiliIterator<T>::address_ = NULL ;
+        }
+      }
+    }
+
+    /* Copy */
+
+    void copy_to( SimiliIterator<T>** target ) const {
+      *target = new IteratorWrapper<iterator>(*this) ;
+    }
+} ;
+
+/* Flattening container iterators : returning the fully dereferenced value */
+
+/* This wrapper aims at transforming a container on pointers to iterators to ...
+ * on a type T into a container on T, applying as many dereferencements
+ * necessary on the elements of the container to reach the non dereferenceable
+ * type. */
+template<typename InputIterator, typename Enable = void>
+class IteratorFlattener ;
+
+/* The same enable_if is used as previously, except that the type of the fully
+ * dereferenced iterator is used instead. This case is on non const final type. 
+ * */
+template<typename InputIterator>
+class IteratorFlattener<
+  InputIterator,
+  typename std::enable_if<
+    !std::is_const<typename full_deref_type<InputIterator>::type>::value
+  >::type
+>: 
+  public SimiliIterator<
+    typename full_deref_type<InputIterator>::type
+  >
+{
+
+    /* Backend iterator type */
+    typedef InputIterator iterator ;
+    /* Iterator dereference type */
+    typedef typename full_deref_type<iterator>::type T ;
+ 
+  protected :
+ 
+    /* Iterator references */
+    iterator it_ ;
+    iterator end_ ;
+
+  public :
+
+    /* Construction */
+
+    IteratorFlattener( const iterator& it, const iterator& end ) : 
+      it_(it), end_(end) {
+      if(it_ != end_) {
+        SimiliIterator<T>::address_ = &(full_deref(it_)) ;
+      }
+    }
+    IteratorFlattener( 
+      const IteratorFlattener<iterator>& rhs 
+    ) : it_(rhs.it_), end_(rhs.end_) {
+      if(it_ != end_) {
+        SimiliIterator<T>::address_ = &(full_deref(it_)) ;
+      }
+    }
+
+    /* Incrementation */
+
+    void incr() {
+      if(it_ != end_) {
+        if(++it_ != end_) {
+          SimiliIterator<T>::address_ = &(full_deref(it_)) ;
+        } else {
+          SimiliIterator<T>::address_ = NULL ;
+        }
+      }
+    }
+
+    /* Copy */
+
+    void copy_to( SimiliIterator<T>** target ) const {
+      *target = new IteratorFlattener<iterator>(*this) ;
+    }
+
+    void copy_to( SimiliIterator<const T>** target ) const {
+      *target = new IteratorFlattener<iterator>(*this) ;
+    }
+
+} ;
+
+/* Case for const final type */
+template<typename InputIterator>
+class IteratorFlattener<
+  InputIterator,
+  typename std::enable_if<
+    std::is_const<typename full_deref_type<InputIterator>::type>::value
+  >::type
+>: 
+  public SimiliIterator<
+    typename full_deref_type<InputIterator>::type
+  >
+{
+
+    /* Backend iterator type */
+    typedef InputIterator iterator ;
+    /* Iterator dereference type */
+    typedef typename full_deref_type<iterator>::type T ;
+ 
+  protected :
+ 
+    /* Iterator references */
+    iterator it_ ;
+    iterator end_ ;
+
+  public :
+
+    /* Construction */
+
+    IteratorFlattener( const iterator& it, const iterator& end ) : 
+      it_(it), end_(end) {
+      if(it_ != end_) {
+        SimiliIterator<T>::address_ = &(full_deref(it_)) ;
+      }
+    }
+    IteratorFlattener( 
+      const IteratorFlattener<iterator>& rhs 
+    ) : it_(rhs.it_), end_(rhs.end_) {
+      if(it_ != end_) {
+        SimiliIterator<T>::address_ = &(full_deref(it_)) ;
+      }
+    }
+
+    /* Incrementation */
+
+    void incr() {
+      if(it_ != end_) {
+        if(++it_ != end_) {
+          SimiliIterator<T>::address_ = &(full_deref(it_)) ;
+        } else {
+          SimiliIterator<T>::address_ = NULL ;
+        }
+      }
+    }
+
+    /* Copy */
+
+    void copy_to( SimiliIterator<T>** target ) const {
+      *target = new IteratorFlattener<iterator>(*this) ;
+    }
+
+} ;
+
+/* Generic iterator, based on a SimiliIterator */
+
+/* We now build true iterators, fulfilling the stl requirements on iterators. To
+ * do so, and to use virtual functions on SimiliIterators, we need to use
+ * pointers on these. A Generic Iterator is therefore responsible of the memory
+ * allocated to the SimiliIterator it is built upon, even though the allocation
+ * is not done by the class itself. */
+
+/* Iterator on non const types */
+template<typename T>
+class GenericIterator : 
+  public std::iterator<std::input_iterator_tag,T> 
+{
+
+    friend class GenericIterator<const T> ;
+  
+    //The generic iterator is responsible for the memory allocated for its
+    //iterator, and will free this memory upon destruction.
+    SimiliIterator<T>* it_ ;
+
+  public :
+
+    /* Construction */
+
+    GenericIterator() : it_(NULL) {
+    }
+    GenericIterator( SimiliIterator<T>* it ) : it_(it) {
+    }
+    GenericIterator( const GenericIterator& rhs ) {
+      rhs.it_->copy_to(&it_) ;
+    }
+
+    /* Assignment */
+    GenericIterator& operator=( const GenericIterator& rhs ) {
+      delete it_ ;
+      rhs.it_->copy_to(&it_) ;
+      return *this ;
+    }
+
+    /* Destruction */
+    virtual ~GenericIterator() { 
+      delete it_ ; 
+    }
+
+    /* Incrementation */
+    GenericIterator& operator++() { 
+      it_->incr(); 
+      return *this ; 
+    }
+    GenericIterator operator++(int) { 
+      GenericIterator tmp(*this) ; 
+      it_->incr(); 
+      return tmp ; 
+    }
+
+    /* Comparison */
+    bool operator==( const GenericIterator& rhs ) const {
+      return *it_ == *(rhs.it_) ;
+    }
+    bool operator==( const GenericIterator<const T>& rhs ) const {
+      return rhs == *this ;
+    }
+
+    bool operator!=( const GenericIterator& rhs ) const {
+      return *it_ != *(rhs.it_) ;
+    }
+    bool operator!=( const GenericIterator<const T>& rhs ) const {
+      return rhs != *this ;
+    }
+
+    /* Dereferencement */
+    T& operator*() {
+      return **it_ ;
+    }
+    const T& operator*() const {
+      return **it_ ;
+    }
+    T* operator->() {
+      return &(**it_) ;
+    }
+    const T* operator->() const {
+      return &(**it_) ;
+    }
+
+} ;
+
+/* Iterator on const types */
+template<typename T>
+class GenericIterator<const T> : 
+  public std::iterator<std::input_iterator_tag,const T> 
+{
+
+  friend class GenericIterator<T> ;
+  
+    //The generic iterator is responsible for the memory allocated for its
+    //iterator, and will free this memory upon destruction.
+    SimiliIterator<const T>* it_ ;
+
+  public :
+
+    /* Construction */
+
+    GenericIterator() : it_(NULL) {
+    }
+    GenericIterator( SimiliIterator<const T>* it ) : it_(it) {
+    }
+    GenericIterator( SimiliIterator<T>* it ) : it_(it) {
+    }
+    GenericIterator( const GenericIterator& rhs ) {
+      rhs.it_->copy_to(&it_) ;
+    }
+    GenericIterator( const GenericIterator<T>& rhs ) {
+      rhs.it_->copy_to(&it_) ;
+    }
+
+    /* Assignment */
+    GenericIterator& operator=( const GenericIterator& rhs ) {
+      delete it_ ;
+      rhs.it_->copy_to(&it_) ;
+      return *this ;
+    }
+    GenericIterator& operator=( const GenericIterator<T>& rhs ) {
+      delete it_ ;
+      rhs.it_->copy_to(&it_) ;
+      return *this ;
+    }
+
+    /* Destruction */
+    virtual ~GenericIterator() { 
+      delete it_ ; 
+    }
+
+    /* Incrementation */
+    GenericIterator& operator++() { 
+      it_->incr(); 
+      return *this ; 
+    }
+    GenericIterator operator++(int) { 
+      GenericIterator tmp(*this) ; 
+      it_->incr(); 
+      return tmp ; 
+    }
+
+    /* Comparison */
+    bool operator==( const GenericIterator& rhs ) const {
+      return *it_ == *(rhs.it_) ;
+    }
+    bool operator==( const GenericIterator<T>& rhs ) const {
+      return *it_ == *(rhs.it_) ;
+    }
+
+    bool operator!=( const GenericIterator& rhs ) const {
+      return *it_ != *(rhs.it_) ;
+    }
+    bool operator!=( const GenericIterator<T>& rhs ) const {
+      return *it_ != *(rhs.it_) ;
+    }
+
+    /* Dereferencement */
+    const T& operator*() const {
+      return **it_ ;
+    }
+    const T* operator->() const {
+      return &(**it_) ;
+    }
+
+} ;
+
+
+/* Generic container, to wrap many existing containers */
+
+/* Now that we can wrap container iterators with a common parent class and build
+ * generic iterators from this class, we can focus on wrapping containers as
+ * well with a common parent class. The following class is this parent class.
+ * Its idea is to only care about providing an input iterator on the content. */
+
+template<typename T>
+class GenericContainer ;
+
+/* Container on const values */
+template<typename T>
+class GenericContainer<const T> {
+  
+  public :
+
+    /* Destruction */
+    virtual ~GenericContainer() {} ;
+
+    /* Typedefs */
+    typedef GenericIterator<T> iterator ;
+    typedef GenericIterator<const T> const_iterator ;
+
+    /* Iteration */
+    virtual const_iterator begin() const = 0 ;
+
+    virtual const_iterator end() const = 0 ;
+} ;
+
+/* Container on non const values. The inheritance ensures the conversion to a
+ * container on const values. */
+template<typename T>
+class GenericContainer : public GenericContainer<const T> {
+  
+  public :
+
+    /* Destruction */
+    virtual ~GenericContainer() {} ;
+
+    /* Typedefs */
+    typedef GenericIterator<T> iterator ;
+    typedef GenericIterator<const T> const_iterator ;
+
+    /* Iteration */
+    virtual iterator begin() = 0 ;
+    virtual const_iterator begin() const = 0 ;
+
+    virtual iterator end() = 0 ;
+    virtual const_iterator end() const = 0 ;
+} ;
+
+/* We now wrap usual containers as GenericContainers */
+
+/* Case for stl containers */
+template<typename Container>
+class ContainerWrapper : 
+  public GenericContainer<typename Container::value_type> 
+{
+
+    Container &c ;
+
+    /* Typedefs */
+    typedef IteratorWrapper<
+      typename Container::iterator
+    > internal_iterator ;
+    typedef IteratorWrapper<
+      typename Container::const_iterator
+    > internal_const_iterator ;
+  
+  public :
+
+    /* Typedefs */
+    typedef typename Container::value_type value_type ;
+    typedef GenericIterator<value_type> iterator ;
+    typedef GenericIterator<const value_type> const_iterator ;
+
+    /* Construction, destruction */
+    ContainerWrapper(Container& _c) : c(_c) {}
+    virtual ~ContainerWrapper() {} ;
+
+    /* Iteration */
+    iterator begin() {
+      return iterator(new internal_iterator(c.begin(), c.end())) ;
+    }
+    const_iterator begin() const {
+      return const_iterator(new internal_const_iterator(c.begin(), c.end())) ;
+    };
+
+    iterator end() {
+      return iterator(new internal_iterator(c.end(),c.end())) ;
+    };
+    const_iterator end() const {
+      return const_iterator(new internal_const_iterator(c.end(),c.end())) ;
+    };
+} ;
+
+/* Case for usual arrays */
+template<typename T>
+class ContainerWrapper<T*> : 
+  public GenericContainer<T> 
+{
+
+    T* begin_ ; 
+    T* end_ ;
+
+    /* Typedefs */
+    typedef IteratorWrapper<
+      T *
+    > internal_iterator ;
+    typedef IteratorWrapper<
+      T const *
+    > internal_const_iterator ;
+  
+  public :
+
+    /* Typedefs */
+    typedef T value_type ;
+    typedef GenericIterator<value_type> iterator ;
+    typedef GenericIterator<const value_type> const_iterator ;
+
+    /* Construction, destruction */
+    ContainerWrapper(T* begin, T* end) : begin_(begin), end_(end) {}
+    virtual ~ContainerWrapper() {} ;
+
+    /* Iteration */
+    iterator begin() {
+      return iterator(new internal_iterator(begin_, end_)) ;
+    }
+    const_iterator begin() const {
+      return const_iterator(new internal_const_iterator(begin_, end_)) ;
+    };
+
+    iterator end() {
+      return iterator(new internal_iterator(end_, end_)) ;
+    };
+    const_iterator end() const {
+      return const_iterator(new internal_const_iterator(end_, end_)) ;
+    };
+} ;
+
+/* Container Flattener for stl like containers */
+/* Virtually transforms a vector of pointers chains to a container 
+ * containing the fully dereferenced elements. */
+
+/* Case for stl containers */
+template<typename Container>
+class ContainerFlattener : 
+  public GenericContainer<
+    typename full_deref_type<typename Container::value_type>::type
+  >
+{
+
+    Container &c ;
+
+    /* Typedefs */
+    typedef IteratorFlattener<
+      typename Container::iterator
+    > internal_iterator ;
+    typedef IteratorFlattener<
+      typename Container::const_iterator
+    > internal_const_iterator ;
+  
+  public :
+
+    /* Typedefs */
+    typedef typename full_deref_type<
+      typename Container::value_type
+    >::type value_type ;
+    typedef GenericIterator<value_type> iterator ;
+    typedef GenericIterator<const value_type> const_iterator ;
+
+    /* Construction, destruction */
+    ContainerFlattener(Container& _c) : c(_c) {}
+    virtual ~ContainerFlattener() {}
+
+    /* Iteration */
+    iterator begin() {
+      return iterator(new internal_iterator(c.begin(), c.end())) ;
+    }
+    const_iterator begin() const {
+      return const_iterator(new internal_const_iterator(c.begin(), c.end())) ;
+    };
+
+    iterator end() {
+      return iterator(new internal_iterator(c.end(),c.end())) ;
+    };
+    const_iterator end() const {
+      return const_iterator(new internal_const_iterator(c.end(),c.end())) ;
+    };
+} ;
+
+/* Case for usual arrays */
+template<typename T>
+class ContainerFlattener<T*> : 
+  public GenericContainer<
+    typename full_deref_type<T>::type
+  >
+{
+
+    T* begin_ ;
+    T* end_ ;
+
+    /* Typedefs */
+    typedef IteratorFlattener<
+      T *
+    > internal_iterator ;
+    typedef IteratorFlattener<
+      T const *
+    > internal_const_iterator ;
+  
+  public :
+
+    /* Typedefs */
+    typedef typename full_deref_type<T>::type value_type ;
+    typedef GenericIterator<value_type> iterator ;
+    typedef GenericIterator<const value_type> const_iterator ;
+
+    /* Construction, destruction */
+    ContainerFlattener(T* begin, T* end) : begin_(begin), end_(end) {}
+    virtual ~ContainerFlattener() {}
+
+    /* Iteration */
+    iterator begin() {
+      return iterator(new internal_iterator(begin_, end_)) ;
+    }
+    const_iterator begin() const {
+      return const_iterator(new internal_const_iterator(begin_, end_)) ;
+    };
+
+    iterator end() {
+      return iterator(new internal_iterator(end_, end_)) ;
+    };
+    const_iterator end() const {
+      return const_iterator(new internal_const_iterator(end_, end_)) ;
+    };
+} ;
+
+/* Container merging */
+
+/* Using the GenericContainer class, several containers of various types can now
+ * be merged together. We first create the iterator type that we be able to
+ * iterate on the elements of a sequence of containers. */
+
+/* Composite iterator */
+
+/* The composite iterator takes a sequence of GenericContainers, and passes from
+ * one container to the other when the end of the first container is reached.*/
+
+/* Case for non const values */
+template<typename T>
+class CompositeIterator : 
+  public std::iterator<std::input_iterator_tag,T> 
+{
+
+  friend class CompositeIterator<const T> ;
+
+  public :
+   
+    /* Typedefs */
+    typedef GenericIterator<T> iterator ;
+    typedef typename std::list<
+      GenericContainer<T>*
+    >::iterator sub_iterator ;
+    typedef typename std::list<
+      GenericContainer<T>*
+    >::const_iterator const_sub_iterator ;
+
+    /* Construction */
+
+    CompositeIterator() : end_(new EndIterator<T>), 
+                          inner_it_(end_), 
+                          outer_it_(containers_.end()) {
+    }
+    CompositeIterator( const CompositeIterator& rhs ) : 
+      end_(new EndIterator<T>) 
+    {
+      *this = rhs ;
+    }
+
+    sub_iterator push_back( GenericContainer<T>* c ) {
+      //we need to ensure that we point to the first value
+      //even when empty containers are provided
+      if(inner_it_ == end_) {
+        containers_.push_back(c) ;
+        outer_it_ = --containers_.end() ;
+        inner_it_ = c->begin() ;
+      } else {
+        containers_.push_back(c) ;
+      }
+      return --containers_.end() ;
+    }
+
+
+    /* Assignment */
+    CompositeIterator& operator=( const CompositeIterator& rhs ) {
+      //copy the inner iterator
+      inner_it_ = rhs.inner_it_ ;
+      //copy the container sequence
+      containers_.clear() ;
+      typedef typename CompositeIterator<T>::const_sub_iterator rhs_iterator ;
+      for( rhs_iterator it = rhs.containers_.begin(); 
+           it != rhs.containers_.end(); 
+           ++it 
+         ) {
+        push_back(*it) ;
+        if(it == rhs.outer_it_) {
+          //replace the outer iterator to the right position in the sequence
+          outer_it_ = --containers_.end() ;
+        }
+      }
+      if(rhs.outer_it_ == rhs.containers_.end()) {
+        //handle the case when rhs is past-the-end
+        outer_it_ = containers_.end() ;
+      }
+      return *this ;
+    }
+
+    /* Incrementation */
+    CompositeIterator& operator++() { 
+      ++inner_it_ ; 
+      while(inner_it_ == end_) {
+        //we pass over the empty arrays here
+        ++outer_it_ ;
+        if(outer_it_ != containers_.end()) {
+          inner_it_ = (*outer_it_)->begin() ;
+        } else {
+          break ;
+        }
+      }
+      return *this ; 
+    }
+    CompositeIterator operator++(int) { 
+      CompositeIterator tmp(*this) ; 
+      this->operator++() ; 
+      return tmp ; 
+    }
+
+    /* Comparison */
+    bool operator==( const CompositeIterator& rhs ) const {
+      return inner_it_ == rhs.inner_it_ ;
+    }
+    bool operator==( const CompositeIterator<const T>& rhs ) const {
+      return inner_it_ == rhs.inner_it_ ;
+    }
+
+    bool operator!=( const CompositeIterator& rhs ) const {
+      return inner_it_ != rhs.inner_it_ ;
+    }
+    bool operator!=( const CompositeIterator<const T>& rhs ) const {
+      return inner_it_ != rhs.inner_it_ ;
+    }
+
+    /* Dereferencement */
+    T& operator*() {
+      return *inner_it_ ;
+    }
+    const T& operator*() const {
+      return *inner_it_ ;
+    }
+    T* operator->() {
+      return &(*inner_it_) ;
+    }
+    const T* operator->() const {
+      return &(*inner_it_) ;
+    }
+
+  private :
+
+    /* global end iterator */
+    iterator end_ ;
+
+    /* current inner iterator */
+    iterator inner_it_ ;
+
+    /* store a list of generic iterators to concatenate */
+    std::list<GenericContainer<T>*> containers_ ;
+
+    /* current outer_iterator_ */
+    sub_iterator outer_it_ ;
+
+} ;
+
+/* Case for const values */
+template<typename T>
+class CompositeIterator<const T> :
+  public std::iterator<std::input_iterator_tag,const T> 
+{
+ 
+  friend class CompositeIterator<T> ;
+
+  public :
+   
+    /* Typedefs */
+    typedef GenericIterator<const T> iterator ;
+    typedef typename std::list<
+      const GenericContainer<const T>*
+    >::const_iterator sub_iterator ;
+
+    /* Construction */
+
+    CompositeIterator() : end_(new EndIterator<const T>), 
+                          inner_it_(end_), 
+                          outer_it_(containers_.end()) {
+    }
+    CompositeIterator( const CompositeIterator& rhs ) : 
+      end_(new EndIterator<const T>) 
+    {
+      *this = rhs ;
+    }
+    CompositeIterator( const CompositeIterator<T>& rhs ) : 
+      end_(new EndIterator<T>) 
+    {
+      *this = rhs ;
+    }
+
+    sub_iterator push_back( const GenericContainer<const T>* c ) {
+      //we need to ensure that we point to the first value
+      //even when empty containers are provided
+      if(inner_it_ == end_) {
+        containers_.push_back(c) ;
+        outer_it_ = --containers_.end() ;
+        inner_it_ = c->begin() ;
+      } else {
+        containers_.push_back(c) ;
+      }
+      return --containers_.end() ;
+    }
+
+
+    /* Assignment */
+    CompositeIterator& operator=( const CompositeIterator& rhs ) {
+      //copy the inner iterator
+      inner_it_ = rhs.inner_it_ ;
+      //copy the container sequence
+      containers_.clear() ;
+      for( sub_iterator it = rhs.containers_.begin(); 
+           it != rhs.containers_.end(); 
+           ++it 
+         ) {
+        push_back(*it) ;
+        if(it == rhs.outer_it_) {
+          //ensure that the outer iterator is correctly set
+          outer_it_ = --containers_.end() ;
+        }
+      }
+      if(rhs.outer_it_ == rhs.containers_.end()) {
+        //handle the case when rhs is past-the-end
+        outer_it_ = containers_.end() ;
+      }
+      return *this ;
+    }
+    CompositeIterator& operator=( const CompositeIterator<T>& rhs ) {
+      //copy the inner iterator
+      inner_it_ = rhs.inner_it_ ;
+      //copy the container sequence
+      containers_.clear() ;
+      typedef typename CompositeIterator<T>::const_sub_iterator rhs_iterator ;
+      for( rhs_iterator it = rhs.containers_.begin(); 
+           it != rhs.containers_.end(); 
+           ++it 
+         ) {
+        push_back(*it) ;
+        if(it == rhs.outer_it_) {
+          //ensure that the outer iterator is correctly set
+          outer_it_ = --containers_.end() ;
+        }
+      }
+      if(rhs.outer_it_ == rhs.containers_.end()) {
+        //handle the case when rhs is past-the-end
+        outer_it_ = containers_.end() ;
+      }
+      return *this ;
+    }
+
+    /* Incrementation */
+    CompositeIterator& operator++() { 
+      ++inner_it_ ; 
+      while(inner_it_ == end_) {
+        //we pass over the empty arrays here
+        ++outer_it_ ;
+        if(outer_it_ != containers_.end()) {
+          inner_it_ = (*outer_it_)->begin() ;
+        } else {
+          break ;
+        }
+      }
+      return *this ; 
+    }
+    CompositeIterator operator++(int) { 
+      CompositeIterator tmp(*this) ; 
+      this->operator++() ; 
+      return tmp ; 
+    }
+
+    /* Comparison */
+    bool operator==( const CompositeIterator& rhs ) const {
+      return inner_it_ == rhs.inner_it_ ;
+    }
+    bool operator==( const CompositeIterator<T>& rhs ) const {
+      return inner_it_ == rhs.inner_it_ ;
+    }
+
+    bool operator!=( const CompositeIterator& rhs ) const {
+      return inner_it_ != rhs.inner_it_ ;
+    }
+    bool operator!=( const CompositeIterator<T>& rhs ) const {
+      return inner_it_ != rhs.inner_it_ ;
+    }
+
+    /* Dereferencement */
+    const T& operator*() const {
+      return *inner_it_ ;
+    }
+    const T* operator->() const {
+      return &(*inner_it_) ;
+    }
+
+  private :
+
+    /* global end iterator */
+    iterator end_ ;
+
+    /* current inner iterator */
+    iterator inner_it_ ;
+
+    /* store a list of generic iterators to concatenate */
+    std::list<const GenericContainer<const T>*> containers_ ;
+
+    /* current outer_iterator_ */
+    sub_iterator outer_it_ ;
+
+} ;
+
+/* An stl like container to merge multiple containers */
+
+template<typename T>
+class composite {
+
+  public :
+
+    /* Typedefs */
+    typedef T value_type ;
+    typedef CompositeIterator<T> iterator ;
+    typedef CompositeIterator<const T> const_iterator ;
+    typedef typename std::list<GenericContainer<T>*>::iterator sub_iterator ;
+    typedef typename std::list<GenericContainer<T>*>::const_iterator const_sub_iterator ;
+
+    /* Construction */
+    composite() {}
+
+    template<typename Container>
+    sub_iterator push_back( Container& container ) {
+      containers_.push_back(new ContainerFlattener<Container>(container)) ;
+      return --containers_.end() ;
+    }
+
+    template<typename Tp>
+    sub_iterator push_back( Tp begin, Tp end ) {
+      containers_.push_back( 
+        new ContainerFlattener<Tp>(begin, end)
+      ) ;
+      return --containers_.end() ;
+    }
+
+    /* Destruction */
+    ~composite() {
+      for( sub_iterator it = containers_.begin(); 
+           it != containers_.end(); 
+           ++it
+         ) {
+        delete *it ;
+      }
+    }
+
+    void erase( sub_iterator it ) {
+      delete *it ;
+      containers_.erase(it) ;
+    }
+
+    /* Iteration */
+    iterator begin() {
+      iterator composite_it ;
+      for( sub_iterator it = containers_.begin(); 
+           it != containers_.end(); 
+           ++it
+         ) {
+        composite_it.push_back(*it) ;
+      }
+      return composite_it ;
+    }
+    const_iterator begin() const {
+      const_iterator composite_it ;
+      for( const_sub_iterator it = containers_.begin(); 
+           it != containers_.end(); 
+           ++it
+         ) {
+        composite_it.push_back(*it) ;
+      }
+      return composite_it ;
+    };
+
+    iterator end() {
+      return end_ ;
+    };
+    const_iterator end() const {
+      return end_ ;
+    };
+
+  private :
+
+    /* Wrapped containers */
+    std::list<GenericContainer<T>*> containers_ ;
+
+    /* global end iterator */
+    iterator end_ ;
+
+} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/disjoint_sets_def.hpp b/contrib/Revoropt/include/Revoropt/Tools/disjoint_sets_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..66a92ea9d1d30c0df3d9d5cd92d103d190ddfc5b
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/disjoint_sets_def.hpp
@@ -0,0 +1,115 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#include "disjoint_sets_fwd.hpp"
+
+namespace Revoropt {
+
+template<typename T, typename hasher>
+const unsigned int DisjointSets<T, hasher>::NO_CLASS = -1 ;
+
+/* Manipulation */
+
+template<typename T, typename hasher>
+unsigned int DisjointSets<T, hasher>::insert( const T& item ) {
+  item_it it = items_.find(item) ;
+  if(it != items_.end()) {
+    return it->second ;
+  } else {
+    unsigned int index = nodes_.size() ;
+    uf_node item_node = { .rep = index, .rank = 1 } ;
+    nodes_.push_back(item_node) ;
+    items_[item] = index ;
+    return index ;
+  }
+}
+
+template<typename T, typename hasher>
+bool DisjointSets<T, hasher>::contains( const T& item ) {
+  return items_.find(item) != items_.end() ;
+}
+
+/* Operations */
+
+template<typename T, typename hasher>
+unsigned int DisjointSets<T, hasher>::item_class( const T& item ) {
+  item_it it = items_.find(item) ;
+  return it == items_.end() ? NO_CLASS : get_rep(it->second) ;
+}
+
+template<typename T, typename hasher>
+unsigned int DisjointSets<T, hasher>::merge_classes( 
+    unsigned int c1, 
+    unsigned int c2 
+    ) {
+  //get class representatives
+  const unsigned int c1_rep = get_rep(c1) ;
+  const unsigned int c2_rep = get_rep(c2) ;
+  //if the classes are already merged, do nothing
+  if(c1_rep == c2_rep) return c1_rep ;
+
+  //merge
+  //get the class ranks
+  const unsigned int c1_rank = get_rank(c1_rep) ;
+  const unsigned int c2_rank = get_rank(c2_rep) ;
+  if(c1_rank < c2_rank) {
+    //tree for c2 is deeper, use c2 as root
+    set_rep(c1_rep, c2_rep) ;
+    return c2_rep ;
+  } else if(c2_rank < c1_rank) {
+    //tree for c1 is deeper, use c1 as root
+    set_rep(c2_rep, c1_rep) ;
+    return c1_rep ;
+  } else {
+    //trees have the same depth, use c1 as root and increase its depth
+    set_rep(c2_rep, c1_rep) ;
+    set_rank(c1_rep, c1_rank+1) ;
+    return c1_rep ;
+  }
+}
+
+template<typename T, typename hasher>
+unsigned int DisjointSets<T, hasher>::merge_items( 
+    const T& item1, 
+    const T& item2 
+    ) {
+  const unsigned int c1 = item_class(item1) ;
+  if(c1 == NO_CLASS) return NO_CLASS ;
+  const unsigned int c2 = item_class(item2) ;
+  if(c2 == NO_CLASS) return NO_CLASS ;
+  return merge_classes(c1, c2) ;
+}
+ 
+template<typename T, typename hasher>
+unsigned int DisjointSets<T, hasher>::get_rep( unsigned int c ) {
+  if(nodes_[c].rep != c) {
+    //the element is within a class with a different root
+    nodes_[c].rep = get_rep(nodes_[c].rep) ;
+  }
+  //return the representative
+  return nodes_[c].rep ;
+}
+
+template<typename T, typename hasher>
+void DisjointSets<T, hasher>::set_rep( unsigned int c, unsigned int rep ) {
+  nodes_[c].rep = rep ;
+}
+
+template<typename T, typename hasher>
+unsigned int DisjointSets<T, hasher>::get_rank( unsigned int c ) {
+  return nodes_[c].rank ;
+}
+
+template<typename T, typename hasher>
+void DisjointSets<T, hasher>::set_rank( unsigned int c, unsigned int rank ) {
+  nodes_[c].rank = rank ;
+}
+
+} //end of namespace Revoropt
diff --git a/contrib/Revoropt/include/Revoropt/Tools/disjoint_sets_fwd.hpp b/contrib/Revoropt/include/Revoropt/Tools/disjoint_sets_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7d24331aba8721a08d4344aee42d822223bb85f7
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/disjoint_sets_fwd.hpp
@@ -0,0 +1,65 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_TOOLE_DISJOINT_SETS_H_
+#define _REVOROPT_TOOLE_DISJOINT_SETS_H_
+
+#include <vector>
+#include <unordered_map>
+#include <functional>
+
+namespace Revoropt {
+
+struct uf_node {
+  unsigned int rep ;
+  unsigned int rank ;
+} ;
+
+template< typename T, typename hasher = std::hash<T> >
+class DisjointSets {
+
+  public :
+
+  static const unsigned int NO_CLASS ;
+
+  /* Construction */
+  
+  DisjointSets() {} ;
+
+  /* Manipulation */
+
+  unsigned int insert( const T& item ) ;
+  bool contains( const T& item ) ;
+
+  /* Operations */
+
+  unsigned int merge_classes( unsigned int c1, unsigned int c2 ) ;
+  unsigned int merge_items( const T& item1, const T& item2 ) ;
+
+  unsigned int get_rep( unsigned int c ) ;
+  unsigned int item_class( const T& item ) ;
+
+  private :
+
+  unsigned int get_rank( unsigned int c ) ;
+  void set_rank(unsigned int c, unsigned int rank) ;
+  void set_rep( unsigned int c, unsigned int rep ) ;
+
+  std::vector<uf_node> nodes_ ;
+  std::unordered_map<T, unsigned int, hasher> items_ ;
+  typedef typename std::unordered_map<
+      T, unsigned int, hasher
+    >::iterator item_it ;
+
+} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/eigen_helpers.hpp b/contrib/Revoropt/include/Revoropt/Tools/eigen_helpers.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..6c567618441df79683b6f0c24a4d0a0d236af427
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/eigen_helpers.hpp
@@ -0,0 +1,70 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_TOOLS_EIGEN_HELPERS_HPP_
+#define _REVOROPT_TOOLS_EIGEN_HELPERS_HPP_
+
+#include <eigen3/Eigen/Dense>
+
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+
+namespace Revoropt {
+
+template<typename Scalar, int Dim>
+std::istream& operator>>( std::istream& in, Eigen::Matrix<Scalar,Dim,1>& v ) {
+  //vector type
+  typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+
+  //save the stream position
+  std::streampos in_pos = in.tellg() ;
+
+  //load buffer
+  Vector data = Vector::Constant(0) ;
+
+  //try loading with spaces
+  for(int i = 0; i<Dim; ++i) {
+    if(in.good()) {
+      in >> data[i] ;
+    } else {
+      break ;
+    }
+  }
+  if(!in.fail()) {
+    data.swap(v) ;
+  } else {
+    //reload backup
+    in.clear() ;
+    in.seekg(in_pos) ;
+    std::string input ;
+    in >> input ;
+
+    std::replace(input.begin(), input.end(), ';', ' ') ;
+    std::stringstream ss(input) ;
+
+    //try copy
+    for(int i = 0; i<Dim; ++i) {
+      if(ss.good()) {
+        ss >> data[i] ;
+      } else {
+        break ;
+      }
+    }
+    if(!ss.fail()) {
+      data.swap(v) ;
+    }
+  }
+  return in ;
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/group_vector.hpp b/contrib/Revoropt/include/Revoropt/Tools/group_vector.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..0779004947edf4506518d07d8fd006c45b41c379
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/group_vector.hpp
@@ -0,0 +1,98 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_TOOLS_GROUP_VECTOR_HPP_
+#define _REVOROPT_TOOLS_GROUP_VECTOR_HPP_
+
+#include "container_wrapper.hpp"
+
+#include <map>
+#include <vector>
+#include <string>
+
+namespace Revoropt {
+
+template<typename T>
+class group_vector {
+
+  public :
+
+    /* Typedefs */
+    typedef T value_type ;
+    typedef typename composite<T>::iterator iterator ;
+    typedef typename composite<T>::const_iterator const_iterator ;
+
+    /* Construction, destruction */
+    group_vector() {
+      all_contained_.push_back(self_contained_) ;
+    }
+
+    /* Iteration */
+    iterator begin() {
+      return all_contained_.begin() ;
+    }
+
+    const_iterator begin() const {
+      return all_contained_.begin() ;
+    }
+
+    iterator end() {
+      return all_contained_.end() ;
+    }
+
+    const_iterator end() const {
+      return all_contained_.end() ;
+    }
+
+    /* Content management */
+    void insert(T* t) {
+      self_contained_.push_back(t) ;
+    }
+
+    template< typename Container >
+    void insert_group( const std::string& name, Container& container ) {
+      groups_[name] = all_contained_.push_back(container) ;
+    }
+
+    template< typename Tp >
+    void insert_group( const std::string& name, Tp begin, Tp end ) {
+      groups_[name] = all_contained_.push_back(begin, end) ;
+    }
+    
+    void erase_group( const std::string& name ) {
+      g_iterator it = groups_.find(name) ;
+      if(it != groups_.end()) {
+        all_contained_.erase(it->second) ;
+      }
+    }
+
+  protected :
+
+    /* Wrapped container for groups */
+    composite<T> all_contained_ ;
+
+  private :
+    /* Inner container for individual elements */
+    std::vector<T*> self_contained_ ;
+
+    /* Group management */
+    typedef typename std::map<
+      std::string, 
+      typename composite<T>::sub_iterator
+    >::iterator g_iterator ;
+    std::map<
+      std::string, 
+      typename composite<T>::sub_iterator
+    > groups_ ;
+} ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/hash.hpp b/contrib/Revoropt/include/Revoropt/Tools/hash.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..877b11c2bb236ba9b09c63e8066c7a57d9e5712c
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/hash.hpp
@@ -0,0 +1,67 @@
+// @licstart farmhash
+// Copyright (c) 2014 Google, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// FarmHash, by Geoff Pike
+
+//
+// http://code.google.com/p/farmhash/
+//
+// This file provides a few functions for hashing strings and other
+// data.  All of them are high-quality functions in the sense that
+// they do well on standard tests such as Austin Appleby's SMHasher.
+// They're also fast.  FarmHash is the successor to CityHash.
+//
+// Functions in the FarmHash family are not suitable for cryptography.
+//
+// WARNING: This code has been only lightly tested on big-endian platforms!
+// It is known to work well on little-endian platforms that have a small penalty
+// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.
+// It should work on all 32-bit and 64-bit platforms that allow unaligned reads;
+// bug reports are welcome.
+//
+// By the way, for some hash functions, given strings a and b, the hash
+// of a+b is easily derived from the hashes of a and b.  This property
+// doesn't hold for any hash functions in this file.
+// 
+// @licend farmhash
+
+#ifndef _REVOROPT_TOOLS_HASH_HPP_
+#define _REVOROPT_TOOLS_HASH_HPP_
+
+#include <functional>
+
+namespace Revoropt {
+
+template < class T, class Hasher = std::hash<T> > 
+inline void hash_combine(std::size_t& seed, const T& v)
+{
+    Hasher hasher;
+    const std::size_t kMul = 0x9ddfea08eb382d69ULL;
+    std::size_t a = (hasher(v) ^ seed) * kMul;
+    a ^= (a >> 47);
+    std::size_t b = (seed ^ a) * kMul;
+    b ^= (b >> 47);
+    seed = b * kMul;
+}
+
+} // end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/intersections_def.hpp b/contrib/Revoropt/include/Revoropt/Tools/intersections_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..66fcabfa5edfbeec56d67d40b5ef183d47cf2eb3
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/intersections_def.hpp
@@ -0,0 +1,687 @@
+#ifndef _REVOROPT_TOOLS_INTERSECTIONS_DEF_HPP_
+#define _REVOROPT_TOOLS_INTERSECTIONS_DEF_HPP_
+
+#include "eigen3/Eigen/Dense"
+
+#include "intersections_fwd.hpp"
+
+namespace Revoropt {
+
+/* 2d orientation check */
+template<typename Scalar>
+char orientation( const Scalar v0[2], const Scalar v1[2] ) {
+  Scalar det = v0[0]*v1[1] - v1[0]*v0[1] ;
+  if(det > 0) return 1 ;
+  if(det < 0) return -1 ;
+  return 0 ;
+}
+
+/* Checks whether a point is in a segment (including endpoints)
+ * If the offset pointer is provided, it is filled with the value of a 
+ * such that p = p0 + a*(p1-p0). If the p is not in the segment, the point
+ * q = p0 + a*(p1-p0) is the point of the segment nearest to p. */
+template<int Dim, typename Scalar>
+bool point_in_segment( const Scalar p_coords[Dim],
+                       const Scalar p0_coords[Dim],
+                       const Scalar p1_coords[Dim],
+                       Scalar* offset //output
+                     ) {
+  //vector type
+  typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+
+  //segment extremities and point
+  Eigen::Map<const Vector> p0(p0_coords) ;
+  Eigen::Map<const Vector> p1(p1_coords) ;
+  Eigen::Map<const Vector> p(p_coords) ;
+
+  //direction of the segment
+  Vector u = p1-p0 ;
+  const Scalar u_len = u.norm() ;
+  if(u_len == 0) {
+    //p1 and p0 are the same point
+    if(offset != NULL) {
+      //by convention, p0 is the nearest point
+      *offset = 0 ;
+    }
+    //check whether p is that point too
+    return (p == p0) ;
+  }
+  u /= u_len ;
+  //project p on the segment line
+  const Vector p_vect = p-p0 ;
+  const Scalar p_offset = p_vect.dot(u) ;
+  //check that the projection is within the extremities
+  if(p_offset < 0) {
+    if(offset != NULL) {
+      *offset = 0 ;
+    }
+    return false ;
+  }
+  if(p_offset > u_len) {
+    if(offset != NULL) {
+      *offset = 1 ;
+    }
+    return false ;
+  }
+  //no return, the projection is within the segment
+  if(offset != NULL) {
+    //assign the offset
+    *offset = p_offset / u_len ;
+  }
+  //check that the projected point is the actual point
+  return (p_offset == p_vect.norm()) ;
+}
+
+/* Segment intersection */
+/* Returns true if the segments are coplanar and intersect.
+ * If the s0_offset pointer is provided, it is filled with the value of a 
+ *   such that the intersection I1 = p0 + a*(p1-p0). If the segments do not
+ *   intersect, I0 is the point of [p0,p1] nearest to [p2,p3].
+ * If the s1_offset pointer is provided, it is filled with the value of b
+ *   such that the intersection I2 = p2 + b*(p3-p2). If the segments do not
+ *   intersect, I1 is the point of [p2,p3] nearest to [p0,p1]. 
+ * If the segments do not intersect, I0 and I1 are the points archieving the
+ * smallest distance between [p0,p1] and [p2,p3]. */
+
+namespace segment_intersection_impl{
+
+template<int Dim, typename Scalar>
+class si_impl {
+  public:
+  //vector type
+  typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+  //2d vector type
+  typedef Eigen::Matrix<Scalar,2,1> Vector2 ;
+
+  static bool do_it( const Scalar p0_coords[Dim],
+                     const Scalar p1_coords[Dim],
+                     const Scalar p2_coords[Dim],
+                     const Scalar p3_coords[Dim],
+                     Scalar* s0_offset, //output
+                     Scalar* s1_offset  //output
+                   ) {
+    //segment extremities
+    Eigen::Map<const Vector> p0(p0_coords) ;
+    Eigen::Map<const Vector> p1(p1_coords) ;
+    Eigen::Map<const Vector> p2(p2_coords) ;
+    Eigen::Map<const Vector> p3(p3_coords) ;
+
+    //projection matri on a plane parallel to both segments
+    Eigen::Matrix<Scalar,2,Dim> P ;
+
+    //unit direction of the first segment
+    P.row(0) = p1-p0 ;
+    const Scalar P0_len = P.row(0).norm() ;
+    if(P0_len == 0) {
+      //the first segment is reduced to a point
+      if(s0_offset != NULL) {
+        //by convention the p0 is nearest to [p2,p3]
+        *s0_offset = 0 ;
+      }
+      //point_segment intersection
+      return point_in_segment<Dim>(p0_coords, p2_coords, p3_coords, s1_offset) ;
+    }
+    P.row(0) /= P0_len ;
+
+    //direction of the second segment
+    P.row(1) = p3-p2 ;
+    if(P.row(1).dot(P.row(1)) == 0) {
+      //the second segment is reduced to a point
+      if(s1_offset != NULL) {
+        //by convention the p2 is nearest to [p0,p1]
+        *s1_offset = 0 ;
+      }
+      //point_segment intersection
+      return point_in_segment<Dim>(p2_coords, p0_coords, p1_coords, s0_offset) ;
+    }
+
+    //orthogonalize the direction wrt the direction of the first segment
+    P.row(1) -= P.row(1).dot(P.row(0))*P.row(0) ;
+    const Scalar P1_len = P.row(1).norm() ;
+    if(P1_len != 0) {
+      //if the segments are parallel, v is 0, otherwise it is normalized
+      P.row(1) /= P1_len ;
+    }
+
+    //projection of one of each segment endpoints 
+    //Dim dimensional vectors here, although 2d in the end
+    Vector2 pp0 = Vector2::Zero() ;
+    Vector2 pp2 = P*(p2-p0) ;
+
+    //check whether the segments are coplanar : same offsets wrt the plane
+    const Vector p2_proj = p2 - P.transpose()*pp2 ;
+    const bool segments_coplanar = p2_proj.dot(p2_proj) == 0 ;
+
+    //early return if the segments are not coplanar, and no offset required
+    if((s0_offset == NULL) && !segments_coplanar) return false ;
+
+    //projections the remaining extremities
+    Vector2 pp1 = P*(p1-p0) ;
+    Vector2 pp3 = P*(p3-p0) ;
+
+    //switch to 2D
+    const bool intersect_2d = si_impl<2,Scalar>::do_it( pp0.data(), 
+                                                        pp1.data(), 
+                                                        pp2.data(), 
+                                                        pp3.data(),
+                                                        s0_offset,
+                                                        s1_offset
+                                                      ) ;
+
+    return intersect_2d && segments_coplanar ;
+  }
+} ;
+
+template<typename Scalar>
+class si_impl<2,Scalar> {
+  public:
+  //vector type
+  typedef Eigen::Matrix<Scalar,2,1> Vector ;
+
+  static bool do_it( const Scalar p0_coords[2],
+                     const Scalar p1_coords[2],
+                     const Scalar p2_coords[2],
+                     const Scalar p3_coords[2],
+                     Scalar* s0_offset, //output
+                     Scalar* s1_offset  //output
+                   ) {
+    //segment extremities
+    Eigen::Map<const Vector> p0(p0_coords) ;
+    Eigen::Map<const Vector> p1(p1_coords) ;
+    Eigen::Map<const Vector> p2(p2_coords) ;
+    Eigen::Map<const Vector> p3(p3_coords) ;
+
+    //segment vectors
+    const Vector s0 = p1-p0 ;
+    const Vector s1 = p3-p2 ;
+
+    //orientation check
+    Vector tested = p2-p0 ;
+    const char o02 = orientation(s0.data(), tested.data()) ;
+    tested = p3-p0 ;
+    const char o03 = orientation(s0.data(), tested.data()) ;
+    tested = p0-p2 ;
+    const char o10 = orientation(s1.data(), tested.data()) ;
+    tested = p1-p2 ;
+    const char o11 = orientation(s1.data(), tested.data()) ;
+
+    //basic intersection check, no enough if the segments are aligned
+    const bool basic_intersect = (o02 != o03) && (o10 != o11) ;
+
+    //no offset is required, return fastly if the intersection is sure
+    if(basic_intersect && (s0_offset == NULL)) return true ;
+
+    //segment normals in a matrix
+    Eigen::Matrix<Scalar,2,2> A ;
+    A << -s0[1], s0[0], -s1[1], s1[0] ;
+
+    //check parallelism of the segments
+    const Scalar det = A.determinant() ;
+
+    if(det == 0) {
+      //the segments are parallel or at least one is 0
+      //length of [p0,p1]
+      const Scalar s0_len = s0.norm() ;
+      if(s0_len == 0) {
+        //p0 and p1 are the same point
+        if(s0_offset != NULL) {
+          //by convention p0 is nearest to [p2,p3]
+          *s0_offset = 0 ;
+        }
+        return point_in_segment<2>(p0_coords, p2_coords, p3_coords, s1_offset) ;
+      }
+      //from now on we know that p0 and p1 are different
+      //project p2 and p3 on [p0,p1]
+      const Scalar pp2 = p2.dot(s0)/s0_len ;
+      const Scalar pp3 = p3.dot(s0)/s0_len ;
+      const Scalar minp = pp2 < pp3 ? pp2 : pp3 ;
+      const Scalar maxp = pp2 < pp3 ? pp3 : pp2 ;
+      //cases
+      if((minp <= 0) && (maxp >= 0)) {
+        //p0 is a point reaching minimal distance to [p2,p3]
+        if(s0_offset != NULL) {
+          //assign it as nearest to [p2,p3] if asked
+          *s0_offset = 0 ;
+        }
+        return point_in_segment<2>(p0_coords, p2_coords, p3_coords, s1_offset) ;
+      }
+      if((minp <= s0_len) && (maxp >= s0_len)) {
+        //p1 is a point reaching minimal distance to [p2,p3]
+        if(s0_offset != NULL) {
+          //assign it as nearest to [p2,p3] if asked
+          *s0_offset = 1 ;
+        }
+        return point_in_segment<2>(p1_coords, p2_coords, p3_coords, s1_offset) ;
+      }
+      if(minp > s0_len) {
+        //no intersection
+        //p1 is nearest to [p2,p3] and the nearest point is at minp
+        if(s0_offset != NULL) {
+          //assign it as nearest to [p2,p3] if asked
+          *s0_offset = 1 ;
+        }
+        if(s1_offset != NULL)  {
+          //assign the point projected at minp as nearest to [p0,p1]
+          *s1_offset = minp == pp2 ? 0 : 1 ;
+        }
+        return false ;
+      }
+      if(maxp < 0) {
+        //no intersection
+        //p0 is nearest to [p2,p3] and the nearest point is at maxp
+        if(s0_offset != NULL) {
+          //assign it as nearest to [p2,p3] if asked
+          *s0_offset = 0 ;
+        }
+        if(s1_offset != NULL)  {
+          //assign the point projected at minp as nearest to [p0,p1]
+          *s1_offset = maxp == pp2 ? 0 : 1 ;
+        }
+        return false ;
+      }
+      //from now on both p2 and p3 project inside [p0,p1]
+      //by convention p2 is nearest to [p0,p1]
+      if(s1_offset != NULL) {
+        *s1_offset = 0 ;
+      }
+      return point_in_segment<2>(p2_coords, p0_coords, p1_coords, s0_offset) ;
+    }
+    //the segments are not parallel
+    //if they intersect, the basic_intersect detected it
+    if(s0_offset == NULL) return false ;
+    //intersection between (p0,p1) and (p2,p3)
+    Vector lhs ;
+    lhs << A.row(0).dot(p0), A.row(1).dot(p2) ;
+    const Vector I = A.inverse()*lhs ;
+    //offsets of the intersection
+    const Scalar s0_tmp_offset = s0.dot(I-p0) / s0.dot(s0) ; //no division by 0
+    const Scalar s1_tmp_offset = s1.dot(I-p2) / s1.dot(s1) ; //no division by 0
+    //if the segments basically intersect, return these offsets
+    if(basic_intersect) {
+      *s0_offset = s0_tmp_offset ;
+      if(s1_offset != NULL) *s1_offset = s1_tmp_offset ;
+      return true ;
+    }
+    //from now on the segments do not intersect
+    if(o02 != o03) {
+      //I lies in [p2,p3]
+      //I does not lie in [p0,p1] otherwise basic_intersect
+      //the extremity of [p0,p1] nearest to I reaches minimal distance
+      const Scalar* s0_nearest = s0_tmp_offset > 0.5 ? p1_coords : p0_coords ;
+      *s0_offset = s0_nearest == p1_coords ? 1 : 0 ;
+      if(s1_offset != NULL) {
+        point_in_segment<2>(s0_nearest, p2_coords, p3_coords, s1_offset) ;
+      }
+      return false ;
+    }
+    //from now on I lies outside [p2,p3]
+    //get the extremity of [p2,p3] nearest to I
+    const Scalar* s1_nearest = s1_tmp_offset > 0.5 ? p3_coords : p2_coords ;
+    //point in [p0,p1] nearest to that point
+    point_in_segment<2>(s1_nearest, p0_coords, p1_coords, s0_offset) ;
+    if((*s0_offset >=0) && (*s0_offset <= 1)) {
+      //s1_nearest reaches minimal distance
+      if(s1_offset != NULL) {
+        *s1_offset = s1_nearest == p3_coords ? 1 : 0 ;
+      }
+      return false ;
+    }
+    //s1_nearest may not reach minimal distance
+    //the extremity of [p0,p1] nearest to I reaches minimal distance anyway
+    *s0_offset = s0_tmp_offset > 0.5 ? 1 : 0 ;
+    if(s1_offset != NULL) {
+      //get that extremity
+      const Scalar* s0_nearest = s0_offset == 0 ? p0_coords : p1_coords ;
+      point_in_segment<2>(s0_nearest, p2_coords, p3_coords, s1_offset) ;
+    }
+    return false ;
+  }
+} ;
+
+} //end of namespace segment_intersection_impl
+
+template<int Dim, typename Scalar>
+bool segment_intersection( const Scalar p0_coords[2],
+                           const Scalar p1_coords[2],
+                           const Scalar p2_coords[2],
+                           const Scalar p3_coords[2],
+                           Scalar* s0_offset, //output
+                           Scalar* s1_offset  //output
+                         ) {
+  using namespace segment_intersection_impl ;
+  return si_impl<Dim,Scalar>::do_it( p0_coords,
+                                     p1_coords,
+                                     p2_coords,
+                                     p3_coords,
+                                     s0_offset,
+                                     s1_offset
+                                   ) ;
+}
+
+
+/* Checks whether a point is strictly in a sphere. 
+ * The *squared* radius is required */
+template<int Dim, typename Scalar>
+bool point_in_sphere( const Scalar point[Dim], 
+                      const Scalar center[Dim], 
+                      Scalar radius 
+                    ) {
+  //vector type
+  typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+
+  Eigen::Map<const Vector> p(point) ;
+  Eigen::Map<const Vector> c(center) ;
+  Vector edge = p-c ;
+
+  //distance check
+  return edge.dot(edge) < radius*radius ;
+}
+
+/* Intersection between the interior of a segment and a sphere.
+ * Returns the number of intersections.
+ * The *squared* radius is required.
+ * The provided output array receives the intersections p 
+ * as the values of u such that p = p1 + u(p2-p1) */
+template<int Dim, typename Scalar>
+unsigned char segment_sphere_intersections( const Scalar p0_coords[Dim], 
+                                            const Scalar p1_coords[Dim],
+                                            const Scalar center[Dim],
+                                            Scalar radius,
+                                            Scalar intersections[2] //output
+                                          ) {
+  //vector type
+  typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+
+  Eigen::Map<const Vector> p0(p0_coords) ;
+  Eigen::Map<const Vector> p1(p1_coords) ;
+  Eigen::Map<const Vector> c(center) ;
+
+  //edge vector and its squared length
+  const Vector edge = p1-p0 ;
+  const Scalar sq_elen = edge.dot(edge) ;
+  //center vector and its squared length
+  const Vector cv = p0-c ;
+  const Scalar sq_cvlen = cv.dot(cv) ;
+  //dot product between the two
+  const Scalar edgedotcv = edge.dot(cv) ;
+
+  //discriminant
+  const Scalar disc = edgedotcv*edgedotcv - sq_elen*(sq_cvlen - radius*radius) ;
+
+  //no intersection case
+  if(disc < 0) return 0 ;
+
+  //intersections, compute their positions
+  const Scalar dist_rt = sqrt(disc) ;
+  const Scalar u0 = (-edgedotcv - dist_rt)/sq_elen ;
+  const Scalar u1 = (-edgedotcv + dist_rt)/sq_elen ;
+
+  //check these positions are in the interior of the segment
+  //and count the number of valid intersections
+  unsigned char number_of_intersections = 0 ;
+  if((u0 > 0) && (u0 < 1)) {
+    intersections[0] = u0 ;
+    ++number_of_intersections ;
+  }
+  if((u1 > 0) && (u1 < 1)) {
+    intersections[number_of_intersections] = u1 ;
+    ++number_of_intersections ;
+  }
+
+  //return the number of intersections
+  return number_of_intersections ;
+}
+
+/* Check whether a point lies in a triangle.
+ * If the bar_coords pointer is provided, it is filled with two scalars a and b
+ * such that the point a.x0 + b.x1 + (1-a-b).x2 is the point in the triangle
+ * x0,x1,x2 nearest to p. */
+
+namespace point_in_triangle_impl {
+
+//classes for partial template specialization, unavailable for functions
+template<int Dim, typename Scalar>
+class pit_impl {
+  public:
+  static bool do_it( const Scalar p_coords[Dim],
+                     const Scalar x0_coords[Dim],
+                     const Scalar x1_coords[Dim],
+                     const Scalar x2_coords[Dim],
+                     Scalar bar_coords[2] = NULL
+                   ) {
+    //vector type
+    typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+    //2d vector type
+    typedef Eigen::Matrix<Scalar,2,1> Vector2 ;
+  
+    Eigen::Map<const Vector> p(p_coords) ;
+    Eigen::Map<const Vector> x0(x0_coords) ;
+    Eigen::Map<const Vector> x1(x1_coords) ;
+    Eigen::Map<const Vector> x2(x2_coords) ;
+  
+    //projection matrix
+    Eigen::Matrix<Scalar,2,Dim,Eigen::RowMajor> P ;
+    //base of the triangle
+    P.row(0) = x1-x0 ;
+    const Scalar base_len = P.row(0).norm() ;
+    if(base_len == 0) {
+      //x0 and x1 are identical
+      if(bar_coords != NULL) {
+        //by convention the nearest point is on segment [x0,x2]
+        bar_coords[1] = 0 ;
+      }
+      return point_in_segment<Dim>(p_coords,x2_coords,x0_coords,bar_coords) ;
+    }
+    P.row(0) /= base_len ;
+  
+    //height of the triangle
+    P.row(1) = x2-x0 ;
+    P.row(1) -= P.row(1).dot(P.row(0))*P.row(0) ;
+    const Scalar height_len = P.row(1).norm() ;
+    if(height_len == 0) {
+      //get the vector used for the height
+      const Vector h = x2-x2 ;
+      //compute the dot product with the base (theoretically 1 or -1)
+      const Scalar bdoth = h.dot(P.row(0)) ;
+      if(bdoth < 0) {
+        //x0 lies on [x1,x2]
+        if(bar_coords != NULL) {
+          //by convention the nearest point is on segment [x1,x2]
+          bar_coords[0] = 0 ;
+          return point_in_segment<Dim>( p_coords,
+                                        x2_coords,
+                                        x1_coords,
+                                        bar_coords+1
+                                      ) ;
+        }
+        return point_in_segment<Dim>(p_coords,x2_coords,x1_coords) ;
+      } else {
+        if(h.dot(h) < base_len*base_len) {
+          //x2 lies on [x0,x1]
+          if(bar_coords != NULL) {
+            //by convention the nearest point is on segment [x0,x1]
+            bool intersect = point_in_segment<Dim>( p_coords,
+                                                    x0_coords,
+                                                    x1_coords,
+                                                    bar_coords+1
+                                                  ) ;
+            bar_coords[0] = 1-bar_coords[1] ;
+            return intersect ;
+          }
+          return point_in_segment<Dim>(p_coords,x0_coords,x1_coords) ;
+        } else {
+          //x1 lies on [x0,x2]
+          if(bar_coords != NULL) {
+            //by convention the nearest point is on segment [x0,x2]
+            bar_coords[1] = 0 ;
+          }
+          return point_in_segment<Dim>( p_coords,
+                                        x2_coords,
+                                        x0_coords,
+                                        bar_coords
+                                      ) ;
+        }
+      }
+    }
+    P.row(1) /= height_len ;
+  
+    //project everything
+    Vector2 pp, x0p, x1p, x2p ;
+    pp = P*(p-x0) ;
+    x0p = Vector2::Zero() ;
+    x1p = P*(x1-x0) ;
+    x2p = P*(x2-x0) ;
+
+    //coplanarity test
+    const Vector p_proj = p - P.transpose()*pp ;
+    bool coplanar = p_proj.dot(p_proj) == 0 ;
+    if((bar_coords == NULL) && (!coplanar)) return false ;
+  
+    //switch to 2D
+    bool intersect =  pit_impl<2,Scalar>::do_it( pp.data(), 
+                                                 x0p.data(), 
+                                                 x1p.data(), 
+                                                 x2p.data(),
+                                                 bar_coords
+                                               ) ;
+    
+    return (coplanar && intersect) ;
+  }
+} ;
+
+template<typename Scalar>
+class pit_impl<2,Scalar> {
+  public:
+  static bool do_it( const Scalar p_coords[2],
+                     const Scalar x0_coords[2],
+                     const Scalar x1_coords[2],
+                     const Scalar x2_coords[2],
+                     Scalar bar_coords[2] = NULL
+                   ) {
+    //Vector type
+    typedef Eigen::Matrix<Scalar,2,1> Vector ;
+  
+    //Query point
+    Eigen::Map<const Vector> p(p_coords) ;
+
+    //Triangle vertices
+    const Scalar* x[3] ;
+    x[0] = x0_coords ;
+    x[1] = x1_coords ;
+    x[2] = x2_coords ;
+  
+    //matrix for sides and point vectors
+    Eigen::Matrix<Scalar,4,3, Eigen::ColMajor> m ;
+
+    for(int i=0; i<3; ++i) {
+      Eigen::Map<const Vector> x1(x[(i+1)%3]) ;
+      Eigen::Map<const Vector> x2(x[(i+2)%3]) ;
+      m.template block<2,1>(0,i) = x2-x1 ;
+      m.template block<2,1>(2,i) = p -x1 ;
+    }
+
+    //twice the triangle area
+    const Scalar twoarea = m.template topLeftCorner<2,2>().determinant() ;
+
+    //barycentric coordinates wrt x0, x1 and x2
+    Scalar b[3] ;
+    for(int i = 0; i<3; ++i) {
+      Eigen::Map< Eigen::Matrix<Scalar,2,2> > mini(m.col(i).data()) ;
+      b[i] = mini.determinant()/twoarea ;
+    }
+
+    for(int i = 0; i<3; ++i) {
+      if(b[i] < 0) {
+        //p is on the wrong side of [x{[i+1)%3],x[(i+2)%3]]
+        if(b[(i+1)%3] < 0) {
+          //p is also on the wrong side of [x[(i+2)%3],x[i]]
+          //x[(i+2)%3] is the vertex in common
+          if( m.template block<2,1>(0,i).dot(
+              m.template block<2,1>(2,(i+1)%3))*twoarea 
+              > 0
+            ) {
+            //the nearest side is [x[(i+2)%3],x[i]]
+            bool intersect = point_in_segment<2>( p_coords,
+                                                  x[(i+2)%3],
+                                                  x[i],
+                                                  bar_coords
+                                                ) ;
+            if(bar_coords != NULL) {
+              b[i] = bar_coords[0] ;
+              b[(i+1)%3] = 0 ;
+              b[(i+2)%3] = 1-bar_coords[0] ;
+              bar_coords[0] = b[0] ;
+              bar_coords[1] = b[1] ;
+            }
+            return intersect ;
+          }
+        }
+        if(b[(i+2)%3] < 0) {
+          //p is also on the wrong side of [x[i],x[(i+1)%3]]
+          //x[(i+1)%3] is the vertex in common
+          if( m.template block<2,1>(0,i).dot(
+              m.template block<2,1>(2,(i+2)%3))*twoarea
+              < 0
+            ) {
+            //the nearest side is [x[i],x[(i+1)%3]]
+            bool intersect = point_in_segment<2>( p_coords,
+                                                  x[(i+1)%3],
+                                                  x[i],
+                                                  bar_coords
+                                                ) ;
+            if(bar_coords != NULL) {
+              b[i] = bar_coords[0] ;
+              b[(i+1)%3] = 1-bar_coords[0] ;
+              b[(i+2)%3] = 0 ;
+              bar_coords[0] = b[0] ;
+              bar_coords[1] = b[1] ;
+            }
+            return intersect ;
+          }
+        }
+        //no return, the nearest point is on [x[(i+1)%3],x[(i+2)%3]]
+        bool intersect = point_in_segment<2>( p_coords,
+                                              x[(i+1)%3],
+                                              x[(i+2)%3],
+                                              bar_coords
+                                            ) ;
+        if(bar_coords != NULL) {
+          b[i] = 0 ;
+          b[(i+1)%3] = 1-bar_coords[0] ;
+          b[(i+2)%3] = bar_coords[0] ;
+          bar_coords[0] = b[0] ;
+          bar_coords[1] = b[1] ;
+        }
+        return intersect ;
+      }
+    }
+    //no return, p is in the triangle
+
+    if(bar_coords != NULL) {
+      bar_coords[0] = b[0] ;
+      bar_coords[1] = b[1] ;
+    }
+    return true ;
+  }
+} ;
+}//end of namespace point_in_triangle_impl
+
+template<int Dim, typename Scalar>
+bool point_in_triangle( const Scalar p_coords[Dim],
+                        const Scalar x0_coords[Dim],
+                        const Scalar x1_coords[Dim],
+                        const Scalar x2_coords[Dim],
+                        Scalar bar_coords[2]
+                      ) {
+  using namespace point_in_triangle_impl ;
+  return pit_impl<Dim,Scalar>::do_it( p_coords,
+                                      x0_coords,
+                                      x1_coords,
+                                      x2_coords,
+                                      bar_coords
+                                    ) ;
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/intersections_fwd.hpp b/contrib/Revoropt/include/Revoropt/Tools/intersections_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..50ed9b51defeebed813ef427c144fb4c024c4006
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/intersections_fwd.hpp
@@ -0,0 +1,76 @@
+#ifndef _REVOROPT_TOOLS_INTERSECTIONS_FWD_HPP_
+#define _REVOROPT_TOOLS_INTERSECTIONS_FWD_HPP_
+
+namespace Revoropt {
+
+/* 2d orientation check */
+template<typename Scalar>
+char orientation( const Scalar v0[2], const Scalar v1[2] ) ;
+
+/* Checks whether a point is in a segment (including endpoints)
+ * If the offset pointer is provided, it is filled with the value of a 
+ * such that p = p0 + a*(p1-p0). If the p is not in the segment, the point
+ * q = p0 + a*(p1-p0) is the point of the segment nearest to p. */
+template<int Dim, typename Scalar>
+bool point_in_segment( const Scalar p_coords[Dim],
+                       const Scalar p0_coords[Dim],
+                       const Scalar p1_coords[Dim],
+                       Scalar* offset = NULL //output
+                     ) ;
+
+/* Segment intersection */
+/* Returns true if the segments are coplanar and intersect.
+ * If the s0_offset pointer is provided, it is filled with the value of a 
+ *   such that the intersection I1 = p0 + a*(p1-p0). If the segments do not
+ *   intersect, I0 is the point of [p0,p1] nearest to [p2,p3].
+ * If the s1_offset pointer is provided, it is filled with the value of b
+ *   such that the intersection I2 = p2 + b*(p3-p2). If the segments do not
+ *   intersect, I1 is the point of [p2,p3] nearest to [p0,p1]. 
+ * If the segments do not intersect, I0 and I1 are the points archieving the
+ * smallest distance between [p0,p1] and [p2,p3]. */
+template<int Dim, typename Scalar>
+bool segment_intersection( const Scalar p0_coords[2],
+                           const Scalar p1_coords[2],
+                           const Scalar p2_coords[2],
+                           const Scalar p3_coords[2],
+                           Scalar* s0_offset = NULL, //output
+                           Scalar* s1_offset = NULL  //output
+                         ) ;
+
+
+/* Checks whether a point is strictly in a sphere. 
+ * The *squared* radius is required */
+template<int Dim, typename Scalar>
+bool point_in_sphere( const Scalar point[Dim], 
+                      const Scalar center[Dim], 
+                      Scalar radius 
+                    ) ;
+
+/* Intersection between the interior of a segment and a sphere.
+ * Returns the number of intersections.
+ * The *squared* radius is required.
+ * The provided output array receives the intersections p 
+ * as the values of u such that p = p1 + u(p2-p1) */
+template<int Dim, typename Scalar>
+unsigned char segment_sphere_intersections( const Scalar p0_coords[Dim], 
+                                            const Scalar p1_coords[Dim],
+                                            const Scalar center[Dim],
+                                            Scalar radius,
+                                            Scalar intersections[2] //output
+                                          ) ;
+
+/* Check whether a point lies in a triangle.
+ * If the bar_coords pointer is provided, it is filled with two scalars a and b
+ * such that the point a.x0 + b.x1 + (1-a-b).x2 is the point in the triangle
+ * x0,x1,x2 nearest to p. */
+template<int Dim, typename Scalar>
+bool point_in_triangle( const Scalar p_coords[Dim],
+                        const Scalar x0_coords[Dim],
+                        const Scalar x1_coords[Dim],
+                        const Scalar x2_coords[Dim],
+                        Scalar bar_coords[2] = NULL
+                      ) ;
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/measure_def.hpp b/contrib/Revoropt/include/Revoropt/Tools/measure_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..223ad4ef646d1ad80f9a458f51a607906265f047
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/measure_def.hpp
@@ -0,0 +1,597 @@
+#ifndef _REVOROPT_TOOLS_MEASURE_DEF_HPP_
+#define _REVOROPT_TOOLS_MEASURE_DEF_HPP_
+
+#include <eigen3/Eigen/Dense>
+
+#include "measure_fwd.hpp"
+#include "intersections_def.hpp"
+
+namespace Revoropt {
+
+/*{{{ Triangle height and area */
+
+/* Height of a triangle, passing through the first vertex provided */
+template<int Dim, typename Scalar>
+Scalar triangle_height( const Scalar x0_p[Dim],
+                        const Scalar x1_p[Dim],
+                        const Scalar x2_p[Dim]
+                      ) {
+  //vector type
+  typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+
+  //vertices of the triangle
+  Eigen::Map<const Vector> x0(x0_p) ;
+  Eigen::Map<const Vector> x1(x1_p) ;
+  Eigen::Map<const Vector> x2(x2_p) ;
+
+  //base of the triangle
+  const Vector base = x2-x1 ;
+  const Scalar base_len = base.norm() ;
+  if(base_len == 0) return (x0-x1).norm() ;
+
+  //height of the triangle
+  Vector height = (x0-x1) ;
+  height -= height.dot(base)*base/(base_len*base_len) ;
+  return height.norm() ;
+}
+
+
+/* Area of a triangle */
+template<int Dim, typename Scalar>
+Scalar triangle_area( const Scalar x0_p[Dim],
+                      const Scalar x1_p[Dim],
+                      const Scalar x2_p[Dim]
+                    ) {
+  //vector type
+  typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+
+  //vertices of the triangle
+  Eigen::Map<const Vector> x0(x0_p) ;
+  Eigen::Map<const Vector> x1(x1_p) ;
+  Eigen::Map<const Vector> x2(x2_p) ;
+
+  //base of the triangle
+  const Vector base = x1-x0 ;
+  const Scalar base_len = base.norm() ;
+  if(base_len == 0) return 0 ;
+
+  //height of the triangle
+  Vector height = (x2-x0) ;
+  height -= height.dot(base)*base/(base_len*base_len) ;
+  const Scalar height_len = height.norm() ;
+
+  //area of the triangle
+  return 0.5*height_len*base_len ;
+}
+
+//}}}
+
+/*{{{ Barycentric coordinates of a point whithin a triangle */
+
+template<int Dim, typename Scalar>
+Scalar triangle_barycentric_coords( const Scalar x0_p[Dim],
+                                    const Scalar x1_p[Dim],
+                                    const Scalar x2_p[Dim],
+                                    const Scalar p[Dim],
+                                    Scalar coords[Dim] //output
+                                  ) {
+  const Scalar area0 = triangle_area<Dim>(p, x1_p, x2_p) ;
+  const Scalar area1 = triangle_area<Dim>(x0_p, p, x2_p) ;
+  const Scalar area2 = triangle_area<Dim>(x0_p, x1_p, p) ;
+  const Scalar sum = area0 + area1 + area2 ;
+  coords[0] = area0 / sum ;
+  coords[1] = area1 / sum ;
+  coords[2] = area2 / sum ;
+}
+
+//}}}
+
+/*{{{ Find a projection plane for points based on SVD */
+
+template< typename Scalar, int Dim >
+void svd_plane( 
+    const Scalar* coords, 
+    unsigned int size , 
+    Scalar paramU[Dim], //output
+    Scalar paramV[Dim] //output
+    ) {
+  //std::cout << "Getting svd parametrisation" << std::endl ;
+  //vector type
+  typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+  typedef Eigen::Matrix<Scalar,Dim, Eigen::Dynamic> PtMatrix ;
+
+  //std::cout << "Dim is " << Dim << std::endl ;
+  //std::cout << "Size is " << size << std::endl ;
+
+  //centroid
+  Vector g = Vector::Zero() ;
+  for(unsigned int i = 0; i < size; ++i) {
+    Eigen::Map<const Vector> p(coords + Dim*i) ;
+    g += p ;
+  }
+  g /= size ;
+
+  //point matrix
+  //std::cout << "Initializing matrix" << std::endl ;
+  PtMatrix M(Dim, size) ;
+  //std::cout << "Filling matrix" << std::endl ;
+  for(unsigned int i = 0; i < size; ++i) {
+    Eigen::Map<const Vector> p(coords + Dim*i) ;
+    M.col(i) = p-g ;
+  }
+
+  //svd
+  //std::cout << "SVD" << std::endl ;
+  Eigen::JacobiSVD<PtMatrix> svd(M, Eigen::ComputeFullU) ;
+  //main eigenvectors
+  //std::cout << "Result" << std::endl ;
+  Eigen::Map<Vector> u(paramU) ;
+  u = svd.matrixU().col(0) ;
+  Eigen::Map<Vector> v(paramV) ;
+  v = svd.matrixU().col(1) ;
+  //std::cout << "u vector :" << std::endl << u << std::endl ;
+  //std::cout << "v vector :" << std::endl << v << std::endl ;
+}
+
+//}}}
+
+/*{{{ Disc areas */
+
+/* Area of a disc sector, defined by the disc radius r
+ * and the length d of the chord joining the extremities 
+ * of the sector
+ *
+ *     /\
+ *    /  \ r
+ *   /    \
+ *  /___d__\
+ *  \______/       
+ */
+template<typename Scalar>
+Scalar disc_sector_area( const Scalar radius,
+                         const Scalar chord_len
+                       ) {
+  //sine of half the sector angle
+  const Scalar d = chord_len/(2*radius) ;
+  //check whether the chord is a diameter of the circle
+  if(d >= 1) {
+    //half circle area
+    return 0.5*M_PI*radius*radius ;
+  } else {
+    //angle of the sector
+    Scalar halftheta = asin(d) ;
+    //area
+    return halftheta*radius*radius ;
+  }
+}
+
+/* Area of a circular segment. The parameters are the same as above. */
+template<typename Scalar>
+Scalar circle_segment_area( const Scalar radius,
+                            const Scalar chord_len
+                          ) {
+  //sine of half the sector angle
+  const Scalar d = chord_len/(2*radius) ;
+  //check whether the chord is a diameter of the circle
+  if(d >= 1) {
+    return 0.5*M_PI*radius*radius ;
+  } else {
+    //angle of the sector
+    Scalar theta = 2*asin(d) ;
+    //area
+    return 0.5*(theta-sin(theta))*radius*radius ;
+  }
+}
+
+/* Triangle sphere intersection area */
+namespace triangle_sphere_intersection_area_impl {
+
+template<typename Scalar>
+Scalar tsia_no_vertex_in_circle( const Scalar x0_coords[2], 
+                                 const Scalar x1_coords[2],
+                                 const Scalar x2_coords[2],
+                                 const Scalar c_coords[2],
+                                 Scalar radius
+                               ) {
+  //Vector type
+  typedef Eigen::Matrix<Scalar,2,1> Vector ;
+
+  //radius and circle area
+  const Scalar circle_area = M_PI*radius*radius ;
+
+  Eigen::Map<const Vector> c(c_coords) ;
+  const Scalar* x[3] = {x0_coords, x1_coords, x2_coords} ;
+
+  //compute edge intersections, and sum the circle area out of the triangle
+  Scalar area_out = 0 ;
+  bool intersects = false ;
+  for(int i = 0; i < 3; ++i) {
+    //vertices of the edge
+    Eigen::Map<const Vector> v0(x[i]) ;
+    Eigen::Map<const Vector> v1(x[(i+1)%3]) ;
+    Eigen::Map<const Vector> v2(x[(i+2)%3]) ;
+    const Vector edge = (v1-v0) ;
+
+    //barycentric coordinates of the circle / segment intersection
+    Scalar intersections[2] ;
+    const unsigned char ninter = segment_sphere_intersections<2>( 
+      v0.data(), v1.data(), c.data(), radius, intersections
+    ) ;
+
+    if(ninter > 0) {
+      intersects = true ;
+      //ninter can only be 2 since the two vertices of the edge are out
+      assert( (ninter == 2) 
+              || "The edge intersects once with both vertices out."
+            ) ;
+
+      //positions of the intersections
+      const Vector i0 = v0 + intersections[0]*edge ;
+      const Vector i1 = v0 + intersections[1]*edge ;
+
+      //area of the piece of circle out of that edge
+      const Scalar segment_area = circle_segment_area(radius, (i0-i1).norm()) ;
+
+      //check the side of the edge for the circle center
+      const Vector redge = v2-v0 ;
+      const Vector tedge = c-v0 ;
+      const char in_side = orientation(edge.data(), redge.data()) ;
+      if(orientation(edge.data(), tedge.data()) != in_side) {
+        area_out += circle_area - segment_area ;
+      } else {
+        area_out += segment_area ;
+      }
+    }
+  }
+
+  assert(area_out == area_out) ;
+
+  if(intersects) {
+    //the circle intersects edges, return the circle area minus the area out
+    return circle_area - area_out ;
+  } else {
+    //no edge intersects
+    if(point_in_triangle<2>(c_coords, x0_coords, x1_coords, x2_coords)) {
+      //the circle is completely in the triangle
+      return circle_area ;
+    } else {
+      //the circle is completely out of the triangle
+      return 0 ;
+    }
+  }
+}
+
+/* The vertex inside is x0 */
+template<typename Scalar>
+Scalar tsia_one_vertex_in_circle( const Scalar x0_coords[2], 
+                                  const Scalar x1_coords[2],
+                                  const Scalar x2_coords[2],
+                                  const Scalar c_coords[2],
+                                  Scalar radius
+                                ) {
+  //Vector type
+  typedef Eigen::Matrix<Scalar,2,1> Vector ;
+
+  //radius and circle area
+  const Scalar circle_area = M_PI*radius*radius ;
+
+  Eigen::Map<const Vector> c(c_coords) ;
+  Eigen::Map<const Vector> x0(x0_coords) ;
+  Eigen::Map<const Vector> x1(x1_coords) ;
+  Eigen::Map<const Vector> x2(x2_coords) ;
+  
+  //intersections with the edges adjacent to x0
+  Scalar intersections[2] ;
+  unsigned char ninter ;
+  
+  ninter =  segment_sphere_intersections<2>( 
+    x0.data(), x1.data(), c.data(), radius, intersections
+  ) ;
+  assert( (ninter == 1) 
+          || "x0 should be in the circle and x1 out."
+        ) ;
+  const Vector i01 = x0 + intersections[0]*(x1-x0) ;
+  
+  ninter =  segment_sphere_intersections<2>( 
+    x0.data(), x2.data(), c.data(), radius, intersections
+  ) ;
+  assert( (ninter == 1) 
+          || "x0 should be in the circle and x2 out."
+        ) ;
+  const Vector i02 = x0 + intersections[0]*(x2-x0) ;
+
+  //area without considering the last edge
+  Scalar area = triangle_area<2>(x0_coords, i01.data(), i02.data()) ;
+  const Vector iedge0 = i02 - i01 ;
+  const Vector redge0 = x0 - i01 ;
+  const Vector tedge0 = c - i01 ;
+  const char in_side0 = orientation(iedge0.data(), redge0.data()) ;
+  if(orientation(iedge0.data(), tedge0.data()) != in_side0) {
+    area += circle_area - circle_segment_area(radius, (iedge0).norm()) ;
+  } else {
+    area += circle_segment_area(radius, (iedge0).norm()) ;
+  }
+
+  //check the intersection of the last edge
+  ninter =  segment_sphere_intersections<2>( 
+    x1.data(), x2.data(), c.data(), radius, intersections
+  ) ;
+  if(ninter > 0) {
+    //ninter can only be 2 since the two vertices of the edge are out
+    assert( (ninter == 2) 
+            || "Edge intersects once with both vertices out."
+          ) ;
+
+    //positions of the intersections
+    const Vector edge = (x2-x1) ;
+    const Vector i0 = x1 + intersections[0]*edge ;
+    const Vector i1 = x1 + intersections[1]*edge ;
+
+    //area of the piece of circle out of that edge
+    const Scalar segment_area = circle_segment_area(radius, (i0-i1).norm()) ;
+
+    //check the side of the edge for the circle center
+    const Vector redge = (x0-x1) ;
+    const Vector tedge = (c-x1) ;
+    const char in_side = orientation(edge.data(), redge.data()) ;
+    if(orientation(edge.data(), tedge.data()) != in_side) {
+      area -= circle_area - segment_area ;
+    } else {
+      area -= segment_area ;
+    }
+  }
+  assert(area == area) ;
+  //prevent warning
+  ninter += ninter ;
+  return area ;
+}
+
+/* The vertices inside are x0 and x1 */
+template<typename Scalar>
+Scalar tsia_two_vertices_in_circle( const Scalar x0_coords[2], 
+                                    const Scalar x1_coords[2],
+                                    const Scalar x2_coords[2],
+                                    const Scalar c_coords[2],
+                                    Scalar radius
+                                  ) {
+  //Vector type
+  typedef Eigen::Matrix<Scalar,2,1> Vector ;
+
+  //radius and circle area
+  const Scalar circle_area = M_PI*radius*radius ;
+
+  Eigen::Map<const Vector> c(c_coords) ;
+  Eigen::Map<const Vector> x0(x0_coords) ;
+  Eigen::Map<const Vector> x1(x1_coords) ;
+  Eigen::Map<const Vector> x2(x2_coords) ;
+
+  //intersections with the edges adjacent to x2
+  Scalar intersections[2] ;
+  unsigned char ninter ;
+  
+  ninter =  segment_sphere_intersections<2>( 
+    x0.data(), x2.data(), c.data(), radius, intersections
+  ) ;
+  assert( (ninter == 1) 
+          && "x0 should be in the circle and x2 out."
+        ) ;
+  const Vector i02 = x0 + intersections[0]*(x2-x0) ;
+  
+  ninter =  segment_sphere_intersections<2>( 
+    x1.data(), x2.data(), c.data(), radius, intersections
+  ) ;
+  assert( (ninter == 1) 
+          && "x1 should be in the circle and x2 out."
+        ) ;
+  const Vector i12 = x1 + intersections[0]*(x2-x1) ;
+
+  //area without considering the last edge
+  Scalar area = triangle_area<2>(x0_coords, i02.data(), i12.data()) ;
+  area += triangle_area<2>(x0_coords, x1_coords, i12.data()) ;
+  const Vector iedge = i12 - i02 ;
+  const Vector redge = x0 - i02 ;
+  const Vector tedge = c - i02 ;
+  const char in_side = orientation(iedge.data(), redge.data()) ;
+  if(orientation(iedge.data(), tedge.data()) != in_side) {
+    area += circle_area - circle_segment_area(radius, (iedge).norm()) ;
+  } else {
+    area += circle_segment_area(radius, (iedge).norm()) ;
+  }
+  assert(area == area) ;
+
+  //prevent warning
+  ninter += ninter ;
+  return area ;
+}
+
+template<typename Scalar>
+Scalar tsia_three_vertices_in_circle( const Scalar x0_coords[2], 
+                                      const Scalar x1_coords[2],
+                                      const Scalar x2_coords[2]
+                                    ) {
+  return triangle_area<2>(x0_coords, x1_coords, x2_coords) ;
+}
+
+template< int Dim, typename Scalar >
+class tsia_impl {
+  public:
+  static Scalar do_it( const Scalar x0_coords[Dim],
+                       const Scalar x1_coords[Dim],
+                       const Scalar x2_coords[Dim],
+                       const Scalar c_coords[Dim],
+                       Scalar radius
+                     ) {
+    //vector type
+    typedef Eigen::Matrix<Scalar,Dim,1> Vector ;
+
+    Eigen::Map<const Vector> c(c_coords) ;
+    Eigen::Map<const Vector> x0(x0_coords) ;
+    Eigen::Map<const Vector> x1(x1_coords) ;
+    Eigen::Map<const Vector> x2(x2_coords) ;
+
+    //projection matrix
+    Eigen::Matrix<Scalar,2,Dim,Eigen::RowMajor> P ;
+    //base of the triangle
+    P.row(0) = x1-x0 ;
+    const Scalar base_len = P.row(0).norm() ;
+    if(base_len == 0) return 0 ;
+    P.row(0) /= base_len ;
+  
+    //height of the triangle
+    P.row(1) = x2-x0 ;
+    P.row(1) -= P.row(1).dot(P.row(0))*P.row(0) ;
+    const Scalar height_len = P.row(1).norm() ;
+    if(height_len == 0) return 0 ;
+    P.row(1) /= height_len ;
+
+    //center projection vector
+    Vector cproj = c - x0 ;
+
+    cproj -= cproj.dot(P.row(0))*P.row(0) + cproj.dot(P.row(1))*P.row(1) ;
+    const Scalar p_radius = sqrt(radius*radius - cproj.dot(cproj)) ;
+
+
+    //radius of the circular intersection of the sphere and the triangle plane
+    if(p_radius > 0) {
+      //the sphere intersects the triangle plane
+      //project enerything
+      Eigen::Matrix<Scalar,2,1> cp, x0p, x1p, x2p ;
+      cp = P*(c-x0) ;
+      x0p = Eigen::Matrix<Scalar,2,1>::Zero() ;
+      x1p = P*(x1-x0) ;
+      x2p = P*(x2-x0) ;
+
+      //switch to 2D
+      return tsia_impl<2,Scalar>::do_it( x0p.data(), 
+                                         x1p.data(), 
+                                         x2p.data(), 
+                                         cp.data(), 
+                                         p_radius
+                                       ) ;
+    } else {
+      //the sphere does not intersect the triangle plane
+      return 0 ;
+    }
+  }
+} ;
+
+template< typename Scalar >
+class tsia_impl<2,Scalar> {
+  public:
+  static Scalar do_it( const Scalar x0_coords[2], 
+                       const Scalar x1_coords[2],
+                       const Scalar x2_coords[2],
+                       const Scalar c_coords[2],
+                       Scalar radius
+                     ) {
+    //check vertices inside
+    unsigned char vertex_status ;
+    vertex_status = point_in_sphere<2>(x0_coords, c_coords, radius) ;
+    vertex_status *= 2 ;
+    vertex_status += point_in_sphere<2>(x1_coords, c_coords, radius) ;
+    vertex_status *= 2 ;
+    vertex_status += point_in_sphere<2>(x2_coords, c_coords, radius) ;
+
+    //handle the cases
+    if(vertex_status == 0) {
+      //no vertex_inside
+      return tsia_no_vertex_in_circle( x0_coords, 
+                                       x1_coords, 
+                                       x2_coords, 
+                                       c_coords, 
+                                       radius
+                                     ) ;
+    } else if(vertex_status == 1) {
+      //x2 inside
+      return tsia_one_vertex_in_circle( x2_coords, 
+                                        x0_coords, 
+                                        x1_coords, 
+                                        c_coords, 
+                                        radius
+                                      ) ;
+    } else if(vertex_status == 2) {
+      //x1 inside
+      return tsia_one_vertex_in_circle( x1_coords, 
+                                        x2_coords, 
+                                        x0_coords, 
+                                        c_coords, 
+                                        radius
+                                      ) ;
+    } else if(vertex_status == 3) {
+      //x1 and x2 inside
+      return tsia_two_vertices_in_circle( x1_coords, 
+                                          x2_coords, 
+                                          x0_coords, 
+                                          c_coords, 
+                                          radius
+                                        ) ;
+    } else if(vertex_status == 4) {
+      //x0 inside
+      return tsia_one_vertex_in_circle( x0_coords, 
+                                        x1_coords, 
+                                        x2_coords, 
+                                        c_coords, 
+                                        radius
+                                      ) ;
+    } else if(vertex_status == 5) {
+      //x0 and x2 inside
+      return tsia_two_vertices_in_circle( x2_coords, 
+                                          x0_coords, 
+                                          x1_coords, 
+                                          c_coords, 
+                                          radius
+                                        ) ;
+    } else if(vertex_status == 6) {
+      //x0 and x1 inside
+      return tsia_two_vertices_in_circle( x0_coords, 
+                                          x1_coords, 
+                                          x2_coords, 
+                                          c_coords, 
+                                          radius
+                                        ) ;
+    } else if(vertex_status == 7) {
+      //all vertices inside
+      return tsia_three_vertices_in_circle( x0_coords, 
+                                            x1_coords, 
+                                            x2_coords
+                                          ) ;
+    }
+
+    return 0 ;
+  }
+} ;
+
+} //end of namespace triangle_sphere_intersection_area_impl
+
+/* Triangle sphere intersection area, general case */
+template<int Dim, typename Scalar>
+Scalar triangle_sphere_intersection_area( const Scalar x0_coords[Dim],
+                                          const Scalar x1_coords[Dim],
+                                          const Scalar x2_coords[Dim],
+                                          const Scalar c_coords[Dim],
+                                          Scalar radius
+                                        ) {
+  //bring in the handling of the various cases
+  using namespace triangle_sphere_intersection_area_impl ;
+  
+  return tsia_impl<Dim,Scalar>::do_it( x0_coords,
+                                       x1_coords,
+                                       x2_coords,
+                                       c_coords,
+                                       radius
+                                     ) ;
+}
+
+
+//}}}
+
+/*{{{ Angles */
+
+template<int Dim, typename Scalar>
+Scalar angle_cos( const Scalar p0[Dim], const Scalar p1[Dim], const Scalar p2[Dim]) ;
+
+//}}}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/measure_fwd.hpp b/contrib/Revoropt/include/Revoropt/Tools/measure_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..e22a100cb2f9607fdd11606acfb8f2808e2b70bd
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/measure_fwd.hpp
@@ -0,0 +1,92 @@
+#ifndef _REVOROPT_TOOLS_MEASURE_FWD_HPP_
+#define _REVOROPT_TOOLS_MEASURE_FWD_HPP_
+
+namespace Revoropt {
+
+/*{{{ Triangle height and area */
+
+/* Height of a triangle, passing through the first vertex provided */
+template<int Dim, typename Scalar>
+Scalar triangle_height( const Scalar x0_p[Dim],
+                        const Scalar x1_p[Dim],
+                        const Scalar x2_p[Dim]
+                      ) ;
+
+
+/* Area of a triangle */
+template<int Dim, typename Scalar>
+Scalar triangle_area( const Scalar x0_p[Dim],
+                      const Scalar x1_p[Dim],
+                      const Scalar x2_p[Dim]
+                    ) ;
+
+//}}}
+
+/*{{{ Barycentric coordinates of a point whithin a triangle */
+
+template<int Dim, typename Scalar>
+Scalar triangle_barycentric_coords( const Scalar x0_p[Dim],
+                                    const Scalar x1_p[Dim],
+                                    const Scalar x2_p[Dim],
+                                    const Scalar p[Dim],
+                                    Scalar coords[Dim] //output
+                                  ) ;
+
+//}}}
+
+/*{{{ Find a projection plane for points based on SVD */
+
+template< typename Scalar, int Dim >
+void svd_plane( 
+    const Scalar* coords, 
+    unsigned int size , 
+    Scalar paramU[Dim], //output
+    Scalar paramV[Dim] //output
+    ) ;
+
+//}}}
+
+/*{{{ Disc areas */
+
+/* Area of a disc sector, defined by the disc radius r
+ * and the length d of the chord joining the extremities 
+ * of the sector
+ *
+ *     /\
+ *    /  \ r
+ *   /    \
+ *  /___d__\
+ *  \______/       
+ */
+template<typename Scalar>
+Scalar disc_sector_area( const Scalar radius,
+                         const Scalar chord_len
+                       ) ;
+
+/* Area of a circular segment. The parameters are the same as above. */
+template<typename Scalar>
+Scalar circle_segment_area( const Scalar radius,
+                            const Scalar chord_len
+                          ) ;
+
+/* Triangle sphere intersection area */
+template<int Dim, typename Scalar>
+Scalar triangle_sphere_intersection_area( const Scalar x0_coords[Dim],
+                                          const Scalar x1_coords[Dim],
+                                          const Scalar x2_coords[Dim],
+                                          const Scalar c_coords[Dim],
+                                          Scalar radius
+                                        ) ;
+
+//}}}
+
+/*{{{ Angles */
+
+template<int Dim, typename Scalar>
+Scalar angle_cos( const Scalar p0[Dim], const Scalar p1[Dim], const Scalar p2[Dim]) ;
+
+//}}}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/meta.hpp b/contrib/Revoropt/include/Revoropt/Tools/meta.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..11ccb1dff08f1b8cf2ed1b24efc20ed032fa1d83
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/meta.hpp
@@ -0,0 +1,221 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_TOOLS_META_HPP_
+#define _REVOROPT_TOOLS_META_HPP_
+
+#include <iostream>
+#include <type_traits>
+
+namespace Revoropt {
+
+/* test whether the operator<< for a type exists */
+
+namespace is_printable_impl {
+
+  typedef char yes[1] ;
+  typedef char  no[2] ;
+
+  struct any_t {
+    template<typename T> any_t( const T& ) ;
+  } ;
+
+  no& operator<<(std::ostream const&, const any_t&) ;
+
+  yes& test( std::ostream& ) ;
+  no&  test( no& ) ;
+
+  template<typename T>
+  struct is_printable {
+    static std::ostream &s ;
+    static const T& t ;
+    static const bool value = sizeof(test((s<<t))) == sizeof(yes) ;
+  } ;
+}
+
+template<typename T>
+struct is_printable : is_printable_impl::is_printable<T> {
+} ;
+
+/* automatic dereferencement */
+/* here be dragons */
+
+template <typename T>
+class is_dereferenceable
+{
+    //used to check which of the test methods below is used
+    //in the definition of the value public attribute
+    typedef char yes[1] ;
+    typedef char  no[2] ;
+
+    //this class is only instanciated when *C is legal
+    template <typename C, int sz = sizeof(**static_cast<C*>(NULL))>
+    struct check {} ;
+
+    //this method can only be instanciated if *C is legal
+    template <typename C> static yes &test( check<C>* ) ;
+    //this method is always instanciated
+    template <typename C> static no  &test(    ...    ) ;
+
+  public:
+    //if the size of the return type of the test function used here is yes
+    //the first test function was instanciated, and therefore *T is legal
+    static bool const value = sizeof(test<T>(0)) == sizeof(yes) ;
+} ;
+
+template<typename T>
+class is_dereferenceable<T&>
+{
+  public:
+  static bool const value = is_dereferenceable<T>::value ;
+} ;
+
+/* base type of a pointing chain */
+
+//one dereferencement
+//basic case, fallback when T is non dereferenceable : no type field
+template<typename T, bool chk = false>
+struct one_deref_type_impl {
+} ;
+
+//case when T is a reference non dereferenceable
+template<typename T>
+struct one_deref_type_impl<T&,false> {
+} ;
+
+//basic case for dereferenceables
+//only works for (references to) iterators and pointers
+template<typename T>
+struct one_deref_type_impl<T,true> {
+  typedef typename one_deref_type_impl<
+    typename std::iterator_traits<T>::pointer,
+    true
+  >::type type ;
+} ;
+
+//case for pointers
+template<typename T>
+struct one_deref_type_impl<T*,true> {
+  typedef T type ;
+} ;
+
+//case for references to dereferenceables
+template<typename T>
+struct one_deref_type_impl<T&,true> {
+  typedef typename one_deref_type_impl<T,true>::type type ;
+} ;
+
+//case for const dereferenceables
+template<typename T>
+struct one_deref_type_impl<T const,true> {
+  typedef typename one_deref_type_impl<T,true>::type type ;
+} ;
+
+//encapsulation to mask the boolean attribute, and prevent bad usage : 
+//providing true with T being not dereferenceable
+template<typename T>
+struct one_deref_type {
+  //use the implementation backend
+  typedef typename one_deref_type_impl<
+    T, 
+    is_dereferenceable<T>::value
+  >::type type ;
+} ;
+
+//full dereferencement
+//basic case, fallback when T is non dereferenceable
+template<typename T, bool chk = false>
+struct full_deref_type_impl {
+  typedef T type ;
+} ;
+
+//case when T is dereferenceable
+template<typename T>
+struct full_deref_type_impl<T, true> {
+  //get the basic type of T dereferenced once
+  typedef typename full_deref_type_impl<
+    //define the type of T dereferenced once
+    typename one_deref_type<T>::type,
+    //check whether T dereferenced once is still dereferenceable
+    is_dereferenceable<typename one_deref_type<T>::type>::value
+  >::type type ;
+} ;
+
+//encapsulation to mask the boolean attribute, and prevent bad usage : 
+//providing true with T being not dereferenceable
+template<typename T>
+struct full_deref_type {
+  //use the implementation backend
+  typedef typename full_deref_type_impl<
+    T, 
+    is_dereferenceable<T>::value
+  >:: type type ;
+} ;
+
+/* full dereferencement */
+
+//basic case, fallback when T us not dereferenceable
+template<typename T, bool chk = true>
+class full_deref_impl {
+  public:
+  //take a reference to the value provided to the constructor
+  full_deref_impl( T& _value ) : value(_value) {} ;
+  T& value ;
+} ;
+
+//case when T is dereferenceable
+template<typename T>
+class full_deref_impl<T,true> {
+  //define the type of T dereferenced once
+  //only works for pointers and iterators
+  typedef typename one_deref_type<T>::type deref_type ;
+  public:
+  //get the fully dereferenced value of _value dereferenced once
+  full_deref_impl( T _value ) : value(
+    //recursive call
+    full_deref_impl<
+      deref_type, 
+      //check that T dereferenced once is stille dereferenceable
+      is_dereferenceable<deref_type>::value
+    >(*_value).value
+  ) {} ;
+  //reference on the fully dereferenced value
+  typename full_deref_type<T>::type& value ;
+} ;
+
+//encapsulation in a function, performing full dereferencement,
+//masking the template parameter by automatic deduction
+
+//case when the provided type is dereferenceable : no reference
+template<typename T>
+typename std::enable_if<
+  is_dereferenceable<T>::value,
+  typename full_deref_type<T>::type&
+>::type full_deref( T dereferenceable ) {
+  //use the implementation backend
+  return full_deref_impl<
+    T, 
+    is_dereferenceable<T>::value
+  >(dereferenceable).value ;
+}
+
+//case when the provided type is not dereferenceable : reference
+template<typename T>
+typename std::enable_if<
+  !is_dereferenceable<T>::value,
+  T&
+>::type full_deref( T& non_dereferenceable ) {
+  //use the implementation backend
+  return non_dereferenceable ;
+}
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/normals_def.hpp b/contrib/Revoropt/include/Revoropt/Tools/normals_def.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..410fb4a627a6caf4af97c934e95316ecec79d215
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/normals_def.hpp
@@ -0,0 +1,60 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_TOOLS_NORMALS_DEF_HPP_
+#define _REVOROPT_TOOLS_NORMALS_DEF_HPP_
+
+#include <eigen3/Eigen/Dense>
+
+/* Normal of a triangle, with the triangle area as norm */
+template<typename Scalar>
+void triangle_area_normal( const Scalar* x0_p,
+                           const Scalar* x1_p,
+                           const Scalar* x2_p,
+                           Scalar output[3]
+                         ) {
+  //vector type
+  typedef Eigen::Matrix<Scalar,3,1> Vector ;
+  //map vertices to eigen vectors
+  Eigen::Map< const Vector> x0(x0_p) ;
+  Eigen::Map< const Vector> x1(x1_p) ;
+  Eigen::Map< const Vector> x2(x2_p) ;
+
+  //map output to an eigen vector
+  Eigen::Map<Vector> normal(output) ;
+
+  //compute
+  normal = 0.5*(x1-x0).cross(x2-x0) ;
+}
+
+/* Normalized normal of a triangle, null if the triangle is flat */
+template<typename Scalar>
+Scalar triangle_normal( const Scalar* x0_p,
+                        const Scalar* x1_p,
+                        const Scalar* x2_p,
+                        Scalar output[3]
+                      ) {
+  //vector type
+  typedef Eigen::Matrix<Scalar,3,1> Vector ;
+  //get the area normal
+  triangle_area_normal(x0_p,x1_p,x2_p,output) ;
+
+  //map output to an eigen vector
+  Eigen::Map<Vector> normal(output) ;
+
+  //norm of the normal
+  const Scalar n_len = normal.norm() ;
+  if(n_len != 0) {
+    normal /= n_len ;
+  }
+  return n_len ;
+}
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/Tools/normals_fwd.hpp b/contrib/Revoropt/include/Revoropt/Tools/normals_fwd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f5d550ee56f6cce513e38d9e02a4979c1062ced2
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/Tools/normals_fwd.hpp
@@ -0,0 +1,30 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_TOOLS_NORMALS_FWD_HPP_
+#define _REVOROPT_TOOLS_NORMALS_FWD_HPP_
+
+/* Normal of a triangle, with the triangle area as norm */
+template<typename Scalar>
+void triangle_area_normal( const Scalar* x0_p,
+                           const Scalar* x1_p,
+                           const Scalar* x2_p,
+                           Scalar output[3]
+                         ) ;
+
+/* Normalized normal of a triangle, null if the triangle is flat */
+template<typename Scalar>
+Scalar triangle_normal( const Scalar* x0_p,
+                        const Scalar* x1_p,
+                        const Scalar* x2_p,
+                        Scalar output[3]
+                      ) ;
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/VSDM/.gitignore b/contrib/Revoropt/include/Revoropt/VSDM/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..dc221b0db2dbcc2d02a2d77125f50bf3e588ac74
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/VSDM/.gitignore
@@ -0,0 +1,2 @@
+VSDMRegul.os
+VSDMSampler.os
diff --git a/contrib/Revoropt/include/Revoropt/VSDM/minimizer.hpp b/contrib/Revoropt/include/Revoropt/VSDM/minimizer.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..cadbf1951d90ab0a3d83efcec27235ac80898897
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/VSDM/minimizer.hpp
@@ -0,0 +1,290 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_VSDM_MINIMIZER_HPP_
+#define _REVOROPT_VSDM_MINIMIZER_HPP_
+
+#include "regul.hpp"
+#include "sampler.hpp"
+
+#include <Revoropt/RVD/rvd.hpp>
+#include <Revoropt/CVT/minimizer.hpp>
+#include <Revoropt/Mesh/base_def.hpp>
+#include <Revoropt/Mesh/wrapper_def.hpp>
+
+#include <vector>
+
+namespace Revoropt {
+
+namespace VSDM {
+
+enum SamplerSetting {
+  SAMPLER_NONE,
+  SAMPLER_MIDFACE
+} ;
+
+enum DiffSamplerSetting {
+  DIFF_SAMPLER_NONE,
+  DIFF_SAMPLER_MIDFACE
+} ;
+
+template< typename TMesh, typename SMesh>
+class ObjFun {
+
+  public :
+  
+  enum {Dim = TMesh::VertexDim} ;
+  typedef ROMeshWrapper<
+      SMesh::FaceSize, 
+      SMesh::VertexDim,
+      typename SMesh::Scalar,
+      SMesh::VertexOffset
+    > SMeshWrapper ;
+
+  ObjFun( 
+      bool reset_gradient = true
+      ) :
+    direct_obj_fun_(false),
+    inverse_obj_fun_(false),
+    regul_obj_fun_(false),
+    target_sampler_(NULL),
+    source_sampler_(NULL),
+    global_factor_(1),
+    direct_factor_(1),
+    inverse_factor_(0),
+    regul_factor_(1),
+    reset_gradient_(reset_gradient) 
+  {}
+
+  ~ObjFun() {
+    delete target_sampler_ ;
+    delete source_sampler_ ;
+  }
+
+  /* Callback to compute the objective function */
+
+  template< typename Data >
+  double operator()( Data* data ) {
+    if(reset_gradient_) {
+      std::fill(data->g, data->g+data->n,0) ;
+    }
+
+    double fx = 0 ;
+    if(global_factor_ > 0) {
+      if(inverse_factor_ > 0) {
+        fx += compute_inverse_CVT(data) ;
+      }
+      if(regul_factor_ > 0) {
+        fx += compute_regul(data) ;
+      }
+      if(direct_factor_ > 0) {
+        fx += compute_direct_CVT(data) ;
+      }
+    }
+    return fx ;
+  }
+
+  /* Weighting the terms of the objective function */
+
+  void set_global_factor( double factor ) {
+    global_factor_ = factor ;
+  }
+  void set_direct_factor( double factor ) {
+    direct_factor_ = factor ;
+  }
+  void set_inverse_factor( double factor ) {
+    inverse_factor_ = factor ;
+  }
+  void set_regul_factor( double factor ) {
+    regul_factor_ = factor ;
+  }
+
+  /* Mesh setting */
+
+  void set_target(const TMesh* mesh) {
+    target_mesh_ = mesh ;
+    direct_obj_fun_.set_mesh(target_mesh_) ;
+    if(target_sampler_) {
+      target_sampler_->set_mesh(target_mesh_) ;
+      inverse_obj_fun_.set_sites(
+          target_sampler_->samples(), 
+          target_sampler_->sample_size()
+      ) ;
+    } else {
+      inverse_obj_fun_.set_sites(
+          target_mesh_->vertices(), 
+          target_mesh_->vertices_size()
+      ) ;
+    }
+  }
+
+  void set_source(SMesh* mesh) {
+    source_mesh_.wrap(mesh) ;
+    variables_ = mesh->vertices() ;
+    variables_size_ = Dim * mesh->vertices_size() ;
+    if(source_sampler_) {
+      source_sampler_->set_mesh(&source_mesh_) ;
+    }
+    regul_obj_fun_.build_matrix(&source_mesh_) ;
+  }
+
+  /* CVT parameters */
+
+  //FIXME
+  ////TODO handle inverse anisotropy
+  //void set_anisotropy( double anisotropy ) ;
+  ////TODO use a separate edge RVD on edge meshes for boundary fitting
+  //void set_border_weight( double border_weight ) ;
+
+  /* Sampler setting */
+
+  void set_target_sampler( SamplerSetting sampler_type ) {
+    //cleanup previous sampler
+    delete target_sampler_ ;
+
+    switch(sampler_type){
+      case SAMPLER_NONE: 
+        {
+          //none defaults to vertex sampling, which is specially treated
+          target_sampler_ = NULL ;
+          break ;
+        }
+      case SAMPLER_MIDFACE: 
+        {
+          //one sample per face center
+          target_sampler_ = new MidFaceSampler<TMesh> ;
+          break ;
+        }
+    }
+
+    if(target_sampler_ && target_mesh_) {
+      target_sampler_->set_mesh(target_mesh_) ;
+    }
+  }
+
+  void set_source_sampler( DiffSamplerSetting diff_sampler_type ) {
+    //cleanup previous sampler
+    delete source_sampler_ ;
+
+    switch(diff_sampler_type){
+      case DIFF_SAMPLER_NONE: 
+        {
+          //none defaults to vertex sampling, which is specially treated
+          source_sampler_ = NULL ;
+          break ;
+        }
+      case DIFF_SAMPLER_MIDFACE: 
+        {
+          //one sample per face center
+          source_sampler_ = new MidFaceSampler<SMeshWrapper> ;
+          break ;
+        }
+    }
+
+    if(source_sampler_) {
+      source_sampler_->set_mesh(&source_mesh_) ;
+    }
+  }
+
+  /* minimization */
+  template<typename Solver>
+  int minimize( unsigned int iterations ) {
+    Solver solver ;
+    return solver.solve(variables_, variables_size_, this, iterations) ;
+  }
+
+  template<typename Solver, typename IterCallback>
+  int minimize( unsigned int iterations, IterCallback* iter_callback ) {
+    Solver solver ;
+    return solver.solve(variables_, variables_size_, this, iterations, iter_callback) ;
+  }
+
+  private :
+
+  /*Computing the different terms */
+  template<typename Data>
+  double compute_direct_CVT( Data* data ) {
+    direct_obj_fun_.set_factor(global_factor_*direct_factor_) ;
+    if(!source_sampler_) {
+      //no sampling, use default behaviour
+      direct_obj_fun_.set_sites(data->x, data->n/Dim) ;
+      return direct_obj_fun_(data->g) ;
+    } else {
+      //a sampler is used
+      source_mesh_.set_vertices(data->x, data->n/Dim) ;
+      source_sampler_->set_mesh(&source_mesh_) ;
+      //reset the gradient wrt the samples
+      source_sample_grad_.assign(Dim*source_sampler_->sample_size(), 0) ;
+      //compute the gradient and value wrt. the samples
+      direct_obj_fun_.set_sites(
+          source_sampler_->samples(), 
+          source_sampler_->sample_size()
+          ) ;
+      double fx = direct_obj_fun_( 
+          source_sample_grad_.data()
+          ) ;
+      //chain to the gradient wrt. the template mesh vertices
+      source_sampler_->chain_derivative( 
+          source_sample_grad_.data(),
+          data->g,
+          false
+          ) ;
+      //return function value
+      return fx ;
+    }
+  }
+  
+  template<typename Data>
+  double compute_inverse_CVT( Data* data ) {
+    inverse_obj_fun_.set_factor(global_factor_*inverse_factor_) ;
+    source_mesh_.set_vertices(data->x, data->n/Dim) ;
+    inverse_obj_fun_.set_mesh(&source_mesh_) ;
+    return inverse_obj_fun_(data->g) ;
+  }
+  
+  template<typename Data>
+  double compute_regul( Data* data ) {
+    regul_obj_fun_.set_factor(global_factor_*regul_factor_) ;
+    return regul_obj_fun_(data) ;
+  }
+
+  /* Meshes */
+  const TMesh* target_mesh_ ;
+  SMeshWrapper source_mesh_ ;
+
+  /* Variables */
+  double* variables_ ;
+  unsigned int variables_size_ ;
+
+  /* Objective functions */
+  CVT::DirectObjFun<TMesh> direct_obj_fun_ ;
+  CVT::InverseObjFun<SMeshWrapper> inverse_obj_fun_ ;
+  RegulTerm<Dim> regul_obj_fun_ ;
+  
+  /* Samplers */
+  Sampler<TMesh>* target_sampler_ ;
+  DiffSampler<SMeshWrapper>* source_sampler_ ;
+  std::vector<double> source_sample_grad_ ;
+
+  /* Parameters */
+  double global_factor_ ;
+  double direct_factor_ ;
+  double inverse_factor_ ;
+  double regul_factor_ ;
+
+  bool reset_gradient_ ;
+
+} ;
+
+} //end of namespace VSDM
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/VSDM/regul.hpp b/contrib/Revoropt/include/Revoropt/VSDM/regul.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a49e641284dc630e2d2b536da40c62dcff06f69c
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/VSDM/regul.hpp
@@ -0,0 +1,167 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_VSDM_REGUL_HPP_
+#define _REVOROPT_VSDM_REGUL_HPP_
+
+#include <Revoropt/RVD/rvd.hpp>
+
+#include <eigen3/Eigen/Dense>
+#include <eigen3/Eigen/Sparse>
+
+namespace Revoropt {
+
+namespace VSDM {
+
+//add the opportunity to modify the value of an Eigen::Triplet
+class my_triplet : public Eigen::Triplet<double> {
+
+  public:
+
+  my_triplet(unsigned int i, unsigned int j, double value) :
+    Eigen::Triplet<double>(i,j,value) {
+  }
+
+  //incrementation
+  void incr_value() {
+    ++m_value ;
+  }
+  //new value
+  void set_value( double value ) {
+    m_value = value ;
+  }
+} ;
+
+template<int Dim>
+class RegulTerm {
+
+  public :
+
+  RegulTerm(bool reset_gradient = true) : 
+      reset_gradient_(reset_gradient),
+      factor_(1)
+  {}
+
+  /* Change the factor value. The default factor is 1/vsize where vsize is the
+   * number of vertices of the mesh. The provided factor will be divided by 
+   * vsize as well.*/
+  template<typename Mesh>
+  void build_matrix(const Mesh* mesh) {
+    //Size of the matrix
+    unsigned int vsize = mesh->vertices_size() ;
+
+    //Use triplets to encode a sparse matrix
+    std::vector<my_triplet> triplets ;
+    //1 coeff per vertex plus 2 per edge. At least 3*face_size/2 edges.
+    triplets.reserve(vsize + 3*mesh->faces_size()) ;
+    //the first triplets correspond to the vertices of the mesh
+    for(unsigned int i = 0; i < vsize; ++i) {
+      //assign the col and row of the diagonal coeffs
+      triplets.push_back(my_triplet(i,i,0)) ;
+    }
+    //Build the quatratic form matrix
+    for(unsigned int f = 0; f < mesh->faces_size(); ++f) {
+      //face data
+      const unsigned int fsize = mesh->face_size(f) ;
+      const unsigned int* fverts = mesh->face(f) ;
+      const unsigned int* fneigh = mesh->face_neighbours(f) ;
+
+      //iterate on edges to build edge coeffs and count edges for a vertex
+      for(unsigned int v = 0; v < fsize; ++v) {
+        //get the vertices of the edge
+        unsigned int v1 = fverts[ v         ] ;
+        unsigned int v2 = fverts[(v+1)%fsize] ;
+
+        //to avoid treating edges twice, check canonical order
+        if(f < fneigh[v]) {
+          //increase vertex neighbourhood size
+          triplets[v1].incr_value() ;
+          triplets[v2].incr_value() ;
+
+          //add coefficients
+          triplets.push_back(my_triplet(v1,v2,1)) ;
+          triplets.push_back(my_triplet(v2,v1,1)) ;
+        }
+      }
+    }
+
+    //Divide each edge coeff by the vertex neighbourhood size corresponding to its vertex
+    for(unsigned int i = vsize; i < triplets.size(); ++i) {
+      my_triplet& coeff = triplets[i] ;
+      coeff.set_value(coeff.value()/triplets[coeff.row()].value()) ;
+    }
+
+    //Reset diagonal coeffs to -1
+    for(unsigned int i = 0; i < vsize; ++i) {
+      //std::cout << "Diagonal triplet has value " << triplets[i].value() << std::endl ;
+      triplets[i].set_value(-1) ;
+    }
+
+    //Build matrix
+    L_.resize(vsize, vsize) ;
+    L_.setFromTriplets(triplets.begin(), triplets.end()) ;
+  }
+
+  void set_factor( double factor ) {
+    factor_ = factor ;
+  }
+
+  template<typename Data>
+  double operator()( Data* data ) {
+    if(reset_gradient_) {
+      std::fill(data->g, data->g+data->n,0) ;
+    }
+
+    double fx = 0 ;
+
+    //accumulate result for each coordinate
+    for(int i = 0; i < Dim; ++i) {
+      //Map the raw pointer data to Eigen vector
+      Eigen::Map< Eigen::VectorXd, 
+        Eigen::Unaligned, 
+        Eigen::Stride<0,Dim> 
+          > g(data->g+i, data->n/Dim) ;
+      Eigen::Map< const Eigen::VectorXd,
+        Eigen::Unaligned,
+        Eigen::Stride<0,Dim>
+          > x(data->x+i, data->n/Dim) ;
+      //std::cout << "X norm is " << x.norm() << std::endl ;
+
+      //Compute function falue
+      const Eigen::VectorXd Lx = L_*x ;
+      //std::cout << "LX norm is " << Lx.norm() << std::endl ;
+      fx += Lx.dot(Lx) ;
+      //std::cout << "fx is " << fx << std::endl ;
+      //std::cout << "factor is " << factor_ << std::endl ;
+
+      //Compute gradient, normalized by the vertex size
+      g.noalias() = g + 2*Dim*factor_*L_.transpose()*Lx/data->n ;
+    }
+
+    //Return function value normalized by vertex size
+    return Dim*factor_*fx/data->n ;
+  }
+
+  private :
+  /* indicates whether the provided gradient should be reset to 0 */
+  bool reset_gradient_ ;
+
+  /* factor weighting the objective function, initialized to 1 */
+  double factor_ ;
+
+  /* Matrix storing the neighbourhoods */
+  Eigen::SparseMatrix<double> L_ ;
+} ;
+
+} //end of namespace VSDM
+
+} //end of namespace Revoropt
+
+#endif
diff --git a/contrib/Revoropt/include/Revoropt/VSDM/sampler.hpp b/contrib/Revoropt/include/Revoropt/VSDM/sampler.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..9cae83c3f30c628d7cf0a5ba0be47660e8f182d4
--- /dev/null
+++ b/contrib/Revoropt/include/Revoropt/VSDM/sampler.hpp
@@ -0,0 +1,263 @@
+// @licstart revoropt
+// This file is part of Revoropt, a library for the computation and 
+// optimization of restricted Voronoi diagrams.
+//
+// Copyright (C) 2013 Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// @licend revoropt
+#ifndef _REVOROPT_VSDM_SAMPLER_H_
+#define _REVOROPT_VSDM_SAMPLER_H_
+
+#include <eigen3/Eigen/Sparse>
+#include <vector>
+
+namespace Revoropt {
+
+namespace VSDM {
+
+/** Generic sampler classes **/
+
+/* Sample a mesh */
+
+template<typename Mesh>
+class Sampler {
+
+  public :
+
+  virtual ~Sampler() {}
+
+  /** Typedefs **/
+  typedef typename Mesh::Scalar Scalar ;
+  enum { Dim = Mesh::VertexDim } ;
+
+  /** Construction **/
+
+  /* Set the mesh to sample */
+  virtual void set_mesh( const Mesh* mesh ) = 0 ;
+
+  /** Access **/
+
+  /* Provides the sample points. If no mesh was set, returns NULL */
+  const double* samples() const { return samples_.data() ; }
+  double* samples() { return samples_.data() ; }
+  unsigned int sample_size() const { return samples_.size()/Dim ; }
+
+  protected :
+
+  /* Samples */
+  std::vector<double> samples_ ;
+
+} ;
+
+/* Sample and compute the derivatives of the samples wrt. the mesh vertices */
+
+template<typename Mesh>
+class DiffSampler : public Sampler<Mesh> {
+
+  protected :
+
+  typedef Sampler<Mesh> Base ;
+  using Base::Scalar ;
+  using Base::Dim ;
+  using Base::samples_ ;
+
+  public :
+
+  using Base::samples ;
+  using Base::sample_size ;
+
+  virtual ~DiffSampler() {}
+
+  /** Differenciation **/
+
+  /* Transfer a derivative wrt the samples to a derivative wrt. the vertices */
+
+  virtual void chain_derivative( 
+      const double* sample_derivative,
+      double* vertex_derivative,
+      bool reset_output = true
+      ) const = 0 ;
+
+} ;
+
+/* Linearly sample a mesh */
+
+template<typename Mesh>
+class LinearSampler : public DiffSampler<Mesh> {
+
+  protected :
+
+  typedef DiffSampler<Mesh> Base ;
+  using Base::Scalar ;
+  using Base::Dim ;
+  using Base::samples_ ;
+
+  public :
+
+  using Base::samples ;
+  using Base::sample_size ;
+
+  virtual ~LinearSampler() {}
+
+  virtual void set_mesh( const Mesh* mesh ) {
+    //map the sample coordinates in a sample_size_ x 3 matrix
+    Eigen::Map< Eigen::Matrix<double,Eigen::Dynamic,Dim>,
+                Eigen::Unaligned,
+                Eigen::Stride<1,Dim>
+              > sample_coord(samples(), sample_size(), Dim) ;
+
+    //map the mesh vertex coordinates in a vertex_size x 3 matrix
+    Eigen::Map< const Eigen::Matrix<double,Eigen::Dynamic,Dim>,
+                Eigen::Unaligned,
+                Eigen::Stride<1,Dim>
+              > vertex_coord(mesh->vertices(), mesh->vertices_size(), Dim) ;
+
+    //apply linear combinations
+    sample_coord = S_*vertex_coord ;
+  }
+
+  /** Differenciation **/
+
+  void chain_derivative( 
+      const double* sample_derivative,
+      double* vertex_derivative,
+      bool reset_output = true
+      ) const {
+    //map the sample coordinates in a sample_size_ x 3 matrix
+    Eigen::Map< 
+        const Eigen::Matrix<double,Eigen::Dynamic,Dim>,
+        Eigen::Unaligned,
+        Eigen::Stride<1,Dim>
+      > sdiff(sample_derivative, sample_size(), Dim) ;
+
+    //map the mesh vertex coordinates in a vertex_size x 3 matrix
+    Eigen::Map< 
+        Eigen::Matrix<double,Eigen::Dynamic,Dim>,
+        Eigen::Unaligned,
+        Eigen::Stride<1,Dim>
+      > vdiff(vertex_derivative, S_.cols(), Dim) ;
+
+    //apply linear combinations backwards
+    if(reset_output) {
+      vdiff = S_.transpose()*sdiff ;
+    } else {
+      vdiff.noalias() = vdiff + S_.transpose()*sdiff ;
+    }
+  }
+
+
+  protected :
+
+  /* Linear coefficients are stored as a sparse matrix */
+  Eigen::SparseMatrix<double> S_ ;
+
+} ;
+
+/** Some particular samplers **/
+
+/* Vertex sampler */
+
+template<typename Mesh>
+class VertexSampler : public DiffSampler<Mesh> {
+
+  protected :
+
+  typedef DiffSampler<Mesh> Base ;
+  using Base::Scalar ;
+  using Base::Dim ;
+  using Base::samples_ ;
+
+  public :
+
+  using Base::samples ;
+  using Base::sample_size ;
+
+  virtual ~VertexSampler() {}
+
+  /* set the mesh to sample */
+  void set_mesh( const Mesh* mesh ) {
+    samples_.assign(
+        mesh->vertices(), 
+        mesh->vertices() + Dim * mesh->vertices_size()
+        ) ;
+  }
+
+  /** Differenciation **/
+
+  void chain_derivative( const double* sample_derivative,
+                         double* vertex_derivative,
+                         bool reset_output = true
+                       ) const {
+    std::copy( 
+        sample_derivative, 
+        sample_derivative + Dim * sample_size(), 
+        vertex_derivative
+        ) ;
+  }
+
+} ;
+
+/* Mid face sampler : one sample per face, at the centroid */
+
+template<typename Mesh>
+class MidFaceSampler : public LinearSampler<Mesh> {
+
+  protected :
+
+  typedef LinearSampler<Mesh> Base ;
+  using Base::Scalar ;
+  using Base::Dim ;
+  using Base::samples_ ;
+  using Base::S_ ;
+
+  public :
+
+  using Base::samples ;
+  using Base::sample_size ;
+
+  virtual ~MidFaceSampler() {}
+
+  /* set the mesh to sample */
+  void set_mesh( const Mesh* mesh ) {
+    //the number of samples is the number of faces
+    samples_.resize(Dim * mesh->faces_size()) ;
+
+    //generate the matrix with the linear combinations
+    std::vector< Eigen::Triplet<double> > triplets ;
+    //each sample linearly depends at least on three vertices
+    triplets.reserve(3*sample_size()) ;
+
+    //generate the coeffs per face/sample
+    for(unsigned int f = 0; f < mesh->faces_size(); ++f) {
+      //size of the face
+      const unsigned int fsize = mesh->face_size(f) ;
+      //recover the vertices of the face
+      const unsigned int* fverts = mesh->face(f) ;
+      //barycentric coeff for this face
+      const double coeff = 1./fsize ;
+      //buid one coeff per vertex
+      for(unsigned int v = 0; v < fsize; ++v) {
+        triplets.push_back(
+            Eigen::Triplet<double>(f,fverts[v],coeff)
+            ) ;
+      }
+    }
+
+    //assemble the matrix from the triplets
+    S_.resize(sample_size(),mesh->vertices_size()) ;
+    S_.setFromTriplets(triplets.begin(), triplets.end()) ;
+
+    //call parent method
+    Base::set_mesh(mesh) ;
+  }
+
+} ;
+
+} //end of namespace VSDM
+
+} //end of namespace Revoropt
+
+#endif