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