NG 체계의 그래픽 함수들 중에서 색상을 채우는 기능을 지원하는 것들이 몇개 있습니다. CONTOUR, FILLPLOT, BARPLOT, POLYGON 등의 함수들이 대표적이고 PLOT의 경우도 나름대로의 방식으로 이런 기능을 지원합니다. 사실 "색상을 채운다"는 것은 내부 공간을 동일한 색상으로 빈 공간 없이 꽉 채워서 칠한다는 의미로 보면 됩니다. 먼저 이러한 예제로서 다음과 같이 POLYGON 함수를 이용하여 간단한 그림을 하나 표출해보겠습니다.
win = WINDOW(DIMENSIONS=[600, 600], /NO_TOOLBAR)
xp = [0.1, 0.1, 0.9, 0.9, 0.1]
yp = [0.1, 0.9, 0.9, 0.1, 0.1]
plg = POLYGON(xp, yp, FILL_COLOR='green', /NORMAL)
결과로 표출되는 그림은 다음과 같습니다. 이와 같이 사각형의 내부가 초록색으로 채워지게 됩니다.
그래서 "색상을 채운다"는 것은 통상적으로는 이러한 의미라고 볼 수 있습니다. 그런데 색상을 채우는데 있어서는 또 다른 방식도 있는데요. 바로 패턴(Pattern)이라는 것을 사용하는 방식입니다. 예를 들면 비스듬한 빗금들로 구성된 모습의 패턴을 폴리곤 내부에 채우는 것입니다. 실제로 POLYGON 함수에서 지원되는 속성들 중에는 'PATTERN_'으로 시작하는 이름의 것들이 몇가지 있는데, 이 속성들이 빗금 패턴으로 채우는 기능과 관련된 것들입니다. 위의 예제 코드에서 POLYGON 함수가 사용되었던 부분을 다음과 같은 내용으로 바꿔봅시다.
plg = POLYGON(xp, yp, FILL_COLOR='green', $
PATTERN_ORIENTATION=45, PATTERN_SPACING=5, $
/NORMAL)
이렇게 패턴과 관련된 속성들 몇가지를 사용하여 표출된 그림은 다음과 같습니다.
여기서 사용된 속성들을 보면 PATTERN_ORIENTATION은 빗금의 경사각도, PATTERN_SPACING은 빗금 사이사이의 간격을 조정하는 역할을 합니다. 이번에는 위의 내용 대신 다음과 같이 해봅시다.
plg = POLYGON(xp, yp, FILL_COLOR='green', $
PATTERN_ORIENTATION=45, PATTERN_SPACING=10, $
PATTERN_THICK=2, /NORMAL)
여기서는 PATTERN_THICK이라는 속성을 사용하여 빗금 선 자체의 두께를 조정했고 그러면서 빗금 사이의 간격을 더 넓혔습니다. 그 결과는 다음 그림과 같습니다.
이와 같이 POLYGON 함수에서 지원되는 PATTERN 관련 속성들을 사용하면 내부를 색상으로 채우는데 있어서 빗금 모양의 패턴을 사용할 수 있습니다. 이와 같이 빗금 모양의 패턴을 채우고 설정하는 기능과 관련된 속성들은 사실 POLYGON 함수 뿐 아니라 다른 몇몇 그래픽 함수들에서도 지원되는데요. 해당되는 그래픽 함수들은 다음과 같습니다.
BARPLOT, ELLIPSE, FILLPLOT, POLYGON
그래도 이러한 기능이 꼭 필요한 함수들에서 지원되고 있다고 볼 수는 있지만 그 갯수 자체는 그리 많은 것은 아닙니다. 물론 패턴의 형태가 아니라 그냥 단순히 색상을 꽉 채우는 방식을 지원하는 그래픽 함수들은 더 많습니다. 위의 것들은 당연히 포함이고 그 외에도 BOXPLOT, CONTOUR, PLOT 등의 함수들도 이렇게 단순히 색상을 꽉 채우는 방식의 기능을 지원합니다.
BARPLOT, ELLIPSE, FILLPLOT, POLYGON, BOXPLOT, CONTOUR, PLOT
그런데 앞서 언급한 PATTERN 관련 속성들을 사용할 경우 실제로 사용 가능한 패턴의 종류는 빗금 형태 하나로 한정되어 있습니다. 그런데 만약 빗금이 아닌 또 다른 형태의 패턴을 사용하고 싶다면 어떻게 해야할까요? 사실 'PATTERN_~~' 속성들만으로는 불가능합니다. 물론 그렇다고 해서 아예 불가능한 것은 아닙니다. 그 비법은 바로 PATTERN_BITMAP이라는 속성을 사용하는 것입니다. 다만 이 속성을 제대로 사용하려면 전제조건이 하나 붙는데, 바로 패턴 자체를 유저가 직접 만들어주는 과정이 선행되어야 합니다. 이 부분이 다소 번거로울 수는 있지만 내가 원하는 커스텀 패턴을 넣으려면 필연적으로 거쳐야 하는 과정입니다. 그래서 그 방법을 한번 차근차근 소개해보도록 하겠습니다.
먼저 커스텀 패턴을 정의해야 하는데, 구체적으로는 32x32의 구조를 갖는 2차원 바이트형 배열로 정의되어야 합니다. 예를 들어서 다음과 같은 방식입니다.
arr = BYTARR(32, 32)
arr[15, 15] = 255
이렇게 하면 32x32의 구조를 갖는 바이트형 배열 내에서 모든 값들은 0인데 가운데 쯤에 위치한 하나의 픽셀만 그 값이 255가 됩니다. 실제로 이 패턴의 모습은 다음 그림과 같습니다. 마치 빈 공간의 가운데에 점 하나만 달랑 있는 것 같은 모습입니다.
이렇게 하면 점 하나로만 구성된 패턴이 만들어집니다. 이제 이렇게 생성된 배열 arr에 대하여 한 단계만 더 거치면 되는데, 여기서 다음과 같이 CVTTOBM이라는 함수를 사용해야 합니다.
arr_pat = CVTTOBM(arr)
여기서 사용된 CVTTOBM 함수의 역할은 IDL 도움말을 보면 다음과 같이 설명되어 있는데요.
The CVTTOBM function converts a byte array in which each byte represents one pixel into a “bitmap byte array” in which each bit represents one pixel.
사실 저도 정확히 이해하지는 못하고 있어서 더 자세히 설명드리긴 힘들 것 같습니다. 그냥 위와 같이 사용해야 한다는 정도로만 언급하고 넘어가겠습니다. 뭐 어쨌든 이제는 이와 같이 얻은 arr_pat를 PATTERN_BITMAP 속성에 부여하는 방식으로 작업을 하면 되는데, 그 내용은 다음과 같습니다. 그리고 앞에서는 색상이 green이었는데 이번에는 crimson으로 바꿔보았습니다.
plg = POLYGON(xp, yp, FILL_COLOR='crimson', $
PATTERN_BITMAP=arr_pat, /NORMAL)
앞서 POLYGON 함수가 사용되었던 부분을 이 내용으로 대체하면 됩니다. 결과는 다음 그림과 같습니다.
얼핏 보면 잘 안보일 수도 있으나 자세히 보면 점들로 구성된 패턴이 사각형의 내부를 채우고 있는 것을 알 수 있습니다. 그래도 점이 너무 작아서 잘 보이지는 않습니다. 그럴 수 밖에 없는 것이 이 패턴에서는 픽셀 하나가 점 하나이기 때문입니다. 그러면 점의 크기를 더 키워봅시다. 그러려면 패턴 배열 생성 과정을 좀 바꿔주면 됩니다. 즉 배열 arr을 생성하는 부분을 다음과 같은 내용으로 바꿔봅시다.
arr[14:17, 14:17] = 255
이렇게 하면 패턴 자체는 다음 그림과 같이 가운데 부분의 점이 좀 더 커진 형태가 됩니다.
그리고 이 상태로 나머지 POLYGON 함수가 사용되는 과정을 그대로 다시 실행해보면 표출되는 그림은 다음과 같습니다.
그러면 아까보다는 점들도 더 커졌고 색상도 식별이 잘 되는 것을 볼 수 있습니다. 결국 32x32의 패턴 배열을 어떻게 만드느냐에 따라서 사용자가 원하는 어떤 패턴으로든 채울 수 있게 됩니다. 즉 패턴 배열 arr을 만드는 부분만 사용자의 목적에 맞게 바꾸면 됩니다. 만약 점들이 더 촘촘하게 찍히는 패턴을 사용하고자 한다면 어떻게 하면 될까요? 이런 경우에는 배열 arr을 다음과 같은 방식으로 만드는 방법도 있습니다.
FOR j = 0, 3 DO BEGIN
FOR i = 0, 3 DO BEGIN
arr[i*8:i*8+2, j*8:j*8+2] = 255
ENDFOR
ENDFOR
이 경우에는 패턴 자체는 다음 그림과 같아집니다.
그리고 이 패턴을 사용하여 표출해보면 결과는 다음 그림과 같습니다.
아마 이 정도면 패턴을 직접 만들어서 그림에 반영하는 방식에 대해서는 설명이 되었을 것 같습니다. 그러면 이와 같이 커스텀 패턴을 사용할 수 있도록 해주는 PATTERN_BITMAP 속성은 어떤 그래픽 함수들에서 사용이 가능할까요? 당연히 앞서 소개했던대로 'PATTERN_~' 속성을 지원하는 4종의 그래픽 함수들(BARPLOT, ELLIPSE, FILLPLOT, POLYGON)이 여기에 해당됩니다. 그런데 실제로는 하나 더 있는데, 바로 CONTOUR 함수입니다. 다만 CONTOUR 함수에서는 해당 속성의 이름이나 적용 방식이 약간 다릅니다(PATTERN_BITMAP이 아님). 즉 CONTOUR 함수에서 지원되는 C_FILL_PATTERN이란 속성이 그 역할을 합니다. 어쨌든 이러한 속성을 사용하면, 색상을 채운 등위선(Filled Contour)을 표출하는데 있어서 패턴이 채워지도록 하는 것이 가능합니다. 예제 코드를 한꺼번에 적으면 다음과 같습니다. 바로 앞서 생성했던 촘촘한 점들로 구성된 패턴이 적용되도록 하였습니다.
data = HANNING(400, 400)*100
add = FLTARR(400, 400)
add[240, 40] = HANNING(150, 150)*50
data = data + add
win = WINDOW(DIMENSIONS=[600, 600], /NO_TOOLBAR)
arr = BYTARR(32, 32)
FOR j = 0, 3 DO BEGIN
FOR i = 0, 3 DO BEGIN
arr[i*8:i*8+2, j*8:j*8+2] = 255
ENDFOR
ENDFOR
arr_pat = CVTTOBM(arr)
oPat = OBJ_NEW('IDLgrPattern', PATTERN=arr_pat, STYLE=2)
cn = CONTOUR(data, /FILL, RGB_TABLE=34, C_FILL_PATTERN=oPat, $
MARGIN=0.1, /CURRENT)
cno = CONTOUR(data, COLOR='black', C_THICK=2, /OVERPLOT)
전반적인 과정은 앞서 설명한 내용과 전반적으로 거의 유사합니다. 다만 여기서는 단 한가지 차이점이 있는데요. 바로 IDLgrPattern 클래스의 객체가 사용된 것입니다. 바로 볼드체로 표시한 라인에서 생성한 oPat입니다. 이렇게 하는 이유는 C_FILL_PATTERN 속성이 받을 수 있는 값의 형태가 이렇게 패턴 클래스의 객체여야만 하기 때문입니다. 문법 자체가 그렇기 때문에 어쩔 수 없습니다. 어쨌든 이와 같이 처리하여 얻게 되는 최종 결과물은 다음 그림과 같습니다.
색상을 꽉 채운 등위선 그림은 아마 많이들 보셨겠지만 이러한 형태는 약간 생소할 수도 있을 것 같습니다. 어쨌든 패턴을 나름대로 구성하여 그 패턴으로 '색상을 채워서' 표출하는 것이 이와 같은 방식으로 가능하다는 점을 참고해두시면 좋을 것 같습니다. 물론 이를 위해서는 패턴 자체를 유저가 직접 설계하고 구성하는 것이 필요한데, 약간 귀찮을 수도 있지만 그 대신 수많은 다양한 종류의 패턴들을 사용할 수 있게 된다는 장점도 분명 있을 것입니다.
그리고 위의 그림을 파일로 저장할 때 유의해야 할 점이 있는데, Save 메서드를 사용할 때 ANTIALIAS 속성도 추가로 사용하면서 이 속성의 값을 0으로 설정하는 것이 필요합니다. 즉 예를 들어 PNG 형식의 파일로 저장할 경우 다음과 같이 처리하는 것이 바람직합니다.
win.Save, 'result.png', WIDTH=600, ANTIALIAS=0
사실 통상적으로는 Save 메서드를 사용할 때 ANTIALIAS 속성을 사용할 일이 흔하지는 않은데, 이와 같이 패턴이 포함된 그래픽 결과물을 저장할 경우에는 필요한 것 같습니다. 이 점만 유의하시기 바랍니다.
'IDL > New Graphics' 카테고리의 다른 글
BUBBLEPLOT 함수 소개 (0) | 2020.12.09 |
---|---|
축의 눈금(Tick)에 대한 조정(커스터마이즈) 방법 (2) | 2020.10.21 |
색상을 채운 플롯(Filled Plot)의 표출 [2] (0) | 2020.10.07 |
에러바(Error Bar)의 표출 [2] (0) | 2020.08.05 |
등위선(Contour)의 표출에서 라벨 문자들의 세부 설정 (0) | 2020.05.07 |