PostGIS'te iki çizginin kesişme açısını nasıl hesaplayabilirim?


19

PostGIS'de kesiştikleri iki çizgi arasındaki açıyı hesaplamak istiyorum.

PostGIS açı hesaplamaları için başlangıç noktası olarak görünüyor ST_Azimuth - ama bu girdi olarak puan alır. İlk düşüncem kesişen çizgilerin uç noktalarını almak ve bunlar üzerinde bir Azimut hesaplaması yapmaktı. Bu yeterince iyi değil, çünkü çizgi özelliklerinin çoğu düz değil ve kesişimdeki açı ile ilgileniyorum. Bu yüzden, şu adımları izleyen iç içe geçmiş bir işlem var:

  1. İki çizgi özellik tablosu arasındaki tüm kesişimleri belirleyin.
  2. Kavşak noktasının etrafında çok küçük bir tampon oluşturun
  3. Çizgi özelliklerinin tampon dışıyla kesiştiği noktaları belirleyin (birden fazla varsa ilk noktayı alarak - gerçekten sadece açının 0, 90 veya 180 dereceye yakın olup olmadığıyla ilgileniyorum)
  4. Bu iki nokta için ST_Azimuth değerini hesaplayın.

Tam SQL burada yayınlamak biraz uzun, ama ilgileniyorsanız burada büktüm . (Bu arada, WITH ifadelerinin aşağısına inen tüm alanları taşımaktan daha iyi bir yol var mı?)

Sonuçlar doğru görünmüyor, bu yüzden açıkça yanlış bir şey yapıyorum:

çıktı örneği 1 çıktı örneği 2

DÜZENLEME EPSG: 3785 hesaplamaları yeniden yaptım ve sonuçlar biraz farklı ama yine de doğru değil:

3785 # 1 çıktı 3785 # 2 çıktı

Sorum şu: Bu süreçte kusurların nerede olduğu. ST_Azimuth'un ne yaptığını yanlış anlıyor muyum? CRS sorunu var mı? Tamamen başka bir şey mi? Ya da belki bunu yapmanın çok, çok daha basit bir yolu var mı?


1
Orijinal CRS neydi? Açı hesaplamaları, öngörülmemiş enlem / boylam (SRID = 4326) ile değil, uyumlu bir projeksiyon ile yapılmalıdır.
Mike T

EPSG: 4326 koordinatları başlangıçta, tüm işlemlerin aynı CRS'de yapılacağından% 100 emin olmak için ST_Translate'i dahil ettim. Konform bir projeksiyon deneyeceğim, teşekkürler.
mvexel

Hesaplamaları EPSG: 3785 olarak yeniden düzenledim ve bir fark yaratıyor - yeni sonuçları göstermek için soruyu değiştireceğim - ancak sonuç hala gerçek açıyı yansıtmıyor.
mvexel

Yanıtlar:


12

İsa'nın Doğuşu vardı. Oldukça sıradan. PostGIS'in doğru açıyı hesaplaması için önemli bir bilgi parçasını dışarıda bırakıyordum.

Hesapladığım şey, sadece küçük tamponun dışını kesen iki nokta arasındaki açı idi. Kavşak açısını hesaplamak için, tampon dış tarafındaki her iki nokta ile iki çizgi özelliğinin kavşak noktası arasındaki her iki açıyı da hesaplayıp çıkarmam gerekir.

Tam SQL'i güncelledim , ancak göze çarpan bit:

SELECT
    ...
    abs
    (
        round
        (
            degrees
            (
            ST_Azimuth
            (
                points.point2,
                points.intersection
            )
            -
            ST_Azimuth
            (
                points.point1,
                points.intersection
            )
        )::decimal % 180.0
        ,2
    )
)
AS angle
...
FROM
points 

1
Kavşakta tamponlanmış noktanın açısını düşünüyordum, ancak ayrıntılı olarak gidecek zamanım yok. Başka bir yön, açısal birimlerdir. Sonuçları derece olarak almak için ST_Azimuth'tan radyan cinsinden sonucu 180.0 / pi () ile çarpmanız gerekir.
Mike T

Evet, bunun için PostgreSQL derece () işlevini kullanıyorum.
mvexel

Cleaver. (Şimdiye kadar bir derece işlevi olduğunu bile bilmiyordum.) Tüm bu mantığı bir işlev çağrısına sarmak güzel olurdu, ama nasıl çalışacağını kavramsallaştırmakta zorlanıyorum, yani ST_IntersectionAngle(...?
Mike T

Aslında bir PostGIS işlevi olmadığına şaşırdım. Bu konudaki görüşleriniz için teşekkür ederiz.
mvexel

2

Son zamanlarda aynı şeyi hesaplamak zorunda kaldım, ancak daha basit ve daha hızlı bir yaklaşıma karar verdim.

Azimut hesaplaması için fazladan noktaları bulmak için, ST_Line_Locate_Point ve ST_Line_Interpolate_Point kullanarak kesişimin arkasındaki uzunluğun (veya hattın en başında gerçekleşmesi nadiren sonra) bir permyriad'ı kontrol ediyorum :

abs(degrees( 
  ST_Azimuth (
    intersection, 
    ST_Line_Interpolate_Point(
      line1, 
      abs(ST_Line_Locate_Point(line1, intersection) - 0.0001)
    )
  )
  -
  ST_Azimuth (
    intersection, 
    ST_Line_Interpolate_Point(
      line2, 
      abs(ST_Line_Locate_Point(line2, intersection) - 0.0001)
    )
  )
))

Permirriad keyfiydi ve daha tutarlı sonuçlar için mutlak bir ofset kullanmak daha iyi olurdu. Örneğin, 20 metre önceden kontrol etmek için sırasıyla 0.0001 20/ST_Length(line1)ve değerini değiştirirsiniz 20/ST_Length(line2).

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.