Circling the point

Blog Post created by Dan_Patterson Champion on Feb 21, 2017

Again, points and directions have arisen.  This time, ...in this post ... ,there was a need to place points within a polygon for geocoding based on compass directions.  The simplest solution turns out to be to create a centroid, then generate points about it at some distance and angle.


So the solution can be approached using search cursors, but as usual, I like numpy since you can vectorize most operations.  The code below, reads in the centroid points of an input polygon theme (r"...\fishnet_label.shp") which in this case was the centroids of a fishnet since they are easy to create.  From there, the steps are simple:


  • convert the input point file to an array (FeatureClassToNumPyArray
  • collect the point coordinates that fall on a circle at a distance and angle from the centroid (_circle def)
  • stack the points and convert back to a point file (Numpyarraytofeatureclass)


Of course, you can put in the angles in the table, provide, sub-identifiers and even the compass representation in text form.  The points can also be created with random angles and distances with little code modification.  A couple of examples are below, followed by the code.  See Darren's example in the link for a cursor approach.


points around circle .... points around circle 2


And the code

:Script:  createcompass.py
:Author:  Dan_Patterson@carleton.ca
: if north angle is needed, you can use this to convert
:    ang = np.mod((450.0 - ang), 360.)

import numpy as np
import arcpy

def _circle(radius=10, theta=22.5, xc=0.0, yc=0.0):
    """Produce points around a circle.
    :  radius - distance from centre
    :  theta - either a single value to form angles about a circle or
    :        - a list or tuple of the desired angles

    if isinstance(theta, (list, tuple)):
        angles = np.deg2rad(np.array(theta))
        angles = np.deg2rad(np.arange(180.0, -180.0-theta, step=-theta))
    x_s = radius*np.cos(angles) + xc    # X values
    y_s = radius*np.sin(angles) + yc    # Y values
    pnts = np.c_[x_s, y_s]
    return pnts

# --------------------------------------------------------------------
if __name__ == '__main__':
    """produce some points around a centroid at angles and distances"""

    inFC = r"C:\Data\points\fishnet_label.shp"
    outFC = r"C:\Data\points\pnts2.shp"
    radius = 2
    theta = 22.5  # or a list like... theta = [0, 90, 180, 270]
    a = arcpy.da.FeatureClassToNumPyArray(inFC, ["SHAPE@X", "SHAPE@Y"])
    b = [_circle(radius, theta, a['SHAPE@X'][i], a['SHAPE@Y'][i])
         for i in range(len(a))]
    c = np.vstack(b)
    c.dtype = a.dtype
    arcpy.da.NumPyArrayToFeatureClass(c, outFC, c.dtype.names)


See other posts about circles and related things.

circles sectors rings buffers and the n-gons