QGIS में अतिव्यापी लाइनों का स्थानांतरण प्रदर्शन?


10

जब बिंदु ओवरलैप हो रहे होते हैं, तो यह संपत्ति होती है जो अपने आप को बहुत से अलग-अलग प्रदर्शित करने की अनुमति देती है जहां वे होते हैं, जिसे 'प्वाइंट विस्थापन' कहा जाता है। लेकिन यह लाइनों के लिए काम नहीं करता है, यहां तक ​​कि यह मुझे लगता है कि कुछ वैसा ही हासिल करने के लिए वैचारिक रूप से संभव है:

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

मुझे बिल्कुल अलग-अलग लाइनों को देखने की जरूरत है जो वास्तव में सभी एक ही जगह हैं (मैं दूरसंचार नेटवर्किंग में काम कर रहा हूं)। एकमात्र तरीका जो मैं अभी देख रहा हूं, वह वास्तव में ऊपर की तस्वीर में अलग-अलग रेखाएं बनाना है, इस प्रकार स्थानिक गलतियां पैदा करना।

मैं QGIS 2.14 का उपयोग कर रहा हूं।


मुझे लगता है कि स्टाइल के लिए कुछ किया जा सकता है। क्या लाइन बीच में शुरू होने वाली रेखा है? फिर, मैं देख रहा हूं कि आपने तीन अलग-अलग ज्यामिति का उपयोग करके एक-एक पंक्ति बनाई है, इसलिए मेरा प्रश्न यह है कि क्या उनके प्रतिपादन से कुछ विशेष अतिरिक्त नियम हैं?
मैगरी

@ मैग्री मैं आपके प्रश्न को समझने के लिए निश्चित नहीं हूँ। प्रदान की गई तस्वीर एक उदाहरण है जिसमें मैंने प्रदर्शन के लिए पांच अलग-अलग पंक्तियों को आकर्षित किया। वास्तव में यह अधिक होगा कि ये 5 लाइनें वास्तव में मध्य एक के स्थान पर हैं (वे तार हैं, इसलिए सभी एक ही म्यान में फंस गए हैं)।
गुइओम क्लेयर

1
आप एक विस्थापन ("ऑफसेट") के साथ भी लाइनें प्रस्तुत कर सकते हैं, लेकिन वे प्रारंभ और अंत बिंदुओं पर नहीं मिलेंगे।
आंद्रेजे

@AndreJ हां, और एक और समस्या यह होगी कि यह काफी मैन्युअल ऑपरेशन होगा जहां मुझे कुछ और स्वचालित की आवश्यकता होगी क्योंकि यह कई उपयोगकर्ताओं द्वारा उपयोग किया जाएगा।
गुइओम क्लेयर

1
@GuiOmClair संलग्न छवि का अनुसरण करते हुए, मैंने मान लिया कि आप एक पंक्ति से शुरू करते हैं जो (उदाहरण के लिए) चार अन्य पंक्तियाँ हैं और आपको उन्हें अलग-अलग प्रदर्शित करने के लिए एक रास्ता खोजने की आवश्यकता है, भले ही वे ओवरलैप हों। मैंने सिर्फ इतना कहा कि नई ज्यामिति बनाने की आवश्यकता के बिना संलग्न छवि में प्रदर्शित किया जा सकता है (लेकिन केवल शुरुआती परत के शैली गुणों के लिए पुनरावृत्ति) संभव है। एक और तरीका आंद्रेजे द्वारा प्रस्तावित किया जाएगा, लेकिन ऐसा लगता है कि यह आपकी आवश्यकताओं के अनुरूप नहीं है।
मेग्री

जवाबों:


12

मैं एक दृष्टिकोण का प्रस्ताव करता हूं जो केवल एक ज्यामिति जनरेटर और एक कस्टम फ़ंक्शन के लिए पुनरावृत्ति करता है।

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

