Como discutimos anteriormente, pgRouting necessita de uma rede de vértices e arestas ao invés dos dados espaciais para calcular rotas. Nosso próximo passo serão utilizadas funções que estão incluídas no pgRouting para gerar a rede necessária.

Começamos abrindo o shell do PostgreSQL e, em seguida, carregando a extensão pgRouting:

psql -U postgres routing

Quando aparecer o prompt do psql, digite o seguinte comando:

CREATE EXTENSION pgrouting;

A função que iremos utilizar é a pgr_createTopology, que vai criar uma nova tabela que contém todos os pontos iniciais e finais de todas as linhas na tabela denominada ‘edges‘ (sem duplicar pontos compartilhados).

Por exemplo, se imaginarmos que estamos falando de estações de um metrô fica muito fácil, pois a função irá identificar as quatro estações marcadas com A, B, C e D.

topology1

Finalmente, a função irá adicionar as estações de origem e de destino para cada um dos segmentos, de tal modo que 1 tem origem em A e destino em B, e assim por diante.

Para o funcionamento da função pgr_createTopology, precisamos adicionar colunas de origem e de destino para a nossa tabela e depois executar o comando. Note que temos que indicar o nome da tabela (‘edges’) e a tolerância considerando dois vértices na rede.

ALTER TABLE edges ADD source INT4;
ALTER TABLE edges ADD target INT4;
SELECT pgr_createTopology('edges', 1);

Podemos agora verificar se as colunas de origem e de destino de nossa tabela foram preenchidas. Caso haja uma nova tabela denominada ‘edges_vertices_pgr‘ a qual enumera todos os vértices da rede, indica que o pgRouting detectou com sucesso.

Nós não resolvemos o problema de rede ainda, no entanto pgr_createTopology fez um bom trabalho de encontrar os vértices quando eles são divididos entre duas estações, mas e quando uma rodovia terminar no meio de uma outra rodovia?

topology2

No exemplo acima, temos novamente quatro vértices, mas não existe um caminho entre o ponto A e o ponto D sendo que o ponto C não é compartilhado entre os dois segmentos de linha.

Para lidar com estes casos, pgRouting tem uma função adicional, a pgr_nodeNetwork, que vai dividir o segmento 1 em dois novos segmentos 3 e 4, de modo que o ponto C pode servir como um “ponto de transferência” compartilhado.

topology3

A nova tabela edges_noded é criada pela função pgr_nodeNetwork e contém um atributo chamado old_id, que indica o valor do segmento originial para cada segmento derivado dele. A partir do exemplo acima, os segmentos 3 e 4 ambos tem na coluna old_id o valor 1.

SELECT pgr_nodeNetwork('edges', 1);

Nossa nova tabela edges_noded agora pode ser usada em uma chamada da função pgr_createTopology para adicionar os novos valores de origem e de destino.

SELECT pgr_createTopology('edges_noded', 1);

Porque pgr_nodeNetwork não copia todas as informações dos atributos da tabela original para a nova tabela, temos que mover as colunas name, highway (que vai mudar o nome de tipo para refletir melhor o significado), oneway e surface nós mesmos.

Primeiro adicione as novas colunas:

ALTER TABLE edges_noded
  ADD COLUMN name VARCHAR,
  ADD COLUMN type VARCHAR,
  ADD COLUMN oneway VARCHAR,
  ADD COLUMN surface VARCHAR;

Em seguida, copie os dados da tabela original. Ao copiar usaremos os nomes de um estado a outro nos casos em que o conjunto de dados não gravar um nome.

UPDATE edges_noded AS new
SET
  name = CASE WHEN old.name IS NULL THEN old.ref ELSE old.name END,
  type = old.highway,
  oneway = old.oneway,
  surface = old.surface
FROM edges AS old
WHERE new.old_id = old.id;