MeVisLab Toolbox Reference
mlGraphToBoostGraph.h
Go to the documentation of this file.
1/*************************************************************************************
2**
3** Copyright 2012, MeVis Medical Solutions AG
4**
5** The user may use this file in accordance with the license agreement provided with
6** the Software or, alternatively, in accordance with the terms contained in a
7** written agreement between the user and MeVis Medical Solutions AG.
8**
9** For further information use the contact form at https://www.mevislab.de/contact
10**
11**************************************************************************************/
12
13#ifndef ML_GRAPH_TO_BOOST_GRAPH_H
14#define ML_GRAPH_TO_BOOST_GRAPH_H
15
16
18
19#include <iterator>
20#include <boost/operators.hpp>
21#include <boost/graph/graph_traits.hpp>
22#include <boost/graph/properties.hpp>
23#include <boost/property_map/property_map.hpp>
24
25#include "mlGraphComponents.h"
26#include "mlGraph.h"
27#include <mlVesselEdge.h>
28
30//
31// Functions and traits for the plain ml::Graph class
32//
34
36class ml_vertex_iterator;
37
39typedef ml::Graph* ml_graph_ptr;
40
41namespace boost {
42
43 // typedef const UndirectedVesselGraph* ml_const_uv_graph_ptr;
44
54 public virtual incidence_graph_tag, // Graph is of type IncidenceGraph
55 // public virtual adjacency_graph_tag,
56 public virtual vertex_list_graph_tag // Graph is of type IncidenceGraph
57 { };
58
59
61 template <> struct graph_traits<ml_graph_ptr> {
62
63 // --- typedefs for boost::Graph ---
64
66 typedef ml::VesselNode* vertex_descriptor;
67
69 typedef ml::VesselEdge* edge_descriptor;
70
72 typedef directed_tag directed_category;
73
77 typedef allow_parallel_edge_tag edge_parallel_category;
78
81
82 // --- typedefs for boost::IncidenceGraph ---
83
86 typedef long degree_size_type;
87
88 // An out-edge iterator for a vertex v provides access to the out-edges of the vertex. As such,
89 // the value type of an out-edge iterator is the edge descriptor type of its graph.
91
92 // --- typedefs for boost::VertexListGraph ---
93
96 typedef ml::Graph::NodeIterator vertex_iterator;
97
99 typedef long vertices_size_type;
100
101 // to do: add missing functions/traits for other boost graph models
102 /*
103 typedef void in_edge_iterator;
104 typedef sgb_adj_iterator adjacency_iterator;
105 typedef void edge_iterator;
106 typedef long edge_size_type;
107 */
108 };
109
110
111
112} // namespace boost
113
114
115// Iterator class to iterate over all out edges of a vertex (out_edge_iterator)
116
117// ml::VesselNode stores all edges in a std::vector but has no information which edges are
118// directed from this node to another; this must be looked up in the edges itself
119// see comment at out_edges
120class ml_out_edge_iterator : public boost::forward_iterator_helper<
121 ml_out_edge_iterator, // operand type
122 ml::VesselEdge*, // value type
123 std::ptrdiff_t, // difference type
124 ml::VesselEdge**, // pointer type
125 ml::VesselEdge*> // reference type
126{
127
129
130public:
131
133
134 ml_out_edge_iterator(ml::VesselNode* vertex,
135 std::vector<ml::VesselEdge*>::iterator edgeIter,
136 std::vector<ml::VesselEdge*>::iterator edgeIterEnd)
137 :_vertex(vertex)
138 ,_edgeIter(edgeIter),
139 _edgeIterEnd(edgeIterEnd)
140 {
141 // set edgeIter to first out edge, skip all edges which predecessor is
142 // not the vertex
143 while ( (_edgeIter!=_edgeIterEnd) &&
144 !((*_edgeIter)->isPred(_vertex)) )
145 {
146 ++_edgeIter;
147 }
148 }
149
150 ml::VesselEdge* operator*() { return *_edgeIter; }
151
153 {
154 do // skip in-edges
155 {
156 // must check if iterator is already at the end, otherwise loop might become endless
157 if (_edgeIter != _edgeIterEnd) { ++_edgeIter; };
158 }
159 while ( (_edgeIter != _edgeIterEnd) && !((*_edgeIter)->isPred(_vertex)) );
160 return *this;
161 }
162
163 friend bool operator==(const self& x, const self& y) {
164 return x._edgeIter == y._edgeIter; }
165
166protected:
167 ml::VesselNode* _vertex;
168 std::vector<ml::VesselEdge*>::iterator _edgeIter;
169 std::vector<ml::VesselEdge*>::iterator _edgeIterEnd;
170};
171
172
173namespace boost {
174
175 // --- functions required by boost::IncidenceGraph ---
176
177
179 inline boost::graph_traits<ml_graph_ptr>::vertex_descriptor
180 source(graph_traits<ml_graph_ptr>::edge_descriptor e,
181 const ml_graph_ptr)
182 {
183 return e->predNode();
184 }
185
187 inline boost::graph_traits<ml_graph_ptr>::vertex_descriptor
188 target(graph_traits<ml_graph_ptr>::edge_descriptor e,
189 const ml_graph_ptr)
190 {
191 return e->succNode();
192 }
193
206 inline std::pair<boost::graph_traits<ml_graph_ptr>::out_edge_iterator,
207 boost::graph_traits<ml_graph_ptr>::out_edge_iterator>
208 out_edges(boost::graph_traits<ml_graph_ptr>::vertex_descriptor vertex,
209 const ml_graph_ptr)
210 {
211 return std::make_pair(
212 ml_out_edge_iterator(vertex, vertex->edges()->begin(), vertex->edges()->end()),
213 ml_out_edge_iterator(vertex, vertex->edges()->end(), vertex->edges()->end()) );
214 }
215
216
220 inline boost::graph_traits<ml_graph_ptr>::degree_size_type
221 out_degree(boost::graph_traits<ml_graph_ptr>::vertex_descriptor vertex,
222 const ml_graph_ptr )
223 {
224 boost::graph_traits<ml_graph_ptr>::degree_size_type count = 0;
225
226 std::vector<ml::VesselEdge*>::iterator edgeIter = vertex->edges()->begin();
227 std::vector<ml::VesselEdge*>::iterator edgeIterEnd = vertex->edges()->end();
228
229 while (edgeIter != edgeIterEnd)
230 {
231 if ((*edgeIter)->isPred(vertex))
232 {
233 ++count;
234 }
235 ++edgeIter;
236 }
237 return count;
238 }
239
240
241 // --- functions required by boost::VertexListGraph ---
242
244 inline std::pair<boost::graph_traits<ml_graph_ptr>::vertex_iterator,
245 boost::graph_traits<ml_graph_ptr>::vertex_iterator>
247 {
248 return std::make_pair( g->beginNode(),
249 g->endNode() );
250 }
251
253 inline boost::graph_traits<ml_graph_ptr>::vertices_size_type
255 {
256 return static_cast<long> (g->numNodes());
257 }
258
259
261 inline boost::graph_traits<ml_graph_ptr>::vertex_descriptor
262 vertex(boost::graph_traits<ml_graph_ptr>::degree_size_type arrayIndex, const ml_graph_ptr g)
263 {
264 return g->getNode(arrayIndex);
265 }
266
267 // --- Property maps ---
268 // put_get_helper<class Reference, class LvaluePropertyMap> is a helper template which
269 // automatically generates the put() and get() functions for a property map
270
273 class ml_vertex_id_map : public boost::put_get_helper<unsigned int, ml_vertex_id_map>
274 {
275 public:
276 // readonly property
277 typedef boost::readable_property_map_tag category;
278
279 // vertex index is of type long
280 typedef unsigned int value_type;
281 typedef unsigned int reference;
282
283 // key = Vertex
284 typedef ml::VesselNode* key_type;
285
286 ml_vertex_id_map() : _g(nullptr) {}
288 unsigned int operator[](ml::VesselNode* vertex) const { return static_cast<unsigned int>(_g->getIndex(vertex)); }
289
290 protected:
292 };
293
296 inline ml_vertex_id_map get(vertex_index_t, ml_graph_ptr g)
297 {
298 return ml_vertex_id_map(g);
299 }
300
301 // --- Property Map Traits classes ---
302 template<>
303 struct property_map<ml_graph_ptr, vertex_index_t>
304 {
307 };
308
309
310 class ml_edge_weight_map : public boost::put_get_helper<double, ml_edge_weight_map>
311 {
312 public:
313 // readonly property
314 typedef boost::lvalue_property_map_tag category;
315
316 // vertex index is of type long
317 typedef double value_type;
318 using reference = double const&;
319
320 // key = edge
321 typedef ml::VesselEdge* key_type;
322
323 value_type operator[](ml::VesselEdge* edge) const {
324 std::cout << "edge.getWeight() = " << edge->getWeight() << std::endl;
325 return edge->getWeight();
326 }
327 };
328
329 inline ml_edge_weight_map get(edge_weight_t, ml_graph_ptr)
330 {
331 return ml_edge_weight_map();
332 }
333
334 // --- Property Map Traits classes ---
335 template<>
336 struct property_map<ml_graph_ptr, edge_weight_t>
337 {
340 };
341
342
343} // namespace boost
344
345
346
349template<class T, class ValueType>
351{
353 typedef std::random_access_iterator_tag iterator_category;
354 typedef ValueType value_type;
355 typedef ptrdiff_t difference_type;
356 typedef ValueType* pointer;
357 typedef ValueType& reference;
358};
359
360
361namespace boost {
362
377template <class IteratorTraits, class IDMap>
379{
380public:
381
382 typedef typename property_traits<IDMap>::key_type key_type;
383 typedef typename IteratorTraits::value_type value_type;
384 typedef typename IteratorTraits::value_type& reference;
385 typedef lvalue_property_map_tag category;
386
390 ml_iterator_map(typename IteratorTraits::iterator_type i = IteratorTraits::iterator_type(),
391 const IDMap& id = IDMap())
392 : m_iter(i), m_id(id) { }
393 typename IteratorTraits::iterator_type m_iter;
394 IDMap m_id;
395};
396
397// Next we implement the three property map functions, get(), put(), and at(). In each of the
398// functions, the key object is converted to an integer offset using the m_id property map, and
399// then that is used as an offset to the random access iterator m_iter.
400
401template <class IteratorTraits, class IDMap>
402typename IteratorTraits::value_type
404 typename property_traits<IDMap>::key_type key)
405{
406 return i.m_iter[i.m_id[key]];
407}
408template <class IteratorTraits, class IDMap>
409void
411 typename property_traits<IDMap>::key_type key,
412 const typename IteratorTraits::value_type& value)
413{
414 // std::cout << "put(" << key <<", " << value <<" )" << std::endl;
415 i.m_iter[i.m_id[key]] = value;
416}
417
418template <class IteratorTraits, class IDMap>
419typename IteratorTraits::value_type&
421 typename property_traits<IDMap>::key_type key)
422{
423 return i.m_iter[i.m_id[key]];
424}
425
426
427
428} // namespace boost
429
430
431#endif
432
@ T
value_type operator[](ml::VesselEdge *edge) const
boost::lvalue_property_map_tag category
This is a helper template to create an external property map for an std random access container.
property_traits< IDMap >::key_type key_type
ml_iterator_map(typename IteratorTraits::iterator_type i=IteratorTraits::iterator_type(), const IDMap &id=IDMap())
Constructor, takes an iterator to the beginning of a container, for example std::vector<>....
IteratorTraits::value_type value_type
IteratorTraits::iterator_type m_iter
lvalue_property_map_tag category
IteratorTraits::value_type & reference
Vertex id Maps each vertex to a unique id.
boost::readable_property_map_tag category
unsigned int operator[](ml::VesselNode *vertex) const
std::vector< ml::VesselEdge * >::iterator _edgeIter
std::vector< ml::VesselEdge * >::iterator _edgeIterEnd
ml_out_edge_iterator(ml::VesselNode *vertex, std::vector< ml::VesselEdge * >::iterator edgeIter, std::vector< ml::VesselEdge * >::iterator edgeIterEnd)
friend bool operator==(const self &x, const self &y)
ml::VesselEdge * operator*()
ml::Graph * ml_graph_ptr
typedef for use with graph_traits<>
Forward declaration for the boost::mutex class.
boost::graph_traits< ml_graph_ptr >::vertices_size_type num_vertices(const ml_graph_ptr g)
Returns the number of vertices in the graph g.
std::pair< boost::graph_traits< ml_graph_ptr >::out_edge_iterator, boost::graph_traits< ml_graph_ptr >::out_edge_iterator > out_edges(boost::graph_traits< ml_graph_ptr >::vertex_descriptor vertex, const ml_graph_ptr)
Returns an iterator-range providing access to the out-edges (for directed graphs) or incident edges (...
void put(const ml_iterator_map< IteratorTraits, IDMap > &i, typename property_traits< IDMap >::key_type key, const typename IteratorTraits::value_type &value)
boost::graph_traits< ml_graph_ptr >::vertex_descriptor vertex(boost::graph_traits< ml_graph_ptr >::degree_size_type arrayIndex, const ml_graph_ptr g)
Returns the vertex at internal index.
IteratorTraits::value_type & at(const ml_iterator_map< IteratorTraits, IDMap > &i, typename property_traits< IDMap >::key_type key)
ml_vertex_id_map get(vertex_index_t, ml_graph_ptr g)
get() function for vertex id property map vertex_index_t just necessary for overloading
std::pair< boost::graph_traits< ml_graph_ptr >::vertex_iterator, boost::graph_traits< ml_graph_ptr >::vertex_iterator > vertices(ml_graph_ptr g)
Returns an iterator-range providing access to all the vertices in the graph g.
boost::graph_traits< ml_graph_ptr >::vertex_descriptor source(graph_traits< ml_graph_ptr >::edge_descriptor e, const ml_graph_ptr)
Returns the vertex descriptor for u of the edge (u,v) represented by e.
boost::graph_traits< ml_graph_ptr >::degree_size_type out_degree(boost::graph_traits< ml_graph_ptr >::vertex_descriptor vertex, const ml_graph_ptr)
Returns the number of out-edges (for directed graphs) or the number of incident edges (for undirected...
boost::graph_traits< ml_graph_ptr >::vertex_descriptor target(graph_traits< ml_graph_ptr >::edge_descriptor e, const ml_graph_ptr)
Returns the vertex descriptor for v of the edge (u,v) represented by e.
ml_graph_traversal_tag traversal_category
This describes the ways in which the vertices and edges of the graph can be visited.
ml::Graph::NodeIterator vertex_iterator
A vertex iterator (obtained via vertices(g)) provides access to all of the vertices in a graph.
ml::VesselNode * vertex_descriptor
The type for vertex representative objects.
long vertices_size_type
The unsigned integer type used to represent the number of vertices in the graph.
allow_parallel_edge_tag edge_parallel_category
This describes whether the graph class allows the insertion of parallel edges (edges with the same so...
ml::VesselEdge * edge_descriptor
The type for edge representative objects.
long degree_size_type
The unsigned intergral type used for representing the number out-edges or incident edges of a vertex.
directed_tag directed_category
This type shall be convertible to directed_tag or undirected_tag.
This describes the ways in which the vertices and edges of the graph can be visited.
Since the correct std::iterator_traits rely on partial template specialization which is not supported...
std::random_access_iterator_tag iterator_category