PyQGIS के साथ पंक्ति के समान आकार के बहुभुज बनाना?


42

मैं अगले चरण में एटलसक्रीट के लिए उनका उपयोग करने के लिए एक लाइन के साथ बहुभुज बनाना चाहूंगा।

ArcMap में स्ट्रिप मैप इंडेक्स फीचर्स नामक एक टूल है ।

इस उपकरण के साथ मैं अपने बहुभुजों की ऊँचाई और चौड़ाई (जैसे कि 8 किमी x 4 किमी) चुन सकता हूँ और स्वचालित रूप से लाइन के साथ उन्हें घुमा सकता हूँ।

प्रत्येक बहुभुज की उत्पन्न विशेषताओं में से एक रोटेशन कोण है जिसे मुझे बाद में एटलस जेनरेटर में अपने उत्तरी तीरों को घुमाने की आवश्यकता है।

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

क्या किसी को यह विचार है कि इस कार्य को QGIS / pyQGIS के साथ कैसे हल किया जाए? ग्रास- या सागा-एल्गोरिदम या एक प्रॉसेसिंग-टूलबॉक्स-मॉडल, जिसे कस्टम प्लगइन के अंदर इस्तेमाल किया जा सकता है, वह भी ठीक होगा;) Edit1: मुझे न केवल प्रिंट एक्स्टेंट की जरूरत है, बल्कि पॉलीगॉन की भी आवश्यकता है क्योंकि मैं एक मैप प्रिंट करना चाहता हूं; सभी बहुभुज / अवलोकन मानचित्र के कुछ प्रकार के रूप में फैली हुई है।

