एक रेखा और एक मूल्य से लाइनों का एक आर्क बनाएं


9

मैं इस तरह एक उत्पत्ति-गंतव्य भूखंड को फिर से बनाने की कोशिश कर रहा हूं :

यहाँ छवि विवरण दर्ज करें

मैंने डेटा को MSOA में LAD टेबल में बदलने में कामयाबी हासिल की है और मैं मूल MDA में से किसी एक के लिए इस तरह का नक्शा बना सकता हूं।

यहाँ छवि विवरण दर्ज करें

एक बार जब आप पीक डिस्ट्रिक्ट कम्यूट में काम करने के लिए (अब हास्यास्पद) लोगों की दूरी की अनुमति देते हैं, तो यह करीब है।

लेकिन मैं उस प्रभाव को काफी पसंद करता हूं जो लेखक ने लाइनों को "अलग" करके हासिल किया है। जाहिर है, 522 और 371 के प्रवाह के साथ, मैं कम्यूटर प्रति एक लाइन के लिए नहीं जा सकता, लेकिन यात्रा करने वाले लोगों की संख्या दिखाने के लिए लाइनों के आनुपातिक चाप का उत्पादन करना अच्छा होगा।

मैंने सोचा था कि मैं ज्योमेट्री जनरेटर का उपयोग करने में सक्षम हो जाएगा, लेकिन लूप निर्माण के बिना, मैं हेडवे बनाने के लिए प्रतीत नहीं कर सकता।


यह ESRI उपकरण आपके लिए रुचि का हो सकता है, या लाइनों के "पच्चर" बनाने पर कोड विचारों के लिए कम से कम एक स्प्रिंग बोर्ड।
हॉर्नबड

और जब एक रेखा का प्रतीक होता है, तो प्रति पंक्ति 50 (100, 200) यात्रियों को कहते हैं? कुछ अजगर कोड (या ज्यामिति जनरेटर के साथ, मुझे यकीन नहीं है) आप एक अलग राशि के साथ लाइनों (x / 50) को घुमा सकते हैं।
स्टीफन

जवाबों:


5

एक बड़ी चुनौती!

यह उत्तर मुख्य रूप से ज्यामिति जनरेटर का उपयोग करता है और QGIS 3.2 में लिखा गया था। QGIS दुर्घटनाग्रस्त हो गया (बिना मुझे बचाए!) बस के बाद मैंने पहली बार लाइनें बनाईं और मैंने लगभग छोड़ दिया, लेकिन हाल ही में उपयोग की गई अभिव्यक्ति सूची ने दिन बचा लिया - ज्यामिति जनरेटर का उपयोग करने के लिए एक और बोनस

मैंने दो बिंदु सेट, एक स्रोत और तीन गंतव्य के साथ शुरू किया। गंतव्यों को गिनती के साथ लेबल किया गया है:

प्रारंभिक बिंदु

मैंने तब निम्न कोड का उपयोग करके वर्चुअल लेयर का उपयोग करके सभी बिंदुओं को स्रोत बिंदु से जोड़ने वाली लाइनें उत्पन्न कीं:

SELECT d.Count_MF, Makeline( s.geometry, d.geometry) 'geometry' 
  FROM Source AS s JOIN Destinations AS d

जुड़े हुए अंक

फिर मैंने लाइनों को स्टाइल करने के लिए निम्नलिखित ज्यामिति जनरेटर अभिव्यक्ति का उपयोग किया:

 intersection(
   geom_from_wkt( 
     'MULTILINESTRING ((' ||  $x_at( 0)  || ' ' || $y_at( 0)  || ', ' || 
     array_to_string(
       array_remove_at( string_to_array( regexp_replace(
             geom_to_wkt(nodes_to_points( tapered_buffer(  $geometry ,0, "Count_MF" * 200, floor("Count_MF" / 10)),true)),
             '[\\(\\)]','')),0)
     , ') , ('  ||  $x_at( 0)  || ' ' || $y_at( 0)  || ', ' )
    || '))')
    ,buffer( point_n(  $geometry ,1), $length))

