QGIS'de komşu çini kimlikleri nasıl belirlenir?


11

Yakın tarihli bir eğitim kursunda, QGIS'in atlas jeneratörü kullanılarak oluşturulan bir harita kitabı için sonraki / önceki ve yukarıdaki / aşağıdaki sayfa numaralarını otomatik olarak hesaplayıp hesaplayamayacağı soruldu. Izgara genişliğini ve yüksekliğini biliyorsanız, normal bir ızgara için oldukça makul bir etiket ifadesi çalışmayı başardım.

Ancak daha sonra, kendi ilçem gibi bir ilçemiz olmayan sayfalar çizmek istemediğimiz gerçekçi örnekler düşünmeye başladık:

resim açıklamasını buraya girin

Bu öğleden sonra, her ızgara hücresi için ilgilendiğim 4 komşuyu çalışmak için bir python senaryosunda oynadım ve bu değerleri ızgarama ekledim (bu, Ujaval Gandhi'nin eğitimine dayanıyor ):

for f in feature_dict.values():
    print 'Working on %s' % f[_NAME_FIELD]
    geom = f.geometry()
    # Find all features that intersect the bounding box of the current feature.
    # We use spatial index to find the features intersecting the bounding box
    # of the current feature. This will narrow down the features that we need
    # to check neighboring features.
    intersecting_ids = index.intersects(geom.boundingBox())
    # Initalize neighbors list and sum
    neighbors = []
    neighbors_sum = 0
    for intersecting_id in intersecting_ids:
        # Look up the feature from the dictionary
        intersecting_f = feature_dict[intersecting_id]
        int_geom = intersecting_f.geometry()
        centroid = geom.centroid()
        height = geom.boundingBox().height()
        width = geom.boundingBox().width()
        # For our purpose we consider a feature as 'neighbor' if it touches or
        # intersects a feature. We use the 'disjoint' predicate to satisfy
        # these conditions. So if a feature is not disjoint, it is a neighbor.
        if (f != intersecting_f and
            not int_geom.disjoint(geom)):
            above_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x(),
               centroid.asPoint().y()+height))
            below_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x(),
               centroid.asPoint().y()-height))
            left_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x()-width,
               centroid.asPoint().y()))
            right_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x()+width,
               centroid.asPoint().y()))
            above = int_geom.contains(above_point)   
            below = int_geom.contains(below_point)   
            left = int_geom.contains(left_point)
            right = int_geom.contains(right_point)
            if above:
                print "setting %d as above %d"%(intersecting_f['id'],f['id'])
                f['above']=intersecting_f['id']

            if below:
                print "setting %d as below %d"%(intersecting_f['id'],f['id'])
                f['below']=intersecting_f['id']

            if left:
                print "setting %d as left of %d"%(intersecting_f['id'],f['id'])
                f['left']=intersecting_f['id']

            if right:
                print "setting %d as right of %d"%(intersecting_f['id'],f['id'])
                f['right']=intersecting_f['id']

    # Update the layer with new attribute values.
    layer.updateFeature(f)

layer.commitChanges()

Bu gayet iyi çalışıyor.

resim açıklamasını buraya girin

Ama dürüst olmak gerekirse, Kuzey'e bir test noktası yaratmak ve sonra tüm olası komşuları test etmek yanlış görünüyor. Ancak bir öğleden sonra beynimi sardıktan sonra belirli bir ızgara hücresinin kuzey komşusunun ne olduğunu belirlemek için daha iyi bir yol düşünemiyorum?

İdeal olarak, bir baskı bestecisi metin kutusuna koymak için yeterince basit bir şey istiyorum, ama bunun için çok fazla şey olduğundan şüpheleniyorum.


bir tarafta komşu yoksa ne olacak. Kapanış hücresinin değerini bir yönde istiyor musunuz yoksa bir boşluk mu bırakırsınız?
radouxju

Bu durumda null için mutluyum, etiketi yalnızca null veya boş olmadığında görüntülenecek şekilde kolayca ayarlayabilirim.
Ian Turton

Yanıtlar:


3

Her sayfa kapsamını (dizin katmanından) tam olarak besteciye sığmazsanız, bunun yerine bitişik sayfalarla (ikinci ekran görüntünüzde gösterildiği gibi) üst üste gelen kenarlıklara sahipseniz, dizin katmanındaki etiketleri, harita sınırının içinde olacaklardı.

