Я збираюся пояснити знайдене рішення (можливо, не найкраще).
Згідно з повідомленням зображення, давайте припустимо , що ми знаходимося в точці А , і ми будемо йти до точці B . Як я пояснював вище, ці точки не є вершиною (джерело / цілі в таблиці, згенеровані інструментом osm2po).
Завдяки цьому нам потрібно знати напрям ходьби / руху. Якщо ми переходимо від найближчої вершини до точки A (крапка зелена) через помаранчевий шлях, нам слід було б підсунути зміщення між точкою A і точкою зеленою (найближча вершина). Але якби нам довелося пройти вулицю Калле Алміранте Боніфаз , то нам слід додати зміщення до довжини цього краю (від точки зеленого до перетину між Калле Алміранте Боніфаз та Калле Сан Хуан ).
Я запускаю наступний запит, щоб отримати найкоротший шлях (потрібне розширення 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 ( id у osm2po створеній таблиці) являє собою ідентифікатор краю. Ну, ми повинні перевірити компенсації на початку та в кінці (бали A / B).
Якщо ми перевіряємо початок зсуву, ми повинні перевірити , якщо перший край безлічі ребер , отриманих в наведеному вище запит одне і те ж до найближчого шляху до точці A . Якщо вони збігаються, ми підсумовуємо компенсацію. Якщо вони не збігаються, ми додамо компенсацію. Щоб отримати дещо найближче посилання до точки, я запускаю такий запит:
SELECT * FROM find_node_by_nearest_link_within_distance(point, 0.1, 'xx_2po_4pgr') as id;
Ви повинні адаптувати цю функцію, щоб вона повернула найближчий край. Спершу потрібно змінити тип link_point (додати поле najbli_link ):
CREATE TYPE link_point AS
(id integer,
name character varying,
nearest_link integer);
ALTER TYPE link_point
OWNER TO postgres;
Ви також повинні змінити find_node_by_nerely_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;
Тоді вам потрібно знати, яка відстань між точкою ( точка А / точка В ) та найближчим краєм (зміщення). Для цього я запускаю цей запит:
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";
Якщо ми перевіримо кінцеве зміщення, то нам доведеться перевірити, чи останній шлях з безлічі шляхів, отриманих у вищезазначеному запиті, такий самий, як найближчий шлях до кінцевої точки ( точка В ), і ми додали б / підсумки так само, як і раніше.
Вибачте мою англійську.