将空间对象裁剪到R中的边界框


14

给定R中的Spatial对象,我如何裁剪其所有元素以使其位于边界框中?

我想做两件事(理想情况下,我会做这两种事情,但是对我当前的问题来说,这都是可以接受的解决方案-将多边形shapefile限制在美国本土)。

  1. 将每个元素都未完全放入边界框中。 这似乎bbox()<-是合乎逻辑的方法,但是不存在这种方法。

  2. 进行真正的裁剪操作,以使非无限小元素(例如,多边形,直线)在边界处被切除sp::bbox缺少赋值方法,所以我想出的唯一方法是将overgContains/ gCrosses与包含带有新边界框坐标的框的SpatialPolygons对象结合使用。然后,在剪切多边形对象时,您必须找出包含的对象与交叉对象,并更改这些多边形的坐标,以使其不会超出框。或类似的东西gIntersection。但是肯定有更简单的方法吗?

虽然我知道边界框存在很多问题,并且通常最好在定义感兴趣区域的多边形上进行空间覆盖,但在许多情况下,边界框可以正常工作并且更简单。


只是要清楚一点,如果扩展了Spatial对象(多边形或线),您想对其进行切割,使其仅返回给定范围内的一部分?我认为没有更简单的方法。
Spacedman

@Spacedman阐明我对这两者都感兴趣,但较简单的版本足以解决当前问题。
Ari B. Friedman

您是否已经使用rgeos实现了(2)的解决方案?听起来您至少已尝试过。您能否给我们提供解决方案和示例,以便至少我们可以将“简单性”与之进行比较?因为,老实说,这似乎很简单。
Spacedman

@Spacedman一切都很简单;只是花时间.... :-)我尝试了一下,gIntersection并想出了Error in RGEOSBinTopoFunc(spgeom1, spgeom2, byid, id, "rgeos_intersection") : TopologyException: no outgoing dirEdge found at 3 2.5 今天没有时间进行调试;写了一个草率的版本,将来会修复。
Ari B. Friedman 2013年

Answers:


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字符串 ”,但这是无害的。


我有spmaptoolsrgdal,和rgeos加载。我可能遇到Error in .class1(object) : could not find function "extent"R / package版本问题?
gregmacfarlane 2014年

请注意library(raster)我的教程中的这一行:robinlovelace.net/r/2014/07/29/clipping-with-r.html让我们知道您的生活!干杯。
RobinLovelace 2014年

这对我产生警告消息:spgeom1和spgeom2具有不同的proj4字符串。添加proj4string(b_poly)<-proj4string(shp)应该可以解决吗?
Matifou

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参数,以使生成的投影框是弯曲的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.