OK, so I created a script that is capable of creating the 300 random points and connect them to 409 lines without intersections of lines. See below the result of two separate runs:
and
Note that there can be points that do not participate in any line.
The script that created these results is listed below:
import arcpy
def main():
import random
import math
arcpy.env.overwriteOutput = True
fc_pnt = r'C:\GeoNet\RandomPoints2Lines\data.gdb\points'
fc_line = r'C:\GeoNet\RandomPoints2Lines\data.gdb\lines'
sr = arcpy.SpatialReference(3116)
number_lines = 409
number_points = 300
max_diag_cutoff = 0.2
min_diag_cutoff = 0.05
xmin = 830000
xmax = 838000
ymin = 1180000
ymax = 1186000
print "create the random points"
points = []
dct_pntg = {}
for oid in range(number_points):
x = random.randrange(xmin, xmax)
y = random.randrange(ymin, ymax)
pnt = arcpy.Point(x, y)
pntg = arcpy.PointGeometry(pnt, sr)
points.append(pntg)
dct_pntg[oid] = pntg
arcpy.CopyFeatures_management(points, fc_pnt)
diag_length = math.hypot(xmax-xmin, ymax-ymin)
max_dist_allowed = diag_length * max_diag_cutoff
min_dist_allowed = diag_length * min_diag_cutoff
print "create a dct of distances"
dct_dist = {}
cnt = 0
for oid1, pntg1 in sorted(dct_pntg.items()):
if oid1 % 25 == 0:
print "oid1", oid1
for oid2 in range(oid1, number_points):
cnt += 1
pntg2 = dct_pntg[oid2]
dist = getDistance(pntg1, pntg2)
if all([dist <= max_dist_allowed, dist >= min_dist_allowed]):
oid_key = "{0}
dct_dist[oid_key] = dist
print "number of possible lines:", cnt
print "lines to be considered:", len(dct_dist.keys())
print "let's create some lines"
dct_lines = {}
for oid_key, dist in dct_dist.items():
lst_oid = oid_key.split('
oid1 = int(lst_oid[0])
oid2 = int(lst_oid[1])
polyline = createLine(dct_pntg[oid1], dct_pntg[oid2])
if linesIntersect(dct_lines, polyline, oid_key) == False:
dct_lines[oid_key] = polyline
if len(dct_lines.keys()) >= number_lines:
break
print "store the result"
lines_found = dct_lines.values()
arcpy.CopyFeatures_management(lines_found, fc_line)
def getDistance(pntg1, pntg2):
'''Calculate the distance between two point geometries'''
return pntg1.distanceTo(pntg2)
def createLine(pntg1, pntg2):
'''Create a line from two point geometries'''
sr = pntg1.spatialReference
return arcpy.Polyline(arcpy.Array([pntg1.firstPoint, pntg2.firstPoint]), sr)
def linesIntersect(dct_lines, polyline, oid_key):
'''Verify if lines cross (lines may share start and end points)'''
intersect = False
lst_oid = oid_key.split('
oid1 = int(lst_oid[0])
oid2 = int(lst_oid[1])
for oid_key2, line in dct_lines.items():
lst_oid2 = oid_key2.split('
oid3 = int(lst_oid2[0])
oid4 = int(lst_oid2[1])
if all([oid3 != oid1, oid3 != oid2, oid4 != oid1, oid4 != oid2]):
if line.crosses(polyline):
intersect = True
break
return intersect
if __name__ == '__main__':
main()
To run this script you will have to change a number of settings according to your specific needs:
- lines 10 and 11 the output featureclass that will be created for the random points and lines
- line 12 the spatial reference to be used for the output featureclasses
- lines 15 and 16 set the number of points and lines to be created
- lines 17 and 18 set the minimum and maximum lengths of the lines to be created (possibilities to be considered). Long lines are more probable to have intersections so don't make them too long and perhaps it is not desired that points located directly next to each other are considered in the process
- lines 21 to 24 indicate the extent in which the random points will be created
Try it for yourself and see what the result is. If you have any problems please let me know and we'll see how we can fix it.
Kind regards, Xander