इसलिए, यह समाधान भौगोलिक और अनुमानित संदर्भ प्रणालियों के लिए काम करता है: निम्नलिखित में, मैंने अनुमान लगाया सीआरएस (यानी माप की इकाइयां मीटर हैं) का उपयोग करने के लिए मान लिया, लेकिन आप उन्हें अपने सीआरएस के अनुसार बदल सकते हैं।


प्रसंग

आइए तारों को दर्शाने वाली इस लिनेस्ट्रिंग वेक्टर परत से शुरू करें (लेबल अतिव्यापी (संयोग) तारों की संख्या का प्रतिनिधित्व करते हैं):

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


समाधान

सबसे पहले, पर जाएँ Layer Properties | Styleऔर फिर Single symbolरेंडरर चुनें।

से Symbol selectorसंवाद, एक चुनें Geometry generatorप्रतीक परत प्रकार के रूप में और Linestring / MultiLinestringज्यामिति प्रकार के रूप में। फिर, Function Editorटैब पर क्लिक करें :

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

फिर, पर क्लिक करें New fileऔर draw_wiresनए फ़ंक्शन का नाम टाइप करें :

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

आप देखेंगे कि एक नया फ़ंक्शन बनाया गया है और यह संवाद के बाईं ओर सूचीबद्ध है। अब, फ़ंक्शन के नाम पर क्लिक करें और @qgsfunctionनिम्न कोड के साथ डिफ़ॉल्ट को बदलें (यहां संलग्न सभी पुस्तकालयों को जोड़ना न भूलें):

from qgis.core import *
from qgis.gui import *
from math import sin, cos, radians

@qgsfunction(args='auto', group='Custom')
def draw_wires(angle, percentage, curr_feat, layer_name, feature, parent):

    def wires(polyline, new_angle, percentage):
        for x in range(0, len(polyline)-1):
            vertices = []
            first_point = polyline[x]
            second_point = polyline[x +1]
            seg = QgsGeometry.fromPolyline([first_point, second_point])
            len_feat = seg.length()
            frac_len = percentage * len_feat
            limb = frac_len/cos(radians(new_angle))
            tmp_azim = first_point.azimuth(second_point)
            angle_1 = radians(90 - (tmp_azim+new_angle))
            dist_x, dist_y = (limb * cos(angle_1), limb * sin(angle_1))
            point_1 = QgsPoint(first_point[0] + dist_x, first_point[1] + dist_y)
            angle_2 = radians(90 - (tmp_azim-new_angle))
            dist_x, dist_y = (limb * cos(angle_2), limb * sin(angle_2))
            point_2 = QgsPoint(second_point[0] - dist_x, second_point[1] - dist_y)
            tmp_azim = second_point.azimuth(first_point)
            angle_3 = radians(90 - (tmp_azim+new_angle))
            dist_x, dist_y = (limb * cos(angle_3), limb * sin(angle_3))
            point_3 = QgsPoint(second_point[0] + dist_x, second_point[1] + dist_y)
            angle_4 = radians(90 - (tmp_azim-new_angle))
            dist_x, dist_y = (limb * cos(angle_4), limb * sin(angle_4))
            point_4 = QgsPoint(first_point[0] - dist_x, first_point[1] - dist_y)
            vertices.extend([first_point, point_1, point_2, second_point, point_3, point_4, first_point])
            tempGeom = QgsGeometry.fromPolyline(vertices)
            num.append(tempGeom)
        return num


    layer = QgsMapLayerRegistry.instance().mapLayersByName(layer_name)[0]

    all_feats = {}
    index = QgsSpatialIndex()
    for ft in layer.getFeatures():
        index.insertFeature(ft)
        all_feats[ft.id()] = ft

    first = True

    tmp_geom = curr_feat.geometry()
    polyline = tmp_geom.asPolyline()
    idsList = index.intersects(tmp_geom.boundingBox())
    occurrences = 0
    for id in idsList:
        test_feat = all_feats[id]
        test_geom = test_feat.geometry()
        if tmp_geom.equals(test_geom):
            occurrences += 1
    if occurrences & 0x1:
        num = [tmp_geom]
    else:
        num = []

    rapp = occurrences/2
    i=2
    new_angle = angle

    while i <= occurrences:
        draw=wires(polyline, new_angle, percentage)
        i += 2
        new_angle -= new_angle/rapp
    first = True
    for h in num:
        if first:
            geom = QgsGeometry(h)
            first = False
        else:
            geom = geom.combine(h)
    return geom

