1

Let say i have a SpatialPolygons object with 3 polygons data name groupexc:

library(raster) 
p1 <- matrix(c(2, 3, 4, 5, 6, 5, 4, 3, 2, 4, 5, 6, 5, 4, 3, 2, 3, 4), ncol=2)
p2 <- matrix(c(8, 9, 10, 11, 12, 11, 10, 9, 8, 4, 5, 6, 5, 4, 3, 2, 3, 4), ncol=2)
p3 <- matrix(c(5, 6, 7, 8, 9, 8, 7, 6, 5, 9, 10, 11, 10, 9, 8, 7, 8, 9), ncol=2)
groupexc <- spPolygons(p1, p2, p3)

And a SpatialPolygons object zoneexc that represents a single zone:

zoneexc = spPolygons(matrix(c(2,1,3,4,6,8,10,13,14,14,12,10,8,6,4,2,1,3,7,10,12,14,12,6,4,3,1,1,1,1,1,1), ncol=2))

Is there a way for me to expand the output from groupexc until it reach points in zoneexc?

before

plot(zoneexc, border='red', lwd=3)
plot(groupexc, add=TRUE, border='blue', lwd=2)
text(groupexc, letters[1:3]) 

enter image description here

after:

enter image description here

Any help would be appreciated.

Robert Hijmans
  • 40,301
  • 4
  • 55
  • 63
ahmad fikri
  • 61
  • 1
  • 8

1 Answers1

3

Here is an approximate solution. This approach might break for large problems, and it depends on having sufficient number of nodes in each polygon. But it may be good enough for your purpose.

# example data 
library(raster) 
p1 <- matrix(c(2, 3, 4, 5, 6, 5, 4, 3, 2, 4, 5, 6, 5, 4, 3, 2, 3, 4), ncol=2)
p2 <- matrix(c(8, 9, 10, 11, 12, 11, 10, 9, 8, 4, 5, 6, 5, 4, 3, 2, 3, 4), ncol=2)
p3 <- matrix(c(5, 6, 7, 8, 9, 8, 7, 6, 5, 9, 10, 11, 10, 9, 8, 7, 8, 9), ncol=2)
groups <- spPolygons(p1, p2, p3, attr=data.frame(name=c('a', 'b', 'c')))
zone <- spPolygons(matrix(c(2,1,3,4,6,8,10,13,14,14,12,10,8,6,4,2,1,3,7,10,12,14,12,6,4,3,1,1,1,1,1,1), ncol=2))

Now create nearest neighbor polygons. For this to work as below, you need dismo version 1.1-1 (or higher)

library(dismo)
# get the coordinates of the polygons    
g <- unique(geom(groups))
v <- voronoi(g[, c('x', 'y')], ext=extent(zone))
# plot(v)
# assign group id to the new polygons
v$group <- g[v$id, 1]

# aggregate (dissolve) polygons by group id
a <- aggregate(v, 'group')
# remove areas outside of the zone
i <- crop(a, zone)

# add another identifier 
i$name <- groups$name[i$group]

plot(i, col=rainbow(3))
text(i, "name", cex=2)
plot(groups, add=TRUE, lwd=2, border='white', lty=2)

white lines show original areas, now expanded to fill up the zone

To see how it works:

points(g[, c('x', 'y')], pch=20, cex=2)
plot(v, add=TRUE)
Robert Hijmans
  • 40,301
  • 4
  • 55
  • 63