3

I have a shapefile with multiple polygons in which I want to distribute random points. Each polygon should contain exactly one point. The minimal distance between the random points should be 200m.

Now the ArcGIS tool "Create Random Points" has an option "Minimum allowed distance". This distance is only respected for random points within a polygon / stratum (see 1). How can I distribute random points where the minimal distance is resptected across polygons / strata?

This question was already asked as How to generate random points with minimum distances between points in multiple polygons. However, in my view, the question was not sufficently answered.

Found in the ArcGIS 10.2 Help:

This value will determine the minimum allowed distance between random points within each input feature. [..] Random points may be within the minimum allowed distance if they were generated inside or along different constraining feature parts.

2 Answers 2

1

I had initially posted the question on geonet. The matter being rather urgent, I posted the question here as well when I didn't recieve an answer there. In the meantime, Xander Bakker posted an excellent script that solves the problem neatly. The full answer can be view here, this is the section that solves the problem (with some slight modifications from me).

import arcpy
import random
import math

def main(path,fc_pol,fc_pnt,fc_mp,min_dist,number_of_points):
    # path = path for the input and output data
    # fc_pol = name of the input polygon shapefile
    # fc_pnt = name of the output point shapefile
    # fc_mp = name of the output point shapefile, used for visualization it and some manual checking
    arcpy.env.overwriteOutput = True

    arcpy.CreateFeatureclass_management(path, fc_pnt, "POINT")
    arcpy.CreateFeatureclass_management(path, fc_mp, "POINT")
    lst_all_pnts = []
    lst_mp = []
    cnt_pol = 0
    with arcpy.da.SearchCursor(path+fc_pol, "SHAPE@") as curs:
        for row in curs:
            cnt_pol += 1
            # print "polygon: {0}".format(cnt_pol)
            polygon = row[0]
            lst_pnts = []
            sr = polygon.spatialReference
            # create points inside polygons
            while len(lst_pnts) < number_of_points:
                print " - len(lst_pnts)={0}".format(len(lst_pnts))
                lst_pnts, bln_ok = add_random_point(lst_pnts, lst_all_pnts, polygon, min_dist)
                if bln_ok == False:
                    # saturation reached
                    print "saturation reached"
                    break
            # write points
            if len(lst_pnts) > 0:
                mp = create_multipoint(lst_pnts, sr)
                lst_mp.append(mp)
                lst_all_pnts.extend(lst_pnts)

    # create outputs
    sr = polygon.spatialReference
    lst_pntgeom = create_pointgeometry_list(lst_all_pnts, sr)
    arcpy.CopyFeatures_management(lst_pntgeom, path + fc_pnt)
    arcpy.CopyFeatures_management(lst_mp, path + fc_mp)
0

If it is a practical question I can suggest a bypass. Yet I don't know how to manipulate such a task, I can suggest, to create the points as suggested, using a field populated with 1's to restrict number of points generated within each polygon. As long as you don't create more than one point a polygon, you can leave the minimal distance untouched.

Second phase is to figure out if the output stand for your rule of minimal distance; that is using the point distance tool, with search radius set to the minimal distnace you wish, i.e. 200 meters. If the output table is empty, thus you have accomplished your task, otherwise - you have a list of the "problematic" points, which can be replaced by another random points creation, for only those polyogns that contain them. e.g. delete the points which are too close together, select empty polyogns and subset into a tmp. layer, generate random points using the tmp. layer etc.

As you can see this is an iterative process, which might function as an algorithm to solve your question; yet coding or modelling it might be problematic, in particular if your polygons are small in dimension, thus many iterations will be required to receive a valid solution. Otherwise, if your polygons are bigger than the 200 meters dimensions it worthwhile to give it a try manually.

EDIT: I've thought about a better workflow that can be coded (or modelled, thus coding will be better); however can't code it myself. Yet I hope it might help with the process. The main idea is to generate a random point (or points) within each polygon separately instead of generate all points together. Workflow follows:

  1. Sort polygon by area; small-to-large
  2. iterate by row (starting from the smallest polygon)
  3. create 1 random point in the selected polygon
  4. create another random point in the second polygon
  5. use point distance to measure distance between points, within your chosen minimal distance as a search radius
  6. Check if output table is empty - TRUE: merge points into one layer AND start phase 4 with the next polygon; FALSE: repeat steps 4 - 6 on the second polygon.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.