Files
geometry/doc/doxygen_output/html/07__graph__route__example_8cpp-example.html
Barend Gehrels 363580fbf6 Added old doxygen docs
[SVN r59777]
2010-02-20 15:57:12 +00:00

477 lines
28 KiB
HTML
Raw Blame History

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.Geometry (aka GGL, Generic Geometry Library)</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
<link href="tabs.css" rel="stylesheet" type="text/css">
</head>
<table cellpadding="2" width="100%">
<tbody>
<tr>
<td valign="top">
<img alt="Boost.Geometry" src="images/ggl-logo-big.png" height="80" width="200">
&nbsp;&nbsp;
</td>
<td valign="top" align="right">
<a href="http://www.boost.org">
<img alt="Boost C++ Libraries" src="images/accepted_by_boost.png" height="80" width="230" border="0">
</a>
</td>
</tr>
</tbody>
</table>
<!-- Generated by Doxygen 1.5.9 -->
<div class="navigation" id="top">
<div class="tabs">
<ul>
<li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
<li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
<li><a href="modules.html"><span>Modules</span></a></li>
<li><a href="namespaces.html"><span>Namespaces</span></a></li>
<li><a href="annotated.html"><span>Classes</span></a></li>
<li><a href="files.html"><span>Files</span></a></li>
<li><a href="examples.html"><span>Examples</span></a></li>
</ul>
</div>
</div>
<div class="contents">
<h1>07_graph_route_example.cpp</h1>The graph route example shows how GGL can be combined with Boost.Graph. The sample does the following things:<ul>
<li>it reads roads (included in the distribution, stored on disk in the form of a text file containing geometries and names)</li><li>it reads cities</li><li>it creates a graph from the roads</li><li>it connects each city to the nearest vertex in the graph</li><li>it calculates the shortest route between each pair of cities</li><li>it outputs the distance over the road, and also of the air</li><li>it creates an SVG image with the roads, the cities, and the first calculated route</li></ul>
<p>
Note that this example is useful, but it is only an example. It could be built in many different ways. For example:<ul>
<li>the roads/cities could be read from a database using SOCI, or from a shapefile using shapelib</li><li>it could support oneway roads and roads on different levels (disconnected bridges)</li><li>it currently uses tuples but that could be anything</li><li>etc</li></ul>
<p>
The SVG looks like: <div align="center">
<img src="07_graph_route_example_svg.png" alt="07_graph_route_example_svg.png">
</div>
<p>
The output screen looks like: <div align="center">
<img src="07_graph_route_example_text.png" alt="07_graph_route_example_text.png">
</div>
<p>
<div class="fragment"><pre class="fragment"><span class="comment">// Boost.Geometry (aka GGL, Generic Geometry Library)</span>
<span class="comment">//</span>
<span class="comment">// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands</span>
<span class="comment">// Copyright Bruno Lalande 2008, 2009</span>
<span class="comment">// Use, modification and distribution is subject to the Boost Software License,</span>
<span class="comment">// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at</span>
<span class="comment">// http://www.boost.org/LICENSE_1_0.txt)</span>
<span class="comment">//</span>
<span class="comment">// Example showing GGL combined with Boost.Graph, calculating shortest routes</span>
<span class="comment">// input: two WKT's, provided in subfolder data</span>
<span class="comment">// output: text, + an SVG, displayable in e.g. Firefox)</span>
<span class="preprocessor">#include &lt;iostream&gt;</span>
<span class="preprocessor">#include &lt;fstream&gt;</span>
<span class="preprocessor">#include &lt;iomanip&gt;</span>
<span class="preprocessor">#include &lt;limits&gt;</span>
<span class="preprocessor">#include &lt;boost/tuple/tuple.hpp&gt;</span>
<span class="preprocessor">#include &lt;boost/foreach.hpp&gt;</span>
<span class="preprocessor">#include &lt;boost/graph/adjacency_list.hpp&gt;</span>
<span class="preprocessor">#include &lt;boost/graph/dijkstra_shortest_paths.hpp&gt;</span>
<span class="preprocessor">#include &lt;boost/geometry/geometry.hpp&gt;</span>
<span class="preprocessor">#include &lt;<a class="code" href="cartesian2d_8hpp.html">boost/geometry/geometries/cartesian2d.hpp</a>&gt;</span>
<span class="comment">// Yes, this example currently uses some extensions:</span>
<span class="comment">// For input:</span>
<span class="preprocessor"> #include &lt;boost/geometry/extensions/gis/io/wkt/read_wkt.hpp&gt;</span>
<span class="comment">// For output:</span>
<span class="preprocessor"> #include &lt;<a class="code" href="write__svg_8hpp.html">boost/geometry/extensions/io/svg/write_svg.hpp</a>&gt;</span>
<span class="comment">// For distance-calculations over the Earth:</span>
<span class="preprocessor"> #include &lt;boost/geometry/extensions/gis/geographic/strategies/andoyer.hpp&gt;</span>
<span class="comment">// Read an ASCII file containing WKT's, fill a vector of tuples</span>
<span class="comment">// The tuples consist of at least &lt;0&gt; a geometry and &lt;1&gt; an identifying string</span>
<span class="keyword">template</span> &lt;<span class="keyword">typename</span> Geometry, <span class="keyword">typename</span> Tuple, <span class="keyword">typename</span> Box&gt;
<span class="keywordtype">void</span> read_wkt(std::string <span class="keyword">const</span>&amp; filename, std::vector&lt;Tuple&gt;&amp; tuples, Box&amp; box)
{
std::ifstream cpp_file(filename.c_str());
<span class="keywordflow">if</span> (cpp_file.is_open())
{
<span class="keywordflow">while</span> (! cpp_file.eof() )
{
std::string line;
std::getline(cpp_file, line);
Geometry geometry;
boost::trim(line);
<span class="keywordflow">if</span> (! line.empty() &amp;&amp; ! boost::starts_with(line, <span class="stringliteral">"#"</span>))
{
std::string name;
<span class="comment">// Split at ';', if any</span>
std::string::size_type pos = line.find(<span class="stringliteral">";"</span>);
<span class="keywordflow">if</span> (pos != std::string::npos)
{
name = line.substr(pos + 1);
line.erase(pos);
boost::trim(line);
boost::trim(name);
}
Geometry geometry;
boost::geometry::read_wkt(line, geometry);
Tuple tuple(geometry, name);
tuples.push_back(tuple);
<a name="a0"></a><a class="code" href="group__combine.html#g7757b2934a94453246217e5d95a78a07" title="Combines a box with another geometry (box, point).">boost::geometry::combine</a>(box, boost::geometry::make_envelope&lt;Box&gt;(geometry));
}
}
}
}
<span class="comment">// Boilerplate code to initialize the SVG XML.</span>
<span class="comment">// Note that this is (on purpose) not part of the library but of this sample.</span>
<span class="comment">// GGL itself only streams small pieces of SVG, in any coordinate system</span>
<span class="keywordtype">void</span> svg_header(std::ofstream&amp; stream)
{
stream &lt;&lt; <span class="stringliteral">"&lt;?xml version=\"1.0\" standalone=\"no\"?&gt;"</span> &lt;&lt; std::endl;
stream &lt;&lt; <span class="stringliteral">"&lt;!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\""</span> &lt;&lt; std::endl;
stream &lt;&lt; <span class="stringliteral">"\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"&gt;"</span> &lt;&lt; std::endl;
stream &lt;&lt; <span class="stringliteral">"&lt;svg width=\"100%\" height=\"100%\" version=\"1.1\""</span> &lt;&lt; std::endl;
stream &lt;&lt; <span class="stringliteral">"xmlns=\"http://www.w3.org/2000/svg\"&gt;"</span> &lt;&lt; std::endl;
}
<span class="comment">// Code to define properties for Boost Graph's</span>
<span class="keyword">enum</span> vertex_ggl_property_t { vertex_ggl_property };
<span class="keyword">enum</span> edge_ggl_property_t { edge_ggl_property };
<span class="keyword">namespace </span>boost
{
BOOST_INSTALL_PROPERTY(vertex, ggl_property);
BOOST_INSTALL_PROPERTY(edge, ggl_property);
}
<span class="comment">// Define properties for vertex</span>
<span class="keyword">template</span> &lt;<span class="keyword">typename</span> Po<span class="keywordtype">int</span>&gt;
<span class="keyword">struct </span>ggl_vertex_property
{
ggl_vertex_property()
{
<a name="a1"></a><a class="code" href="group__access.html#ge605b147a3c95d645e7b62e5e2ee8fea" title="assign zero values to a box, point">boost::geometry::assign_zero</a>(location);
}
ggl_vertex_property(Point <span class="keyword">const</span>&amp; loc)
{
location = loc;
}
Point location;
};
<span class="comment">// Define properties for edge</span>
<span class="keyword">template</span> &lt;<span class="keyword">typename</span> Line<span class="keywordtype">string</span>&gt;
<span class="keyword">struct </span>ggl_edge_property
{
ggl_edge_property(Linestring <span class="keyword">const</span>&amp; line)
: m_line(line)
{
m_length = <a name="a2"></a><a class="code" href="group__length.html#g1537537131cd91037cf3ad9fd80d50f1" title="Calculate length of a geometry.">boost::geometry::length</a>(line);
}
<span class="keyword">inline</span> operator double()<span class="keyword"> const</span>
<span class="keyword"> </span>{
<span class="keywordflow">return</span> m_length;
}
<span class="keyword">inline</span> Linestring <span class="keyword">const</span>&amp; line()<span class="keyword"> const</span>
<span class="keyword"> </span>{
<span class="keywordflow">return</span> m_line;
}
<span class="keyword">private</span> :
<span class="keywordtype">double</span> m_length;
Linestring m_line;
};
<span class="comment">// Utility function to add a vertex to a graph. It might exist already. Then do not insert,</span>
<span class="comment">// but return vertex descriptor back. It might not exist. Then add it (and return).</span>
<span class="comment">// To efficiently handle this, a std::map is used.</span>
<span class="keyword">template</span> &lt;<span class="keyword">typename</span> M, <span class="keyword">typename</span> K, <span class="keyword">typename</span> G&gt;
<span class="keyword">inline</span> <span class="keyword">typename</span> boost::graph_traits&lt;G&gt;::vertex_descriptor find_or_insert(M&amp; map, K <span class="keyword">const</span>&amp; key, G&amp; graph)
{
<span class="keyword">typename</span> M::const_iterator it = map.find(key);
<span class="keywordflow">if</span> (it == map.end())
{
<span class="comment">// Add a vertex to the graph</span>
<span class="keyword">typename</span> boost::graph_traits&lt;G&gt;::vertex_descriptor new_vertex
= boost::add_vertex(graph);
<span class="comment">// Set the property (= location)</span>
boost::put(<a name="a3"></a><a class="code" href="group__access.html#g369b4a9519f357a05b68739fcf4ab374" title="get coordinate value of a Point ( / Sphere)">boost::get</a>(vertex_ggl_property, graph), new_vertex,
ggl_vertex_property&lt;typename M::key_type&gt;(key));
<span class="comment">// Add to the map, using POINT as key</span>
map[key] = new_vertex;
<span class="keywordflow">return</span> new_vertex;
}
<span class="keywordflow">return</span> it-&gt;second;
}
<span class="keyword">template</span>
&lt;
<span class="keyword">typename</span> Line,
<span class="keyword">typename</span> Graph,
<span class="keyword">typename</span> RoadTupleVector,
<span class="keyword">typename</span> CityTupleVector
&gt;
<span class="keywordtype">void</span> add_roads_and_connect_cities(Graph&amp; graph,
RoadTupleVector <span class="keyword">const</span>&amp; roads,
CityTupleVector&amp; cities)
{
<span class="keyword">typedef</span> <span class="keyword">typename</span> <a name="_a4"></a><a class="code" href="structboost_1_1geometry_1_1point__type.html" title="Meta-function which defines point type of any geometry.">boost::geometry::point_type&lt;Line&gt;::type</a> point_type;
<span class="keyword">typedef</span> <span class="keyword">typename</span> boost::graph_traits&lt;Graph&gt;::vertex_descriptor vertex_type;
<span class="comment">// Define a map to be used during graph filling</span>
<span class="comment">// Maps from point to vertex-id's</span>
<span class="keyword">typedef</span> std::map&lt;point_type, vertex_type, boost::geometry::less&lt;point_type&gt; &gt; map_type;
map_type map;
<span class="comment">// Fill the graph</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> boost::range_value&lt;RoadTupleVector&gt;::type road_type;
BOOST_FOREACH(road_type <span class="keyword">const</span>&amp; road, roads)
{
<span class="comment">// Find or add begin/end point of these line</span>
vertex_type from = find_or_insert(map, road.get&lt;0&gt;().front(), graph);
vertex_type to = find_or_insert(map, road.get&lt;0&gt;().back(), graph);
boost::add_edge(from, to, ggl_edge_property&lt;Line&gt;(road.get&lt;0&gt;()), graph);
}
<span class="comment">// Find nearest graph vertex for each city, using the map</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> boost::range_value&lt;CityTupleVector&gt;::type city_type;
BOOST_FOREACH(city_type&amp; city, cities)
{
<span class="keywordtype">double</span> min_distance = 1e300;
<span class="keywordflow">for</span>(<span class="keyword">typename</span> map_type::const_iterator it = map.begin(); it != map.end(); ++it)
{
<span class="keywordtype">double</span> dist = <a name="a5"></a><a class="code" href="group__distance.html#g8fb8022d64a75b24c80a64ba46ec4738" title="Calculate distance between two geometries with a specified strategy.">boost::geometry::distance</a>(it-&gt;first, city.get&lt;0&gt;());
<span class="keywordflow">if</span> (dist &lt; min_distance)
{
min_distance = dist;
<span class="comment">// Set the vertex</span>
city.get&lt;2&gt;() = it-&gt;second;
}
}
}
}
<span class="keyword">template</span> &lt;<span class="keyword">typename</span> Graph, <span class="keyword">typename</span> Route&gt;
<span class="keyword">inline</span> <span class="keywordtype">void</span> add_edge_to_route(Graph <span class="keyword">const</span>&amp; graph,
<span class="keyword">typename</span> boost::graph_traits&lt;Graph&gt;::vertex_descriptor vertex1,
<span class="keyword">typename</span> boost::graph_traits&lt;Graph&gt;::vertex_descriptor vertex2,
Route&amp; route)
{
std::pair
&lt;
<span class="keyword">typename</span> boost::graph_traits&lt;Graph&gt;::edge_descriptor,
<span class="keywordtype">bool</span>
&gt; opt_edge = boost::edge(vertex1, vertex2, graph);
<span class="keywordflow">if</span> (opt_edge.second)
{
<span class="comment">// Get properties of edge and of vertex</span>
ggl_edge_property&lt;Route&gt; <span class="keyword">const</span>&amp; edge_prop =
<a class="code" href="group__access.html#g369b4a9519f357a05b68739fcf4ab374" title="get coordinate value of a Point ( / Sphere)">boost::get</a>(<a class="code" href="group__access.html#g369b4a9519f357a05b68739fcf4ab374" title="get coordinate value of a Point ( / Sphere)">boost::get</a>(edge_ggl_property, graph), opt_edge.first);
ggl_vertex_property&lt;typename boost::geometry::point_type&lt;Route&gt;::type&gt; <span class="keyword">const</span>&amp; vertex_prop =
<a class="code" href="group__access.html#g369b4a9519f357a05b68739fcf4ab374" title="get coordinate value of a Point ( / Sphere)">boost::get</a>(<a class="code" href="group__access.html#g369b4a9519f357a05b68739fcf4ab374" title="get coordinate value of a Point ( / Sphere)">boost::get</a>(vertex_ggl_property, graph), vertex2);
<span class="comment">// Depending on how edge connects to vertex, copy it forward or backward</span>
<span class="keywordflow">if</span> (<a name="a6"></a><a class="code" href="group__equals.html#ge18e3cb2ad5b7fbc8f0ce9e0f92397bc" title="Detect if two geometries are spatially equal.">boost::geometry::equals</a>(edge_prop.line().front(), vertex_prop.location))
{
std::copy(edge_prop.line().begin(), edge_prop.line().end(),
std::back_inserter(route));
}
<span class="keywordflow">else</span>
{
std::reverse_copy(edge_prop.line().begin(), edge_prop.line().end(),
std::back_inserter(route));
}
}
}
<span class="keyword">template</span> &lt;<span class="keyword">typename</span> Graph, <span class="keyword">typename</span> Route&gt;
<span class="keyword">inline</span> <span class="keywordtype">void</span> build_route(Graph <span class="keyword">const</span>&amp; graph,
std::vector&lt;<span class="keyword">typename</span> boost::graph_traits&lt;Graph&gt;::vertex_descriptor&gt; <span class="keyword">const</span>&amp; predecessors,
<span class="keyword">typename</span> boost::graph_traits&lt;Graph&gt;::vertex_descriptor vertex1,
<span class="keyword">typename</span> boost::graph_traits&lt;Graph&gt;::vertex_descriptor vertex2,
Route&amp; route)
{
<span class="keyword">typedef</span> <span class="keyword">typename</span> boost::graph_traits&lt;Graph&gt;::vertex_descriptor vertex_type;
vertex_type pred = predecessors[vertex2];
add_edge_to_route(graph, vertex2, pred, route);
<span class="keywordflow">while</span> (pred != vertex1)
{
add_edge_to_route(graph, predecessors[pred], pred, route);
pred = predecessors[pred];
}
}
<span class="keywordtype">int</span> main()
{
<span class="comment">// Define a point in the Geographic coordinate system</span>
<span class="keyword">typedef</span> <a name="_a7"></a><a class="code" href="classboost_1_1geometry_1_1point.html" title="Basic point class, having coordinates defined in a neutral way.">boost::geometry::point&lt;double, 2, boost::geometry::cs::geographic&lt;boost::geometry::degree&gt;</a> &gt; point_type;
<span class="keyword">typedef</span> <a name="_a8"></a><a class="code" href="classboost_1_1geometry_1_1linestring.html" title="A linestring (named so by OGC) is a collection (default a vector) of points.">boost::geometry::linestring&lt;point_type&gt;</a> line_type;
<span class="comment">// Define the graph, lateron containing the road network</span>
<span class="keyword">typedef</span> boost::adjacency_list
&lt;
boost::vecS, boost::vecS, boost::undirectedS
, boost::property&lt;vertex_ggl_property_t, ggl_vertex_property&lt;point_type&gt; &gt;
, boost::property&lt;edge_ggl_property_t, ggl_edge_property&lt;line_type&gt; &gt;
&gt; graph_type;
<span class="keyword">typedef</span> boost::graph_traits&lt;graph_type&gt;::vertex_descriptor vertex_type;
<span class="comment">// Init a bounding box, lateron used to define SVG map</span>
<a name="_a9"></a><a class="code" href="classboost_1_1geometry_1_1box.html" title="Class box: defines a box made of two describing points.">boost::geometry::box_2d</a> box;
<a name="a10"></a><a class="code" href="group__access.html#g214bc5c2c841a98c58f4d1baca423f86" title="assign to a box inverse infinite">boost::geometry::assign_inverse</a>(box);
<span class="comment">// Read the cities</span>
<span class="keyword">typedef</span> boost::tuple&lt;point_type, std::string, vertex_type&gt; city_type;
std::vector&lt;city_type&gt; cities;
read_wkt&lt;point_type&gt;(<span class="stringliteral">"data/cities.wkt"</span>, cities, box);
<span class="comment">// Read the road network</span>
<span class="keyword">typedef</span> boost::tuple&lt;line_type, std::string&gt; road_type;
std::vector&lt;road_type&gt; roads;
read_wkt&lt;line_type&gt;(<span class="stringliteral">"data/roads.wkt"</span>, roads, box);
graph_type graph;
<span class="comment">// Add roads and connect cities</span>
add_roads_and_connect_cities&lt;line_type&gt;(graph, roads, cities);
<span class="keywordtype">double</span> <span class="keyword">const</span> km = 1000.0;
std::cout &lt;&lt; <span class="stringliteral">"distances, all in KM"</span> &lt;&lt; std::endl
&lt;&lt; std::fixed &lt;&lt; std::setprecision(0);
<span class="comment">// Main functionality: calculate shortest routes from/to all cities</span>
<span class="comment">// For the first one, the complete route is stored as a linestring</span>
<span class="keywordtype">bool</span> first = <span class="keyword">true</span>;
line_type route;
<span class="keywordtype">int</span> <span class="keyword">const</span> n = boost::num_vertices(graph);
BOOST_FOREACH(city_type <span class="keyword">const</span>&amp; city1, cities)
{
std::vector&lt;vertex_type&gt; predecessors(n);
std::vector&lt;double&gt; costs(n);
<span class="comment">// Call Dijkstra (without named-parameter to be compatible with all VC)</span>
boost::dijkstra_shortest_paths(graph, city1.get&lt;2&gt;(),
&amp;predecessors[0], &amp;costs[0],
<a class="code" href="group__access.html#g369b4a9519f357a05b68739fcf4ab374" title="get coordinate value of a Point ( / Sphere)">boost::get</a>(edge_ggl_property, graph),
<a class="code" href="group__access.html#g369b4a9519f357a05b68739fcf4ab374" title="get coordinate value of a Point ( / Sphere)">boost::get</a>(boost::vertex_index, graph),
std::less&lt;double&gt;(), std::plus&lt;double&gt;(),
(std::numeric_limits&lt;double&gt;::max)(), <span class="keywordtype">double</span>(),
boost::dijkstra_visitor&lt;boost::null_visitor&gt;());
BOOST_FOREACH(city_type <span class="keyword">const</span>&amp; city2, cities)
{
<span class="keywordflow">if</span> (! <a class="code" href="group__equals.html#ge18e3cb2ad5b7fbc8f0ce9e0f92397bc" title="Detect if two geometries are spatially equal.">boost::equals</a>(city1.get&lt;1&gt;(), city2.get&lt;1&gt;()))
{
<span class="keywordtype">double</span> <a class="code" href="group__distance.html#g8fb8022d64a75b24c80a64ba46ec4738" title="Calculate distance between two geometries with a specified strategy.">distance</a> = costs[city2.get&lt;2&gt;()] / km;
<span class="keywordtype">double</span> acof = <a class="code" href="group__distance.html#g8fb8022d64a75b24c80a64ba46ec4738" title="Calculate distance between two geometries with a specified strategy.">boost::geometry::distance</a>(city1.get&lt;0&gt;(), city2.get&lt;0&gt;()) / km;
std::cout
&lt;&lt; std::setiosflags (std::ios_base::left) &lt;&lt; std::setw(15)
&lt;&lt; city1.get&lt;1&gt;() &lt;&lt; <span class="stringliteral">" - "</span>
&lt;&lt; std::setiosflags (std::ios_base::left) &lt;&lt; std::setw(15)
&lt;&lt; city2.get&lt;1&gt;()
&lt;&lt; <span class="stringliteral">" -&gt; through the air: "</span> &lt;&lt; std::setw(4) &lt;&lt; acof
&lt;&lt; <span class="stringliteral">" , over the road: "</span> &lt;&lt; std::setw(4) &lt;&lt; distance
&lt;&lt; std::endl;
<span class="keywordflow">if</span> (first)
{
build_route(graph, predecessors,
city1.get&lt;2&gt;(), city2.get&lt;2&gt;(),
route);
first = <span class="keyword">false</span>;
}
}
}
}
<span class="comment">// Create the SVG</span>
<span class="keyword">typedef</span> <a name="_a11"></a><a class="code" href="classboost_1_1geometry_1_1point__xy.html" title="2D point in Cartesian coordinate system">boost::geometry::point_xy&lt;int&gt;</a> svg_point_type;
std::ofstream stream(<span class="stringliteral">"routes.svg"</span>);
svg_header(stream);
<a name="_a12"></a><a class="code" href="structboost_1_1geometry_1_1strategy_1_1transform_1_1map__transformer.html" title="Transformation strategy to do map from one to another Cartesian system.">boost::geometry::strategy::transform::map_transformer</a>
&lt;
point_type,
svg_point_type, <span class="keyword">true</span>, <span class="keyword">true</span>
&gt; matrix(box, 1000, 800);
<span class="comment">// Map roads</span>
BOOST_FOREACH(road_type <span class="keyword">const</span>&amp; road, roads)
{
<a class="code" href="classboost_1_1geometry_1_1linestring.html" title="A linestring (named so by OGC) is a collection (default a vector) of points.">boost::geometry::linestring&lt;svg_point_type&gt;</a> line;
<a name="a13"></a><a class="code" href="group__transform.html#g6b9a387b5ac973d7d9e273d9dffc1d3e" title="Transforms from one geometry to another geometry using a strategy.">boost::geometry::transform</a>(road.get&lt;0&gt;(), line, matrix);
stream &lt;&lt; <a name="a14"></a><a class="code" href="group__svg.html#ged9f8d69d3138781ffc624d11b96f95c" title="Main svg function to stream geometries as SVG.">boost::geometry::svg</a>(line, <span class="stringliteral">"stroke:rgb(128,128,128);stroke-width:1"</span>) &lt;&lt; std::endl;
}
<span class="comment">// Map the calculated route as thicker green transparent markation</span>
{
<a class="code" href="classboost_1_1geometry_1_1linestring.html" title="A linestring (named so by OGC) is a collection (default a vector) of points.">boost::geometry::linestring&lt;svg_point_type&gt;</a> line;
<a class="code" href="group__transform.html#g6b9a387b5ac973d7d9e273d9dffc1d3e" title="Transforms from one geometry to another geometry using a strategy.">boost::geometry::transform</a>(route, line, matrix);
stream &lt;&lt; <a class="code" href="group__svg.html#ged9f8d69d3138781ffc624d11b96f95c" title="Main svg function to stream geometries as SVG.">boost::geometry::svg</a>(line, <span class="stringliteral">"stroke:rgb(0, 255, 0);stroke-width:6;opacity:0.5"</span>) &lt;&lt; std::endl;
}
<span class="comment">// Map cities</span>
BOOST_FOREACH(city_type <span class="keyword">const</span>&amp; city, cities)
{
svg_point_type point;
<a class="code" href="group__transform.html#g6b9a387b5ac973d7d9e273d9dffc1d3e" title="Transforms from one geometry to another geometry using a strategy.">boost::geometry::transform</a>(city.get&lt;0&gt;(), point, matrix);
stream &lt;&lt; <a class="code" href="group__svg.html#ged9f8d69d3138781ffc624d11b96f95c" title="Main svg function to stream geometries as SVG.">boost::geometry::svg</a>(point, <span class="stringliteral">"fill:rgb(255,255,0);stroke:rgb(0,0,0);stroke-width:1"</span>) &lt;&lt; std::endl;
}
stream &lt;&lt; <span class="stringliteral">"&lt;/svg&gt;"</span> &lt;&lt; std::endl;
<span class="keywordflow">return</span> 0;
}
</pre></div> </div>
<hr size="1">
<table width="100%">
<tbody>
<tr>
<td align="left"><small>
<p>December 1, 2009</p>
</small></td>
<td align="right">
<small>Copyright <20> 1995-2009 Barend Gehrels, Geodan, Amsterdam<br>
Copyright <20> 2008-2009 Bruno Lalande, Paris<br>
Copyright <20> 2009 Mateusz Loskot, Cadcorp, London<br>
</small>
</td>
</tr>
</tbody>
</table>
<address style="text-align: right;"><small>
Documentation is generated by&nbsp;<a href="http://www.doxygen.org/index.html">Doxygen</a>
</small></address>
</body>
</html>