यह प्रत्येक पंक्ति लेता है और निम्नलिखित चरणों को लागू करता है:

  1. गंतव्य छोर पर गंतव्य गणना द्वारा मापी गई चौड़ाई के स्रोत पर शून्य चौड़ाई से जा रहा एक पतला बफर बनाता है। बफ़र पॉइंट डेंसिटी को डेस्टिनेशन काउंट विशेषता द्वारा भी स्केल किया जाता है।
  2. बफ़र बहुभुज के कोने बिंदुओं में परिवर्तित हो जाते हैं (यह संभवतः शानदार है), और फिर WKT को निर्यात किया जाता है, और एक सरणी में परिवर्तित करने से पहले, ब्रैकेट्स को एक regex का उपयोग करके हटा दिया जाता है।
  3. फिर सरणी को एक मल्टीलाइनरिंग के लिए WKT स्ट्रिंग में वापस विस्तारित किया जाता है, स्रोत बिंदु के निर्देशांक और प्रासंगिक प्रारूपण में सम्मिलित करता है - यह स्रोत बिंदु से जुड़े निकाले गए प्रत्येक कोने के लिए एक अलग रेखा बनाता है।
  4. WKT को वापस एक ज्यामिति ऑब्जेक्ट में परिवर्तित किया जाता है और अंत में उन्हें उस बिंदु पर वापस लाने के लिए स्रोत बिंदु के बफर के साथ प्रतिच्छेद किया जाता है, जो गंतव्य बिंदु पर बैठता है (देखें tapered_bufferकि यह आवश्यक क्यों है, इसे समझने के लिए एक का आउटपुट देखें )

प्रशंसक

चरणों को लिखने में, मुझे पता चलता है कि एक सरणी से और उसके लिए रूपांतरण आवश्यक है, और सभी डब्ल्यूकेटी हेरफेर को रेक्सेक्स के साथ किया जा सकता है। यह अभिव्यक्ति नीचे है, और यदि tapered_arrayफ़ंक्शन को एक अलग से बदला जा सकता है तो इसका उपयोग QGIS 2.18 में भी किया जा सकता है।

intersection(
   geom_from_wkt(
    'MULTILINESTRING ((' ||  $x_at( 0)  || ' ' || $y_at( 0)  || ', ' ||
  replace(
    regexp_replace(
      regexp_replace(
        geom_to_wkt(tapered_buffer(  $geometry ,0, "Count_MF" * 200, floor("Count_MF" / 10))),
      '^[^,]*,',''),
    ',[^,]*$',''),
  ',',') , ('  ||  $x_at( 0)  || ' ' || $y_at( 0)  || ', ')
  || '))')
,buffer( point_n(  $geometry ,1), $length))

6

आपके प्रश्न ने मुझे जिज्ञासु बना दिया।

यह समाधान केवल पायथन कंसोल में QGIS 2.x के लिए काम करता है

जैसा कि मेरी टिप्पणी में उल्लेख किया गया है, पायथन के साथ लाइनों के आर्क को बनाने का मेरा विचार है।

मेरे पास दो बिंदु परत है:

मैं। पूँजी धारण करना (आईडी, पूँजी)

ii। कस्बों (आईडी, शहर, यात्रियों) को पकड़े

यात्रियों की राशि "बैंकनोट्स में अलग हो जाती है" और ये वे लाइनें होंगी जो आर्क का निर्माण करती हैं। तो 371 यात्रियों को 3x100, 1x50, 2x10 और 1x1 और कुल 7 बैंकनोटों का एक संयोजन है। बाद में लाइनों को नियम आधारित स्टाइल द्वारा स्टाइल किया जाता है।

यहाँ कोड है:

from qgis.gui import *
from qgis.utils import *
from qgis.core import *
from PyQt4 import QtGui, uic
from PyQt4.QtGui import *
from PyQt4.QtCore import *

for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
    if lyr.name() == "capital":
        capital_layer = lyr

for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
    if lyr.name() == "town":
        town_layer = lyr

    # creating the memory layer
d_lyr = QgsVectorLayer('LineString', 'distance', 'memory')
QgsMapLayerRegistry.instance().addMapLayer(d_lyr)
prov = d_lyr.dataProvider()
prov.addAttributes( [ QgsField("id", QVariant.Int), QgsField("banknote",QVariant.Int)])

    # function to create the banknotes
