আর-তে বহুবিধ সেন্ট্রয়েডগুলি কীভাবে গণনা করতে হবে (অ-আকারের আকারের জন্য)


41

আমি এই প্রশ্নের উত্তর খুঁজে পেতে কিছুটা সময় ব্যয় করেছি। এটি গুগল অনুসন্ধান থেকে তাত্ক্ষণিকভাবে স্পষ্ট নয় , সুতরাং ভেবেছি উত্তরটি এখানে পোস্ট করা কার্যকর হতে পারে। অবিচ্ছিন্ন বহুভুজ সম্পর্কে একটি অতিরিক্ত প্রশ্নও রয়েছে ।

তাত্ক্ষণিক সহজ উত্তর: কমান্ডটি ব্যবহার করুন:

centroids <- getSpPPolygonsLabptSlots(polys)

(এই পাওয়া যায় বর্গ বিবরণ দ সর্বোচ্চ স্থানিক প্যাকেজের জন্য SpatialPolygonsDataFrame আর ডেটা ক্লাসের, SP )

এই হিসাবে ঠিক একই জিনিস বলে মনে হচ্ছে

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")

যেখানে সেন্ট (নীল) এবং সেন্ট্রয়েডস (লাল) অভিন্ন সেন্ট্রয়েড থাকে (কোডটি চালানোর পরে এটি প্লট হওয়া উচিত):

সেন্ট্রোডগুলি গণনা করে আর

এ পর্যন্ত সব ঠিকই. কিন্তু আপনি কিউজিআইএস-এ বহুভুজ সেন্ট্রয়েডগুলি গণনা করার সময় (মেনু: ভেক্টর | জ্যামিতি | বহুভুজ সেন্ট্রয়েড) অ-স্বতন্ত্র বহুভুজগুলির জন্য কিছুটা আলাদা ফলাফল পাওয়া যায়:

কিউজিআইএস বহুভুজ উত্পন্ন করে

সুতরাং এই প্রশ্নটি 3-জিনিস:

  1. একটি দ্রুত এবং সহজ উত্তর
  2. অন-সংলগ্ন বহুভুজগুলির জন্য সেন্ট্রয়েড গণনা করতে আর ব্যবহারকারী লোকদের জন্য একটি সতর্কতা
  3. মাল্টি-পার্ট (নন-কনজিস্টিউজ) বহুভুজের সঠিকভাবে অ্যাকাউন্টে এটি কীভাবে করা উচিত সে সম্পর্কে একটি প্রশ্ন

আমার উপরে জানতে হবে যে আমি কীভাবে উপরে বর্ণিত ফাংশনটি সেন্ট্রয়েডকে উদ্ধৃত করতে পারি। ধন্যবাদ
সান্তিয়াগো ফার্নান্দেজ

জিআইএস স্ট্যাকএক্সচেঞ্জে স্বাগতম! একটি নতুন ব্যবহারকারী হিসাবে ট্যুর নিন দয়া করে । এটি এই প্রশ্নের উত্তর না দিয়ে একটি নতুন প্রশ্ন হিসাবে উপস্থিত হবে। একটি নতুন প্রশ্ন হিসাবে পোস্ট করুন।
হাসি 15

উত্তর:


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
বেশ কয়েকটি আর এর স্থানিক প্যাকেজগুলির বিকাশকারী রজার বিভান্ডের মতে, এটি হ'ল: "হ্যাঁ।" বহুভুজন-শ্রেণীর "ক্লাস ডকুমেন্টেশনটি এই ঘটনাটি উল্লেখ করে না, কারণ অন্যান্য পয়েন্টগুলি বৈধভাবে লেবেল পয়েন্ট হিসাবে beোকানো যেতে পারে। ডিফল্ট নির্মাতা পলিগনস অবজেক্টের বৃহত্তম নন-হোল রিংয়ের সেন্ট্রয়েড ব্যবহার করে। - অসম্পূর্ণতা ব্যাখ্যা করে। stat.ethz.ch/pipermail/r-help/2009- ফেব্রুয়ারী / 187436.html । নিশ্চিত: gCentroid (sids, বাইড = সত্য) প্রকৃতপক্ষে সমস্যার সমাধান করে।
রবিনলোয়েস

আমার জন্য কাজ করে না ... এমনকি gCentroid (বহুভুজ, বাইড = সত্য) প্রয়োগ করলেও আমার সেন্ট্রয়েড দুটি বহুভুজের মধ্যে স্থান .. সুতরাং, আমি ধরে নিই যে সেগুলি বহুগুণ বহুভুজ হিসাবে বিবেচিত হয়? আমি কীভাবে এগুলিকে আলাদা করতে পারি? পয়েন্টগুলি (স্থানাঙ্ক (এসসি। ট্র্যাকস), pch = 16, কল = "নীল", সিক্স = 0.4) তবে উত্পাদনের ফলে বহুভুজ থেকে সেন্ট্রয়েড তৈরি হয় না ... ধন্যবাদ!
maycca

Stat.ethz.ch এর লিঙ্কটি আর কাজ করে না। কেবলমাত্র নিখুঁততার
এক্সোকম

8

এখানে এসএফ ব্যবহার করে একটি পন্থা। আমি যেমন দেখিয়েছি, 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
}

ধীর অথচ খুব সুন্দর ফলাফল দেয়। এটি ভাল কেন্দ্রিক এবং লেবেল স্থাপনের জন্য একটি ভাল ফলাফল দেয়
বাসটিয়েন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.