[pgrouting-users] driving directions

Hi All,

Does any one can provide sample functions or any kind of help on driving directions? I am trying to figure out how to do that but any help would be very helpful.

Thank you,

Emre

On 1/23/2011 9:22 AM, Emre Koc wrote:

Hi All,

Does any one can provide sample functions or any kind of help on driving
directions? I am trying to figure out how to do that but any help would
be very helpful.

Thank you,

Emre

Here is the thread where I described it before:
http://www.google.com/#hl=en&num=100&newwindow=1&q=site%3Ahttp%3A%2F%2Flists.postlbs.org%2Fpipermail%2Fpgrouting-users%2F+swoodbridge+"directions+problem"&aq=f&aqi=&oq=&fp=2755c6b3e9b2e9

Also look at the GSoC project at:
http://sourceforge.net/apps/trac/opengraphrouter/wiki
http://imaptools.com:8080/maps/gsoc2009/?zoom=4&lat=53.56076&lon=-122.60619&layers=BTTT&start=-131.686064%2058.79915&stop=-114.055306%2049.024077&method=GetDD&lang=eng

This has an initial implementation is C++ but it is not well documented
yet and needs a lot of additional work.

-Steve

Looks like the list moved so this might work better:
http://www.google.com/#hl=en&newwindow=1&safe=off&&sa=X&ei=G2k8TeniA4Kr8Aapg5ylCg&ved=0CBIQBSgA&q=site%3Ahttp%3A//lists.postlbs.org/pipermail/pgrouting-users/+woodbridge+"directions+problem"&spell=1&fp=241062ed1d424d73

Hi Emre, hi list

I faced the Driving Direction issue and I wrote a pl/pgsql function.

It is only an example and it is not optimized. There are some comments in italian language (I’m sorry … I didn’t have the time to translate them).

It assume the name of the street table as “ways”, use the SPS algorithm and returns a xml containing the Driving Directions and the geometry of the route.

If you want to see it in action you can visit the demo at http://routing.geosdi.org (also mentioned in the pgRouting Gallery - thanks to Daniel)

Some information about the algorithm:

the routing query returns the geometries of the edges composing the shortest path, but they are not oriented. So the first things to do is to analyze every couple ov edge and flip the segments if necessary, so that the final point of the n_th segment coincides with the start point of the n+1_th segment.
than, using the azimuth, evaluate the angle between two consecutive segments to define the maneuver to suggest.

This is far to be used in a production environment, but it could be an example to start (I could not find any example when I started to face the DD issue !!)

Hope this help.

Daniel … we could post it into the contribution with git after I optimize it … How to do this?

Here is the not-optimized function.

– Function: xml_directions(integer, integer, text)

– DROP FUNCTION xml_directions(integer, integer, text);

CREATE OR REPLACE FUNCTION xml_directions(source_id integer, target_id integer, tab_name text)
RETURNS xml AS
$BODY$DECLARE

start_point geometry; --geometria del punto iniziale
tab_name text :=$3; – nome della tabella (ways)
s_id integer :=$1; – source id
t_id integer :=$2; – target id
_first boolean :=true; --è il primo step dell’algoritmo
fc real:= 111073.2835905824; – fattore conversione moltiplicativo per le distanze
_A geometry;
_B geometry;
_C geometry;
_D geometry;
a1 float; – azimuth fine prima geometria
a2 float; – azimuth inizio seconda geometria
angoli real; – array degli angoli (differenza) da restituire
i integer; – intero per scorrere l’array - NB è definito fuori dal loop perchè serve anche per ottenere la lunghezza degli array

the_route CURSOR FOR SELECT rt.gid, rt.the_geom, length(rt.the_geom), ways.name FROM ways, (SELECT gid, the_geom FROM shootingstar_sp(tab_name, s_id, t_id, 0.1, ‘cost’, true, true)) AS rt WHERE ways.gid=rt.gid;
–variabili per il fetch
GID_1 integer;
GID_2 integer;
GEOM_1 geometry;
GEOM_2 geometry;
LENGTH_1 real;
LENGTH_2 real;
NAME_1 text;
NAME_2 text;

