Mm biriminde tutarlı bir şekilde boyutlandırılmış çokgenler mi üretiyorsunuz?


11

Çokgen olarak temsil edilen Solar Fotovolatic panelleri oluşturan bir fonksiyonum var. Temel olarak, kullanıcının aşağıdaki parametreleri belirtebileceği dikdörtgen bir ızgara oluşturur:

  • uzunluk
  • Genişlik
  • Yatay mesafe
  • Dikey mesafe

Kod, FeatureGridCreator eklentisine dayanır, ancak yalnızca çokgen yönüne odaklanır. Özellikle büyük boyutlarda (örneğin 10m uzunluk ve genişlik; 10m yatay ve dikey mesafeler) çokgenler oluştururken çoğunlukla iyi çalışır.

Ama birkaç konuyu fark ettim:

  1. Hem uzunluk hem de genişlik için 2 metreden küçük boyutlar için çokgenler belirtilirken, çokgen oluşturulmaz.

  2. Farklı boyutlara (örneğin 5m uzunluk ve 7m genişlik) sahip çokgenler belirtilirken, Ölçüm Çizgisi aracıyla ölçüldüğünde boyutlar aynı değildi . Bu boyutlar için uzunluk ve genişliğin sırasıyla 4m ve 6m olduğu gösterilmiştir.

    Farklı uzunluk ve genişlik örneği

Hem projeksiyon hem de katman için kullanılan CRS, EPSG: 27700 olsa da bunun bir sorun olacağını düşünmezdim.

Peki bu sorunlara neyin sebep olabileceği hakkında bir fikri olan var mı? Kodun nasıl geliştirilebileceği veya daha iyi bir alternatifle nasıl değiştirilebileceği konusunda da önerilere açığım.


Python Konsolunda çoğaltılabilen kod , işlevi çalıştırmadan önce ilgili bir CRS ile bir çokgen katmanının seçilmesi gerekir:

from PyQt4.QtCore import QVariant
from math import ceil

def generate_pv_panels(length, width, distance_x, distance_y):
    # Define layer properties
    layer = iface.activeLayer()
    crs = layer.crs()
    memory_lyr = QgsVectorLayer("Polygon?crs=epsg:" + unicode(crs.postgisSrid()) + "&index=yes", "PV panels for " + str(layer.name()), "memory")
    QgsMapLayerRegistry.instance().addMapLayer(memory_lyr)
    memory_lyr.startEditing()
    provider = memory_lyr.dataProvider()
    provider.addAttributes([QgsField("ID", QVariant.Int)])
    fid = 0
    start_x = 0
    start_y = 0
    # Ensure polygons are not created 'within each other'
    if distance_x < (length / 1000):
        distance_x = (length / 1000)
    if distance_y < (width / 1000):
        distance_y = (width / 1000)
    fts = []
    for f in layer.getFeatures():
        fid += 1
        bbox = f.geometry().boundingBox()
        start_x = bbox.xMinimum() + float(distance_x / 2)
        start_y = bbox.yMinimum() + float(distance_y / 2)
        for row in range(0, int(ceil(bbox.height() / distance_y))):
            for column in range(0, int(ceil(bbox.width() / distance_x))):
                fet = QgsFeature()
                geom_type = pv_panel_size(length, width, start_x, start_y)
                if f.geometry().contains(geom_type):
                    fet.setGeometry(geom_type)
                    fet.setAttributes([fid])
                    fts.append(fet)
                start_x += distance_x + (length / 1000)
            start_x = bbox.xMinimum() + float(distance_x / 2)
            start_y += distance_y + (width / 1000)
    provider.addFeatures(fts)
    memory_lyr.updateFields()
    memory_lyr.commitChanges()

def pv_panel_size(length, width, x, y):
    # Length & width measured in mm; x & y measured in m
    l = length / 2000
    w = width / 2000
    return QgsGeometry.fromRect(QgsRectangle(x - l, y - w, x + l, y + w))

generate_pv_panels(10000, 10000, 100, 100)

Yanıtlar:


11

