将 GPS 经纬度跟踪数据转换为足球场上的位置 x 和位置 y?
Convert GPS latitude and longitude tracking data to a position x and position y on a football pitch?
我目前在 m/s 中有一个包含玩家姓名、时间、纬度、经度和速度的数据框。我想绘制球员热图,但我的问题是将纬度和经度转换为足球场图像上的位置 x 和位置 y。
目前可以像下面的图 1 那样绘制出经纬度路径,但这些值不是在平坦足球场的方向上,而是在类似于图 2 的方向上
理想情况下,我想将 lat 和 lon 值转换为足球场上的位置 x 和位置 y,并输出类似于下面的图。
我目前所做的尝试如下,我从 google 地图中获取了左上角、左下角、右上角和右下角的最大和最小(纬度和经度)值.计算间距长度和间距宽度,然后使用以下公式向 df 添加两个新列。但这并没有解决我的问题任何想法我将非常感谢。
#pitch dimensions taken from google
top_left_lat <- 51.662233
top_left_lon <- -0.273183
top_right_lat <- 51.662518
top_right_lon <- -0.272164
bottom_left_lat <- 51.661337
bottom_left_lon <- -0.272539
bottom_right_lat <- 51.661630
bottom_right_lon <- -0.271528
#calculate pitch length
pitch_length <- acos(cos(deg2rad(90 - top_left_lat)) * cos(deg2rad(90 - bottom_left_lat))
+ sin(deg2rad(90 - top_left_lat)) * sin(deg2rad(90 - bottom_left_lat))
* cos(deg2rad(top_left_lon - bottom_left_lon))) * 6371
pitch_length
#calculate pitch width
pitch_width <- acos(cos(deg2rad(90 - top_left_lat)) * cos(deg2rad(90 - top_right_lat))
+ sin(deg2rad(90 - top_left_lat)) * sin(deg2rad(90 - top_right_lat))
* cos(deg2rad(top_left_lon - top_right_lon))) * 6371
pitch_width
#convert lat lon to pos x and y on a pitch
a <- mutate(a, posX = (pitch_width/360)*(180 + a$Lon))
a <- mutate(a, posY = (pitch_length/180)*(90 - a$Lat))
不是最好的解决方案,但我能够在 sf
:
中进行必要的转换
首先,我获取了您的俯仰坐标并将其转换为平面坐标 (27700),并随机抽取了一个样本来表示您的 gps 数据:
library(dplyr)
library(sf)
pts <- data.frame(lat = c(top_left_lat,bottom_left_lat, bottom_right_lat, top_right_lat),
lng = c(top_left_lon,bottom_left_lon, bottom_right_lon, top_right_lon )) %>%
st_as_sf(coords = c('lng', 'lat'), crs = 4326) %>%
st_transform(27700)
poly <- pts %>%
st_union() %>%
st_convex_hull()
centroid <- st_centroid(poly)
set.seed(2020)
path <- st_sample(poly, 20) %>%
st_union() %>%
st_cast("LINESTRING")
st_transform(poly, 4326) %>%
ggplot() +
geom_sf(fill = NA, col = "black") +
geom_sf(data = st_transform(path,4326), col = 'red')
然后计算俯仰角度并将我们的数据旋转该角度(rot
sf
vignette 中的函数):
# get angle of pitch
se <- st_coordinates(pts[1,])
ne <- st_coordinates(pts[2,])
dy <- ne[2] - se[2]
dx <- ne[1] - se[1]
angle = atan(dy/dx)
# rotate
rot <- function(a) matrix(c(cos(a), sin(a), -sin(a), cos(a)), 2, 2)
poly2 <- (poly - centroid) * rot(angle) + centroid
path2 <- (path - centroid) * rot(angle)+ centroid
最终翻译到 (0,0) 的左下角:
# translate to 0,0
xmin <- st_bbox(poly2)[1]
ymin <- st_bbox(poly2)[2]
pitch <- poly2 - c(xmin, ymin)
positions <- path2 - c(xmin, ymin)
## fetch the x,y coordinates:
position_xy <- positions %>%
st_coordinates() %>%
as.data.frame()
pitch_xy <- pitch %>%
st_cast("LINESTRING") %>%
st_coordinates %>%
as.data.frame
position_xy %>%
ggplot() +
geom_path(aes(x = X, y= Y), col= 'red') +
geom_path(data = pitch_xy ,aes(x = X, y = Y))
我目前在 m/s 中有一个包含玩家姓名、时间、纬度、经度和速度的数据框。我想绘制球员热图,但我的问题是将纬度和经度转换为足球场图像上的位置 x 和位置 y。
目前可以像下面的图 1 那样绘制出经纬度路径,但这些值不是在平坦足球场的方向上,而是在类似于图 2 的方向上
理想情况下,我想将 lat 和 lon 值转换为足球场上的位置 x 和位置 y,并输出类似于下面的图。
我目前所做的尝试如下,我从 google 地图中获取了左上角、左下角、右上角和右下角的最大和最小(纬度和经度)值.计算间距长度和间距宽度,然后使用以下公式向 df 添加两个新列。但这并没有解决我的问题任何想法我将非常感谢。
#pitch dimensions taken from google
top_left_lat <- 51.662233
top_left_lon <- -0.273183
top_right_lat <- 51.662518
top_right_lon <- -0.272164
bottom_left_lat <- 51.661337
bottom_left_lon <- -0.272539
bottom_right_lat <- 51.661630
bottom_right_lon <- -0.271528
#calculate pitch length
pitch_length <- acos(cos(deg2rad(90 - top_left_lat)) * cos(deg2rad(90 - bottom_left_lat))
+ sin(deg2rad(90 - top_left_lat)) * sin(deg2rad(90 - bottom_left_lat))
* cos(deg2rad(top_left_lon - bottom_left_lon))) * 6371
pitch_length
#calculate pitch width
pitch_width <- acos(cos(deg2rad(90 - top_left_lat)) * cos(deg2rad(90 - top_right_lat))
+ sin(deg2rad(90 - top_left_lat)) * sin(deg2rad(90 - top_right_lat))
* cos(deg2rad(top_left_lon - top_right_lon))) * 6371
pitch_width
#convert lat lon to pos x and y on a pitch
a <- mutate(a, posX = (pitch_width/360)*(180 + a$Lon))
a <- mutate(a, posY = (pitch_length/180)*(90 - a$Lat))
不是最好的解决方案,但我能够在 sf
:
首先,我获取了您的俯仰坐标并将其转换为平面坐标 (27700),并随机抽取了一个样本来表示您的 gps 数据:
library(dplyr)
library(sf)
pts <- data.frame(lat = c(top_left_lat,bottom_left_lat, bottom_right_lat, top_right_lat),
lng = c(top_left_lon,bottom_left_lon, bottom_right_lon, top_right_lon )) %>%
st_as_sf(coords = c('lng', 'lat'), crs = 4326) %>%
st_transform(27700)
poly <- pts %>%
st_union() %>%
st_convex_hull()
centroid <- st_centroid(poly)
set.seed(2020)
path <- st_sample(poly, 20) %>%
st_union() %>%
st_cast("LINESTRING")
st_transform(poly, 4326) %>%
ggplot() +
geom_sf(fill = NA, col = "black") +
geom_sf(data = st_transform(path,4326), col = 'red')
然后计算俯仰角度并将我们的数据旋转该角度(rot
sf
vignette 中的函数):
# get angle of pitch
se <- st_coordinates(pts[1,])
ne <- st_coordinates(pts[2,])
dy <- ne[2] - se[2]
dx <- ne[1] - se[1]
angle = atan(dy/dx)
# rotate
rot <- function(a) matrix(c(cos(a), sin(a), -sin(a), cos(a)), 2, 2)
poly2 <- (poly - centroid) * rot(angle) + centroid
path2 <- (path - centroid) * rot(angle)+ centroid
最终翻译到 (0,0) 的左下角:
# translate to 0,0
xmin <- st_bbox(poly2)[1]
ymin <- st_bbox(poly2)[2]
pitch <- poly2 - c(xmin, ymin)
positions <- path2 - c(xmin, ymin)
## fetch the x,y coordinates:
position_xy <- positions %>%
st_coordinates() %>%
as.data.frame()
pitch_xy <- pitch %>%
st_cast("LINESTRING") %>%
st_coordinates %>%
as.data.frame
position_xy %>%
ggplot() +
geom_path(aes(x = X, y= Y), col= 'red') +
geom_path(data = pitch_xy ,aes(x = X, y = Y))