Альтернатива для R-пакета concaveman для создания полигонов

#r #gis #polygon #raster

#r #гис #полигон #растр

Вопрос:

У меня есть скрипт, использующий R-пакет ‘concaveman’, но из-за проблем на платформе ubuntu, на которой мне нужно запустить код, я не могу установить этот пакет (у меня ушло три дня на его решение). Итак, я ищу альтернативу.

У меня есть случайный набор точек в диапазоне от 3 до 1000 точек. Я хочу нарисовать выпуклую оболочку / многоугольник вокруг большинства внешних точек (следующим шагом будет растрирование). Я пытался сделать это, преобразовав точки в растр, затем используя растровые полигонов, но в редких случаях точки будут находиться в одной и той же ячейке растра, что приводит только к двум уникальным точкам. Convaveman превратил бы это в линейный многоугольник (чего я и хочу, без использования concaveman). Вот входные данные, которые могут быть проблематичными:

 x <- structure(list(x = c(166.867, 166.867, 167.117, 166.8667), y = c(-20.6333, 
-20.633, -20.833, -20.6333)), row.names = c(NA, -4L), class = c("tbl_df", 
"tbl", "data.frame"))
  

Это то, что я не пробовал (с ошибкой, которую я получаю):

 SP_pt       <- SpatialPoints(x, proj4string=crs(" proj=longlat  ellps=WGS84 ` towgs84=0,0,0,0,0,0,0  no_defs"))`
gridded(SP_pt) <- T
SP_pt_R     <- raster(SP_pt)
SP_poly     <- rasterToPolygons(SP_pt_R, dissolve = T)

suggested tolerance minimum: 0.333333 
Error in points2grid(points, tolerance, round) : 
  dimension 1 : coordinate intervals are not constant
  

Ответ №1:

Вы можете использовать chull в базовом R:

 sp::Polygon(x[c(chull(x), chull(x)[1]), ])
#> An object of class "Polygon"
#> Slot "labpt":
#> [1] 166.95023 -20.69977
#> 
#> Slot "area":
#> [1] 6.75e-05
#> 
#> Slot "hole":
#> [1] FALSE
#> 
#> Slot "ringDir":
#> [1] 1
#> 
#> Slot "coords":
#>             x        y
#> [1,] 167.1170 -20.8330
#> [2,] 166.8667 -20.6333
#> [3,] 166.8670 -20.6330
#> [4,] 167.1170 -20.8330

  

Или, если вы хотите использовать sf пакет:

 sf::st_polygon(list(as.matrix(x[c(chull(x), chull(x)[1]),])))
#> POLYGON ((167.117 -20.833, 166.8667 -20.6333, 166.867 -20.633, 167.117 -20.833))
  

Комментарии:

1. Спасибо! Почему-то я не могу преобразовать полученный полигон в sf .. есть идеи?

2. При попытке я получаю следующую ошибку: Ошибка в методе использования («st_cast»): нет применимого метода для ‘st_cast’, применяемого к объекту класса «c (‘Polygon’, ‘Line’)»

3. @Shark167 почему бы просто не создать st_polygon напрямую, если вы хотите использовать sf ? Смотрите мое обновление

4. Хороший момент, но тогда он все равно не позволит мне растеризировать: Ошибка в (function (classes, fdef, mtable) : не удалось найти унаследованный метод для функции ‘rasterize’ для подписи ‘»XY», «RasterLayer»’ Дополнительно: Предупреждающее сообщение: неизвестный или неинициализированный столбец : individualCount .

5. РЕДАКТИРОВАТЬ: на самом деле хотелось бы растрировать его с помощью ‘fasterize’, но это выдает мне следующее сообщение: Ошибка в fasterize (y, WorldGrd, field = NULL): не удалось преобразовать с помощью функции R: as.data.frame.

Ответ №2:

Вы можете использовать dismo::convHull , а затем использовать predict или rasterize

 library(dismo)
xy <- cbind(x=c(1,1,2,2), y=c(3,2,1,2))
# must be matrix or data.frame, not a tbl
ch <- convHull(xy)
plot(ch)

# predict
r <- raster(xmn=0, xmx=5, ymn=0, ymx=5, res=.25)
p <- predict(ch, r)

# Or rasterize
sp <- polygons(ch)
x <- rasterize(sp, r)
  

Для более быстрой растеризации вы можете использовать terra

 library(terra)
v <- vect(sp)
rr <- rast(r)
y <- rasterize(v, rr)
  

Для приведения sp к sf

 sf <- as(sp, "sf")