I wonder how can I define if the polygon has an open edge or not. I consider that polygon does not have an open edge if it is completely surrounded by neighbors.
Using wonderful poly2nb(fc)
I get back the list of neighbors: but, from this list, I don't know how many neighbors the cell has to have to be completely surrounded by neighbors? Here is the situation:
My central red
polygon has in both cases 3 neighbors, but has open edge (left) or is completely surrounded by neighbors (right). If using raster
format and queen case, completely surrounded cell requires 8 neighbors. If it is less, it is open cell. But, can I get something similar from poly2nb(fc)
and nb
object? Of course, my data can contain slivers and gaps between individual polygons, so I don't want entirely rely on overlapping edges or something else.
My real data is available on dropbox or googleDrive
And r code example to calculate the amount of neighbors:
setwd("U:/Desktop/raw/myDir")
# Read input forest stand data
forest_fc = readOGR(getwd(),
layer = "forest_fc")
# continuity based neighbourhood:
# import whole
# shapefile, do not split it by one feature at time
nb <- poly2nb(forest_fc,
#row.names = forest_fc,
snap = 0) # snap to correct for the gaps/slivers
# store the number of neighbours by cell
forest_fc$nb_count<- card(nb)
plot(forest_fc,
col = "white",
border = "grey")
plot(nb,
coordinates(forest_fc),
add = T,
lwd = 2,
col = "black",
pch = 16,
cex = 0.5)
text(forest_fc, "nb_count", col = "red", cex = 1.2)
How can I differentiate between completely surrounded polygons and polygons with open edge?
This solution combines the contiguity and distance based neighborhood. The neighbors are stands that are within the buffer distance from the central stand. The stand has open edge if:
Here is a schema about taking into account the different situation with open edge, which however has the same amount of neighbors:
My function loops through shapefile row by row. For each row, it identifies set of neighbors based on buffer, and compare the stands high with its neighbors. If the difference is less than 5, it additionally check for existence of gap by erasing neighbors from the buffer.
Here is the whole function:
defineOpenEdge <- function(spdf, treeHeight, distance = 10, pixel.width = 16, ...) {
# loop through the dataframe
spdf@data$open_edge <- FALSE
for (i in seq_along(spdf)) {
# define stands and leftover forest
one = spdf[i, ]
left = spdf[-i,]
# Create buffer and intersectb buffer with neighbors: evalues if any are left?
buff = buffer(one, distance)
# Identify neighbors
nbrs.buff <- left[which(gOverlaps(sp::geometry(buff),
sp::geometry(left),
byid = TRUE)),]
# Conditions for open edge:
# - no neighbors
if (nrow(nbrs.buff) == 0) {
spdf@data[i,]$open_edge <- TRUE
} else { # neighbors are smaller than the stands
# Compare the height of the stands:
height.one = rep(one@data$treeHeight, nrow(nbrs.buff))
height.nbrs = nbrs.buff@data$treeHeight
# Get the differences between the neighbouring stands
difference = height.one - height.nbrs
# compare here the tree heights of stands
if(any(difference > 5)) {
spdf@data[i,]$open_edge <- TRUE
# Check if there is a big gap in neighborhood
} else {
# Get the difference between two shapefiles???
int.buff.one = rgeos::gDifference(buff, nbrs.buff + one)
# Is the size of the openning larger than one pixel 16x16 m?
if (!is.null(int.buff.one) ) {
# Calculate area of intersected data
int.buff.one.area = gArea(int.buff.one)
if (int.buff.one.area > 16*16) {
spdf@data[i,]$open_edge <- TRUE
}
}
}
}
}
return(spdf)
}
This identifies, if stands have open edge or not. At buffer size 10 m, my stands with open edge are: