问题描述
是否有更好的方法在给定距离的周围围绕起点生成N个纬度/经度坐标?这是我的方法,但不会创建均匀的分布。
generate_gps_coordinates_in_circle<-function(start_lat,start_lon,max_distance_in_m,min_distance_in_m){
lat <- (start_lat * pi / 180) #center of the circle
lon <- (start_lon * pi / 180) #center of the circle
earth_radius <- 6371000
distance <- sqrt(runif(1,1) * (max_distance_in_m ** 2 - min_distance_in_m ** 2) + min_distance_in_m ** 2) #max and min distance from the center
delta_lat = cos(runif(1) * pi) * distance / earth_radius
sign = runif(1,2) * 2 - 1
delta_lon = sign * acos(((cos(distance/earth_radius) - cos(delta_lat)) / (cos(lat) * cos(delta_lat + lat))) + 1)
result <- c(lon = (lon + delta_lon) * 180 / pi,lat =(lat + delta_lat) * 180 / pi)
return(result)
}
解决方法
您可以使用destPoint
包中的函数geosphere
来获取给定点的坐标,该点是给定方位角以及距地球表面原点的距离。通过执行runif(1) * 360
很容易获得随机方位。但是,如果要在点周围形成均匀的密度,则需要将均匀随机变量的平方根作为距离。
因此,我们可以使用destPoint
重写您的函数,还可以利用向量化的优势,以便我们返回n
点的数据帧:
generate_gps_coordinates_in_circle <- function(
start_lat,start_lon,max_distance_in_m,min_distance_in_m,n = 1)
{
d <- geosphere::destPoint(c(start_lon,start_lat),360 * runif(n),min_distance_in_m + (max_distance_in_m - min_distance_in_m) * sqrt(runif(n)))
setNames(as.data.frame(d),c("lon","lat"))
}
这使我们能够做到:
df <- generate_gps_coordinates_in_circle(54,200,n = 1000)
head(df)
#> lon lat
#> 1 -0.0010012322 53.99864
#> 2 0.0028912625 53.99959
#> 3 0.0021632655 54.00045
#> 4 -0.0006538438 53.99894
#> 5 0.0014026358 54.00087
#> 6 0.0005882192 54.00172
我们可以看到结果令人满意,在小距离处产生一个圆:
plot(df$lon,df$lat)
但是在较大距离处有适当变形的圆:
df <- generate_gps_coordinates_in_circle(54,2000e3,n = 1000)
plot(df$lon,df$lat)