logo


Os topicos abaixos cobrem conceitos básicos de como usar ferramentas de programação para criar mapas interativos, integração com banco de dados e geoprocessamento básico de imagens.



Módulo I - Preparando o seu ambiente de programação.

Um servidor/sistema que gera mapas interativos depende dos fatores abaixo:

  • O Servidor em si - de preferência em ambiente Linux.
  • Um servidor de páginas web - aqui usamos Go como servidor e backend (processos no servidor).
  • Um banco de dados PostgreSQL com a extensão Postgis.
  • Leaflet javaScript que será o nosso frontend (processos no computador de quem acessa).

    Na ilustração abaixo vemos um sistema semelhante, onde a esquerda são os usuários que visualizam ou interagem com os dados via internet (no meio) com os dados do servidor mais o banco de dados (na direita).

    Aqui nestes tutoriais vamos montar o servidor, o banco de dados e acessar como cliente em um único desktop ou laptop. Vamos por etapas cobrindo os conceitos básicos de Linux e depois como instalar as ferramentas que iremos utilizar. Caso já tenha conhecimento de Linux, ja tenha Go e PostgreSQL com o Postgis instalados, você pode pular para o próximo tópico.

  • Parte 1 - O Linux - Conhecimento base

    Usaremos o programa "Terminal" em um sistema Ubuntu para aprender a usar os comandos básicos e essenciais do linux.

    O programa terminal pode ser executado a partir do ícone da barra de favoritos. Alternativamente podemos abrir clicando com o botão direito do mouse na tela principal e selecionando terminal na listagem de menu.

    A tela do terminal é mostrada abaixo:

    O Sinal '$', conhecido como prompt, indica que o usuário não é o usuário 'root'. O usuário 'root' seria representado pelo prompt '#'.

    Mas o que vem a ser o usuário 'root'?

    O 'root' é o super usuário do sistema que pode ter acesso a todos os arquivos do sistema e mudar configurações em todo o sistema. Sendo assim usar o computador como 'root' é bastante arriscado e pode comprometer o sistema se usado de forma errada.

    Desta forma, vamos na maioria do tempo usar o sistema como um usuário comum mas com poderes de super usuário.

    Para usarmos um comando que modificará o sistema ou que vai alterar um arquivo que não somos dono temos ter usar a prerrogativa 'sudo' (abreviação para 'super user do' ou 'feito pelo super usuário') e confirmarmos com a senha de usuário para termos esse privilégio. Isso previne bastante o risco de mudarmos o que não queremos.

    Regra número 1 - Nunca use 'sudo', ao menos se você tenha absoluta certeza do que está fazendo, por exemplo instalando um programa no sistema.

    Vamos agora iniciar o aprendizado dos comandos.

    No Terminal, conforme falamos acima, temos o prompt e aqui ele é representado por você@seu.computador:~$. Digite somente o que vem depois dessa parte.

    No Unix e no Linux os comandos possuem o seguinte formato:

    comando -[opções] [argumento]

    Comandos de navegação nos diretórios (ou pastas)

  • ls
  • O comando ls lista o conteúdo da pasta corrente.

    você@seu.computador:~$ ls
     Android                 Modelos
     AndroidStudioProjects   Música
    'Área de Trabalho'       Público
     Documentos              swift-4.2.1-RELEASE-ubuntu18.04.tar.gz
     Downloads               ubuntando.odt
     examples.desktop        Vídeos
     Imagens                 xAndre

    Com a opção -l lista no formato longo que dá mais informações sobre cada arquivo ou sub pastas nesta pasta.
    Lista o tamanho dos arquivos na pasta na primeira linha e depois a seguinte informação de cada subpasta ou arquivo:
    permissões, níveis de subdiretórios, dono, grupo, tamanho, data de criação co horário, nome.

    você@seu.computador:~$ ls -l
    total 214504
    drwxr-xr-x 3 andre andre      4096 mai  4 15:07  Android
    drwxr-xr-x 3 andre andre      4096 mai  4 15:12  AndroidStudioProjects
    drwxr-xr-x 2 andre andre      4096 abr 28 06:02 'Área de Trabalho'
    drwxr-xr-x 2 andre andre      4096 abr 28 06:02  Documentos
    drwxr-xr-x 2 andre andre      4096 mai  4 16:57  Downloads
    -rw-r--r-- 1 andre andre      8980 abr 28 05:55  examples.desktop
    drwxr-xr-x 3 andre andre      4096 mai  4 13:11  Imagens
    drwxr-xr-x 2 andre andre      4096 abr 28 06:02  Modelos
    drwxr-xr-x 2 andre andre      4096 abr 28 06:02  Música
    drwxr-xr-x 2 andre andre      4096 abr 28 06:02  Público
    -rw-r--r-- 1 andre andre 219569359 out 31  2018  swift-4.2.1-RELEASE-ubuntu18.04.tar.gz
    -rw-rw-r-- 1 andre andre     18288 abr 28 20:45  ubuntando.odt
    drwxr-xr-x 2 andre andre      4096 abr 28 06:02  Vídeos
    drwxr-xr-x 5 andre andre      4096 abr 28 08:59  xAndre

    Com a opção -a lista os arquivos ocultos (que no Linux geralmente começam com '.')

    você@seu.computador:~$ ls -a
     .                       Imagens
     ..                      .java
     .android                .lldb
     Android                 .local
     .AndroidStudio3.4       .macromedia
     AndroidStudioProjects   Modelos
    'Área de Trabalho'       .mozilla
     .bash_history           Música
     .bash_logout            .profile
     .bashrc                 .psql_history
     .cache                  Público
     .config                 .python_history
     .dbus                   .ssh
     Documentos              .sudo_as_admin_successful
     Downloads               swift-4.2.1-RELEASE-ubuntu18.04.tar.gz
     examples.desktop        ubuntando.odt
     .gnupg                  Vídeos
     .gradle                 .wget-hsts
     .ICEauthority           xAndre

    Usar argumentos para filtrar os resultados pode ser bastante útil. Podemos usar 'wildcards' ou caracteres coringas. O caractere coringa pode ser o '*' ou o '?'. O '*' representa qualquer caractere quantas vezes eles existirem e '?' representa qualquer caractere somente uma vez. Já '??' representa qualquer caractere duas vezes e assim por diante.

    Veja abaixo alguns exemplos de uso do caractere coringa:

    você@seu.computador:~$ ls
    andre1.txt    andre34.txt   andre843.txt  jose2.png  jose843.txt
    andre2.txt    andre3.txt    jose1.png     jose2.txt
    andre343.txt  andre843.png  jose1.txt     jose3.txt
    você@seu.computador:~$ ls andre*
    andre1.txt  andre343.txt  andre3.txt    andre843.txt
    andre2.txt  andre34.txt   andre843.png
    você@seu.computador:~$ ls jose*
    jose1.png  jose1.txt  jose2.png  jose2.txt  jose3.txt  jose843.txt
    você@seu.computador:~$ ls jose?.txt
    jose1.txt  jose2.txt  jose3.txt
    você@seu.computador:~$ ls jose?.*
    jose1.png  jose1.txt  jose2.png  jose2.txt  jose3.txt
    você@seu.computador:~$ ls andre???.txt
    andre343.txt  andre843.txt
    você@seu.computador:~$ ls andre???.*
    andre343.txt  andre843.png  andre843.txt
    você@seu.computador:~$ ls *e?.txt
    andre1.txt  andre2.txt  andre3.txt  jose1.txt  jose2.txt  jose3.txt
    
  • pwd
  • O comando pwd informa em qual pasta estamos.

    você@seu.computador:~$ pwd
    /home/andre
  • cd
  • O comando cd (change directory) muda para a pasta informada no argumento. Se usarmos o argumento .. movemos uma pasta acima, se usarmos o argumento ~ movemos para a pasta home do usuário e se usarmos / como argumento vamos para o diretório raiz do computador.

    você@seu.computador:~$ cd ..
    você@seu.computador:/home$ pwd
    /home
    você@seu.computador:/home$ cd /
    você@seu.computador:/$> pwd
    /
    você@seu.computador:/$ cd ~ 
    você@seu.computador:~$ pwd
    /home/andre
    você@seu.computador:~$ cd /usr/bin
    você@seu.computador:/usr/bin$ pwd
    /usr/bin
    você@seu.computador:/usr/bin$ cd ~
    você@seu.computador:~$ pwd
    /home/andre

    Comandos de manuais e informaçãos sobre comandos

  • man
  • O comando man gera um manual de ajuda sobre o comando passado como argumento.

    Execute o comando abaixo e navegue usando as setas para cima e para baixo, para sair aperte a tecla 'q':

    você@seu.computador:~$ man ls

    Caso a página esteja em inglês vamos mudar para o português conforme abaixo

    você@seu.computador:~$ sudo apt-get install language-pack-br
    você@seu.computador:~$ sudo apt-get install manpages-pt
    você@seu.computador:~$ LANG=pt_BR.UTF-8

    Agora tente novamente e a página deve estar em português

    você@seu.computador:~$ man ls
    LS(1)                       General Commands Manual                      LS(1)
    
    NOME
           ls, dir, vdir - lista o conteúdo do diretório
    
    SINOPSE
           ls [opções] [arquivo...]
           dir [arquivo...]
           vdir [arquivo...]
    
           Opções POSIX: [-CFRacdilqrtu1]
    
           Opções  GNU  (forma reduzida): [-1abcdfghiklmnopqrstuvwxABCDFGHLNQRSUX]
           [-w    coluna]    [-T     coluna]     [-I     modelo]     [--full-time]
           [--show-control-chars]                              [--block-size=size]
           [--format={long,verbose,commas,across,vertical,single-column}]
           [--sort={none,time,size,extension}]
           [--time={atime,access,use,ctime,status}] [--color[={none,auto,always}]]
           [--help] [--version] [--]
    
    DESCRIÇÃO
           O  programa  ls  lista  primeiramente  seus  argumentos  que  não sejam
    

    Como podemos ver, existem muitas outras opções para serem usadas com o comando ls. Vimos apenas as mais usadas e faremos o mesmo pra os outros comandos, use o 'man' para aprender mais sobre os comandos.

    Infelizmente nem todos manuais estão em português.

  • info
  • O comando info gera informação mais detalhada de comandos e programas instalados no computador. O problema é que a maioria da informação está em inglês.

    você@seu.computador:~$info pwd
    19.1 ‘pwd’: Print working directory
    ===================================
    
    ‘pwd’ prints the name of the current directory.  Synopsis:
    
         pwd [OPTION]...
    
       The program accepts the following options.  Also see *note Common
    options::.
    
    ‘-L’
    ‘--logical’
         If the contents of the environment variable ‘PWD’ provide an
         absolute name of the current directory with no ‘.’ or ‘..’
         components, but possibly with symbolic links, then output those
         contents.  Otherwise, fall back to default ‘-P’ handling.
    
    ‘-P’
    ‘--physical’
    
  • whatis
  • O comando whatis retorna uma descrição do que o comando faz retornando somente um resultado que é exatamente o comando passado no argumento.

    você@seu.computador:~$ whatis unzip
    unzip (1)            - list, test and extract compressed files in a ZIP archive
  • apropos
  • O comando apropos pesquisa os comandos que incluam o argumento pesquisado, seja no nome do comando ou na descrição do que ele é.

    você@seu.computador:~$ apropos unzip
    bunzip2 (1)          - a block-sorting file compressor, v1.0.6
    funzip (1)           - filter for extracting from a ZIP archive in a pipe
    gunzip (1)           - compress or expand files
    lz (1)               - gunzips and shows a listing of a gzip'd tar'd archive
    PerlIO::gzip (3pm)   - Perl extension to provide a PerlIO layer to gzip/gunzip
    preunzip (1)         - prefix delta compressor for Aspell
    unzip (1)            - list, test and extract compressed files in a ZIP archive
    unzipsfx (1)         - self-extracting stub for prepending to ZIP archives
    uz (1)               - gunzips and extracts a gzip'd tar'd archive

    Comandos de visualização e informação sobre arquivos

    Os comandos aqui mostrados são úteis para se obter informações sobre um determinado arquivo. Vamos supor que temos um arquivo texto chamado 'arqui.txt' com a seguinte linha: 'oi, sou texto mano!'

  • file
  • O comando file retorna informações sobre o arquivo passado como argumento.

    você@seu.computador:~$ file arqui.txt
    arqui.txt: ASCII text
  • cat
  • O comando cat retorna o conteúdo do arquivo passado como argumento.

    você@seu.computador:~$ cat arqui.txt
    oi, sou texto mano!

    Comandos de copia, renomeação, remoção e movimentação de arquivos

    Os comandos que veremos agora servem para copiar, remover e mover (ou renomear) arquivos e pastas. Muita atenção deve ser dada quando usando o comando rm pois se trata de uma operação irreversível.

  • cp
  • O comando cp copia um arquivo (ou diretório) de uma localidade (pasta) para outra. O formato é:
    cp opções fonte destino

    Nesse exemplo copiaremos o arquivo arqui.txt que está no nosso diretório home para dentro da pasta Documentos também localizada no diretório home.

    você@seu.computador:~$ cp arqui.txt Documentos/

    Vamos agora usar cd para ir ao diretório Documentos e usar ls para verificar se o arquivo foi copiado nele.

    você@seu.computador:~$ cd Documentos
    você@seu.computador:~/Documentos$ ls
    arqui.txt

    Podemos copiar de forma recursiva, ou seja, uma pasta inteira com sub pastas de uma localidade para outra usando a opção -R.

    Por exemplo, copiando a pasta Documentos para a pasta Música.

    você@seu.computador:~/Documentos$ cd ..
    você@seu.computador:~$ cp -R Documentos Música/
    você@seu.computador:~$ cd Música
    você@seu.computador:~/Música$ ls
    Brazilian-Songbook-Online-popular-1.pdf
    Brazilian-Songbook-Online-popular-2.pdf
    Brazilian-Songbook-Online-popular-3.pdf
    Documentos
    você@seu.computador:~/Música$ cd Documentos
    você@seu.computador:~/Música/Documentos$ ls
    arqui.txt
  • rm
  • Vamos mostrar como usar o comando rm. Muito cuidado para saber direito o que estamos fazendo, primeiro vamos voltar uma pasta acima para o diretório Música e ai vamos remover o Diretório Documentos de forma recursiva usando a opção -R.

    você@seu.computador:~/Música/Documentos$ cd ..
    você@seu.computador:~/Música$ rm -R Documentos
    você@seu.computador:~/Música$ ls
    Brazilian-Songbook-Online-popular-1.pdf
    Brazilian-Songbook-Online-popular-2.pdf
    Brazilian-Songbook-Online-popular-3.pdf

    Agora vamos subir novamente para o diretório home e remover o arquivo arqui.txt.

    você@seu.computador:~/Música$ cd ..
    você@seu.computador:~$ rm arqui.txt
    você@seu.computador:~$ ls
    Android                 Modelos
     AndroidStudioProjects   Música
    'Área de Trabalho'       Público
     Documentos              swift-4.2.1-RELEASE-ubuntu18.04.tar.gz
     Downloads               ubuntando.odt
     examples.desktop        Vídeos
     Imagens                 xAndre

    Novamente, muito cuidado ao usar rm, evite usar -R e caracteres coringa. Usar um comando tipo rm -R * pode causar um grande estrago irreversível que irá apagar todos os arquivo e pastas daquele diretório.

  • mv
  • O comando mv pode ser usado tanto para renomear como para mover um arquivo ou pasta.

    Vamos mover o arquivo arqui.txt que copiamos no diretório Documentos para o diretório home usando mv.

    você@seu.computador:~$ cd Documentos
    você@seu.computador:~/Documentos$ ls
    arqui.txt
    você@seu.computador:~$ mv arqui.txt ~/
    você@seu.computador:~/Documentos$ ls
    você@seu.computador:~/Documentos$ cd ..
    você@seu.computador:~$ ls
    Android                 Modelos
     AndroidStudioProjects   Música
    'Área de Trabalho'       Público
     arqui.txt               swift-4.2.1-RELEASE-ubuntu18.04.tar.gz
     Documentos              ubuntando.odt
     Downloads               Vídeos
     examples.desktop        xAndre
     Imagens

    Vamos agora renomear o arquivo arqui.txt para novo.txt usando mv e usar cat para mostrar que o conteúdo do arquivo permanece o mesmo.

    você@seu.computador:~$ mv arqui.txt novo.txt
    você@seu.computador:~$ ls
    Android                 Música
     AndroidStudioProjects   novo.txt
    'Área de Trabalho'       Público
     Documentos              swift-4.2.1-RELEASE-ubuntu18.04.tar.gz
     Downloads               ubuntando.odt
     examples.desktop        Vídeos
     Imagens                 xAndre
     Modelos
    você@seu.computador:~$ cat novo.txt
    oi, sou texto mano!

    Comandos de criação de arquivos e diretórios.

    Vamos ver agora dois comandos que servem para criar arquivo vazio ou uma nova pasta.

  • touch
  • O comando touch cria um arquivo vazio com o nome dado no argumento.

    você@seu.computador:~$ touch teste.txt
    você@seu.computador:~$ ls
     Android                 Imagens                                  teste.txt
     AndroidStudioProjects   Modelos                                  ubuntando.odt
    'Área de Trabalho'       Música                                   Vídeos
     Documentos              novo.txt                                 xAndre
     Downloads               Público
     examples.desktop        swift-4.2.1-RELEASE-ubuntu18.04.tar.gz
  • mkdir
  • O comando mkdir cria um novo diretório com nome e localidade indicada no argumento

    você@seu.computador:~$ mkdir Documentos/novo_dir
    você@seu.computador:~$ cd Documentos
    você@seu.computador:~/Documentos$ ls
    novo_dir

    Comandos de saída do terminal.

  • exit ou logout
  • O comando exit ou logout, como o próprio nome diz efetua a saída do usuário do terminal (fecha o terminal e/ou termina a conexão).

    você@seu.computador:~$ exit

    O terminal foi fechado.

    Vimos os comandos básicos do linux, são poucos mas são os básicos que te atenderam a maior parte do tempo. Seja curioso e tente apreender novos comandos e novas opções dos comandos que você aprendeu usando 'man'. A seguir veremos outros comandos importantes e os conceitos de pipe e redireção.

    Nesta parte veremos como é feito o redirecionamento de resultados de comandos. Comandos geralmente mostram seus resultados na tela, este é o padrão, mas podemos direcionar o resultado para um arquivo novo ou para o final de um arquivo já existente. Também podemos direcionar o resultado de um comando como a entrada de um outro comando.

    Veremos abaixo como fazer isso:

  • >
  • O '>' redireciona o resultado para um arquivo novo. Por exemplo, podemos listar um diretório dentro de um arquivo que chamaremos de lista.txt usando:

    você@seu.computador:~$ ls > lista.txt

    e podemos ler o conteúdo deste arquivo usando o comando cat:

    você@seu.computador:~$ cat lista.txt
    cartões de festa.txt
    compras.pdf
    lista.txt
    recibo.pdf 
  • >>
  • O Comando '>>' adiciona, no final de um arquivo existente, o resultado de um comando. Por exemplo, se listarmos o diretório novamente usando '>>' o resultado será adicionado no fim do arquivo, se esse arquivo não existir um novo será criado.

    você@seu.computador:~$ ls >> lista.txt

    e novamente podemos ler o conteúdo deste arquivo usando cat:

    você@seu.computador:~$ cat lista.txt
    cartões de festa.txt
    compras.pdf
    lista.txt
    recibo.pdf
    cartões de festa.txt
    compras.pdf
    lista.txt
    recibo.pdf
  • |
  • O '|' também conhecido como pipe redireciona o resultado de um comando para outro comando. Por exemplo, se listarmos todos os arquivos do diretório dev do linux não poderíamos ver todo o conteúdo numa só tela e somente a listagem final seria vista, mas direcionando o resultado usando '|' para o comando 'more' uma página por vez seria mostrada e, ao pressionar a barra de espaço, a próxima página seria mostrada e assim por diante até chegar ao final da listagem.

    você@seu.computador:~$ ls -la /dev | more
    total 16
    drwxr-xr-x. 21 root   root        3480 Mai  9 11:37 .
    dr-xr-xr-x. 17 root   root       12288 Mai  9 11:38 ..
    crw-------.  1 root   root     10, 235 Mai  9 11:37 autofs
    drwxr-xr-x.  2 root   root         300 Mai  9 11:37 block
    drwxr-xr-x.  2 root   root          80 Mai  9 07:37 bsg
    crw-------.  1 root   root     10, 234 Mai  9 11:37 btrfs-control
    drwxr-xr-x.  3 root   root          60 Mai  9 07:36 bus
    lrwxrwxrwx.  1 root   root           3 Mai  9 11:37 cdrom -> sr0
    drwxr-xr-x.  2 root   root         100 Mai  9 11:37 centos
    drwxr-xr-x.  2 root   root        3360 Mai 15 06:35 char
    crw-------.  1 root   root      5,   1 Mai  9 11:37 console
    lrwxrwxrwx.  1 root   root          11 Mai  9 07:37 core -> /proc/kcore
    drwxr-xr-x.  6 root   root         140 Mai  9 07:36 cpu
    crw-------.  1 root   root     10,  61 Mai  9 11:37 cpu_dma_latency
    crw-------.  1 root   root     10,  62 Mai  9 11:37 crash
    drwxr-xr-x.  8 root   root         160 Mai  9 07:37 disk
    brw-rw----.  1 root   disk    253,   0 Mai  9 11:37 dm-0
    --Mais--
  • tee
  • O comando tee seria como uma bifurcação do que ele recebe e é usado com o pipe geralmente. Ele pega o resultado do comando passado pelo pipe '|' e mostra na tela e ao mesmo tempo grava em um arquivo. Por exemplo: se usarmos uma listagem do diretório corrente usando tee teremos o resultado mostrado na tela e também gravado no arquivo 'resultado.txt'

    você@seu.computador:~$ ls | tee resultado.txt
    cartões de festa.txt
    compras.pdf
    lista.txt
    recibo.pdf
    

    e usamos cat para ver o conteúdo do arquivo 'resultado.txt'

    você@seu.computador:~$ cat resultado.txt
    cartões de festa.txt
    compras.pdf
    lista.txt
    recibo.pdf
    
  • grep
  • O comando grep é muito útil para extrair ou checar informação de dentro de um arquivo. Ele retorna a linha onde existe a ocorrência do texto passado pelo argumento. Nesse exemplo vamos criar um arquivo com o conteúdo da página de manual do ls, Primeiro criamos esse arquivo com o comando man e direcionando o resulta para o arquivo manual.txt

    você@seu.computador:~$ man ls > manual_ls.txt

    Agora usamos o comando grep para achar as linhas onde a palavra free ocorre.

    você@seu.computador:~$ grep free manual_ls.txt
    This is free software: you are free to change and redistribute it.  There is NO WARRANTY, to the extent

    Parte 2 - Ferramentas úteis para acesso remoto de sistemas, baixar arquivos e compressão de arquivos

    O ambiente Linux possui vários programas (ou ferramentas) que tornam bastante eficiente a manipulação, acesso e a organização de arquivos e de dados.

    Muitas dessas ferramentas são relacionadas a acesso remoto, compactação e descompactação de arquivos e obtenção eficiente de dados na rede.

    O ssh (Secure Shell) é usado para fazer o login em um computador remoto de maneira segura (criptografado).

    Instalamos ele usando o apt da seguinte forma:

    você@seu.computador:~$ sudo apt-get install openssh-server

    Em seguida adicionamos a instrução de inicializar o ssh ao ligar usando:

    você@seu.computador:~$ sudo update-rc.d ssh enable

    O uso dessa ferramenta é bastante simples bastando apenas ao usuário do computador remoto efetuar o login de forma remota usando:

    você@seu.computador:~$ ssh nomeDoUsuário@domínio.ou.ip,do.computador

    Será pedido a confirmação de chave no primeiro acesso e também a senha do usuário no sistema remoto. Em computadores com linux ou MacOS use o próprio terminal para fazer o acesso remoto. No windows instale o programa Putty.

    O protocolo de transferência de arquivos (File Transfer Protocol no inglês) é um servidor que permite a transferência de arquivos entre computadores na rede como o próprio nome diz. Ele é usado para transferência de arquivos de tamanho maior mas pode ser para qualquer arquivo.

    Vamos instalar o vsftpd que é um servidor ftp bastante usado. Instalamos ele usando:

    você@seu.computador:~$ sudo apt-get install vsftpd

    Em seguida adicionamos a instrução de inicializar o servidor FTP ao ligar usando:

    você@seu.computador:~$ sudo update-rc.d vsftpd enable

    Use programas de cliente FTP do tipo filezilla ou o próprio terminal para ter acesso a um servidor FTP.

    O wget é um ótimo programa para obter dados da web sem necessariamente ter de entrar em um navegador da web.

    Instalamos ele com o seguinte comando:

    você@seu.computador:~$ sudo apt-get install wget

    O unzip serve para descompactar arquivos do tipo zip ou criar arquivo compactado zip.

    Instalamos ele da seguinte forma:

    você@seu.computador:~$ sudo apt-get install unzip

    Vamos mostras agora como baixar um arquivo do tipo zip com o wget.

    você@seu.computador:~$ wget http://sigmine.dnpm.gov.br/sirgas2000/AM.zip
    --2019-05-04 16:58:40--  http://sigmine.dnpm.gov.br/sirgas2000/AM.zip
    Resolvendo sigmine.dnpm.gov.br (sigmine.dnpm.gov.br)... 200.198.193.233
    Conectando-se a sigmine.dnpm.gov.br (sigmine.dnpm.gov.br)|200.198.193.233|:80... conectado.
    A requisição HTTP foi enviada, aguardando resposta... 200 OK
    Tamanho: 1193526 (1,1M) [application/x-zip-compressed]
    Salvando em: “AM.zip”
    
    AM.zip              100%[===================>]   1,14M  1,00MB/s    em 1,1s    
    
    2019-05-04 16:58:41 (1,00 MB/s) - “AM.zip” salvo [1193526/1193526]

    E agora vamos descompactar este arquivo usando unzip

    você@seu.computador:~$ unzip AM.zip
    Archive:  AM.zip
      inflating: AM.dbf                  
      inflating: AM.prj                  
      inflating: AM.sbn                  
      inflating: AM.sbx                  
      inflating: AM.shp                  
      inflating: AM.shp.xml              
      inflating: AM.shx  

    Os arquivos foram baixados e descompactados do arquivo zip original de forma rápida e eficiente com wget e unzip.

    Parte 3 - Instalando um servidor de Banco de Dados

    Muitas aplicações e sistemas modernos são baseados em bancos de dados robustos e que podem ser acessados de formas diversas, inclusive via o servidor de páginas da web e aplicativos de smartphones.

    O PostgreSQL é um dos sistemas de banco de dados mais sofisticados que existem e veremos agora como instalar este banco de dados.

    Começamos por entrando no sistema como usuário root (Note que $ muda para #).

    você@seu.computador:~$ sudo su -

    Em seguida instalamos o PostgreSQL digitando no terminal:

    você@seu.computador:# apt-get install postgresql postgresql-contrib

    Adicionamos a instrução de inicializar o PostgreSQL ao ligar usando:

    você@seu.computador:# sudo update-rc.d postgresql enable

    E iniciamos o serviço com:

    você@seu.computador:# service postgresql start

    Iremos agora testar se a instalação foi feita com sucesso mudando para o usuário postgres e entrando no banco de dados psql conforme abaixo:

    você@seu.computador:# su - postgres
    você@seu.computador:~$ psql

    O seguinte deve aparecer: (para sair digite \q)

    psql (10.7 (Ubuntu 10.7-0ubuntu0.18.10.1))
    Type "help" for help.

    postgres=# \q

    Saia do usuário postgres e root digitando no terminal:

    você@seu.computador:~$ exit
    # exit

    Vamos agora criar um super usuário e usar este usuário para criar um banco de dados chamado teste. Substituir 'nome' pelo nome de um usuário válido no ubuntu (o seu nome de usuário). Você deverá entrar uma senha para o banco de dados diferente da sua senha de usuário, guarde essa senha:

    você@seu.computador:~$ sudo -u postgres createuser -P -s -e nome
    Enter password for new role:
    Enter it again:
    SELECT pg_catalog.set_config('search_path', '', false)
    CREATE ROLE andre PASSWORD 'minhaSenhaSecreta' SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN;

    Vamos agora criar um banco de dados chamado teste e vamos visualizar os usuários do banco de dados usando \du.

    você@seu.computador:~$ createdb -O nome teste
    você@seu.computador:~$ psql teste
    psql (10.7 (Ubuntu 10.7-0ubuntu0.18.10.1))
    Type "help" for help.

    teste=# \du
                                       List of roles
    Role name | Attributes | Member of
    -----------+------------------------------------------------------------+-----------
    nome | Superuser, Create role, Create DB | {}
    postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

    teste=# \q

    Vamos dar prosseguimento instalando o sistema Postgis usando:

    você@seu.computador:~$ sudo apt install postgis

    Criamos agora as extensões do Postgis no nosso banco de dados 'teste' criado acima:

    você@seu.computador:~$ psql -c "CREATE EXTENSION postgis; CREATE EXTENSION postgis_topology;" teste

    Vamos checar o banco de dados usando '\d' e sair usando '\q':

    você@seu.computador:~$ psql teste
    psql (10.7 (Ubuntu 10.7-0ubuntu0.18.10.1))
    Type "help" for help.
    
    teste=# \d
                    List of relations
      Schema  |       Name                  |   Type   | Owner 
    ------------+-------------------------+----------+-------
     public     | geography_columns         | view     | nome
     public     | geometry_columns          | view     | nome
     public     | raster_columns            | view     | nome
     public     | raster_overviews          | view     | nome
     public     | spatial_ref_sys           | table    | nome
     topology   | layer                     | table    | nome
     topology   | topology                  | table    | nome
     topology   | topology_id_seq           | sequence | nome
    (8 rows)
    
    teste=# \q

    Parte 4 - Instalando as Linguagens de Programação

    Vamos agora nessa parte final instalar R e Go.

    R é uma linguagem de programação poderosa que usaremos nas outras partes deste site.

    Usaremos Go como nosso servidor nestes tutoriais.

    Instale o R usando:

    você@seu.computador:~$ sudo apt install r-base

    Teste a instalação conforme abaixo (use q() para sair).

    você@seu.computador:~$ R
      
    R version 3.6.0 (2019-04-26) -- "Planting of a Tree"
    Copyright (C) 2019 The R Foundation for Statistical Computing
    Platform: x86_64-redhat-linux-gnu (64-bit)
    
    R is free software and comes with ABSOLUTELY NO WARRANTY.
    You are welcome to redistribute it under certain conditions.
    Type 'license()' or 'licence()' for distribution details.
    
      Natural language support but running in an English locale
    
    R is a collaborative project with many contributors.
    Type 'contributors()' for more information and
    'citation()' on how to cite R or R packages in publications.
    
    Type 'demo()' for some demos, 'help()' for on-line help, or
    'help.start()' for an HTML browser interface to help.
    Type 'q()' to quit R.
    
    > 
     q()
    Save workspace image? [y/n/c]: n
    

    Baixe o aquivo Go de acordo com o seu sistema (32 ou 64bits) usando.

    você@seu.computador:~$ wget https://dl.google.com/go/go1.13.1.linux-amd64.tar.gz
    

    Agora descompacte o arquivo baixado usando tar e mova ele para /usr/local/.

    você@seu.computador:~$ sudo tar -xvf go1.13.1.linux-amd64.tar.gz
    você@seu.computador:~$ sudo mv go /usr/local
    

    Ajuste as variáveis de ambiente GOROOT, GOPATH e PATH conforme abaixo:

    GOROOT é onde você moveu Go (/usr/local/go)

    você@seu.computador:~$ export GOROOT=/usr/local/go
    

    GOPATH é onde vamos executar nosso programa Go no seu diretóro de trabalho (~/Go).

    você@seu.computador:~$ mkdir ~/Go
    você@seu.computador:~$ export GOPATH=$HOME/Go
    

    E por último ajustamos a variável PATH para ser visível por todo o sistema operacional.

    você@seu.computador:~$ export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
    

    Adicione estas três linhas iniciadas com 'export' no seu arquivo ~/.profile .

    Teste usando:

    você@seu.computador:~$ go version
    go version go1.13.1 linux/amd64
    

    Prontinho! Go está instalado



    Módulo II - Ferramentas para criar Mapas Interativos.

    Vamos ver agora os conceitos mínimos de cada linguagem para gerar um mapa interativo. Vamos cobrir superficialmente cada uma delas mas caso queira se aprofundar existem recursos na web suficientes para se aprender mais sobre elas.

    Parte 1 - HTML

    Um documento <html> padrão para adicionarmos um mapa leaflet é constituído basicamente por duas partes (HEAD e BODY) conforme abaixo:

    <!DOCTYPE html>
    <html>
    <head>
     <title>Mapa Leaflet</title>
     <link/>
     <script>
     </script>
     <style>
     </style>
    </head>
    <body>
    <div></div>
    <script>
    </script>
    </body>
    </html>
    

    Na porção HEAD adicionaremos os links para os objetos javaScript e css que constituem o sistema Leaflet bem como definir em style a dimensão do mapa que criaremos e em head colocaremos um elemento <div> para o mapa e o script javaScript que define o nosso mapa.

    Parte 2 - CSS e os elementos do Leaflet

    Aqui criamos o link css e script do leaflet na porção HEAD e também a dimensão do nosso mapa em <style>. Na porção HEAD adicionamos o id mapa em <div>.

    <!DOCTYPE html>
    <html>
    <head>
     <title>Mapa Leaflet</title>
     <link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css"
       integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
       crossorigin=""/>
     <script  src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"
       integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og=="
       crossorigin="">
     </script>
     <style>
     #mapa {
      width: 800px;
      height: 460px;
     }
     </style>
    </head>
    <body>
    <div id=mapa></div>
    <script>
    </script>
    </body>
    </html>
    

    Pronto, nossa base está preparada para adicionarmos o mapa interativo Leaflet.

    Parte 3 - O Servidor Go

    Antes de adicionarmos o mapa vamos preparar o nosso servidor de websites usando Go.

    Caso queira se aprofundar mais sobre a linguagem Go faça o download da apostila que fiz nesse link.

    Vamos mostrar como podemos de maneira rápida criar um servidor em Go e mostrar um mapa Leaflet usando somente Go básico.

    Primeiro criamos o diretório MapaLeaflet que será o ambiente para o servidor Go dentro do diretório $GOPATH/src/ do seu sistema (crie o diretório 'src' caso esse ainda não exista):

    MapaLeaflet
    	|
    	|_ templates
    	|	|
    	|	|_ mapa.html
    	|	|_ layout.html
    	|
    	|_ static
    	|	|
    	|	|_ js
    	|	    |
    	|	    |_ leaflet.js
    	|	    |_ leaflet.css
    	|
    	 servidor.go
    

    Dentro do diretório MapaLeaflet criamos o arquivo servidor.go abaixo:

    package main
    import (
      "net/http"
      "html/template"
      "path/filepath"
    )
    
    func mapa(w http.ResponseWriter, r *http.Request){
     l := filepath.Join("templates", "layout.html")
     f := filepath.Join("templates", filepath.Clean(r.URL.Path))
     tpl, _ := template.ParseFiles(l, f)
     tpl.ExecuteTemplate(w, "layout", nil)
    }
    
    func main() {
      fs := http.FileServer(http.Dir("static"))
      http.Handle("/static/", http.StripPrefix("/static/", fs))
      http.HandleFunc("/mapa.html", mapa)
      println("Servidor Rodando...")
      http.ListenAndServe(":8080", nil)
    }
    

    Carregue os arquivos leaflet dentro do diretório MapaLeaflet/static/js/ baixando eles deste link

    Descompacte o arquivo ZIP e coloque os arquivos leaflet.css e leaflet.css dentro do diretório MapaLeaflet/static/js/ bem como o diretório images.

    Agora vamos criar os dois arquivos layout.html e mapa.html dentro da pasta MapaLeaflet/templates/.

    layout.html

    {{define "layout"}}
    <!DOCTYPE html>
    <html>
    <head>
     <title>Mapa Leaflet</title>
     <link rel="stylesheet" href="static/js/leaflet.css"/>
     <script  src="static/js/leaflet.js"></script>
     <style>
     #mapa {
      width: 800px;
      height: 460px;
     }
     </style>
    </head>
    <body>
    <div id=mapa></div>
    <script>
      {{template "body"}}
    </script>
    </body>
    </html>
    {{end}}
    

    mapa.html

    {{define "body"}}
      var map = L.map('mapa').setView([-3.09, -60.0], 12);
    {{end}}
    

    Vamos testar nosso primeiro servidor de mapa leaflet digitando no monitor, dentro do diretório MapaLeaflet:

    você@seu.computador:~/go/src/MapaLeaflet$ go install MapaLeaflet
    você@seu.computador:~/go/src/MapaLeaflet$ $GOPATH/bin/MapaLeaflet
    Servidor Rodando...
    

    Ao digitar localhost:8080/mapa.html no navegador deveremos ver:

    Não parece muito atraente mas essa é a base de onde criaremos nossos mapas usando Leaflet e Go. Antes disso vamos dar uma olhada nos conceitos básicos de Postgis.

    Parte 4 - Postgis

    Dados espaciais (geográficos e geométricos) são melhores armazenados usando a extensão postgis do PostgreSQL.

    Dados espaciais são fundamentais onde informações pontuais, áreas e imagens são usadas constantemente para representar valores e características. Essas informações devem estar armazenadas de forma eficiente e acessível no geobanco também.

    Uma vez instalado PostgreSQL e Postgis, o processo de criação de um banco de dados chamado leaflet com a extensão postgis é bem simples:

    você@seu.computador:~$ createdb leaflet -O user --encoding=utf-8 
    você@seu.computador:~$ psql leaflet -c "CREATE EXTENSION postgis;" 
    CREATE EXTENSION
    

    Vamos entrar no banco de dados leaflet e listar as tabelas existentes usando \d. (Para sair digite \q):
    você@seu.computador:~$ psql leaflet
    psql (11.5 (Ubuntu 11.5-0ubuntu0.19.04.1))
    Type "help" for help.
    
    leaflet=# \d
                 List of relations
     Schema |       Name        | Type  | Owner 
    --------+-------------------+-------+-------
     public | geography_columns | view  | andre
     public | geometry_columns  | view  | andre
     public | raster_columns    | view  | andre
     public | raster_overviews  | view  | andre
     public | spatial_ref_sys   | table | andre
    (5 rows)
    
    leaflet=# 
    

    A extensão Postgis cria as seguintes tabelas (‘tables’) e visões (‘views’) no geobanco:

    - geometry_columns: Visão que armazena informações de elementos 
    geométricos do tipo vector
    - geography_columns: Visão que armazena informações de elementos geográficos 
    do tipo vector
    - raster_columns: Visão que armazena informações gerais de elementos do tipo raster.
    - raster_overviews: Visão que armazena informações de ‘overviews’ de elementos do 
    tipo raster.
    - spatial_ref_sys: Tabela contendo informações dos sistemas de referência de 
    coordenadas (SRID). 

    Cobrimos aqui somente uma pequena parte para podermos dar continuidade no tópico de criarmos Mapas Interativos. Sugiro as seguintes apostilas para se aprofundar no assunto e para criar uma base sólida quando abordarmos banco de dados e geoprocessamento.

    Fundamentos de R.
    R e banco de dados espaciais.



    Módulo III - Mapas Interativos com Leaflet e Postgis.

    Parte 1 - O primeiro Mapa

    No modelo que criamos usando Go vamos adicionar um mapa base.

    Fazemos isso adicionando ao objeto mapa um objeto L.tileLayer que é uma base cartográfica que pode ser carregada dinamicamente.

    Modifique o arquivo mapa.html conforme abaixo:

    {{define "body"}}
      var map = L.map('mapa').setView([-3.09, -60.0], 12);
      var base = L.tileLayer('http://{s}.www.toolserver.org/tiles/bw-mapnik/{z}/{x}/{y}.png',{
      maxZoom: 19,
      attribution: '& copy;  <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'}).addTo(map);
    {{end}}
    

    E executamos:

    você@seu.computador:~/go/src/MapaLeaflet$ go install MapaLeaflet
    você@seu.computador:~/go/src/MapaLeaflet$ $GOPATH/bin/MapaLeaflet
    Servidor Rodando...
    

    Após iniciar o servidor, ao digitar localhost:8080/mapa.html no navegador web, teremos:

    Use o zoom + ou - para ver como o mapa interage.

    Com o objeto map 'map' e o objeto tileLayer 'base' temos o nosso primeiro mapa funcional.

    Na instrução var map = L.map('mapa').setView([-3.09, -60.0], 12); criamos o nosso objeto mapa no DOM de id 'mapa'. Este id foi definido no nosso template em um <div> e no <style> definimos sua área com 800x460 pixels onde o mapa será desenhado.

    O método setView deste objeto define que o mapa está centrado nas coordenadas fornecidas e o nível do zoom é 12.

    Existem várias opções e métodos para um objeto L.map, você pode checar a referência para este e os demais objetos neste link.

    Na instrução var base = L.tileLayer('http://{s}.www.toolserver.org/tiles/bw-mapnik/{z}/{x}/{y}.png',{ maxZoom: 19,attribution: '& copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'}).addTo(map); criamos uma base cartográfica de um provedor de 'tiles' (neste caso da OpenStreetMap) e definimos o zoom máximo em nível 19. A opção 'attribution' faz mostrar no canto inferior direito do mapa os créditos deste fornecedor de tiles.

    O Método addTo adiciona esta base ao objeto 'map'.

    Parte 2 - Integração Leaflet e Postgis

    Vamos agora mostrar como podemos interagir com o banco de dados. Primeiramente vamos carregar 3 objetos (arquivos shapefile) no nosso banco de dados PostgreSQL/postgis 'leaflet' que criamos no módulo anterior:

    Baixe os arquivos shapefile aqui:

  • pocos.shp - pocos.dbf - pocos.shx - pocos.prj - Dados ponto
  • 2dposc.shp - 2dposc.dbf - 2dposc.shx - 2dposc.prj - Dados linha
  • blocos.shp - blocos.dbf - blocos.shx - blocos.prj - Dados polígono

    Agora vamos carregar esses objetos geográficos no banco de dados 'leaflet' usando:

    você@seu.computador:~$ shp2pgsql -s 4326 -d pocos public.pocos | psql -d leaflet
    você@seu.computador:~$ shp2pgsql -s 4326 -d blocos public.blocos | psql -d leaflet
    você@seu.computador:~$ shp2pgsql -s 4326 -d 2dposc public.sismica | psql -d leaflet
    

    Temos agora 3 tabelas no banco de dados leaflet (pocos, blocos e sismica) prontos para serem usados por um mapa interativo.

  • O acesso a banco de dados pelo leaflet pode ser feito usando uma interface conhecida como AJAX (usando a linguagem PHP geralmente) ou podemos extrair diretamente um geoJSON do banco de dados via SQL chamado do programa Go e adicionar ele ao javaScript durante o carregamento da página.

    Vamos usar o segundo modo através do SQL abaixo que retorna um geoJSON da tabela 'nome' com os atributos listados em 'colunaX'

    SELECT row_to_json(fc) FROM ( 
    SELECT 'FeatureCollection' As type, array_to_json(array_agg(f)) As features FROM (
    SELECT 'Feature' As type,ST_AsGeoJSON(st_flipcoordinates(lg.geom))::json As geometry,
     row_to_json((coluna1,coluna2,...,colunaN)) 
    As properties FROM nome As lg) As f )  As fc;
    

    Vamos ver abaixo como criar o nosso mapa com os objetos geométricos do banco de dados.

    Parte 3 - Criando o Mapa com as Camadas extraídas do Banco de Dados

    Alteramos o arquivo layout.html para o mapa ocupar a tela inteira e poder ser visualizado melhor em aparelhos móveis.

    {{define "layout"}}
    <!DOCTYPE html>
    <html>
    <head>
     <title>Mapa Leaflet</title>
     <link rel="stylesheet" href="static/js/leaflet.css"/>
     <script  src="static/js/leaflet.js"></script>
     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
     <style>
     #mapa {
      height: 600px;
      width: 1000px;
     }
     </style>
    </head>
    <body>
    <div id=mapa></div>
    <script>
      var grPocos= L.layerGroup();
      var grSismica= L.layerGroup();
      var grBlocos= L.layerGroup();
      var map = L.map('mapa',{center: [-3.7, -65],zoom: 6,layers:[grBlocos,grSismica,grPocos]});
      var base = L.tileLayer('http://{s}.www.toolserver.org/tiles/bw-mapnik/{z}/{x}/{y}.png',{maxZoom: 19,attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'}).addTo(map);
      var imagem =  L.tileLayer('https://api.maptiler.com/maps/hybrid/{z}/{x}/{y}.jpg?key=krAZ650YRKtaBwGULajV',{tileSize: 512,zoomOffset: -1,minZoom: 1,attribution: '<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">© OpenStreetMap contributors</a>',crossOrigin: true});
      var baseMaps = {"Base":base,"Satélite":imagem};
      var overlayMaps = {"Poços": grPocos,"Sísmica":grSismica,"Blocos": grBlocos};
      L.control.layers(baseMaps, overlayMaps).addTo(map);
      {{template "body"}}
    </script>
    </body>
    </html>
    {{end}}
    

    Deixamos vazio o mapa.html para carregar dinamicamente com o arquivo Go.

    {{define "body"}}
    
    {{end}}
    

    servidor.go:

    package main
    import (
      "strconv"
      "net/http"
      "database/sql"
      "text/template"
      "path/filepath"
      _ "github.com/lib/pq"
    )
    const sqlInfo = "host=localhost port=5432 user=user password=segredo dbname=leaflet sslmode=disable"
    //-----------------------------------------------------------------
    func jsonizador(camada string,atributos string,nome string) string{
      db, erro := sql.Open("postgres", sqlInfo)
      if erro != nil {
        panic(erro)
      }
      defer db.Close()
      sql := "SELECT row_to_json(fc) FROM ( SELECT 'FeatureCollection' As type, array_to_json(array_agg(f)) As features FROM (SELECT 'Feature' As type, ST_AsGeoJSON(st_flipcoordinates(lg.geom))::json As geometry, row_to_json(("+atributos+")) As properties FROM "+nome+" As lg) As f )  As fc;"
      jayzon := ""
      erro = db.QueryRow(sql).Scan(&jayzon)
      if erro != nil {
         panic(erro)
      }
      um := "let "+camada +" = new L.GeoJSON("
      return um + jayzon
    }
    //------------------------------------------------------------------
    func linEpoli(dados []string,colunas int) string{
      jayzon := jsonizador(dados[0],dados[10],dados[2])
      dois := `, {coordsToLatLng: function (coords) {return new L.LatLng(coords[0], coords[1], coords[2]);}, 
        onEachFeature: function(feature, marker) {`+
        "marker.setStyle({color:"+dados[3]+",fillCollor:" + dados[4] + ",weight:" + dados[5] + ",fillOpacity:" + dados[6] +",opacity:" + dados[7] +",radius:" + dados[8] +"});"+
        "marker.bindPopup('<table style=\"font-family: times, serif; font-size:9pt\" width=300><tr><th colspan=2>'+feature.properties.f1+'</th></tr>"
      tres :=" "
      for i:=1;i<=colunas;i++{
        tres = tres + " <tr><th>"+dados[10+i]+" </th><td>'+ feature.properties.f"+strconv.Itoa(i)+"+'</td></tr>"
      }
      quatro := "</table>');marker.bindTooltip('<b style=\"font-family: times, serif; font-size:9pt\">'+feature.properties.f1+'</b>');},stroke:"+dados[9]+"}).addTo(" + dados[1] + ");"+"\n"
      return jayzon + dois  + tres + quatro
    }
    //-------------------------------------------------------------------
    func ponto(dados []string,colunas int) string{
      jayzon := jsonizador(dados[0],dados[10],dados[2])
      dois := `, {coordsToLatLng: function (coords) {return new L.LatLng(coords[0], coords[1], coords[2]);}, 
        onEachFeature: function(feature, marker) {`+
        "marker.bindPopup('<table style=\"font-family: times, serif; font-size:9pt\" width=300><tr><th colspan=2>'+feature.properties.f1+'</th></tr>"
      tres :=" "
      for i:=1;i<=colunas;i++{
        tres = tres + " <tr><th>"+dados[10+i]+" </th><td>'+ feature.properties.f"+strconv.Itoa(i)+"+'</td></tr>"
      }
      quatro := "</table>');marker.bindTooltip('<b style=\"font-family: times, serif; font-size:9pt\">'+feature.properties.f1+'</b>');},pointToLayer: function (feature, latlng) {return L.circleMarker(latlng, {color: "+dados[3]+",opacity: " + dados[7] +"," +"weight: " + dados[5] + ",fillColor: " + dados[4] + ",fillOpacity: " + dados[6] +",radius: " + dados[8] + ",stroke:"+dados[9]+"});}}).addTo(" + dados[1] + ");"+"\n"
      return jayzon + dois  + tres + quatro
    }
    //---------------------------------------------------------------------
    func mapa(w http.ResponseWriter, r *http.Request){
      bloco :=[]string{"bloco","grBlocos","blocos","'#556B2F'","'#556B2F'","0.5","0.2","0.2","0", "true", "nom_bloco,nom_bacia,operador_c,num_descob,rodada","Bloco","Bacia","Operador","Número Descobrimentos","Rodada"}
      cam1 := linEpoli(bloco,5)
      sis :=[]string{"sis2d","grSismica","sismica","'#b40401'","'#b40401'","0.5","1.0","1.0","0","true","surv_name,ident","Nome do Levantamento","Identificação"}
      cam2 := linEpoli(sis,2)
      pocos :=[]string{"pocos","grPocos","pocos","'purple'","'cyan'","0.5","0.7","1.0","2.0", "true", "po_o_opera,bacia,bloco,campo,ativo,fase,operador,po_o_anp,objetivo,in_cio,t_rmino,conclus_o,profundida,sonda","Poço", "Bacia","Bloco","Campo","Ativo","Fase","Operador","Cod ANP","Objetivo","Início","Término","Conclusão", "Profundidade","Sonda"}
      cam3 := ponto(pocos,14)
      l := filepath.Join("templates", "layout.html")
      f := filepath.Join("templates", filepath.Clean(r.URL.Path))
      tpl, _ := template.ParseFiles(l, f)
      tudo :=cam1+cam2+cam3
      tpl.Parse("{{define \"body\"}}"+tudo+"{{end}}")
      tpl.ExecuteTemplate(w, "layout", nil)
    }
    //---------------------------------------------------------------------
    func main() {
      fs := http.FileServer(http.Dir("static"))
      http.Handle("/static/", http.StripPrefix("/static/", fs))
      http.HandleFunc("/mapa.html", mapa)
      println("Servidor Rodando...")
      http.ListenAndServe(":8080", nil)
    }
    

    Antes de executar você precisa carregar o seguinte drive para Go poder enxergar o banco de dados PostgreSQL:

    você@seu.computador:~/go/src/MapaLeaflet$ go get github.com/lib/pq
    

    Vamos agora ver o nosso mapa.

    Executando o servidor e acessando no navegador da mesma forma que anteriormente veremos o seguinte mapa:

    No canto superior esquerdo vemos o controle de camadas onde podemos selecionar a base e também as camadas que queremos ver:

    Ao clicar em um dos poços, ou nos outros elementos também, um popup aparecerá com informações extraídas do banco de dados:

    Explore o mapa um pouco mais para entender a dinâmica dele.

    Os métodos bindTooltip e bindPopup servem para mostrar informações sobre cada elemento de um objeto no Leaflet. Em nosso exemplo mostramos o primeiro atributo de cada geoJSON como 'Tooltip' e os dados dos atributos carregados como 'Popup'.

    O conteudo mostrado pelo dois pode ser em html e foi o que usamos nos dois casos. Para o Popup usei uma tabela.

    bindTooltip('<b style=\"font-family: times, serif; font-size:9pt\">'+feature.properties.f1+'</b>');
    
    bindPopup('<table style=\"font-family: times, serif; font-size:9pt\" width=300><tr><th colspan=2>'+feature.properties.f1+'</th></tr>
    <tr><th>"+dados[10+i]+" </th><td>'+ feature.properties.f2+'</td></tr>
    <tr><th>"+dados[10+i]+" </th><td>'+ feature.properties.f3+'</td></tr>
    ...
    </table>');
    

    O 'layerGroup' é usado para agrupar uma ou mais camadas em um determinado objeto, nesse exemplo criamos três 'layerGroups', um para cada geoJSON extraído do banco de dados. Isso foi feito para podermos incluir cada um deles no controle de camadas 'L.control.layers'.

    O 'L.control.layers' é usado para mostrar ou esconder os 'layerGroups' e também para selecionar qual 'tile' é visível, caso exista mais de um.

    Parte 4 - Plugins

    Um plugin é um objeto complementar para o leaflet geralmente desenvolvido por contribuidores externos para os usuários do leaflet.

    Baixe os arquivos desta página para o diretório js.

    Adicione as seguintes linhas no arquivo layout.html as duas primeiras no HEAD e a terceira logo após L.control.layers(baseMaps, overlayMaps).addTo(map);

    <link rel="stylesheet" href="static/js/leaflet.fullscreen.css"/>
    <script src="static/js/Leaflet.fullscreen.js"></script>
    
    map.addControl(new L.Control.Fullscreen());
    

    O mapa agora poderá ser visto no modo tela cheia:

    Outros plugins funcionam de forma similar.

    A base para criar mapas interativos foi aqui apresentada, agora depende só de você se aprofundar no assunto e desenvolver ótimos mapas.



    Módulo IV - Geoprocessamento.

    Parte 1 - R e Geoprocessamento

    Nesta breve introdução ao geoprocessamento vamos falar de dois pacotes básicos que iremos usar com R para carregar e manipular imagens. Estes pacotes são o raster e o rgdal. Instale os dois em R usando:

    > install.packages('raster')
    > install.packages('rgdal')
    

    Vamos também carregar as seguintes imagens Sentinel 2 na resolução de 20 metros por pixel, originalmente as bandas 2, 3, 4 e 8 tem resolução de 10 metros mas foram ajustadas para 20 metros que é a resolução das demais bandas (5, 6, 7 ,8a, 11 e 12). Também baixe o modelo de elevação na resolução de 30 metros.

  • Banda 2
  • Banda 3
  • Banda 4
  • Banda 5
  • Banda 6
  • Banda 7
  • Banda 8
  • Banda 8A
  • Banda 11
  • Banda 12
  • Modelo de Elevação Digital (DEM)
  • Parte 2 - Imagens Multiespectrais

    A banda 4 corresponde ao comprimento de onda do vermelho, a 3 do verde e a 2 do azul. Ao criarmos uma imagem RGB (red, green, blue) com essas respectivas bandas, nós criamos o que chamamos de composição de cor verdadeira (true color composition - tcc em inglês).

    Caso prescise de maiores fundamentos em R, as apostilas listadas ao lado podem te ajudar.

    > library(raster)
    Loading required package: sp
    > tcc<-stack('b4lr.tif','b3lr.tif','b2lr.tif')
    > plotRGB(tcc,stretch='lin')
    

    Uma composição vnir (very near infrared) é usada para avaliar vegetação. Executamos uma composição de cor false (fcc em inglês) com as bandas 7, 6 e 5. Note que a vegetação saudável é mostrada em amarelo.

    > vnir<-stack('b7.tif','b6.tif','b5.tif')
    > plotRGB(vnir,stretch='lin')
    

    A faixa espectral correspondente ao infravermelho de ondas curtas (swir na sigla em inglês) e bastante sensível para mudanças de composição de solo e rochas. Note a separação entre as principais unidades geológicas com a composição abaixo usando as bandas 12, 11 e 8 nos canais RGB respectivamente.

    > swir<-stack('b12.tif','b11.tif','b8lr.tif')
    > plotRGB(swir,stretch='lin')
    

    Essas composições coloridas RGB são alguns exemplos. Experimente diferentes composições de bandas e compare os resultados.

    Vamos agora examinar um Modelo de Elevação Digital e os produtos que podemos extrair dele.

    Parte 3 - DEM

    Um modelo de elevação digital ou DEM é uma imagem raster onde cada pixel corresponde a um valor de elevação. O dado de estamos usando é da agência espacial japonesa JAXA do programa "ALOS World 3D - 30m (AW3D30)" com 30 metros de resolução de pixel.

    > dem<-raster('dem.tif')
    > plot(dem,col=grey(0:100/100),main='Modelo de elevação Digital - DEM')
    

    Além da imagem acima, podemos gerar a partir do DEM diversos produtos com a ajuda de R, vamos ver quais eles são aqui:

    Slope e Aspect

    A inclinação é o plano de tangência em um determinado ponto da superfície e é dividido em dois parâmetros:

  • Gradiente ou derivada ou queda: Aqui referido como 'Slope' é o ângulo que a superficie faz com o plano horizontal em radianos de 0 a pi/2.
  • Aspecto: Aqui referido como 'aspect' é a direção do megulho máximo deste plano em radianos de 0 a 2*pi em relação ao norte.
    > gradient<-terrain(dem,opt='slope',unit='radians')
    > aspect<-terrain(dem,opt='aspect',unit='radians')
    > plot(gradient,zlim=c(0,1.6),axes=FALSE)
    > plot(aspect,zlim=c(0,6.3),axes=FALSE)
    

    Slope

    Aspect

    TPI

    TPI ou índice de posição topográfica é a diferença entre o valor desta célula com a média das células a seu redor. Valores positivos indicam que essa célula é mais alta , negativo mais baixo e zero próximo de zero indicam uma superficie com um gradiente constante.

    > tpi<-terrain(dem,opt='TPI')
    > plot(tpi,zlim=c(-12,12),axes=FALSE)
    

    TRI

    Terrain Ruggedness Index (TRI) é a média da diferença absoluta entre os valores de uma célula e o valor das oito células (ou pixels) adjacentes a ele.

    > tri<-terrain(dem,opt='TRI')
    > plot(tri,zlim=c(0,30),axes=FALSE)
    

    Roughness

    Rughnees mostra a rugosidade do terreno. É expresso pela diferença dos valores máximo e do mínimo dos 8 pixels adjacentes

    > roughness<-terrain(dem,opt='roughness')
    > plot(roughness,zlim=c(0,55),axes=FALSE) 
    

    Flow

    O fluxo (flow) retorna a direção do fluxo. Ou seja, a direção de maior queda na elevação (ou o menor inclinação se todos os valores vizinhos forem mais elevados).

    > flow<-terrain(dem,opt='flowdir',unit='radians')
    > plot(flow,zlim=c(0,20),axes=FALSE)
    

  • O hillshade mostra o relevo com sombreamento, ele e gerado usando o slope e o aspecto criados acima .

    > hillshade<-hillShade(gradient,aspect,angle=45,direction=270,normalize= TRUE)
    > plot(hillshade,col=grey(0:100/100),zlim=c(0,250))
    

    Sobrepondo o hillshade na composição swir para resaltar o relevo.

    > plotRGB(swir,stretch='lin')
    > plot(hillshade,add=TRUE,legend=FALSE,axes=FALSE,col=grey(0.4:0.9),alpha=0.3,zlim=c(100,200))
    

    Você pode gravar esses dados criados acima no forma de um arquivo geotiff.

    > library(rgdal)
    > writeRaster(hillshade, filename='hillshade.tif', drive='GeoTiff')
    

    Parte 4 - PCA

    O PCA ou análise de componentes principais é um procedimento estatístico que usa uma transformação ortogonal para converter um conjuto de observações de variáveis possívelmente correlacionáveis em um conjunto de varíaveis linearmente não correlacionáveis chamado de componentes principais.

    Se existem n observações de p variáveis então o número de distintos componentes princiais será o menor valor entre n-1 e p. Esta transformação é definida de tal maneira que o primeiro componente principal tenha a maior variância possível e cada componente seguinte tenha a maior variância respeitando que seja ortogonal ao componente anterior.

    Primeiro vamos criar um raster com as bandas 2, 3, 4, 5, 6, 7, 8, 11, e 12 onde faremos a análise de componentes principais;

    > library(raster)
    Loading required package: sp
    > todas<-stack('b2lr.tif','b3lr.tif','b4lr.tif','b5.tif','b6.tif','b7.tif','b8lr.tif','b11.tif','b12.tif')
    > todas
    class      : RasterStack 
    dimensions : 5490, 5490, 30140100, 9  (nrow, ncol, ncell, nlayers)
    resolution : 20, 20  (x, y)
    extent     : 499980, 609780, 7990240, 8100040  (xmin, xmax, ymin, ymax)
    crs        : +proj=utm +zone=23 +south +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
    names      :  b2lr,  b3lr,  b4lr,    b5,    b6,    b7,  b8lr,   b11,   b12 
    min values :     0,     0,     0,     0,     0,     0,     0,     0,     0 
    max values : 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535 
    

    Vamos agora criar uma amostra do nosso conjunto de dados (população) aleatoriamente com um tamanho que seja representativo desta população. Lembre-se que análises estatísticas envolvendo imagens tem um volume de dados muito grande e consequentemente demoram um pouco (25 a 30 minutos) para serem processados, seja paciente!

    > set.seed(1)
    > amostra<-sampleRandom(todas,300000)
    

    Agora vamos efetuar o PCA na amostra para termos os preditores de cada componente e aplicar estes na nossa população gerando os nove componentes principais de nossa polulação:

    > pca <- prcomp(amostra, scale = TRUE)
    > pca
    Standard deviations (1, .., p=9):
    [1] 2.4938825 1.4405068 0.6506558 0.3245173 0.2507924 0.2101730 0.1725472
    [8] 0.1521670 0.1297261
    
    Rotation (n x k) = (9 x 9):
                PC1         PC2          PC3          PC4         PC5        PC6
    b2lr -0.3500839  0.21786006 -0.487521294  0.451152030 -0.37757283 -0.2949587
    b3lr -0.3703183  0.14580034 -0.445177787 -0.009218293  0.00742522  0.2270376
    b4lr -0.3709968  0.18873698 -0.240328170 -0.331789692  0.65117918  0.2191660
    b5   -0.3833114  0.07602207  0.178701902 -0.636503618 -0.27668479 -0.5143922
    b6   -0.3020342 -0.44426207  0.045971733 -0.193578987 -0.30085933  0.2728383
    b7   -0.2546075 -0.53012978  0.017193159  0.049618293 -0.11197494  0.2017823
    b8lr -0.2447077 -0.53589076  0.008766872  0.319041692  0.39225323 -0.3215784
    b11  -0.3505529  0.21457965  0.520360445  0.306977293  0.24457257 -0.2678492
    b12  -0.3419363  0.27972942  0.448538596  0.212598578 -0.20015435  0.5084364
                 PC7        PC8           PC9
    b2lr  0.33783895 -0.1951474  0.0835675215
    b3lr -0.69691336  0.2935101 -0.1410700518
    b4lr  0.37005967 -0.2149661  0.0606220352
    b5    0.06198892  0.2171109 -0.1344925163
    b6   -0.12450615 -0.2888241  0.6387034513
    b7    0.10786017 -0.2715668 -0.7160607841
    b8lr  0.08512160  0.5058650  0.1750840968
    b11  -0.37475020 -0.4405098 -0.0035602696
    b12   0.29081065  0.4186952 -0.0004243326
    > pci1<-predict(todas,pca,index=1)
    > pci2<-predict(todas,pca,index=2)
    > pci3<-predict(todas,pca,index=3)
    > pci4<-predict(todas,pca,index=4)
    > pci5<-predict(todas,pca,index=5)
    > pci6<-predict(todas,pca,index=6)
    > pci7<-predict(todas,pca,index=7)
    > pci8<-predict(todas,pca,index=8)
    > pci9<-predict(todas,pca,index=9)
    

    E agora vamos plotar cada um dos componentes principais criados usando:

    > par(mfrow=c(3,3))
    > plot(pci1,axes=FALSE,col=grey(0:100/100))
    > plot(pci2,axes=FALSE,col=grey(0:100/100))
    > plot(pci3,axes=FALSE,col=grey(0:100/100))
    > plot(pci4,axes=FALSE,col=grey(0:100/100))
    > plot(pci5,axes=FALSE,col=grey(0:100/100))
    > plot(pci6,axes=FALSE,col=grey(0:100/100))
    > plot(pci7,axes=FALSE,col=grey(0:100/100))
    > plot(pci8,axes=FALSE,col=grey(0:100/100))
    > plot(pci9,axes=FALSE,col=grey(0:100/100))
    

    Vamos gravar cada um destes componentes como imagem raster para uso posterior usando:

    > rm(amostra)
    > library(rgdal)
    > writeRaster(pci1,filename='pca1.tif',driver='Geotiff')
    > writeRaster(pci2,filename='pca2.tif',driver='Geotiff')
    > writeRaster(pci3,filename='pca3.tif',driver='Geotiff')
    > writeRaster(pci4,filename='pca4.tif',driver='Geotiff')
    > writeRaster(pci5,filename='pca5.tif',driver='Geotiff')
    > writeRaster(pci6,filename='pca6.tif',driver='Geotiff')
    > writeRaster(pci7,filename='pca7.tif',driver='Geotiff')
    > writeRaster(pci8,filename='pca8.tif',driver='Geotiff')
    > writeRaster(pci9,filename='pca9.tif',driver='Geotiff')
    

    Parte 5 - IHS

    Vamos agora criar imagens do tipo IHS (intensidade, matiz e saturação) a partir de uma composição RGB. Este tipo de procedimento é bastante usado para gerar uma maior resposta espectral em alguns caso, principalmente nas imagens H e S.

    Vamos gerar uma composição RGB usando SWIR (bandas 12,11 e 8) nos canais RGB inicialmente e proceder com a geração de imagens RGB a partir dela.

    > library(raster)
    > swir<-stack('b12.tif','b11.tif','b8lr.tif')
    

    Precisaremos de normalizar estas imagens para valores entre 0 e 1, fazemos isso usando:

    > Nor<-swir/65535
    > Nor
    class      : RasterBrick 
    dimensions : 5490, 5490, 30140100, 3  (nrow, ncol, ncell, nlayers)
    resolution : 20, 20  (x, y)
    extent     : 499980, 609780, 7990240, 8100040  (xmin, xmax, ymin, ymax)
    crs        : +proj=utm +zone=23 +south +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
    source     : /tmp/RtmpGjvJwB/raster/r_tmp_2019-10-16_102611_32256_56357.grd 
    names      :        b12,        b11,       b8lr 
    min values :          0,          0,          0 
    max values : 0.38136873, 0.19211109, 0.08664073 
    

    Convertemos de RGB par IHS usando as seguintes fórmulas:

    I=(R+G+B)/3
    S=1-(3/(R+G+B))*mínimo(R,G,B)
    H*=acos(0.5*((R-G))+(R-B)))/sqrt((R-B)²+((R-G)*(G-B)) ) ))
    > I<-(Nor[[1]]+Nor[[2]]+Nor[[3]])/3
    > S<-1-(3/(Nor[[1]]+Nor[[2]]+Nor[[3]]))*min(Nor[[1]],Nor[[2]],Nor[[3]])
    > H<- acos((0.5*((Nor[[1]]-Nor[[2]])+(Nor[[1]]-Nor[[3]])))/(sqrt((Nor[[1]]-Nor[[2]])^2+((Nor[[1]]-Nor[[3]])*(Nor[[2]]-Nor[[3]])))))
    

    Plotando as imagens I, H e S separadamente

    > par(mfrow=c(1,3))
    > plot(I,axes=FALSE,legend=FALSE,col=grey(0:100/100))
    > plot(H,axes=FALSE,legend=FALSE,col=grey(0:100/100))
    > plot(S,axes=FALSE,legend=FALSE,col=grey(0:100/100))
    

    Criando uma Composição IHS

    > ihs<-brick(I,H,S)
    > plotRGB(ihs,stretch='lin')
    

    Vamos agorar salvar cada uma dessas imagens para uso futuro usando:

    > library(rgdal)
    > writeRaster(I,filename='I.tif',driver='Geotiff')
    > writeRaster(H,filename='H.tif',driver='Geotiff')
    > writeRaster(S,filename='S.tif',driver='Geotiff')
    

    Parte 6 - Composição de Imagens

    Carregaremos as três imagens IHS, os primeiros cinco componentes principais e a imagem de sombra de relevo para criarmos algumas composições.

    > library(raster)
    > ihs<-stack('I.tif','H.tif','S.tif')
    > pca<-stack('pca1.tif','pca2.tif','pca3.tif','pca4.tif','pca5.tif')
    > relevo<-raster('hillshade.tif')
    

    Criaremos 4 combinações distintas com essas bandas. Experimente novas combinações.

    > par(mfrow=c(2,2))
    > PC1PC2H<-stack(pca[[1]],pca[[2]],ihs[[2]])
    > plotRGB(PC1PC2H,stretch='lin')
    > PC1PC2S<-stack(pca[[1]],pca[[2]],ihs[[3]])
    > plotRGB(PC1PC2S,stretch='lin')
    > PC1PC5H<-stack(pca[[1]],pca[[5]],ihs[[2]])
    > plotRGB(PC1PC5H,stretch='lin')
    > PC1PC5S<-stack(pca[[1]],pca[[5]],ihs[[3]])
    > plotRGB(PC1PC5S,stretch='lin')
    

    Escolhi a primeira das imagens acima que apresentou melhor resposta espectral e associei ela com a sombra de relevo. Veja o resultado final abaixo:

    > par(mfrow=c(1,1))
    > plotRGB(PC1PC2H,stretch='lin')
    > plot(relevo,add=TRUE,legend=FALSE,axes=FALSE,col=grey(0.4:0.9),alpha=0.3,zlim=c(100,200))
    

    Parte 7 - Razão entre Bandas

    Razão entre bandas é bastante usado em geoprocessamento, principalmente para se criar índices. Vamos aqui ver alguns desses índices sendo criados usando razão entre bandas.

    NDVI ou índice de vegetação normalizado resalta a diferença de resposta de clorofila em plantas nessas duas bandas, vegetação saudável (verde) tem boa reflectância para as duas bandas e vegetação seca somente para o infravermelho. O índice , através da razão, fornece valores altos para vegetação mais saudável.

    > library(raster)
    > b4<-raster('b4lr.tif')
    > b8<-raster('b8lr.tif')
    > ndvi<-(b8-b4)/(b8+b4)
    > co<-colorRampPalette(c('gray','yellow','green'), bias = 1, space = c("rgb", "Lab"),interpolate = c("linear", "spline"), alpha = FALSE)
    > plot(ndvi,col=co(24),zlim=c(-0.4,0.7))
    

    NDMI ou índice de humidade normalizado resalta a diferença de resposta da presença de humidade em vegetação saudável nessas duas bandas. O índice , através da razão, fornece valores altos para zonas com água e de maior humidade.

    > library(raster)
    > b11<-raster('b11.tif')
    > b8<-raster('b8lr.tif')
    > ndmi<-(b8-b11)/(b8+b11)
    > co<-colorRampPalette(c('gray','yellow','green'), bias = 1, space = c("rgb", "Lab"),interpolate = c("linear", "spline"), alpha = FALSE)
    > plot(ndmi,col=co(24),zlim=c(-0.4,0.7))
    

    NDWI ou índice de água normalizado resalta a presença de água nessas duas bandas. O índice , através da razão, fornece valores altos para zonas com água .

    > library(raster)
    > b5<-raster('b5.tif')
    > b3<-raster('b3lr.tif')
    > ndwi<-(b3-b5)/(b3+b5)
    > co<-colorRampPalette(c('gray','blue'), bias = 1, space = c("rgb", "Lab"),interpolate = c("linear", "spline"), alpha = FALSE)
    > plot(ndwi,col=co(24),zlim=c(0,1))