मिमी इकाइयों में लगातार-आयामित बहुभुज बनाना?


11

मेरे पास एक फ़ंक्शन है जो सौर फोटोवोल्टिक पैनलों को बहुभुज के रूप में प्रस्तुत करता है। अनिवार्य रूप से, यह एक आयताकार ग्रिड बनाता है जहाँ उपयोगकर्ता निम्नलिखित मापदंडों को निर्दिष्ट कर सकता है:

  • लंबाई
  • चौड़ाई
  • क्षैतिज दूरी
  • ऊर्ध्वाधर दूरी

कोड प्लगइन FeatureGridCreator पर आधारित है लेकिन केवल बहुभुज पहलू पर ध्यान केंद्रित कर रहा है। यह अधिकांश भाग के लिए अच्छी तरह से काम करता है, खासकर जब बड़े आयामों (जैसे 10 मीटर लंबाई और चौड़ाई; 10 मीटर क्षैतिज और ऊर्ध्वाधर दूरी) के साथ बहुभुज बनाते हैं।

लेकिन मैंने कुछ मुद्दों पर ध्यान दिया:

  1. जब लंबाई और चौड़ाई दोनों के लिए आयामों को 2 मीटर से कम करने के लिए बहुभुज निर्दिष्ट करते हैं, तो कोई बहुभुज नहीं बनाए गए थे।

  2. विभिन्न आयामों (जैसे 5 मीटर लंबाई और 7 मीटर चौड़ाई) के साथ बहुभुज निर्दिष्ट करते समय, माप लाइन उपकरण के साथ मापा जाने पर आयाम समान नहीं थे । इन आयामों के लिए, लंबाई और चौड़ाई क्रमशः 4m और 6m दिखाई गई।

    भिन्न लंबाई और चौड़ाई का उदाहरण

प्रोजेक्शन और लेयर दोनों के लिए इस्तेमाल किया जाने वाला CRS EPSG: 27700 है, हालाँकि मुझे नहीं लगा होगा कि यह कोई समस्या होगी।

तो क्या किसी को भी इस बात का कोई अंदाजा है कि इन मुद्दों का क्या कारण हो सकता है? मैं सुझावों के लिए भी खुला हूं कि कैसे कोड में सुधार किया जा सकता है या एक बेहतर विकल्प के साथ प्रतिस्थापित किया जा सकता है।


यहाँ कोड है जिसे पायथन कंसोल में पुन: पेश किया जा सकता है , बहुभुज परत को फ़ंक्शन चलाने से पहले एक प्रासंगिक सीआरएस के साथ चुना जाना चाहिए:

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)

जवाबों:


11

आपका एल्गोरिथ्म समझ में आता है, लेकिन ऐसा लगता है कि आपकी समस्या एक गोल त्रुटि के कारण है जब आप 2000 से विभाजित करते हैं (पूर्णांक द्वारा विभाजित करते हैं, जो बताता है कि एक संख्या दो से छोटी क्यों 0 देती है, और सभी दूरी भी मानों तक गोल हैं)

आपको पूर्णांक विभाजन को एक फ्लोट डिवीजन के साथ बदलना चाहिए

l = length / 2000

होना चाहिए

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

या

l = float(length) / 2000

ध्यान दें कि यह आपको फॉर्म द्वारा दर्ज किए गए सटीक आयाम देता है, लेकिन आप अपने पार्सल के आकार को एक मीटर पर गोल करने का निर्णय ले सकते हैं:

l = float(length/1000) / 2

ध्यान दें कि आपको प्रारंभ निर्देशांक पर गोलाई की भी जांच करनी चाहिए, लेकिन मुझे नहीं पता कि यह गोलाई उद्देश्य पर है या नहीं।

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

मुझे लगता है कि इससे मेरे द्वारा बताए गए मुद्दों का समाधान हो गया है (विडंबना यह है कि मैंने कुछ नए मुद्दों को देखा है लेकिन लगता है कि वे हल हो गए हैं)। आगे भी इसका परीक्षण जारी रखेगा और वापस रिपोर्ट करेगा। बहुत धन्यवाद :)
यूसुफ

हाँ, मुझे विश्वास है कि आपके समाधान ने काम किया है। फिर से धन्यवाद;)
जोसेफ

3

@Radouxju के लिए धन्यवाद , यहां अंतिम कोड है जो क्षैतिज और ऊर्ध्वाधर दूरी को शून्य होने का भी ध्यान रखता है:

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))

  • का उपयोग कर generate_pv_panels(5500, 5000, 20, 1):

    दृष्टांत 1


  • का उपयोग कर generate_pv_panels(5500, 5000, 20, 0):

    दृश्य २

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.