/*========================================================================= 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. -------------------------------------------------------------------------*/ /** * @class vtkDirectedGraph * * * Including this header allows you to use a vtkDirectedGraph* in boost algorithms. * To do this, first wrap the class in a vtkDirectedGraph* or * vtkUndirectedGraph* depending on whether your graph is directed or undirected. * You may then use these objects directly in boost graph algorithms. */ #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 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 struct property_traits; struct read_write_property_map_tag; #define vtkPropertyMapMacro(T, V) \ template <> \ struct property_traits \ { \ typedef V value_type; \ typedef V reference; \ typedef vtkIdType key_type; \ typedef read_write_property_map_tag category; \ }; \ \ inline property_traits::reference get(T* const& arr, property_traits::key_type key) \ { \ return arr->GetValue(key); \ } \ \ inline void put( \ T* arr, property_traits::key_type key, const property_traits::value_type& value) \ { \ arr->InsertValue(key, value); \ } vtkPropertyMapMacro(vtkIntArray, int); vtkPropertyMapMacro(vtkIdTypeArray, vtkIdType); vtkPropertyMapMacro(vtkDoubleArray, double); vtkPropertyMapMacro(vtkFloatArray, float); // vtkDataArray template <> struct property_traits { 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 { 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 // STL Header #include #include #if BOOST_VERSION > 107300 && BOOST_VERSION < 107600 #define BOOST_ALLOW_DEPRECATED_HEADERS #define BOOST_BIND_GLOBAL_PLACEHOLDERS #endif #include #include #include #include // 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 { 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 { public: explicit vtk_edge_iterator(vtkGraph* g = 0, 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() : 0; if (helper) { myRank = this->graph->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER()); vertex = helper->MakeDistributedId(myRank, vertex); lastVertex = helper->MakeDistributedId(myRank, lastVertex); } if (graph != 0) { directed = (vtkDirectedGraph::SafeDownCast(graph) != 0); 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() : 0; if (helper) { myRank = this->graph->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER()); } while (iter != 0 && ( // 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 { public: explicit vtk_out_edge_pointer_iterator(vtkGraph* g = 0, 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 { public: explicit vtk_in_edge_pointer_iterator(vtkGraph* g = 0, 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 { 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::type adjacency_iterator; }; #if BOOST_VERSION >= 104500 template <> struct graph_property_type { typedef no_property type; }; #endif template <> struct vertex_property_type { typedef no_property type; }; template <> struct edge_property_type { typedef no_property type; }; #if BOOST_VERSION >= 104500 template <> struct graph_bundle_type { typedef no_property type; }; #endif template <> struct vertex_bundle_type { typedef no_property type; }; template <> struct edge_bundle_type { typedef no_property type; }; inline bool has_no_edges(vtkGraph* g) { return ((g->GetNumberOfEdges() > 0) ? false : true); } inline void remove_edge(graph_traits::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 : graph_traits { typedef directed_tag directed_category; }; // The graph_traits for a const graph are the same as a non-const graph. template <> struct graph_traits : graph_traits { }; // The graph_traits for a const graph are the same as a non-const graph. template <> struct graph_traits : graph_traits { }; #if BOOST_VERSION >= 104500 // Internal graph properties template <> struct graph_property_type : graph_property_type { }; // Internal graph properties template <> struct graph_property_type : graph_property_type { }; #endif // Internal vertex properties template <> struct vertex_property_type : vertex_property_type { }; // Internal vertex properties template <> struct vertex_property_type : vertex_property_type { }; // Internal edge properties template <> struct edge_property_type : edge_property_type { }; // Internal edge properties template <> struct edge_property_type : edge_property_type { }; #if BOOST_VERSION >= 104500 // Internal graph properties template <> struct graph_bundle_type : graph_bundle_type { }; // Internal graph properties template <> struct graph_bundle_type : graph_bundle_type { }; #endif // Internal vertex properties template <> struct vertex_bundle_type : vertex_bundle_type { }; // Internal vertex properties template <> struct vertex_bundle_type : vertex_bundle_type { }; // Internal edge properties template <> struct edge_bundle_type : edge_bundle_type { }; // Internal edge properties template <> struct edge_bundle_type : edge_bundle_type { }; //=========================================================================== // vtkTree template <> struct graph_traits : graph_traits { }; // The graph_traits for a const graph are the same as a non-const graph. template <> struct graph_traits : graph_traits { }; // The graph_traits for a const graph are the same as a non-const graph. template <> struct graph_traits : graph_traits { }; //=========================================================================== // vtkUndirectedGraph template <> struct graph_traits : graph_traits { typedef undirected_tag directed_category; }; // The graph_traits for a const graph are the same as a non-const graph. template <> struct graph_traits : graph_traits { }; // The graph_traits for a const graph are the same as a non-const graph. template <> struct graph_traits : graph_traits { }; #if BOOST_VERSION >= 104500 // Internal graph properties template <> struct graph_property_type : graph_property_type { }; // Internal graph properties template <> struct graph_property_type : graph_property_type { }; #endif // Internal vertex properties template <> struct vertex_property_type : vertex_property_type { }; // Internal vertex properties template <> struct vertex_property_type : vertex_property_type { }; // Internal edge properties template <> struct edge_property_type : edge_property_type { }; // Internal edge properties template <> struct edge_property_type : edge_property_type { }; #if BOOST_VERSION >= 104500 // Internal graph properties template <> struct graph_bundle_type : graph_bundle_type { }; // Internal graph properties template <> struct graph_bundle_type : graph_bundle_type { }; #endif // Internal vertex properties template <> struct vertex_bundle_type : vertex_bundle_type { }; // Internal vertex properties template <> struct vertex_bundle_type : vertex_bundle_type { }; // Internal edge properties template <> struct edge_bundle_type : edge_bundle_type { }; // Internal edge properties template <> struct edge_bundle_type : edge_bundle_type { }; //=========================================================================== // vtkMutableDirectedGraph template <> struct graph_traits : graph_traits { }; // The graph_traits for a const graph are the same as a non-const graph. template <> struct graph_traits : graph_traits { }; // The graph_traits for a const graph are the same as a non-const graph. template <> struct graph_traits : graph_traits { }; #if BOOST_VERSION >= 104500 // Internal graph properties template <> struct graph_property_type : graph_property_type { }; // Internal graph properties template <> struct graph_property_type : graph_property_type { }; #endif // Internal vertex properties template <> struct vertex_property_type : vertex_property_type { }; // Internal vertex properties template <> struct vertex_property_type : vertex_property_type { }; // Internal edge properties template <> struct edge_property_type : edge_property_type { }; // Internal edge properties template <> struct edge_property_type : edge_property_type { }; #if BOOST_VERSION >= 104500 // Internal graph properties template <> struct graph_bundle_type : graph_bundle_type { }; // Internal graph properties template <> struct graph_bundle_type : graph_bundle_type { }; #endif // Internal vertex properties template <> struct vertex_bundle_type : vertex_bundle_type { }; // Internal vertex properties template <> struct vertex_bundle_type : vertex_bundle_type { }; // Internal edge properties template <> struct edge_bundle_type : edge_bundle_type { }; // Internal edge properties template <> struct edge_bundle_type : edge_bundle_type { }; //=========================================================================== // vtkMutableUndirectedGraph template <> struct graph_traits : graph_traits { }; // The graph_traits for a const graph are the same as a non-const graph. template <> struct graph_traits : graph_traits { }; // The graph_traits for a const graph are the same as a non-const graph. template <> struct graph_traits : graph_traits { }; #if BOOST_VERSION >= 104500 // Internal graph properties template <> struct graph_property_type : graph_property_type { }; // Internal graph properties template <> struct graph_property_type : graph_property_type { }; #endif // Internal vertex properties template <> struct vertex_property_type : vertex_property_type { }; // Internal vertex properties template <> struct vertex_property_type : vertex_property_type { }; // Internal edge properties template <> struct edge_property_type : edge_property_type { }; // Internal edge properties template <> struct edge_property_type : edge_property_type { }; #if BOOST_VERSION >= 104500 // Internal graph properties template <> struct graph_bundle_type : graph_bundle_type { }; // Internal graph properties template <> struct graph_bundle_type : graph_bundle_type { }; #endif // Internal vertex properties template <> struct vertex_bundle_type : vertex_bundle_type { }; // Internal vertex properties template <> struct vertex_bundle_type : vertex_bundle_type { }; // Internal edge properties template <> struct edge_bundle_type : edge_bundle_type { }; // Internal edge properties template <> struct edge_bundle_type : edge_bundle_type { }; //=========================================================================== // API implementation template <> class vertex_property { public: typedef vtkIdType type; }; template <> class edge_property { public: typedef vtkIdType type; }; } // end namespace boost inline boost::graph_traits::vertex_descriptor source( boost::graph_traits::edge_descriptor e, vtkGraph*) { return e.Source; } inline boost::graph_traits::vertex_descriptor target( boost::graph_traits::edge_descriptor e, vtkGraph*) { return e.Target; } inline std::pair::vertex_iterator, boost::graph_traits::vertex_iterator> vertices(vtkGraph* g) { typedef boost::graph_traits::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::edge_iterator, boost::graph_traits::edge_iterator> edges(vtkGraph* g) { typedef boost::graph_traits::edge_iterator Iter; return std::make_pair(Iter(g), Iter(g, g->GetNumberOfVertices())); } inline std::pair::out_edge_iterator, boost::graph_traits::out_edge_iterator> out_edges(boost::graph_traits::vertex_descriptor u, vtkGraph* g) { typedef boost::graph_traits::out_edge_iterator Iter; std::pair p = std::make_pair(Iter(g, u), Iter(g, u, true)); return p; } inline std::pair::in_edge_iterator, boost::graph_traits::in_edge_iterator> in_edges(boost::graph_traits::vertex_descriptor u, vtkGraph* g) { typedef boost::graph_traits::in_edge_iterator Iter; std::pair p = std::make_pair(Iter(g, u), Iter(g, u, true)); return p; } inline std::pair::adjacency_iterator, boost::graph_traits::adjacency_iterator> adjacent_vertices(boost::graph_traits::vertex_descriptor u, vtkGraph* g) { typedef boost::graph_traits::adjacency_iterator Iter; typedef boost::graph_traits::out_edge_iterator OutEdgeIter; std::pair out = out_edges(u, g); return std::make_pair(Iter(out.first, &g), Iter(out.second, &g)); } inline boost::graph_traits::vertices_size_type num_vertices(vtkGraph* g) { return g->GetNumberOfVertices(); } inline boost::graph_traits::edges_size_type num_edges(vtkGraph* g) { return g->GetNumberOfEdges(); } inline boost::graph_traits::degree_size_type out_degree( boost::graph_traits::vertex_descriptor u, vtkGraph* g) { return g->GetOutDegree(u); } inline boost::graph_traits::degree_size_type in_degree( boost::graph_traits::vertex_descriptor u, vtkDirectedGraph* g) { return g->GetInDegree(u); } inline boost::graph_traits::degree_size_type degree( boost::graph_traits::vertex_descriptor u, vtkGraph* g) { return g->GetDegree(u); } inline boost::graph_traits::vertex_descriptor add_vertex( vtkMutableDirectedGraph* g) { return g->AddVertex(); } inline std::pair::edge_descriptor, bool> add_edge( boost::graph_traits::vertex_descriptor u, boost::graph_traits::vertex_descriptor v, vtkMutableDirectedGraph* g) { boost::graph_traits::edge_descriptor e = g->AddEdge(u, v); return std::make_pair(e, true); } inline boost::graph_traits::vertex_descriptor add_vertex( vtkMutableUndirectedGraph* g) { return g->AddVertex(); } inline std::pair::edge_descriptor, bool> add_edge( boost::graph_traits::vertex_descriptor u, boost::graph_traits::vertex_descriptor v, vtkMutableUndirectedGraph* g) { boost::graph_traits::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 { typedef vtkIdType value_type; typedef vtkIdType reference; typedef vtkEdgeType key_type; typedef readable_property_map_tag category; }; inline property_traits::reference get( vtkGraphEdgeMap vtkNotUsed(arr), property_traits::key_type key) { return key.Id; } //=========================================================================== // Helper for vtkGraph edge property maps // Automatically converts boost edge ids to vtkGraph edge ids. template class vtkGraphEdgePropertyMapHelper { public: vtkGraphEdgePropertyMapHelper(PMap m) : pmap(m) { } PMap pmap; typedef typename property_traits::value_type value_type; typedef typename property_traits::reference reference; typedef vtkEdgeType key_type; typedef typename property_traits::category category; reference operator[](const key_type& key) const { return get(pmap, key.Id); } }; template inline typename property_traits::reference get( vtkGraphEdgePropertyMapHelper helper, vtkEdgeType key) { return get(helper.pmap, key.Id); } template inline void put(vtkGraphEdgePropertyMapHelper helper, vtkEdgeType key, const typename property_traits::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 class vtkGraphVertexPropertyMapHelper { public: vtkGraphVertexPropertyMapHelper(PMap m) : pmap(m) { } PMap pmap; typedef typename property_traits::value_type value_type; typedef typename property_traits::reference reference; typedef vtkIdType key_type; typedef typename property_traits::category category; reference operator[](const key_type& key) const { return get(pmap, key); } }; template inline typename property_traits::reference get( vtkGraphVertexPropertyMapHelper helper, vtkIdType key) { return get(helper.pmap, key); } template inline void put(vtkGraphVertexPropertyMapHelper helper, vtkIdType key, const typename property_traits::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 { typedef vtkIdType value_type; typedef vtkIdType reference; typedef vtkIdType key_type; typedef readable_property_map_tag category; }; inline property_traits::reference get( vtkGraphIndexMap vtkNotUsed(arr), property_traits::key_type key) { return key; } //=========================================================================== // Helper for vtkGraph property maps // Automatically multiplies the property value by some value (default 1) template class vtkGraphPropertyMapMultiplier { public: vtkGraphPropertyMapMultiplier(PMap m, float multi = 1) : pmap(m) , multiplier(multi) { } PMap pmap; float multiplier; typedef typename property_traits::value_type value_type; typedef typename property_traits::reference reference; typedef typename property_traits::key_type key_type; typedef typename property_traits::category category; }; template inline typename property_traits::reference get( vtkGraphPropertyMapMultiplier multi, const typename property_traits::key_type& key) { return multi.multiplier * get(multi.pmap, key); } template inline void put(vtkGraphPropertyMapMultiplier multi, const typename property_traits::key_type& key, const typename property_traits::value_type& value) { put(multi.pmap, key, value); } // Allow algorithms to automatically extract vtkGraphIndexMap from a // VTK graph template <> struct property_map { typedef vtkGraphIndexMap type; typedef vtkGraphIndexMap const_type; }; template <> struct property_map : property_map { }; template <> struct property_map : property_map { }; inline vtkGraphIndexMap get(vertex_index_t, vtkGraph*) { return vtkGraphIndexMap(); } template <> struct property_map { typedef vtkGraphIndexMap type; typedef vtkGraphIndexMap const_type; }; template <> struct property_map : property_map { }; template <> struct property_map : property_map { }; inline vtkGraphIndexMap get(edge_index_t, vtkGraph*) { return vtkGraphIndexMap(); } // property_map specializations for const-qualified graphs template <> struct property_map : property_map { }; template <> struct property_map : property_map { }; template <> struct property_map : property_map { }; template <> struct property_map : property_map { }; } // namespace boost #if BOOST_VERSION > 104000 #include #else #include #endif #endif // vtkBoostGraphAdapter_h // VTK-HeaderTest-Exclude: vtkBoostGraphAdapter.h