directions text; --vettore contenente i codici relaivi alle manovre
lengths real; --vettore contenente le lunghezze dei tratti da percorrere
streets text; --vettore contenente i nomi dele strade della rotta
geoms geometry; --vettore delle singole geometrie
line geometry; --geometria complessiva della rotta
tot_len real :=0;
tot_time real:=0;
tlu text := ‘m’; – total length units

– var per l’execute della query per la composizione dell’xml
pre_string text;

steps_fragment text:=‘XMLELEMENT(NAME step,XMLELEMENT(NAME text,’'Start from ';
line_fragment text;

xml_result xml;

BEGIN

angoli[0] :=0; – la prima indicazione è sempre “procedi su via …” . Il riempimento del vettore angoli deve partire da angoli[1]
i:=0;
OPEN the_route;
FETCH the_route INTO GID_1, GEOM_1, LENGTH_1, NAME_1;

IF NAME_1 IS NOT NULL THEN
streets[0]:= replace(trim(both from NAME_1),‘’‘’,‘’‘’‘’);
ELSE streets[0]:=‘Missing Street Name’;
END IF;

lengths[0]:= LENGTH_1*fc;
–tot_len := tot_len + lengths[0];
line:=ST_Union(GEOM_1);
RAISE NOTICE ’ STREET [0] = %‘,streets[0];
RAISE NOTICE ’ LENGTHS [0] = %’,lengths[0];
LOOP
FETCH the_route INTO GID_2, GEOM_2, LENGTH_2, NAME_2;
EXIT WHEN NOT FOUND;

– caso primo segmento

IF _first THEN
– devo capire chi è il punto iniziale
_A :=ST_PointN(GEOM_1,1);
_B :=ST_PointN(GEOM_1,ST_NumPoints(GEOM_1));
_C :=ST_PointN(GEOM_2,1);
_D :=ST_PointN(GEOM_2,ST_NumPoints(GEOM_2));
IF (ST_Equals(_A, _C)) THEN
start_point := _B;

ELSIF (ST_Equals(_A, _D)) THEN
start_point := _B;

ELSE
start_point := _A;

END IF;

–valuto quale endpoint della prima geometria è connessa allo startpoint e se necessario flippo la geometria
IF NOT(ST_Equals(start_point,ST_PointN(GEOM_1,1))) THEN – lo start point non coincide con il primo punto del primo segmento, quindi il segmento va flippato
GEOM_1 := ST_Reverse(GEOM_1);

END IF;
geoms[i]:= GEOM_1;

start_point:= ST_PointN(Geom_1,ST_NumPoints(GEOM_1)); --aggiorno lo start point come l’ultimo punto della prima geometria

–valuto quale endpoint della seconda geometria è connessa all’ultimo punto della prima geometria (che è già stata correttamente orientata) e se necessario flippo la seconda geometria
IF NOT(ST_Equals(start_point, ST_PointN(GEOM_2,1))) THEN
GEOM_2 := ST_Reverse(GEOM_2);

END IF;
start_point:= ST_PointN(Geom_2,ST_NumPoints(GEOM_2)); – aggiorno lo start point per lo step successivo del loop

– i segmenti sono orientati; calcolo gli azimuth e definisco la direzione
a1 := trunc(ST_Azimuth(ST_PointN(GEOM_1,ST_NumPoints(GEOM_1)-1),ST_PointN(GEOM_1,ST_NumPoints(GEOM_1)))/(2*pi())*360);

a2 := trunc(ST_Azimuth(ST_PointN(GEOM_2,1),ST_PointN(GEOM_2,2))/(2*pi())*360);

– la differenza di questi angoli definisce la manovra da effettuare, quindi VA RITORNATA IN QUALCHE MODO
angoli[i+1] := (a1 - a2);
IF (angoli[i+1] >180.0) THEN angoli[i+1]:=angoli[i+1]-360;
END IF;
IF (angoli[i+1]< -180) THEN angoli[i+1]:=angoli[i+1]+360;
END IF;
IF NAME_2 IS NOT NULL THEN
streets[i+1]:= replace(trim(both from NAME_2),‘’‘’,‘’‘’‘’);
ELSE
streets[i+1]:=‘nome strada mancante’;
END IF;

– Se le strade hanno lo stesso nome

IF ((streets[i+1] =streets[i])) THEN

geoms[i]:=ST_Union(geoms[i],GEOM_2);
lengths[i]:=lengths[i]+(LENGTH_2 * fc);
line:=ST_Union(line,GEOM_2);
GEOM_1 := GEOM_2;
NAME_1 := NAME_2;

ELSE
lengths[i+1]:= LENGTH_2 * fc;

geoms[i+1]:= GEOM_2;
line:=ST_Union(line,GEOM_2);

i:= i+1;

GID_1 := GID_2;
GEOM_1 := GEOM_2;
LENGTH_1 := LENGTH_2 * fc;
NAME_1 := NAME_2;
END IF;

_first := false;

– caso segmenti successivi al primo (la prima geometria è già orientata)
ELSE
IF NOT(ST_Equals(start_point, ST_PointN(GEOM_2,1))) THEN
GEOM_2 := ST_Reverse(GEOM_2);

END IF;
start_point:= ST_PointN(Geom_2,ST_NumPoints(GEOM_2)); – aggiorno lo start point per lo step successivo del loop

– i segmenti sono orientati; calcolo gli azimuth e definisco la direzione
a1 := trunc(ST_Azimuth(ST_PointN(GEOM_1,ST_NumPoints(GEOM_1)-1),ST_PointN(GEOM_1,ST_NumPoints(GEOM_1)))/(2*pi())*360);

a2 := trunc(ST_Azimuth(ST_PointN(GEOM_2,1),ST_PointN(GEOM_2,2))/(2*pi())*360);

– la differenza di questi angoli definisce la manovra da effettuare, quindi VA RITORNATA IN QUALCHE MODO

angoli[i+1] := (a1 - a2);
IF (angoli[i+1] >180) THEN angoli[i+1]:=angoli[i+1]-360;
END IF;
IF (angoli[i+1]< -180) THEN angoli[i+1]:=angoli[i+1]+360;
END IF;

IF NAME_2 IS NOT NULL THEN
streets[i+1]:= replace(trim(both from NAME_2),‘’‘’,‘’‘’‘’);
ELSE
streets[i+1]:=‘nome strada mancante’;
END IF;

– Se le strade hanno lo stesso nome
IF ( (streets[i+1] =streets[i])) THEN

geoms[i]:=ST_Union(geoms[i],GEOM_2);
lengths[i]:=lengths[i]+(LENGTH_2 * fc);
line:=ST_Union(line,GEOM_2);
GEOM_1 := GEOM_2;
NAME_1 := NAME_2;

ELSE

lengths[i+1]:= LENGTH_2 * fc;
–tot_len := tot_len + lengths[i+1];
geoms[i+1]:=GEOM_2;

line:=ST_Union(line,GEOM_2);

i:= i+1;
–GID_1 := GID_2;
GEOM_1 := GEOM_2;
–LENGTH_1 := LENGTH_2 * fc;
NAME_1 := NAME_2;
END IF;

END IF;

END LOOP;

CLOSE the_route;

–codifico gli angoli in manovre
for k in 0…i LOOP
CASE
WHEN angoli[k]>=-5 AND angoli[k]<=5 THEN
directions[k]:=‘Go straight along’;
–RAISE NOTICE’RAMO 1 %‘,directions[k];
WHEN angoli[k]>=-45 AND angoli[k]<-5 THEN
directions[k]:=‘Slight right onto’;
–RAISE NOTICE’RAMO 2 %’,directions[k];
WHEN angoli[k]>=-100 AND angoli[k]<-45 THEN
directions[k]:=‘Turn right onto’;
–RAISE NOTICE’RAMO 3 %‘,directions[k];
WHEN angoli[k]>=-135 AND angoli[k]<-100 THEN
directions[k]:=‘bend to the right on’;
–RAISE NOTICE’RAMO 4 %’,directions[k];
WHEN angoli[k]>=-180 AND angoli[k]<-135 THEN
directions[k]:=‘U-turn right onto’;
–RAISE NOTICE’RAMO 5 %‘,directions[k];
WHEN angoli[k]>5 AND angoli[k]<=45 THEN
directions[k]:=‘Slight left onto’;
–RAISE NOTICE’RAMO 6 %’,directions[k];
WHEN angoli[k]>45 AND angoli[k]<=100 THEN
directions[k]:=‘Turn left onto’;
–RAISE NOTICE’RAMO 7 %‘,directions[k];
WHEN angoli[k]>100 AND angoli[k]<=135 THEN
directions[k]:=‘bend to the left on’;
–RAISE NOTICE’RAMO 8 %’,directions[k];
WHEN angoli[k]>135 AND angoli[k]<=180 THEN
directions[k]:=‘U-turn left onto’;
–RAISE NOTICE’RAMO 9 %‘,directions[k];
ELSE RAISE NOTICE’ ELSE%',directions[k];
END CASE;
tot_len := tot_len + lengths[k];
END LOOP;
tot_len := trunc(tot_len);
tot_time := trunc(tot_len/833.33333); – si assume velocità media di 50 km/h

IF (tot_len >= 1000) THEN
tot_len := tot_len/1000; --mostro la len in km
tlu := ‘km’;
END IF;
pre_string:=‘XMLROOT(XMLELEMENT(NAME result, XMLELEMENT(NAME route, XMLELEMENT(NAME total_length, ‘‘circa ‘||tot_len||’ ‘||tlu||’’’), XMLELEMENT( NAME total_estimated_time, ‘‘about ‘||tot_time||’ min’’), XMLELEMENT(NAME directions,’;
steps_fragment := steps_fragment||streets[0]||‘’‘))’;
for j in 0…i LOOP
–RAISE NOTICE’geometria ------- %/‘,ST_AsText(geoms[j]);
steps_fragment := steps_fragment||’,XMLELEMENT(NAME step,XMLELEMENT(NAME text,‘||’‘’‘||directions[j]||’ ‘||streets[j]||’ (about ‘||trunc(lengths[j])||’ m)‘||’‘’‘||’),XMLELEMENT(NAME line,‘’‘||ST_AsText(geoms[j])||’‘’))';
END LOOP;

line_fragment:=‘),XMLELEMENT(NAME complete_line,’‘’||ST_AsText(line)||‘’‘))),VERSION 1.0,STANDALONE YES)’;
–RAISE NOTICE’geometria -----------------------\n --------------------------------------- \n\n %\n\n----------------------------------------',ST_AsText(line);

