PostGIS로 맨해튼 거리를 어떻게 계산합니까?


9

ST_Distance 함수를 사용하여 두 기하학 (기차역과 건물) 사이의 거리를 계산하고 있습니다. 모든 건물과 모든 기차역이 우수하고 완전한 거리 격자가있는 시카고에 있다는 것을 알고 있으므로 맨해튼 을 사용하고 싶습니다 (또는 택시) 거리 .

이에 대한 일반적인 공식은 X의 차이에 Y의 차이를 더한 것이므로 Abs (X1-X2) + Abs (Y1-Y2)입니다.

어떤 PostgreSQL 쿼리가이 작업을 수행합니까?


1
여기서 간단히 생각해보십시오. 그리드 'x'와 'y'는 반드시 좌표 시스템의 'x'와 'y'와 일치하지 않아도됩니다. 따라서 성분을 추출하고 계산하기 전에 벡터를 회전시켜야 할 수도 있습니다.
Craig Ringer

@CraigRinger 좌표를 로컬에서 널리 사용되는 투영, EPSG 3435, 일리노이 StatePlane East Feet로 변환합니다. 이것은 시카고 시가 모든 GIS 작업에 사용합니다. Google지도 보행 거리 계산을 사용하여 일부 유효성 검사로 내 질문에 대답했습니다.
stevevance

1
pgRouting 모듈로 PostGIS 데이터를 확장 하고 내장 기능을 사용하는 것도 고려해 보셨습니까 ? 분명히 A * 방법은 비슷한 것을 사용합니다 .
RyanKDalton

@RyanDalton 나는 내 다른 프로젝트에 pgRouting을 사용하는 것을 고려 했지만 이 프로젝트에 대한 프로젝트 를 설정하는 번거 로움은 경로를 계산하는 데 더 정확한 결과 또는 리소스 비용이 가치가 없습니다.
stevevance

답변:


6

제안 된 쿼리로 내 질문에 대답하고 있습니다.

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

결과적으로 일부 열이 잘립니다.

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

첫 번째 숫자 열은 ST_Distance PostGIS 함수로 계산 한 거리 (EPS 3435를 사용하기 때문에 피트 단위)이며 두 번째 숫자 열은 맨해튼 거리 공식의 결과입니다.

나는 두 번째 결과를 확인하여 Addison Blue Line CTA 역과 3226 W Belle Plaine Ave (구문에서 '100533644'로 표시)의 건물 사이의 Google지도에서 도보 거리를 얻었습니다. Google지도는 1.1 마일 걷기 경로를 출력했으며 Postgres 결과는 5,790 피트 = 1.09 마일입니다. 내 목적에 차이가 있습니다.


1
이것은 훌륭합니다-PGRouting 'driving distance'기능에서 다루는 문제를 해결했을 수도 있습니다 ... 나는 우리가 DPS에서 가지고있는 몇 가지 문제에 대해 이것을 테스트 할 것입니다 ...!
DPSSpatial

@mapBaker 감사합니다! pgRouting은 간단한 수학 요구에 비해 너무 복잡합니다.
stevevance

3

삼각법과 내장 함수를 사용 ST_Azimuth하여 멋진 함수로 캡슐화 하는 약간 더 우아한 솔루션을 찾았습니다 .

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.