Je vais expliquer la solution que j'ai trouvée (peut-être pas la meilleure).
Selon l'image du post, supposons que nous sommes au point A et que nous allons aller au point B . Comme je l'ai expliqué ci-dessus, ces points ne sont pas des sommets (source / cibles dans le tableau généré avec l'outil osm2po).
Pour cette raison, nous devons connaître la direction de marche / conduite. Si nous passons du sommet le plus proche au point A (point vert) par un chemin orange, nous devons soustraire le décalage entre le point A et le point vert (sommet le plus proche). Mais si nous devions traverser la rue Calle Almirante Bonifaz , alors nous devrions ajouter le décalage à la longueur de ce bord (du point vert à l'intersection entre la rue Almirante Bonifaz et la rue San Juan ).
J'exécute la requête suivante pour obtenir le chemin le plus court (vous avez besoin de l'extension pgRouting expliquée ici pgRouting - installation et exigences ici installation et exigences ):
SELECT gid, cost, st_astext(the_geom) as the_geom FROM dijkstra_sp_delta('xx_2po_4pgr', source_vertex, target_vertex, 0.1);
Il en résulte un ensemble d'arêtes qui représente l'itinéraire complet. Par exemple, une sortie possible pour cette requête peut être:
Où le champ gid ( id dans la table générée par osm2po) représente l'identifiant de bord. Eh bien, nous devons vérifier les décalages au début et à la fin (points A / B).
Si nous vérifions le décalage de départ, il faut vérifier si le premier bord de l'ensemble des arêtes obtenues dans la requête ci - dessus est le même au plus proche chemin vers le point A . S'ils correspondent, nous soustraireons l'offset. S'ils ne correspondent pas, nous ajouterons le décalage. Pour obtenir le lien le plus proche d'un point, j'exécute la requête suivante:
SELECT * FROM find_node_by_nearest_link_within_distance(point, 0.1, 'xx_2po_4pgr') as id;
Vous devez adapter cette fonction pour qu'elle renvoie le bord le plus proche. Vous devez d'abord modifier le type de point de liaison (ajouter le champ lien le plus proche ):
CREATE TYPE link_point AS
(id integer,
name character varying,
nearest_link integer);
ALTER TYPE link_point
OWNER TO postgres;
Vous devez également modifier le find_node_by_nearest_link_within_distance . Ajoutez simplement la dernière ligne (je ne montre qu'un extrait de la fonction):
-- 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;
Ensuite, vous devez savoir quelle est la distance entre le point ( point A / point B ) et l'arête la plus proche (décalage). À cet effet, je lance cette requête:
SELECT ST_Line_Locate_Point(geom , point)as offset;
Où geom est le the_geom champ dans osm2po table générée.
À ce stade, nous aurions le décalage à ajouter ou à soustraire.
Enfin, vous devrez connaître la longueur de l'arête pour appliquer la valeur obtenue dans la requête ci-dessus et ajuster le réel (si vous travaillez avec le type de géométrie, vous devrez normaliser en mètres la valeur obtenue. Il suffit de multiplier 111000 par la longueur obtenue en la requête):
select st_length(the_geom) from (select ST_ASTEXT(the_geom) as the_geom FROM dr_2po_4pgr WHERE id= edge_identifier)t";
Si nous vérifions le décalage de fin, nous devons vérifier si le dernier chemin de l'ensemble de chemins obtenu dans la requête ci-dessus est le même que le chemin le plus proche du point de fin ( point B ) et nous ajouterons / soustraireons à de la même manière que précédemment.
Excuse mon anglais.