Вы на правильном пути, но есть две вещи, которые необходимо изменить в вашем коде. Во-первых, существует специальный метод определения пользовательских свойств вершин. Во-вторых, существует другой синтаксис (более предпочтительный и, вероятно, единственный, который является правильным) для именованных параметров BGL.
По первому пункту, пожалуйста, обратитесь к разделу документации под названием Пользовательские свойства вершин . По сути, для определения пользовательского свойства вершины сначала необходимо определить «тип тега» (struct
с именем, оканчивающимся на _t
):
struct vertex_position_t {
typedef boost::vertex_property_tag kind;
};
Затем вы включаете тип тега где-то в шаблон boost::property
, который определяет внутренне хранимые свойства вершин:
typedef boost::property<boost::vertex_index_t, std::size_t,
boost::property<vertex_position_t, Position> > VertexProperties;
Вышеприведенное typedef
определяет два хранимых внутри свойства: индекс и пользовательскую "позицию".
В отношении второго элемента, предпочтительный способ использовать именованные параметры - это синтаксис, похожий на цепочку методов. Например, если функция принимает два именованных параметра, named_param1
и named_param2
, в пространстве имен boost
с именами named_param1
и named_param2
есть две функции, соответственно. Функция boost::named_param1
принимает значение параметра named_param1
и возвращает объект, имеющий метод named_param2
(аналогично, функция boost::named_param2
принимает значение параметра named_param2
и возвращает объект, имеющий named_param1
метод ). Вы вызываете метод для установки значения этого именованного параметра (который, в свою очередь, возвращает другой объект, имеющий методы для других поддерживаемых именованных параметров).
Чтобы передать значения val1
и val2
для именованных параметров named_param1
и named_param2
, вы можете использовать:
boost::named_parameter1(val1).named_param2(val2)
или
boost::named_parameter2(val2).named_param1(val1)
Для справки, вот полная программа, которая копирует сетку в объект типа Graph
:
#include <cassert>
#include <cstddef>
#include <cstdlib>
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/copy.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/grid_graph.hpp>
#include <boost/property_map/property_map.hpp>
struct vertex_position_t {
typedef boost::vertex_property_tag kind;
};
struct Position {
std::size_t x, y;
Position()
: x(0), y(0)
{
}
};
typedef boost::property<boost::vertex_index_t, std::size_t, boost::property<vertex_position_t, Position> > VertexProperties;
typedef boost::adjacency_list<boost::vecS, boost::listS, boost::undirectedS, VertexProperties> Graph;
typedef boost::graph_traits<Graph> GraphTraits;
namespace detail {
typedef boost::grid_graph<2> Grid;
typedef boost::graph_traits<Grid> GridTraits;
struct grid_to_graph_vertex_copier {
typedef boost::property_map< Grid, boost::vertex_index_t>::type grid_vertex_index_map;
typedef boost::property_map< ::Graph, boost::vertex_index_t>::type graph_vertex_index_map;
typedef boost::property_map< ::Graph, ::vertex_position_t>::type graph_vertex_position_map;
const Grid& grid;
grid_vertex_index_map grid_vertex_index;
graph_vertex_index_map graph_vertex_index;
graph_vertex_position_map graph_vertex_position;
grid_to_graph_vertex_copier(const Grid& grid_, Graph& graph)
: grid(grid_), grid_vertex_index(get(boost::vertex_index_t(), grid_)),
graph_vertex_index(get(boost::vertex_index_t(), graph)),
graph_vertex_position(get(::vertex_position_t(), graph))
{
}
private:
Position grid_vertex_index_to_position(std::size_t idx) const {
unsigned num_dims = grid.dimensions();
assert(grid.dimensions() == 2);
idx %= grid.length(0) * grid.length(1);
Position ret;
ret.x = idx % grid.length(0);
ret.y = idx / grid.length(0);
return ret;
}
public:
void operator()(GridTraits::vertex_descriptor grid_vertex, ::GraphTraits::vertex_descriptor graph_vertex) const {
std::size_t idx = get(grid_vertex_index, grid_vertex);
put(graph_vertex_index, graph_vertex, idx);
Position pos = grid_vertex_index_to_position(idx);
std::cout << "grid_vertex = " << idx << ", pos.x = " << pos.x << ", pos.y = " << pos.y << std::endl;
put(graph_vertex_position, graph_vertex, pos);
}
};
struct grid_to_graph_edge_copier {
void operator()(GridTraits::edge_descriptor grid_edge, ::GraphTraits::edge_descriptor graph_edge) const {
}
};
}
int main()
{
boost::array<std::size_t, 2> lengths = { { 3, 5 } };
detail::Grid grid(lengths);
Graph graph;
boost::copy_graph(grid, graph, boost::vertex_copy(detail::grid_to_graph_vertex_copier(grid, graph))
.edge_copy(detail::grid_to_graph_edge_copier()));
std::cout << std::endl;
boost::write_graphviz(std::cout, graph);
return EXIT_SUCCESS;
}
Когда я запустил это, я получил следующий вывод:
grid_vertex = 0, pos.x = 0, pos.y = 0
grid_vertex = 1, pos.x = 1, pos.y = 0
grid_vertex = 2, pos.x = 2, pos.y = 0
grid_vertex = 3, pos.x = 0, pos.y = 1
grid_vertex = 4, pos.x = 1, pos.y = 1
grid_vertex = 5, pos.x = 2, pos.y = 1
grid_vertex = 6, pos.x = 0, pos.y = 2
grid_vertex = 7, pos.x = 1, pos.y = 2
grid_vertex = 8, pos.x = 2, pos.y = 2
grid_vertex = 9, pos.x = 0, pos.y = 3
grid_vertex = 10, pos.x = 1, pos.y = 3
grid_vertex = 11, pos.x = 2, pos.y = 3
grid_vertex = 12, pos.x = 0, pos.y = 4
grid_vertex = 13, pos.x = 1, pos.y = 4
grid_vertex = 14, pos.x = 2, pos.y = 4
graph G {
0;
1;
2;
3;
4;
5;
6;
7;
8;
9;
10;
11;
12;
13;
14;
0--1 ;
1--2 ;
3--4 ;
4--5 ;
6--7 ;
7--8 ;
9--10 ;
10--11 ;
12--13 ;
13--14 ;
1--0 ;
2--1 ;
4--3 ;
5--4 ;
7--6 ;
8--7 ;
10--9 ;
11--10 ;
13--12 ;
14--13 ;
0--3 ;
1--4 ;
2--5 ;
3--6 ;
4--7 ;
5--8 ;
6--9 ;
7--10 ;
8--11 ;
9--12 ;
10--13 ;
11--14 ;
3--0 ;
4--1 ;
5--2 ;
6--3 ;
7--4 ;
8--5 ;
9--6 ;
10--7 ;
11--8 ;
12--9 ;
13--10 ;
14--11 ;
}