IDL/Programming

격자점들의 다각형 내부/외부 판별 (Grids inside Polygon) (Part 1)

이상우_idl 2019. 10. 28. 17:45
728x90
반응형

XY 평면상에 특정한 다각형(Polygon)이 정의되어 있을 때, 어떤 한 점(Point)이 그 다각형의 내부 또는 외부에 존재하는지 여부를 판별하는방법에 관하여 소개하는 게시물을 얼마 전에 올린 바 있습니다. 오늘은 개념을 좀 더 확대하여, 한 점이 아닌 격자점들에 대한 경우를 생각해보기로 하겠습니다. 즉, XY 평면상에 X 및 Y 방향으로 일정 간격의 격자점들이 정의되어 있고, 동시에 특정한 다각형이 함께 정의되어 있는 상태를 가정하는 것입니다. 이 상태에서 다각형의 내부에 속하는 격자점들을 판별하는 작업이라고 보면 됩니다. 문제에 대한 이해들 돕기 위하여 다음과 같은 그림을 보면서 설명을 하는 것이 좋을 것 같습니다.



이와 같이 2차원 격자 데이터가 있고 원형의 다각형이 함께 존재하는 상태에서 원형 안에 속하는 격자점들을 한꺼번에 판별하는 작업입니다. 사실 원론적으로 본다면, 지난번 게시물에서 소개했던 내용과 근본적으로는 다르지 않습니다. 다만 그러한 작업을 모든 격자점들에 대하여 일일이 해줘야 한다는 것인데, 반복형 구문을 사용한다면 충분히 가능하긴 하지만 귀찮은 작업이 될 수도 있습니다. 그리고 이와 같이 격자점들에 대하여 한꺼번에 판별을 하는 작업에 있어서는 효율적인 방법들이 따로 존재합니다. 그렇기 때문에 이 방법들에 관하여 소개를 하고자 합니다. 두가지 방법이 있는데, 하나는 POLYFILLV 함수를 사용하는 방법이고 또 하나는 IDLanROI 객체를 사용하는 방법입니다. 두 방법을 모두 소개하려고 하는데, 사실 두 방법에 의한 결과가 서로 조금 다릅니다. 어떻게 다른지 그리고 어떤 방법이 더 좋을 것인지에 대해서는 뒤에 가서 다시 살펴보겠습니다.


그러면 먼저 예제 데이터의 생성 및 표출 작업부터 시작합니다. 앞서 제시된 그림을 표출하기 위한 내용이라고 보면 됩니다. 이 과정은 다음과 같습니다. 일단 가상의 2차원 격자 데이터를 다음과 같이 생성합니다.


dxsz = 50

dysz = 50

img = HANNING(dxsz, dysz)*10


여기서는 50x50의 격자 형태를 갖는 2차원 데이터를 HANNING 함수를 사용하여 생성하였습니다. 그리고 X축 및 Y축 방향 격자 크기에 해당되는 dxsz, dysz 변수들을 정의하여 활용하였습니다. 적절한 크기의 그래픽 창을 띄우고 이 2차원 데이터를 이미지의 형태로 표출하는 내용은 다음과 같습니다.


xrn = [0, dxsz]

yrn = [0, dysz]

win = WINDOW(DIMENSIONS=[600, 600], /NO_TOOLBAR)

im = IMAGE(img, XRANGE=xrn, YRANGE=yrn, RGB_TABLE=67, AXIS_STYLE=2, $

  MARGIN=0.1, /CURRENT)


여기서는 IMAGE 함수를 사용하여 격자 데이터를 이미지의 형태로 표출하였습니다. 이 때 AXIS_STYLE 키워드의 값을 2로 설정함으로써 이미지의 표출임에도 X, Y축이 함께 표시되도록 하였습니다. 그리고 격자 데이터의 배열 크기 자체는 50x50으로 매우 작지만 표출을 할 때 MARGIN 속성을 0.1로 설정하여 상하좌우 여백을 정의하면 격자들의 형태가 눈에 보이게끔 충분히 크게 표출할 수 있습니다. 이 상태로 표출된 결과는 다음 그림과 같습니다. 물론 아직은 원형 다각형은 정의되지 않은 상태입니다.



그러면 이제 이 XY 공간상에 존재하는 원형의 다각형을 정의하여 표출하겠습니다. 이 과정은 다음과 같이 처리하였습니다.


theta = [0:360:10.]

xpts = COS(theta*!dtor)*15+19

ypts = SIN(theta*!dtor)*15+28

plg = POLYGON(xpts, ypts, COLOR='blue', FILL_BACKGROUND=0, THICK=2, /DATA)


여기서는 원형 다각형을 구성하는 꼭지점들(Vertices)을 정의하였습니다. 총 37개의 꼭지점들이 정의되었고, 각 점의 X 좌표값들을 xpts 배열에 그리고 Y 좌표값들을 ypts 배열에 담았습니다. 앞서 정의했던 2차원 격자 데이터는 배열 구조가 50x50이었는데, 이러한 데이터가 존재하는 영역은 X축 방향으로 0~50 그리고 Y축 방향으로 0~50의 범위를 갖는다고 볼 수 있습니다. 그리고 방금 정의한 원형 다각형은 중심점 좌표가 (19, 28)이고 반경은 15가 되도록 한 것입니다. 이 다각형을 POLYGON 함수를 사용하여 동일한 XY 공간상에 표출하면 됩니다. 그 결과는 다음 그림과 같습니다. 앞서 맨 처음에 제시되었던 그림과 동일합니다.



이제 이 상태에서 원형 다각형의 내부에 속하는 격자점들을 판별해 봅시다. 먼저 첫번째 방법인 POLYFILLV 함수를 사용하는 방법부터 보겠습니다. POLYFILLV 함수는 IDL의 내장함수로서 그 역할은 IDL 도움말에서 찾아보면 다음과 같이 제시되어 있습니다.