Edit2: मैं एक इनाम की पेशकश कर रहा हूं क्योंकि मैं अभी भी एक PyQGIS -solution की तलाश कर रहा हूं जिसे QGIS- प्लगिन में QGIS से अलग सॉफ़्टवेयर स्थापित करने की आवश्यकता के बिना उपयोग किया जा सकता है (PostGIS (Oracle की तरह कोई RDBMS नहीं)


4
यह एक प्लगइन के लिए एक मजेदार विचार की तरह दिखता है।
अल्फाबेटासैप

1
एक जंगली विचार के रूप में, मुझे लगता है कि प्यूकर-डगलस सामान्यीकरण पर आधारित कुछ काम हो सकता है
plablo09

1
शायद v.split.length, फिर सेगमेंट की शुरुआत और समापन बिंदु के बीच एक सीधी रेखा खींचना और फिर विकल्प के साथ v.buffer "पॉलीइन्स के सिरों पर कैप न बनाएं"
थॉमस बी

1
मैं इस प्रश्न पर एक इनाम शुरू करना पसंद करूंगा, लेकिन मेरे पास अभी तक पर्याप्त प्रतिष्ठा नहीं है? (
बर्लिनमॅपर

2
"लेबल-अनुसरण लाइन" कार्यान्वयन में कुछ पुन: प्रयोज्य कोड हो सकते हैं। आपकी आयतें कुछ मोनोसेप्ड फ़ॉन्ट के ग्लिफ़ के पैरों के निशान की तरह हैं।
user30184

जवाबों:


29

दिलचस्प सवाल! यह कुछ ऐसा है जिसे मैं खुद आजमाना चाहता हूं, इसलिए इसे छोड़ दिया।

आप इसे पोस्टग्रेज / POSTGIS में एक फ़ंक्शन के साथ कर सकते हैं जो पॉलीगॉन का एक सेट उत्पन्न करता है।

मेरे मामले में, मेरे पास एक टेबल है जिसमें एक विशेषता (एक बहुभाषी) है जो एक रेलवे लाइन का प्रतिनिधित्व करता है। इसे मीटर में एक सीआरएस का उपयोग करने की आवश्यकता है, मैं ओस्बर्ग (27700) का उपयोग कर रहा हूं। मैंने 4 किमी x 2 किमी 'पृष्ठ' किए हैं।

यहां, आप परिणाम देख सकते हैं ... हरे रंग का सामान सड़क नेटवर्क है, जो रेलवे के चारों ओर 1 किमी बफर से जुड़ा हुआ है, जो बहुभुज की ऊंचाई से अच्छी तरह मेल खाता है।

पोस्टगिस ने स्ट्रिप मैप तैयार किया

यहां देखें फंक्शन ...

CREATE OR REPLACE FUNCTION getAllPages(wid float, hite float, srid integer, overlap float) RETURNS SETOF geometry AS
$BODY$
DECLARE
    page geometry; -- holds each page as it is generated
    myline geometry; -- holds the line geometry
    startpoint geometry;
    endpoint geometry;
    azimuth float; -- angle of rotation
    curs float := 0.0 ; -- how far along line left edge is
    step float;
    stepnudge float;
    currpoly geometry; -- used to make pages
    currline geometry;
    currangle float;
    numpages float;
BEGIN
    -- drop ST_LineMerge call if using LineString 
    -- replace this with your table.
    SELECT ST_LineMerge(geom) INTO myline from traced_osgb; 
    numpages := ST_Length(myline)/wid;

    step := 1.0/numpages;
    stepnudge := (1.0-overlap) * step; 
    FOR r in 1..cast (numpages as integer)
    LOOP
        -- work out current line segment

        startpoint :=  ST_SetSRID(ST_Line_Interpolate_Point(myline,curs),srid);
        endpoint :=  ST_SetSRID(ST_Line_Interpolate_Point(myline,curs+step),srid);
        currline := ST_SetSRID(ST_MakeLine(startpoint,endpoint),srid);

        -- make a polygon of appropriate size at origin of CRS
        currpoly := ST_SetSRID(ST_Extent(ST_MakeLine(ST_MakePoint(0.0,0.0),ST_MakePoint(wid,hite))),srid);

        -- then nudge downwards so the midline matches the current line segment
        currpoly := ST_Translate(currpoly,0.0,-hite/2.0);

        -- Rotate to match angle
        -- I have absolutely no idea how this bit works. 
        currangle := -ST_Azimuth(startpoint,endpoint) - (PI()/2.0) + PI();
        currpoly := ST_Rotate(currpoly, currangle);

        -- then move to start of current segment
        currpoly := ST_Translate(currpoly,ST_X(startpoint),ST_Y(startpoint));

        page := currpoly;

        RETURN NEXT page as geom; -- yield next result
        curs := curs + stepnudge;
    END LOOP;
    RETURN;
END
$BODY$
LANGUAGE 'plpgsql' ;

इस फ़ंक्शन का उपयोग करना

यहाँ एक उदाहरण है; 4 किमी x 2 किमी पृष्ठ, एप्सग: 27700 और 10% ओवरलैप

select st_asEwkt(getallpages) from getAllPages(4000.0, 2000.0, 27700, 0.1);

इसे चलाने के बाद आप PgAdminIII से एक सीएसवी फ़ाइल में निर्यात कर सकते हैं। आप इसे क्यूजीआईएस में आयात कर सकते हैं, लेकिन आपको परत के लिए सीआरएस को मैन्युअल रूप से सेट करने की आवश्यकता हो सकती है - क्यूजीआईएस आपके लिए परत सीआरएस सेट करने के लिए EWKT में SRID का उपयोग नहीं करता है: /

असर विशेषता जोड़ना

यह संभवतः पोस्टगिस में आसान है, यह QGIS अभिव्यक्तियों में किया जा सकता है लेकिन आपको कुछ कोड लिखने की आवश्यकता होगी। कुछ इस तरह...

create table pages as (
    select getallpages from getAllPages(4000.0, 2000.0, 27700, 0.1)
);

alter table pages add column bearing float;

update pages set bearing=ST_Azimuth(ST_PointN(getallpages,1),ST_PointN(getallpages,2));

चेतावनियां

यह एक साथ हैक किया गया है, और केवल एक डेटासेट पर परीक्षण करने का मौका था।

100% निश्चित नहीं है कि आपको कौन-से दो गुणनखंडों को उस असर विशेषता अद्यतन पर चुनना होगा query.. प्रयोग करने की आवश्यकता हो सकती है।

मुझे स्वीकार करना चाहिए कि मुझे इस बात का कोई अंदाजा नहीं है कि मौजूदा लाइन खंड से मेल खाने के लिए बहुभुज को घुमाने के लिए मुझे इस तरह के जटिल फॉर्मूले की आवश्यकता क्यों है। मुझे लगा कि मैं ST_Azimuth () से ST_Rotate () में आउटपुट का उपयोग कर सकता हूं, लेकिन प्रतीत नहीं होता।


आपका उत्तर वास्तव में बहुत अच्छा है और मैं निश्चित रूप से इसके लिए प्रयास करूंगा। मेरे लिए प्रतिबंध यह है कि मैं जिस परियोजना पर काम कर रहा हूं, उसके लिए पोस्टग्रेज का उपयोग नहीं कर सकता और कुछ ऐसा चाहिए जो सर्वर साइड पर निर्भर न हो। लेकिन शायद मैं आपका उपयोग कर सकता हूं pyQGIS के साथ ऐसा कुछ करने के लिए महान तर्क।
बर्लिनमैपर

2
यदि ऐसा है, तो QgsGeometry वर्ग पर एक नज़र डालें । इसमें PostGIS के ज्योमेट्री ऑपरेशंस का एक सबसेट है और यदि आप पीक्यूजी मार्ग जाना चाहते हैं तो यह एक अच्छी शुरुआत होगी। एल्गोरिथ्म pyQGIS के लिए पोर्टेबल होना चाहिए ..
स्टीवन Kay

3
मुझे लगता है कि संदर्भ लाइनों को उत्पन्न करने के लिए ST_Simplify का उपयोग करने के लिए एक दृष्टिकोण पोस्टगेज के लिए और खंडों के लिए लाइन को तोड़ने और फिर ST_Buffer और ST_Envelope का उपयोग कम और अधिक कुशल होगा।
मथायस कुह्न

@ मैथियास कुह्न: अगर मैं खंडों को खंड को तोड़ता हूं तो मुझे समान आकार की रेखाएं मिल सकती हैं लेकिन जरूरी नहीं कि समान आकार के बहुभुज भी हों। उदाहरण के लिए यदि रेखा सुंदर 'सुडौल' है तो बहुभुज संभवतः छोटा होगा, है न?
बर्लिनमैपर

2
मैंने आपके समाधान और आपकी स्क्रिप्ट के PyQGIS- संस्करण का परीक्षण किया। किसी भी छोटी सी समस्या को हल करने के लिए कैसे विचार करें: bit.ly/1KL7JHn ?
बर्लिनमेपर

12

विभिन्न समाधान है। और यह सरल पॉलीलाइन और कई चयनित संस्थाओं के साथ काम कर सकता है

खंड आरेख:

  1. पैरामीटर

    1. पीढ़ी के लिए अभिविन्यास चुनें और सूचकांक पढ़ें (बाएं से दाएं, उत्तर-से-दक्षिण ...)
    2. ऑब्जेक्ट का आकार निर्धारित करें

    shape = (4000,8000) # (<width>,<length>)
    1. सुपरपोजिशन कोफ़ को परिभाषित करें (डिफ़ॉल्ट रूप से 10%?)
  2. इस में
    1. अपनी अभिविन्यास पसंद पर निर्भर करते हुए ऑर्डरिंग पॉलीलाइन (स्टार्ट एंड एंड पॉइंट की तुलना करें) ऑर्डर करने के लिए फीचरक्लास ऑर्डरनॉड्स ऑर्डर करें
  3. ऑर्डरनोड्स पर लूप

    1. आप पहले एंकर के रूप में बिंदु बनाएँ

    2. प्रत्येक शीर्ष के लिए इसे तानाशाह x, y, id पर जोड़ें और एक वेक्टर की गणना करें

    3. सुपरपोजिशन (10% / 2) को कम करने के साथ पॉलीगोन (लंबाई और वेक्टर अभिविन्यास पर)> 5% बायें बहुभुज 5% दायें बहुभुज एक ही एंकर पॉइंट के साथ
    4. जब एक पूर्ववर्ती शीर्ष बिंदु बहुभुज से बाहर हो या अगर वेक्टर लेन> लंबाई को आकार देने के लिए है तो रुकें
    5. पिछले अच्छे समाधान के साथ बहुभुज उत्पन्न करें और अंतिम अच्छी स्थिति के साथ लंगर बिंदु सेट करें
    6. नया लूप निष्पादित करें और अगले बहुभुज ऑब्जेक्ट को उत्पन्न करने के लिए ताना एक्स, वाई, आईडी रीसेट करें।

आप इस प्रस्ताव को बदल सकते हैं यदि यह वास्तव में स्पष्ट या टिप्पणी नहीं है।


यह परिष्कृत लगता है, लेकिन मुझे यह स्वीकार करना होगा कि मुझे अभी तक यह नहीं पता है कि मॉडलर या पायक्यूजीएस के लिए इसका उपयोग कैसे किया जाए। वैसे: क्या एक superposition गुणांक है?
बर्लिनमपर

@Berlinmapper इस मामले में सुपरपोस्टियन 8000 x 10% के साथ बहुभुज का एक हिस्सा है। आप एक दूसरे को चुन सकते हैं या एक फिक्स डिस्टेंस सुपरपोजिशन बीट्वीन पॉलीगोन बना सकते हैं। आप देख सकते हैं कि कोने में अगले टाइल पृष्ठ को इंगित करने के लिए सभी एटलस में
जियोस्टोनमार्टन

क्या आपका समाधान pyQGIS या प्रोसेसिंग टूलबॉक्स के साथ उपयोग किया जाना है? यह बहुत अच्छा लगता है, लेकिन मुझे अभी भी पता नहीं है कि कैसे आगे बढ़ना है
बर्लिनमॅपर

1
@Berlinmapper मुझे लगता है कि आपको प्रक्रिया स्क्रिप्ट बनाने और प्रसंस्करण टूलबॉक्स या QGIS प्लगइन में इनपुट और आउटपुट पैरामीटर सेट करने के लिए pyQGIS का उपयोग करने की आवश्यकता है। आर्कगिस्टोलबॉक्स के रूप में भी। मेरे पास वास्तव में ऐसा करने और उसे परखने का कोई समय नहीं है।
जियोस्टोनमार्टन

12

पाइकगिस में स्टीवन केस का जवाब। स्क्रिप्ट चलाने से पहले बस अपनी परत में लाइनों का चयन करें। स्क्रिप्ट लिनेमरिंग का समर्थन नहीं करती है इसलिए यह मल्टीलाइनरिंग के साथ परत पर काम नहीं कर सकता है

#!python
# coding: utf-8

# https://gis.stackexchange.com/questions/173127/generating-equal-sized-polygons-along-line-with-pyqgis
from qgis.core import QgsMapLayerRegistry, QgsGeometry, QgsField, QgsFeature, QgsPoint
from PyQt4.QtCore import QVariant


def getAllPages(layer, width, height, srid, overlap):
    for feature in layer.selectedFeatures():
        geom = feature.geometry()
        if geom.type() <> QGis.Line:
            print "Geometry type should be a LineString"
            return 2
        pages = QgsVectorLayer("Polygon?crs=epsg:"+str(srid), 
                      layer.name()+'_id_'+str(feature.id())+'_pages', 
                      "memory")
        fid = QgsField("fid", QVariant.Int, "int")
        angle = QgsField("angle", QVariant.Double, "double")
        attributes = [fid, angle]
        pages.startEditing()
        pagesProvider = pages.dataProvider()
        pagesProvider.addAttributes(attributes)
        curs = 0
        numpages = geom.length()/(width)
        step = 1.0/numpages
        stepnudge = (1.0-overlap) * step
        pageFeatures = []
        r = 1
        currangle = 0
        while curs <= 1:
            # print 'r =' + str(r)
            # print 'curs = ' + str(curs)
            startpoint =  geom.interpolate(curs*geom.length())
            endpoint = geom.interpolate((curs+step)*geom.length())
            x_start = startpoint.asPoint().x()
            y_start = startpoint.asPoint().y()
            x_end = endpoint.asPoint().x()
            y_end = endpoint.asPoint().y()
            # print 'x_start :' + str(x_start)
            # print 'y_start :' + str(y_start)
            currline = QgsGeometry().fromWkt('LINESTRING({} {}, {} {})'.format(x_start, y_start, x_end, y_end))
            currpoly = QgsGeometry().fromWkt(
                'POLYGON((0 0, 0 {height},{width} {height}, {width} 0, 0 0))'.format(height=height, width=width))
            currpoly.translate(0,-height/2)
            azimuth = startpoint.asPoint().azimuth(endpoint.asPoint())
            currangle = (startpoint.asPoint().azimuth(endpoint.asPoint())+270)%360
            # print 'azimuth :' + str(azimuth)
            # print 'currangle : ' +  str(currangle)

            currpoly.rotate(currangle, QgsPoint(0,0))
            currpoly.translate(x_start, y_start)
            currpoly.asPolygon()
            page = currpoly
            curs = curs + stepnudge
            feat = QgsFeature()
            feat.setAttributes([r, currangle])
            feat.setGeometry(page)
            pageFeatures.append(feat)
            r = r + 1

        pagesProvider.addFeatures(pageFeatures)
        pages.commitChanges()
        QgsMapLayerRegistry.instance().addMapLayer(pages)
    return 0

layer = iface.activeLayer()
getAllPages(layer, 500, 200, 2154, 0.4)

1
महान। मैंने समाधान का परीक्षण किया। किसी भी विचार कैसे इन समस्याओं को हल करने के लिए समाधान अभी भी है: bit.ly/1KL7JHn ?
बर्लिनमेपर

शायद यहाँ कुछ "प्रेरणा" है: github.com/maphew/arcmapbook/blob/master/Visual_Basic/…
थॉमस बी

धन्यवाद.ग्रेट संसाधन यह समझने के लिए कि कैसे आर्कप टूल काम करता है। दुर्भाग्य से मैं ', VB के लिए उपयोग नहीं किया गया, लेकिन शायद कोई और व्यक्ति इसका उपयोग उत्तर / टिप्पणी पोस्ट करने के लिए कर सकता है;)
बर्लिनमपर

4

दो उत्तर (पोस्टिंग के समय) सरल और अच्छी तरह से समझाया गया है। हालाँकि, इसके लिए एक बहुत ही सरल लेकिन प्रभावी उपाय भी संभव है (यह मानते हुए कि आप अपने सभी मानचित्रों को नदी के आधार पर एक यादृच्छिक उत्तर दिशा की बजाय पारंपरिक तरीके से उत्तर के साथ संरेखित करेंगे)। यदि आप घुमाव चाहते हैं, तो यह संभव है लेकिन थोड़ा अधिक जटिल (नीचे देखें)।

पहले यहाँ मेरी पोस्ट पर एक नज़र है । यह आपको एटलस के लिए मैप कवरेज बनाने के लिए कैसे-कैसे देता है। जिस विधि को आप चाहते हैं, वह है 'वर्कफ़्लो 2' का एक रूपांतरण। अपनी रैखिक सुविधा को लंबवत या लंबाई से विभाजित करें और किसी भी राशि से सुविधाओं को बफ़र करें। आपके द्वारा बफर की जाने वाली राशि आंशिक रूप से ओवरलैप तय करेगी (लेकिन नीचे देखें) लेकिन इससे भी महत्वपूर्ण बात यह है कि यह एक क्षेत्र के साथ एक विशेषता बनाता है। आप लाइनों को विभाजित करने के लिए किसी भी संख्या में प्लगइन्स का उपयोग कर सकते हैं लेकिन GRASS v.split.length और v.split.vert अच्छे विकल्प हैं (प्रसंस्करण टूलबॉक्स में उपलब्ध हैं)।

मानचित्र संगीतकार में एटलस जेनरेशन को सक्षम करने और अपनी बफर लेयर का चयन करने के बाद, आइटम टैब पर वापस जाएं और अपना मैप ऑब्जेक्ट चुनें। 'एटलस द्वारा नियंत्रित' की जाँच करें, और आपके उपयोग के मामले में, मैं फीचर के आसपास मार्जिन का विकल्प चुनूंगा। यह नक्शे के बीच आपके ओवरलैप को नियंत्रित करेगा (वैकल्पिक रूप से आप निश्चित पैमाने को पसंद कर सकते हैं)।

आप संगीतकार के शीर्ष टूलबार में पूर्वावलोकन एटलस बटन का उपयोग करके आपको एटलस का पूर्वावलोकन कर सकते हैं और देखें कि यह कितने पृष्ठों का उत्पादन करेगा। ध्यान दें कि आप सभी पृष्ठों को एक पीडीएफ में या अलग-अलग फ़ाइलों के रूप में निर्यात करना चुन सकते हैं।

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


इस समाधान के लिए धन्यवाद। लेकिन मुझे लगता है कि मैं इस तरह के एकल अंशों के बहुभुज नहीं प्राप्त कर पाऊंगा जिन्हें मैं प्रिंट करना चाहता हूं। मैं उन्हें भी सभी प्रिंट extents के साथ एक "अवलोकन मानचित्र" का उत्पादन करने की आवश्यकता है।
बर्लिनमपर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.