Saya membuat peta GIS di R menggunakan sf
paket (dan paket terkait) untuk dibaca di shapefile, dan ggplot2
(dan teman) untuk merencanakan. Ini berfungsi dengan baik, tetapi saya tidak dapat menemukan cara (secara otomatis / terprogram) membuat penempatan label untuk fitur seperti sungai dan jalan. Fitur-fitur ini biasanya linestrings, dengan bentuk tidak beraturan. Lihat gambar terlampir misalnya dari wikimedia.
The ggrepel
paket bekerja dengan baik untuk label poin dengan cara otomatis, tapi ini tidak masuk akal untuk fitur geografis lainnya yang tidak diskrit poin Lat / Long.
Saya bisa membayangkan melakukan ini dengan menempatkan label teks pada masing-masing fitur secara individual, tetapi saya sedang mencari sesuatu yang lebih otomatis, jika mungkin. Saya menyadari bahwa otomatisasi semacam itu bukan masalah sepele, tetapi sudah diselesaikan sebelumnya (ArcGIS tampaknya memiliki cara untuk melakukan ini dengan ekstensi yang disebut maplex, tetapi saya tidak memiliki akses ke perangkat lunak, dan saya ingin tetap berada di dalamnya. R jika memungkinkan).
Adakah yang tahu cara melakukan ini?
MWE di sini:
#MWE Linestring labeling
library(tidyverse)
library(sf)
library(ggrepel)
set.seed(120)
#pick a county from the built-in North Carolina dataset
BuncombeCounty <- st_read(system.file("shapes/", package="maptools"), "sids") %>%
filter(NAME == "Buncombe")
#pick 4 random points in that county
pts_sf <- data.frame(
x = seq(-82.3, -82.7, by=-0.1) %>%
sample(4),
y = seq(35.5, 35.7, by=0.05) %>%
sample(4),
placenames = c("A", "B", "C", "D")
) %>%
st_as_sf(coords = c("x","y"))
#link those points into a linestring
linestring_sf <- pts_sf %>%
st_coordinates() %>%
st_linestring()
st_cast("LINESTRING")
#plot them with labels, using geom_text_repel() from the `ggrepel` package
ggplot() +
geom_sf(data = BuncombeCounty) +
geom_sf(data = linestring_sf) +
geom_label_repel(data = pts_sf,
stat = "sf_coordinates",
aes(geometry = geometry,
label = placenames),
nudge_y = 0.05,
label.r = 0, #don't round corners of label boxes
min.segment.length = 0,
segment.size = 0.4,
segment.color = "dodgerblue")
ggrepel
, pada dasarnya ulangi pekerjaan yang telah Anda lakukan. Ini membuat kemungkinan Anda untuk mendapat jawaban yang sangat kecil kemungkinannya.Jawaban:
Saya pikir saya memiliki sesuatu yang mungkin bekerja untuk Anda. Saya telah mengambil kebebasan untuk mengubah contoh Anda menjadi sesuatu yang sedikit lebih realistis: beberapa "sungai" acak yang dibuat dengan jalan acak yang diperhalus, masing-masing panjangnya 100 poin:
Kami dapat memplotnya sesuai contoh Anda:
Solusi saya pada dasarnya adalah mengekstraksi poin dari linestrings dan melabeli mereka. Seperti gambar di bagian atas pertanyaan Anda, Anda mungkin ingin beberapa salinan dari setiap label di sepanjang linestring, jadi jika Anda ingin n label Anda cukup mengekstrak n titik-titik yang berjarak sama.
Tentu saja, Anda ingin dapat memberi label pada kedua sungai sekaligus tanpa bertabrakan dengan label, sehingga Anda harus dapat melewati beberapa fitur geografis sebagai daftar bernama.
Berikut adalah fungsi yang melakukan semua itu:
Jadi jika kita meletakkan objek yang ingin kita beri label dalam daftar bernama seperti ini:
Maka kita bisa melakukan ini:
sumber
sfheaders::sf_linestring(obj = data.frame(x = x1, y = y1))
akan memudahkan beberapasf
kode penghasil.