An arcpy solution for randomizing overlapping points within a shape?

496
2
Jump to solution
01-21-2022 05:18 PM
BrianBowers1
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)
0 Kudos
1 Solution

Accepted Solutions
JayantaPoddar
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[0]
            disperse_points(fcPoints, polygon)
        del row
    print "ready..."

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[0][0], p[0][1]):
                # 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

View solution in original post

2 Replies
JayantaPoddar
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[0]
            disperse_points(fcPoints, polygon)
        del row
    print "ready..."

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[0][0], p[0][1]):
                # 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
BrianBowers1
New Contributor

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

0 Kudos