Я собираюсь объяснить решение, которое я нашел (возможно, не лучший).
Согласно сообщению изображения, давайте предположим , что мы находимся в точке А , и мы будем идти к точке B . Как я объяснил выше, эти точки не вершины (источник / цели в таблице, сгенерированной с помощью инструмента osm2po).
В связи с этим нам нужно знать направление ходьбы / вождения. Если мы пойдем из ближайшей вершины в точку A (зеленая точка) по оранжевому пути, нам придется вычесть смещение между точкой A и зеленой точкой (ближайшая вершина). Но если нам нужно было пройти через улицу Calle Almirante Bonifaz , то мы должны добавить смещение к длине этого края (от зеленой точки до пересечения между Calle Almirante Bonifaz и Calle San Juan ).
Я запускаю следующий запрос, чтобы получить кратчайший путь (вам нужно расширение pgRouting, описанное здесь pgRouting - установка и требования здесь установка и требования ):
SELECT gid, cost, st_astext(the_geom) as the_geom FROM dijkstra_sp_delta('xx_2po_4pgr', source_vertex, target_vertex, 0.1);
Это приводит к набору ребер, которые представляют полный маршрут. Например, одним из возможных выходных данных для этого запроса может быть:
Где поле gid ( идентификатор в сгенерированной таблице osm2po) представляет идентификатор края. Что ж, мы должны проверить смещения в начале и в конце (точки A / B).
Если мы проверяем начало смещения, мы должны проверить , если первый край множества ребер , полученных в приведенном выше запрос одно и то же до ближайшего пути к точке A . Если они совпадают, мы вычтем смещение. Если они не совпадают, мы добавим смещение. Чтобы получить ближайшую ссылку на точку, я запускаю следующий запрос:
SELECT * FROM find_node_by_nearest_link_within_distance(point, 0.1, 'xx_2po_4pgr') as id;
Вы должны адаптировать эту функцию так, чтобы она возвращала ближайшее ребро. Сначала вы должны изменить тип link_point (добавить поле near_link ):
CREATE TYPE link_point AS
(id integer,
name character varying,
nearest_link integer);
ALTER TYPE link_point
OWNER TO postgres;
Вы также должны изменить find_node_by_nearest_link_within_distance . Просто добавьте последнюю строку (я только показываю выдержку из функции):
-- 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;
Затем вам нужно знать, каково расстояние между точкой ( точка A / точка B ) и ближайшим краем (смещение). Для этого я запускаю этот запрос:
SELECT ST_Line_Locate_Point(geom , point)as offset;
Где геом это the_geom поле в osm2po сгенерированной таблицы.
На этом этапе у нас будет смещение, чтобы добавить или вычесть.
Наконец, вам нужно знать длину края, чтобы применить значение, полученное в запросе выше, и откорректировать действительное (если вы работаете с типом геометрии, вам придется нормализовать полученное значение в метрах. Просто умножьте 111000 на длину, полученную в запрос):
select st_length(the_geom) from (select ST_ASTEXT(the_geom) as the_geom FROM dr_2po_4pgr WHERE id= edge_identifier)t";
Если бы мы проверили конечное смещение, то нам нужно было бы проверить, совпадает ли последний путь из набора путей, полученных в вышеупомянутом запросе, с ближайшим путем к конечной точке ( точка B ), и мы добавили бы / вычли в так же, как и раньше.
Извините за мой английский.