PostGIS kullanarak en yakın komşu hesaplamayı optimize etme


13

Çokgenlerin en yakın komşularını hesaplamak için PostGIS kullanıyorum. Hesaplamak istediğim, her çokgenden en yakın çokgene olan minimum mesafedir.

Şimdiye kadar (küçük bir değişiklikle alıntıladığım) Mike Toews'ın cevabından çok yardım aldım :

SELECT 
  a.hgt AS a_hgt,
  b.hgt AS b_hgt,
  ST_Distance(a.the_geom, b.the_geom) AS distance_between_a_and_b
FROM 
  public."TestArea" AS a, public."TestArea" AS b
WHERE
  a.hgt !=  b.hgt AND ST_Distance(a.the_geom, b.the_geom) < 400

Sonra minimum hesapladım:

SELECT a_hgt, MIN(distance_between_a_and_b)
FROM public."lon_TestArea"
GROUP BY a_hgt

Bununla birlikte, benim meydan okumam bunu çok sayıda çokgen (1.000.000) için hesaplamaktır. Yukarıdaki hesaplama her çokgeni diğer çokgenlerle karşılaştırdığından, 10 ^ 12 hesaplamaları yapmak zorunda kalmamam için hesaplamayı nasıl geliştirebileceğimi merak ettim.

Sahip olduğum bir düşünce, her çokgeni arabelleğe almak ve daha sonra o çokgenin arabelleğindeki tüm değerlerin en yakın komşularını hesaplamak ve minimum değeri kaydetmekti. Bunun en iyi yaklaşım olup olmadığından ya da PostGIS'te kullanmam gereken bir işlev olup olmadığından emin değilim.


DÜZENLEME: Nicklas'ın önerilerinden birini kullanarak şunları deniyorum ST_Dwithin():

CREATE TABLE mytable_withinRange AS SELECT 
  a.hgt AS a_hgt,
  b.hgt AS b_hgt,
  ST_DWithin(a.the_geom, b.the_geom, 400)
FROM 
  public."lon_TestArea" AS a, public."lon_TestArea" AS b

resim açıklamasını buraya girin

Bu, her çokgenin kimliğinin ve belirli bir mesafe içinde olup olmadığını gösteren bir tablo döndürür. IF/ELSESQL kullanarak bir tür ifadesi oluşturmak mümkün mü ? ( CASEDurumu kullanma hakkında okudum ) Yoksa ürettiğim tabloyu özgün tabloya katmayı ve sonra sorguyu tekrar ST_Distance kullanarak çalıştırmayı denemeliyim?


cevabımdaki boston gis bağlantısındaki ikinci örneğe bir göz atın. sorgunun nerede bölümünde st_dwithin kullanmalısınız.
Nicklas Avén

Yanıtlar:


7

BostonGIS sayfasında büyük bir "En Yakın Komşu" bölümü var .


DÜZENLE:

Peki ya

CREATE TABLE mytable_withinRange AS SELECT 
 a.hgt AS a_hgt,
 b.hgt AS b_hgt
FROM 
 public."lon_TestArea" AS a, public."lon_TestArea" AS b
WHERE 
 ST_DWithin(a.the_geom, b.the_geom, 400)

Hakkında CASE deyimi :

SELECT a,
   CASE WHEN a=1 THEN 'one'
        WHEN a=2 THEN 'two'
        ELSE 'other'
   END
FROM test;

Hattın WHERE ST_DWithin(a.the_geom, b.the_geom, 400)daha büyük mesafelerin 400hesaplanmasını mı yoksa yeni kaydedilmesini mi engelleyeceğini biliyor musunuz ? Ayrıca, bir vaka ifadesi sayısal hesaplamalar için kullanılabilir mi? örneğin:CASE WHEN ST_DWithin(a.the_geom, b.the_geom, 400) == TRUE THEN ST_DWithin(a.the_geom, b.the_geom)
djq

1
@celenius Mesafe 400 m'den fazla ise, seçilen parçadaki hiçbir şey hesaplanmaz. Neden karışıma dava koymak istediğinizi anlamıyorum.
Nicklas Avén

@Nicklas tamam - anlıyorum. Sadece 400'den daha az mesafenin depolanmış olabileceğini düşündüm; bu benden daha kolay. Teşekkürler!
djq

3

alo

Bazı şeylerin daha hızlı hareket etmesini sağlamayı düşünen bazı şeyler ve gelecekte mümkün olabilecek bazı şeyler var.

İlk olarak , tüm kombinasyonları hesaplamaktan kaçınmak için minimum aralıktaki çokgenleri bulmak için bir tampon kullanmayı düşündüğünüzü söylemiştiniz.

Başka linkte bahsedildiği gibi Boston gis PostGIS içinde kullandığı yapmanın doğru yolunu ST_Dwithin . ST_Diçinde belirli bir aralıktaki komşuları bulmak için dizini kullanır.

Tüm çokgenler için sadece st_DWithin için sabit bir değer kullanmanın yeterli olup olmadığı veya underdark ve wildintellect gibi bir şey yapmanız gerekip gerekmediği elbette veri kümesine bağlıdır.

İkinci bir şey de PostGIS 1.5+ 'ı burada kullanmaktır. Çünkü sınırlayıcı kutuları kesişmiyorsa 1.5'ten beri çokgene çokgen hesaplamaları çok daha hızlıdır. Bununla ilgili daha fazla bilgiyi buradan edinebilirsiniz. .

Sözü edilen üçüncü şey gelecek.

PostgreSQL 9.1'de knn-gist adı verilen bir şey olacak. Bu sadece evet veya hayır yanıtı verilemez aynı zamanda doğrudan dizinden sipariş sonucu döndüren bir endeks. Bunu burada okuyabilirsiniz .

Ancak, knist gist böyle şeylere yardımcı olmadan önce PostGIS tarafında yapılacak çok iş olacak. Burada bir bilet var.

Saygılarımızla

Nicklas


Öneriler için teşekkürler Nicklas; pgAdmin / PostGIS'i çalıştırmak ve çalıştırmak için zor bulduğum için şu anda 1.5 kullanmaktan kaçınacağımı düşünüyorum. Görünüşe göre ST_Dwithin () bunu çözmenin bir yolu.
djq

2
1.5 kurulumu postgresql ve pgadmin arasındaki ilişkiyi etkilemez. veritabanı sunucusunda birden fazla postgis sürümüne sahip olabilir ve bunlardan birini veritabanına yükleyebilirsiniz. böylece bir 1.4 ve bir 1.5 veritabanına sahip olabilirsiniz.
Nicklas Avén

1

Nathan Kerr'ın ustalarının çalışmalarıyla ilgili aşağıdaki sayfalar bu doğrudan konu hakkında iyi bir fikir vermektedir. İş arkadaşım burada ve burada Bostongis yöntemini denedi , ancak doğru çalışmasını sağlayan bazı sorunlar vardı.

Tampona benzer olduğunu düşünmek için başka bir yaklaşım, genişleyen / daralan bir dikdörtgen yapmaktır. Temel olarak 1 en az bir kesişmeyi yakalayacağınızı düşündüğünüz bir kesişme kutusu (orijinal çokgeninizin bbox'ına düz + x birimleri) yapın. Kesişen veriler için, bu eşleşmeleri en yakın olanı test eden bir alt sorgu gerçekleştirin. Eşleşemeyen veriler için sınırlama kutusunu genişletin ve tekrarlayın.

Bu açıkça tekrarlanan bir programlama problemidir ve Python'da Shagely ile doğrudan postgis'te% 100'den daha iyi yapılabilir.

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.