Ответ 1
Если я правильно понимаю, вы можете сделать это достаточно просто с помощью gDistance
в пакете rgeos
.
Прочитайте строки в виде SpatialLines/DataFrame
и укажите как SpatialPoints/DataFrame
, а затем проведите по каждой точке каждый раз, вычисляя расстояние:
require(rgeos)
## untested code
shortest.dists <- numeric(nrow(sp.pts))
for (i in seq_len(nrow(sp.pts)) {
shortest.dists[i] <- gDistance(sp.pts[i,], sp.lns)
}
Здесь sp.pts
- объект пространственных точек, а sp.lns
- объект пространственных линий.
Вы должны выполнить цикл, чтобы сравнить только одну координату в sp.pts
со всей геометрией линий в sp.lns
, иначе вы получите расстояние от совокупного значения во всех точках.
Поскольку ваши данные находятся в широте/долготе, вы должны преобразовать линии и точки в подходящую проекцию, так как функция gDistance
принимает декартово расстояние.
БОЛЬШЕ ОБСУЖДЕНИЯ И ПРИМЕР (изменить)
Было бы аккуратно получить ближайшую точку на линии/с, а не только расстояние, но это открывает еще один вариант, который заключается в том, нужна ли вам ближайшая координата вдоль линии или фактическое пересечение с сегментом линии, ближе к любой существующей вершине. Если ваши вершины достаточно плотные, чтобы разница не имела значения, используйте spDistsN1
в пакете sp
. Вам нужно будет извлечь все координаты из каждой строки в наборе (не сложно, но немного уродливо), а затем перебрать каждую интересующую точку, вычисляя расстояние до вершин линии - тогда вы можете найти, что является самым коротким и выбрать которые координируются из множества вершин, поэтому вы можете легко и легко определить расстояние и координату. Там нет необходимости проецировать либо, так как функция может использовать эллипсоидальные расстояния с аргументом longlat = TRUE
.
library(maptools)
## simple global data set, which we coerce to Lines
data(wrld_simpl)
wrld_lines <- as(wrld_simpl, "SpatialLinesDataFrame")
## get every coordinate as a simple matrix (scary but quick)
wrld_coords <- do.call("rbind", lapply([email protected], function(x1) do.call("rbind", lapply([email protected], function(x2) [email protected][-nrow([email protected]), ]))))
Проверьте это в интерактивном режиме, вам придется изменить это, чтобы сохранить координаты или минимальные расстояния. Это будет строить линии и ждать, пока вы нажмете в любом месте сюжета, затем он нарисует линию от вашего клика до ближайшей вершины на линии.
## no out of bounds clicking . . .
par(mar = c(0, 0, 0, 0), xaxs = "i", yaxs = "i")
plot(wrld_lines, asp = "")
n <- 5
for (i in seq_len(n)) {
xy <- matrix(unlist(locator(1)), ncol = 2)
all.dists <- spDistsN1(wrld_coords, xy, longlat = TRUE)
min.index <- which.min(all.dists)
points(xy, pch = "X")
lines(rbind(xy, wrld_coords[min.index, , drop = FALSE]), col = "green", lwd = 2)
}