एक बार जब आप ऐसा कर लेते हैं, तो Loadबटन पर क्लिक करें और आप फ़ंक्शन Customको Expressionसंवाद के मेनू से देख पाएंगे ।

अब, इस अभिव्यक्ति को टाइप करें (संदर्भ के रूप में नीचे की छवि देखें):

draw_wires(40, 0.3, $currentfeature, @layer_name)

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

आपने केवल एक फ़ंक्शन चलाया है, जो एक काल्पनिक तरीके से कह रहा है:

"वर्तमान परत ( @ लेयर_नाम ) और वर्तमान सुविधा ( $ करंट ) के लिए, 40 डिग्री के प्रारंभिक अधिकतम उपयोग के साथ तारों को प्रदर्शित करें और वर्तमान खंड की लंबाई के 0.3 गुना की दूरी पर दिशा में परिवर्तन के साथ।"

केवल एक चीज जिसे आपको बदलने की आवश्यकता है, वह पहले दो मापदंडों का मान है जैसा आप चाहते हैं, लेकिन स्पष्ट रूप से एक उचित तरीके से (अन्य फ़ंक्शन मापदंडों को प्रदान किए गए तरीके से छोड़ दें)।

अंत में, Applyपरिवर्तनों को लागू करने के लिए बटन पर क्लिक करें ।

आपको कुछ इस तरह दिखाई देगा:

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

जैसा सोचा था।


संपादित करें

एक टिप्पणी में ओपी द्वारा उठाए गए एक विशिष्ट अनुरोध के अनुसार:

"क्या यह पैटर्न प्रत्येक वर्टेक्स के बीच के बजाय प्रत्येक पॉलीलाइन की शुरुआत और अंत के बीच बनाना संभव होगा?"

मैंने कोड को थोड़ा संपादित किया। निम्नलिखित फ़ंक्शन को अपेक्षित परिणाम वापस करना चाहिए:

from qgis.core import *
from qgis.gui import *
from math import sin, cos, radians

@qgsfunction(args='auto', group='Custom')
def draw_wires(angle, percentage, curr_feat, layer_name, feature, parent):

    def wires(polyline, new_angle, percentage):
        vertices = []
        len_feat = polyline.length()
        frac_len = percentage * len_feat
        limb = frac_len/cos(radians(new_angle))
        tmp_azim = first_point.azimuth(second_point)
        angle_1 = radians(90 - (tmp_azim+new_angle))
        dist_x, dist_y = (limb * cos(angle_1), limb * sin(angle_1))
        point_1 = QgsPoint(first_point[0] + dist_x, first_point[1] + dist_y)
        angle_2 = radians(90 - (tmp_azim-new_angle))
        dist_x, dist_y = (limb * cos(angle_2), limb * sin(angle_2))
        point_2 = QgsPoint(second_point[0] - dist_x, second_point[1] - dist_y)
        tmp_azim = second_point.azimuth(first_point)
        angle_3 = radians(90 - (tmp_azim+new_angle))
        dist_x, dist_y = (limb * cos(angle_3), limb * sin(angle_3))
        point_3 = QgsPoint(second_point[0] + dist_x, second_point[1] + dist_y)
        angle_4 = radians(90 - (tmp_azim-new_angle))
        dist_x, dist_y = (limb * cos(angle_4), limb * sin(angle_4))
        point_4 = QgsPoint(first_point[0] - dist_x, first_point[1] - dist_y)
        vertices.extend([first_point, point_1, point_2, second_point, point_3, point_4, first_point])
        tempGeom = QgsGeometry.fromPolyline(vertices)
        num.append(tempGeom)

    layer = QgsMapLayerRegistry.instance().mapLayersByName(layer_name)[0]

    all_feats = {}
    index = QgsSpatialIndex()
    for ft in layer.getFeatures():
        index.insertFeature(ft)
        all_feats[ft.id()] = ft
    first = True
    tmp_geom = curr_feat.geometry()
    coords = tmp_geom.asMultiPolyline()
    if coords:
        new_coords = [QgsPoint(x, y) for x, y in z for z in coords]
    else:
        coords = tmp_geom.asPolyline()
        new_coords = [QgsPoint(x, y) for x, y in coords]
    first_point = new_coords[0]
    second_point = new_coords[-1]
    polyline=QgsGeometry.fromPolyline([first_point, second_point])
    idsList = index.intersects(tmp_geom.boundingBox())
    occurrences = 0
    for id in idsList:
        test_feat = all_feats[id]
        test_geom = test_feat.geometry()
        if tmp_geom.equals(test_geom):
            occurrences += 1
    if occurrences & 0x1:
        num = [polyline]
    else:
        num = []

    rapp = occurrences/2
    i=2
    new_angle = angle

    while i <= occurrences:
        draw=wires(polyline, new_angle, percentage)
        i += 2
        new_angle -= new_angle/rapp
    first = True
    for h in num:
        if first:
            geom = QgsGeometry(h)
            first = False
        else:
            geom = geom.combine(h)
    return geom

