1 Introduction

Dalam dunia pemodelan geospasial, visualisasi data spasial topografi 3D sangatlah penting. Pada contoh kali ini, kita akan membahas bagaimana melakukan visualisasi dengan menggunakan library rayshader di R dan menghasilkan output yang indah.

Rayshader adalah sebuah library open source yang digunakan dalam bahasa pemrograman R untuk menghasilkan visualisasi peta 3D dan pemodelan topografi dengan tampilan realistis. Library ini diciptakan oleh Tyler Morgan-Wall dan merupakan salah satu library yang paling populer digunakan untuk visualisasi topografi 3D di R. Library ini memungkinkan kita untuk membuat peta, model gunung, lereng, dan relief lainnya dengan efek 3D yang memukau.

2 Library dan Setup

Adapun library yang dibutuhkan dalam pembuatan topografi 3D yakni sebagai berikut:

library(rayshader)
library(raster)
library(dplyr)
library(ggplot2)
library(car)
library(leaflet)
library(RColorBrewer)
library(magick)
library(animation)
library(osmdata)
library(sf)
library(viridis) 
library(terra)
library(av)

3 Pembuatan Peta menggunakan library rayshader

Mari kita membuat sebuah peta menggunakan library rayshader dalam bahasa pemrograman R. rayshader adalah sebuah paket yang digunakan untuk membuat visualisasi peta 3D dari data elevasi topografi. Dalam contoh ini, kita akan menggunakan data elevasi topografi dari situs web “tanahair.indonesia.go.id” dan memprosesnya menggunakan R.

Berikut adalah langkah-langkahnya :

  1. Membaca Data TIFF: Pertama, kita perlu membaca data TIFF yang akan digunakan. Data TIFF ini berisi informasi elevasi topografi. Kode di bawah ini digunakan untuk membaca data TIFF tersebut.

DATASET DEMNAS

Kita dapat membaca data TIFF dengan rast() dari library terra. Berikut contoh kode lengkapnya:

# Baca data TIFF
datatiffpare <-  rast("dataset/DEMNAS_Parepare.tif")
  1. Cek Spesifikasi Data: Setelah membaca data, kita dapat memeriksa spesifikasi data tersebut, seperti batas-batas area yang dicakup oleh data tersebut menggunakan fungsi ext(), menggunakan kode berikut:
# Cek Spesifikasi Data
ext(datatiffpare)
#> SpatExtent : 119.625, 119.75, -4.125, -4 (xmin, xmax, ymin, ymax)

