disperse points

3185
4
Jump to solution
10-01-2015 09:58 AM
JayMukherjee
New Contributor III

Is there a way to disperse coincidental points randomly within a polygon and maintain the attributes?

Thanks!

0 Kudos
1 Solution

Accepted Solutions
JoshuaBixby
MVP Esteemed Contributor

Are you interested in randomly placing a point within a Polygon, moving an existing point to a new location while maintaining it attributes, or both?  Since the latter question is a bit more straightforward to answer, I will start there.

Moving an existing point to a new location while maintaining its attributes....

This can be accomplished using an update cursor, I prefer ArcPy Data Access cursors.  Assuming you have an existing list of coincident points to be moved as well as a list of new point locations that are randomly placed with a polygon of interest, the basic structure of an update cursor would look like this:

with arcpy.da.UpdateCursor(fc, ["OID@","SHAPE@XY"]) as cur:
    for oid, xy in cur:
        if oid in move_oid_list:
            cur.updateRow([oid, new_xy])

Since you didn't ask about identifying coincident points, I will assume you already have a method of doing that, which leaves the issue of a new random point.

Randomly placing a point within a Polygon....

With the limited information provided in the original question, it is hard to know exactly what to suggest.  There are built-in tools (Create Random Points), quick-and-dirty approximate methods for moving limited number of points, and of course, one could roll his own based on the many different mathematical approaches found across the web.

I sometimes use a random point generator that involves generating points within a polygon's extent and then checking to see whether they are contained within the polygon.

def RandomPoints(polygon):
    from random import uniform
    ext = polygon.extent
    while True:
        pt = arcpy.Point(uniform(ext.XMin, ext.XMax), uniform(ext.YMin, ext.YMax))
        if polygon.contains(pt):
            yield pt

If you are generating tens of thousands of points or more, performance of the code might become an issue, but it does have an extremely small memory footprint since new points are created on demand instead of the Create Random Points tool that generates all of them at once.  The built-in tool, though, takes a more mathematically/statistically rigorous approach so that needs to weigh into one's decision as well.

Modifying my update cursor code to use the RandomPoints function would look like:

with arcpy.da.UpdateCursor(fc, ["OID@","SHAPE@XY"]) as cur:
    for oid, xy in cur:
        if oid in move_oid_list:
            rndPts = RandomPoints(constraining_polygon)  
            new_pt = next(rndPts)
            new_xy = (new_pt.X, new_pt.Y)
            cur.updateRow([oid, new_xy)])

I nested the RandomPoints function within the oid loop under the thought that the constraining polygon could vary by each point being moved.

If you are going to use the built-in tool, you can create a feature class of random points in memory and then either use a search cursor to access the points or copy them into a list of points using the Copy Features tool.

View solution in original post

4 Replies
ChrisDonohue__GISP
MVP Alum

If you need to do this for purely cartographic reasons, you can make Representations ​of your points and then use this (setting it to "Random"):

Disperse Markers (Cartography)

ArcGIS Help (10.2, 10.2.1, and 10.2.2)

Chris Donohue, GISP

JayMukherjee
New Contributor III

i saw that but i am looking to move actual points with attributes.  thanks.

0 Kudos
PatrickMurphy
Occasional Contributor

Yes, I don't have the exact details, but the way you do it is break the polygon into the number of sub polys of equal area and then randomly place a point in each poly.  The way I have done this in the past was to use R to accomplish this.

This is a type of stratified random.  All requirements for randomness are maintained, that is, every point in the poly has an equal probability of being selected randomly.  This helps reduce the clumping and dispersion that is inherent in simple random point generation.

JoshuaBixby
MVP Esteemed Contributor

Are you interested in randomly placing a point within a Polygon, moving an existing point to a new location while maintaining it attributes, or both?  Since the latter question is a bit more straightforward to answer, I will start there.

Moving an existing point to a new location while maintaining its attributes....

This can be accomplished using an update cursor, I prefer ArcPy Data Access cursors.  Assuming you have an existing list of coincident points to be moved as well as a list of new point locations that are randomly placed with a polygon of interest, the basic structure of an update cursor would look like this:

with arcpy.da.UpdateCursor(fc, ["OID@","SHAPE@XY"]) as cur:
    for oid, xy in cur:
        if oid in move_oid_list:
            cur.updateRow([oid, new_xy])

Since you didn't ask about identifying coincident points, I will assume you already have a method of doing that, which leaves the issue of a new random point.

Randomly placing a point within a Polygon....

With the limited information provided in the original question, it is hard to know exactly what to suggest.  There are built-in tools (Create Random Points), quick-and-dirty approximate methods for moving limited number of points, and of course, one could roll his own based on the many different mathematical approaches found across the web.

I sometimes use a random point generator that involves generating points within a polygon's extent and then checking to see whether they are contained within the polygon.

def RandomPoints(polygon):
    from random import uniform
    ext = polygon.extent
    while True:
        pt = arcpy.Point(uniform(ext.XMin, ext.XMax), uniform(ext.YMin, ext.YMax))
        if polygon.contains(pt):
            yield pt

If you are generating tens of thousands of points or more, performance of the code might become an issue, but it does have an extremely small memory footprint since new points are created on demand instead of the Create Random Points tool that generates all of them at once.  The built-in tool, though, takes a more mathematically/statistically rigorous approach so that needs to weigh into one's decision as well.

Modifying my update cursor code to use the RandomPoints function would look like:

with arcpy.da.UpdateCursor(fc, ["OID@","SHAPE@XY"]) as cur:
    for oid, xy in cur:
        if oid in move_oid_list:
            rndPts = RandomPoints(constraining_polygon)  
            new_pt = next(rndPts)
            new_xy = (new_pt.X, new_pt.Y)
            cur.updateRow([oid, new_xy)])

I nested the RandomPoints function within the oid loop under the thought that the constraining polygon could vary by each point being moved.

If you are going to use the built-in tool, you can create a feature class of random points in memory and then either use a search cursor to access the points or copy them into a list of points using the Copy Features tool.