PostGIS ile Manhattan mesafesini nasıl hesaplayabilirim?


9

İki geometri (bir tren istasyonu ve bir bina) arasındaki mesafeyi hesaplamak için ST_Distance işlevini kullanıyorum Tüm binaların ve tüm tren istasyonlarının mükemmel / eksiksiz bir sokak ızgarası olan Chicago'da olduğunu bildiğim için Manhattan'ı kullanmak istiyorum (veya taksi) mesafesi .

Bunun genel formülü X'deki fark artı Y'deki farktır, bu yüzden Abs (X1-X2) + Abs (Y1-Y2).

Hangi PostgreSQL sorgusu bu işe yarayacaktır?


1
Burada kısa bir düşünce: 'x' ve 'y' ızgaralarınız mutlaka koordinat sisteminin 'x' ve 'y' ile aynı hizaya getirilmiş değildir. Bu nedenle, bileşenleri çıkarmadan ve hesaplamadan önce vektörü döndürmeniz gerekebilir.
Craig Ringer

@CraigRinger Koordinatları yerel olarak geçerli projeksiyona dönüştürüyorum, EPSG 3435, Illinois StatePlane East Feet. Bu, Şikago şehri tarafından tüm CBS çalışmaları için kullanılır. Google Haritalar yürüme mesafesi hesaplamasını kullanarak bazı doğrulamayla kendi sorumu yanıtladım.
stevevance

1
PostGIS verilerinizi pgRouting modülü ile genişletmeyi ve yerleşik işlevlerini kullanmayı da düşündünüz mü? Görünüşe göre A * yöntemi benzer bir şey kullanıyor .
RyanKDalton

Ben pgRouting kullanarak kabul var @RyanDalton benim başka proje ama bir tane kurma zorluğu bu proje değerinde daha doğru sonuçlar veya rotayı hesaplanmasında kaynak maliyeti değildir.
stevevance

Yanıtlar:


6

Önerilen bir sorgu ile kendi soruma cevap veriyorum.

select *, ABS(x_permit-x_station)+ABS(y_permit-y_station) as manhattan FROM (SELECT
longname AS NAME,
lines AS metadata,
T .slug,
ST_Distance (
    T .geom,
    ST_Transform (P .geometry, 3435)
) AS distance, 
ST_X(ST_Transform(p.geometry, 3435)) as x_permit,
ST_Y(ST_Transform(p.geometry, 3435)) as y_permit,
ST_X(t.geom) as x_station,
ST_Y(t.geom) as y_station
FROM
permits P,
stations_cta T
WHERE
P .permit_ = '100533644'
ORDER BY
distance
LIMIT 2) as foo

Bu, bazı sütunlar kesildiğinde aşağıdakilere neden olur:

Kedzie-Ravenswood   Brown Line  3738.52830193659    3796.29623843171
Addison-O'Hare  Blue Line   4105.37381385087    5790.20002649655

İlk numaralı sütun ST_Distance PostGIS işlevi tarafından hesaplanan mesafedir (feet cinsinden, çünkü EPSG 3435 kullanıyorum) ve ikinci numaralı sütun Manhattan uzaklık formülünün sonucudur.

İkinci sonucu, Addison Blue Line CTA istasyonu ile 3226 W Belle Plaine Ave'deki binada (sorguda '100533644' olarak belirtildi) arasındaki Google Haritalar'dan yürüme mesafesini elde ederek nokta kontrol ettim. Google Haritalar 1,7 mil yürüyüş rotası çıkardı. Aradaki fark benim amacım için kabul edilebilir.


1
bu harika - PGRouting 'sürüş mesafesi' fonksiyonunda ele alınan bir sorunu çözmüş olabilirsiniz ... Bunu DPS'de yaşadığımız bazı problemler için test edeceğim ...!
DPSSpatial

@mapBaker Teşekkürler! pgRouting basit matematik ihtiyacım için çok karmaşık.
stevevance

3

Ben de trigonometri ve yerleşik ST_Azimuthfonksiyon kullanan ve güzel bir fonksiyon içine kapsüllenmiş biraz daha zarif bir çözüm buldum düşünüyorum :

CREATE OR REPLACE FUNCTION JZ_TaxiCab(p1 geometry, p2 geometry)
RETURNS REAL AS $$
DECLARE 
    az REAL;
    h REAL;
BEGIN
    az := ST_Azimuth(p1, p2);
    /* Cast to geography to get result in meters */
    h := ST_Distance(p1::geography, p2::geography);
    /*   Note: we have to take abs() because the values returned by
         can be positive or negative. We really don't necessarily care
         about the reference point since it's going to be a right triangle.
    */
    RETURN h * abs(sin(az)) + h * abs(cos(az));
END;
$$  LANGUAGE plpgsql
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.