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 .
sumber
Jawaban:
Anda harus mengubah dua hal agar ini berfungsi. Namun, Anda tidak akan mendapatkan turbin angin maksimum per area. Untuk ini, Anda perlu menjalankan beberapa iterasi untuk setiap nilai dan mendapatkan jumlah poin maksimal.
Saya telah memindahkan
index = QgsSpatialIndex()
dan dipoints = dict()
luar for loop. Kode akan terlihat seperti ini:EDIT:
Joseph benar. perubahan saya hanya bekerja untuk area yang benar-benar kecil. Saya telah menguji sekitar dan menemukan solusi baru dengan memindahkan dua variabel dari for for dan mengubah
pointCount
variabel.Saya sudah mengujinya dengan 500m dan ini hasilnya (dua percobaan berbeda):
sumber
Salah satu metode dapat membuat fungsi lain yang melakukan hal berikut:
Ini adalah fungsi yang saya gunakan:
Fungsi dapat dieksekusi segera di akhir
generate_wind_turbines()
fungsi dengan menggunakan:Ini memberikan hasil seperti yang ditunjukkan pada gambar dalam pertanyaan. Mungkin bukan solusi yang paling efisien tetapi tampaknya berhasil.
Beberapa contoh di mana titik merah adalah yang dihasilkan pada awalnya dan titik yang ditampilkan sebagai turbin dengan batas adalah hasil akhir:
generate_wind_turbines(500)
generate_wind_turbines(1000)
sumber