mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-13 12:32:09 +00:00
477 lines
28 KiB
HTML
477 lines
28 KiB
HTML
<!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">
|
||
|
||
</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 Page</span></a></li>
|
||
<li><a href="pages.html"><span>Related 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 <iostream></span>
|
||
<span class="preprocessor">#include <fstream></span>
|
||
<span class="preprocessor">#include <iomanip></span>
|
||
<span class="preprocessor">#include <limits></span>
|
||
|
||
<span class="preprocessor">#include <boost/tuple/tuple.hpp></span>
|
||
<span class="preprocessor">#include <boost/foreach.hpp></span>
|
||
|
||
<span class="preprocessor">#include <boost/graph/adjacency_list.hpp></span>
|
||
<span class="preprocessor">#include <boost/graph/dijkstra_shortest_paths.hpp></span>
|
||
|
||
<span class="preprocessor">#include <boost/geometry/geometry.hpp></span>
|
||
<span class="preprocessor">#include <<a class="code" href="cartesian2d_8hpp.html">boost/geometry/geometries/cartesian2d.hpp</a>></span>
|
||
|
||
|
||
<span class="comment">// Yes, this example currently uses some extensions:</span>
|
||
|
||
<span class="comment">// For input:</span>
|
||
<span class="preprocessor"> #include <boost/geometry/extensions/gis/io/wkt/read_wkt.hpp></span>
|
||
|
||
<span class="comment">// For output:</span>
|
||
<span class="preprocessor"> #include <<a class="code" href="write__svg_8hpp.html">boost/geometry/extensions/io/svg/write_svg.hpp</a>></span>
|
||
|
||
<span class="comment">// For distance-calculations over the Earth:</span>
|
||
<span class="preprocessor"> #include <boost/geometry/extensions/gis/geographic/strategies/andoyer.hpp></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 <0> a geometry and <1> an identifying string</span>
|
||
<span class="keyword">template</span> <<span class="keyword">typename</span> Geometry, <span class="keyword">typename</span> Tuple, <span class="keyword">typename</span> Box>
|
||
<span class="keywordtype">void</span> read_wkt(std::string <span class="keyword">const</span>& filename, std::vector<Tuple>& tuples, Box& 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() && ! 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<Box>(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& stream)
|
||
{
|
||
stream << <span class="stringliteral">"<?xml version=\"1.0\" standalone=\"no\"?>"</span> << std::endl;
|
||
stream << <span class="stringliteral">"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\""</span> << std::endl;
|
||
stream << <span class="stringliteral">"\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">"</span> << std::endl;
|
||
|
||
stream << <span class="stringliteral">"<svg width=\"100%\" height=\"100%\" version=\"1.1\""</span> << std::endl;
|
||
stream << <span class="stringliteral">"xmlns=\"http://www.w3.org/2000/svg\">"</span> << 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> <<span class="keyword">typename</span> Po<span class="keywordtype">int</span>>
|
||
<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>& loc)
|
||
{
|
||
location = loc;
|
||
}
|
||
|
||
Point location;
|
||
};
|
||
|
||
<span class="comment">// Define properties for edge</span>
|
||
<span class="keyword">template</span> <<span class="keyword">typename</span> Line<span class="keywordtype">string</span>>
|
||
<span class="keyword">struct </span>ggl_edge_property
|
||
{
|
||
ggl_edge_property(Linestring <span class="keyword">const</span>& 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>& 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> <<span class="keyword">typename</span> M, <span class="keyword">typename</span> K, <span class="keyword">typename</span> G>
|
||
<span class="keyword">inline</span> <span class="keyword">typename</span> boost::graph_traits<G>::vertex_descriptor find_or_insert(M& map, K <span class="keyword">const</span>& key, G& 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<G>::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<typename M::key_type>(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->second;
|
||
}
|
||
|
||
<span class="keyword">template</span>
|
||
<
|
||
<span class="keyword">typename</span> Line,
|
||
<span class="keyword">typename</span> Graph,
|
||
<span class="keyword">typename</span> RoadTupleVector,
|
||
<span class="keyword">typename</span> CityTupleVector
|
||
>
|
||
<span class="keywordtype">void</span> add_roads_and_connect_cities(Graph& graph,
|
||
RoadTupleVector <span class="keyword">const</span>& roads,
|
||
CityTupleVector& 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<Line>::type</a> point_type;
|
||
|
||
<span class="keyword">typedef</span> <span class="keyword">typename</span> boost::graph_traits<Graph>::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<point_type, vertex_type, boost::geometry::less<point_type> > 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<RoadTupleVector>::type road_type;
|
||
BOOST_FOREACH(road_type <span class="keyword">const</span>& road, roads)
|
||
{
|
||
<span class="comment">// Find or add begin/end point of these line</span>
|
||
vertex_type from = find_or_insert(map, road.get<0>().front(), graph);
|
||
vertex_type to = find_or_insert(map, road.get<0>().back(), graph);
|
||
boost::add_edge(from, to, ggl_edge_property<Line>(road.get<0>()), 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<CityTupleVector>::type city_type;
|
||
BOOST_FOREACH(city_type& 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->first, city.get<0>());
|
||
<span class="keywordflow">if</span> (dist < min_distance)
|
||
{
|
||
min_distance = dist;
|
||
<span class="comment">// Set the vertex</span>
|
||
city.get<2>() = it->second;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
<span class="keyword">template</span> <<span class="keyword">typename</span> Graph, <span class="keyword">typename</span> Route>
|
||
<span class="keyword">inline</span> <span class="keywordtype">void</span> add_edge_to_route(Graph <span class="keyword">const</span>& graph,
|
||
<span class="keyword">typename</span> boost::graph_traits<Graph>::vertex_descriptor vertex1,
|
||
<span class="keyword">typename</span> boost::graph_traits<Graph>::vertex_descriptor vertex2,
|
||
Route& route)
|
||
{
|
||
std::pair
|
||
<
|
||
<span class="keyword">typename</span> boost::graph_traits<Graph>::edge_descriptor,
|
||
<span class="keywordtype">bool</span>
|
||
> 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<Route> <span class="keyword">const</span>& 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<typename boost::geometry::point_type<Route>::type> <span class="keyword">const</span>& 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> <<span class="keyword">typename</span> Graph, <span class="keyword">typename</span> Route>
|
||
<span class="keyword">inline</span> <span class="keywordtype">void</span> build_route(Graph <span class="keyword">const</span>& graph,
|
||
std::vector<<span class="keyword">typename</span> boost::graph_traits<Graph>::vertex_descriptor> <span class="keyword">const</span>& predecessors,
|
||
<span class="keyword">typename</span> boost::graph_traits<Graph>::vertex_descriptor vertex1,
|
||
<span class="keyword">typename</span> boost::graph_traits<Graph>::vertex_descriptor vertex2,
|
||
Route& route)
|
||
{
|
||
<span class="keyword">typedef</span> <span class="keyword">typename</span> boost::graph_traits<Graph>::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<double, 2, boost::geometry::cs::geographic<boost::geometry::degree></a> > 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<point_type></a> line_type;
|
||
|
||
<span class="comment">// Define the graph, lateron containing the road network</span>
|
||
<span class="keyword">typedef</span> boost::adjacency_list
|
||
<
|
||
boost::vecS, boost::vecS, boost::undirectedS
|
||
, boost::property<vertex_ggl_property_t, ggl_vertex_property<point_type> >
|
||
, boost::property<edge_ggl_property_t, ggl_edge_property<line_type> >
|
||
> graph_type;
|
||
|
||
<span class="keyword">typedef</span> boost::graph_traits<graph_type>::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<point_type, std::string, vertex_type> city_type;
|
||
std::vector<city_type> cities;
|
||
read_wkt<point_type>(<span class="stringliteral">"data/cities.wkt"</span>, cities, box);
|
||
|
||
<span class="comment">// Read the road network</span>
|
||
<span class="keyword">typedef</span> boost::tuple<line_type, std::string> road_type;
|
||
std::vector<road_type> roads;
|
||
read_wkt<line_type>(<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<line_type>(graph, roads, cities);
|
||
|
||
<span class="keywordtype">double</span> <span class="keyword">const</span> km = 1000.0;
|
||
std::cout << <span class="stringliteral">"distances, all in KM"</span> << std::endl
|
||
<< std::fixed << 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>& city1, cities)
|
||
{
|
||
std::vector<vertex_type> predecessors(n);
|
||
std::vector<double> costs(n);
|
||
|
||
<span class="comment">// Call Dijkstra (without named-parameter to be compatible with all VC)</span>
|
||
boost::dijkstra_shortest_paths(graph, city1.get<2>(),
|
||
&predecessors[0], &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<double>(), std::plus<double>(),
|
||
(std::numeric_limits<double>::max)(), <span class="keywordtype">double</span>(),
|
||
boost::dijkstra_visitor<boost::null_visitor>());
|
||
|
||
BOOST_FOREACH(city_type <span class="keyword">const</span>& 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<1>(), city2.get<1>()))
|
||
{
|
||
<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<2>()] / 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<0>(), city2.get<0>()) / km;
|
||
|
||
std::cout
|
||
<< std::setiosflags (std::ios_base::left) << std::setw(15)
|
||
<< city1.get<1>() << <span class="stringliteral">" - "</span>
|
||
<< std::setiosflags (std::ios_base::left) << std::setw(15)
|
||
<< city2.get<1>()
|
||
<< <span class="stringliteral">" -> through the air: "</span> << std::setw(4) << acof
|
||
<< <span class="stringliteral">" , over the road: "</span> << std::setw(4) << distance
|
||
<< std::endl;
|
||
|
||
<span class="keywordflow">if</span> (first)
|
||
{
|
||
build_route(graph, predecessors,
|
||
city1.get<2>(), city2.get<2>(),
|
||
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<int></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>
|
||
<
|
||
point_type,
|
||
svg_point_type, <span class="keyword">true</span>, <span class="keyword">true</span>
|
||
> matrix(box, 1000, 800);
|
||
|
||
<span class="comment">// Map roads</span>
|
||
BOOST_FOREACH(road_type <span class="keyword">const</span>& 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<svg_point_type></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<0>(), line, matrix);
|
||
stream << <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>) << 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<svg_point_type></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 << <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>) << std::endl;
|
||
}
|
||
|
||
<span class="comment">// Map cities</span>
|
||
BOOST_FOREACH(city_type <span class="keyword">const</span>& 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<0>(), point, matrix);
|
||
stream << <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>) << std::endl;
|
||
}
|
||
|
||
stream << <span class="stringliteral">"</svg>"</span> << 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 <a href="http://www.doxygen.org/index.html">Doxygen</a>
|
||
</small></address>
|
||
</body>
|
||
</html>
|