EXECUTE 'SELECT '||pre_string||steps_fragment||line_fragment INTO xml_result;

RETURN xml_result;

END;

$BODY$
LANGUAGE ‘plpgsql’ VOLATILE
COST 100;
ALTER FUNCTION xml_directions(integer, integer, text) OWNER TO postgres;

2011/1/23 Stephen Woodbridge <woodbri@swoodbridge.com>

On 1/23/2011 9:22 AM, Emre Koc wrote:

Hi All,

Does any one can provide sample functions or any kind of help on driving
directions? I am trying to figure out how to do that but any help would
be very helpful.

Thank you,

Emre

Here is the thread where I described it before:
http://www.google.com/#hl=en&num=100&newwindow=1&q=site%3Ahttp%3A%2F%2Flists.postlbs.org%2Fpipermail%2Fpgrouting-users%2F+swoodbridge+%22directions+problem%22&aq=f&aqi=&oq=&fp=2755c6b3e9b2e9

Also look at the GSoC project at:
http://sourceforge.net/apps/trac/opengraphrouter/wiki
http://imaptools.com:8080/maps/gsoc2009/?zoom=4&lat=53.56076&lon=-122.60619&layers=BTTT&start=-131.686064%2058.79915&stop=-114.055306%2049.024077&method=GetDD&lang=eng

