在SpatialPolygon中/内部计算质心 [英] Calculate Centroid WITHIN / INSIDE a SpatialPolygon

查看:138
本文介绍了在SpatialPolygon中/内部计算质心的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在ArcMap之类的软件中,可以为多边形 中的多边形创建质心.在如下所示的情况下,这是必要的.

In Software like ArcMap one can create centroids for polygons within a polygon. In cases like the one shown below this is necessary.

R中,可以使用rgeos::gCentroid()计算空间多边形的质心.但是,没有办法强制在多边形内计算质心.

In R it is possible to calculate centroids of spatial polygons with rgeos::gCentroid(). However there is no way to force the calculation of centroids within the polygon.

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计算.

gCentroid() creates a centroid which in this specific case is located outside of the polygon. Despite being geometrically correct, some applications require centroids within the polygon, as they can be calculated by ArcMap.

xCent <- gCentroid(x, byid = TRUE)
points(xCent, col = "red", pch = 16)

所需的输出(来自ArcMap)如下所示:

A desired output (from ArcMap) looks like this:

在R中是否有可能生成这样的质心?

Is there any possibility to generate centroids like this in R?

编辑:

经过挖掘,事实证明ArcMap在多边形"中选择了一个随机点:

After some digging, it turns out that ArcMap picks a random point within the Polygon:

对于输入多边形:输出点将在多边形内部."

"For an input polygon: the output point will be inside the polygon."

因此问题必须是:是否有一个函数可以在多边形内的任意随机位置创建一个点?

Thus the question has to be: is there a function that creates a point at any random position WITHIN the polygons?

推荐答案

sf解决方案

随着sf软件包的出现,事情变得简单了一些.只需使用:

sf solution

With the advent of the sf package, things got a bit easier. Just use:

library(sf)
y <- st_as_sf(x) # only necessary when you don't already have an sf object
st_point_on_surface(y)

返回保证在(多)曲面上的点."

正如Question更新中所指出的那样,ArcMap似乎只是将点放置在多边形内的任意位置.这也可以通过gPointsOnSurface(..., n = 1, type = 'random')来实现.

As pointed out in the updates of the Question, it seems that ArcMap is just putting a point at a random location within the polygon. This can be achieved by gPointsOnSurface(..., n = 1, type = 'random') as well.

xCent2 <- gPointOnSurface(x, byid = T)
points(xCent2, col = "blue", pch = 16)

我编写了此函数,该函数首先找到质心,如果它不在之内上(即它不与多边形重叠/相交),则将其替换为表面上的一个点.此外,它返回一个新列,该列指示一个点是否为真实质心.

I wrote this function which first finds the centroid and, if it is not on within (i.e. it does not overlap / intersect the polygon), it is substituted by a point on the surface. Furhtermore, it returns a new column which indicates if a point is the real centroid or not.

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, ])
  })

  if(all(centsInOwnPoly) == TRUE){
        return(centsDF)
    }

  else {
    # 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)
  }

这篇关于在SpatialPolygon中/内部计算质心的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