# How to rename points by clockwise direction or change starting point in polygon features?

I have a polygon feature class. I convert it to a point. Name of field (for example !Number!) in a point feature converted from polygon "A2"(The first point should be in the upper left corner (relative to north) of the polygon.) must match the direction of points in a clockwise. I know "AutoIncrement ()" at using Field Calculator, to change the numerical name of points by OBJECTID, but the point ID identifier sometimes do not match with the clockwise direction. Only one method that I know is to copy the contents of a table in Excel and renumber as I need. Then insert into ArcGIS the modified table in Excel and "display XY data"->"Data"->"Export data to point features". But maybe someone knows how to do it easier?

• Do you need to create new polygons so the vertex order starts in the Upper-Left or do you want a list of vertices, for each polygon, in the corrected order? Commented Nov 22, 2013 at 0:28
• Both variants are good. I know how to fix the order of the vertices using Excel, but it is slow and not always convenient method. As a result, I need to make a list of vertices (including coordinates) for each polygon in the correct order. And the correct order of the vertices must be displayed on the map. I need the fastest possible way. Commented Nov 26, 2013 at 0:08
• Perhaps it might look like , 1 Use the repair tool geometry and vertex IDs goes clockwise direction . 2 converted polygons to points. 3 in attribute table using python autoIncrement () "expression. cal" 4 From upper left points are numbered with pStart = 1. 5 The rest of the points are numbered with pStart => next number of the last numbered point in paragraph 4 . 6 As a result, the point of going clockwise direction points are numbered as I need to . But they have the wrong ID order. Maybe it's not so important. Do you think there is another way more faster? Commented Nov 26, 2013 at 5:32
• Hi Jannik, did you find out a solution to your problem? Also interested if there is a way of doing this. Commented Sep 12, 2016 at 5:19

Use the Repair Geometry tool - the polygon will be reset as clockwise direction.

The Check Geometry documentation says:

Incorrect ring ordering—The polygon is topologically simple, but its rings may not be oriented correctly (outer rings—clockwise, inner rings—counterclockwise).

While the Repair Geometry documentation does not mention clockwise/counterclockwise but says:

Incorrect ring ordering: The geometry will be updated to have correct ring ordering.

• The first point should be in the upper left corner (relative to north) of the polygon. Commented Nov 21, 2013 at 9:02
• There is no topological requirement in GIS software that specifies where the first point should be. What is the rationale for such a need? Commented Nov 21, 2013 at 9:04
• Conditions of numbering for issue of cadastral parcels. Commented Nov 21, 2013 at 9:31
• @Jannik but how do you define the upper left with complex shapes. Like in your exemple 6 is the left poitn, but 9 is the uppr point and 8 could be a "corner" candidate. Commented Sep 12, 2016 at 5:56
• Agree with @radouxju starting point requires better definition, e.g. nearest to NW corner of shape extent Commented Sep 18, 2016 at 20:25

The polygon below was created counterclockwise (not sure if it matters) starting at point 11/15. The point furthest to the left will get objectid 1.

``````import arcpy
arcpy.env.workspace=r'D:\Arenden_D\Dribbel\flip.gdb'
arcpy.env.overwriteOutput=1
arcpy.env.outputCoordinateSystem = 'D:\Projektionsfiler\SWEREF99TM.prj'

#Create points from polygon vertices
arcpy.FeatureVerticesToPoints_management(in_features='counterclockwise_polygon', out_feature_class='clockwise_points')
#Duplicate points are created at start/stop, removing one
with arcpy.da.UpdateCursor('clockwise_points',['OBJECTID'], 'OBJECTID = 1') as ucursor:
for row in ucursor:
ucursor.deleteRow()

#create a list of x, y, and objectid of the clockwise points
coordinates = [f for f in arcpy.da.SearchCursor('clockwise_points',['SHAPE@X','SHAPE@Y','OBJECTID'])]

#find starting point = point furthest to the left
start_point = sorted(coordinates)[0]
#find index of start point in coordinates list
index_of_start_point = [i for i,x in enumerate(coordinates) if x[2]==start_point[2]]

#move start point to first position in list
coordinates.insert(0,coordinates.pop(int(index_of_start_point[0])))

#find index of points with smaller OBJECTID than start point
index_of_lesserpoints = [j for j,z in enumerate(coordinates) if z[2]<start_point[2]]

