我有一张地图,上面画着8个点:
library(ggplot2)
library(ggmap)
data = data.frame(
ID = as.numeric(c(1:8)),
longitude = as.numeric(c(-63.27462, -63.26499, -63.25658, -63.2519, -63.2311, -63.2175, -63.23623, -63.25958)),
latitude = as.numeric(c(17.6328, 17.64614, 17.64755, 17.64632, 17.64888, 17.63113, 17.61252, 17.62463))
)
island = get_map(location = c(lon = -63.247593, lat = 17.631598), zoom = 13, maptype = "satellite")
islandMap = ggmap(island, extent = "panel", legend = "bottomright")
RL = geom_point(aes(x = longitude, y = latitude), data = data, color = "#ff0000")
islandMap + RL + scale_x_continuous(limits = c(-63.280, -63.21), expand = c(0, 0)) + scale_y_continuous(limits = c(17.605, 17.66), expand = c(0, 0))
现在我想围绕8个绘制位置绘制一个圆圈。圆的半径必须为450米。
这就是我的意思,但随后使用ggplot:https://gis.stackexchange.com/questions/119736/ggmap-create-circle-symbol-where-radius-represents-distance-miles-or-km
我怎样才能做到这一点?
答案 0 :(得分:15)
如果你只在地球的一个小区域工作,这里是近似值。每个纬度都代表40075/360公里。每个经度表示(40075/360)* cos(纬度)千米。有了这个,我们可以计算大约一个数据框,包括圆上的所有点,知道圆心和半径。
procedure TForm1.FormClick(Sender: TObject);
var
List: TIdContextList;
begin
List := IdTCPServer1.Contexts.LockList;
try
//has the context already been removed?
if List.IndexOf(TestContext) <> -1 then
TestContext.Connection.Disconnect;
finally
IdTCPServer1.Contexts.UnlockList;
end;
end;
答案 1 :(得分:6)
好吧,正如referred posting已经建议的那样 - 切换到以米为单位的投影,然后返回:
library(rgeos)
library(sp)
d <- SpatialPointsDataFrame(coords = data[, -1],
data = data,
proj4string = CRS("+init=epsg:4326"))
d_mrc <- spTransform(d, CRS("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs"))
现在,width
可以以米为单位指定:
d_mrc_bff_mrc <- gBuffer(d_mrc, byid = TRUE, width = 450)
将其转换回来并使用geom_path
:
d_mrc_bff <- spTransform(d_mrc_bff_mrc, CRS("+init=epsg:4326"))
d_mrc_bff_fort <- fortify(d_mrc_bff)
islandMap +
RL +
geom_path(data=d_mrc_bff_fort, aes(long, lat, group=group), color="red") +
scale_x_continuous(limits = c(-63.280, -63.21), expand = c(0, 0)) +
scale_y_continuous(limits = c(17.605, 17.66), expand = c(0, 0))
答案 2 :(得分:4)
计算给定纬度和经度的km的距离并不是非常直接的;例如,1度纬度/长度在赤道处的距离大于在极点处的距离。如果您想要一个简单的解决方法,您可以考虑准确性,您可以尝试:
islandMap + RL +
scale_x_continuous(limits = c(-63.280, -63.21), expand = c(0, 0)) +
scale_y_continuous(limits = c(17.605, 17.66), expand = c(0, 0)) +
geom_point(aes(x = longitude, y = latitude), data = data, size = 20, shape = 1, color = "#ff0000")
您需要调整第二个size
中的geom_point
参数,以便更接近您想要的内容。我希望有所帮助!
答案 3 :(得分:1)
准确的解决方案是使用geosphere :: destPoint()函数。无需切换投影即可实现。
定义函数以确定在一个点附近具有特定半径的360个点:
library(dplyr)
library(geosphere)
fn_circle <- function(id1, lon1, lat1, radius){
data.frame(ID = id1, degree = 1:360) %>%
rowwise() %>%
mutate(lon = destPoint(c(lon1, lat1), degree, radius)[1]) %>%
mutate(lat = destPoint(c(lon1, lat1), degree, radius)[2])
}
将函数应用于data
的每一行并转换为data.frame:
circle <- apply(data, 1, function(x) fn_circle(x[1], x[2], x[3], 450))
circle <- do.call(rbind, circle)
然后可以通过以下方式轻松获得地图:
islandMap +
RL +
scale_x_continuous(limits = c(-63.280, -63.21), expand = c(0, 0)) +
scale_y_continuous(limits = c(17.605, 17.66), expand = c(0, 0)) +
geom_polygon(data = circle, aes(lon, lat, group = ID), color = "red", alpha = 0)
答案 4 :(得分:0)
使用sf软件包中的st_buffer()的解决方案。
library(ggmap)
library(ggplot2)
library(sf)
data <- data.frame(
ID = 1:8,
longitude = c(-63.27462, -63.26499, -63.25658, -63.2519,
-63.2311, -63.2175, -63.23623, -63.25958),
latitude = c(17.6328, 17.64614, 17.64755, 17.64632,
17.64888, 17.63113, 17.61252, 17.62463)
)
将data.frame转换为sf对象:
points_sf <- sf::st_as_sf(data, coords = c("longitude", "latitude"), crs = 4326)
在此示例中,我们使用UTM区域20,其中包含岛屿的坐标:
data_sf_utm <- sf::st_transform(points_sf, "+proj=utm +zone=20")
现在我们可以将点缓冲450米:
circle <- sf::st_buffer(data_sf_utm, dist = 450)
ggmap似乎与geom_sf有关。将Inherit.aes设置为FALSE会返回所需的映射。
island <- ggmap::get_map(location = c(lon = -63.247593, lat = 17.631598), zoom = 14, maptype = "satellite")
ggmap(island, extent = "panel", legend = "bottomright") +
geom_sf(data = points_sf, color = "red", inherit.aes = FALSE) +
geom_sf(data = circle, color = "red", alpha = 0, inherit.aes = FALSE)
由reprex package(v0.3.0)于2020-10-11创建