일치하는 세그먼트에 대한 알고리즘


23

세그먼트와 일치하는 가장 좋은 알고리즘은 무엇입니까?

두 개의지도 소스에서 해당 세그먼트를 일치 시키려고합니다. 하나는 덜 정확하지만 세그먼트 이름은 있고 다른 하나는 세그먼트 이름이없는 것이 더 정확합니다. 더 정확한 맵에 세그먼트 이름을 반자동으로 적용하고 싶습니다.

요청 된 알고리즘은 "일치"가 잘 정의되지 않았고 시나리오마다 많은 요소 (방향, 상대 길이, 거리)의 가중치가 다를 수 있기 때문에 모호한 설명이 있습니다. 그러나이 문제를 처리하는 일반적인 방법에 대한 기본 지식을 찾고 있습니다.

오픈 소스 환경 (PostGIS, shapely, ...)에 대한 실제 구현은 따뜻하게 환영합니다.

샘플 세그먼트 : 아래 이미지를 참조하십시오.


데이터의 스냅 샷을 게시하여 세그먼트 밀도와 그 차이에 대한 개요를 제공 할 수 있습니까?
Julien

1
플리커에 그림을 게시했습니다. 링크를 참조하십시오.
Adam Matan

1
"conflation"을 검색해보십시오.
커크 Kuykendall

답변:


14

하우스 도르프 거리가 사용될 수있다 : 일치하는 부분이 거리에 따라 '확대'세그먼트 일 수있다. 세그먼트를 계산하는 것은 매우 간단합니다.

