Вот решение с использованием пакета sf
.Я поработаю с созданными вами объектами и преобразую их в sf
, хотя вы можете читать шейп-файлы в sf
объекты и создавать их с нуля, поэтому, если нет другой причины использовать sp
объекты, я бы порекомендовал это.
Используйте эти пакеты:
library(sf)
library(dplyr)
Преобразование полигонов.Я отбрасываю загрузку столбцов из parks_sub
, чтобы они могли печататься аккуратно - если они вам нужны, не отбрасывайте их:
p = st_as_sf(parks_sub)
p = p[,c("OBJECTID","PARK_NAME")]
Конвертируйте строки.Я собираюсь работать только с вашим первым объектом линии, напишите цикл над списком, чтобы сделать весь набор:
l1 = st_as_sf(lineldf[[1]])
Следующим шагом будет вычисление всех точек пересечения между вашей линией и полигонами.Вы должны: а) преобразовать многоугольники в линейные линии, в противном случае пересечение многоугольника и линии является линией, и б) преобразовать пересечения "MULTIPOINT", когда линия пересекает многоугольник более одного раза, в набор объектов POINT, используя st_cast
:
pts = st_cast(st_cast(st_intersection(l1,
st_cast(p,"MULTILINESTRING")
),"MULTIPOINT"),"POINT")
Далее нам понадобится первая точка линии.Для данных, которые вы создаете в этом примере, конец линии в многоугольнике фактически является второй точкой, поэтому я извлеку это здесь.
first_point = st_cast(l1$geom,"POINT")[2]
Если в ваших реальных данных это первая точка, введите туда [1]
.Если это зависит, то это еще одна маленькая проблема.
Теперь вычислите расстояния от этой первой точки до всех точек пересечения:
pts$d_first = st_distance(first_point, pts)[1,]
Итак, что нам нужно, так это ближайшая точка пересечения в каждомгруппа точек, определенных одним и тем же идентификатором многоугольника.
near_pts = pts %>% group_by(OBJECTID) %>% filter(d_first==min(d_first))
Затем нужные линии строятся от первой точки до ближайших точек:
nlines = st_cast(st_union(near_pts, first_point),"LINESTRING")
Построить полигоны и линии вуменьшение ширины для отображения перекрытия:
plot(p$geom)
plot(nlines$geom, lwd=c(10,7,4), col=c("black","grey","white"), add=TRUE)
Обратите внимание, что три линии включают короткую (белым) от первой точки до границыполигона, в котором он находится - если вы не хотите этого, вы можете отфильтровать точку с ближайшим расстоянием от фрейма данных перед построением линий - но это предполагает, что первая точка находится внутри многоугольника ...
nlines
сохраняет атрибуты многоугольников, которые пересекает линия, а также идентификатор линии:
> nlines
Simple feature collection with 3 features and 4 fields
geometry type: LINESTRING
dimension: XY
bbox: xmin: 310276 ymin: 5522728 xmax: 333000 ymax: 5530000
epsg (SRID): 26911
proj4string: +proj=utm +zone=11 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs
id OBJECTID PARK_NAME d_first geometry
1 181 2254 Mission Creek 6794.694 m LINESTRING (326528.6 552792...
2 181 1831 Glen Canyon 23859.161 m LINESTRING (310276 5522728,...
3 181 1838 Black Mountain 1260.329 m LINESTRING (331799.6 552961...
, поэтому теперь оберните все это в функцию и зациклитеВаши строки и работа выполнены!?