PostGIS에서 가장 가까운 지오메트리 찾기


16

함수의 PostGIS "API"를 살펴 보았는데 대부분 비교하기 위해 두 가지 요소가 필요하다는 것을 알았습니다. 예를 들어 ST_Distance 함수는 거리를 찾기 위해 두 개의 지오메트리 / 지리 요소를 사용합니다.

"지오메트리 G를 지정하고 G.id <> GClosest.id 인 표 T에서 가장 가까운 지오메트리 G를 제공하십시오."와 같은 기능은 없습니다.

PL / PgSQL 함수를 작성하여 테이블을 반복하고 각 요소에서 ST_Distance를 호출 할 수 있다는 것을 알고 있지만 더 좋고 효율적인 솔루션이 있기를 바랍니다.


1
당신은 가장 가까운 기하학, 체크까지의 거리에 관심이 있다면 gis.stackexchange.com/questions/11979/...
언더 다크

내가 올바르게 이해했는지 알려주십시오 ... 가장 가까운 거리와 동일한 거리를 가진 다음 기능을 원하십니까?
falcacibar

답변:


7

질문은 전체 레코드와 참조 지오메트리까지의 거리를 반환하는 다음과 같은 단일 (복잡하지만) 쿼리로도 대답 할 수 있습니다. 둘 이상의 레코드가 최소 거리와 일치하면 모두 반환됩니다.

SELECT 
  i.*,
  md.min_distance
FROM
  address AS i, 
  (SELECT 
     ga.address_geom,
     min( ST_Distance(
            ga.address_geom,
            gb.address_geom)
        ) AS min_distance
   FROM
     address AS ga,
     address AS gb 
   WHERE 
     ga.id <> gb.id 
   AND 
     ga.id = 3
   GROUP BY 
     ga.address_geom
  ) AS md 
WHERE 
  ST_Distance( i.address_geom, md.address_geom) = md.min_distance;

주소 테이블 에서이 쿼리를 테스트했으며 작동합니다. 위의 쿼리에서 id = 3 인 가장 가까운 지점을 찾고 있습니다.


이것은 좋은 정보입니다-감사합니다 ... 정의에 따라 min (..) 집계 함수를 이해하지만 예제에서 어떻게 사용되는지 혼란 스럽습니다. st_distance (X, Y)는 두 가지 지오메트리 유형을 취하고 그 사이의 거리 (단일 값)를 반환합니다. 그렇다면 왜 단일 값 결과에서 집계 함수를 호출합니까? 어쩌면 나는 내부 select 서술문을 잘못 해석하고 있을지도 모른다 ...
Jmoney38

그룹 기준 은 전체 결과 집합에 대해 상수 인 ga 형상에 있으므로 ( ga 는 id = 3로 선택됨) 기본적으로 아무 것도 수행하지 않습니다. 이는 테이블을 다시 두 번 조인하지 않고 외부 쿼리의 st_distance 에서 ga 기하학을 사용할 수있게 하는 트릭 입니다. 오늘 나는 파티션 절 을 사용하여 내부 쿼리를 완전히 벗어날 수 있다고 생각했습니다 . 또한 성능을 향상시켜야합니다. 시도해보고 알려 드리겠습니다.
unicoletti

불행히도 창 함수는 8.4에 도입되었으며 이제 postgis와 해당 버전이 모두있는 서버에 액세스 할 수 없으므로 partion 절로 다시 작성된 쿼리를 테스트 할 수 없습니다.
unicoletti

7

George MacKerron은 내가 찾은 간단한 Nearest Neighbor 함수 를 작성했습니다 . 이 함수는 주어진 지형지 물에 가장 가까운 이웃의 ID를 반환합니다.

create or replace function 
  nn(nearTo                   geometry
   , initialDistance          real
   , distanceMultiplier       real 
   , maxPower                 integer
   , nearThings               text
   , nearThingsIdField        text
   , nearThingsGeometryField  text)
 returns integer as $$
declare 
  sql     text;
  result  integer;
begin
  sql := ' select ' || quote_ident(nearThingsIdField) 
      || ' from '   || quote_ident(nearThings)
      || ' where st_dwithin($1, ' 
      ||   quote_ident(nearThingsGeometryField) || ', $2 * ($3 ^ $4))'
      || ' order by st_distance($1, ' || quote_ident(nearThingsGeometryField) || ')'
      || ' limit 1';
  for i in 0..maxPower loop
     execute sql into result using nearTo              -- $1
                                , initialDistance     -- $2
                                , distanceMultiplier  -- $3
                                , i;                  -- $4
    if result is not null then return result; end if;
  end loop;
  return null;
end
$$ language 'plpgsql' stable;

사용 예 :

SELECT id, nn(pt_geom,0.00001,2,100,'nw_node','node_id','node_geom') FROM my_point_table;

... my_point_table의 모든 항목에 대해 nw_node 테이블에서 가장 가까운 노드를 선택합니다.

Boston GIS 사이트 에는 보다 일반적인 기능있습니다 .


좀 더 일반적인 의미로 쿼리 1 : N 쿼리를 만드는 방법에 더 관심이 있습니다. 예를 들어 형상 G에 가장 가까운 요소를 찾는 대신 G와 겹치는 첫 번째 요소를 찾고 싶을 수 있습니다. 정보에 관계없이 감사합니다. 보스턴 GIS와의 연결은 매우 유용했습니다! 나는 이미 일부 치트 시트를 인쇄했다 :-)
Jmoney38

어쩌면 @ Jmoney48와 같이 조금 더 명확하게 질문을 바꿔 쓸 수도 있습니다. 따라서 가장 가까운 이웃 문제에 관심이 없지만 하나의 지오메트리를 테이블의 모든 지오메트리와 비교하는 방법에 관심이 있습니까?
underdark

항상 Boston GIS 사이트의 일반적인 기능을 사용하십시오. 간단한 테이블은 큰 테이블에서 매우 느리고 적용 노력이 더 크지 않습니다.
Vladtn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.