Herhangi bir çakışma yoksa, MapInfo'da geçmişte başarılı bir şekilde kullandığım bir tekniği (tesadüfen E&W Sussex'te!) Çoğaltabilirsiniz, burada her dizin özelliği için dört nokta kümesi oluşturan küçük bir komut dosyası yazdım , hem sayfa numarasının hem de ofset yönünün özelliklerine sahip bitişik özelliklere kaydırın. Nokta katmanı daha sonra tekrar etiket oluşturmak için kullanıldı, ofset yönü, etiketlerin yönünün daha hoş bir etki için ayarlanmasına izin verdi.

Bunu denemedim, ancak yeni geometri üreteci stil işlevselliğini kullanarak QGIS'de ayrı bir veri katmanı oluşturmaktan kaçınabilirsiniz, bu MapInfo'da ulaşılamayan daha zarif ve dinamik bir çözüm sağlayacaktır!


Gerçekten sadece diğer çokgenlerin etiketlerini kullanmayı düşünmeliydim! :-) Geometry Generator ile hızlı bir denemeden sonra sınırlayıcı bir kutu çizebilirim, ancak bir ızgara oluşturmak daha zor
Ian Turton

Izgaralar yerine bitişik çokgenlere ofset etiket noktaları oluşturma çizgileri boyunca düşünüyordum. Başka bir seçenek, etiketlerin çizilmesine izin vermek için dizin özelliğinin MBR'sini bitişik özelliklere genişletmek olacaktır.
Andy Harfoot

Sadece bir oyun oynadım ve geometri üreteci stilinin yarattığı geometrinin etiketlenmediği anlaşılıyor, bu yüzden umduğum daha zarif bir çözüm değil.
Andy Harfoot

8

Aslında, atlas kullanarak yazdırmak istediğiniz döşemeleri belirlemek için gereken işlerin çoğunu zaten yaptınız. Ancak asıl mesele, yalnızca ihtiyacınız olan döşeme kimliklerini göstermek için her şeyi birlikte nasıl ayarlayacağınızdır. Fikrimi göstermek için, bu örnekte aşağıda gördüğünüz gibi bir DEM görüntüsü ve bir ızgara vektör dosyası kullanacağım:

resim açıklamasını buraya girin

İlk önce her ızgaranın etiketini göstermemiz gerekiyor.

Düzen görünümünde, atlas'ta kapsama katmanı olarak ızgara kullandım, iki harita oluşturdum: ana görünüm penceresi haritası ve aşağıda görebileceğiniz gibi yalnızca ızgarayı gösteren bir dizin haritası:

resim açıklamasını buraya girin

Sonra aşağıdakileri yaptım:

  1. Dizin haritasının ölçeğini tüm ızgara kapsamını gösterecek şekilde ayarladım ve ardından ölçeği düzelttim
  2. Haritayı kullanırken haritanın kaydırılmasını önlemek için görünüm boyutunu düzelttim Preview atlasve
  3. Ben etkin Overviewaşağıda görebileceğiniz gibi, ana görünümü harita kapsamını ve konumu görmek için:

resim açıklamasını buraya girin

Ana görünüm penceresi haritası için, aşağıda gördüğünüz gibi, bir şey olursa ölçeğin değişmeyeceğinden emin olmak için ölçeği her ızgara bloğunun boyutuna sabitledim;

resim açıklamasını buraya girin

Bir dizin haritası kullanarak, ızgarayı ana görünüm haritası penceresinden kapatsanız bile, her döşemenin kimliğini ve konumunu diğer döşemeye referansla kolayca görebilirsiniz. Örneğin, aşağıdaki haritanın döşeme kimliği = 14'tür ve çevresindeki döşeme kimliklerini görebilirsiniz.

resim açıklamasını buraya girin

Güncelleme :

Cevabımı güncelleyeceğim çünkü çevredeki yerleşimlerin kimlik numaralarını değil, çevredeki yerleşimlerin sayfa numarası dizinini göstermek istediğinizi fark ettim.

Sürecin anlaşılmasını kolaylaştırmak için, dizin haritasındaki kimlik numaralarını, aşağıda gösterildiği gibi düzen sayfa numarasını gösterecek şekilde güncelleyeceğim:

resim açıklamasını buraya girin

Sahip olduğum kimlikler 0'dan (Sıfır) başladığından beri, dizin haritasında gösterilen ilk kılavuzun kimliği 3'ten başlayacaktır. Bu nedenle, Atlas'taki kimlik numarasından 2 çıkararak sayfa numarasını 1'den başlamak üzere değiştirmek istiyorum: Page number: ID -2, sonra geçerli sayfa, önceki sayfa, sonraki sayfa, yukarı sayfa ve aşağıdaki sayfa için etiketler oluşturmak üzere ifadede referans olarak geçerli sayfa numarasını kullanacağım:

