Saya memiliki fungsi yang menciptakan Turbin Angin yang direpresentasikan sebagai poin. Pada dasarnya, ia menggunakan kode dari titik acak di dalam alat poligon (tetap) meskipun dengan sedikit perubahan.
Tujuannya adalah untuk membuat titik acak di dalam poligon dengan mempertimbangkan jarak minimum yang ditentukan. Ini bekerja sangat baik terutama dengan poligon yang tidak dekat dengan yang lain (misalnya poligon tunggal):
Namun, jika poligon dekat atau berdampingan dengan poligon lain (misalnya seperti yang ditunjukkan di bawah), titik-titik dari setiap poligon dapat berada dalam jarak minimum seperti yang ditunjukkan dengan warna merah:
Bagaimana saya bisa mengubah kode sehingga titik-titik merah tidak dekat dengan yang lain dari poligon terdekat?
Idealnya, saya ingin beberapa poin diganti oleh satu titik:
Berikut adalah kode yang dapat direproduksi dalam Konsol Python , lapisan poligon harus dipilih dengan CRS yang relevan sebelum menjalankan fungsi:
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:
Melarutkan dan / atau mengonversi poligon menjadi bagian tunggal tampaknya tidak banyak membantu karena poin yang dihasilkan tampaknya masih berada dalam jarak minimum.
Diuji pada QGIS 2.18.3 .