Voy a explicar la solución que he encontrado (quizás no sea la mejor).
Según la imagen del post, supongamos que estamos en Punto A y vamos a ir a Punto B . Como he explicado anteriormente estos puntos no son vértices (fuente / objetivos en la tabla generada con la herramienta osm2po).
Debido a esto, necesitamos saber el sentido de la marcha/conducción. Si vamos desde el vértice más cercano a Punto A (punto verde) a través del camino naranja tendríamos que restar el desplazamiento entre Punto A y el punto verde (vértice más cercano). Pero si tuviéramos que pasar por Calle Almirante Bonifaz calle, entonces debemos añadir el desplazamiento a la longitud de este borde (desde el punto verde hasta la intersección entre Calle Almirante Bonifaz y Calle San Juan ).
Ejecuto la siguiente consulta para obtener el camino más corto (se necesita la extensión pgRouting explicada aquí pgRouting - instalación y requisitos aquí instalación y requisitos ):
SELECT gid, cost, st_astext(the_geom) as the_geom FROM dijkstra_sp_delta('xx_2po_4pgr', source_vertex, target_vertex, 0.1);
El resultado es un conjunto de aristas que representa la ruta completa. Por ejemplo, una posible salida para esta consulta podría ser:
Donde el campo gid ( id en la tabla generada por osm2po) representa el identificador del borde. Pues bien, debemos comprobar los desplazamientos al inicio y al final (Puntos A/B).
Si comprobamos el desplazamiento de inicio, debemos comprobar si la primera arista del conjunto de aristas obtenidas en la consulta anterior coincide con el camino más cercano a Punto A . Si coinciden, entonces restaremos el desplazamiento. Si no coinciden, añadiremos el desplazamiento. Para obtener el enlace más cercano a un punto, ejecuto la siguiente consulta:
SELECT * FROM find_node_by_nearest_link_within_distance(point, 0.1, 'xx_2po_4pgr') as id;
Debes adaptar esta función para que devuelva la arista más cercana. En primer lugar, debe modificar la función punto_de_enlace tipo (añadir enlace_más_cercano campo):
CREATE TYPE link_point AS
(id integer,
name character varying,
nearest_link integer);
ALTER TYPE link_point
OWNER TO postgres;
También debe modificar el find_node_by_nearest_link_within_distance . Sólo hay que añadir la última línea (sólo muestro un extracto de la función):
-- 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;
Entonces hay que saber cuál es la distancia entre el punto ( Punto A/Punto B ) y la arista más cercana (offset). Para ello ejecuto esta consulta:
SELECT ST_Line_Locate_Point(geom , point)as offset;
Dónde geom es el el_geom en la tabla generada por osm2po.
En este punto, tendríamos el desplazamiento para sumar o restar.
Por último, necesitarías saber el legth de la arista para aplicar el valor obtenido en la consulta anterior y ajustar el real (si trabajas con geometría tipo, tendrás que normalizar a metros el valor obtenido. Sólo hay que multiplicar 111000 por la longitud obtenida en la consulta):
select st_length(the_geom) from (select ST_ASTEXT(the_geom) as the_geom FROM dr_2po_4pgr WHERE id= edge_identifier)t";
Si quisiéramos comprobar el desplazamiento final, tendríamos que comprobar si el último camino del conjunto de caminos obtenidos en la consulta anterior es el mismo que el camino más cercano al punto final ( Punto B ) y añadimos/abstraemos de la misma manera que antes.
Disculpe mi inglés.