आर में बहुभुज सेंट्रोइड्स की गणना कैसे करें (गैर-सन्निहित आकार के लिए)


41

मैंने इस प्रश्न का उत्तर जानने के लिए थोड़ा समय बिताया है। यह Google खोज से तुरंत स्पष्ट नहीं है , इसलिए यहां पर उत्तर पोस्ट करना उपयोगी हो सकता है। गैर-सन्निहित बहुभुज के बारे में एक अतिरिक्त प्रश्न भी है ।

तत्काल आसान उत्तर: कमांड का उपयोग करें:

centroids <- getSpPPolygonsLabptSlots(polys)

(यह आर, एसपी में स्थानिक पैकेज के लिए SpatialPolygonsDataFrame R डेटा वर्ग के वर्ग विवरण में पाया गया था )

यह ठीक वैसा ही काम करने लगता है

cents <- SpatialPointsDataFrame(coords=cents, data=sids@data, proj4string=CRS("+proj=longlat +ellps=clrk66"))

निम्नलिखित कोड में, जो किसी भी आर इंस्टॉलेशन पर पुनरावृत्ति योग्य होना चाहिए (इसे आज़माएं!)

#Rcentroids
install.packages("GISTools")
library(GISTools)
sids <- readShapePoly(system.file("shapes/sids.shp", package="maptools")[1], 
                      proj4string=CRS("+proj=longlat +ellps=clrk66"))
class(sids)
plot(sids)
writeSpatialShape(sids, "sids")
cents <- coordinates(sids)
cents <- SpatialPointsDataFrame(coords=cents, data=sids@data, 
                  proj4string=CRS("+proj=longlat +ellps=clrk66"))
points(cents, col = "Blue")
writeSpatialShape(cents, "cents")

centroids <- getSpPPolygonsLabptSlots(sids)
points(centroids, pch = 3, col = "Red")

जहाँ सेंट (नीला) और केन्द्रक (लाल) समान केन्द्रक हैं (यह आपको कोड चलाने के बाद दिखाई देना चाहिए):

केन्द्रक की गणना R द्वारा की जाती है

अब तक सब ठीक है। लेकिन जब आप QGIS में बहुभुज केन्द्रक की गणना करते हैं (मेनू: वेक्टर | ज्यामिति | बहुभुज Centroids), गैर-सन्निहित बहुभुज के लिए थोड़ा भिन्न परिणाम होते हैं:

QGIS ने बहुभुज उत्पन्न किए

तो यह प्रश्न 3-बातें हैं:

  1. एक त्वरित और आसान जवाब
  2. आर का उपयोग करने वाले लोगों के लिए एक चेतावनी गैर-सन्निहित बहुभुज के लिए सेंट्रोइड्स की गणना करने के लिए
  3. बहु-भाग (गैर-सन्निहित) बहुभुज के लिए आर को ठीक से कैसे किया जाना चाहिए, इस बारे में एक प्रश्न

मुझे यह जानने की जरूरत है कि मैं ऊपर बताए गए फ़ंक्शन सेंट्रोइड का हवाला कैसे दे सकता हूं। के धन्यवाद
सैंटियागो फ़र्नांडीज़

GIS StackExchange में आपका स्वागत है! एक नए उपयोगकर्ता के रूप में कृपया यात्रा करें । यह एक नया प्रश्न प्रतीत होता है, बजाय इस प्रश्न के उत्तर के। कृपया एक नए प्रश्न के रूप में पोस्ट करें।
स्माइलर

जवाबों:


56

सबसे पहले, मुझे ऐसा कोई भी दस्तावेज नहीं मिला है जो यह कहता हो कि coordinatesया getSpPPolygonsLabptSlotsकेंद्र का द्रव्यमान केन्द्रक लौटाता है। वास्तव में बाद का कार्य अब 'पदावनत' के रूप में दिखता है और चेतावनी जारी करनी चाहिए।

केंद्र के द्रव्यमान के रूप में आप केन्द्रक की गणना के लिए क्या चाहते हैं gCentroid, rgeosपैकेज से कार्य है । कर help.search("centroid")यह पाया होगा।

trueCentroids = gCentroid(sids,byid=TRUE)
plot(sids)
points(coordinates(sids),pch=1)
points(trueCentroids,pch=2)

अंतर दिखाना चाहिए, और क्यूजीस सेंट्रोइड्स के समान होना चाहिए।


3
रोजर बीवंड के अनुसार, आर के स्थानिक पैकेजों के एक डेवलपर के अनुसार, यह करता है: "हाँ। क्लास का प्रलेखन?" पॉलीगन्सन-क्लास "यह नहीं बताता है कि यह मामला है, क्योंकि अन्य बिंदुओं को लेबल बिंदुओं के साथ वैध रूप से डाला जा सकता है। डिफ़ॉल्ट कंस्ट्रक्टर पॉलीगन्स ऑब्जेक्ट में सबसे बड़े नॉन-होल रिंग के सेंट्रोइड का उपयोग करता है। " - गैर-संदर्भ को स्पष्ट करता है। stat.ethz.ch/pipermail/r-help/2009-Febdays/187436.html । पुष्टि की गई: gCentroid (sids, byid = TRUE) वास्तव में समस्या का समाधान करता है।
रॉबिनवेल्स

