Analisis Kesesuaian Lahan Kawasan Industri Kabupaten Temanggung, Jawa Tengah
Metode: Overlay SIG dengan Skoring (MCDA – Equal-Weight)
Referensi: Ruuhulhaq (2025); Peraturan Menteri
Perindustrian No. 35 Tahun 2010.
Tools: R (terra, sf) |
CRS: UTM Zone 49S (EPSG:32749) |
Resolusi: ±100 m
## Warning: package 'knitr' was built under R version 4.5.3
## Warning: package 'kableExtra' was built under R version 4.5.3
| No | Parameter | Tujuan_Analisis | Metode |
|---|---|---|---|
| 1 | Kemiringan Lereng | Menentukan kestabilan lahan untuk pembangunan industri | Klasifikasi raster slope |
| 2 | Multi Bahaya Bencana | Mengurangi risiko bencana pada kawasan industri | Klasifikasi indeks bahaya |
| 3 | Jarak dari Jalan | Menilai aksesibilitas kawasan terhadap jaringan transportasi | Analisis buffer jarak |
| 4 | Jarak dari Sungai | Menilai kedekatan sumber air untuk kebutuhan industri | Analisis buffer jarak |
| 5 | Jarak dari Permukiman | Mengurangi konflik penggunaan lahan dengan permukiman | Analisis buffer jarak |
| 6 | Jenis Tanah | Menentukan daya dukung tanah terhadap aktivitas industri | Skoring jenis tanah |
Kabupaten Temanggung memiliki posisi strategis di Provinsi Jawa Tengah dengan infrastruktur jalan lintas provinsi yang memadai dan ketersediaan sumber daya alam serta tenaga kerja lokal. Namun, penentuan lokasi kawasan industri di daerah ini belum selalu didasari analisis spasial yang komprehensif dan terukur. Pemilihan lokasi yang tidak tepat berpotensi menimbulkan risiko bencana, kerusakan ekosistem, dan konflik lahan. Oleh karena itu, kajian berbasis SIG dengan pendekatan Multi-Criteria Decision Analysis (MCDA) diperlukan untuk menghasilkan peta kesesuaian lahan yang ilmiah dan dapat direproduksi.
# ============================================================
# ATUR DIREKTORI DI SINI
# Ganti path sesuai lokasi data Anda
# ============================================================
dir_raster <- "D:/SEMESTER 6/SEB/temanggung/data/raster/"
dir_vektor <- "D:/SEMESTER 6/SEB/temanggung/data/vektor/"
dir_output <- "D:/SEMESTER 6/SEB/temanggung/output/"
if (!dir.exists(dir_output)) dir.create(dir_output, recursive = TRUE)
# Palet warna dan label global
warna_4 <- c("#d73027", "#fc8d59", "#91cf60", "#1a9641")
label_4 <- c("Tidak Sesuai", "Kurang Sesuai", "Sesuai", "Sangat Sesuai")
cat("Direktori output:", dir_output, "\n")## Direktori output: D:/SEMESTER 6/SEB/temanggung/output/
# ============================================================
# 1. PEMUATAN DATA
# ============================================================
cat(">> [1/8] Memuat data...\n")## >> [1/8] Memuat data...
# ---- Raster ----
dem <- rast(file.path(dir_raster, "dem_temanggung.tif"))
mb_raster <- rast(file.path(dir_raster, "multibahaya_temanggung.tif"))
# ---- Vektor ----
batas <- st_read(file.path(dir_vektor, "batas_temanggung.shp"),
quiet = TRUE)
jalan <- st_read(file.path(dir_vektor, "jalan_temanggung.shp"),
quiet = TRUE)
permukiman <- st_read(file.path(dir_vektor, "permukiman_temanggung.shp"),
quiet = TRUE,
options = "SHAPE_RESTORE_SHX=YES")
industri <- st_read(file.path(dir_vektor, "industri_existing.shp"),
quiet = TRUE)
sungai <- st_read(file.path(dir_vektor, "sungai_temanggung.shp"),
quiet = TRUE)
tanah <- st_read(file.path(dir_vektor, "jenis_tanah_temanggung.shp"),
quiet = TRUE)
cat(" Semua data berhasil dimuat.\n")## Semua data berhasil dimuat.
df_info <- data.frame(
No = 1:8,
Layer = c("DEM (DEMNAS)", "Multi Bahaya", "Batas Kab.", "Jalan",
"Permukiman", "Industri Eksisting", "Sungai", "Jenis Tanah"),
Tipe = c("Raster", "Raster", "Vektor (polygon)", "Vektor (polyline)",
"Vektor (polygon)", "Vektor (point)", "Vektor (polyline)",
"Vektor (polygon)"),
Sumber = c("DEMNAS BIG", "BNPB", "BIG / Kemendagri", "OpenStreetMap",
"OpenStreetMap", "Survey/OSM", "BIG (RBI)", "DTPH"),
Keterangan = c(
"Elevasi tanah; force-assign WGS84",
"Indeks komposit bencana 0-1",
"Batas administrasi kabupaten",
"Jaringan jalan primer-lokal",
"Kawasan terbangun permukiman; tanpa .shx",
"Titik industri eksisting",
"Jaringan sungai utama",
"Jenis tanah per poligon"
)
)
kable(df_info,
caption = "Tabel 2. Inventarisasi Data Masukan",
align = c("c", "l", "l", "l", "l")) |>
kable_styling(bootstrap_options = c("striped", "hover", "bordered"),
full_width = TRUE) |>
column_spec(1, bold = TRUE, width = "2em")| No | Layer | Tipe | Sumber | Keterangan |
|---|---|---|---|---|
| 1 | DEM (DEMNAS) | Raster | DEMNAS BIG | Elevasi tanah; force-assign WGS84 |
| 2 | Multi Bahaya | Raster | BNPB | Indeks komposit bencana 0-1 |
| 3 | Batas Kab. | Vektor (polygon) | BIG / Kemendagri | Batas administrasi kabupaten |
| 4 | Jalan | Vektor (polyline) | OpenStreetMap | Jaringan jalan primer-lokal |
| 5 | Permukiman | Vektor (polygon) | OpenStreetMap | Kawasan terbangun permukiman; tanpa .shx |
| 6 | Industri Eksisting | Vektor (point) | Survey/OSM | Titik industri eksisting |
| 7 | Sungai | Vektor (polyline) | BIG (RBI) | Jaringan sungai utama |
| 8 | Jenis Tanah | Vektor (polygon) | DTPH | Jenis tanah per poligon |
# ============================================================
# 2. KOREKSI CRS, PROYEKSI, DAN MASKING
# ============================================================
cat(">> [2/8] Koreksi CRS dan standarisasi spasial...\n")## >> [2/8] Koreksi CRS dan standarisasi spasial...
# ---- Verifikasi extent DEM ----
ext_dem <- ext(dem)
cat(sprintf(" Extent DEM: xmin=%.4f / xmax=%.4f / ymin=%.4f / ymax=%.4f\n",
ext_dem$xmin, ext_dem$xmax, ext_dem$ymin, ext_dem$ymax))## Extent DEM: xmin=109.9371 / xmax=110.3330 / ymin=-7.4041 / ymax=-7.0775
# Validasi rentang koordinat WGS84 Jawa Tengah
stopifnot(
"GAGAL: Extent DEM bukan WGS84 Jawa Tengah. Periksa file DEM." =
ext_dem$xmin > 100 && ext_dem$xmax < 115 &&
ext_dem$ymin > -10 && ext_dem$ymax < -5
)
cat(" Validasi extent DEM: OK — koordinat WGS84 terkonfirmasi\n")## Validasi extent DEM: OK — koordinat WGS84 terkonfirmasi
# ---- Force-assign CRS yang benar ----
crs(dem) <- "EPSG:4326"
crs(mb_raster) <- "EPSG:4326"
# ---- Proyeksi ke UTM Zone 49S ----
dem_utm <- project(dem, "EPSG:32749", method = "bilinear")
mb_utm <- project(mb_raster, "EPSG:32749", method = "near")
# ---- Standarisasi resolusi ±100 m ----
fact_agg <- max(1L, round(100 / res(dem_utm)[1]))
dem_100 <- aggregate(dem_utm, fact = fact_agg, fun = "mean", na.rm = TRUE)
mb_100 <- resample(mb_utm, dem_100, method = "near")
cat(sprintf(" Resolusi setelah aggregate (fact=%d): %.1f m x %.1f m\n",
fact_agg, res(dem_100)[1], res(dem_100)[2]))## Resolusi setelah aggregate (fact=3): 89.3 m x 89.3 m
# ---- Transformasi vektor ke UTM + hapus dimensi Z ----
batas_utm <- st_zm(st_transform(batas, 32749), drop = TRUE, what = "ZM")
jalan_utm <- st_zm(st_transform(jalan, 32749), drop = TRUE, what = "ZM")
permukiman_utm <- st_zm(st_transform(permukiman, 32749), drop = TRUE, what = "ZM")
industri_utm <- st_zm(st_transform(industri, 32749), drop = TRUE, what = "ZM")
sungai_utm <- st_zm(st_transform(sungai, 32749), drop = TRUE, what = "ZM")
tanah_utm <- st_zm(st_transform(tanah, 32749), drop = TRUE, what = "ZM")
# ---- Masking ke batas kabupaten ----
batas_utm <- st_buffer(batas_utm, 0)
batas_union <- st_union(batas_utm)
batas_vect <- vect(batas_union)
batas_v <- vect(batas_utm)
dem_masked <- mask(crop(dem_100, batas_vect), batas_vect)
mb_masked <- mask(crop(mb_100, batas_vect), batas_vect)
# ---- Normalisasi multibahaya ke 0-1 (jika perlu) ----
mb_vals <- values(mb_masked, na.rm = TRUE)
mb_range <- range(mb_vals)
cat(sprintf(" Range multibahaya: %.4f - %.4f\n", mb_range[1], mb_range[2]))## Range multibahaya: 5.0000 - 11.0000
if (mb_range[2] > 1) {
mb_masked <- (mb_masked - mb_range[1]) / (mb_range[2] - mb_range[1])
cat(" Normalisasi multibahaya selesai (skala 0-1)\n")
}## Normalisasi multibahaya selesai (skala 0-1)
## Standarisasi spasial selesai.
Catatan koreksi data:
permukiman_temanggung.shp tidak memiliki
.shx → dibaca dengan opsi
SHAPE_RESTORE_SHX=YESst_zm()# ============================================================
# FUNGSI PLOTTING KARTOGRAFI
# Layout: peta di atas — legenda di bawah (tidak menutupi peta)
# ============================================================
plot_peta_jurnal <- function(r, judul, warna, leg_label, leg_judul,
overlay_line = NULL,
overlay_col = "white",
overlay_lwd = 0.5) {
layout(matrix(c(1, 2), nrow = 2), heights = c(5, 1.2))
# Panel 1 — Peta
par(mar = c(1, 3, 3.5, 3), xpd = FALSE)
plot(r, col = warna, legend = FALSE, axes = TRUE,
main = judul, cex.main = 0.88, font.main = 2)
plot(batas_v, add = TRUE, border = "grey25", lwd = 0.8)
if (!is.null(overlay_line))
plot(overlay_line, add = TRUE, col = overlay_col, lwd = overlay_lwd)
# Panel 2 — Legenda horizontal di bawah
par(mar = c(0.5, 3, 0.2, 3), xpd = TRUE)
plot.new()
legend(x = "center",
legend = leg_label,
fill = warna,
title = leg_judul,
horiz = TRUE,
cex = 0.72,
bty = "n",
title.font = 2,
title.adj = 0.5)
layout(1)
}
# Helper: ekspor PNG resolusi tinggi ke folder output
export_png <- function(nama_file, FUN, lebar = 2200, tinggi = 2000, res = 200) {
path_out <- file.path(dir_output, nama_file)
png(path_out, width = lebar, height = tinggi, res = res)
FUN()
dev.off()
invisible(cat(" Tersimpan:", path_out, "\n"))
}
cat("Fungsi plotting siap digunakan.\n")## Fungsi plotting siap digunakan.
| Kelas | Rentang | Skor | Kesesuaian |
|---|---|---|---|
| Datar | 0 - 8% | 4 | Sangat Sesuai |
| Landai | 8 - 15% | 3 | Sesuai |
| Agak Curam | 15 - 25% | 2 | Kurang Sesuai |
| Curam | 25 - 45% | 1 | Tidak Sesuai |
| Sangat Curam | > 45% | 1 | Tidak Sesuai |
# ============================================================
# 3. PARAMETER 1 — KEMIRINGAN LERENG
# ============================================================
cat(">> [3/8] Kemiringan lereng...\n")## >> [3/8] Kemiringan lereng...
slope_deg <- terrain(dem_masked, v = "slope", unit = "degrees")
slope_pct <- tan(slope_deg * pi / 180) * 100
slope_brks <- matrix(c(
0, 8, 4,
8, 15, 3,
15, 25, 2,
25, 45, 1,
45, Inf, 1
), ncol = 3, byrow = TRUE)
slope_r <- classify(slope_pct, slope_brks, include.lowest = TRUE)
names(slope_r) <- "skor_slope"
plot_peta_jurnal(
r = slope_r,
judul = "Peta Kemiringan Lereng\nKabupaten Temanggung",
warna = warna_4,
leg_label = c(">45%/25-45% Curam", "15-25% Agak Curam",
"8-15% Landai", "0-8% Datar"),
leg_judul = "Kelas Slope"
)Gambar 1. Peta Kemiringan Lereng Kabupaten Temanggung
export_png("peta_slope.png", function() {
plot_peta_jurnal(
r = slope_r,
judul = "Peta Kemiringan Lereng\nKabupaten Temanggung",
warna = warna_4,
leg_label = c(">45%/25-45% Curam", "15-25% Agak Curam",
"8-15% Landai", "0-8% Datar"),
leg_judul = "Kelas Slope"
)
})## Tersimpan: D:/SEMESTER 6/SEB/temanggung/output//peta_slope.png
## Slope selesai.
| Kelas | Rentang | Skor | Kesesuaian |
|---|---|---|---|
| Rendah | 0,00 - 0,33 | 4 | Sangat Sesuai |
| Sedang | 0,33 - 0,66 | 3 | Sesuai |
| Tinggi | 0,66 - 1,00 | 1 | Tidak Sesuai |
# ============================================================
# 4. PARAMETER 2 — MULTI BAHAYA
# ============================================================
cat(">> [4/8] Multi bahaya...\n")## >> [4/8] Multi bahaya...
mb_brks <- matrix(c(
0.00, 0.33, 4,
0.33, 0.66, 3,
0.66, 1.00, 1
), ncol = 3, byrow = TRUE)
bahaya_r <- classify(mb_masked, mb_brks, include.lowest = TRUE)
names(bahaya_r) <- "skor_multibahaya"
warna_bahaya <- c("#d73027", "#91cf60", "#1a9641")
label_bahaya <- c("Tinggi (Tidak Sesuai)", "Sedang (Sesuai)",
"Rendah (Sangat Sesuai)")
plot_peta_jurnal(
r = bahaya_r,
judul = "Peta Multi Bahaya Bencana\nKabupaten Temanggung",
warna = warna_bahaya,
leg_label = label_bahaya,
leg_judul = "Tingkat Bahaya"
)Gambar 2. Peta Multi Bahaya Bencana Kabupaten Temanggung
export_png("peta_multibahaya.png", function() {
plot_peta_jurnal(
r = bahaya_r,
judul = "Peta Multi Bahaya Bencana\nKabupaten Temanggung",
warna = warna_bahaya,
leg_label = label_bahaya,
leg_judul = "Tingkat Bahaya"
)
})## Tersimpan: D:/SEMESTER 6/SEB/temanggung/output//peta_multibahaya.png
## Multi bahaya selesai.
| Kelas | Jarak | Skor | Kesesuaian |
|---|---|---|---|
| Sangat Dekat | 0 - 500 m | 4 | Sangat Sesuai |
| Dekat | 500 - 1.000 m | 3 | Sesuai |
| Sedang | 1.000 - 1.500 m | 2 | Kurang Sesuai |
| Jauh | 1.500 - 2.000 m | 2 | Kurang Sesuai |
| Sangat Jauh | > 2.000 m | 1 | Tidak Sesuai |
# ============================================================
# 5. PARAMETER 3 — JARAK DARI JALAN
# ============================================================
cat(">> [5/8] Jarak dari jalan...\n")## >> [5/8] Jarak dari jalan...
jalan_vect <- vect(jalan_utm)
jalan_dist <- mask(distance(dem_masked, jalan_vect), batas_vect)
jalan_brks <- matrix(c(
0, 500, 4,
500, 1000, 3,
1000, 1500, 2,
1500, 2000, 2,
2000, 1e7, 1
), ncol = 3, byrow = TRUE)
jalan_r <- classify(jalan_dist, jalan_brks, include.lowest = TRUE)
names(jalan_r) <- "skor_jalan"
plot_peta_jurnal(
r = jalan_r,
judul = "Peta Jangkauan dari Jalan Utama\nKabupaten Temanggung",
warna = warna_4,
leg_label = c(">2.000 m", "1.000-2.000 m", "500-1.000 m", "0-500 m"),
leg_judul = "Jarak dari Jalan",
overlay_line = jalan_vect,
overlay_col = "white",
overlay_lwd = 0.5
)Gambar 3. Peta Jangkauan dari Jalan Utama Kabupaten Temanggung
export_png("peta_jarak_jalan.png", function() {
plot_peta_jurnal(
r = jalan_r,
judul = "Peta Jangkauan dari Jalan Utama\nKabupaten Temanggung",
warna = warna_4,
leg_label = c(">2.000 m", "1.000-2.000 m", "500-1.000 m", "0-500 m"),
leg_judul = "Jarak dari Jalan",
overlay_line = jalan_vect,
overlay_col = "white",
overlay_lwd = 0.5
)
})## Tersimpan: D:/SEMESTER 6/SEB/temanggung/output//peta_jarak_jalan.png
## Jarak jalan selesai.
| Kelas | Jarak | Skor | Kesesuaian |
|---|---|---|---|
| Dekat | 0 - 5.000 m | 4 | Sesuai |
| Jauh | > 5.000 m | 1 | Tidak Sesuai |
# ============================================================
# 6. PARAMETER 4 — JARAK DARI SUNGAI
# ============================================================
cat(">> [6/8] Jarak dari sungai...\n")## >> [6/8] Jarak dari sungai...
sungai_vect <- vect(sungai_utm)
sungai_dist <- mask(distance(dem_masked, sungai_vect), batas_vect)
sungai_brks <- matrix(c(
0, 5000, 4,
5000, 1e7, 1
), ncol = 3, byrow = TRUE)
sungai_r <- classify(sungai_dist, sungai_brks, include.lowest = TRUE)
names(sungai_r) <- "skor_sungai"
warna_sungai <- c("#d73027", "#1a9641")
label_sungai <- c("> 5 km (Tidak Sesuai)", "0-5 km (Sesuai)")
plot_peta_jurnal(
r = sungai_r,
judul = "Peta Jangkauan dari Sungai\nKabupaten Temanggung",
warna = warna_sungai,
leg_label = label_sungai,
leg_judul = "Jarak dari Sungai",
overlay_line = sungai_vect,
overlay_col = "blue",
overlay_lwd = 0.6
)Gambar 4. Peta Jangkauan dari Sungai Kabupaten Temanggung
export_png("peta_jarak_sungai.png", function() {
plot_peta_jurnal(
r = sungai_r,
judul = "Peta Jangkauan dari Sungai\nKabupaten Temanggung",
warna = warna_sungai,
leg_label = label_sungai,
leg_judul = "Jarak dari Sungai",
overlay_line = sungai_vect,
overlay_col = "blue",
overlay_lwd = 0.6
)
})## Tersimpan: D:/SEMESTER 6/SEB/temanggung/output//peta_jarak_sungai.png
## Jarak sungai selesai.
| Kelas | Jarak | Skor | Kesesuaian |
|---|---|---|---|
| Dekat | 0 - 2.000 m | 4 | Sesuai |
| Jauh | > 2.000 m | 1 | Tidak Sesuai |
# ============================================================
# 7. PARAMETER 5 — JARAK DARI PERMUKIMAN
# ============================================================
cat(">> [7a/8] Jarak dari permukiman...\n")## >> [7a/8] Jarak dari permukiman...
permukiman_vect <- vect(permukiman_utm)
perm_dist <- mask(distance(dem_masked, permukiman_vect), batas_vect)
perm_brks <- matrix(c(
0, 2000, 4,
2000, 1e7, 1
), ncol = 3, byrow = TRUE)
perm_r <- classify(perm_dist, perm_brks, include.lowest = TRUE)
names(perm_r) <- "skor_permukiman"
warna_perm <- c("#d73027", "#1a9641")
label_perm <- c("> 2 km (Tidak Sesuai)", "0-2 km (Sesuai)")
plot_peta_jurnal(
r = perm_r,
judul = "Peta Jangkauan dari Permukiman\nKabupaten Temanggung",
warna = warna_perm,
leg_label = label_perm,
leg_judul = "Jarak dari Permukiman",
overlay_line = permukiman_vect,
overlay_col = "white",
overlay_lwd = 0.4
)Gambar 5. Peta Jangkauan dari Permukiman Kabupaten Temanggung
export_png("peta_jarak_permukiman.png", function() {
plot_peta_jurnal(
r = perm_r,
judul = "Peta Jangkauan dari Permukiman\nKabupaten Temanggung",
warna = warna_perm,
leg_label = label_perm,
leg_judul = "Jarak dari Permukiman",
overlay_line = permukiman_vect,
overlay_col = "white",
overlay_lwd = 0.4
)
})## Tersimpan: D:/SEMESTER 6/SEB/temanggung/output//peta_jarak_permukiman.png
## Jarak permukiman selesai.
| Jenis Tanah | Skor | Kesesuaian | Alasan |
|---|---|---|---|
| Latosol, Mediteran | 4 | Sangat Sesuai | Stabil, drainase baik, daya dukung tinggi |
| Regosol, Aluvial | 3 | Sesuai | Tekstur kasar, cukup permeabel |
| Andosol, Grumosol, Glei | 2 | Kurang Sesuai | Ekspansif / jenuh air / lapisan kedap dangkal |
| Litosol, Podzol | 1 | Tidak Sesuai | Tipis, berbatu, mudah erosi |
# ============================================================
# 8. PARAMETER 6 — JENIS TANAH
# ============================================================
cat(">> [7b/8] Jenis tanah...\n")## >> [7b/8] Jenis tanah...
## Jenis tanah unik di data:
## - Andosol
## - Latosol Coklat
## - Latosol Coklat Kemerahan
## - Latosol Merah Kekuningan
## - Regosol Coklat Kekelabuan
## - Regosol Kuning
tanah_utm$skor_tanah <- ifelse(
grepl("Latosol|Mediteran", tanah_utm$j_tanah, ignore.case = TRUE), 4,
ifelse(grepl("Regosol|Aluvial", tanah_utm$j_tanah, ignore.case = TRUE), 3,
ifelse(grepl("Andosol|Grumosol|Glei", tanah_utm$j_tanah, ignore.case = TRUE), 2,
ifelse(grepl("Litosol|Podzol", tanah_utm$j_tanah, ignore.case = TRUE), 1,
2)))) # default: Kurang Sesuai jika tidak ada kecocokan
tanah_vect <- vect(tanah_utm)
tanah_r <- rasterize(tanah_vect, dem_masked,
field = "skor_tanah", fun = "min")
tanah_r <- mask(tanah_r, batas_vect)
names(tanah_r) <- "skor_tanah"
label_tanah <- c(
"Litosol/Podzol (Tidak Sesuai)",
"Andosol/Grumosol/Glei (Kurang Sesuai)",
"Regosol/Aluvial (Sesuai)",
"Latosol/Mediteran (Sangat Sesuai)"
)
plot_peta_jurnal(
r = tanah_r,
judul = "Peta Jenis Tanah\nKabupaten Temanggung",
warna = warna_4,
leg_label = label_tanah,
leg_judul = "Jenis Tanah"
)Gambar 6. Peta Jenis Tanah Kabupaten Temanggung
export_png("peta_jenis_tanah.png", function() {
plot_peta_jurnal(
r = tanah_r,
judul = "Peta Jenis Tanah\nKabupaten Temanggung",
warna = warna_4,
leg_label = label_tanah,
leg_judul = "Jenis Tanah"
)
})## Tersimpan: D:/SEMESTER 6/SEB/temanggung/output//peta_jenis_tanah.png
## Jenis tanah selesai.
Overlay dilakukan dengan rata-rata aritmetika berbobot setara (equal-weight average) sesuai Ruuhulhaq (2025):
\[\bar{S} = \frac{S_{\text{lereng}} + S_{\text{bahaya}} + S_{\text{jalan}} + S_{\text{sungai}} + S_{\text{permukiman}} + S_{\text{tanah}}}{6}\]
Jumlah kelas akhir ditentukan dengan Rumus Sturges: \(K = 1 + 3{,}3 \cdot \log_{10}(n)\), dibulatkan ke 4 kelas dengan interval \(\Delta = (4-1)/4 = 0{,}75\).
# ============================================================
# 9. OVERLAY SIG
# ============================================================
cat(">> [8/8] Overlay SIG...\n")## >> [8/8] Overlay SIG...
template <- dem_masked
slope_rs <- mask(resample(slope_r, template, method = "near"), batas_vect)
bahaya_rs <- mask(resample(bahaya_r, template, method = "near"), batas_vect)
jalan_rs <- mask(resample(jalan_r, template, method = "near"), batas_vect)
sungai_rs <- mask(resample(sungai_r, template, method = "near"), batas_vect)
perm_rs <- mask(resample(perm_r, template, method = "near"), batas_vect)
tanah_rs <- mask(resample(tanah_r, template, method = "near"), batas_vect)
# Skor komposit kontinu
wo_kontinu <- (slope_rs + bahaya_rs + jalan_rs +
sungai_rs + perm_rs + tanah_rs) / 6
# Rumus Sturges -> 4 kelas
n_piksel <- sum(!is.na(values(wo_kontinu)))
K <- round(1 + 3.3 * log10(n_piksel))
cat(sprintf(" Jumlah piksel valid (n) : %d\n", n_piksel))## Jumlah piksel valid (n) : 106624
## K Sturges : 18 -> dibulatkan ke 4 kelas
interval <- (4 - 1) / 4
wo_brks <- matrix(c(
1 + 0 * interval, 1 + 1 * interval, 1,
1 + 1 * interval, 1 + 2 * interval, 2,
1 + 2 * interval, 1 + 3 * interval, 3,
1 + 3 * interval, 4 + 0.001, 4
), ncol = 3, byrow = TRUE)
cat(sprintf(" Break kelas: %.2f | %.2f | %.2f | %.2f | %.3f\n",
wo_brks[1, 1], wo_brks[1, 2], wo_brks[2, 2],
wo_brks[3, 2], wo_brks[4, 2]))## Break kelas: 1.00 | 1.75 | 2.50 | 3.25 | 4.001
kesesuaian_final <- classify(wo_kontinu, wo_brks, include.lowest = TRUE)
names(kesesuaian_final) <- "kelas_kesesuaian"
levels(kesesuaian_final) <- data.frame(
value = 1:4,
label = c("Tidak Sesuai", "Kurang Sesuai", "Sesuai", "Sangat Sesuai")
)
cat(" Overlay selesai.\n")## Overlay selesai.
# ============================================================
# 10. VALIDASI DENGAN DATA INDUSTRI EKSISTING
# ============================================================
cat(">> Validasi model...\n")## >> Validasi model...
skor_eksisting <- extract(kesesuaian_final, industri_v)
names(skor_eksisting)[2] <- "kelas"
tbl_validasi <- table(skor_eksisting$kelas)
n_valid <- sum(tbl_validasi)
n_sesuai <- sum(tbl_validasi[names(tbl_validasi) %in% c("3", "4")],
na.rm = TRUE)
pct_valid <- if (n_valid > 0) round(n_sesuai / n_valid * 100, 1) else NA
cat(" Distribusi kelas pada lokasi industri eksisting:\n")## Distribusi kelas pada lokasi industri eksisting:
##
## Tidak Sesuai Kurang Sesuai Sesuai Sangat Sesuai
## 0 0 7 71
cat(sprintf(
" Akurasi validasi: %d/%d titik di zona Sesuai/Sangat Sesuai (%.1f%%)\n",
n_sesuai, n_valid, pct_valid
))## Akurasi validasi: 0/78 titik di zona Sesuai/Sangat Sesuai (0.0%)
| Kelas Skor | Jumlah Titik | Keterangan | Persen |
|---|---|---|---|
| Tidak Sesuai | 0 | NA | 0 |
| Kurang Sesuai | 0 | NA | 0 |
| Sesuai | 7 | NA | 9 |
| Sangat Sesuai | 71 | NA | 91 |
Interpretasi: Nilai akurasi validasi >= 70% menunjukkan model memadai untuk perencanaan kawasan industri tingkat kabupaten.
# ============================================================
# 11. STATISTIK LUAS PER KELAS
# ============================================================
freq_tbl <- freq(kesesuaian_final)
sel_area_ha <- prod(res(kesesuaian_final)) / 10000
hasil_tbl <- data.frame(
Kelas = seq_len(nrow(freq_tbl)),
Keterangan = as.character(freq_tbl$value),
Jumlah_Sel = freq_tbl$count,
Luas_Ha = round(freq_tbl$count * sel_area_ha, 2),
Persen = round(freq_tbl$count / sum(freq_tbl$count) * 100, 2)
)
cat("=========================================================\n")## =========================================================
## HASIL KESESUAIAN LAHAN - KAB. TEMANGGUNG
## =========================================================
## Kelas Keterangan Jumlah_Sel Luas_Ha Persen
## 1 Kurang Sesuai 3705 2955.34 3.47
## 2 Sesuai 13447 10726.18 12.61
## 3 Sangat Sesuai 89472 71368.56 83.91
## Total: 85050.08 Ha
## =========================================================
| Kelas | Keterangan | Jumlah Sel | Luas (Ha) | Persentase (%) |
|---|---|---|---|---|
| 1 | Kurang Sesuai | 3.705 | 2.955.34 | 3.47 |
| 2 | Sesuai | 13.447 | 10.726.18 | 12.61 |
| 3 | Sangat Sesuai | 89.472 | 71.368.56 | 83.91 |
# ============================================================
# 12a. PETA KESESUAIAN FINAL
# ============================================================
.plot_final <- function() {
layout(matrix(c(1, 2), nrow = 2), heights = c(5, 1.5))
par(mar = c(1, 3, 3.5, 3), xpd = FALSE)
plot(kesesuaian_final, col = warna_4, legend = FALSE, axes = TRUE,
main = paste0("Peta Kesesuaian Lahan Kawasan Industri\n",
"Kabupaten Temanggung, Jawa Tengah"),
cex.main = 0.88, font.main = 2)
plot(batas_v, add = TRUE, border = "grey25", lwd = 0.8)
plot(industri_v, add = TRUE, col = "blue", pch = 17, cex = 0.7)
par(mar = c(0.5, 3, 0.2, 3), xpd = TRUE)
plot.new()
legend(x = "center",
legend = c(label_4, "Industri Eksisting"),
fill = c(warna_4, NA),
pch = c(NA, NA, NA, NA, 17),
col = c(rep(NA, 4), "blue"),
border = c(rep("black", 4), NA),
horiz = TRUE, cex = 0.68, bty = "n",
title = "Keterangan", title.font = 2)
layout(1)
}
.plot_final()Gambar 7. Peta Kesesuaian Lahan Kawasan Industri Kabupaten Temanggung, Jawa Tengah
## Tersimpan: D:/SEMESTER 6/SEB/temanggung/output//peta_kesesuaian_industri.png
# ============================================================
# 12b. DIAGRAM BATANG
# ============================================================
.plot_bar <- function() {
par(mar = c(5, 8, 4, 2))
x_pos <- barplot(
height = hasil_tbl$Luas_Ha,
names.arg = hasil_tbl$Keterangan,
col = warna_4,
border = "white",
ylab = "Luas (Ha)",
main = paste0("Distribusi Luas Kesesuaian Lahan Industri\n",
"Kabupaten Temanggung"),
cex.names = 0.78,
las = 1,
ylim = c(0, max(hasil_tbl$Luas_Ha) * 1.25)
)
text(
x = x_pos,
y = hasil_tbl$Luas_Ha + max(hasil_tbl$Luas_Ha) * 0.04,
labels = paste0(
prettyNum(round(hasil_tbl$Luas_Ha), big.mark = "."),
" Ha\n(", hasil_tbl$Persen, "%)"
),
cex = 0.7, font = 2
)
grid(nx = NA, ny = NULL, lty = 2, col = "grey80")
mtext("Sumber: Hasil Analisis, 2025 | Metode: Ruuhulhaq (2025)",
side = 1, line = 3.8, cex = 0.55, col = "grey45")
}
.plot_bar()Gambar 8. Diagram Distribusi Luas Kesesuaian Lahan Industri Kabupaten Temanggung
## Tersimpan: D:/SEMESTER 6/SEB/temanggung/output//diagram_luas_kesesuaian.png
# ============================================================
# 13. SIMPAN SEMUA OUTPUT
# ============================================================
cat(">> Menyimpan output ke:", dir_output, "\n")## >> Menyimpan output ke: D:/SEMESTER 6/SEB/temanggung/output/
# ---- Raster ----
writeRaster(kesesuaian_final,
file.path(dir_output, "kesesuaian_industri_temanggung.tif"),
overwrite = TRUE, datatype = "INT1U")
writeRaster(slope_rs,
file.path(dir_output, "skor_slope.tif"),
overwrite = TRUE, datatype = "INT1U")
writeRaster(bahaya_rs,
file.path(dir_output, "skor_multibahaya.tif"),
overwrite = TRUE, datatype = "INT1U")
writeRaster(jalan_rs,
file.path(dir_output, "skor_jarak_jalan.tif"),
overwrite = TRUE, datatype = "INT1U")
writeRaster(sungai_rs,
file.path(dir_output, "skor_jarak_sungai.tif"),
overwrite = TRUE, datatype = "INT1U")
writeRaster(perm_rs,
file.path(dir_output, "skor_jarak_permukiman.tif"),
overwrite = TRUE, datatype = "INT1U")
writeRaster(tanah_rs,
file.path(dir_output, "skor_jenis_tanah.tif"),
overwrite = TRUE, datatype = "INT1U")
# ---- Shapefile ----
kesesuaian_poly <- as.polygons(kesesuaian_final, dissolve = TRUE)
kesesuaian_sf <- st_as_sf(kesesuaian_poly)
# Ganti nama kolom non-geometry menjadi "kelas"
idx <- which(!(names(kesesuaian_sf) %in% "geometry"))
names(kesesuaian_sf)[idx[1]] <- "kelas"
kesesuaian_sf$kelas <- as.integer(kesesuaian_sf$kelas)
kesesuaian_sf$keterangan <- c(
"1" = "Tidak Sesuai", "2" = "Kurang Sesuai",
"3" = "Sesuai", "4" = "Sangat Sesuai"
)[as.character(kesesuaian_sf$kelas)]
kesesuaian_sf <- kesesuaian_sf[!is.na(kesesuaian_sf$kelas), ]
kesesuaian_sf$luas_ha <- round(
as.numeric(st_area(kesesuaian_sf)) / 10000, 2
)
kesesuaian_sf$persen <- round(
kesesuaian_sf$luas_ha / sum(kesesuaian_sf$luas_ha, na.rm = TRUE) * 100, 2
)
st_write(kesesuaian_sf,
file.path(dir_output, "kesesuaian_industri_temanggung.shp"),
delete_layer = TRUE, quiet = TRUE)
cat(" Seluruh output tersimpan.\n")## Seluruh output tersimpan.