In ArcMap, I am using the Polygon Neighbors tool to generate a list of each polygon's adjacent polygons, or 'neighbors.' Currently, ArcMap orders the polygons using each polygon's numeric ID. What I would like to do is order each polygon's neighbor list in clockwise order relative to the center of the "source" polygon.

For example, in the picture below, if Polygon 1 is my source precinct, the neighbors currently appear ordered 2,3,4,5,6,7. I would like the ordering to be clockwise - say, 6,3,7,5,4,2. (The start of the list does not matter, only that they are clockwise relative to the starting neighbor in the list.)

Is there a way to do this in ArcMap?

Example of Polygon Neighbors

  • That looks like a random ordering to me. You can of course construct whatever attribute allocation scheme you want, but first you need to choose a programming environment, and then start programming. – Vince May 26 '19 at 21:15
  • Hi, @Vince. For clarification, which ordering are you saying looks random? – Anna Marie Vagnozzi May 26 '19 at 21:27
  • To do this I would try ArcPy and look at the angles between the centroid of the centre polygon and each of its neighbours. – PolyGeo May 26 '19 at 21:33
  • @PolyGeo, that's what I originally did. However, due to the irregular shapes of some of the polygons and the placement of their centroids, the order sorted by angles does not correspond to the clockwise order in many cases. Too many to fix manually, at least. – Anna Marie Vagnozzi May 26 '19 at 21:35
  • What about the angles between the centroid of the centre polygon and the points where it intersects each pair of neighbours? If that does not work then assembling a list of the coordinates where the centre polygon intersects each pair of its neighbours, and then examining them against each coordinate in the string of coordinates that make up the polygon should let you write a new list in the clock-wise order. – PolyGeo May 26 '19 at 21:54

This workflow will create mid points of edges between polygons and delete outer ones called "LINKS":

arcpy.FeatureToLine_management(in_features="PGONS", out_feature_class="C:/SCRATCH/OUTLINES.shp", cluster_tolerance="", attributes="NO_ATTRIBUTES")
arcpy.Dissolve_management(in_features="OUTLINES", out_feature_class="C:/SCRATCH/edges.shp", dissolve_field="", statistics_fields="", multi_part="SINGLE_PART", unsplit_lines="DISSOLVE_LINES")
arcpy.FeatureVerticesToPoints_management(in_features="edges", out_feature_class="C:/SCRATCH/midpoints.shp", point_location="MID")
arcpy.SpatialJoin_analysis(target_features="midpoints", join_features="PGONS", out_feature_class="C:/SCRATCH/SJ.shp", join_operation="JOIN_ONE_TO_MANY")
arcpy.Dissolve_management(in_features="SJ", out_feature_class="C:/SCRATCH/links.shp", dissolve_field="TARGET_FID", statistics_fields="JOIN_FID FIRST;JOIN_FID LAST", multi_part="SINGLE_PART", unsplit_lines="DISSOLVE_LINES")
arcpy.SelectLayerByAttribute_management(in_layer_or_view="links", selection_type="NEW_SELECTION", where_clause='"FIRST_JOIN" = "LAST_JOIN_"')

I thought to continue that way, but realised, that I don't know how to compute chainage on a closed line using linear referencing and I don't know model builder good enough to loop through polygons. So here you go:

import arcpy,os
import networkx as nx
with arcpy.da.SearchCursor(edges,("Shape@","FIRST_JOIN","LAST_JOIN_")) as cursor:
    for pG,f,t in cursor:
geometryList=[pgon.boundary() for pgon in arcpy.CopyFeatures_management(nodes,g)]
curT = arcpy.da.InsertCursor("out_points",("F","T","SHAPE@"))
for f in G.nodes():
    for t in nx.neighbors(G,f):
        chainage = outline.measureOnLine(p)
    for chainage,f,t,p in aList:
del curT


enter image description here

I connected some of the output points:

enter image description here

Note: tested on shapefiles.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.