The POLYFILLV function returns a vector containing the subscripts of the array elements contained inside a polygon defined by vectors.


즉 어떤 다각형의 내부에 속하는 점들의 배열 인덱스 값들을 전달해주는 역할을 합니다. 그리고 사용 문법은 다음과 같습니다.


Result = POLYFILLVX, Y, Sx, Sy[, Run_Length] )


첫번째 및 두번째 인수는 다각형을 구성하는 꼭지점들의 X 좌표값 배열 및 Y 좌표값 배열입니다. 우리의 예제에서는 xpts, ypts가 됩니다. 그리고 세번째 및 네번째 인수는 X 및 Y 방향 격자 갯수로서 우리의 예제에서는 dxsz, dysz가 됩니다. 따라서 다음과 같이 사용하여 결과를 바로 얻을 수 있습니다.


result = POLYFILLV(xpts, ypts, dxsz, dysz)

HELP, result


여기서 결과로 얻은 result에 대하여 HELP 명령으로 출력된 정보는 다음과 같습니다.


RESULT          LONG      = Array[711]


즉 판별된 격자점들의 갯수는 711개라는 것이고, result는 이 711개의 점들에 대한 배열 인덱스 값들이 됩니다. 하지만 이 결과만으로는 판별된 격자점들이 어디 있는지를 시각적으로 확인할 수는 없습니다. 따라서 다음과 같이 원본 2차원 데이터와 동일한 배열 구조를 갖는 mask라는 배열을 따로 정의하여 처리해주는 것이 좋습니다.


mask = INTARR(dxsz, dysz)

mask[result] = 1


이렇게 하면 mask 배열은 처음에는 모든 배열값들이 0으로 통일된 상태로 정의되지만, 이와 같은 처리를 거침으로써 다각형 내에 있는 것으로 판별된 격자들에 대해서만 값이 1로 대체됩니다. 마치 이미지에 대하여 마스킹(Masking) 처리를 한 것과 유사한 느낌의 결과 데이터를얻는 것입니다. 이렇게 얻어진 mask 배열을 별도의 그래픽창에서 다음과 같이 표출해 봅시다.


win_mask = WINDOW(DIMENSIONS=[600, 600], /NO_TOOLBAR)

im_mask = IMAGE(mask, XRANGE=xrn, YRANGE=yrn, RGB_TABLE=0, AXIS_STYLE=2, $

  MARGIN=0.1, /CURRENT)


표출 방식 자체는 앞서 원본 2차원 데이터인 img를 표출했던 과정과 유사합니다. 하지만 그 결과는 다음 그림과 같습니다.



여기서 흰색 부분이 바로 다각형 내부에 있는 것으로 판별된 격자점들에 해당됩니다. 따라서 POLYFILLV 함수를 사용하여 다각형 내부의 격자점들을 판별하는 작업이 잘 진행되었음을 알 수 있습니다. 그리고 다음과 같이 POLYGON 함수를 사용하여 원형 다각형의 윤곽선을 중첩하여 표출하면, 다각형 내 격자점들이 어떤 식으로 판별되었는지 더 자세히 확인해볼 수 있습니다.


plg = POLYGON(xpts, ypts, COLOR='crimson', FILL_BACKGROUND=0, THICK=2, /DATA)


이렇게 판별 결과와 다각형을 함께 중첩 표출해 본 결과는 다음 그림과 같습니다.



이 그림을 보면 판별의 결과는 그럭저럭 잘 나온 것 같은데, 다각형의 경계선 부근에서는 약간 애매하게 판별된 듯한 모습들도 좀 보입니다. 이것은 POLYFILLV 함수에서 다각형 내 격자점들을 판별하는데 사용된 알고리즘의 특성에 의한 것이라고 보면 됩니다. 이 알고리즘에 관해서는 IDL 도움말에서 POLYFILLV 함수에 관한 내용에서 확인할 수 있으므로 그 내용을 직접 확인해보시기 바랍니다.


그리고 다음과 같이 원본 2차원 데이터인 img를 이미지의 형태로 먼저 표출해놓은 상태에서, 판별 결과 데이터인 mask를 반투명으로 중첩한 다음, 원형 다각형을 이어서 중첩하는 과정을 거쳐서 표출되도록 할 수도 있습니다.


win = WINDOW(DIMENSIONS=[600, 600], /NO_TOOLBAR)

im0 = IMAGE(img, XRANGE=xrn, YRANGE=yrn, RGB_TABLE=67, AXIS_STYLE=2, $

  MARGIN=0.1, /CURRENT)

im = IMAGE(mask, RGB_TABLE=0, TRANSPARENCY=50, /OVERPLOT)

plg = POLYGON(xpts, ypts, COLOR='blue', FILL_BACKGROUND=0, /DATA)

tx = TEXT(0.5, 0.92, 'Masked with POLYFILLV', FONT_SIZE=16, $

  ALIGNMENT=0.5, /NORMAL)


이렇게 하면 다음과 같은 그림을 얻게 됩니다.



이와 같은 방식으로 표출을 하면 원본 데이터의 모습도 함께 보이도록 하면서도 다각형 내부에 속하는 격자점들만 강조되는 효과를 볼 수 있습니다. 지금까지 POLYFILLV 함수를 사용하여 다각형 내부의 격자점들을 판별하고 그 결과를 표출하는 작업을 진행해 보았습니다. 오늘은 여기까지 하고, 다음 회차에서는 IDLanROI 객체를 활용하여 유사한 작업을 진행해보고 오늘 얻은 결과와 비교도 함께 해보도록 하겠습니다.

반응형