একটি রেখা এবং একটি মান থেকে রেখার একটি তোরণ তৈরি করুন


9

আমি এটির মতো একটি উত্স-গন্তব্য প্লটটি পুনরায় তৈরি করার চেষ্টা করছি :

এখানে চিত্র বর্ণনা লিখুন

আমি একটি এমএসওএ থেকে এলএডি টেবিলের মধ্যে ডেটা মুনেজ করতে পেরেছি এবং মূল এমএসওএর মধ্যে একটির জন্য এটির মতো মানচিত্র আঁকতে পারি।

এখানে চিত্র বর্ণনা লিখুন

যা একবার আপনি (এখন হাস্যকর) দূরত্বের জন্য পিক জেলাতে যাতায়াতের লোকদের কাছ থেকে কাজ করার অনুমতি দিচ্ছেন।

তবে লেখক লাইনগুলি "স্প্লে" করে যে প্রভাব ফেলেছেন তা আমি বেশ পছন্দ করি। স্পষ্টতই, 522 এবং 371 প্রবাহের সাথে, আমি যাত্রী প্রতি একক লাইনের জন্য যেতে পারি না তবে ভ্রমণটি করা লোকের সংখ্যা দেখানোর জন্য আনুপাতিক লাইনের আনুপাতিক চাপ তৈরি করা ভাল লাগবে।

আমি ভেবেছিলাম যে আমি জ্যামিতি জেনারেটরটি ব্যবহার করতে সক্ষম হব তবে লুপ নির্মাণ ছাড়া, আমি অগ্রসর হতে পারব না।


এই ইএসআরআই সরঞ্জামটি আপনার পক্ষে আগ্রহী হতে পারে বা লাইনগুলির "ওয়েজ" তৈরির বিষয়ে কোড ধারণার জন্য কমপক্ষে একটি স্প্রিং বোর্ড।
হর্নবিড্ড

এবং যখন কোনও লাইন প্রতীকী হয়, আসুন প্রতি লাইনে 50 (100, 200) যাত্রী বলি? কিছু অজগর কোড (বা জ্যামিতি জেনারেটর, আমি নিশ্চিত নই) দিয়ে আপনি পৃথক পরিমাণে লাইনগুলি (x / 50) ঘোরান।
স্টিফান

উত্তর:


5

একটি দুর্দান্ত চ্যালেঞ্জ!

এই উত্তরটি প্রাথমিকভাবে জ্যামিতি জেনারেটর ব্যবহার করে এবং QGIS 3.2 এ লেখা হয়েছিল। কিউজিআইএস ক্র্যাশ হয়ে গেছে (আমি বাঁচানো ছাড়া!) আমি প্রথম লাইনগুলি তৈরি করার পরে এবং আমি প্রায় ছেড়ে দিয়েছিলাম, তবে সম্প্রতি ব্যবহৃত অভিব্যক্তি তালিকার দিনটি বাঁচিয়েছে - জ্যামিতি জেনারেটরটি ব্যবহার করার জন্য আরেকটি বোনাস

আমি দুটি পয়েন্ট সেট, একটি উত্স এবং তিনটি গন্তব্য দিয়ে শুরু করেছি। গন্তব্যগুলি গণনা সহ লেবেলযুক্ত:

প্রাথমিক পয়েন্ট

তারপরে আমি নিম্নলিখিত কোডটি ব্যবহার করে ভার্চুয়াল স্তর ব্যবহার করে সমস্ত গন্তব্যগুলিতে উত্সকে সংযোগকারী লাইন তৈরি করেছি:

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. বাফার বহুভুজের অনুভূমিকগুলি বিন্দুতে রূপান্তরিত হয় (এটি সম্ভবত অতিরিক্ত অতিরিক্ত) এবং তারপরে ডাব্লুকেটিতে রফতানি করা হয় এবং বন্ধনীগুলি অ্যারেতে রূপান্তরিত করার আগে একটি রেজেক্স ব্যবহার করে অপসারণ করা হয়
  3. অ্যারেরটি আবার একটি মাল্টিলিনেস্ট্রিংয়ের জন্য ডাব্লুকেটি স্ট্রিংয়ে প্রসারিত করা হয়, উত্স পয়েন্টের স্থানাঙ্ক এবং প্রাসঙ্গিক বিন্যাসে সন্নিবেশ করানো - এটি উত্স পয়েন্টের সাথে সংযুক্ত প্রতিটি নিষ্কাশিত উল্লম্বের জন্য একটি পৃথক রেখা তৈরি করে
  4. ডব্লিউকেটি জ্যামিতি অবজেক্টে ফিরে রূপান্তরিত হয় এবং শেষ অবধি উত্সের বাফারের সাথে ছেদ করে গন্তব্য পয়েন্টটি যে বৃত্তে বসে থাকে তা ক্লিপ করতে ( 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 এর জন্য কাজ করে

এখানে আমার মন্তব্যে উল্লিখিত মতটি পাইথনের সাথে রেখার চাপ তৈরির জন্য আমার ধারণা।

আমার দুটি পয়েন্ট স্তর রয়েছে:

আমি। একটি মূলধন ধারণ করে (আইডি, মূলধন)

আ। একটি শহর ধরে রাখা (আইডি, শহর, যাত্রী)

যাত্রীদের পরিমাণ "নোটগুলিতে বিভক্ত" এবং এগুলি সেই লাইন যা আর্ক তৈরি করে। সুতরাং 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()

ফলাফলটি এরকম দেখতে পারে:এখানে চিত্র বর্ণনা লিখুন

একটি বিষয় যা কার্টোগ্রাফিক দৃষ্টিকোণ থেকে আদর্শ নয়:

লাইনের একটি তোরণ আকারটি প্রথম নজরে বিরক্তিকর হতে পারে, যাতে একটি বড় চাপ আরও বেশি যাত্রীদের প্রতিনিধিত্ব করতে পারে। আরও বেশি যাত্রী (৩১১ জন যাত্রী / ৫ টি নোট) অন্যের চেয়ে কম যাত্রী (২৮৯ জন যাত্রী / ১১ টি নোট) দিয়ে একটি চাপ বড় হতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.