围绕一个地理点(纬度、经度)以一定半径生成均匀分布的地理点
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)
有没有更好的方法在给定距离的起点周围生成 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)