Skip to content

Commit 2983475

Browse files
Own Dijkstra implementation
1 parent 040146c commit 2983475

File tree

13 files changed

+666
-266
lines changed

13 files changed

+666
-266
lines changed

docs/profiles.md

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ The following global properties can be set under `properties` in the hash you re
9595

9696
Attribute | Type | Notes
9797
-------------------------------------|----------|----------------------------------------------------------------------------
98-
weight_name | String | Name used in output for the routing weight property (default `'duration'`)
98+
weight_name | String | Name used in output for the routing weight property (default `"duration"`)
9999
weight_precision | Unsigned | Decimal precision of edge weights (default `1`)
100100
left_hand_driving | Boolean | Are vehicles assumed to drive on the left? (used in guidance, default `false`)
101101
use_turn_restrictions | Boolean | Are turn restrictions followed? (default `false`)
@@ -167,28 +167,28 @@ weight | read-only | float | The weight
167167
#### obstacle_type
168168
An enum with the following keys:
169169

170-
Keys |
171-
----------------|
172-
none |
173-
barrier |
174-
traffic_signals |
175-
stop |
176-
give_way |
177-
crossing |
178-
traffic_calming |
179-
mini_roundabout |
180-
turning_loop |
181-
turning_circle |
170+
| Keys |
171+
|-----------------|
172+
| none |
173+
| barrier |
174+
| traffic_signals |
175+
| stop |
176+
| give_way |
177+
| crossing |
178+
| traffic_calming |
179+
| mini_roundabout |
180+
| turning_loop |
181+
| turning_circle |
182182

183183
#### obstacle_direction
184184
An enum with the following keys:
185185

186-
Keys |
187-
---------|
188-
none |
189-
forward |
190-
backward |
191-
both |
186+
| Keys |
187+
|----------|
188+
| none |
189+
| forward |
190+
| backward |
191+
| both |
192192

193193
### obstacle_map
194194
A global user type. It stores obstacles.
@@ -409,10 +409,10 @@ weight | Read/write | Float |
409409
duration | Read/write | Float | Penalty to be applied for this turn (duration in deciseconds)
410410

411411

412-
#### `from`, `via`, and `to`
412+
#### from, via, and to
413413
Use these node IDs to retrieve obstacles. See: `obstacle_map:get`.
414414

415-
#### `source_road`, `target_road`, `roads_on_the_right`, and `roads_on_the_left`
415+
#### source_road, target_road, roads_on_the_right, and roads_on_the_left
416416

417417
The information of `source_road`, `target_road`, `roads_on_the_right`, and
418418
`roads_on_the_left` that can be read are as follows:
@@ -455,7 +455,7 @@ When turning from `a` to `b` via `x`,
455455

456456
Note that indices of arrays in lua are 1-based.
457457

458-
#### `highway_turn_classification` and `access_turn_classification`
458+
#### highway_turn_classification and access_turn_classification
459459
When setting appropriate turn weights and duration, information about the highway and access tags of roads that are involved in the turn are necessary. The lua turn function `process_turn` does not have access to the original osrm tags anymore. However, `highway_turn_classification` and `access_turn_classification` can be set during setup. The classification set during setup can be later used in `process_turn`.
460460

461461
**Example**

