[GIS] Extracting border between contiguous polygons using ArcGIS for Desktop

arcgis-10.2arcgis-desktoparcpyborderspolygon

I have a shapefile with polygons representing unique populations. I want to determine contiguous polygons in my shapefile, and then extract the border separating contiguous polygons as a separate polyline file. Importantly, I require the created polyline file to indicate the two polygons it separates.

I am aware of Polygon Neighbor to produce a table of all contiguous pairs, but this doesn't help me extract borders as polylines.

Consider group A in the following example map:

Example Border

Group A has 8 contiguous pairs: AB, AC, AD, AE, AF, AG, AH, AI. I would like the output file to separate the aggregate border for group A into 8 separate lines, each line referencing only the shared border between each contiguous pair; e.g., the border of AH in red would be a single line in the output data. As noted before it is important that the output file also identifies the two groups each line separates.

To clarify, I require a general solution for all possible contiguous pairs in my dataset. I do not have a single group such as the example group A that I am interested in.

This question is similar to Extracting polyline of border between differing polygons using R or GRASS?, except I'm interested in a solution using ArcGIS 10.2 for Desktop. I have some knowledge of Python if an ArcPy solution is easiest.

Best Answer

This will convert your polygons into arcs very quickly. You need 2 layers in table of content: 1st - polylines, 2nd - polygons

import arcpy, traceback, os, sys,time
from arcpy import env
env.overwriteOutput = True
dissolved="in_memory/dissolved"

try:
    def showPyMessage():
        arcpy.AddMessage(str(time.ctime()) + " - " + message)

    mxd = arcpy.mapping.MapDocument("CURRENT")
    theLinksLayer=arcpy.mapping.ListLayers(mxd)[0]
    PGONS=arcpy.mapping.ListLayers(mxd)[1]
    arcpy.DeleteFeatures_management(theLinksLayer)
    curT = arcpy.da.InsertCursor(theLinksLayer,"SHAPE@")
    with arcpy.da.SearchCursor(PGONS, "Shape@") as cursor:
        for row in cursor:
            feat = row[0].boundary()
            curT.insertRow((feat,))
    arcpy.Dissolve_management(theLinksLayer, dissolved,"","", "SINGLE_PART")
    arcpy.DeleteFeatures_management(theLinksLayer)
    m=0
    arcpy.AddMessage("Dissolving ...")
    curT = arcpy.da.InsertCursor(theLinksLayer,"SHAPE@")
    with arcpy.da.SearchCursor(dissolved, "SHAPE@") as cursor:
        for row in cursor:
            m+=1
            curT.insertRow((row[0],))

    arcpy.Delete_management("in_memory")
    arcpy.RefreshActiveView()
    arcpy.AddMessage("\nPolygons unbuilt into %i lines\n" %m)
    del curT

except:
    message = "\n*** PYTHON ERRORS *** "; showPyMessage()
    message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
    message = "Python Error Info: " +  str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()

From here it is enough to spatially join lines to polygons (one to many, SHARE_A_LINE_SEGMENT_WITH) and dissolve output using line name and first, last polygon IDs to get this:

enter image description here