围绕半径内的某个地理点纬度,经度生成均匀分布的地理点

问题描述

是否有更好的方法在给定距离的周围围绕起点生成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)

enter image description here

但是在较大距离处有适当变形的圆:

df <- generate_gps_coordinates_in_circle(54,2000e3,n = 1000)
plot(df$lon,df$lat)

enter image description here