#create a new list and add coordinate pairs with Objectids in the right order starting with OBJECTID of start_point
coordinates_in_order=[]
coordinates_in_order.extend((coordinates[0],))
coordinates_in_order.extend(coordinates[1+max(index_of_lesserpoints):])
coordinates_in_order.extend(coordinates[min(index_of_lesserpoints):1+max(index_of_lesserpoints)])

#create a new point fc and insert points
arcpy.CreateFeatureclass_management(out_path=arcpy.env.workspace, out_name='new_clockwise_points', geometry_type='POINT')
with arcpy.da.InsertCursor('new_clockwise_points',['SHAPE@XY']) as icursor:
for pair in coordinates_in_order:
icursor.insertRow((pair[0:2],))
``````

• Great, Will give this a shot. Would you know how this would handle donuts? Commented Sep 19, 2016 at 3:40

INPUTS:

SCRIPT:

``````import arcpy

##  input parameters
mxd = arcpy.mapping.MapDocument("CURRENT")
polygons = arcpy.mapping.ListLayers(mxd,"PGONS")[0]
points = arcpy.mapping.ListLayers(mxd,"POINTS")[0]

##truncated coordinate as string
def truncate(f, n):
s = '{}'.format(f)
i, p, d = s.partition('.')
return '.'.join([i, (d+'0'*n)[:n]])

with arcpy.da.SearchCursor(polygons,["SHAPE@","MB2013"]) as cursor:
for shp,idL in cursor:
##      get extent NW corner
ext=shp.extent
UL=arcpy.PointGeometry(ext.upperLeft)
Q='"MB2013" = %s'%("'"+idL+"'")
points.definitionQuery=Q
aList=[];pLine=shp.boundary()
##      order points along boundary at new start
dMin=1e6
with arcpy.da.SearchCursor(points,"SHAPE@") as pCur:
for line in pCur:
pnt=line[0].firstPoint
L=pLine.measureOnLine(pnt)
d=UL.distanceTo(pnt)
if d<dMin: dMin=d;lMin=L
aList.append([L,pnt])
for i,(L,pnt) in enumerate(aList):
if L>=lMin: aList[i][0]=L-lMin
else:aList[i][0]=L+pLine.length-lMin
##     dictionary of points signatures and chainage
newList=sorted(aList)
for i,(L,pnt) in enumerate(newList):
aKey=truncate(pnt.X,2)+truncate(pnt.Y,2)
##      transfer new order to points table
with arcpy.da.UpdateCursor(points,("SHAPE@","GroupNo")) as pCur:
for pnt,no in pCur:
aKey=truncate(pnt.firstPoint.X,2)+truncate(pnt.firstPoint.Y,2)
``````

RESULT:

I hope there are enough comments in the script to understand a method I applied. It is tested on shapefiles and of course field names are to be changed

• This great, would you know how this would handle with donuts in the shape? Commented Sep 19, 2016 at 3:39
• It most likely will, providing points are sitting on the outer ring only, multipart - unlikely. Just test it, no harm expected Commented Sep 19, 2016 at 3:54

The Production Mapping extension includes a Set Origin Vertex tool that may suit your purposes:

A polygon is a collection of rings. Rings contain collections of points, or vertices, which describe a closed path. The first vertex, number 0, in the outermost ring of a polygon is the origin vertex. Vertices are oriented in a clockwise direction from the origin vertex. The origin vertex is the from-point (and to-point) of the ring that encloses a polygon.

The Set Origin Vertex tool allows you to change the origin vertex of a polygon feature. The following workflows may require you to use this tool:

• Grid and graticules layers—Set an origin location for an area of interest.
• Suppress outline geometry effect—Control where line suppression starts.
• Ow it`s look like very simple but we don`t have "Production Mapping extension". Maybe you know another way? Commented Nov 22, 2013 at 8:43

Solving a portion of the problem, I recommend that the starting vertex is the vertex closest to the NW corner of the polygon's minimum bounding box (MBR).

An efficient processing function for the entire problem would:

1. Create a temporary array of vertex, old and new vertex order
2. Create a temporary point geometry variable and store the MBR NW cnr in it
3. Read in a geometry into the temp array
4. Measure each vertex distance to the NW corner of the MBR
5. Find the minimum distance of all measures in step 4
6. Assign that vertex as the start point (new order = 1)
7. Assign the remaining vertex orders as +1 from the new start point, proceeding in the old order
8. Update the geometry by recreating the vertex array in the new order
9. Return the updated geometry

Examples of how to implement such ordinate array processing, temporary variable assignment, etc. can be found here for the case of SDO geometry storage in Oracle.

Not strictly an easier solution than manipulation in Excel, but it scales well to lots of polygons.