Como desenvolvedor, faz parte da minha rotina acessar banco de dados, consultar tabelas e manipular dados em colunas que possuem tipos numérico, date, float, strings e suas variações. Agora, como isso funciona quando tratamos dados geográficos ?
Quando falamos de um sistema que manipula dados geográficos (ou dados geoespaciais), estamos falando de um SIG (Sistema de Informação Geográfica).
SIGs precisam manter e manipular dados geográficos que envolvem representações bastante complexas. Normalmente não precisam apenas armazenar, precisam também manipular, como por exemplo, saber se um determinado ponto entrou dentro de um perímetro (geofence). Este é o foco do nosso artigo que começa agora
Porque o POSTGIS ?
Existe uma organização voluntária chamada OGS – Open Geospatial Consortium que é responsável por definir os padrões para construção de serviços e ferramentas para tratamento de dados geoespaciais. Um desses padrões é o SFSQL que define os padrões que devem ser seguidos por bancos de dados que queiram implementar suporte a dados geoespaciais.
O PostGIS é uma extensão do banco de dados postgreSQL criada para manipular dados geoespaciais e que segue esse padrão da OGS. Claro que outros bancos também possuem implementações geoespaciais, mas a opção pelo PostGIS é pelo fato de ser gratuito, simples de instalar e ser um banco bastante robusto com enorme aceitação no mercado e cases de sucesso.
Caso queira buscar informações sobre implementações em outros bancos tradicionais, pode dar uma olhada no Locator e Spatial do Oracle e o Spatial Extender do IBM DB2.
Instalando o PostGIS
O PostGIS é uma extensão do postgreSQL, para instala-lo é necessário ter o postgreSQL instalado. Para esse artigo usei a versão 10, mas vocês podem utilizar uma versão mais recente se for o caso.
Para instalar o postgreSQL acesse a pagina de download oficial. O uso do postgreSQL é gratuito.
Após instalar o postgreSQL, acesse a pasta bin e nela você vai encontrar o executável stackbuilder (Para instalações no MAC ou Linux o procedimento pode ser diferente).
Após executar o stackbuilder vai ser apresentada uma interface para você selecionar a instalação do postgreSQL.
Após selecionar a versão, vai ser apresentada uma interface para você selecionar os complementos que deseja instalar. Aqui selecione a versão mais recente do PostGIS na pasta Spatial Extensions.
feito isso basta seguir com a instalação passo a passo. Com a atenção para os itens abaixo
Não é necessário marcar a opção Create Spatial Database. O PostGIS é uma extensão e pode ser habilitada para qualquer banco do postgreSQL que você tenha.
Podem surgir algumas perguntas para adicionar variáveis de ambiente e habilitar algumas opções, marque sempre a opção default, como na pergunta acima.
Ao finalizar a instalação, basta executar o comando abaixo no banco de dados para habilitara extensão:
CREATE EXTENSION postgis;
CENÁRIO PARA ANALISE
Agora que já temos o nosso banco de dados preparado para manipular dados geoespaciais, vamos começar!
Vamos imaginar inicialmente um cenário.
Nós trabalhamos numa empresa que acabou de criar um aplicativo chamando Family Tracker, nesse app você consegue conectar um grupo de pessoas e acompanhar onde cada membro do grupo está fisicamente.
Para o aplicativo funcionar, a cada 30 segundos é feito um acesso ao GPS do celular para fazer a leitura da posição do usuário. Esses dados, que consistem em latitude e longitude, são enviados ao nosso sistema através de um serviço REST.
Cada localização de usuário recebida pelo nosso sistema nós vamos chamar de PING daqui pra frente.
Manipulando dados com PostGIS
Vamos criar agora uma tabela para armazenar os pings recebidos pelo sistema. A tabela deve ter os dados latitude e longitude do tipo double e um campo chamado geo do tipo geometry.
O dado do tipo geometry é um dado especifico do PostGIS que representa dados em formato geométricos. Um dado geométrico pode ser um ponto, uma linha ou um polígono por exemplo.
1 2 3 4 5 6 7 8 | CREATE TABLE public.ping_geo ( id BIGINT NOT NULL, loun_dt_location TIMESTAMP WITHOUT TIME zone NOT NULL, latitude DOUBLE PRECISION, longitude DOUBLE PRECISION, ping geometry, CONSTRAINT pk_ping_geo PRIMARY KEY (id) ) |
Vamos criar também um sequence para essa tabela.
1 | CREATE SEQUENCE public.ping_geo_seq INCREMENT 1 MINVALUE 1 MAXVALUE 99999999999999999; |
POINT (latitude e longitude)
O primeiro dado que vamos trabalhar é o mais simples, um ponto geoespacial criado a partir de uma latitude e longitude. Cada ping recebido pelo serviço, será transformado em um ponto utilizando um comando de INSERT SQL. Execute o comando abaixo para incluir nosso primeiro ping.
1 | INSERT INTO ping_geo VALUES (NEXTVAL('ping_geo_seq'), now(), -22.912177, -43.230336, ST_SetSRID(ST_MakePoint(-43.230336,-22.912177),4326)); |
O que temos de diferente na instrução acima é a gravação da representação geométrica do PING na coluna geo do tipo geometry. Nesta coluna estamos usando a função ST_MakePoint do PostGIS que recebe como entrada uma latitude e longitude e retorna um dado do tipo geometry representando um ponto.
No resultado dessa função chamamos uma outra função chamada ST_SetSRID para setar o SRID da representação geométrica.
O SRID corresponde a um sistema de referência espacial para mapeamento de terra plana ou de terra redonda. Resumindo, é o sistema de coordenadas que sua representação geométrica utiliza. O numero 4326 representa o sistema de coordenadas mais utilizado que é o WGS84. Não precisa se preocupar com isso, apenas tenha em mente que todas as suas representações geométricas precisam utilizar esse mesmo sistema de coordenadas.
Criado o primeiro ponto, vamos seguir em frente inserindo novos pings. Execute o comando abaixo para inserir mais 8 entradas.
1 2 3 4 5 6 7 8 | INSERT INTO ping_geo VALUES (NEXTVAL('ping_geo_seq'), now(), -22.913161, -43.232021, ST_SetSRID(ST_MakePoint(-43.232021,-22.913161),4326)); INSERT INTO ping_geo VALUES (NEXTVAL('ping_geo_seq'), now(), -22.912410, -43.234650, ST_SetSRID(ST_MakePoint(-43.234650,-22.912410),4326)); INSERT INTO ping_geo VALUES (NEXTVAL('ping_geo_seq'), now(), -22.913537, -43.235519, ST_SetSRID(ST_MakePoint(-43.235519,-22.913537),4326)); INSERT INTO ping_geo VALUES (NEXTVAL('ping_geo_seq'), now(), -22.914150, -43.237890, ST_SetSRID(ST_MakePoint(-43.237890,-22.914150),4326)); INSERT INTO ping_geo VALUES (NEXTVAL('ping_geo_seq'), now(), -22.914861, -43.241345, ST_SetSRID(ST_MakePoint(-43.241345,-22.914861),4326)); INSERT INTO ping_geo VALUES (NEXTVAL('ping_geo_seq'), now(), -22.915632, -43.244896, ST_SetSRID(ST_MakePoint(-43.244896,-22.915632),4326)); INSERT INTO ping_geo VALUES (NEXTVAL('ping_geo_seq'), now(), -22.916907, -43.247546, ST_SetSRID(ST_MakePoint(-43.247546,-22.916907),4326)); INSERT INTO ping_geo VALUES (NEXTVAL('ping_geo_seq'), now(), -22.917580, -43.245876, ST_SetSRID(ST_MakePoint(-43.245876,-22.917580),4326)); |
Trabalhando com GEOFENCES
Geofences, também conhecida em nosso idioma como geocercas, são perímetros virtuais de uma posição geográfica. Imagina que um dos recursos do nosso sistema envolva marcar um encontro entre 2 usuários, Rick and Morty. Quando um deles chegar no local, o outro deve receber uma mensagem informando que a pessoa já está no local.
Para implementar esse recurso, criamos um ponto no local de encontro e a partir desse ponto geramos um círculo com por exemplo, 50 metros de raio. Quando o sistema receber o ping, vamos verificar se a localização está dentro do raio do ponto de encontro, que é nossa geofence.
Se o Morty estiver dentro da geofence, enviamos um push pro aplicativo do Rick informando que o Morty chegou ao local combinado.
Vamos ver agora como criamos a geofence e verificamos se o Morty já chegou ao local combinado
No nosso exemplo sobre criação de pontos no mapa, criamos 9 pings no banco. Vamos tratar o último ping como o ponto de encontro. Para gerar uma geofence, utilizamos a função ST_BUFFER do PostGIS.
1 | SELECT ST_Buffer(ST_SetSRID(ST_MakePoint(-43.245876,-22.917580),4326)::Geography, 50, 'quad_segs=8')::geometry; |
O ST_BUFFER recebe como parâmetro um ponto geoespacial, um raio e um formato de configuração do polígono que será gerado.
No SQL que executamos acima, fizemos uma conversão do tipo de dado do ponto de geometry para geography, que é outro formato de armazenamento geoespacial do PostGIS. Essa conversão foi feita porque a função ST_BUFFER ao receber como parâmetro um ponto no formato geography , o raio é calculado em metros, ao contrário do tipo geometry que usa units do sistema geoespacial. No final da query, convertemos novamente o resultado para geometry.
Os dois formatos podem ser utilizados para armazenar dados, o geometry utiliza dados cartesianos e o geography utilizando dados GEODÉSICOS (??)
Eu sei, essa explicação ficou confusa, e não vai influenciar em nada o seu aprendizado, mas pra não ficar incompleto, o termo geodésico foi criado por Aristóteles e é usado na matemática para a medição e cálculo acima de superfícies curvas usando métodos semelhantes àqueles usados na superfície curva da terra.
mas enfim, o que de fato você precisa saber é que é melhor trabalhar e armazenar os dados em geometry, pois seus cálculos são mais rápidos e possui muito mais recursos do que o geography. Quando você precisar trabalhar com funções que precisa calcular distância e utilizam medidas de entrada/saída em metro, faça a conversão para geography.
Voltando a geração da geofence, o formato ‘quad_segs=8’ na função ST_BUFFER representa um circulo, você pode encontrar outras configurações na documentação para gerar outros tipos de polígono.
Agora vamos imaginar que o nosso aplicativo está rodando e Rick e Morty saíram para se encontrar. Morty já entrou dentro da geofence do ponto de encontro, como fazemos para verificar essa informação para enviar um push ao aplicativo do Rick ?
Para fazer essa verificação vamos utilizar a função ST_Contains que deve verificar para cada ping se ele está dentro da geofence. Esta função recebe como parâmetro a geofence que criamos e um ponto para verificar se ele está dentro dela.
1 2 3 4 5 | --verificando se o ponto 1 encontra-se dentro da geocerca: false SELECT ST_Contains(ST_Buffer(ST_SetSRID(ST_MakePoint(-43.245876,-22.917580),4326)::Geography, 50, 'quad_segs=8')::geometry, ST_SetSRID(ST_MakePoint(-43.230336,-22.912177),4326)); --verificando se o ponto 9 encontra-se dentro da geocerca: true SELECT ST_Contains(ST_Buffer(ST_SetSRID(ST_MakePoint(-43.245876,-22.917580),4326)::Geography, 50, 'quad_segs=8')::geometry, ST_SetSRID(ST_MakePoint(-43.245876,-22.917580),4326)); |
Acima temos duas consultas utilizando o ST_Contains. Ambas verificam se um ping do Morty está dentro da geofence do ponto de encontro. O primeiro deve retornar false e o segundo true.
Calculando distancia entre pontos
Um dos recursos do nosso app é mostrar a qual distancia as pessoas encontram-se do destino final. Para obter essa informação precisamos calcular a distância entre o ponto final e o último ping informado pelo usuário.
Este cálculo é realizado pela função ST_DISTANCE do PostGIS. No exemplo abaixo, calculamos a distância em metros do terceiro ping do Morty e o ponto de destino.
1 | SELECT ST_Distance(ST_SetSRID(ST_MakePoint(-43.234650,-22.912410),4326)::Geography, ST_SetSRID(ST_MakePoint(-43.245876,-22.917580),4326)::Geography) |
O resultado final são 1286.10 metros, repare novamente que mais uma vez convertemos o objeto geometry para geography para trabalharmos com metros ao invés de units
Importante lembrar que a distância é calculada entre dois pontos como um vetor, não estamos considerando rotas baseadas em ruas. Caso deseje implementar algo do tipo, como indicar o melhor caminho para um de nossos usuários chegar ao ponto de encontro (tipo um waze), dê uma olhada no pgRouting, que é um complemento do PostGIS e foi criado para trabalhar com esse tipo de informação. O uso do google maps também pode atender a sua solução.
Verificando se o usuário saiu da rota
Nosso app possui ainda um outro recurso que permite ao usuário traçar uma rota pra monitorar um caminho percorrido, por exemplo se o seu filho está indo pra escola pelo caminho correto. Ao entrar ou sair desse caminho nosso app deve emitir um alerta.
Criamos então em nosso aplicativo uma integração com o google maps onde o usuário pode desenhar uma rota entre um ponto A e o ponto B. Extraímos do maps esse caminho e salvamos a rota em nosso sistema. A rota que salvamos nada mais é que um conjunto de pontos com latitude e longitude.
Como vamos verificar se Beth Smith, filha de Rick, está utilizando a rota para ir a escola ?
O primeiro passo é criar um polígono no PostGIS que represente o caminho desta rota. O passo seguinte é verificar se os pings recebidos do app da Beth, estão dentro deste polígono. Aqui, assim como a geofence, precisamos definir também um tamanho de raio, pois se isso não for feito, o polígono gerado terá uma largura muito pequena e facilmente indicaria que a Beth saiu da rota para a escola.
Vamos considerar para este exemplo que todos os pings inseridos na tabela ping_geo representam o caminho da rota. Vamos executar abaixo o SQL que vai listar todos esses pings e gerar uma rota a partir deles
1 2 | SELECT ST_Buffer(ST_MakeLine(ST_SetSRID(ST_MakePoint(p.longitude,p.latitude),4326)::geometry)::geography,50, 'join=mitre mitre_limit=5.0') FROM ping_geo p |
Novamente a função ST_BUFFER é utilizada, como fizemos na geofence, porem passamos como parâmetro para ela um outro tipo de polígono, que é uma linha, gerada a partir de todos os pontos lidos da tabela com a função ST_MakeLine.
O segundo parâmetro com o valor de 50, indica que estamos criando um raio de 50 metros, mas como não estamos falando de um círculo, este raio na verdade vai “engordar” a linha 50 metros para um lado e 50 metros para o outro.
Veja abaixo a representação da rota em vermelho pra ficar mais claro
Vendo o mapa acima fico tudo mais claro, não é? como já encerramos as funcionalidades do nosso app, vamos ver agora como visualizar o que construímos neste artigo.
Monitoramento com google earth
Desenvolver uma solução SIG sem visualizar os dados em um mapa é bastante complicado. Para construir uma solução desse tipo precisamos de ferramentas para visualizar os pontos, geofences e rotas e conseguir investigar e validar se os resultados estão sendo apresentados corretamente. A ferramenta que utilizo para isso é o Google Earth Pro
O Google Earth Pro permite a importação de dados de SIG para visualização na ferramenta. Esses dados são importados utilizando o formato KML, que é um formato semelhante ao XML, para representação de dados geográficos.
Antes de prosseguir, é importante que você desmarque as opções de camada do google earth para conseguir visualizar os dados que serão plotados no mapa
No caso do nosso cenário, o Morty teve 9 pings no total que salvando os dados no formato KML, eles são apresentados no google earth conforme abaixo
Se não conhece a região, o nosso amigo Morty, estava no estádio do maracanã (POINT 1) e foi até o ponto de encontro após o jogo (POINT 9)
Para visualizar os dados acima, criamos um arquivo com o nome VISUALIZACAO_GOOGLE_EARTH.KLM com o seguinte conteúdo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | <?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom"> <Document> <name>KML Artigo POSTGIS Codechain</name> <open>1</open> <description>exibição dos dados utilizados no artigo codechain</description> <Style id="pin_amarelo"> <IconStyle> <scale>1.3</scale> <Icon><href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href></Icon> <hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/> </IconStyle> </Style> <Style id="pin_vermelho"> <IconStyle> <scale>1.3</scale> <Icon><href>http://maps.google.com/mapfiles/kml/pushpin/red-pushpin.png</href></Icon> <hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/> </IconStyle> </Style> <Style id="geofence"> <LineStyle> <color>ff7fffff</color> </LineStyle> <PolyStyle> <color>ff00ffff</color> </PolyStyle> </Style> <Folder> <name>Rick</name> <open>1</open> <description>Pings realizados pelo RICK</description> <Placemark> <name>POINT 1</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.230336,-22.912177</coordinates></Point> </Placemark> <Placemark> <name>POINT 2</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.232021,-22.913161</coordinates></Point> </Placemark> <Placemark> <name>POINT 3</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.234650,-22.912410</coordinates></Point> </Placemark> <Placemark> <name>POINT 4</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.235519,-22.913537</coordinates></Point> </Placemark> <Placemark> <name>POINT 5</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.237890,-22.914150</coordinates></Point> </Placemark> <Placemark> <name>POINT 6</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.241345,-22.914861</coordinates></Point> </Placemark> <Placemark> <name>POINT 7</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.244896,-22.915632</coordinates></Point> </Placemark> <Placemark> <name>POINT 8</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.247546,-22.916907</coordinates></Point> </Placemark> <Placemark> <name>POINT 9</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.245876,-22.917580</coordinates></Point> </Placemark> </Folder> </Document> </kml> |
Olhando o conteúdo do arquivo, percebe que ele é bastante intuitivo. Criamos inicialmente 3 estilos pra apresentar os dados no mapa e 1 placemark para cada ping dentro da pasta. Cada placemark recebe como entrada a latitude e longitude da localização.
Repare que o estilo utiliza um código de cor diferente do RGB e do HTML. Utilize esse site para fazer a conversão facilmente.
Lógico que pra esse nosso exemplo inicial é muito simples plotar pontos, pois nós temos a latitude e longitude que representam eles, mas como faremos pra representar uma geofence ou rota?
O PostGIS possui uma função chamada ST_AsKML que recebe como parâmetro um objeto geometry ou geography e retorna um XML representando o polígono resultante. Se aplicarmos esta função na geofence que criamos nesse artigo faríamos a seguinte consulta:
1 | SELECT ST_AsKML(ST_Buffer(ST_SetSRID(ST_MakePoint(-43.245876,-22.917580),4326)::Geography, 50, 'quad_segs=8')::Geometry); |
O resultado da query acima exibe o XML abaixo
1 2 3 4 5 6 7 8 | <?xml version="1.0" encoding="UTF-8"?> <Polygon> <outerBoundaryIs> <LinearRing> <coordinates>-43.245388632402218,-22.917574615289258 -43.245396862830752,-22.917662795074339 -43.245423506259407,-22.917747793117666 -43.245467538827725,-22.917826342985233 -43.245527268411436,-22.917895426037575 -43.245600399646293,-22.917952387436291 -43.24568412213619,-22.917995038170268 -43.245775218455591,-22.91802173918073 -43.245870187796058,-22.918031464351589 -43.245965380504629,-22.918023839944237 -43.246057138343126,-22.917999158960992 -43.246141935077688,-22.917958369885049 -43.24621651199476,-22.917903040229842 -43.246278003135046,-22.917835296298435 -43.24632404543231,-22.917757741468623 -43.246352869524074,-22.917673356144011 -43.246363367744621,-22.917585383216522 -43.246355136687704,-22.917497203442174 -43.246328492703988,-22.917412205519629 -43.246284459738412,-22.91733365586451 -43.246224729975744,-22.917264573083916 -43.246151598807458,-22.917207611974909 -43.246067876619556,-22.917164961504486 -43.245976780791565,-22.917138260691281 -43.245881812057121,-22.917128535621377 -43.245786619976926,-22.917136160017989 -43.245694862693504,-22.917160840880459 -43.245610066356193,-22.917201629743946 -43.245535489618085,-22.917256959127393 -43.245473998411207,-22.917324702769093 -43.245427955811962,-22.917402257335361 -43.245399131228787,-22.91748664246272 -43.245388632402218,-22.917574615289258</coordinates> </LinearRing> </outerBoundaryIs> </Polygon> |
este XML deve ser inserido no arquivo KML, dentro do placemark.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | <?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom"> <Document> <name>KML Artigo POSTGIS Codechain</name> <open>1</open> <description>exibição dos dados utilizados no artigo codechain</description> <Style id="pin_amarelo"> <IconStyle> <scale>1.3</scale> <Icon><href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href></Icon> <hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/> </IconStyle> </Style> <Style id="pin_vermelho"> <IconStyle> <scale>1.3</scale> <Icon><href>http://maps.google.com/mapfiles/kml/pushpin/red-pushpin.png</href></Icon> <hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/> </IconStyle> </Style> <Style id="geofence"> <LineStyle> <color>ff7fffff</color> </LineStyle> <PolyStyle> <color>64000000</color> </PolyStyle> </Style> <Folder> <name>Geofences</name> <open>1</open> <description>Pings realizados pelo RICK</description> <Placemark> <name>Ponto de Encontro Rick e Morty</name> <styleUrl>geofence</styleUrl> <Polygon><outerBoundaryIs><LinearRing><coordinates>-43.245388632402218,-22.917574615289258 -43.245396862830752,-22.917662795074339 -43.245423506259407,-22.917747793117666 -43.245467538827725,-22.917826342985233 -43.245527268411436,-22.917895426037575 -43.245600399646293,-22.917952387436291 -43.24568412213619,-22.917995038170268 -43.245775218455591,-22.91802173918073 -43.245870187796058,-22.918031464351589 -43.245965380504629,-22.918023839944237 -43.246057138343126,-22.917999158960992 -43.246141935077688,-22.917958369885049 -43.24621651199476,-22.917903040229842 -43.246278003135046,-22.917835296298435 -43.24632404543231,-22.917757741468623 -43.246352869524074,-22.917673356144011 -43.246363367744621,-22.917585383216522 -43.246355136687704,-22.917497203442174 -43.246328492703988,-22.917412205519629 -43.246284459738412,-22.91733365586451 -43.246224729975744,-22.917264573083916 -43.246151598807458,-22.917207611974909 -43.246067876619556,-22.917164961504486 -43.245976780791565,-22.917138260691281 -43.245881812057121,-22.917128535621377 -43.245786619976926,-22.917136160017989 -43.245694862693504,-22.917160840880459 -43.245610066356193,-22.917201629743946 -43.245535489618085,-22.917256959127393 -43.245473998411207,-22.917324702769093 -43.245427955811962,-22.917402257335361 -43.245399131228787,-22.91748664246272 -43.245388632402218,-22.917574615289258</coordinates></LinearRing></outerBoundaryIs></Polygon> </Placemark> </Folder> <Folder> <name>Rick</name> <open>1</open> <description>Pings realizados pelo RICK</description> <Placemark> <name>POINT 1</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.230336,-22.912177</coordinates></Point> </Placemark> <Placemark> <name>POINT 2</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.232021,-22.913161</coordinates></Point> </Placemark> <Placemark> <name>POINT 3</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.234650,-22.912410</coordinates></Point> </Placemark> <Placemark> <name>POINT 4</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.235519,-22.913537</coordinates></Point> </Placemark> <Placemark> <name>POINT 5</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.237890,-22.914150</coordinates></Point> </Placemark> <Placemark> <name>POINT 6</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.241345,-22.914861</coordinates></Point> </Placemark> <Placemark> <name>POINT 7</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.244896,-22.915632</coordinates></Point> </Placemark> <Placemark> <name>POINT 8</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.247546,-22.916907</coordinates></Point> </Placemark> <Placemark> <name>POINT 9</name> <styleUrl>pin_amarelo</styleUrl> <Point><coordinates>-43.245876,-22.917580</coordinates></Point> </Placemark> </Folder> </Document> </kml> |
O arquivo final contendo todos os pontos, geofence e rota deste artigo estão disponíveis no GIT
CONCLUSÃO
Com tudo o que vimos nesse artigo você será capaz de iniciar e criar o seu próprio SIG. Lógico que o PostGIS possui muito mais recursos e a motivação aqui não é a especialização.
Caso queira se aprofundar mais, existe um ótimo livro utilizado como referência no meio chamado PostGIS in Action.
chegamos ao fim pessoal! Wubba lubba dub dub!
tema do artigo: Rick and Morty
Seja o primeiro a comentar