Algoritmanız mantıklı, ancak 2000'e bölündüğünüzde sorununuz bir yuvarlama hatasından kaynaklanıyor gibi görünüyor (tamsayıya bölün, bu ikiden küçük bir sayının neden 0 verdiğini ve tüm mesafelerin eşit değerlere yuvarlandığını açıklar)

Tamsayı bölümünü bir kayan bölümle değiştirmelisiniz

l = length / 2000

olmalı

l = length / 2000. # the . makes sure that you divide by a decimal value

veya

l = float(length) / 2000

Bunun, form tarafından girilen tam boyutları verdiğini unutmayın, ancak isterseniz parsellerinizin boyutunu bir metrede yuvarlamaya karar verebilirsiniz:

l = float(length/1000) / 2

Başlangıç ​​koordinatlarındaki yuvarlamayı da kontrol etmeniz gerektiğini unutmayın, ancak bu yuvarlamanın kasıtlı olup olmadığını bilmiyorum.

start_x = bbox.xMinimum() + float(distance_x) / 2

Bunun bahsettiğim sorunları çözdüğünü düşünüyorum (ironik olarak, bazı yeni sorunların olduğunu fark ettim ama çözüldüklerini düşünüyorum). Bunu daha fazla test etmeye devam edip rapor vereceğim. Çok teşekkürler :)
Joseph

Evet, inanıyorum ki çözümünüz işe yaradı. Tekrar teşekkür ederim;)
Joseph

3

@Radouxju sayesinde , yatay ve dikey mesafelerin sıfır olduğunu da dikkate alan son kod:

from PyQt4.QtCore import QVariant
from math import ceil

def generate_pv_panels(length, width, distance_x, distance_y):
    # Define layer properties
    layer = iface.activeLayer()
    crs = layer.crs()
    memory_lyr = QgsVectorLayer("Polygon?crs=epsg:" + unicode(crs.postgisSrid()) + "&index=yes", "PV panels for " + str(layer.name()), "memory")
    QgsMapLayerRegistry.instance().addMapLayer(memory_lyr)
    memory_lyr.startEditing()
    provider = memory_lyr.dataProvider()
    provider.addAttributes([QgsField("ID", QVariant.Int)])
    # Define variables
    fid = 0
    start_x = 0
    start_y = 0
    state_x = False
    state_y = False
    # Ensure polygons are not created 'within each other' if distance is zero;
    # Instead they will align on the bounding box
    if distance_x == 0:
        distance_x = (length / 1000)
        state_x = True
    if distance_y == 0:
        distance_y = (width / 1000)
        state_y = True
    fts = []
    for f in layer.getFeatures():
        fid += 1
        bbox = f.geometry().boundingBox()
        start_x = bbox.xMinimum() + float(distance_x / 2)
        start_y = bbox.yMinimum() + float(distance_y / 2)
        for row in range(0, int(ceil(bbox.height() / distance_y))):
            for column in range(0, int(ceil(bbox.width() / distance_x))):
                fet = QgsFeature()
                geom_type = pv_panel_size(length, width, start_x, start_y)
                if f.geometry().contains(geom_type):
                    fet.setGeometry(geom_type)
                    fet.setAttributes([fid])
                    fts.append(fet)
                if state_x == False:
                    start_x += distance_x + (length / 1000)
                else:
                    start_x += distance_x
            start_x = bbox.xMinimum() + float(distance_x / 2)
            if state_y == False:
                start_y += distance_y + (width / 1000)
            else:
                start_y += distance_y
    provider.addFeatures(fts)
    memory_lyr.updateFields()
    memory_lyr.commitChanges()

def pv_panel_size(length, width, x, y):
    # Length & width measured in mm; x & y measured in m
    l = float(length) / 2000
    w = float(width) / 2000
    return QgsGeometry.fromRect(QgsRectangle(x - l, y - w, x + l, y + w))

  • Kullanma generate_pv_panels(5500, 5000, 20, 1):

    Senaryo 1


  • Kullanma generate_pv_panels(5500, 5000, 20, 0):

    Senaryo 2

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.