वाह! यह एक प्रभावशाली जवाब है! इसे खोजने और साझा करने के लिए समय निकालने के लिए बहुत-बहुत धन्यवाद। हालाँकि: 1. मुझे अपने डेटा पर इसे लागू करने में परेशानी हो रही है (जब मैं फ़ंक्शन को लागू करता हूं, तो लाइनें गायब हो जाती हैं), लेकिन मुझे लगता है कि समस्या मेरे डेटा से आती है क्योंकि यह एक अस्थायी परत पर काम करती है और 2. क्या यह बनाना संभव होगा यह पैटर्न केवल प्रत्येक पॉलीलाइन के बीच के बजाय प्रत्येक पॉलीलाइन की शुरुआत और अंत के बीच है?
गुइओम क्लेयर

@GuiOmClair लाइनें गायब हो जाती हैं क्योंकि फ़ंक्शन के साथ कुछ गलत हो जाता है। समस्या अस्थायी परत के उपयोग से नहीं आती है, लेकिन यह रेखा ज्यामितीय के बजाय मल्टीलाइन ज्यामिति के उपयोग से संबंधित हो सकती है। कृपया, QGIS में परत को लोड करें और फिर पायथन कंसोल में इन दो पंक्तियों को टाइप करें: layer=iface.activeLayer()और फिर print layer.wkbType()। क्लिक करें Run: मुद्रित संख्या का मूल्य क्या है?
माजरी

संख्या 5 है (इसका क्या मतलब है?)
गुइओम क्लेयर

@GuiOmClair इसका मतलब है कि आपकी परत एक मल्टीलाइनरिंग परत है, जबकि मैंने माना कि यह एक लाइनस्ट्रिंग परत थी (क्योंकि आपने इसे निर्दिष्ट नहीं किया था)। यह एक समस्या नहीं होगी और मैं जितनी जल्दी हो सके कोड को ठीक से संपादित करूंगा (शायद कल)। इसके अलावा, मैं केवल प्रत्येक (बहु) लाइन सुविधा के पहले और अंतिम बिंदु के बीच तारों को प्रस्तुत करने में सक्षम होना चाहिए।
माजरी

1
हां, विशेषताएं सीधी रेखाएं हैं (चूंकि वे आमतौर पर प्रबंधन और निर्यात करने में आसान हैं), इसलिए तारों की वास्तविक लंबाई पर विचार करना बेहतर होगा।
गुइओम क्लेयर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.