Вычислить центроид внутри / внутри SpatialPolygon
в программном обеспечении, таком как ArcMap, можно создавать центроиды для полигонов внутри полигон. В случаях, подобных приведенному ниже, это необходимо.
на R
можно вычислить центроиды пространственных полигонов с помощью rgeos::gCentroid()
. Однако нет способа принудительно вычислить центроиды внутри полигона.
library(rgdal)
library(rgeos)
x <- readWKT("POLYGON ((1441727.5096940901130438 6550163.0046194596216083,
1150685.2609429201111197 6669225.7427449300885201,
975398.4520359700545669 6603079.7771196700632572,
866257.6087542800232768 6401334.5819626096636057,
836491.9242229099618271 6106985.0349301798269153,
972091.1537546999752522 5835786.5758665995672345,
1547561.0546945100650191 5782869.8033663900569081,
1408654.5268814601004124 5600968.3978968998417258,
720736.4843787000281736 5663807.0652409195899963,
598366.4479719599476084 6001151.4899297598749399,
654590.5187534400029108 6341803.2128998702391982,
869564.9070355399744585 6784981.1825891500338912,
1451649.4045378800947219 6788288.4808704098686576,
1441727.5096940901130438 6550163.0046194596216083))")
plot(x)
это полигон x
gCentroid()
создает центроид, который в данном конкретном случае находится вне многоугольника. Несмотря на геометрическую корректность, некоторые приложения требуют центроидов внутри полигона, поскольку они могут быть вычислены ArcMap.
xCent <- gCentroid(x, byid = TRUE)
points(xCent, col = "red", pch = 16)
желаемый вывод (из ArcMap) выглядит следующим образом:
есть ли возможность генерировать центроиды, подобные этому, в R?
редактировать:
после некоторые рытье, оказывается, ArcMap выбирает случайную точку внутри многоугольника:
" для входного многоугольника: выходная точка будет находиться внутри многоугольника."
таким образом, вопрос должен быть: есть ли функция, которая создает точку в любой случайной позиции внутри полигонов?
1 ответов
как указано в обновлениях вопроса, кажется, что ArcMap просто ставит точку в случайном месте внутри многоугольника. Это может быть достигнуто gPointsOnSurface(..., n = 1, type = 'random')
Как хорошо.
xCent2 <- gPointOnSurface(x, byid = T)
points(xCent2, col = "blue", pch = 16)
Я написал эту функцию, которая сначала находит центроид и, если она не включена внутри (т. е. он не перекрывает / не пересекает многоугольник), он заменяется точкой на поверхности. Furhtermore, он возвращает новый столбец, который указывает, является ли точка реальным центроидом или не.
gCentroidWithin <- function(pol) {
require(rgeos)
pol$.tmpID <- 1:length(pol)
# initially create centroid points with gCentroid
initialCents <- gCentroid(pol, byid = T)
# add data of the polygons to the centroids
centsDF <- SpatialPointsDataFrame(initialCents, pol@data)
centsDF$isCentroid <- TRUE
# check whether the centroids are actually INSIDE their polygon
centsInOwnPoly <- sapply(1:length(pol), function(x) {
gIntersects(pol[x,], centsDF[x, ])
})
# substitue outside centroids with points INSIDE the polygon
newPoints <- SpatialPointsDataFrame(gPointOnSurface(pol[!centsInOwnPoly, ],
byid = T),
pol@data[!centsInOwnPoly,])
newPoints$isCentroid <- FALSE
centsDF <- rbind(centsDF[centsInOwnPoly,], newPoints)
# order the points like their polygon counterpart based on `.tmpID`
centsDF <- centsDF[order(centsDF$.tmpID),]
# remove `.tmpID` column
centsDF@data <- centsDF@data[, - which(names(centsDF@data) == ".tmpID")]
cat(paste(length(pol), "polygons;", sum(centsInOwnPoly), "actual centroids;",
sum(!centsInOwnPoly), "Points corrected \n"))
return(centsDF)
}