This has an initial implementation is C++ but it is not well documented
yet and needs a lot of additional work.

-Steve

Looks like the list moved so this might work better:
http://www.google.com/#hl=en&newwindow=1&safe=off&&sa=X&ei=G2k8TeniA4Kr8Aapg5ylCg&ved=0CBIQBSgA&q=site%3Ahttp%3A//lists.postlbs.org/pipermail/pgrouting-users/+woodbridge+%22directions+problem%22&spell=1&fp=241062ed1d424d73


Pgrouting-users mailing list
Pgrouting-users@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/pgrouting-users


Lorenzo Amato
lorenzo.amato@geosdi.org
lorenzotlc@gmail.com
lorenzo.amato@nsdi.it

Consiglio Nazionale delle Ricerche
Istituto di Metodologie per l’Analisi Ambientale - geoSDI

Hi Lorenzo,

Thank you!
We have https://github.com/pgRouting/pgrouting-contrib for this
purpose. I think Daniel will give you detailed instructions a bit
later.

Anton.

Easy way for howto’s:
Just create a page in the GitHub Wiki (for example for a small tutorial) and I will add it to the website.
https://github.com/pgrouting/pgrouting/wiki

For code examples like wrapper functions you can use the pgrouting-contrib repository (pretty empty right now).
If you tell me your Gihub account name, then I can give you commit right. Or you make a fork of the repository and notify me then to pull your changes into the repository.