def banknoteOutput(number):
    number_list = []
    number_list.append(number)
    banknote_count = []
    temp_list = []
    banknote_list = []
    for n in number_list:
        total_sum = 0
        total = int(n/100)
        total_sum = total_sum + total
        if total > 0:
            banknote_count.append([total, 100])
        n = n-(total*100)
        total = int(n/50)
        total_sum = total_sum + total
        if total > 0:
            banknote_count.append([total, 50])
        n = n-(total*50)
        total = int(n/10)
        total_sum = total_sum + total
        if total > 0:
            banknote_count.append([total, 10])
        n = n-(total*10)
        total = int(n/5)
        total_sum = total_sum + total
        if total > 0:
            banknote_count.append([total, 5])
        n = n-(total*5)
        total = int(n/1)
        total_sum = total_sum + total
        if total > 0:
            banknote_count.append([total, 1])
        for i in banknote_count:
            temp_list.append(i*i[0])
        banknote_list = [item for sublist in temp_list for item in sublist][1::2]
        return banknote_list

        # creating lines with the amount of banknotes
for capital in capital_layer.getFeatures():
    for town in town_layer.getFeatures():
        commuter_splitting = banknoteOutput(town['commuters'])
        for i,banknote in enumerate(commuter_splitting):
            angle = 2
            distance = QgsDistanceArea()
            distance.measureLine(capital.geometry().asPoint(), town.geometry().asPoint())
            vect = QgsFeature()
            vect.setGeometry(QgsGeometry.fromPolyline([capital.geometry().asPoint(), town.geometry().asPoint()]))
            vect.geometry().rotate(0+(i*angle), capital.geometry().asPoint())
            vect.setAttributes([int(town["id"]), int(banknote)])
            prov.addFeatures([vect])

d_lyr.updateExtents()
d_lyr.triggerRepaint()
d_lyr.updateFields()

परिणाम इस तरह दिख सकता है:

यहाँ छवि विवरण दर्ज करें

अद्यतन: भेद पुरुष / महिला

4 मेमोरी लेयर में परिणाम।

from qgis.gui import *
from qgis.utils import *
from qgis.core import *
from PyQt4 import QtGui, uic
from PyQt4.QtGui import *
from PyQt4.QtCore import *

for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
    if lyr.name() == "capital":
        capital_layer = lyr

for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
    if lyr.name() == "town":
        town_layer = lyr

    # function to create the banknotes
def banknoteOutput(number):
    number_list = []
    number_list.append(number)
    banknote_count = []
    temp_list = []
    banknote_list = []
    for n in number_list:
        total_sum = 0
        total = int(n/100)
        total_sum = total_sum + total
        if total > 0:
            banknote_count.append([total, 100])
        n = n-(total*100)
        total = int(n/50)
        total_sum = total_sum + total
        if total > 0:
            banknote_count.append([total, 50])
        n = n-(total*50)
        total = int(n/10)
        total_sum = total_sum + total
        if total > 0:
            banknote_count.append([total, 10])
        n = n-(total*10)
        total = int(n/5)
        total_sum = total_sum + total
        if total > 0:
            banknote_count.append([total, 5])
        n = n-(total*5)
        total = int(n/1)
        total_sum = total_sum + total
        if total > 0:
            banknote_count.append([total, 1])
        for i in banknote_count:
            temp_list.append(i*i[0])
        banknote_list = [item for sublist in temp_list for item in sublist][1::2]
        return banknote_list

    # creating the male memory layer
cmt_male = QgsVectorLayer('LineString', 'Commuters_Male', 'memory')
QgsMapLayerRegistry.instance().addMapLayer(cmt_male)
prov_male = cmt_male.dataProvider()
prov_male.addAttributes( [ QgsField("id", QVariant.Int), QgsField("banknote",QVariant.Int)])

    # creating the male polygon memory layer
cmt_male_polygon = QgsVectorLayer('Polygon', 'Commuters_Male_Poly', 'memory')
QgsMapLayerRegistry.instance().addMapLayer(cmt_male_polygon)
prov_cmt_male_polygon = cmt_male_polygon.dataProvider()
prov_cmt_male_polygon.addAttributes( [ QgsField("id", QVariant.Int), QgsField("banknote",QVariant.Int)])

    # creating lines with the amount of banknotes
