Vou explicar a solução que encontrei (talvez não seja a melhor).
De acordo com a imagem post, vamos supor que estamos no ponto A e vamos ir ao Ponto B . Como expliquei acima, esses pontos não são vértices (origem / destinos na tabela gerada com a ferramenta osm2po).
Devido a isso, precisamos saber a direção a pé / direção. Se formos do vértice mais próximo ao ponto A (ponto verde) pelo caminho laranja, teremos que subtrair o deslocamento entre o ponto A e o ponto verde (vértice mais próximo). Mas se tivéssemos que atravessar a rua Calle Almirante Bonifaz , adicionaríamos o deslocamento ao comprimento dessa aresta (do ponto verde à interseção entre a rua Almirante Bonifaz e a Calle San Juan ).
Executo a seguinte consulta para obter o caminho mais curto (você precisa da extensão pgRouting explicada aqui pgRouting - instalação e requisitos aqui instalação e requisitos ):
SELECT gid, cost, st_astext(the_geom) as the_geom FROM dijkstra_sp_delta('xx_2po_4pgr', source_vertex, target_vertex, 0.1);
Isso resulta em um conjunto de arestas que representam a rota completa. Por exemplo, uma saída possível para esta consulta pode ser:
Onde o campo gid ( id na tabela gerada osm2po) representa o identificador de borda. Bem, devemos verificar as compensações no início e no final (pontos A / B).
Se verificar o início offset, é preciso verificar se a primeira borda do conjunto de arestas obtidos na consulta acima é o mesmo para o caminho mais próximo para o Ponto A . Se eles coincidirem, subtrairemos o deslocamento. Se eles não corresponderem, adicionaremos o deslocamento. Para obter o link mais próximo de um ponto, execute a seguinte consulta:
SELECT * FROM find_node_by_nearest_link_within_distance(point, 0.1, 'xx_2po_4pgr') as id;
Você deve adaptar esta função para que ela retorne a aresta mais próxima. Primeiro você deve modificar o tipo de link_point (adicione o campo mais próximo_link ):
CREATE TYPE link_point AS
(id integer,
name character varying,
nearest_link integer);
ALTER TYPE link_point
OWNER TO postgres;
Você também deve modificar o find_node_by_nearest_link_within_distance . Basta adicionar a última linha (apenas mostro um extrato da função):
-- 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;
Então você precisa saber qual é a distância entre o ponto ( ponto A / ponto B ) e a aresta mais próxima (deslocamento). Para esse fim, eu executo esta consulta:
SELECT ST_Line_Locate_Point(geom , point)as offset;
Onde geom é o the_geom campo no osm2po tabela gerada.
Nesse ponto, teríamos o deslocamento para adicionar ou subtrair.
Finalmente, você precisa conhecer a largura da aresta para aplicar o valor obtido na consulta acima e ajustar o real (se você trabalha com o tipo de geometria, terá que normalizar para metros o valor obtido. Apenas multiplique 111000 pelo comprimento obtido em A pergunta):
select st_length(the_geom) from (select ST_ASTEXT(the_geom) as the_geom FROM dr_2po_4pgr WHERE id= edge_identifier)t";
Se verificarmos o deslocamento final, teremos que verificar se o último caminho do conjunto de caminhos obtido na consulta acima é o mesmo para o caminho mais próximo ao ponto final ( ponto B ) e adicionamos / subtraímos em da mesma maneira que antes.
Desculpe meu Inglês.