JTS 에서 무료 Java 구현을 사용할 수 있습니다 ( JTS Distance Package 참조) . JCS Conflation Suite (현재 폐기 됨, 소스 사본 (예 : https://github.com/oschrenk/jcs ))를 살펴볼 수도 있습니다 .


2
Hausdorff의 거리는 GEOS의 PostGIS에도 있으므로 JTS와 동일한 알고리즘입니다.
Nicklas Avén

10

'최고'가 무엇인지 잘 모르겠습니다. 세그먼트의 세부 사항에 따라 달라지기 때문입니다.

일반적으로 좋은 접근 방식은 세그먼트를 중요한 기하학적 정보로 해시하는 것 입니다. 여기에는 최소한 중심 위치 (x, y), 방향 (0-180도) 및 길이가 포함됩니다. 적절한 가중치를 적용하고 방향을 미세 조정하면 (180이 "주변"으로 다시 0으로 돌아 감) 거의 모든 통계 클러스터링 알고리즘 을 모든 세그먼트의 컬렉션에 적용 할 수 있습니다. ( K- 평균 은 좋은 옵션이지만 대부분의 계층 적 방법은 잘 작동해야합니다. 이러한 군집 분석은 빠르고 적용하기 쉬운 경향이 있습니다.) 이상적으로는 세그먼트가 쌍으로 (또는 일치하지 않는 세그먼트의 경우 단일 톤) 나머지는 발생합니다. 쉽습니다.

오리엔테이션 문제를 처리하는 한 가지 방법은 레이블이있는 세그먼트를 복사하는 것입니다. 첫 번째 사본의 방향이 90보다 작 으면 180도를 더하고 그렇지 않으면 방향에서 180도를 뺍니다. 이렇게하면 데이터 세트가 (확실히) 확대되지만 알고리즘은 변경되지 않습니다.

좌표, 길이 및 방향의 차이가 해당 세그먼트의 유사성에 대해 상당히 다른 것을 의미 할 수 있으므로 가중치가 필요합니다. 많은 어플리케이션에서 세그먼트 간의 차이는 엔드 포인트의 위치 차이로 인해 발생합니다. 대략적인 근사치로서, 세그먼트 길이의 전형적인 변동은 종점 간의 전형적인 변동과 거의 같을 것으로 예상 할 수 있습니다. 따라서 x, y 및 길이와 관련된 가중치는 거의 같아야합니다. 까다로운 부분은 가중치 방향입니다. 방향은 거리와 동일하지 않으며, 더 짧은 세그먼트는 긴 세그먼트보다 방향이 잘못 될 가능성이 높기 때문입니다. 세그먼트 사이의 일반적인 간격 크기와 약간의 오 방향을 동일시하고 절차가 잘 작동 할 때까지 조정하는 시행 착오 방법을 고려하십시오. 안내를 위해L 은 전형적인 세그먼트 길이입니다. 자그마한 각도에 의한 배향 변화 t의 각도는 대략의 거리를 넓힐 L를 / 2 * t / 60이고 (60 한 라디안 정도의 수에 근접) L / 120 회 t를 . 즉 , x, y 및 길이에 대한 단위 중량과 방향에 대한 L / 120 의 중량으로 시작하는 것이 좋습니다 .

요약 하면이 제안은 다음과 같습니다.

  1. 레이블이있는 세그먼트를 복사합니다 (방향 미세 조정에 대한 단락에 설명 된대로).

  2. 각 세그먼트를 4 배 (x, y, 길이, L / 120 * 방향)로 변환합니다. 여기서 L 은 일반적인 세그먼트 길이입니다.

  3. 사중의 군집 분석을 수행하십시오. 좋은 통계 패키지를 사용하십시오 ( R 은 무료 임).

  4. 클러스터 분석 출력을 찾아보기 테이블로 사용하여 레이블이 지정된 세그먼트를 근처의 레이블이없는 세그먼트와 연관 ​​시키십시오.


4

약 5 년 전에 비슷한 요구 사항을 가진 프로젝트를 진행했습니다. 거리 중심선 (상대 좌표 정밀도가 높은)의 좌표를 고속도로 성능 모니터링 시스템 (HPMS) 트래픽 네트워크 링크와 결합하는 작업이 포함되었습니다.

당시 FHWA는 이런 종류의 작업을 수행하는 도구를 제공하지 않았습니다. 변경되었을 수도 있습니다. 확인하고 싶을 수도 있습니다. 고속도로 데이터를 사용하지 않더라도 도구가 여전히 관련 될 수 있습니다.

ArcGIS로 작성했지만 ISegmentGraph 와 유사한 추적 기능을 제공하는 한 알고리즘은 오픈 소스에서 작동해야합니다 .

// features is a collection of features with higher geometry
// Links are a collection features with attributes but low res geometry
For each Link in lowResFeatureclass
    point startPoint = SnapToClosestPoint(Link.StartPoint, hiResfeatures);
    if(startPoint == null)
       continue;
    point endPoint = SnapToClosest(Link.EndPoint, hiResfeatures);
    if(endPoint == null)
       continue;
    polyline trace = Trace(hiResfeatures,startPoint,endPoint);
    if(polyline != null)
    {
        // write out a link with high precision polyline
        Write(Link,polyline);
    }
Next Link

4

여기 아이디어가 온다

정점이 다른 선 스트링과 일정 거리 내에 있는지 비교하고 테스트하기 위해 선 스트링 중 하나를 찢을 경우 여러 가지 방법으로 테스트를 제어 할 수 있습니다.

이 예제는 PostGIS에서 작동합니다 (누가 추측 할 수 있습니다 :-))

먼저 table_1의 선 스트링에있는 모든 정점이 0.5 미터 (맵 단위)이거나 table_2의 선 스트링에 더 가까운 경우 일치가 있다고 가정합니다.

SELECT a.id, b.id FROM
(SELECT ST_NPoints(the_geom) as num_of_points,
(ST_Dumppoints(the_geom)).geom as p, id FROM table_1) a 
INNER JOIN 
table_2 b 
ON ST_DWithin(a.p, b.the_geom, 0.5) GROUP BY a.id, b.id
HAVING COUNT(*)=num_of_points;

그런 다음 table_1의 라인 스트링에있는 vertex_points의 60 % 이상이 table_2의 라인 스트링 거리 내에 있으면 일치한다고 말할 수 있습니다.

SELECT a.id, b.id FROM
(SELECT ST_NPoints(the_geom) as num_of_points, 
(ST_Dumppoints(the_geom)).geom as p, id FROM table_1) a 
INNER JOIN 
table_2 b 
ON ST_DWithin(a.p, b.the_geom, 0.5) GROUP BY a.id, b.id
HAVING COUNT(b.id)/num_of_points::float > 0.6

또는 한 지점이 범위 내에 있지 않다는 것을 인정할 수 있습니다.

SELECT a.id, b.id FROM
(SELECT ST_NPoints(the_geom) as num_of_points, 
(ST_Dumppoints(the_geom)).geom as p, id FROM table_1) a 
INNER JOIN 
table_2 b 
ON ST_DWithin(a.p, b.the_geom, 0.5) GROUP BY a.id, b.id
HAVING COUNT(b.id)-num_of_points <= 1;

table_1 및 table_2를 사용하여 역순으로 쿼리를 실행해야합니다.

나는 그것이 얼마나 빠른지 모른다. ST_Dumppoints는 현재 PostGIS에서 sql 함수이며 C 함수가 아니 어서 필요한 것보다 느립니다. 그러나 어쨌든 그것은 매우 빠를 것이라고 생각합니다.

공간 인덱스는 ST_Dwithin이 효과적으로 작동하는 데 많은 도움이됩니다.

HTH 니켈 라스


1
+1 이것은 내가 마지막으로 사용한 접근법과 매우 유사합니다 (곧 답변을 게시 할 것입니다).
Adam Matan 2019

4

경계 생성기에서 조잡한 선 세그먼트 일치를 처리하고 겹치는 코드를 작성했습니다. http://blog.shoutis.org/2008/10/inside-boundary-generator-computational.html 여기에 (공평한 초등) 수학을 썼습니다 . 코드는 오픈 소스이며 해당 블로그 게시물에서 링크되어 있습니다.

코드는 매우 간단한 접근 방식을 따릅니다.

  • 주어진 각도 및 거리 공차 내에서 두 선 세그먼트가 겹치는 지, 겹치는 정도를 알려주는 세그먼트 세그먼트 테스트입니다.
  • 데이터 세트의 모든 선분을 데이터 세트의 다른 모든 선분에 대해 테스트 할 필요가없는 빠른 공간 인덱스입니다.

이 방법의 주요 장점은 유효한 각도, 거리 및 겹침 길이에 대해 매우 정밀한 노브를 얻는 것입니다. 단점은 일반적으로 두 선 세그먼트의 유사성을 측정하는 방법이 아니기 때문에 통계 클러스터링을 수행하여 가능한 일치 항목을 결정하는 것이 훨씬 어렵습니다. 정확한 손잡이가 붙어 있습니다.

참고 : 충분한 SQL 잘라내기를 사용하면 세그먼트 세그먼트 테스트를 WHERE 절에 넣을 수 있다고 생각합니다 ... :)

건배!


+1 이것은 좋은 접근법입니다. 쿼드 트리를 작성하면 계산 상 우수합니다. 그러나주의 세부 사항에 필요한 :에서 세그먼트 원산지 : 세그먼트 근접 또는 유사성을 (대신 교차로) 결정할 때, 당신은 당신의 데이터 구조는 세그먼트의 독특한 표현을 제공하지 않는다는 사실을 설명 할 필요가 X를 방향으로, V , 길이 t는 에서 세그먼트 발신 똑같이 잘 X + t의 V 방향에서 -v 길이의 t는 .
whuber

1

여기 에서 지도 일치를위한 대략적인 프로토 타입을 구현했습니다 . 이는 상대적으로 사용하기 쉽습니다. 오픈 소스 라우팅 엔진을 기반으로하며 Java로 작성되었습니다. 사용 된 알고리즘은 여기 에 설명되어 있습니다 .

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