pgRouting with Shooting-Star algorithm
Shooting-Star algorithm is the latest of pgRouting shortest path algorithms. Its speciality is that it routes from link to link, not from vertex to vertex as Dijkstra and A-Star algorithms do. This makes it possible to define relations between links for example, and it solves some other vertex-based algorithm issues like "parallel links", which have same source and target but different costs.
Prepare routing table for Shooting-Star
For Shooting-Star you need to prepare your network table and add the "reverse_cost" and "to_cost" column. Like A-Star this algorithm also has a heuristic function, which prefers links closer to the target of the search.
ALTER TABLE ways ADD COLUMN reverse_cost double precision; UPDATE ways SET reverse_cost = length;
ALTER TABLE ways ADD COLUMN to_cost double precision; ALTER TABLE ways ADD COLUMN rule text;
Shortest Path Shooting-Star core function
Shooting-Star algorithm introduces two new attributes:
- rule: a string with a comma separated list of edge IDs, which describes a rule for turning restriction (if you came along these edges, you can pass through the current one only with the cost stated in to_cost column)
- to_cost: a cost of a restricted passage (can be very high in a case of turn restriction or comparable with an edge cost in a case of traffic light)
shortest_path_shooting_star( sql text, source_id integer, target_id integer, directed boolean, has_reverse_cost boolean )
Note:
- Source and target IDs are link IDs.
- Undirected graphs ("directed false") ignores "has_reverse_cost" setting
Example for Shooting-Star "rule"
Shooting* algorithm calculates a path from edge to edge (not from vertex to vertex). Column vertex_id contains start vertex of an edge from column edge_id.
To describe turn restrictions:
gid | source | target | cost | x1 | y1 | x2 | y2 | to_cost | rule -----+--------+--------+------+----+----+----+----+---------+------ 12 | 3 | 10 | 2 | 4 | 3 | 4 | 5 | 1000 | 14
means that the cost of going from edge 14 to edge 12 is 1000, and
gid | source | target | cost | x1 | y1 | x2 | y2 | to_cost | rule -----+--------+--------+------+----+----+----+----+---------+------ 12 | 3 | 10 | 2 | 4 | 3 | 4 | 5 | 1000 | 14, 4
means that the cost of going from edge 14 to edge 12 through edge 4 is 1000.
If you need multiple restrictions for a given edge then you have to add multiple records for that edge each with a separate restriction.
gid | source | target | cost | x1 | y1 | x2 | y2 | to_cost | rule -----+--------+--------+------+----+----+----+----+---------+------ 11 | 3 | 10 | 2 | 4 | 3 | 4 | 5 | 1000 | 4 11 | 3 | 10 | 2 | 4 | 3 | 4 | 5 | 1000 | 12
means that the cost of going from either edge 4 or 12 to edge 11 is 1000. And then you always need to order your data by gid when you load it to a shortest path function..
Example of Shooting-Star core function
SELECT * FROM shortest_path_shooting_star(' SELECT gid as id, source::integer, target::integer, length::double precision as cost, x1, y1, x2, y2, rule, to_cost FROM ways', 293, 761, false, false);
vertex_id | edge_id | cost -----------+---------+--------------------- 4232 | 293 | 0.0059596293824534 3144 | 293 | 0.0059596293824534 4232 | 4632 | 0.0846731039249787 ... | ... | ... 51 | 761 | 0.0305298478239596 (63 rows)
Wrapper function WITH bounding box
Wrapper functions extend the core functions with transformations, bounding box limitations, etc..
SELECT gid, AsText(the_geom) AS the_geom FROM shootingstar_sp('ways', 293, 761, 0.1, 'length', true, true);
gid | the_geom --------+--------------------------------------------------------------- 293 | MULTILINESTRING((18.4074149 -33.9443308,18.4074019 -33.9443833)) 293 | MULTILINESTRING((18.4074149 -33.9443308,18.4074019 -33.9443833)) 4632 | MULTILINESTRING((18.4074149 -33.9443308,18.4077388 -33.9436183)) ... | ... 762 | MULTILINESTRING((18.4241422 -33.9179275,18.4237423 -33.9182966)) 761 | MULTILINESTRING((18.4243523 -33.9177154,18.4241422 -33.9179275)) (62 rows)
Note:
- There is currently no wrapper function for A-Star without bounding box, since bounding boxes are very useful to increase performance. If you don't need a bounding box Dijkstra will be enough anyway.
- The projection of OSM data is "degree", so we set a bounding box containing start and end vertex plus a 0.1 degree buffer for example.