J'ai une fonction qui crée des éoliennes représentées par des points. Essentiellement, il utilise le code des points aléatoires à l'intérieur de l' outil polygones (fixe) , mais avec quelques légères modifications.
L'objectif est de créer des points aléatoires à l'intérieur des polygones en tenant compte de la distance minimale spécifiée. Cela fonctionne très bien surtout avec des polygones qui ne sont pas proches les uns des autres (par exemple un seul polygone):
Cependant, si le polygone est proche ou adjacent à un autre polygone (par exemple, comme indiqué ci-dessous), les points de chaque polygone peuvent être dans la distance minimale comme indiqué en rouge:
Comment pourrais-je changer le code pour que ces points en rouge ne soient pas proches les uns des autres d'un polygone voisin?
Idéalement, je souhaite que plusieurs points soient remplacés par un seul:
Voici le code qui peut être reproduit dans la console Python , une couche polygonale doit être sélectionnée avec un CRS approprié avant d'exécuter la fonction:
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)
Éditer:
La dissolution et / ou la conversion des polygones en parties uniques ne semble pas beaucoup aider car les points générés semblent toujours se situer dans la distance minimale.
Testé sur QGIS 2.18.3 .