diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0f2651e5ed8be1515f61c146a95e9d1a934fefb5..428bd386eb1aee5533d2d9040d1577e4423ddafd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,22 +2,37 @@ cmake_minimum_required(VERSION 3.8)
 
 # name of the project
 project(projet-stage)
-
 set(CMAKE_CXX_STANDARD 11)
 
+# Search for library TTK/VTK
 find_package(TTKVTK REQUIRED)
 
+# Add src files
 add_executable(projet-stage main.cpp operation_mesh.cpp vtkOFFReader.cxx)
-
 target_link_libraries(projet-stage
   PUBLIC
     ttk::vtk::ttkAll
   PRIVATE ${VTK_LIBRARIES}
     )
     
-# vtk_module_autoinit is needed
+# Adding vtkPolyDataToGraph
+add_library(vtkPolyDataToGraph STATIC vtkPolyDataToGraph.cxx)
+target_link_libraries(vtkPolyDataToGraph 
+  PUBLIC
+    ttk::vtk::ttkAll
+  PRIVATE ${VTK_LIBRARIES}
+    )
+
+# vtp2dot executable
+add_executable(vpt2dot vpt2dot.cxx vtkPolyDataToGraph.cxx)
+target_link_libraries(vpt2dot
+  PUBLIC
+    vtkPolyDataToGraph ttk::vtk::ttkAll
+  PRIVATE ${VTK_LIBRARIES}
+    )
+
+# vtk_module
 vtk_module_autoinit(
-  TARGETS projet-stage
-  MODULES ${VTK_LIBRARIES}
-)
-    
+    TARGETS projet-stage vpt2dot
+    MODULES ${VTK_LIBRARIES}
+)
\ No newline at end of file
diff --git a/vpt2dot.cxx b/vpt2dot.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..59997ebed634db610922f0af14cbf476d4280b33
--- /dev/null
+++ b/vpt2dot.cxx
@@ -0,0 +1,86 @@
+#include <vtkSmartPointer.h>
+#include <vtkXMLPolyDataReader.h>
+#include <vtkCommand.h>
+#include <vtkGraphToPolyData.h>
+#include "vtkPolyDataToGraph.h"
+#include "vtkBoostGraphAdapter.h"
+
+#include <boost/graph/graphviz.hpp>
+
+#include <vtkCallbackCommand.h>
+#include <vtkCommand.h>
+
+#define VTK_CREATE(type, name) vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
+
+void FilterEventHandlerVTK(vtkObject *caller, long unsigned int eventId, void *clientData, void *callData)
+{
+
+    vtkAlgorithm *filter = static_cast<vtkAlgorithm *>(caller);
+
+    switch (eventId)
+    {
+    case vtkCommand::ProgressEvent:
+        fprintf(stderr, "\r%s progress: %5.1f%%", filter->GetClassName(), 100.0 * filter->GetProgress()); // stderr is flushed directly
+        break;
+    case vtkCommand::EndEvent:
+        std::cerr << std::endl
+                  << std::flush;
+        break;
+
+        //// VTK does not throw errors (http://public.kitware.com/pipermail/vtkusers/2009-February/050805.html) use Error-Events: http://www.cmake.org/Wiki/VTK/Examples/Cxx/Utilities/ObserveError
+    case vtkCommand::ErrorEvent:
+        std::cerr << "Error: " << static_cast<char *>(callData) << std::endl
+                  << std::flush;
+        break;
+    case vtkCommand::WarningEvent:
+        std::cerr << "Warning: " << static_cast<char *>(callData) << std::endl
+                  << std::flush;
+        break;
+    }
+}
+
+int main(int argc, char *argv[])
+{
+
+    if (argc != 3)
+    {
+        std::cerr << "Usage: " << argv[0]
+                  << " input"
+                  << " output"
+                  << std::endl;
+        return EXIT_FAILURE;
+    }
+
+    if (!(strcasestr(argv[1], ".vtp")))
+    {
+        std::cerr << "The input should end with .vtp" << std::endl;
+        return -1;
+    }
+
+    if (!(strcasestr(argv[2], ".dot") || strcasestr(argv[2], ".gv")))
+    {
+        std::cerr << "The output should end with .dot or .gv" << std::endl;
+        return -1;
+    }
+
+    VTK_CREATE(vtkCallbackCommand, eventCallbackVTK);
+    eventCallbackVTK->SetCallback(FilterEventHandlerVTK);
+
+    VTK_CREATE(vtkXMLPolyDataReader, reader);
+    reader->SetFileName(argv[1]);
+    reader->AddObserver(vtkCommand::AnyEvent, eventCallbackVTK);
+    reader->Update();
+
+    // VTK_CREATE(vtkPolyDataToGraph, filter);
+    vtkSmartPointer<vtkPolyDataToGraph> filter;
+    filter->SetInputConnection(0, reader->GetOutputPort());
+    filter->AddObserver(vtkCommand::AnyEvent, eventCallbackVTK);
+    filter->Update();
+
+    vtkUndirectedGraph *graph = vtkUndirectedGraph::SafeDownCast(filter->GetOutput());
+
+    std::ofstream fout(argv[2]);
+    boost::write_graphviz(fout, graph);
+
+    return EXIT_SUCCESS;
+}
diff --git a/vtkBoostGraphAdapter.h b/vtkBoostGraphAdapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..322c97fdee068b4aa1823a56b676859c243a0259
--- /dev/null
+++ b/vtkBoostGraphAdapter.h
@@ -0,0 +1,1301 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    vtkBoostGraphAdapter.h
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+/*-------------------------------------------------------------------------
+  Copyright 2008 Sandia Corporation.
+  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+  the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------*/
+#ifndef vtkBoostGraphAdapter_h
+#define vtkBoostGraphAdapter_h
+
+#include "vtkAbstractArray.h"
+#include "vtkDataArray.h"
+#include "vtkDataObject.h"
+#include "vtkDirectedGraph.h"
+#include "vtkDistributedGraphHelper.h"
+#include "vtkDoubleArray.h"
+#include "vtkFloatArray.h"
+#include "vtkIdTypeArray.h"
+#include "vtkInformation.h"
+#include "vtkIntArray.h"
+#include "vtkMutableDirectedGraph.h"
+#include "vtkMutableUndirectedGraph.h"
+#include "vtkTree.h"
+#include "vtkUndirectedGraph.h"
+#include "vtkVariant.h"
+
+#include <boost/version.hpp>
+
+namespace boost
+{
+  //===========================================================================
+  // VTK arrays as property maps
+  // These need to be defined before including other boost stuff
+
+  // Forward declarations are required here, so that we aren't forced
+  // to include boost/property_map.hpp.
+  template <typename>
+  struct property_traits;
+  struct read_write_property_map_tag;
+
+#define vtkPropertyMapMacro(T, V)                                                                \
+  template <>                                                                                    \
+  struct property_traits<T *>                                                                    \
+  {                                                                                              \
+    typedef V value_type;                                                                        \
+    typedef V reference;                                                                         \
+    typedef vtkIdType key_type;                                                                  \
+    typedef read_write_property_map_tag category;                                                \
+  };                                                                                             \
+                                                                                                 \
+  inline property_traits<T *>::reference get(T *const &arr, property_traits<T *>::key_type key)  \
+  {                                                                                              \
+    return arr->GetValue(key);                                                                   \
+  }                                                                                              \
+                                                                                                 \
+  inline void put(                                                                               \
+      T *arr, property_traits<T *>::key_type key, const property_traits<T *>::value_type &value) \
+  {                                                                                              \
+    arr->InsertValue(key, value);                                                                \
+  }
+
+  vtkPropertyMapMacro(vtkIntArray, int);
+  vtkPropertyMapMacro(vtkIdTypeArray, vtkIdType);
+  vtkPropertyMapMacro(vtkDoubleArray, double);
+  vtkPropertyMapMacro(vtkFloatArray, float);
+
+  // vtkDataArray
+  template <>
+  struct property_traits<vtkDataArray *>
+  {
+    typedef double value_type;
+    typedef double reference;
+    typedef vtkIdType key_type;
+    typedef read_write_property_map_tag category;
+  };
+
+  inline double get(vtkDataArray *const &arr, vtkIdType key)
+  {
+    return arr->GetTuple1(key);
+  }
+
+  inline void put(vtkDataArray *arr, vtkIdType key, const double &value)
+  {
+    arr->SetTuple1(key, value);
+  }
+
+  // vtkAbstractArray as a property map of vtkVariants
+  template <>
+  struct property_traits<vtkAbstractArray *>
+  {
+    typedef vtkVariant value_type;
+    typedef vtkVariant reference;
+    typedef vtkIdType key_type;
+    typedef read_write_property_map_tag category;
+  };
+
+  inline vtkVariant get(vtkAbstractArray *const &arr, vtkIdType key)
+  {
+    return arr->GetVariantValue(key);
+  }
+
+  inline void put(vtkAbstractArray *arr, vtkIdType key, const vtkVariant &value)
+  {
+    arr->InsertVariantValue(key, value);
+  }
+
+#if defined(_MSC_VER)
+  namespace detail
+  {
+    using ::boost::get;
+    using ::boost::put;
+  }
+#endif
+}
+
+#include <utility> // STL Header
+
+#include <boost/config.hpp>
+#include <boost/version.hpp>
+
+#if BOOST_VERSION > 107300 && BOOST_VERSION < 107600
+#define BOOST_ALLOW_DEPRECATED_HEADERS
+#define BOOST_BIND_GLOBAL_PLACEHOLDERS
+#endif
+
+#include <boost/graph/adjacency_iterator.hpp>
+#include <boost/graph/graph_traits.hpp>
+#include <boost/graph/properties.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+
+// The functions and classes in this file allows the user to
+// treat a vtkDirectedGraph or vtkUndirectedGraph object
+// as a boost graph "as is".
+
+namespace boost
+{
+
+  class vtk_vertex_iterator
+      : public iterator_facade<vtk_vertex_iterator, vtkIdType, bidirectional_traversal_tag,
+                               const vtkIdType &, vtkIdType>
+  {
+  public:
+    explicit vtk_vertex_iterator(vtkIdType i = 0)
+        : index(i)
+    {
+    }
+
+  private:
+    const vtkIdType &dereference() const { return index; }
+
+    bool equal(const vtk_vertex_iterator &other) const { return index == other.index; }
+
+    void increment() { index++; }
+    void decrement() { index--; }
+
+    vtkIdType index;
+
+    friend class iterator_core_access;
+  };
+
+  class vtk_edge_iterator
+      : public iterator_facade<vtk_edge_iterator, vtkEdgeType, forward_traversal_tag,
+                               const vtkEdgeType &, vtkIdType>
+  {
+  public:
+    explicit vtk_edge_iterator(vtkGraph *g = nullptr, vtkIdType v = 0)
+        : directed(false), vertex(v), lastVertex(v), iter(nullptr), end(nullptr), graph(g)
+    {
+      if (graph)
+      {
+        lastVertex = graph->GetNumberOfVertices();
+      }
+
+      vtkIdType myRank = -1;
+      vtkDistributedGraphHelper *helper =
+          this->graph ? this->graph->GetDistributedGraphHelper() : nullptr;
+      if (helper)
+      {
+        myRank = this->graph->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER());
+        vertex = helper->MakeDistributedId(myRank, vertex);
+        lastVertex = helper->MakeDistributedId(myRank, lastVertex);
+      }
+
+      if (graph != nullptr)
+      {
+        directed = (vtkDirectedGraph::SafeDownCast(graph) != nullptr);
+        while (vertex < lastVertex && this->graph->GetOutDegree(vertex) == 0)
+        {
+          ++vertex;
+        }
+
+        if (vertex < lastVertex)
+        {
+          // Get the outgoing edges of the first vertex that has outgoing
+          // edges
+          vtkIdType nedges;
+          graph->GetOutEdges(vertex, iter, nedges);
+          if (iter)
+          {
+            end = iter + nedges;
+
+            if (!directed)
+            {
+              while ( // Skip non-local edges
+                  (helper && helper->GetEdgeOwner(iter->Id) != myRank)
+                  // Skip entirely-local edges where Source > Target
+                  || (((helper && myRank == helper->GetVertexOwner(iter->Target)) || !helper) &&
+                      vertex > iter->Target))
+              {
+                this->inc();
+              }
+            }
+          }
+        }
+        else
+        {
+          iter = nullptr;
+        }
+      }
+
+      RecalculateEdge();
+    }
+
+  private:
+    const vtkEdgeType &dereference() const
+    {
+      assert(iter);
+      return edge;
+    }
+
+    bool equal(const vtk_edge_iterator &other) const
+    {
+      return vertex == other.vertex && iter == other.iter;
+    }
+
+    void increment()
+    {
+      inc();
+      if (!directed)
+      {
+        vtkIdType myRank = -1;
+        vtkDistributedGraphHelper *helper =
+            this->graph ? this->graph->GetDistributedGraphHelper() : nullptr;
+        if (helper)
+        {
+          myRank = this->graph->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER());
+        }
+
+        while (iter != nullptr &&
+               ( // Skip non-local edges
+                   (helper && helper->GetEdgeOwner(iter->Id) != myRank)
+                   // Skip entirely-local edges where Source > Target
+                   || (((helper && myRank == helper->GetVertexOwner(iter->Target)) || !helper) &&
+                       vertex > iter->Target)))
+        {
+          inc();
+        }
+      }
+      RecalculateEdge();
+    }
+
+    void inc()
+    {
+      ++iter;
+      if (iter == end)
+      {
+        // Find a vertex with nonzero out degree.
+        ++vertex;
+        while (vertex < lastVertex && this->graph->GetOutDegree(vertex) == 0)
+        {
+          ++vertex;
+        }
+
+        if (vertex < lastVertex)
+        {
+          vtkIdType nedges;
+          graph->GetOutEdges(vertex, iter, nedges);
+          end = iter + nedges;
+        }
+        else
+        {
+          iter = nullptr;
+        }
+      }
+    }
+
+    void RecalculateEdge()
+    {
+      if (iter)
+      {
+        edge = vtkEdgeType(vertex, iter->Target, iter->Id);
+      }
+    }
+
+    bool directed;
+    vtkIdType vertex;
+    vtkIdType lastVertex;
+    const vtkOutEdgeType *iter;
+    const vtkOutEdgeType *end;
+    vtkGraph *graph;
+    vtkEdgeType edge;
+
+    friend class iterator_core_access;
+  };
+
+  class vtk_out_edge_pointer_iterator
+      : public iterator_facade<vtk_out_edge_pointer_iterator, vtkEdgeType, bidirectional_traversal_tag,
+                               const vtkEdgeType &, ptrdiff_t>
+  {
+  public:
+    explicit vtk_out_edge_pointer_iterator(vtkGraph *g = nullptr, vtkIdType v = 0, bool end = false)
+        : vertex(v), iter(nullptr)
+    {
+      if (g)
+      {
+        vtkIdType nedges;
+        g->GetOutEdges(vertex, iter, nedges);
+        if (end)
+        {
+          iter += nedges;
+        }
+      }
+      RecalculateEdge();
+    }
+
+  private:
+    const vtkEdgeType &dereference() const
+    {
+      assert(iter);
+      return edge;
+    }
+
+    bool equal(const vtk_out_edge_pointer_iterator &other) const { return iter == other.iter; }
+
+    void increment()
+    {
+      iter++;
+      RecalculateEdge();
+    }
+
+    void decrement()
+    {
+      iter--;
+      RecalculateEdge();
+    }
+
+    void RecalculateEdge()
+    {
+      if (iter)
+      {
+        edge = vtkEdgeType(vertex, iter->Target, iter->Id);
+      }
+    }
+
+    vtkIdType vertex;
+    const vtkOutEdgeType *iter;
+    vtkEdgeType edge;
+
+    friend class iterator_core_access;
+  };
+
+  class vtk_in_edge_pointer_iterator
+      : public iterator_facade<vtk_in_edge_pointer_iterator, vtkEdgeType, bidirectional_traversal_tag,
+                               const vtkEdgeType &, ptrdiff_t>
+  {
+  public:
+    explicit vtk_in_edge_pointer_iterator(vtkGraph *g = nullptr, vtkIdType v = 0, bool end = false)
+        : vertex(v), iter(nullptr)
+    {
+      if (g)
+      {
+        vtkIdType nedges;
+        g->GetInEdges(vertex, iter, nedges);
+        if (end)
+        {
+          iter += nedges;
+        }
+      }
+      RecalculateEdge();
+    }
+
+  private:
+    const vtkEdgeType &dereference() const
+    {
+      assert(iter);
+      return edge;
+    }
+
+    bool equal(const vtk_in_edge_pointer_iterator &other) const { return iter == other.iter; }
+
+    void increment()
+    {
+      iter++;
+      RecalculateEdge();
+    }
+
+    void decrement()
+    {
+      iter--;
+      RecalculateEdge();
+    }
+
+    void RecalculateEdge()
+    {
+      if (iter)
+      {
+        edge = vtkEdgeType(iter->Source, vertex, iter->Id);
+      }
+    }
+
+    vtkIdType vertex;
+    const vtkInEdgeType *iter;
+    vtkEdgeType edge;
+
+    friend class iterator_core_access;
+  };
+
+  //===========================================================================
+  // vtkGraph
+  // VertexAndEdgeListGraphConcept
+  // BidirectionalGraphConcept
+  // AdjacencyGraphConcept
+
+  struct vtkGraph_traversal_category
+      : public virtual bidirectional_graph_tag,
+        public virtual edge_list_graph_tag,
+        public virtual vertex_list_graph_tag,
+        public virtual adjacency_graph_tag
+  {
+  };
+
+  template <>
+  struct graph_traits<vtkGraph *>
+  {
+    typedef vtkIdType vertex_descriptor;
+    static vertex_descriptor null_vertex() { return -1; }
+    typedef vtkEdgeType edge_descriptor;
+    static edge_descriptor null_edge() { return vtkEdgeType(-1, -1, -1); }
+    typedef vtk_out_edge_pointer_iterator out_edge_iterator;
+    typedef vtk_in_edge_pointer_iterator in_edge_iterator;
+
+    typedef vtk_vertex_iterator vertex_iterator;
+    typedef vtk_edge_iterator edge_iterator;
+
+    typedef allow_parallel_edge_tag edge_parallel_category;
+    typedef vtkGraph_traversal_category traversal_category;
+    typedef vtkIdType vertices_size_type;
+    typedef vtkIdType edges_size_type;
+    typedef vtkIdType degree_size_type;
+
+    typedef adjacency_iterator_generator<vtkGraph *, vertex_descriptor, out_edge_iterator>::type
+        adjacency_iterator;
+  };
+
+#if BOOST_VERSION >= 104500
+  template <>
+  struct graph_property_type<vtkGraph *>
+  {
+    typedef no_property type;
+  };
+#endif
+
+  template <>
+  struct vertex_property_type<vtkGraph *>
+  {
+    typedef no_property type;
+  };
+
+  template <>
+  struct edge_property_type<vtkGraph *>
+  {
+    typedef no_property type;
+  };
+
+#if BOOST_VERSION >= 104500
+  template <>
+  struct graph_bundle_type<vtkGraph *>
+  {
+    typedef no_property type;
+  };
+#endif
+
+  template <>
+  struct vertex_bundle_type<vtkGraph *>
+  {
+    typedef no_property type;
+  };
+
+  template <>
+  struct edge_bundle_type<vtkGraph *>
+  {
+    typedef no_property type;
+  };
+
+  inline bool has_no_edges(vtkGraph *g)
+  {
+    return ((g->GetNumberOfEdges() > 0) ? false : true);
+  }
+
+  inline void remove_edge(graph_traits<vtkGraph *>::edge_descriptor e, vtkGraph *g)
+  {
+    if (vtkMutableDirectedGraph::SafeDownCast(g))
+    {
+      vtkMutableDirectedGraph::SafeDownCast(g)->RemoveEdge(e.Id);
+    }
+    else if (vtkMutableUndirectedGraph::SafeDownCast(g))
+    {
+      vtkMutableUndirectedGraph::SafeDownCast(g)->RemoveEdge(e.Id);
+    }
+  }
+
+  //===========================================================================
+  // vtkDirectedGraph
+
+  template <>
+  struct graph_traits<vtkDirectedGraph *> : graph_traits<vtkGraph *>
+  {
+    typedef directed_tag directed_category;
+  };
+
+  // The graph_traits for a const graph are the same as a non-const graph.
+  template <>
+  struct graph_traits<const vtkDirectedGraph *> : graph_traits<vtkDirectedGraph *>
+  {
+  };
+
+  // The graph_traits for a const graph are the same as a non-const graph.
+  template <>
+  struct graph_traits<vtkDirectedGraph *const> : graph_traits<vtkDirectedGraph *>
+  {
+  };
+
+#if BOOST_VERSION >= 104500
+  // Internal graph properties
+  template <>
+  struct graph_property_type<vtkDirectedGraph *> : graph_property_type<vtkGraph *>
+  {
+  };
+
+  // Internal graph properties
+  template <>
+  struct graph_property_type<vtkDirectedGraph *const> : graph_property_type<vtkGraph *>
+  {
+  };
+#endif
+
+  // Internal vertex properties
+  template <>
+  struct vertex_property_type<vtkDirectedGraph *> : vertex_property_type<vtkGraph *>
+  {
+  };
+
+  // Internal vertex properties
+  template <>
+  struct vertex_property_type<vtkDirectedGraph *const> : vertex_property_type<vtkGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_property_type<vtkDirectedGraph *> : edge_property_type<vtkGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_property_type<vtkDirectedGraph *const> : edge_property_type<vtkGraph *>
+  {
+  };
+
+#if BOOST_VERSION >= 104500
+  // Internal graph properties
+  template <>
+  struct graph_bundle_type<vtkDirectedGraph *> : graph_bundle_type<vtkGraph *>
+  {
+  };
+
+  // Internal graph properties
+  template <>
+  struct graph_bundle_type<vtkDirectedGraph *const> : graph_bundle_type<vtkGraph *>
+  {
+  };
+#endif
+
+  // Internal vertex properties
+  template <>
+  struct vertex_bundle_type<vtkDirectedGraph *> : vertex_bundle_type<vtkGraph *>
+  {
+  };
+
+  // Internal vertex properties
+  template <>
+  struct vertex_bundle_type<vtkDirectedGraph *const> : vertex_bundle_type<vtkGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_bundle_type<vtkDirectedGraph *> : edge_bundle_type<vtkGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_bundle_type<vtkDirectedGraph *const> : edge_bundle_type<vtkGraph *>
+  {
+  };
+
+  //===========================================================================
+  // vtkTree
+
+  template <>
+  struct graph_traits<vtkTree *> : graph_traits<vtkDirectedGraph *>
+  {
+  };
+
+  // The graph_traits for a const graph are the same as a non-const graph.
+  template <>
+  struct graph_traits<const vtkTree *> : graph_traits<vtkTree *>
+  {
+  };
+
+  // The graph_traits for a const graph are the same as a non-const graph.
+  template <>
+  struct graph_traits<vtkTree *const> : graph_traits<vtkTree *>
+  {
+  };
+
+  //===========================================================================
+  // vtkUndirectedGraph
+  template <>
+  struct graph_traits<vtkUndirectedGraph *> : graph_traits<vtkGraph *>
+  {
+    typedef undirected_tag directed_category;
+  };
+
+  // The graph_traits for a const graph are the same as a non-const graph.
+  template <>
+  struct graph_traits<const vtkUndirectedGraph *> : graph_traits<vtkUndirectedGraph *>
+  {
+  };
+
+  // The graph_traits for a const graph are the same as a non-const graph.
+  template <>
+  struct graph_traits<vtkUndirectedGraph *const> : graph_traits<vtkUndirectedGraph *>
+  {
+  };
+
+#if BOOST_VERSION >= 104500
+  // Internal graph properties
+  template <>
+  struct graph_property_type<vtkUndirectedGraph *> : graph_property_type<vtkGraph *>
+  {
+  };
+
+  // Internal graph properties
+  template <>
+  struct graph_property_type<vtkUndirectedGraph *const> : graph_property_type<vtkGraph *>
+  {
+  };
+#endif
+
+  // Internal vertex properties
+  template <>
+  struct vertex_property_type<vtkUndirectedGraph *> : vertex_property_type<vtkGraph *>
+  {
+  };
+
+  // Internal vertex properties
+  template <>
+  struct vertex_property_type<vtkUndirectedGraph *const> : vertex_property_type<vtkGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_property_type<vtkUndirectedGraph *> : edge_property_type<vtkGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_property_type<vtkUndirectedGraph *const> : edge_property_type<vtkGraph *>
+  {
+  };
+
+#if BOOST_VERSION >= 104500
+  // Internal graph properties
+  template <>
+  struct graph_bundle_type<vtkUndirectedGraph *> : graph_bundle_type<vtkGraph *>
+  {
+  };
+
+  // Internal graph properties
+  template <>
+  struct graph_bundle_type<vtkUndirectedGraph *const> : graph_bundle_type<vtkGraph *>
+  {
+  };
+#endif
+
+  // Internal vertex properties
+  template <>
+  struct vertex_bundle_type<vtkUndirectedGraph *> : vertex_bundle_type<vtkGraph *>
+  {
+  };
+
+  // Internal vertex properties
+  template <>
+  struct vertex_bundle_type<vtkUndirectedGraph *const> : vertex_bundle_type<vtkGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_bundle_type<vtkUndirectedGraph *> : edge_bundle_type<vtkGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_bundle_type<vtkUndirectedGraph *const> : edge_bundle_type<vtkGraph *>
+  {
+  };
+
+  //===========================================================================
+  // vtkMutableDirectedGraph
+
+  template <>
+  struct graph_traits<vtkMutableDirectedGraph *> : graph_traits<vtkDirectedGraph *>
+  {
+  };
+
+  // The graph_traits for a const graph are the same as a non-const graph.
+  template <>
+  struct graph_traits<const vtkMutableDirectedGraph *> : graph_traits<vtkMutableDirectedGraph *>
+  {
+  };
+
+  // The graph_traits for a const graph are the same as a non-const graph.
+  template <>
+  struct graph_traits<vtkMutableDirectedGraph *const> : graph_traits<vtkMutableDirectedGraph *>
+  {
+  };
+
+#if BOOST_VERSION >= 104500
+  // Internal graph properties
+  template <>
+  struct graph_property_type<vtkMutableDirectedGraph *> : graph_property_type<vtkDirectedGraph *>
+  {
+  };
+
+  // Internal graph properties
+  template <>
+  struct graph_property_type<vtkMutableDirectedGraph *const> : graph_property_type<vtkDirectedGraph *>
+  {
+  };
+#endif
+
+  // Internal vertex properties
+  template <>
+  struct vertex_property_type<vtkMutableDirectedGraph *> : vertex_property_type<vtkDirectedGraph *>
+  {
+  };
+
+  // Internal vertex properties
+  template <>
+  struct vertex_property_type<vtkMutableDirectedGraph *const>
+      : vertex_property_type<vtkDirectedGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_property_type<vtkMutableDirectedGraph *> : edge_property_type<vtkDirectedGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_property_type<vtkMutableDirectedGraph *const> : edge_property_type<vtkDirectedGraph *>
+  {
+  };
+
+#if BOOST_VERSION >= 104500
+  // Internal graph properties
+  template <>
+  struct graph_bundle_type<vtkMutableDirectedGraph *> : graph_bundle_type<vtkDirectedGraph *>
+  {
+  };
+
+  // Internal graph properties
+  template <>
+  struct graph_bundle_type<vtkMutableDirectedGraph *const> : graph_bundle_type<vtkDirectedGraph *>
+  {
+  };
+#endif
+
+  // Internal vertex properties
+  template <>
+  struct vertex_bundle_type<vtkMutableDirectedGraph *> : vertex_bundle_type<vtkDirectedGraph *>
+  {
+  };
+
+  // Internal vertex properties
+  template <>
+  struct vertex_bundle_type<vtkMutableDirectedGraph *const> : vertex_bundle_type<vtkDirectedGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_bundle_type<vtkMutableDirectedGraph *> : edge_bundle_type<vtkDirectedGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_bundle_type<vtkMutableDirectedGraph *const> : edge_bundle_type<vtkDirectedGraph *>
+  {
+  };
+
+  //===========================================================================
+  // vtkMutableUndirectedGraph
+
+  template <>
+  struct graph_traits<vtkMutableUndirectedGraph *> : graph_traits<vtkUndirectedGraph *>
+  {
+  };
+
+  // The graph_traits for a const graph are the same as a non-const graph.
+  template <>
+  struct graph_traits<const vtkMutableUndirectedGraph *> : graph_traits<vtkMutableUndirectedGraph *>
+  {
+  };
+
+  // The graph_traits for a const graph are the same as a non-const graph.
+  template <>
+  struct graph_traits<vtkMutableUndirectedGraph *const> : graph_traits<vtkMutableUndirectedGraph *>
+  {
+  };
+
+#if BOOST_VERSION >= 104500
+  // Internal graph properties
+  template <>
+  struct graph_property_type<vtkMutableUndirectedGraph *> : graph_property_type<vtkUndirectedGraph *>
+  {
+  };
+
+  // Internal graph properties
+  template <>
+  struct graph_property_type<vtkMutableUndirectedGraph *const>
+      : graph_property_type<vtkUndirectedGraph *>
+  {
+  };
+#endif
+
+  // Internal vertex properties
+  template <>
+  struct vertex_property_type<vtkMutableUndirectedGraph *> : vertex_property_type<vtkUndirectedGraph *>
+  {
+  };
+
+  // Internal vertex properties
+  template <>
+  struct vertex_property_type<vtkMutableUndirectedGraph *const>
+      : vertex_property_type<vtkUndirectedGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_property_type<vtkMutableUndirectedGraph *> : edge_property_type<vtkUndirectedGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_property_type<vtkMutableUndirectedGraph *const>
+      : edge_property_type<vtkUndirectedGraph *>
+  {
+  };
+
+#if BOOST_VERSION >= 104500
+  // Internal graph properties
+  template <>
+  struct graph_bundle_type<vtkMutableUndirectedGraph *> : graph_bundle_type<vtkUndirectedGraph *>
+  {
+  };
+
+  // Internal graph properties
+  template <>
+  struct graph_bundle_type<vtkMutableUndirectedGraph *const> : graph_bundle_type<vtkUndirectedGraph *>
+  {
+  };
+#endif
+
+  // Internal vertex properties
+  template <>
+  struct vertex_bundle_type<vtkMutableUndirectedGraph *> : vertex_bundle_type<vtkUndirectedGraph *>
+  {
+  };
+
+  // Internal vertex properties
+  template <>
+  struct vertex_bundle_type<vtkMutableUndirectedGraph *const>
+      : vertex_bundle_type<vtkUndirectedGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_bundle_type<vtkMutableUndirectedGraph *> : edge_bundle_type<vtkUndirectedGraph *>
+  {
+  };
+
+  // Internal edge properties
+  template <>
+  struct edge_bundle_type<vtkMutableUndirectedGraph *const> : edge_bundle_type<vtkUndirectedGraph *>
+  {
+  };
+
+  //===========================================================================
+  // API implementation
+  template <>
+  class vertex_property<vtkGraph *>
+  {
+  public:
+    typedef vtkIdType type;
+  };
+
+  template <>
+  class edge_property<vtkGraph *>
+  {
+  public:
+    typedef vtkIdType type;
+  };
+} // end namespace boost
+
+inline boost::graph_traits<vtkGraph *>::vertex_descriptor source(
+    boost::graph_traits<vtkGraph *>::edge_descriptor e, vtkGraph *)
+{
+  return e.Source;
+}
+
+inline boost::graph_traits<vtkGraph *>::vertex_descriptor target(
+    boost::graph_traits<vtkGraph *>::edge_descriptor e, vtkGraph *)
+{
+  return e.Target;
+}
+
+inline std::pair<boost::graph_traits<vtkGraph *>::vertex_iterator,
+                 boost::graph_traits<vtkGraph *>::vertex_iterator>
+vertices(vtkGraph *g)
+{
+  typedef boost::graph_traits<vtkGraph *>::vertex_iterator Iter;
+  vtkIdType start = 0;
+  if (vtkDistributedGraphHelper *helper = g->GetDistributedGraphHelper())
+  {
+    int rank = g->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER());
+    start = helper->MakeDistributedId(rank, start);
+  }
+
+  return std::make_pair(Iter(start), Iter(start + g->GetNumberOfVertices()));
+}
+
+inline std::pair<boost::graph_traits<vtkGraph *>::edge_iterator,
+                 boost::graph_traits<vtkGraph *>::edge_iterator>
+edges(vtkGraph *g)
+{
+  typedef boost::graph_traits<vtkGraph *>::edge_iterator Iter;
+  return std::make_pair(Iter(g), Iter(g, g->GetNumberOfVertices()));
+}
+
+inline std::pair<boost::graph_traits<vtkGraph *>::out_edge_iterator,
+                 boost::graph_traits<vtkGraph *>::out_edge_iterator>
+out_edges(boost::graph_traits<vtkGraph *>::vertex_descriptor u, vtkGraph *g)
+{
+  typedef boost::graph_traits<vtkGraph *>::out_edge_iterator Iter;
+  std::pair<Iter, Iter> p = std::make_pair(Iter(g, u), Iter(g, u, true));
+  return p;
+}
+
+inline std::pair<boost::graph_traits<vtkGraph *>::in_edge_iterator,
+                 boost::graph_traits<vtkGraph *>::in_edge_iterator>
+in_edges(boost::graph_traits<vtkGraph *>::vertex_descriptor u, vtkGraph *g)
+{
+  typedef boost::graph_traits<vtkGraph *>::in_edge_iterator Iter;
+  std::pair<Iter, Iter> p = std::make_pair(Iter(g, u), Iter(g, u, true));
+  return p;
+}
+
+inline std::pair<boost::graph_traits<vtkGraph *>::adjacency_iterator,
+                 boost::graph_traits<vtkGraph *>::adjacency_iterator>
+adjacent_vertices(boost::graph_traits<vtkGraph *>::vertex_descriptor u, vtkGraph *g)
+{
+  typedef boost::graph_traits<vtkGraph *>::adjacency_iterator Iter;
+  typedef boost::graph_traits<vtkGraph *>::out_edge_iterator OutEdgeIter;
+  std::pair<OutEdgeIter, OutEdgeIter> out = out_edges(u, g);
+  return std::make_pair(Iter(out.first, &g), Iter(out.second, &g));
+}
+
+inline boost::graph_traits<vtkGraph *>::vertices_size_type num_vertices(vtkGraph *g)
+{
+  return g->GetNumberOfVertices();
+}
+
+inline boost::graph_traits<vtkGraph *>::edges_size_type num_edges(vtkGraph *g)
+{
+  return g->GetNumberOfEdges();
+}
+
+inline boost::graph_traits<vtkGraph *>::degree_size_type out_degree(
+    boost::graph_traits<vtkGraph *>::vertex_descriptor u, vtkGraph *g)
+{
+  return g->GetOutDegree(u);
+}
+
+inline boost::graph_traits<vtkDirectedGraph *>::degree_size_type in_degree(
+    boost::graph_traits<vtkDirectedGraph *>::vertex_descriptor u, vtkDirectedGraph *g)
+{
+  return g->GetInDegree(u);
+}
+
+inline boost::graph_traits<vtkGraph *>::degree_size_type degree(
+    boost::graph_traits<vtkGraph *>::vertex_descriptor u, vtkGraph *g)
+{
+  return g->GetDegree(u);
+}
+
+inline boost::graph_traits<vtkMutableDirectedGraph *>::vertex_descriptor add_vertex(
+    vtkMutableDirectedGraph *g)
+{
+  return g->AddVertex();
+}
+
+inline std::pair<boost::graph_traits<vtkMutableDirectedGraph *>::edge_descriptor, bool> add_edge(
+    boost::graph_traits<vtkMutableDirectedGraph *>::vertex_descriptor u,
+    boost::graph_traits<vtkMutableDirectedGraph *>::vertex_descriptor v, vtkMutableDirectedGraph *g)
+{
+  boost::graph_traits<vtkMutableDirectedGraph *>::edge_descriptor e = g->AddEdge(u, v);
+  return std::make_pair(e, true);
+}
+
+inline boost::graph_traits<vtkMutableUndirectedGraph *>::vertex_descriptor add_vertex(
+    vtkMutableUndirectedGraph *g)
+{
+  return g->AddVertex();
+}
+
+inline std::pair<boost::graph_traits<vtkMutableUndirectedGraph *>::edge_descriptor, bool> add_edge(
+    boost::graph_traits<vtkMutableUndirectedGraph *>::vertex_descriptor u,
+    boost::graph_traits<vtkMutableUndirectedGraph *>::vertex_descriptor v,
+    vtkMutableUndirectedGraph *g)
+{
+  boost::graph_traits<vtkMutableUndirectedGraph *>::edge_descriptor e = g->AddEdge(u, v);
+  return std::make_pair(e, true);
+}
+
+namespace boost
+{
+  //===========================================================================
+  // An edge map for vtkGraph.
+  // This is a common input needed for algorithms.
+
+  struct vtkGraphEdgeMap
+  {
+  };
+
+  template <>
+  struct property_traits<vtkGraphEdgeMap>
+  {
+    typedef vtkIdType value_type;
+    typedef vtkIdType reference;
+    typedef vtkEdgeType key_type;
+    typedef readable_property_map_tag category;
+  };
+
+  inline property_traits<vtkGraphEdgeMap>::reference get(
+      vtkGraphEdgeMap vtkNotUsed(arr), property_traits<vtkGraphEdgeMap>::key_type key)
+  {
+    return key.Id;
+  }
+
+  //===========================================================================
+  // Helper for vtkGraph edge property maps
+  // Automatically converts boost edge ids to vtkGraph edge ids.
+
+  template <typename PMap>
+  class vtkGraphEdgePropertyMapHelper
+  {
+  public:
+    vtkGraphEdgePropertyMapHelper(PMap m)
+        : pmap(m)
+    {
+    }
+    PMap pmap;
+    typedef typename property_traits<PMap>::value_type value_type;
+    typedef typename property_traits<PMap>::reference reference;
+    typedef vtkEdgeType key_type;
+    typedef typename property_traits<PMap>::category category;
+
+    reference operator[](const key_type &key) const { return get(pmap, key.Id); }
+  };
+
+  template <typename PMap>
+  inline typename property_traits<PMap>::reference get(
+      vtkGraphEdgePropertyMapHelper<PMap> helper, vtkEdgeType key)
+  {
+    return get(helper.pmap, key.Id);
+  }
+
+  template <typename PMap>
+  inline void put(vtkGraphEdgePropertyMapHelper<PMap> helper, vtkEdgeType key,
+                  const typename property_traits<PMap>::value_type &value)
+  {
+    put(helper.pmap, key.Id, value);
+  }
+
+  //===========================================================================
+  // Helper for vtkGraph vertex property maps
+  // Automatically converts boost vertex ids to vtkGraph vertex ids.
+  template <typename PMap>
+  class vtkGraphVertexPropertyMapHelper
+  {
+  public:
+    vtkGraphVertexPropertyMapHelper(PMap m)
+        : pmap(m)
+    {
+    }
+    PMap pmap;
+    typedef typename property_traits<PMap>::value_type value_type;
+    typedef typename property_traits<PMap>::reference reference;
+    typedef vtkIdType key_type;
+    typedef typename property_traits<PMap>::category category;
+
+    reference operator[](const key_type &key) const { return get(pmap, key); }
+  };
+
+  template <typename PMap>
+  inline typename property_traits<PMap>::reference get(
+      vtkGraphVertexPropertyMapHelper<PMap> helper, vtkIdType key)
+  {
+    return get(helper.pmap, key);
+  }
+
+  template <typename PMap>
+  inline void put(vtkGraphVertexPropertyMapHelper<PMap> helper, vtkIdType key,
+                  const typename property_traits<PMap>::value_type &value)
+  {
+    put(helper.pmap, key, value);
+  }
+
+  //===========================================================================
+  // An index map for vtkGraph
+  // This is a common input needed for algorithms
+
+  struct vtkGraphIndexMap
+  {
+  };
+
+  template <>
+  struct property_traits<vtkGraphIndexMap>
+  {
+    typedef vtkIdType value_type;
+    typedef vtkIdType reference;
+    typedef vtkIdType key_type;
+    typedef readable_property_map_tag category;
+  };
+
+  inline property_traits<vtkGraphIndexMap>::reference get(
+      vtkGraphIndexMap vtkNotUsed(arr), property_traits<vtkGraphIndexMap>::key_type key)
+  {
+    return key;
+  }
+
+  //===========================================================================
+  // Helper for vtkGraph property maps
+  // Automatically multiplies the property value by some value (default 1)
+  template <typename PMap>
+  class vtkGraphPropertyMapMultiplier
+  {
+  public:
+    vtkGraphPropertyMapMultiplier(PMap m, float multi = 1)
+        : pmap(m), multiplier(multi)
+    {
+    }
+    PMap pmap;
+    float multiplier;
+    typedef typename property_traits<PMap>::value_type value_type;
+    typedef typename property_traits<PMap>::reference reference;
+    typedef typename property_traits<PMap>::key_type key_type;
+    typedef typename property_traits<PMap>::category category;
+  };
+
+  template <typename PMap>
+  inline typename property_traits<PMap>::reference get(
+      vtkGraphPropertyMapMultiplier<PMap> multi, const typename property_traits<PMap>::key_type &key)
+  {
+    return multi.multiplier * get(multi.pmap, key);
+  }
+
+  template <typename PMap>
+  inline void put(vtkGraphPropertyMapMultiplier<PMap> multi,
+                  const typename property_traits<PMap>::key_type &key,
+                  const typename property_traits<PMap>::value_type &value)
+  {
+    put(multi.pmap, key, value);
+  }
+
+  // Allow algorithms to automatically extract vtkGraphIndexMap from a
+  // VTK graph
+  template <>
+  struct property_map<vtkGraph *, vertex_index_t>
+  {
+    typedef vtkGraphIndexMap type;
+    typedef vtkGraphIndexMap const_type;
+  };
+
+  template <>
+  struct property_map<vtkDirectedGraph *, vertex_index_t> : property_map<vtkGraph *, vertex_index_t>
+  {
+  };
+
+  template <>
+  struct property_map<vtkUndirectedGraph *, vertex_index_t> : property_map<vtkGraph *, vertex_index_t>
+  {
+  };
+
+  inline vtkGraphIndexMap get(vertex_index_t, vtkGraph *)
+  {
+    return vtkGraphIndexMap();
+  }
+
+  template <>
+  struct property_map<vtkGraph *, edge_index_t>
+  {
+    typedef vtkGraphIndexMap type;
+    typedef vtkGraphIndexMap const_type;
+  };
+
+  template <>
+  struct property_map<vtkDirectedGraph *, edge_index_t> : property_map<vtkGraph *, edge_index_t>
+  {
+  };
+
+  template <>
+  struct property_map<vtkUndirectedGraph *, edge_index_t> : property_map<vtkGraph *, edge_index_t>
+  {
+  };
+
+  inline vtkGraphIndexMap get(edge_index_t, vtkGraph *)
+  {
+    return vtkGraphIndexMap();
+  }
+
+  // property_map specializations for const-qualified graphs
+  template <>
+  struct property_map<vtkDirectedGraph *const, vertex_index_t>
+      : property_map<vtkDirectedGraph *, vertex_index_t>
+  {
+  };
+
+  template <>
+  struct property_map<vtkUndirectedGraph *const, vertex_index_t>
+      : property_map<vtkUndirectedGraph *, vertex_index_t>
+  {
+  };
+
+  template <>
+  struct property_map<vtkDirectedGraph *const, edge_index_t>
+      : property_map<vtkDirectedGraph *, edge_index_t>
+  {
+  };
+
+  template <>
+  struct property_map<vtkUndirectedGraph *const, edge_index_t>
+      : property_map<vtkUndirectedGraph *, edge_index_t>
+  {
+  };
+} // namespace boost
+
+#if BOOST_VERSION > 104000
+#include <boost/property_map/vector_property_map.hpp>
+#else
+#include <boost/vector_property_map.hpp>
+#endif
+
+#endif // vtkBoostGraphAdapter_h
+       // VTK-HeaderTest-Exclude: vtkBoostGraphAdapter.h
\ No newline at end of file
diff --git a/vtkPolyDataToGraph.cxx b/vtkPolyDataToGraph.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..31bf7926084d010a2d6bcc30e6a98637728ae29c
--- /dev/null
+++ b/vtkPolyDataToGraph.cxx
@@ -0,0 +1,208 @@
+#include "vtkPolyDataToGraph.h"
+
+// for testing only
+#include "vtkXMLPolyDataWriter.h"
+
+#include <vtkGraphToPolyData.h>
+#include <vtkFloatArray.h>
+#include <vtkPointData.h>
+#include <vtkExtractEdges.h>
+#include <vtkLine.h>
+#include <vtkObjectFactory.h>
+#include <vtkStreamingDemandDrivenPipeline.h>
+#include <vtkInformationVector.h>
+#include <vtkInformation.h>
+#include <vtkMutableUndirectedGraph.h>
+#include <vtkAdjacentVertexIterator.h>
+#include <vtkPolyData.h>
+#include <vtkImageData.h>
+#include <vtkSmartPointer.h>
+
+int vtkPolyDataToGraph::RequestDataObject(vtkInformation *vtkNotUsed(request),
+                                          vtkInformationVector **inputVector,
+                                          vtkInformationVector *outputVector)
+{
+  vtkMutableUndirectedGraph *output = 0;
+  output = vtkMutableUndirectedGraph::New();
+
+  this->GetExecutive()->SetOutputData(0, output);
+  output->Delete();
+
+  return 1;
+}
+
+/*
+//it works with or without this re-implementation
+int vtkMeshToGraph::FillOutputPortInformation(
+  int vtkNotUsed(port), vtkInformation* info)
+{
+  // now add our info
+  info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMutableUndirectedGraph");
+  return 1;
+}
+*/
+
+//----------------------------------------------------------------------------
+int vtkPolyDataToGraph::FillInputPortInformation(
+    int vtkNotUsed(port), vtkInformation *info)
+{
+  info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData");
+  return 1;
+}
+
+int vtkPolyDataToGraph::RequestData(
+    vtkInformation *vtkNotUsed(request),
+    vtkInformationVector **inputVector,
+    vtkInformationVector *outputVector)
+{
+  // get the input and ouptut
+  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
+  // vtkPolyData *input = vtkPolyData::SafeDownCast(
+  vtkPolyData *input = vtkPolyData::SafeDownCast(
+      inInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+  std::cout << "vtkPolyDataToGraph: Input has " << input->GetNumberOfPoints() << " points." << std::endl;
+
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  vtkMutableUndirectedGraph *output = vtkMutableUndirectedGraph::SafeDownCast(
+      outInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+  // add a vertex for every point
+  for (vtkIdType i = 0; i < input->GetNumberOfPoints(); i++)
+  {
+    output->AddVertex();
+  }
+
+  // output->GetVertexData()->ShallowCopy(input->GetPointData());
+  output->GetVertexData()->PassData(input->GetPointData());
+
+  // add the edge between every point and every point connected to it (do not allow duplicates)
+  for (vtkIdType i = 0; i < input->GetNumberOfPoints(); i++)
+  {
+    vtkSmartPointer<vtkIdList> idList =
+        vtkSmartPointer<vtkIdList>::New();
+    this->GetConnectedVertices(input, i, idList);
+
+    for (vtkIdType id = 0; id < idList->GetNumberOfIds(); id++)
+    {
+      if (!EdgeExists(output, i, idList->GetId(id)))
+      {
+        output->AddEdge(i, idList->GetId(id));
+      }
+    }
+  }
+
+  output->SetPoints(input->GetPoints());
+
+  {
+    vtkSmartPointer<vtkMutableUndirectedGraph> outputGraph =
+        vtkSmartPointer<vtkMutableUndirectedGraph>::New();
+    outputGraph->ShallowCopy(output);
+
+    vtkSmartPointer<vtkGraphToPolyData> graphToPolyData =
+        vtkSmartPointer<vtkGraphToPolyData>::New();
+    graphToPolyData->SetInputData(outputGraph);
+    graphToPolyData->Update();
+
+    vtkSmartPointer<vtkXMLPolyDataWriter> writer =
+        vtkSmartPointer<vtkXMLPolyDataWriter>::New();
+    writer->SetFileName("MeshToGraphOutput.vtp");
+    writer->SetInputConnection(graphToPolyData->GetOutputPort());
+    writer->Write();
+  }
+
+  return 1;
+}
+
+bool vtkPolyDataToGraph::EdgeExists(vtkSmartPointer<vtkGraph> g, int pointID, int neighborID)
+{
+  // check if the edge already exists
+  vtkSmartPointer<vtkAdjacentVertexIterator> iterator =
+      vtkSmartPointer<vtkAdjacentVertexIterator>::New();
+  g->GetAdjacentVertices(pointID, iterator);
+
+  bool edgeExists = false;
+  while (iterator->HasNext())
+  {
+    if (iterator->Next() == neighborID)
+    {
+      edgeExists = true;
+      break;
+    }
+  }
+  return edgeExists;
+}
+
+void vtkPolyDataToGraph::GetConnectedVertices(vtkSmartPointer<vtkPolyData> mesh, int seed, vtkSmartPointer<vtkIdList> connectedVertices)
+{
+
+  // get all cells that vertex 'seed' is a part of
+  vtkSmartPointer<vtkIdList> cellIdList =
+      vtkSmartPointer<vtkIdList>::New();
+  mesh->GetPointCells(seed, cellIdList);
+
+  // cout << "There are " << cellIdList->GetNumberOfIds() << " cells that use point " << seed << endl;
+
+  // loop through all the cells that use the seed point
+  for (vtkIdType i = 0; i < cellIdList->GetNumberOfIds(); i++)
+  {
+
+    vtkCell *cell = mesh->GetCell(cellIdList->GetId(i));
+    // cout << "The cell has " << cell->GetNumberOfEdges() << " edges." << endl;
+
+    // if the cell doesn't have any edges, it is a line
+    if (cell->GetNumberOfEdges() <= 0)
+    {
+      // vtkLine* line = vtkLine::SafeDownCast(input->GetCell(i));
+      vtkLine *line = vtkLine::SafeDownCast(mesh->GetCell(cellIdList->GetId(i)));
+
+      // if the cell didn't have any edges, and it is not a line, it must be a vertex, so skip it
+      if (!line)
+      {
+        continue;
+      }
+      else
+      {
+        int p0 = line->GetPointId(0);
+        int p1 = line->GetPointId(1);
+        if (p0 == seed)
+        {
+          connectedVertices->InsertNextId(p1);
+        }
+        else
+        {
+          connectedVertices->InsertNextId(p0);
+        }
+      }
+      continue;
+    }
+
+    // if we get to here, the cell is a polygon, so extract its border edges
+    for (vtkIdType e = 0; e < cell->GetNumberOfEdges(); e++)
+    {
+      vtkCell *edge = cell->GetEdge(e);
+
+      vtkIdList *pointIdList = edge->GetPointIds();
+      // cout << "This cell uses " << pointIdList->GetNumberOfIds() << " points" << endl;
+      /*
+      for(vtkIdType p = 0; p < pointIdList->GetNumberOfIds(); p++)
+        {
+        cout << "Edge " << i << " uses point " << pointIdList->GetId(p) << endl;
+        }
+        */
+      if (pointIdList->GetId(0) == seed || pointIdList->GetId(1) == seed)
+      {
+        if (pointIdList->GetId(0) == seed)
+        {
+          connectedVertices->InsertNextId(pointIdList->GetId(1));
+        }
+        else
+        {
+          connectedVertices->InsertNextId(pointIdList->GetId(0));
+        }
+      }
+    }
+  }
+
+  // cout << "There are " << connectedVertices->GetNumberOfIds() << " points connected to point " << seed << endl;
+}
\ No newline at end of file
diff --git a/vtkPolyDataToGraph.h b/vtkPolyDataToGraph.h
new file mode 100644
index 0000000000000000000000000000000000000000..8cb42635084e87a2a0224ec5905f9586f16228d7
--- /dev/null
+++ b/vtkPolyDataToGraph.h
@@ -0,0 +1,39 @@
+// This class converts all of the points in a vtkPolyData into vertices in a vtkGraph, and all
+//  "edges" in a vtkPolyData (borders of polygons and vtkLines) into edges in a vtkGraph
+
+#ifndef __vtkPolyDataToGraph_h
+#define __vtkPolyDataToGraph_h
+
+#include <vtkGraphAlgorithm.h>
+#include <vtkSmartPointer.h>
+
+class vtkPolyData;
+class vtkIdList;
+
+class vtkPolyDataToGraph : public vtkGraphAlgorithm
+{
+public:
+  static vtkPolyDataToGraph *New();
+
+protected:
+  vtkPolyDataToGraph() {}
+  ~vtkPolyDataToGraph() {}
+
+  virtual int FillInputPortInformation(int port, vtkInformation *info);
+
+  int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
+
+  int RequestDataObject(vtkInformation *vtkNotUsed(request),
+                        vtkInformationVector **inputVector,
+                        vtkInformationVector *outputVector);
+
+private:
+  vtkPolyDataToGraph(const vtkPolyDataToGraph &); // Not implemented.
+  void operator=(const vtkPolyDataToGraph &);     // Not implemented.
+
+  // should not be part of this class
+  bool EdgeExists(vtkSmartPointer<vtkGraph> g, int pointID, int neighborID);
+  void GetConnectedVertices(vtkSmartPointer<vtkPolyData> mesh, int seed, vtkSmartPointer<vtkIdList> connectedVertices);
+};
+
+#endif
\ No newline at end of file