围绕一个地理点(纬度、经度)以一定半径生成均匀分布的地理点

Generate uniform distributed geo points around a geo point (Lat,Long) in a radius

有没有更好的方法在给定距离的起点周围生成 N 个 Lat/Long 坐标?这是我的方法,但它不会创建均匀分布。

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, 0, 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, 0, 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)
}

您可以使用 geosphere 包中的函数 destPoint 来获取给定点的 co-ordinates,该点是地球表面上距原点的给定方位角和距离。通过 runif(1) * 360 获得随机方位很简单。但是,如果您想要点周围的密度均匀,则需要取均匀随机变量的平方根作为距离。

因此,我们可以使用 destPoint 重写您的函数,还可以利用向量化的优势,以便我们可以 return 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, 0, 200, 0, 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, 0, 2000e3, 0, n = 1000)
plot(df$lon, df$lat)