Spiegherò la soluzione che ho trovato (forse non essere il migliore).
Secondo l'immagine appena catturata, supponiamo che siamo in punto A e faremo andare a Point B . Come ho spiegato sopra, questi punti non sono vertici (sorgente / target nella tabella generata con lo strumento osm2po).
Per questo motivo, dobbiamo conoscere la direzione di marcia / guida. Se passiamo dal vertice più vicino al punto A (punto verde) attraverso il percorso arancione dovremmo sottrarre l'offset tra il punto A e il punto verde (vertice più vicino). Ma se dovessimo attraversare Calle Almirante Bonifaz , dovremmo aggiungere l'offset alla lunghezza di questo bordo (dal punto verde all'intersezione tra Calle Almirante Bonifaz e Calle San Juan ).
Eseguo la seguente query per ottenere il percorso più breve (è necessaria l'estensione pgRouting spiegata qui pgRouting - installazione e requisiti qui installazione e requisiti ):
SELECT gid, cost, st_astext(the_geom) as the_geom FROM dijkstra_sp_delta('xx_2po_4pgr', source_vertex, target_vertex, 0.1);
Ciò si traduce in un insieme di spigoli che rappresenta il percorso completo. Ad esempio, un possibile output per questa query potrebbe essere:
Dove il campo gid ( id nella tabella generata osm2po) rappresenta l'identificatore del bordo. Bene, dobbiamo controllare gli offset all'inizio e alla fine (punti A / B).
Se controlliamo compensato dall'inizio, dobbiamo controllare se il primo bordo del set di spigoli ottenuti nella query precedente è uguale al percorso più vicino al punto A . Se corrispondono, sottrarremo l'offset. Se non corrispondono, aggiungeremo l'offset. Per ottenere il collegamento più vicino a un punto, eseguo la seguente query:
SELECT * FROM find_node_by_nearest_link_within_distance(point, 0.1, 'xx_2po_4pgr') as id;
È necessario adattare questa funzione in modo che restituisca il bordo più vicino. In primo luogo è necessario modificare il link_point tipo (aggiungere nearest_link campo):
CREATE TYPE link_point AS
(id integer,
name character varying,
nearest_link integer);
ALTER TYPE link_point
OWNER TO postgres;
È inoltre necessario modificare find_node_by_nearest_link_within_distance . Basta aggiungere l'ultima riga (mostro solo un estratto della funzione):
-- Searching for a nearest link
FOR row in EXECUTE 'select id from find_nearest_link_within_distance('''||point||''', '||distance||', '''||tbl||''') as id'
LOOP
END LOOP;
IF row.id is null THEN
res.id = -1;
RETURN res;
END IF;
link:=row.id;
res.nearest_link:=link;
Quindi è necessario sapere qual è la distanza tra il punto ( Punto A / Punto B ) e il bordo più vicino (offset). A tale scopo eseguo questa query:
SELECT ST_Line_Locate_Point(geom , point)as offset;
Dove geom è il the_geom campo in osm2po tabella generata.
A questo punto, avremmo l'offset da aggiungere o sottrarre.
Infine, dovresti conoscere la legenda del bordo per applicare il valore ottenuto nella query sopra e regolare il reale (se lavori con il tipo di geometria, dovrai normalizzare a metri il valore ottenuto. Basta moltiplicare 111000 per la lunghezza ottenuta in la query):
select st_length(the_geom) from (select ST_ASTEXT(the_geom) as the_geom FROM dr_2po_4pgr WHERE id= edge_identifier)t";
Se dovessimo controllare l'offset finale, dovremmo verificare se l'ultimo percorso dell'insieme di percorsi ottenuto nella query sopra è lo stesso del percorso più vicino al punto finale ( Punto B ) e aggiungeremmo / sottrai a allo stesso modo di prima.
Scusa il mio inglese.