我有一组点,它们勾勒出一个Map区域的轮廓。我想使用这些点定义一个多边形,以便使用简单要素(sf)库使用ggplot绘制该多边形。但是,这些点的顺序不对,因此连接它们的线不能形成一个闭合形状。我已经尝试了geom_line和geom_path。是否有任何方法可以重新组织这些点,而无需手动排序?
在下面这个可重复的例子中,“好圆”是我想要的,而“坏圆”是我拥有的,它们都包括相同的x,y点,但由于坏圆的顺序不对,我无法画出一个封闭的图形。
library(dplyr)
library(ggplot2)
library(sf)
x_coords <- rad * cos(seq(0, (2 * pi), (pi / 6)))
y_coords <- rad * sin(seq(0, (2 * pi), (pi / 6)))
perimeter <- as.matrix(rbind(cbind(x_coords, y_coords), c(x_coords[1], y_coords[1])))
perimeter
good_circle = st_multipolygon(list(list(perimeter)))
ggplot() + geom_sf(data = good_circle, fill = "blue") + ggtitle("good circle")
我得到的结果是这样的:
bad_circle <- slice(data.frame(perimeter), sample(1:n()))
ggplot(bad_circle, aes(x = x_coords, y = y_coords)) + geom_point() + geom_line() + ggtitle("bad circle")
3条答案
按热度按时间eh57zj3b1#
我建议你用一种不同的方法,不用重新排序点,你可以在你的无序点周围创建一个convex hull并得到多边形。
虽然sf有一个函数(
sf::st_convex_hull()
),但我通常更喜欢concaveman
包的结果,它也与sf
对象兼容。创建于2023年1月13日,使用reprex v2.0.2
https://en.wikipedia.org/wiki/Convex_hull
qc6wkl3g2#
将点转换为极坐标:
然后按Angular 的顺序画出这些点:
要保持ggplot中的顺序,请使用geom_path:
voase2hg3#
您描述的操作可以解释为查找convex hull。
这并不是一个不常见的操作,因此在
{sf}
环境中有标准化的工具来实现它(尽管我必须说,将点转换为极坐标,然后按照@user1505631的建议找到r和theta是相当有创造性的)。我的建议是,首先通过
sf::st_union()
调用将多个单独的点转换为单个多点对象,然后通过sf::st_convex_hull()
调用找到它的船体。这是可能的-特别是在点的情况下,不是那么方便的间隔作为您的圆-船体将不完全符合期望;在这种情况下,还考虑
concaveman::concaveman()
;对于实际应用中的示例(以及真实的世界数据中凸面 shell 和凹面 shell 之间的差异),请查看How to draw Polygon for lots of lat/long coordinates and calculate surface are?