Затиснути Просторовий об’єкт до обмежувального поля в R


14

З огляду на просторовий об’єкт у R, як я вирізаю, що всі його елементи лежать у обмежувальній коробці?

Я хотів би зробити дві речі (в ідеалі я б знав, як це зробити і те, і інше є прийнятним рішенням моєї нинішньої проблеми - обмеження форми профілю багатокутника до континентальних США).

  1. Закиньте кожен елемент не повністю в обмежувальний ящик. Здається, це bbox()<-було б логічним шляхом, але такого методу не існує.

  2. Зробіть справжню операцію із затисканням, щоб неінфінітимальні елементи (наприклад, багатокутники, лінії) були відрізані на межі . sp::bboxне вистачає методу присвоєння, тому єдиний спосіб, який я придумав, - це використовувати overабо gContains/ gCrossesв поєднанні з об'єктом SpatialPolygons, що містить поле з новими координатами обмежувального поля. Тоді під час відсікання об’єкта багатокутника вам доведеться з’ясувати, які містяться проти хреста, та змінити координати цих многокутників, щоб вони не перевищували поле. Або щось подібне gIntersection. Але напевно є простіший спосіб?

Хоча я знаю, що існує багато проблем з обмежувальними коробками , і що просто переважання просторового накладання на багатокутник, який визначає область, яка цікавить, в багатьох ситуаціях обмежувальні коробки працюють добре і простіше.


Щоб було зрозуміло, якщо ваш просторовий об’єкт розширений (багатокутники або лінії), ви хочете вирізати його таким чином, щоб він повертав лише шматок його, що знаходиться всередині вашої заданої міри? Я не думаю, що існує простіший спосіб.
Розміщений

@Spacedman Пояснив, що мене цікавить і те, і інше, але більш простої версії вистачить для цього питання.
Арі Б. Фрідман

Ви вже реалізували рішення для (2) за допомогою rgeos? Здається, що ви принаймні спробували. Чи можете ви дати нам це рішення та приклад, щоб, принаймні, нам було з чим порівняти для «простоти»? Бо, чесно кажучи, це здається досить простим.
Розміщений

@Spacedman Все просто; просто потрібен час .... :-) Я спробував це gIntersectionі придумав Error in RGEOSBinTopoFunc(spgeom1, spgeom2, byid, id, "rgeos_intersection") : TopologyException: no outgoing dirEdge found at 3 2.5 немає часу для налагодження сьогодні; написав неохайну версію і виправить це в майбутньому.
Арі Б. Фрідман

Відповіді:


11

Я створив для цієї мети невелику функцію, і її використовували інші з хорошими відгуками!

gClip <- function(shp, bb){
  if(class(bb) == "matrix") b_poly <- as(extent(as.vector(t(bb))), "SpatialPolygons")
  else b_poly <- as(extent(bb), "SpatialPolygons")
  gIntersection(shp, b_poly, byid = TRUE)
}

Це повинно вирішити вашу проблему. Подальше пояснення тут: http://robinlovelace.net/r/2014/07/29/clipping-with-r.html

У b_polyствореному багатокутнику манекена немає рядка proj4, що призводить до " Попередження: spgeom1 та spgeom2 мають різні рядки proj4 ", але це нешкідливо.


Я sp, maptools, rgdalі rgeosзавантажений. Error in .class1(object) : could not find function "extent"Можливо, я отримав випуск версії R / пакет?
gregmacfarlane

Зверніть увагу на рядок library(raster)у моєму підручнику: robinlovelace.net/r/2014/07/29/clipping-with-r.html повідомте нам, як ви дістаєтесь! Ура.
RobinLovelace

Це створює попереджувальне повідомлення для мене: spgeom1 та spgeom2 мають різні рядки proj4. Додавання proj4string (b_poly) <- proj4string (shp) має вирішити це?
Матифу

7

Ось недбала межа версії (достатня для задоволення моїх потреб вчасно до мінімуму завтрашнього дня :-)):

#' Convert a bounding box to a SpatialPolygons object
#' Bounding box is first created (in lat/lon) then projected if specified
#' @param bbox Bounding box: a 2x2 numerical matrix of lat/lon coordinates
#' @param proj4stringFrom Projection string for the current bbox coordinates (defaults to lat/lon, WGS84)
#' @param proj4stringTo Projection string, or NULL to not project
#' @seealso \code{\link{clipToExtent}} which uses the output of this to clip to a bounding box
#' @return A SpatialPolygons object of the bounding box
#' @example 
#' bb <- matrix(c(3,2,5,4),nrow=2)
#' rownames(bb) <- c("lon","lat")
#' colnames(bb) <- c('min','max')
as.SpatialPolygons.bbox <- function( bbox, proj4stringFrom=CRS("+proj=longlat +datum=WGS84"), proj4stringTo=NULL ) {
  # Create unprojected bbox as spatial object
  bboxMat <- rbind( c(bbox['lon','min'],bbox['lat','min']), c(bbox['lon','min'],bbox['lat','max']), c(bbox['lon','max'],bbox['lat','max']), c(bbox['lon','max'],bbox['lat','min']), c(bbox['lon','min'],bbox['lat','min']) ) # clockwise, 5 points to close it
  bboxSP <- SpatialPolygons( list(Polygons(list(Polygon(bboxMat)),"bbox")), proj4string=proj4stringFrom  )
  if(!is.null(proj4stringTo)) {
    bboxSP <- spTransform( bboxSP, proj4stringTo )
  }
  bboxSP
}


#' Restrict to extent of a polygon
#' Currently does the sloppy thing and returns any object that has any area inside the extent polygon
#' @param sp Spatial object
#' @param extent a SpatialPolygons object - any part of sp not within a polygon will be discarded
#' @seealso \code{\link{as.SpatialPolygons.bbox}} to create a SP from a bbox
#' @return A spatial object of the same type
#' @example
#' set.seed(1)
#' P4S.latlon <- CRS("+proj=longlat +datum=WGS84")
#' ply <- SpatialPolygons(list(Polygons(list(Polygon(cbind(c(2,4,4,1,2),c(2,3,5,4,2)))), "s1"),Polygons(list(Polygon(cbind(c(5,4,2,5),c(2,3,2,2)))), "s2")), proj4string=P4S.latlon)
#' pnt <- SpatialPoints( matrix(rnorm(100),ncol=2)+2, proj4string=P4S.latlon )
#' # Make bounding box as Spatial Polygon
#' bb <- matrix(c(3,2,5,4),nrow=2)
#' rownames(bb) <- c("lon","lat")
#' colnames(bb) <- c('min','max')
#' bbSP <- as.SpatialPolygons.bbox(bb, proj4stringTo=P4S.latlon )
#' # Clip to extent
#' plyClip <- clipToExtent( ply, bbSP )
#' pntClip <- clipToExtent( pnt, bbSP )
#' # Plot
#' plot( ply )
#' plot( pnt, add=TRUE )
#' plot( bbSP, add=TRUE, border="blue" )
#' plot( plyClip, add=TRUE, border="red")
#' plot( pntClip, add=TRUE, col="red", pch="o")
clipToExtent <- function( sp, extent ) {
    require(rgeos)
    keep <- gContains( extent, sp,byid=TRUE ) | gOverlaps( extent, sp,byid=TRUE )
    stopifnot( ncol(keep)==1 )
    sp[drop(keep),]
}

відсікання bbox

Якщо вам потрібне обмежувальне поле для проектування, версія тут додає interpolateаргумент, так що отримане проектоване поле буде кривим.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.