Eu tenho uma função que cria turbinas eólicas representadas como pontos. Essencialmente, ele usa o código dos pontos Aleatórios dentro da ferramenta polígonos (fixos) , embora com algumas pequenas alterações.
O objetivo é criar pontos aleatórios dentro dos polígonos, levando em consideração a distância mínima especificada. Isso funciona muito bem, especialmente com polígonos que não estão próximos de outro (por exemplo, um único polígono):
No entanto, se o polígono estiver próximo ou adjacente a outro polígono (por exemplo, como mostrado abaixo), os pontos de cada polígono podem estar dentro da distância mínima, como mostrado em vermelho:
Como eu poderia mudar o código para que esses pontos em vermelho não fiquem próximos de outros de um polígono próximo?
Idealmente, gostaria que vários pontos fossem substituídos por um único ponto:
Aqui está o código que pode ser reproduzido no Python Console , uma camada de polígono deve ser selecionada com um CRS relevante antes de executar a função:
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)
Editar:
Dissolver e / ou converter os polígonos em peças únicas não parece ajudar muito, pois os pontos gerados ainda parecem estar dentro da distância mínima.
Testado no QGIS 2.18.3 .