{"id":5607,"date":"2016-06-13T07:42:16","date_gmt":"2016-06-13T10:42:16","guid":{"rendered":"http:\/\/www.fernandoquadro.com.br\/html\/?p=5607"},"modified":"2016-08-12T15:12:45","modified_gmt":"2016-08-12T18:12:45","slug":"criando-um-aplicativo-de-rotas-com-pgrouting-parte-4","status":"publish","type":"post","link":"https:\/\/www.fernandoquadro.com.br\/html\/2016\/06\/13\/criando-um-aplicativo-de-rotas-com-pgrouting-parte-4\/","title":{"rendered":"Criando um aplicativo de rotas com pgRouting \u2013 Parte 4"},"content":{"rendered":"<p>O nosso trabalho de banco de dados foi conclu\u00eddo <a href=\"http:\/\/www.fernandoquadro.com.br\/html\/2016\/06\/10\/criando-um-aplicativo-de-rotas-com-pgrouting-parte-3\/\" target=\"_blank\">no \u00faltimo post<\/a> e agora j\u00e1 podemos publicar o nosso roteamento como camadas din\u00e2micas no GeoServer. Primeiro crie um novo workspace chamado tutorial e uma nova store PostGIS que se conecte ao banco de dados.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/stores-1024x257.png\" alt=\"stores\" width=\"676\" height=\"170\" class=\"aligncenter size-large wp-image-5611\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/stores-1024x257.png 1024w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/stores-300x75.png 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/stores-768x193.png 768w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/stores-945x237.png 945w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/stores-600x151.png 600w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/stores.png 1055w\" sizes=\"auto, (max-width: 676px) 100vw, 676px\" \/><\/p>\n<p>N\u00f3s estaremos criando duas camadas em GeoServer: <i>shortest_path<\/i>, que encontra a rota entre dois v\u00e9rtices em nossa rede de roteamento e retorna uma lista de caracter\u00edsticas que representam esse caminho; e <i>nearest_vertex<\/i>, que encontra o v\u00e9rtice mais pr\u00f3ximo de qualquer ponto do nosso conjunto de dados. Nossa aplica\u00e7\u00e3o ir\u00e1 permitir que o usu\u00e1rio selecione um ponto no mapa traduzindo-o em um v\u00e9rtice, que pode ser usado como origem ou destino na nossa camada de gera\u00e7\u00e3o de rota.<\/p>\n<p>Vamos configurar um novo modo de exibi\u00e7\u00e3o SQL chamado shortest_path com a seguinte consulta SQL:<\/p>\n<pre>SELECT\r\n&nbsp;&nbsp;min(r.seq)&nbsp;AS&nbsp;seq,\r\n&nbsp;&nbsp;e.old_id&nbsp;AS&nbsp;id,\r\n&nbsp;&nbsp;e.name,\r\n&nbsp;&nbsp;e.type,\r\n&nbsp;&nbsp;e.oneway,\r\n&nbsp;&nbsp;sum(e.time)&nbsp;AS&nbsp;time,\r\n&nbsp;&nbsp;sum(e.distance)&nbsp;AS&nbsp;distance,\r\n&nbsp;&nbsp;ST_Collect(e.the_geom)&nbsp;AS&nbsp;geom\r\nFROM\r\n&nbsp;&nbsp;pgr_dijkstra(\r\n&nbsp;&nbsp;&nbsp;'SELECT\r\n&nbsp;&nbsp;&nbsp;&nbsp;id,\r\n&nbsp;&nbsp;&nbsp;&nbsp;source::INT4,\r\n&nbsp;&nbsp;&nbsp;&nbsp;target::INT4,\r\n&nbsp;&nbsp;&nbsp;&nbsp;%cost%&nbsp;AS&nbsp;cost,\r\n&nbsp;&nbsp;&nbsp;&nbsp;CASE&nbsp;oneway\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WHEN&nbsp;''yes''&nbsp;THEN&nbsp;-1\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ELSE&nbsp;%cost%\r\n&nbsp;&nbsp;&nbsp;&nbsp;END&nbsp;AS&nbsp;reverse_cost\r\n&nbsp;&nbsp;FROM&nbsp;edges_noded',&nbsp;%source%,&nbsp;%target%,&nbsp;true,&nbsp;true)&nbsp;AS&nbsp;r,\r\n&nbsp;&nbsp;edges_noded&nbsp;AS&nbsp;e\r\nWHERE\r\n&nbsp;&nbsp;r.id2&nbsp;=&nbsp;e.id\r\nGROUP&nbsp;BY\r\n&nbsp;&nbsp;e.old_id,&nbsp;e.name,&nbsp;e.type,&nbsp;e.oneway<\/pre>\n<p>A camada tem tr\u00eas par\u00e2metros: source, target and cost. Os dois primeiros s\u00e3o o n\u00famero de identifica\u00e7\u00e3o do v\u00e9rtice e o custo a qualquer dist\u00e2ncia ou tempo, dependendo de qual m\u00e9trica utilizada para calcular a rota.<\/p>\n<p>Note-se tamb\u00e9m a fun\u00e7\u00e3o ST_Collect ir\u00e1 combinar os segmentos de linha em uma \u00fanica geometria MultiLineString.<\/p>\n<p>Por raz\u00f5es de seguran\u00e7a, quando estamos criando uma SQL View, devemos mudar a valida\u00e7\u00e3o de express\u00e3o regular dos campos source e target para que somente d\u00edgitos sejam permitidos (^ [\\ d] + $) e para o campo coast de tal forma que as palavras &#8220;time&#8221; e &#8220;distance&#8221;sejam permitidas (^ [\\ w] + $).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_params-1024x125.png\" alt=\"route_view_params\" width=\"676\" height=\"83\" class=\"aligncenter size-large wp-image-5614\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_params-1024x125.png 1024w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_params-300x37.png 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_params-768x94.png 768w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_params-945x116.png 945w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_params-600x73.png 600w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_params.png 1054w\" sizes=\"auto, (max-width: 676px) 100vw, 676px\" \/><\/p>\n<p>Por \u00faltimo, certifique-se de que especificar qual atributo ir\u00e1 identificar cada recurso na rota, o tipo de geometria (MultiLineString) e o SRID (3857).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_attributes-1024x252.png\" alt=\"route_view_attributes\" width=\"676\" height=\"166\" class=\"aligncenter size-large wp-image-5616\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_attributes-1024x252.png 1024w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_attributes-300x74.png 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_attributes-768x189.png 768w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_attributes-945x233.png 945w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_attributes-600x148.png 600w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/route_view_attributes.png 1055w\" sizes=\"auto, (max-width: 676px) 100vw, 676px\" \/><\/p>\n<p>Isto \u00e9 tudo o que precisamos configurar no GeoServer para fornecer rotas entre dois v\u00e9rtices, mas o nosso cliente precisa saber os n\u00fameros de identifica\u00e7\u00e3o dos v\u00e9rtices, por isso vamos publicar a tabela <i>edges_noded_vertices_pgr<\/i> que foi criada automaticamente. Isso nos leva a nossa segunda SQL View, que vai encontrar o v\u00e9rtice mais pr\u00f3ximo a um ponto no mapa como uma forma de selecionar o in\u00edcio ou o fim do nosso percurso.<\/p>\n<p>Usaremos <i>nearest_vertex<\/i> como nome da camada para publicar a seguinte consulta SQL:<\/p>\n<pre>SELECT\r\n&nbsp;&nbsp;v.id,\r\n&nbsp;&nbsp;v.the_geom,\r\n&nbsp;&nbsp;string_agg(distinct(e.name),',')&nbsp;AS&nbsp;name\r\nFROM\r\n&nbsp;&nbsp;edges_noded_vertices_pgr&nbsp;AS&nbsp;v,\r\n&nbsp;&nbsp;edges_noded&nbsp;AS&nbsp;e\r\nWHERE\r\n&nbsp;&nbsp;v.id&nbsp;=&nbsp;(SELECT\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FROM&nbsp;edges_noded_vertices_pgr\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ORDER&nbsp;BY&nbsp;the_geom&nbsp;<->&nbsp;ST_SetSRID(ST_MakePoint(%x%,&nbsp;%y%),&nbsp;3857)&nbsp;LIMIT&nbsp;1)\r\n&nbsp;&nbsp;AND&nbsp;(e.source&nbsp;=&nbsp;v.id&nbsp;OR&nbsp;e.target&nbsp;=&nbsp;v.id)\r\nGROUP&nbsp;BY&nbsp;v.id,&nbsp;v.the_geom<\/pre>\n<p>Devido o fato de que coordenadas podem conter n\u00fameros negativos ou positivos, certifique-se de mudar as express\u00f5es regulares de valida\u00e7\u00e3o para incluir apenas d\u00edgitos e ambos os s\u00edmbolos necess\u00e1rios: ^ [\\ d .-] + $.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/vertex_view-1024x340.png\" alt=\"vertex_view\" width=\"676\" height=\"224\" class=\"aligncenter size-large wp-image-5619\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/vertex_view-1024x340.png 1024w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/vertex_view-300x100.png 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/vertex_view-768x255.png 768w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/vertex_view-945x313.png 945w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/vertex_view-600x199.png 600w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/vertex_view.png 1028w\" sizes=\"auto, (max-width: 676px) 100vw, 676px\" \/><\/p>\n<p>A subconsulta usa um truque para encontrar rapidamente o ponto mais pr\u00f3ximo aos par\u00e2metros x e y. Al\u00e9m de retornar a geometria deste ponto, ir\u00e1 criar uma lista de todas as estradas que se encontram no v\u00e9rtice. Como exemplo, veja a imagem abaixo:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/intersection.png\" alt=\"intersection\" width=\"620\" height=\"276\" class=\"aligncenter size-full wp-image-5621\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/intersection.png 620w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/intersection-300x134.png 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/intersection-600x267.png 600w\" sizes=\"auto, (max-width: 620px) 100vw, 620px\" \/><\/p>\n<p>Finalmente, se publicamos as tabelas <i>edges_noded_vertices_pgr<\/i> e <i>edges_noded<\/i>, podemos visualizar nossa rede de roteamento no GeoServer. Isso n\u00e3o \u00e9 necess\u00e1rio para a nossa aplica\u00e7\u00e3o, mas ajuda a visualizar os dados que se est\u00e1 trabalhando.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/network.png\" alt=\"network\" width=\"750\" height=\"400\" class=\"aligncenter size-full wp-image-5622\" srcset=\"https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/network.png 750w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/network-300x160.png 300w, https:\/\/www.fernandoquadro.com.br\/html\/wp-content\/uploads\/2016\/06\/network-600x320.png 600w\" sizes=\"auto, (max-width: 750px) 100vw, 750px\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>O nosso trabalho de banco de dados foi conclu\u00eddo no \u00faltimo post e agora j\u00e1 podemos publicar o nosso roteamento como camadas din\u00e2micas no GeoServer. Primeiro crie um novo workspace chamado tutorial e uma nova store PostGIS que se conecte&#8230; <a class=\"more-link\" href=\"https:\/\/www.fernandoquadro.com.br\/html\/2016\/06\/13\/criando-um-aplicativo-de-rotas-com-pgrouting-parte-4\/\">Continue Reading &rarr;<\/a><\/p>\n","protected":false},"author":275,"featured_media":5610,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,24,132,11],"tags":[208,223,250,266,212],"class_list":["post-5607","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-geoserver","category-gis","category-openlayers","category-postgis","tag-geoserver","tag-gis","tag-openlayers","tag-pgrouting","tag-postgis"],"_links":{"self":[{"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/posts\/5607","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/users\/275"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/comments?post=5607"}],"version-history":[{"count":9,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/posts\/5607\/revisions"}],"predecessor-version":[{"id":6212,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/posts\/5607\/revisions\/6212"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/media\/5610"}],"wp:attachment":[{"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/media?parent=5607"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/categories?post=5607"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fernandoquadro.com.br\/html\/wp-json\/wp\/v2\/tags?post=5607"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}