resim açıklamasını buraya girin

  • Geçerli Sayfa, etiket metni kutusunda şu ifadeye sahiptir: Current Page Number: [%@atlas_pagename%]

  • Önceki Sayfa ifadesi: [%if((@atlas_pagename = 1), Null, '↑ Page Number: ' || (@atlas_pagename - 1))%]daha önce hiç sayfa olmadığı için 1

  • Sonraki Sayfa ifadesi: [%if( (@atlas_pagename = 25), Null, '↓ Page Number: ' || (@atlas_pagename + 1))%]25'ten sonra sayfa olmadığından

  • Yukarı Sayfa ifadesi: [%if((@atlas_pagename <= 6),NULL,'↑ Page Number: ' || (@atlas_pagename -6))%]üst yönde 6'dan önce sayfa olmadığından

  • Sayfa ifadesinin altında: [%if((@atlas_pagename >= 20), Null, '↓ Page Number: ' || (@atlas_pagename + 6))%]alt yönde 20'den sonra sayfa olmadığından

Bazı çıktı sonuçları:

resim açıklamasını buraya girin

resim açıklamasını buraya girin

resim açıklamasını buraya girin

resim açıklamasını buraya girin


Yararlı olmasına rağmen, bu onun sorusuna cevap vermiyor.
Victor

@Victor Yorumunuz için teşekkürler, cevabımı güncelledim.
ahmadhanb

bu, örneğinizde (ve onun) işe yarar, çünkü tuş haritasının / ızgaranın kenarları düzenli. Düz değilse, eklenecek veya çıkarılacak sayı (örneğinizde 6) bulunduğunuz atlas sayfasına bağlı olarak değişeceğinden çalışmaz.
Victor

2
Size katılıyorum. Şebeke düzenli değilse süreç daha karmaşık olacaktır. Ancak düzenli bir ızgaraya uygulamak istediğinden, önerilen çözümümde uygulanan yöntem işe yarayacak.
ahmadhanb

sadece gerçeği not edin, başka bir iyi fikriniz varsa! Özellikle şebekem düzenli olmadığından!
Victor

2

Bu çözüm dikdörtgen ızgaralar için çalışır ve otomatiktir (herhangi bir senaryo için herhangi bir şeyi manuel olarak ayarlamadan çalışmalıdır).

Sayfa numaralarını içeren bir kılavuzunuz olduğunu varsayalım. İşleme komut dosyasını , ızgara katmanını ve sayfa numarası alanını parametre olarak seçerek çalıştırabilirsiniz . Komut dosyası right, left, above, below, ızgara katmanında dört alan ( ) oluşturur ve her ızgara hücresi için karşılık gelen komşu sayfa kimliğini hesaplar. Ardından, [% if( "left" is not NULL, 'to page' || "left", "" ) %]komşu sayfa etiketlerini göstermek için ifadelerinizi (örn. ) Kullanabilirsiniz .

QGIS Kaynak Paylaşımı eklentisinden deposumu ( https://github.com/gacarrillor/QGIS-Resources.git ) eklemeniz ve komut dosyasını yüklemeniz yeterlidir: resim açıklamasını buraya girin

resim açıklamasını buraya girin

Nasıl çalışır

Komut dosyası, hem geçerli ızgara hücresinden hem de kesişen her hücreden sınırlayıcı kutu koordinatlarını karşılaştırarak ilişkiyi belirler (sağ, sol, yukarıda veya altında). Her ilişki için koordinatlardan birinin eksik olduğu ortaya çıkıyor.

İlişki ise above, eksik koordinat yMin, yani mevcut ızgara hücresinin sınırlayıcı kutusundaki diğer tüm 3 koordinat yukarıdaki hücrenin sınırlayıcı kutusunda bulunur. QGIS sınırlayan kutuları bu sırada tanımlanır unutmayın: [xMin, yMin, xMax, yMax].

Sayısal bir örnek için, kenarları 1 olan dikdörtgenler alalım. Geçerli hücrenin sınırlama kutusunun olarak tanımlandığını varsayalım bbox1=[0,0,1,1]. Yukarıdaki hücrenin sınırlayıcı kutusu olarak tanımlanır bbox2=[0,1,1,2]. Bbox1'deki X koordinatları bbox2'de bulunurken, bbox1'ler bbox2'nin yMinY koordinatlarında eksiktir.

4 ilişkimizi şu şekilde tanımlayabiliriz (o: şimdiki, #: eksik):

right: [#,o,o,o]
above: [o,#,o,o]
left:  [o,o,#,o]
below: [o,o,o,#]

Gördüğünüz gibi, eksik dizin bize ihtiyacımız olan tüm bilgileri veriyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.