2

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?

maycca
  • 3,848
  • 5
  • 36
  • 67
  • A possible solution could be: 1. Create a large polygon around you current polygons 2. calculate the neighbours 3. compare the calculated number of neighbours with your original number of neighbours. All polygons with an open edge will have +1 neighbours. – Koot6133 Jan 27 '20 at 10:46
  • @Koot6133, thank you for suggestion. Does the data work now? It works for me in incognito mode as well. The shapefile contains 4 files, all of them need to be downloaded. Please, can you be more specific how my neighbors1 and neighbors2 will be generated? I like the idea about differencing is as +1 neighbor! :) – maycca Jan 27 '20 at 11:29
  • Hmm weird I still can't acces the data. Neighbours1 you already created by calculating the neighbours. Neighbours2 you can create by: 1. Creating a large rectangle around your polygons. 2. Do the same calculation as you did for Neighbours1. Then substract Neighbours1 from Neighbours2. – Koot6133 Jan 27 '20 at 12:05
  • @Koot6133, I added the data also on google drive, saved as zipped file. Does it works now? – maycca Jan 28 '20 at 06:32
  • Unfortunately it seems very hard to add another polygon to a SpatialPolygonsDataframe in R. I created a question here: https://stackoverflow.com/questions/59933458/adding-a-polygon-to-a-spatialpolygonsdataframe. Maybe it is possible to create an extra polygon in another programm – Koot6133 Jan 29 '20 at 13:38

1 Answers1

0

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:

  • has no neighbors
  • difference between tree height in neighbors and surrounding stands is less than 5
  • if the spatial erase `buffer - neighbors' is more then certain value, here I use 16 m.

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

maycca
  • 3,848
  • 5
  • 36
  • 67