I have a function which creates Wind Turbines represented as points. Essentially, it uses the code from the Random points inside polygons (fixed) tool albeit with some slight changes.
The goal is to create random points inside polygons taking into account the minimum distance specified. This works very well especially with polygons which are not close to another (e.g. a single polygon):
However, if the polygon is close to or adjoined to another polygon (e.g. as shown below), the points from each polygon can be within the minimum distance as shown in red:
How could I change the code so that those points in red are not close to another from a nearby polygon?
Ideally, I would like multiple points to be replaced by a single point:
Here is the code which can be reproduced in the Python Console, a polygon layer must be selected with a relevant CRS before running the function:
import random
from PyQt4.QtCore import QVariant
def checkMinDistance(point, index, distance, points):
if distance == 0:
return True
neighbors = index.nearestNeighbor(point, 1)
if len(neighbors) == 0:
return True
if neighbors[0] in points:
np = points[neighbors[0]]
if np.sqrDist(point) < (distance * distance):
return False
return True
def generate_wind_turbines(spacing):
layer = iface.activeLayer()
crs = layer.crs()
# Memory layer
memory_lyr = QgsVectorLayer("Point?crs=epsg:" + unicode(crs.postgisSrid()) + "&index=yes", "Wind turbines for " + str(layer.name()), "memory")
QgsMapLayerRegistry.instance().addMapLayer(memory_lyr)
memory_lyr.startEditing()
provider = memory_lyr.dataProvider()
provider.addAttributes([QgsField("ID", QVariant.Int)])
# Variables
point_density = 0.0001
fid = 1
distance_area = QgsDistanceArea()
# List of features
fts = []
# Create points
for f in layer.getFeatures():
fGeom = QgsGeometry(f.geometry())
bbox = fGeom.boundingBox()
pointCount = int(round(point_density * distance_area.measure(fGeom)))
index = QgsSpatialIndex()
points = dict()
nPoints = 0
fid += 1
nIterations = 0
maxIterations = pointCount * 200
random.seed()
while nIterations < maxIterations and nPoints < pointCount:
rx = bbox.xMinimum() + bbox.width() * random.random()
ry = bbox.yMinimum() + bbox.height() * random.random()
pnt = QgsPoint(rx, ry)
geom = QgsGeometry.fromPoint(pnt)
if geom.within(fGeom) and checkMinDistance(pnt, index, spacing, points):
f = QgsFeature(nPoints)
f.setAttributes([fid])
f.setGeometry(geom)
fts.append(f)
index.insertFeature(f)
points[nPoints] = pnt
nPoints += 1
nIterations += 1
provider.addFeatures(fts)
memory_lyr.updateFields()
memory_lyr.commitChanges()
generate_wind_turbines(500)
Edit:
Dissolving and/or converting the polygons to singleparts does not seem to help much as the generated points still seem to fall within the minimum distance.
Tested on QGIS 2.18.3.