for capital in capital_layer.getFeatures():
    for town in town_layer.getFeatures():
        commuter_splitting = banknoteOutput(town['cmt_male'])
        points = []
        for i,banknote in enumerate(reversed(commuter_splitting)):
            angle = 2
            distance = QgsDistanceArea()
            distance.measureLine(capital.geometry().asPoint(), town.geometry().asPoint())
            vect = QgsFeature()
            vect.setGeometry(QgsGeometry.fromPolyline([capital.geometry().asPoint(), town.geometry().asPoint()]))
            vect.geometry().rotate(0+(i*angle), capital.geometry().asPoint())
            vect.setAttributes([int(town["id"]), int(banknote)])
            points.append(vect.geometry().asPolyline()[1])
            prov_male.addFeatures([vect])
        polygon = QgsFeature()
        points.insert(0,capital.geometry().asPoint())
        points.insert(len(points),capital.geometry().asPoint())
        polygon.setGeometry(QgsGeometry.fromPolygon([points]))
        polygon.setAttributes([1, 2])
        prov_cmt_male_polygon.addFeatures([polygon])

cmt_male.updateExtents()
cmt_male.triggerRepaint()
cmt_male.updateFields()
cmt_male_polygon.updateExtents()
cmt_male_polygon.triggerRepaint()
cmt_male_polygon.updateFields()

    # creating the female memory layer
cmt_female = QgsVectorLayer('LineString', 'Commuters_Female', 'memory')
QgsMapLayerRegistry.instance().addMapLayer(cmt_female)
prov_female = cmt_female.dataProvider()
prov_female.addAttributes( [ QgsField("id", QVariant.Int), QgsField("banknote",QVariant.Int)])

    # creating the female polygon memory layer
cmt_female_polygon = QgsVectorLayer('Polygon', 'Commuters_Female_Poly', 'memory')
QgsMapLayerRegistry.instance().addMapLayer(cmt_female_polygon)
prov_cmt_female_polygon = cmt_female_polygon.dataProvider()
prov_cmt_female_polygon.addAttributes( [ QgsField("id", QVariant.Int), QgsField("banknote",QVariant.Int)])

    # creating lines with the amount of banknotes
for capital in capital_layer.getFeatures():
    for town in town_layer.getFeatures():
        commuter_splitting = banknoteOutput(town['cmt_female'])
        points = []
        for i,banknote in enumerate(commuter_splitting):
            angle = 2
            distance = QgsDistanceArea()
            distance.measureLine(capital.geometry().asPoint(), town.geometry().asPoint())
            vect = QgsFeature()
            vect.setGeometry(QgsGeometry.fromPolyline([capital.geometry().asPoint(), town.geometry().asPoint()]))
            vect.geometry().rotate(-angle-(i*angle), capital.geometry().asPoint())
            vect.setAttributes([int(town["id"]), int(banknote)])
            points.append(vect.geometry().asPolyline()[1])
            prov_female.addFeatures([vect])
        polygon = QgsFeature()
        points.insert(0,capital.geometry().asPoint())
        points.insert(len(points),capital.geometry().asPoint())
        polygon.setGeometry(QgsGeometry.fromPolygon([points]))
        polygon.setAttributes([1, 2])
        prov_cmt_female_polygon.addFeatures([polygon])

cmt_female.updateExtents()
cmt_female.triggerRepaint()
cmt_female.updateFields()
cmt_female_polygon.updateExtents()
cmt_female_polygon.triggerRepaint()
cmt_female_polygon.updateFields()

परिणाम इस तरह दिख सकता है:यहाँ छवि विवरण दर्ज करें

एक बात जो कार्टोग्राफिक दृष्टिकोण से आदर्श नहीं है:

एक चाप के आकार को पहली नज़र में परेशान किया जा सकता है, जिस तरह से एक बड़ा चाप अधिक यात्रियों का प्रतिनिधित्व कर सकता है। कम यात्रियों (289 यात्रियों / 11 बैंकनोट्स) के साथ एक चाप अधिक यात्रियों (311 यात्रियों / 5 बैंकनोट्स) के मुकाबले बड़ा हो सकता है।

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