길이가 다른 일치하는 세그먼트


13

나는 작은 세그먼트를 큰 세그먼트와 일치 시키려고합니다.

내가 가진 데이터의 전형적인 예는 다음과 같습니다.

세그먼트

711과 707이 일치하지 않는 동안 세그먼트 652와 198969를 일치시켜야합니다.

나는 다른 방법, 특히 Hausdorff 거리를 찾았습니다 ( 여기 의 답변을 바탕으로 ). PostGIS를 사용하여 계산했지만 이상한 결과가 나타납니다. 최단 거리는 707에서 198985 사이이며 652는 198985보다 198969까지 더 먼 거리입니다 (필요한 경우 쿼리 및 결과를 추가 할 수 있음).

실제로 Hausdorff가이를 해결하는 올바른 방법입니까? 다른 접근법이 있습니까? 나는 내가 언급 한 매개 변수 (거리, 베어링 등)에 대한 일련의 검사를 만들려고 생각했지만 가장자리 사례 또는 처리량을 임계 값과 같은 것들을 처리하기 위해 여러 조건을 추가 해야하는 것을 두려워합니다. 서로 마주보고

업데이트 : 허용 가능한 타협처럼 보이는 방법을 찾았습니다.

  • 먼저 <->10 미터 미만 의 (PostGIS 연산자를 사용하여) 일치시키려는 파란색 세그먼트에서 가장 가까운 10 개의 검은 세그먼트를 찾습니다 .
  • 그런 다음 각 검은 색 세그먼트에서 파란색 세그먼트의 끝 부분에 가장 가까운 점을 찾아서 새 세그먼트를 만들고 ST_ClosestPoint길이가 파란색의 90 % 미만인 결과를 필터링합니다 (세그먼트가 아닌 것을 의미합니다) 방향 또는 베어링 차이가 ~ 20 ° 이상인 경우)
  • 그런 다음 거리와 Hausdorff 거리로 정렬 된 첫 번째 결과를 얻습니다.

약간의 조정이 필요할 수 있지만 현재로서는 허용 가능한 작업을 수행하는 것 같습니다. 가장자리 케이스를 놓친 경우 실행할 다른 방법이나 추가 검사를 계속 찾고 있습니다.


1
왜 (파란색) 세그먼트의 끝점을 사용하여 대상 (검은 색) 세그먼트 사이의 잠재적 일치를 식별하지 않습니까? 찾고있는 세그먼트 일치는 두 엔드 포인트가 공통 대상에 가까울 때 발생합니다. 이는 간단한 쿼리 실행입니다. 이 방법은 세그먼트 끝점의 위치 오류로 인한 불일치를 처리합니다. 그렇지 않으면 대처하기 어려울 수 있습니다. 매우 짧은 (파란색) 세그먼트는 긴 세그먼트보다 훨씬 덜 정밀한 베어링입니다.
whuber

1
그렇습니다. 실제로이 라인을 따라 무언가를 시도하고 있습니다. 세부 사항으로 질문을 업데이트하겠습니다.
Jukurrpa

1
내가 당신을 올바르게 이해하고 있는지 확실하지 않지만 파란색 선의 중심을 만든 다음 가장 가까운 선까지의 거리를 확인하여 가장 짧은 거리를 남겨 두었습니까?
Cyril Mikhalchenko

1
안녕하세요 Cyril, 저는 더 이상이 문제에 대해 연구하고 있지 않지만, 문제는 방향에 따라 파란색 선과 일치하고 검은 선과 얼마나 "얼마나"직면하고 있는가였습니다. 이 경우에 711은 그가 검은 색 세그먼트에 아주 가깝더라도 아무 것도 일치하지 않아야 함을 의미합니다
Jukurrpa

답변:


1

내가 작성한 몇 가지 기능은 다음과 같습니다. 폴리 라인이 선을 분해하는 경우 선이 폴리 라인인지 또는 세그먼트인지 확인한 다음 선의 첫 번째 점과 마지막 점의 방위각과 역을 비교하고 코드를 결정할 수있는 적절한 기준을 설정하십시오. 이것들은 아크 피 방법이지만 수정할 수 있습니다.

선분 ESRI @shape에서 방위각 반환

def returnAzimuth(shape):
    point1 = shape.firstPoint
    point2 = shape.lastPoint
    dX = point2.X-point1.X
    dY = point2.Y-point1.Y
    az = math.atan2(dX,dY)*180/math.pi
    if az<0:
        az = az+360
        return az
    return az

ESRI 포인트에서 역으로 반환

def returnInverse(point1,point2):
    dX = point2.X-point1.X
    dY = point2.Y-point1.Y
    dis = sqrt(dX**2+dY**2)
    az = math.atan2(dX,dY)*180/math.pi
    if az<0:
        az = az+360
        return az,dis
    return az,dis

폴리 라인을 선분으로 분해

def explodePolyline(shape):
    sr = "insert your spatial reference"
    lines=[]
    pnts = shape.getPart(0)
    for x in range(len(pnts)-1):
        array = arcpy.Array()
        point1 = arcpy.Point(pnts.getObject(x).X,pnts.getObject(x).Y,pnts.getObject(x).Z)
        point2 = arcpy.Point(pnts.getObject(x+1).X,pnts.getObject(x+1).Y,pnts.getObject(x+1).Z)
        array.add(point1)
        array.add(point2)
        line = arcpy.Polyline(array,sr,True,True)
        print(line)
        lines.append(line)
    return lines

이처럼 당신의 테이블을 통해 실행

for shape in Table:
    for shape2 in Table:
         check if shape is polyline:
            if yes, explode and compare returned line segments with shape2
                for seg in returnedlinesegments
                    if seg.firstpoint=shape2.lastpoint and shape.az=shape2.az
                        do stuff.....
            if no, compare shape and shape2
                if shape.firstpoint=shape2.lastpoint and shape.az=shape2.az
                   do stuff.....

이러한 속성은 postgis에서 사용할 수 있어야합니다-firstpoint, lastpoint, pointarray 위의 esri 속성을 가장 잘 알고 있기 때문에 위의 속성을 가정하지만 postgis에서 작동하도록 위의 내용을 쉽게 변경할 수 있습니다.

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