include/extractor/area/area_manager.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
namespace osrm::extractor::area
1717
{
1818

19+
/**
20+
* @brief Registers area objects from LUA.
21+
*
22+
* An object of this class is a global variable in LUA scripts. Call way() if you want
23+
* to turn a closed way into an area, call relation() if you want to turn a multipolygon
24+
* relation into an area.
25+
*/
1926
class AreaManager
2027
: public osmium::relations::RelationsManager<AreaManager, false, true, false, false>
2128
{

include/extractor/area/area_mesher.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ namespace osrm::extractor::area
2626

2727
class AreaManager;
2828

29+
/**
30+
* @brief A class that "meshes" areas
31+
*
32+
* A class that "meshes" an area by creating OSM ways that follow each shortest path
33+
* between all pairs of entry points to the area. It first generates a visibility map,
34+
* then uses Dijkstra's shortest path algorithm to reduce the number of edges. The
35+
* generated ways are returned in an osmium buffer.
36+
*/
2937
class AreaMesher
3038
{
3139
public:
@@ -47,6 +55,10 @@ class AreaMesher
4755
using WayNodeIDOffsets = std::vector<size_t>;
4856
using WayIDVector = std::vector<OSMWayID>;
4957

58+
std::set<OsmiumSegment> run_dijkstra(const OsmiumPolygon &poly,
59+
std::set<OsmiumSegment> &vis_map,
60+
const NodeRefSet &entry_points);
61+
5062
ExtractionRelationContainer::RelationIDList
5163
get_relations(const osmium::Area &area, const ExtractionRelationContainer &relations);
5264

include/extractor/area/dijkstra.hpp

Lines changed: 134 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,159 @@
11
#ifndef OSRM_EXTRACTOR_AREA_DIJKSTRA_HPP
22
#define OSRM_EXTRACTOR_AREA_DIJKSTRA_HPP
33

4-
#include "extractor/area/typedefs.hpp"
4+
#include "index_priority_queue.hpp"
55

6-
#include <boost/graph/adjacency_list.hpp>
7-
#include <boost/graph/dijkstra_shortest_paths.hpp>
8-
#include <boost/graph/dijkstra_shortest_paths_no_color_map.hpp>
9-
#include <boost/graph/graph_traits.hpp>
10-
11-
#include <iterator>
12-
#include <osmium/osm.hpp>
13-
#include <osmium/osm/node_ref.hpp>
14-
#include <osmium/osm/types.hpp>
6+
#include <cmath>
7+
#include <limits>
8+
#include <map>
9+
#include <vector>
1510

1611
namespace osrm::extractor::area
1712
{
1813

1914
/**
20-
* Runs the Dijkstra shortest path algorithm on the area polygon and the visibility
21-
* graph.
15+
* @brief Implements the Dijkstra shortest-path algorithm.
2216
*
23-
* We do not want to keep all visible edges we found, only those that are part of a
24-
* shortest path between any two entry points to the area. We use Dijkstra to find all
25-
* these shortest paths.
17+
* @tparam vertex_t The type of a vertex.
2618
*/
27-
class Dijkstra
19+
template <class vertex_t> class DijkstraImpl
2820
{
29-
using vertices_t = std::vector<osmium::NodeRef>;
30-
using vertices_iter_t = vertices_t::iterator;
31-
using graph_t = boost::adjacency_list<boost::vecS,
32-
boost::vecS,
33-
boost::undirectedS,
34-
boost::no_property,
35-
boost::property<boost::edge_weight_t, double>>;
36-
using vertex_descriptor = boost::graph_traits<graph_t>::vertex_descriptor;
37-
using Edge = std::pair<vertex_descriptor, vertex_descriptor>;
21+
struct Edge
22+
{
23+
size_t other;
24+
double weight;
25+
};
26+
std::vector<vertex_t> vertices;
27+
std::map<vertex_t, size_t> seen_vertices;
3828

39-
public:
40-
Dijkstra(const OsmiumPolygon &poly, std::set<OsmiumSegment> &vis_map);
41-
std::set<OsmiumSegment> run(const NodeRefSet &entry_points);
29+
std::vector<double> distances;
30+
std::vector<size_t> predecessors;
31+
std::vector<std::vector<Edge>> adj;
4232

43-
private:
44-
vertices_iter_t find(const osmium::NodeRef &n)
33+
/**
34+
* @brief Initialize the data structures before each run.
35+
*/
36+
void init_data()
4537
{
46-
return std::lower_bound(vertices.begin(),
47-
vertices.end(),
48-
n,
49-
[](const osmium::NodeRef &u, const osmium::NodeRef &v)
50-
{ return u < v; });
38+
double inf = std::numeric_limits<double>::infinity();
39+
distances.resize(vertices.size());
40+
predecessors.resize(vertices.size());
41+
for (size_t i = 0; i < vertices.size(); ++i)
42+
{
43+
distances[i] = inf;
44+
predecessors[i] = i;
45+
}
5146
}
52-
vertex_descriptor indexOf(const osmium::NodeRef &n)
47+
48+
public:
49+
/**
50+
* @brief Add one vertex to the graph.
51+
*
52+
* If a vertex is already present it will not be inserted again and the index of the
53+
* present vertex will be returned.
54+
*
55+
* @param v The vertex
56+
* @return size_t The index of the vertex.
57+
*/
58+
size_t add_vertex(const vertex_t &v)
5359
{
54-
return std::distance(vertices.begin(), find(n));
60+
if (seen_vertices.contains(v))
61+
return seen_vertices.at(v);
62+
size_t pos = vertices.size();
63+
seen_vertices.emplace(v, pos);
64+
vertices.push_back(v);
65+
return pos;
66+
};
67+
68+
/**
69+
* @brief Return the index of the vertex.
70+
*
71+
* @param v The vertex
72+
* @return size_t The index of the vertex.
73+
*/
74+
size_t index_of(const vertex_t &v) { return seen_vertices.at(v); }
75+
76+
/**
77+
* @brief Get the vertex object
78+
*
79+
* @param i The index of the vertex
80+
* @return const vertex_t& The vertex
81+
*/
82+
const vertex_t &get_vertex(size_t i) { return vertices.at(i); };
83+
84+
/**
85+
* @brief Add one edge to the graph.
86+
*
87+
* @param u The first vertex.
88+
* @param v The second vertex.
89+
* @param weight The weight of the edge.
90+
*/
91+
void add_edge(const vertex_t &u, const vertex_t &v, double weight)
92+
{
93+
size_t iu = add_vertex(u);
94+
size_t iv = add_vertex(v);
95+
adj.resize(vertices.size());
96+
adj[iu].emplace_back(iv, weight);
97+
adj[iv].emplace_back(iu, weight);
5598
}
56-
vertex_descriptor insert(const osmium::NodeRef &n)
99+
100+
const std::vector<size_t> &get_predecessors() { return predecessors; }
101+
const std::vector<double> &get_distances() { return distances; }
102+
103+
/**
104+
* @brief Run the Dijkstra shortest-path algorithm starting at vertex s.
105+
*
106+
* After this function completes the predecessor for each vertex will be stored in
107+
* {@code predecessors} and the distance from {@code s} to each vertex will be
108+
* stored in {@code distances}.
109+
*
110+
* @param s The index of the "start" vertex.
111+
*/
112+
void run(size_t s)
57113
{
58-
vertices_iter_t found = find(n);
59-
if (found != vertices.end() && *found == n)
60-
return std::distance(vertices.begin(), found);
61-
return std::distance(vertices.begin(), vertices.insert(found, n));
62-
};
114+
init_data();
115+
116+
IndexPriorityQueue pq(vertices.size(),
117+
[this](size_t u, size_t v) -> bool
118+
{ return distances[u] < distances[v]; });
119+
120+
distances[s] = 0;
121+
pq.insert(s);
122+
123+
while (!pq.empty())
124+
{
125+
size_t u = pq.pop();
126+
double dist_u = distances[u];
127+
for (Edge e : adj[u])
128+
{
129+
size_t v = e.other;
130+
if (dist_u + e.weight < distances[v])
131+
{
132+
distances[v] = dist_u + e.weight;
133+
predecessors[v] = u;
134+
pq.insert_or_decrease(v);
135+
}
136+
}
137+
}
138+
}
139+
140+
/**
141+
* @brief Return the number of vertices.
142+
*/
143+
size_t num_vertices() { return vertices.size(); }
63144

64-
/** The vertices, unique and sorted. */
65-
vertices_t vertices;
66145
/**
67-
* Temporary store for segments. We must have inserted all vertices before starting
68-
* on edges because edges are defined as pair of indices into the (sorted) vertices
69-
* vector.
146+
* @brief Return the number of edges.
70147
*/
71-
std::set<OsmiumSegment> poly_segments;
72-
std::set<OsmiumSegment> &vis_map;
148+
size_t num_edges()
149+
{
150+
size_t n = 0;
151+
for (auto &a : adj)
152+
{
153+
n += a.size();
154+
}
155+
return n / 2;
156+
}
73157
};
74158

75159
} // namespace osrm::extractor::area

0 commit comments

Comments
 (0)