새로운 버전의 포스트가 있습니다. 아래 내용이 틀리지는 않았으나 거리 계산 시 평면상에서의 계산만을 적어 놓은 아쉬움이 있고 도형 표현식도 좀 더 단순화 가능하다는 것을 뒤늦게 알게 되었습니다. 본 포스트 내용을 갱신하려다가 쉽지 않은 것 같아 아래의 거리 계산 항목에 해당 내용을 추가하고 좀 더 가독성 좋게 별도의 새로운 포스트를 작성했습니다. (2024. 8. 8.)
오랜만에 다시 읽어 보니 내용이 너무 듬성듬성 불친절한 것 같아 과정 설명을 좀 더 보충함. (Last updated: 2023. 08. 23.)
최근에 연습하게 된 도형 간 최근접선 그리기와 거리 구하기.
찾아보면 더 많은 방법이 있는 것 같은데 어려워서 소화해 내지 못한 건 제쳐두고 여러 번 연습해서 나름대로 익숙해진 두 가지 방법을 적어 본다. 두 번째 방법이 좀 더 편하긴 한데, 다양한 방법을 알고 있으면 언젠가 도움이 되겠지. 여기에서는 라인 하나와 포인트 8개를 가지고 작업해 보았다.
- 좌표계 : 평면직각좌표계(TM)
- 라인 1개 - 레이어 이름 : 경계(라인)
- 포인트 8개 - 레이어 이름 : 지점(포인트)

첫 번째 방법
① 선 그리기 : 벡터 도형 > 표현식 기반 도형
- 입력 레이어 : Point 레이어 (지점(포인트))
- 산출 도형 유형 : Line
- 도형 표현식 : shortest_line($geometry,aggregate('경계(라인)','collect',$geometry))


② 거리 계산 : 필드 계산기
*추가한 내용
변경한 도형 레이어에서,
- 새로운 필드 생성 : 체크(V)
- 산출 필드 이름 : 1_distance
- 산출 필드 유형 : 십진수 (실수)
- 표현식(타원체상) : $length
만약, 후술하는 2가지 방법의 계산 결과와 값을 일치시킬 경우 (평면상) 표현식: length(@geometry)
point layer (지점(포인트))를 선택한 상태에서 작업. 포인트에서 (아래 표현식을 이용해) 라인까지 거리 계산을 위함.
- 새로운 필드 생성 : 체크(V)
- 산출 필드 이름 : 1_distance (아래 기술할 두 번째 방법의 결과물과 이름이 겹칠까봐 1_을 붙임)
- 산출 필드 유형 : 십진수 (실수)
- 표현식 : length(shortest_line($geometry,aggregate('경계(라인)','collect',$geometry)))
계산된 거리 정보는 point layer (지점(포인트)) 속성 테이블에서 확인할 수 있다.
*만약 거리 계산이 잘 안 되거나 말도 안 되는 숫자가 나온다면 대부분 경위도 좌표계로 작업한 경우이다. 평면직각좌표계(TM)로 재투영하여 다시 작업하도록 하자.


두 번째 방법
① 최단 지점 위치 및 거리 계산 : 벡터 일반 > 최근접 거리를 이용하여 속성을 결합
- 입력 레이어 : point 레이어 (지점(포인트))
- 입력 레이어 2 : line 레이어 (경계(라인))
- 만약 최장 거리 (옵션) 오른쪽 '미터'라고 뜨는 부분에 느낌표가 뜨면서 경고 표시가 있는 경우 대부분 경위도 좌표계로 작업한 경우이다. 평면직각좌표계(TM)로 재투영하여 다시 작업하도록 하자.
- 새로 생성되는 레이어의 이름을 지정하지 않고 자동으로 만들어지는 임시 레이어로 작업함. 새로 만들어지는 임시 레이어 이름은 결합한 레이어.
새로 생성된 결합한 레이어의 속성 테이블을 확인하면 거리(distance), 지점(포인트)의 좌표(feature_x, feature_y)와 경계(라인)상의 가장 가까운 좌표(nearest_x, nearest_y)가 계산되어 저장되어 있음.


② 선 그리기 : 벡터 도형 > 표현식 기반 도형
앞에서 만든 point 레이어(지점(포인트))의 좌표(feature_x, feature_y)와 line 레이어(경계(라인))상의 가장 가까운 좌표(nearest_x, nearest_y)를 선으로 이어주면 된다.
- 입력 레이어 : 결합한 레이어
- 산출 도형 유형 : Line
- 도형 표현식 : MAKE_LINE($geometry, MAKE_POINT("nearest_x", "nearest_y"))
- 산출물 이름 지정을 하지 않고 작업하여 변경된 도형이라는 임시 레이어로 만들어짐


두 방법의 결과물 비교
당연하겠지만, 두 방법의 결과물은 최단 거리 라인도 동일하고 거리도 동일하다. 좌표 정보가 속성 테이블에 남는지 그렇지 않은지 정도는 다르다.

항만 방파제를 라인으로 그린 후 선박의 위치 포인트와 최단거리를 구해보고 싶은데 상기 방법으로 하니 진행이 잘 안되네요. 혹시 방법이 있을 지 문의드립니다.
말씀 중에는 어떤 과정 부분에서 어떤 에러가 나는지 알 수 없어서 어떤 답변을 드려야 할 지 모르겠습니다. 다만, 지금 다시 동일한 과정으로 작업을 해 보았을 때 문제없이 결과값이 나옵니다.
이런 상황을 유추해 보면 좌표계의 문제일 수 있어 보입니다. 작업 대상이 되는 모든 레이어의 좌표계가 평면직각좌표계(TM)인지 확인해 보시면 좋을 것 같습니다. 만약 좌표계 문제가 아니라면, 잘 되지 않는 부분에 대한 설명을 좀 더 해 주시면 감사하겠습니다.
그리고 포스트의 내용을 다시 보니 저도 이해하기 불편한 것 같아 과정상의 내용을 조금 더 풀어 업데이트 해 두었습니다. 조금이라도 도움이 되시면 좋겠네요.
안녕하세요, 덕분에 최단거리 계산을 해볼 수 있었습니다. 그 밖의 포스팅도 도움이 많이 되었습니다. 다만 제가 아직 표현식 이해도가 낮아서, 조금만 더 도움을 부탁드리고 싶습니다.
예시에서는 라인과 포인트 사이의 최단거리를 구해주셨는데요, 과 사이의 최단거리를 구하고 싶습니다. 혹시 이 경우 표현식을 어떻게 하면 좋을까요?
앞선 댓글의 일부에 제가 괄호를 쳐놨더니 생략되어 보이지가 않네요. ‘기준이 되는 폴리곤의 중심점’과 ‘그 밖의 폴리곤들의 중심점’ 사이의 거리를 구하고 싶습니다. 모쪼록 괜찮으실 때 의견을 부탁드립니다. 감사합니다.
제 글에 도움을 받고 계신다니 다행입니다. 말씀하신 부분은 (1) 폴리곤에서 중심점을 구한 후 거리를 구하는 방법과 (2) (추가 내용) 표현식을 변형한 방법으로 접근 가능한 것 같습니다. 관련해서 포스트(lazytrees.com/4950/)를 작성해 보았으니 참고하시면 될 것 같습니다.
원하는 기능을 찾고 있었는데 딱나와서 너무 좋네요 감사합니다.
도움이 되셨다니 기쁘네요. 댓글 감사합니다!