If you have questions, feel free to ask.

Daniel

2011/1/26 Anton Patrushev <anton.patrushev@georepublic.de>

Hi Lorenzo,

Thank you!
We have https://github.com/pgRouting/pgrouting-contrib for this
purpose. I think Daniel will give you detailed instructions a bit
later.

Anton.


Pgrouting-users mailing list
Pgrouting-users@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/pgrouting-users


Georepublic UG & Georepublic Japan
eMail: daniel.kastl@georepublic.de
Web: http://georepublic.de

Hi Daniel

mi github username is lorenzo-amato

About the wiki … I’ll write it asap!

thanks

2011/1/26 Daniel Kastl <daniel@georepublic.de>

Easy way for howto’s:
Just create a page in the GitHub Wiki (for example for a small tutorial) and I will add it to the website.
https://github.com/pgrouting/pgrouting/wiki

For code examples like wrapper functions you can use the pgrouting-contrib repository (pretty empty right now).
If you tell me your Gihub account name, then I can give you commit right. Or you make a fork of the repository and notify me then to pull your changes into the repository.

If you have questions, feel free to ask.

Daniel

2011/1/26 Anton Patrushev <anton.patrushev@georepublic.de>

Hi Lorenzo,

Thank you!
We have https://github.com/pgRouting/pgrouting-contrib for this
purpose. I think Daniel will give you detailed instructions a bit
later.

Anton.


Pgrouting-users mailing list
Pgrouting-users@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/pgrouting-users


Georepublic UG & Georepublic Japan
eMail: daniel.kastl@georepublic.de
Web: http://georepublic.de


Pgrouting-users mailing list
Pgrouting-users@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/pgrouting-users


Lorenzo Amato
lorenzo.amato@geosdi.org
lorenzotlc@gmail.com
lorenzo.amato@nsdi.it

Consiglio Nazionale delle Ricerche
Istituto di Metodologie per l’Analisi Ambientale - geoSDI

Thank you!
I added you to the contrib repository:
https://github.com/pgRouting/pgrouting-contrib

Feel free to create folders as you like, if you have a good idea for a good folder structure. We can reorganize it later if necessary.

Daniel

2011/1/26 lorenzo amato <lorenzo.amato@geosdi.org>

lorenzo-amato


Georepublic UG & Georepublic Japan
eMail: daniel.kastl@georepublic.de
Web: http://georepublic.de