# An arcpy solution for randomizing overlapping points within a shape?

298
2
01-21-2022 05:18 PM New Contributor

I have a shapefile layer with polygons for the 50 U.S. states ("States"). I also have a point featureclass with potentially many overlapping points at the centroid of each state polygon ("Dots").

I want to use the CreateRandomPoints_management() function to find new placements for all the points in each state, essentially creating a 1:1 dot density map with clickable point features.

Here's the workflow I have envisioned:

1. Loop through and select each state, one by one
2. Get the count of points contained within each state polygon boundary
3. Use CreateRandomPoints_management to generate count number of randomized points within each state boundary
4. Move the original points to the new random locations and then delete the random points layer -or- Add fields and assign values to the newly created random points layer from the original points [Whichever's simpler and more reliable]

I've tried several times to write this code, but my arcpy chops aren't that great yet. Any ideas or examples would be greatly appreciated!

Tags (3)
1 Solution

Accepted Solutions by MVP Esteemed Contributor

Solved: Re: Dispersing geocoded points within a Polygon - Esri Community

Hope the following script works for you (Courtesy @XanderBakker and ArcPy Team)

``````#-------------------------------------------------------------------------------
# Name:        Disperse3.py
# Purpose:     Disperse points in multiple polygons
# Author:      arcpy Team
#              http://arcpy.wordpress.com/2013/06/07/disperse-overlapping-points/
# Created:     02-dec-2013
#-------------------------------------------------------------------------------

import arcpy
import random

def main():
fcPoints = r"C:\Project\_Forums\Disperse\test.gdb\points3"
fcPolygon = r"C:\Project\_Forums\Disperse\test.gdb\Polygons"
arcpy.env.overwriteOutput = True

with arcpy.da.SearchCursor(fcPolygon, ("SHAPE@")) as cursor:
for row in cursor:
polygon = row
disperse_points(fcPoints, polygon)
del row

def point_in_poly(poly, x, y):
pg = arcpy.PointGeometry(arcpy.Point(x, y), poly.spatialReference)
return poly.contains(pg)

def disperse_points(in_points, polygon):
lenx = polygon.extent.width
leny = polygon.extent.height
with arcpy.da.UpdateCursor(in_points, "SHAPE@XY") as points:
for p in points:
if point_in_poly(polygon, p, p):
# I changed code here!
x = (random.random() * lenx) + polygon.extent.XMin
y = (random.random() * leny) + polygon.extent.YMin
inside = point_in_poly(polygon, x, y)
while not inside:
x = (random.random() * lenx) + polygon.extent.XMin
y = (random.random() * leny) + polygon.extent.YMin
inside = point_in_poly(polygon, x, y)
points.updateRow([(x, y)])
else:
pass # don't update location if point doesn't originally falls inside current polygon

if __name__ == '__main__':
main()‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍``````

*Change the path of the point and polygon feature classes in Line No. 13/14.

Think Location
2 Replies by MVP Esteemed Contributor

Solved: Re: Dispersing geocoded points within a Polygon - Esri Community

Hope the following script works for you (Courtesy @XanderBakker and ArcPy Team)

``````#-------------------------------------------------------------------------------
# Name:        Disperse3.py
# Purpose:     Disperse points in multiple polygons
# Author:      arcpy Team
#              http://arcpy.wordpress.com/2013/06/07/disperse-overlapping-points/
# Created:     02-dec-2013
#-------------------------------------------------------------------------------

import arcpy
import random

def main():
fcPoints = r"C:\Project\_Forums\Disperse\test.gdb\points3"
fcPolygon = r"C:\Project\_Forums\Disperse\test.gdb\Polygons"
arcpy.env.overwriteOutput = True

with arcpy.da.SearchCursor(fcPolygon, ("SHAPE@")) as cursor:
for row in cursor:
polygon = row
disperse_points(fcPoints, polygon)
del row

def point_in_poly(poly, x, y):
pg = arcpy.PointGeometry(arcpy.Point(x, y), poly.spatialReference)
return poly.contains(pg)

def disperse_points(in_points, polygon):
lenx = polygon.extent.width
leny = polygon.extent.height
with arcpy.da.UpdateCursor(in_points, "SHAPE@XY") as points:
for p in points:
if point_in_poly(polygon, p, p):
# I changed code here!
x = (random.random() * lenx) + polygon.extent.XMin
y = (random.random() * leny) + polygon.extent.YMin
inside = point_in_poly(polygon, x, y)
while not inside:
x = (random.random() * lenx) + polygon.extent.XMin
y = (random.random() * leny) + polygon.extent.YMin
inside = point_in_poly(polygon, x, y)
points.updateRow([(x, y)])
else:
pass # don't update location if point doesn't originally falls inside current polygon

if __name__ == '__main__':
main()‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍``````

*Change the path of the point and polygon feature classes in Line No. 13/14.

Think Location New Contributor

Thanks, Jayanta! That function does look like it might do what I need. 