rspatialnearest-neighborneighbours

Has polygon have an open edge? Consider full/partial neighbors in R {spdep}


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:

enter image description here

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)

define open edge

How can I differentiate between completely surrounded polygons and polygons with open edge?


Solution

  • 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:

    enter image description here

    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:

    enter image description here