gpt4 book ai didi

r - R中GIS map 的自动标签放置

转载 作者:行者123 更新时间:2023-12-03 14:20:27 24 4
gpt4 key购买 nike

我正在使用 sf 在 R 中制作 GIS map 要在 shapefile 中读取的包(和相关包),以及 ggplot2 (和 friend )用于策划。这工作正常,但我找不到(自动/以编程方式)为河流和道路等要素创建标签放置的方法。这些特征通常是具有不规则形状的线串。请参阅例如来自维基媒体的图片。

enter image description here
ggrepel包适用于以自动方式标记点,但这对于不是离散纬度/经度点的其他地理特征没有多大意义。

我可以想象通过在每个功能上单独放置单独的文本标签来实现这一点,但如果可能的话,我正在寻找更自动化的东西。我意识到这种自动化不是一个小问题,但之前已经解决了(ArcGIS 显然有一种方法可以使用名为 Maplex 的扩展程序来做到这一点,但我无法访问该软件,我想留在R 如果可能)。

有谁知道这样做的方法?

MWE在这里:

#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")

enter image description here

最佳答案

我想我有一些可能对你有用的东西。我冒昧地将您的示例更改为更现实的示例:几条由平滑的随机游走制成的随机“河流”,每条 100 点长:

library(tidyverse)
library(sf)
library(ggrepel)

BuncombeCounty <- st_read(system.file("shapes/", package = "maptools"), "sids") %>%
filter(NAME == "Buncombe")
set.seed(120)

x1 <- seq(-82.795, -82.285, length.out = 100)
y1 <- cumsum(runif(100, -.01, .01))
y1 <- predict(loess(y1 ~ x1, span = 0.1)) + 35.6

x2 <- x1 + 0.02
y2 <- cumsum(runif(100, -.01, .01))
y2 <- predict(loess(y2 ~ x2, span = 0.1)) + 35.57

river_1 <- data.frame(x = x1, y = y1) %>%
st_as_sf(coords = c("x", "y")) %>%
st_coordinates() %>%
st_linestring() %>%
st_cast("LINESTRING")

river_2 <- data.frame(x = x2, y = y2) %>%
st_as_sf(coords = c("x", "y")) %>%
st_coordinates() %>%
st_linestring() %>%
st_cast("LINESTRING")

我们可以根据您的示例绘制它们:

riverplot  <- ggplot() +
geom_sf(data = BuncombeCounty) +
geom_sf(data = river_1, colour = "blue", size = 2) +
geom_sf(data = river_2, colour = "blue", size = 2)

riverplot

enter image description here

我的解决方案基本上是从线串中提取点并标记它们。就像问题顶部的图片一样,您可能需要沿线串长度的每个标签的多个副本,因此如果您需要 n 个标签,您只需提取 n 个等距的点。

当然,您希望能够同时标注两条河流而不会发生标注冲突,因此您需要能够将多个地理要素作为命名列表传递。

这是一个完成所有这些工作的函数:

linestring_labels <- function(linestrings, n)
{
do.call(rbind, mapply(function(linestring, label)
{
n_points <- length(linestring)/2
distance <- round(n_points / (n + 1))
data.frame(x = linestring[1:n * distance],
y = linestring[1:n * distance + n_points],
label = rep(label, n))
}, linestrings, names(linestrings), SIMPLIFY = FALSE)) %>%
st_as_sf(coords = c("x","y"))
}

因此,如果我们将要标记的对象放在一个命名列表中,如下所示:
river_list <- list("River 1" = river_1, "River 2" = river_2)

然后我们可以这样做:
riverplot + 
geom_label_repel(data = linestring_labels(river_list, 3),
stat = "sf_coordinates",
aes(geometry = geometry, label = label),
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")

enter image description here

关于r - R中GIS map 的自动标签放置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60086107/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com