Como criar um relevo em 3D com sombras no R usando o pacote rayshader?
Representar relevos em 2 dimensões não tem muita graça. Veja como criar seus relevos em 3D usando o pacote rayshader no R. Acrescente sombras e água, rotacione e mude o angulo de iluminação.
Há várias formas de representar o relevo de um determinada área, podemos utilizar curvas de nível, cores ou representações em 3 dimensões.
Tais representações em 3D podem ser obtidas em diferentes softwares, como no GRASS GIS, no ArcScene do ArcGIS e com o Qgis2threejs no QGIS. Desta lista, o R, normalmente utilizado para o desenvolvimento de análises estatísticas, também pode ser utilizado.
O pesquisador Tyler Morgan-Wall desenvolveu o pacote rayshader com o objetivo de criar esses mapas em 3D, mostrando o relevo com sombras, perspectiva e diferentes focos.
Agora que sabemos das potencialidades deste pacote, vamos criar nosso próprio relevo. Você pode realizar o download de modelos digitais de terreno (MDT) no Earth Explorer ou no SIG-SC (válido somente para Santa Catarina).
Obviamente, antes de iniciarmos, vamos instalar e carregar o pacote rayshader e outros pacotes necessários no nosso R com o código abaixo.
install.packages("rayshader") install.packages("rgdal") library(rayshader) library(rgdal)
Após rodar esse comando, o R irá realizar o download de vários pacotes, dos quais o rayshader depende para funcionar.
Agora, vamos definir nosso ambiente de trabalho para evitarmos ter que escrever o caminho para nossos arquivos todo momento e vamos carregar nosso MDT.
Cuidado com arquivos de MDTs muito pesados, pois isso poderá dificultar o carregamento e processamento dele. Tenha um bom processador para executar esse tipo de arquivo.
setwd("C:/Users/ferna/Desktop/R/") # Define nosso ambiente de trabalho mdt_local <- raster::raster("MDT10.tif") mat_elev <- matrix(raster::extract(mdt_local, raster::extent(mdt_local), buffer=1000), nrow = ncol(mdt_local), ncol = nrow(mdt_local))
Note que utilizamos dois “Dois Pontos” para utilizar as funções do pacote Raster sem carregá-lo. Na função raster(), salvamos nosso MDT em uma variável e depois convertemos ela para matriz.
Utilizamos a função extract() para tirar os dados do nosso MDT (elevação, tamanho) e indicamos o número de linhas (nrow) e de colunas (ncol).
Agora que carregamos nosso relevo, vamos visualizá-lo. Perceba que utilizamos o chamado operador Pipe para criar uma sequência de comandos de forma que o resultado da primeira linha é utilizado na segunda, e o resultado da segunda é usado na terceira.
mat_elev %>% sphere_shade(texture = "desert") %>% plot_map()
Neste exemplo, utilizamos a textura “desert”, mas outras também são possíveis (e.g. “imhof1”, “bw” e “unicorn”).
Note que, conforme o tamanho do pixel é aumentado, há um maior destaque das sombras no relevo (mas se ele for grande demais, perdemos os detalhes do relevo).
Você pode modificar o tamanho do pixel do MDT usando softwares como QGIS (Exportando Raster) e ArcGIS (com a ferramenta Resample).
Dentro do comando sphere_shade() também é possível modificar o ângulo de incidência da luz solar, basta inserir o parâmetro sunangle e igualar ele ao ângulo de interesse (e.g. sphere_angle(sunangle = 45, texture = “desert”).
Também é possível adicionar uma camada de água utilizando as funções:
- add_water()
- detect_water()
- render_water()
Porém, o algoritmo que a função detect_water() utiliza não demarcou o local que deveria ter um rio, mas você pode testar o código no seu MDT.
mat_elev %>% sphere_shade(texture = "desert") %>% add_water(detect_water(mat_elev), color = "desert") %>% plot_map()
No próximo passo, iremos gerar mais alguns tipos de sombra usando a função ray_shade() e ambient_shade().
mat_ray <- ray_shade(mat_elev, lambert = TRUE) mat_amb <- ambient_shade(mat_elev) mat_elev %>% sphere_shade(texture = "desert") %>% #add_water(detect_water(mat_elev), color = "desert") %>% add_shadow(mat_ray, 0.7) %>% add_shadow(mat_amb, 0.7) %>% plot_map()
O resultado das duas funções é apresentado na figura abaixo, onde a primeira imagem representa somente a função ray_shade() e a segunda uma combinação da primeira função e da ambient_shade().
Agora que aprendemos como carregar nosso raster, mostrar ele com diferentes texturas e adicionar sombras, vamos usar a função plot_3d(). Nesta função, temos vários parâmetros para serem configurados, os quais são apresentados abaixo:
- zscale: Este parâmetro controla o exagero vertical, quanto maior for o número, maior é a distância entre os pixels (resultando em elevações menos exageradas);
- theta: Rotação no eixo Z;
- zoom: Fator de zoom;
- phi: ângulo azimute;
- windowsize: Tamanho da janela que irá gerar o relevo 3D.
Com o código abaixo, iremos gerar o relevo em três dimensões.
mat_ray <- ray_shade(mat_elev, zscale=3,maxsearch = 300) mat_amb <- ambient_shade(mat_elev) mat_elev %>% sphere_shade(texture = "desert") %>% #add_water(detect_water(mat_elev), color = "desert") %>% add_shadow(mat_ray, 0.7) %>% add_shadow(mat_amb, 0.7) %>% #plot_map() plot_3d(mat_elev,zscale=3,fov=0,theta=135,zoom=0.75,phi=45, windowsize = c(800,600))
O resultado deste código é apresentado abaixo.
Já havíamos comentado de como inserir uma camada d’água no nosso relevo, mas também é possível adicionar após gerar ele usando os parâmetros como “water” (para carregar a camada) e “waterdepth” (determina a cota da lâmina d’água) na função plot_3d().
mat_elev %>% sphere_shade(texture = "imhof1") %>% #add_water(detect_water(mat_elev), color = "desert") %>% add_shadow(mat_ray, 0.7) %>% add_shadow(mat_amb, 0.7) %>% #plot_map() plot_3d(mat_elev,zscale=3,fov=0,theta=135,zoom=0.75,phi=45, windowsize = c(800,600), water=TRUE, waterdepth=80, wateralpha=0.5, watercolor="lightblue", waterlinecolor = "white", waterlinealpha = 0.3)
O resultado deste procedimento é apresentado na figura abaixo.
Veja que a cota de água é constante ao longo do relevo, o que, neste caso, acaba representando incorretamente a camada de água.
Também é possível utilizar o pacote rayshader para criar objetos para serem impressos em impressoras 3D, basta utilizar a função save_3dprint(). Mais detalhes no blog do Tyler Morgan-Wall.
Agora com o código pronto, podemos pegar outros MDTs e gerar nossos relevos em 3D, confira abaixo o relevo da bacia hidrográfica do rio Urussanga.
O rayshader também tem algumas funcionalidades que estão em desenvolvimento, tais como inserir rótulos e desfocar a imagem. Porém, para usá-las, você precisa instalar a versão do pacote em desenvolvimento, que é realizada usando os comandos abaixo.
install.packages('devtools') devtools::install_github("tylermorganwall/rayshader")
Ficou com alguma dúvida? Deixe ela nos comentários que estaremos respondendo assim que possível e se o artigo te ajudou, compartilhe ele.
Fontes Consultadas. rayshader github. Disponível em: <https://github.com/tylermorganwall/rayshader>. Acesso em 22 dez. 2018. Confira também o twitter do desenvolver do pacote: Tyler Morgan-Wall.
Boa Noite. Amei o post, me ajudou muito. Só fiquei na dúvida de como faço pra salvar a imagem?
Boa tarde Krisnara,
Obrigado pelo comentário.
No RStudio, o relevo em 3D irá aparecer na janela de plotagem (Plot) e poderá ser exportado como imagem clicando em “Export” e “Save as Image”.
Porém, no uso da função plot_3d(), você pode dar um print screen. Considerando que o pacote rayshader usa o rgl na função plot_3d(), é possível que esse comando funcione para exportar o gráfico em 3d como imagem: rgl.snapshot(filename = “plot.png”) (Fonte: http://www.sthda.com/english/wiki/a-complete-guide-to-3d-visualization-device-system-in-r-r-software-and-data-visualization#export-images-as-png-or-pdf).
Trabalhando apenas com código, acredito que seja possível salvar como imagem usando funções do tipo png() ou jpg().