คลิปวัตถุเชิงพื้นที่ไปยังกล่องขอบเขตใน R


14

ให้วัตถุเชิงพื้นที่ใน R ฉันจะคลิปองค์ประกอบทั้งหมดของมันให้อยู่ในกล่องที่มีขอบเขตได้อย่างไร

มีสองสิ่งที่ฉันต้องการจะทำ (นึกคิดฉันจะรู้วิธีที่จะทำทั้งสองอย่าง แต่ทั้งสองเป็นวิธีที่ได้รับการยอมรับในการแก้ไขปัญหาปัจจุบันของฉัน - การ จำกัด ไฟล์รูปหลายเหลี่ยมรูปร่างเพื่อทวีปสหรัฐอเมริกา)

  1. ปล่อยแต่ละองค์ประกอบไม่เต็มภายในกล่องขอบเขต ดูเหมือนว่าbbox()<-จะเป็นวิธีตรรกะ แต่ไม่มีวิธีการดังกล่าวอยู่

  2. ทำคลิปการดำเนินงานที่แท้จริงเช่นว่าไม่ใช่องค์ประกอบเล็ก (เช่นรูปหลายเหลี่ยมเส้น) ถูกตัดออกไปในขอบเขต sp::bboxไม่มีวิธีการกำหนดดังนั้นวิธีเดียวที่ฉันคิดจะใช้overหรือgContains/ gCrossesร่วมกับวัตถุ SpatialPolygons ที่มีกล่องที่มีพิกัดของกล่องขอบเขตใหม่ จากนั้นเมื่อตัดวัตถุรูปหลายเหลี่ยมคุณจะต้องคิดออกว่ามีรูปกากบาทอยู่ที่ไหนและตัดกันและเปลี่ยนพิกัดของรูปหลายเหลี่ยมเหล่านั้นเพื่อไม่ให้เกินกล่อง หรืออะไรทำนองgIntersectionนั้น แต่แน่นอนว่ามีวิธีที่ง่ายกว่า?

ในขณะที่ฉันรู้ว่ามีปัญหามากมายเกี่ยวกับกล่องที่มีขอบเขตและการซ้อนทับเชิงพื้นที่ไปยังรูปหลายเหลี่ยมที่กำหนดภูมิภาคที่น่าสนใจมักเป็นที่นิยมมากกว่าในหลาย ๆ สถานการณ์กล่องที่ทำงานได้ดีและเรียบง่ายกว่า


จะชัดเจนถ้าวัตถุอวกาศของคุณขยาย (รูปหลายเหลี่ยมหรือเส้น) คุณต้องการตัดมันเพื่อที่จะส่งคืนเฉพาะอันของวัตถุที่อยู่ในขอบเขตของคุณหรือไม่ ฉันไม่คิดว่าจะมีวิธีที่ง่ายกว่านี้
Spacedman

@ Spacerman ชี้แจงว่าฉันสนใจทั้งสองอย่าง แต่เวอร์ชั่นที่เรียบง่ายกว่านั้นก็เพียงพอแล้วสำหรับคำถามปัจจุบัน
Ari B. Friedman

คุณใช้วิธีแก้ปัญหากับ (2) โดยใช้ rgeos แล้ว ดูเหมือนคุณจะลองมาแล้วอย่างน้อย คุณช่วยให้เราแก้ปัญหานั้นและตัวอย่างดังนั้นอย่างน้อยเรามีสิ่งที่จะเปรียบเทียบกับ 'เรียบง่าย'? เพราะความจริงแล้วมันดูเรียบง่าย
Spacedman

@ Spacerman ทุกอย่างง่าย ๆ ; เพิ่งใช้เวลา .... :-) ฉันลองด้วยgIntersectionและมาพร้อมกับError in RGEOSBinTopoFunc(spgeom1, spgeom2, byid, id, "rgeos_intersection") : TopologyException: no outgoing dirEdge found at 3 2.5 ไม่มีเวลาให้ดีบั๊กวันนี้; เขียนรุ่นเลอะเทอะและจะแก้ไขในอนาคต
Ari B. Friedman

คำตอบ:


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) ควรแก้ปัญหาหรือไม่
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อาร์กิวเมนต์เพื่อให้กล่องฉายภาพที่ได้นั้นเป็นแบบโค้ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.