Ini akan menampilkan informasi mengenai batas-batas data seperti koordinat minimum dan maksimum.

  1. Definisi Extent Baru (Bounding Box): Berikutnya, kita akan mendefinisikan extent baru atau bounding box untuk area yang akan di-crop dari data. Anda dapat mengganti nilai-nilai koordinat sesuai dengan area yang ingin kita fokuskan. Untuk mendapatkan nilai-nilai koordinatnya, kita bisa mengaksesnya di situs (http://bboxfinder.com/). Dalam contoh ini, extent baru didefinisikan sebagai berikut:
# Definisi extent baru/bounding box area baru untuk cropping
new_extent_pare <- ext(119.625, 119.7, -4.08, -4)
  1. Memotong Data Raster: Dengan extent baru yang telah didefinisikan, kita dapat memotong data raster asli untuk mendapatkan data yang sesuai dengan extent tersebut. Ini dilakukan dengan menggunakan fungsi crop.
# Memotong data raster
croptiff_pare <- crop(datatiffpare, new_extent_pare)
  1. Menyimpan Data yang Telah Dipotong: Data yang telah dipotong dapat disimpan dalam format TIFF yang baru dengan menggunakan kode berikut:
# writeRaster(croptiff_pare, filename = "Hasil_crop_pare.tif", overwrite = TRUE)

Dalam kode di atas, data dipotong disimpan dengan nama file “Hasil_crop_pare.tif”.

  1. Membuat Plot Peta: Terakhir, kita dapat membuat plot peta menggunakan data yang telah dipotong. Dalam contoh ini, kita menggunakan fungsi plot untuk membuat peta.
plot(croptiff_pare)

Kode di atas akan menghasilkan plot peta 2D dari area yang telah dipotong dengan warna yang sesuai.


3.1 Pembuatan Visualisasi 2D

Berikut adalah langkah-langkah untuk membuat visualisasi peta dengan penerapan berbagai fungsi dan pemrosesan data:

Kode yang akan digunakan menggunakan bantuan berbagai paket seperti raster, sp, leaflet, dan lainnya.

  1. Penentuan Batasan Area (Bounding Box):
    • Kode pertama ini menentukan batasan area yang akan digunakan dalam visualisasi peta. Batasan ini didefinisikan dengan menyimpan lintang (lat_range) dan bujur (long_range) dalam bentuk rentang koordinat geografis. Dalam kasus ini, area yang dibatasi adalah lintang -8.5 hingga -8.3 dan bujur 116.3 hingga 116.5. Bisa didapatkan secara otomatis dari bboxfinder.
# add bounding box to add osm map
lat_range_pare  <-  c(-4.08, -4)
long_range_pare <- c(119.625, 119.7)
  1. Konversi Data Raster Menjadi Matriks:
    • Kode ini mengambil data raster croptiff_pare dan mengonversinya ke dalam bentuk matriks dengan menggunakan fungsi raster_to_matrix. Hasil konversi disimpan dalam variabel tiffmat_pare.
# Konversi Data
tiffmat_pare <- raster_to_matrix(croptiff_pare)
  1. Resize Matriks:
    • Selanjutnya, kode ini mengubah ukuran matriks yang telah dihasilkan (tiffmat_pare) dengan faktor resize sebesar 0.4. Hasil resize disimpan dalam variabel tiff_pare. Namun, pada kode yang diberikan, variabel croptiff_pare yang digunakan di kode ini tidak didefinisikan sebelumnya. Pastikan croptiff_pare adalah data raster yang telah dibaca dan diproses sebelumnya.
# Resize
tiff_pare <- resize_matrix(heightmap = tiffmat_pare, scale = 0.4)
  1. Input Data Raster ke Leaflet:
    • Terakhir, mari kita coba memasukkan data raster ke dalam leaflet agar bisa langsung mendapatkan lokasi dan basemap menggunakan library leaflet dengan input data raster tiff.
# Definisikan palet warna yang merepresentasikan elevasi
palet <-rev(terrain.colors(50))


# Definisikan palette warna berdasarkan elevasi dalam data raster
pal <- colorNumeric(palet,
                    values(croptiff_pare),
                    na.color = "transparent")

# Konversi data raster dari terra ke raster
croptiff_raster <- raster(croptiff_pare)

# leaflet() %>%
#   addProviderTiles("Stamen.Terrain") %>%
#   addRasterImage(croptiff_raster, colors = pal, opacity = 0.6) %>%
#   addLegend(pal = pal, values = values(croptiff), title = "Elevasi")

leaflet() %>%
  addProviderTiles("Stamen.Terrain") %>%
  addRasterImage(croptiff_raster, colors = pal, opacity = 0.6) %>%
  addLegend(pal=pal, values = values(croptiff_pare), title = "Elevasi")
# # Install dan load library mapview
# library(mapview)
# # Membuat tampilan peta dengan mapview
# map <- mapview() %>% 
#   addTiles("Stamen.Terrain") +
#   addMarkers(lng = 116.458, lat = -8.411, popup = "Gunung Rinjani") +
#   addRasterImage(croptiff, col = pal, opacity = 0.6) +
#   addLegend(colors = pal, values = values(croptiff), title = "Elevasi") +
#   addMouseCoordinates()

4 Intro to Rayshader Packages

Berikut ini bagian dari penggunaan paket rayshader di R untuk membuat visualisasi peta 3D. Paket ini memungkinkan kita untuk membuat visualisasi topografi berdasarkan data elevasi. Di bawah ini, akan dijelaskan setiap blok kode secara terpisah:

  1. Penggunaan height_shade() dan plot_map():
# Code here
tiff_pare %>% 
  height_shade() %>% 
  plot_map()

Kode di atas digunakan untuk menghasilkan visualisasi 3D dari data elevasi yang disimpan dalam tiff_pare. height_shade() digunakan untuk memberikan bayangan dan highlight pada visualisasi berdasarkan elevasi, sehingga memberikan efek 3D yang lebih baik. Kemudian, plot_map() digunakan untuk menggambar peta hasil visualisasi tersebut.

  1. Penggunaan Tekstur dengan sphere_shade():
# Add tekstur
tiff_pare %>% 
  sphere_shade(texture = "imhof1") %>% 
  plot_map()

Kode di atas menunjukkan penggunaan tekstur dengan sphere_shade(). Fungsi ini menghasilkan efek tekstur pada visualisasi 3D. Dalam contoh ini, tekstur “imhof1” digunakan. Setelah menerapkan tekstur, plot_map() digunakan lagi untuk menggambar visualisasi 3D dengan tekstur.

  1. Penggunaan Lapisan Air dengan detect_water() dan add_water():
# Add water
tiff_pare %>% 
  sphere_shade(texture = "imhof1") %>% 
  add_water(detect_water(tiff_pare),color = "imhof1") %>% 
  plot_map()

Kode ini menambahkan lapisan air ke visualisasi. detect_water() digunakan untuk mendeteksi area-air dalam data tiff_pare, dan kemudian add_water() digunakan untuk menambahkan lapisan air tersebut ke visualisasi dengan warna yang sesuai. Tampak kode di atas gagal menangkap visual air pada map parepare.

  1. Penggunaan Bayangan dengan add_shadow() dan ray_shade():
# Add sun direction effect
tiff_pare %>% 
  sphere_shade(texture = "imhof1") %>% 
  add_water(detect_water(tiff_pare), color = "imhof1") %>% 
  add_shadow(ray_shade(tiff_pare)) %>% 
  plot_map()


5 Peta 3D

Mari kita coba buat visualisasi peta diatas menjadi peta 3D dengan berbagai efek seperti tekstur, lapisan air, bayangan, dan perspektif yang berbeda menggunakan library rayshader.

5.1 3D Sederhana

Kode ini melanjutkan dari kode sebelumnya yang telah digunakan untuk menghasilkan visualisasi 3D dengan tekstur, lapisan air, dan bayangan pada data elevasi (tiff_pare). Menggunakan plot_3d().

# Code here
tiff_pare %>% 
  sphere_shade(texture = "imhof3") %>% 
  add_water(detect_water(tiff_pare), color = "desert") %>% 
  add_shadow(ray_shade(tiff_pare)) %>% 
  plot_3d(tiff_pare, zscale = 6)

5.2 3D dengan Legenda dan Efek Tambahan

Membuat visualisasi peta 3D yang dinamis dengan legenda, scale bar, dan kompas, serta untuk membuat serangkaian bingkai (frames) yang nantinya dapat digunakan untuk membuat animasi visualisasi 3D. Berikut ini adalah penjelasan kode tersebut:

montshadow = ray_shade(tiff_pare, zscale = 66, lambert = FALSE)
montamb = ambient_shade(tiff_pare, zscale = 6)

tiffmat_viz <- tiff_pare %>%
  sphere_shade(texture = "imhof1") %>%
  add_shadow(montshadow, 0.5) %>%
  add_shadow(montamb, 0) %>%
  add_water(detect_water(tiff_pare), color = "lightblue") %>%
  plot_3d(tiff_pare, zscale = 6, fov = 0, theta = 60, zoom = 0.75, phi = 45)

render_scalebar(limits=c(0, 5, 10),label_unit = "km",position = "W", y=50,
                scale_length = c(0.33,1))

render_compass(position = "E")
Sys.sleep(0.2)

Note:

Note: - sphere_shade(): Fungsi ini memberikan efek tekstur pada visualisasi 3D. Dalam contoh ini, tekstur “desert” digunakan.

  • add_water(): Fungsi ini menambahkan lapisan air ke visualisasi berdasarkan deteksi air menggunakan detect_water(). Lapisan air ini memiliki warna yang sesuai dengan tekstur “desert”.

  • add_shadow(): Fungsi ini menambahkan bayangan ke visualisasi. Dalam kode ini, ada dua jenis bayangan yang ditambahkan: bayangan berdasarkan cahaya matahari (ray_shade()) dengan faktor penskalaan zscale = 6, dan bayangan ambient (ambient_shade()) dengan faktor 0 (tidak ada bayangan ambient).

  • plot_3d(): Fungsi plot_3d dalam paket rayshader digunakan untuk menggambar visualisasi peta 3D. Parameter-parameter yang ada dalam fungsi plot_3d memengaruhi tampilan dan perspektif visualisasi tersebut. Di bawah ini adalah penjelasan parameter-parameter yang digunakan dalam kode Anda:

    1. tiff_bali: Ini adalah data elevasi yang digunakan untuk membuat visualisasi. Data ini adalah dasar visualisasi 3D.

    2. zscale: Parameter ini mengontrol tingkat penskalaan dalam sumbu z (elevasi) dalam visualisasi. Semakin tinggi nilainya, semakin besar perbedaan ketinggian dalam visualisasi. Sebaliknya, semakin rendah nilai zscale, semakin datar visualisasi tersebut.

    3. fov: Fov (Field of View) mengontrol sudut pandang (bidang pandang) dari visualisasi. Semakin tinggi nilai fov, semakin luas bidang pandangnya. Sebaliknya, semakin rendah nilai fov, semakin sempit bidang pandangnya.

    4. theta: Parameter ini mengontrol sudut horizontal visualisasi. Nilai positif akan menggeser visualisasi ke kanan, sedangkan nilai negatif akan menggesernya ke kiri.

    5. phi: Parameter ini mengontrol sudut vertikal visualisasi. Nilai positif akan mengangkat pandangan ke atas, sedangkan nilai negatif akan menurunkannya.

    6. windowsize: Ini mengatur ukuran jendela visualisasi dalam piksel. Semakin besar nilai windowsize, semakin besar visualisasi yang akan dihasilkan.

    7. zoom: Parameter ini mengontrol tingkat zoom visualisasi. Nilai yang lebih tinggi akan memberikan efek zoom yang lebih besar, sementara nilai yang lebih rendah akan memberikan efek zoom yang lebih kecil.

  • Sys.sleep(0.2): Ini adalah perintah untuk memberikan jeda selama 0.2 detik sebelum rendering dilakukan. Hal ini digunakan untuk memberikan waktu bagi visualisasi untuk siap sebelum diproses lebih lanjut.

  • render_snapshot(): Ini adalah perintah yang digunakan untuk mengambil snapshot dari visualisasi yang telah dibuat. Rendering mungkin memerlukan waktu beberapa saat tergantung pada kompleksitas visualisasi.

  • ray_shade() dan ambient_shade(): Dalam blok ini, Anda menghasilkan bayangan berdasarkan cahaya matahari dengan ray_shade() dan bayangan ambient dengan ambient_shade(). Ini digunakan untuk memberikan efek bayangan pada visualisasi 3D.

  • render_scalebar(): Fungsi ini digunakan untuk menambahkan skala (scale bar) ke visualisasi. Anda dapat mengatur batas skala, unit label, posisi, panjang skala, dan lain-lain.

  • render_compass(): Ini digunakan untuk menambahkan kompas ke visualisasi dengan mengatur posisinya.


6 Save 3D .mp4/.gif

Untuk menyimpan visualisasi 3D yang dibuat rayshader sebagai file MP4/GIF, kita dapat menggunakan fungsi rayshader::render_movie(). Fungsi ini memungkinkan membuat Mp4 atau GIF animasi dengan melakukan iterasi melalui berbagai sudut pandang plot 3D. Untuk bisa melakukan rendering movie, kita butuh packages av untuk render .mp4 sedangkan untuk .gif memerlukan library gifski.

Berikut cara memodifikasi kode untuk menyimpan visualisasi sebagai MP4:

# Run chunk below
montshadow = ray_shade(tiff_pare, zscale = 6, lambert = FALSE)
montamb = ambient_shade(tiff_pare, zscale = 6)

# add 3d map
tiff_pare %>%
  sphere_shade(texture = "imhof1") %>%
  add_shadow(montshadow, 0.5) %>%
  add_shadow(montamb, 0) %>%
  add_water(detect_water(tiff_pare), color = "lightblue") %>%
  plot_3d(tiff_pare, zscale = 6, fov = 0, theta = 60, zoom = 0.75, phi = 45)

# add scalebar
render_scalebar(limits = c(0, 5, 10),label_unit = "km", position = "W", y = 50,
                scale_length = c(0.33,1))
# add compass
render_compass(position = "E")
#
# `av` package required for render_movie()
# magick::image_annotate -> untuk menggunakan title

render_movie(filename = "3D_Parepare.mp4", type = "oscillate",
            frames = 60, fps = 30,  phi = 30, theta = 90,
            title_text = "Parepare 3D Map Using Rayshader Packages")
#> [1] "/Users/trisaputraungko/Documents/Algoritma/RStudio/DSS_Geospatial-Rayshader/3D_Parepare.mp4"