मेरे लिए काम नहीं करता है ... यहां तक ​​कि अगर जीसेन्ट्रोइड (बहुभुज, बायिड = ट्रू) को लागू करने से मेरा सेंट्रोइड दो बहुभुजों के बीच होता है .. इस प्रकार, मुझे लगता है कि उन लोगों को बहुभुज माना जाता है? मैं उन्हें अलग कैसे कर सकता हूं? अंक (निर्देशांक (SC.tracks), pch = 16, col = "blue", cex = 0.4), हालांकि, उत्पादन बहुभुज से सेंट्रोइड का उत्पादन नहीं करता है ... धन्यवाद!
maycca

Stat.ethz.ch का लिंक अब काम नहीं करता है। पूर्णता के लिए, मुझे यकीन है कि उत्तर अब लगभग यहाँ मिल सकता है: r.789695.n4.nabble.com/…
एक्सॉनोम

8

यहाँ sf का उपयोग कर एक दृष्टिकोण है। जैसा कि मैंने प्रदर्शित किया, sf :: st_centroid और rgeos :: gCentroid के परिणाम समान हैं।

library(sf)
library(ggplot2)

# I transform to utm because st_centroid is not recommended for use on long/lat 
nc <- st_read(system.file('shape/nc.shp', package = "sf")) %>% 
  st_transform(32617)

# using rgeos
sp_cent <- gCentroid(as(nc, "Spatial"), byid = TRUE)

# using sf
sf_cent <- st_centroid(nc)

# plot both together to confirm that they are equivalent
ggplot() + 
  geom_sf(data = nc, fill = 'white') +
  geom_sf(data = sp_cent %>% st_as_sf, color = 'blue') + 
  geom_sf(data = sf_cent, color = 'red') 

यहाँ छवि विवरण दर्ज करें


3

इस समस्या को दूर करने के लिए मैंने जो किया वह एक ऐसा कार्य उत्पन्न करना है जो बहुभुज को नकारात्मक रूप से बफ़र करता है जब तक कि यह एक उत्तल बहुभुज की अपेक्षा करने के लिए काफी छोटा है। उपयोग करने का कार्य हैcentroid(polygon)

#' find the center of mass / furthest away from any boundary
#' 
#' Takes as input a spatial polygon
#' @param pol One or more polygons as input
#' @param ultimate optional Boolean, TRUE = find polygon furthest away from centroid. False = ordinary centroid

require(rgeos)
require(sp)

centroid <- function(pol,ultimate=TRUE,iterations=5,initial_width_step=10){
  if (ultimate){
    new_pol <- pol
    # For every polygon do this:
    for (i in 1:length(pol)){
      width <- -initial_width_step
      area <- gArea(pol[i,])
      centr <- pol[i,]
      wasNull <- FALSE
      for (j in 1:iterations){
        if (!wasNull){ # stop when buffer polygon was alread too small
          centr_new <- gBuffer(centr,width=width)
          # if the buffer has a negative size:
          substract_width <- width/20
          while (is.null(centr_new)){ #gradually decrease the buffer size until it has positive area
            width <- width-substract_width
            centr_new <- gBuffer(centr,width=width)
            wasNull <- TRUE
          }
          # if (!(is.null(centr_new))){
          #   plot(centr_new,add=T)
          # }
          new_area <- gArea(centr_new)
          #linear regression:
          slope <- (new_area-area)/width
          #aiming at quarter of the area for the new polygon
          width <- (area/4-area)/slope
          #preparing for next step:
          area <- new_area
          centr<- centr_new
        }
      }
      #take the biggest polygon in case of multiple polygons:
      d <- disaggregate(centr)
      if (length(d)>1){
        biggest_area <- gArea(d[1,])
        which_pol <- 1                             
        for (k in 2:length(d)){
          if (gArea(d[k,]) > biggest_area){
            biggest_area <- gArea(d[k,])
            which_pol <- k
          }
        }
        centr <- d[which_pol,]
      }
      #add to class polygons:
      new_pol@polygons[[i]] <- remove.holes(new_pol@polygons[[i]])
      new_pol@polygons[[i]]@Polygons[[1]]@coords <- centr@polygons[[1]]@Polygons[[1]]@coords
    }
    centroids <- gCentroid(new_pol,byid=TRUE)
  }else{
    centroids <- gCentroid(pol,byid=TRUE)  
  }  
  return(centroids)
}

#Given an object of class Polygons, returns
#a similar object with no holes


remove.holes <- function(Poly){
  # remove holes
  is.hole <- lapply(Poly@Polygons,function(P)P@hole)
  is.hole <- unlist(is.hole)
  polys <- Poly@Polygons[!is.hole]
  Poly <- Polygons(polys,ID=Poly@ID)
  # remove 'islands'
  max_area <- largest_area(Poly)
  is.sub <- lapply(Poly@Polygons,function(P)P@area<max_area)  
  is.sub <- unlist(is.sub)
  polys <- Poly@Polygons[!is.sub]
  Poly <- Polygons(polys,ID=Poly@ID)
  Poly
}
largest_area <- function(Poly){
  total_polygons <- length(Poly@Polygons)
  max_area <- 0
  for (i in 1:total_polygons){
    max_area <- max(max_area,Poly@Polygons[[i]]@area)
  }
  max_area
}

धीमा लेकिन बहुत अच्छा परिणाम देता है। यह अच्छी तरह से केंद्रित है और लेबल प्लेसमेंट के लिए एक अच्छा परिणाम देता है
बैस्टियन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.