오늘은 IDL에서 서피스(Surface)의 형태로 가시화를 할 때 시선방향을 조정하는 방법에 관하여 알아보고자 합니다. 서피스는 XYZ축이 공존하는 3차원적인 표출 방식인데, 이렇게 표출된 서피스 개체는 시선 방향에 따라 다르게 보일 수 밖에 없습니다. 물론 우리가 흔히 보게 되는 디폴트 시선 방향이 있긴 하지만, 이러한 시선 방향 외에 다른 시선 방향으로도 표출하려면 어떻게 하면 되는가에 관하여 알아보고자 합니다. 그러면 NG 체계의 SURFACE 함수를 사용하여 표출하는 예제를 통하여 구체적인 내용을 살펴보기로 하겠습니다. 먼저 예제 데이터를다음과 같이 먼저 생성합니다. 참고로 이 예제 데이터는 제가 지난번 머신러닝 관련 게시물에서 사용했던 것과 동일한 데이터입니다.
HELP에 의하여 출력된 내용에서 볼 수 있듯이 이 데이터(zz)는 100x100의 구조를 갖는 2차원 배열입니다. 그리고 X축 및 Y축 방향 격자점배열인 xx, yy도 함께 생성하였습니다. 먼저 SURFACE 함수를 이용하여 기본적인 방식으로 표출해 봅시다.
sz = 100
x = FINDGEN(sz)/(sz-1)*4-2
y = FLTARR(sz)+1.0
xx = x#y
yy = TRANSPOSE(xx)
zz = 2.0/(EXP((xx-0.5)^2+yy^2))-2.0/(EXP((xx+0.5)^2+yy^2))
win = WINDOW(DIMENSIONS=[600, 500], /NO_TOOLBAR)
surf = SURFACE(zz, xx, yy, ZRANGE=[-2, 2], $
TEXTURE_IMAGE=BYTSCL(zz), RGB_TABLE=34, /CURRENT)
여기서는 서피스의 표면을 단일 색상으로 처리하지 않고, 컬러테이블이 적용된 이미지를 입혔습니다. 이러한 처리는 TEXTURE_IMAGE라는 속성을 이용하면 가능합니다. 표출된 그림은 다음과 같습니다.
이것이 바로 서피스 형태로 표출된 그림의 전형적인 모습입니다. 아마 많이들 보셨을 것입니다. 그런데 이 그림을 잘 보면 마치 약간 위에서 비스듬히 내려다보는 느낌의 시선 방향으로 처리되어 있음을 알 수 있습니다. IDL에서는 이러한 시선 방향이 서피스 형태의 표출에 있어서 디폴트 설정입니다. 3차원적인 그래픽 개체를 평면상에서 그나마 가장 잘 보여주는데 있어서 이러한 시선 방향이 가장 무난하다고 판단했나 봅니다. 사실 이 정도가 가장 무난한 시선 방향이라는 것은 충분히 이해가 갑니다.
다만 데이터의 특성에 따라서는 다른 시선 방향으로 보는 것이 필요할 수도 있습니다. 그러기 위해서는 어떻게 해야 할까요? 사실 가장 간단한 방법은 표출된 그래픽창 내에서 서피스 그림 개체를 마우스 왼쪽 버튼으로 클릭한 상태로 드래그하여 돌려보는 것입니다. 서피스 그림상에서 마우스 왼쪽 버튼을 한번 클릭하여 개체가 선택된 상태로 들어가면 마우스 포인터가 둥근 화살표가 되는데, 이 때 왼쪽 버튼을 클릭한 상태로 드래그를 하면 됩니다. 이렇게 하면 자유자재로 시선 방향을 돌려가며 볼 수 있습니다. 그런데 이렇게 마우스로 직접 드래그하는 방식 말고, 아예 처음에 표출될 때 시선 방향이 디폴트가 아닌 내가 원하는 방향이 되도록 하고 싶을 경우도 있습니다. 만약 이렇게 하고자 한다면 위의 예제코드에서 약간의 내용이 더 추가되어야 합니다. 이를 위해서는 SURFACE 함수의 Rotate 메서드를 사용하면 됩니다. 일단 다음과 같은 명령을 추가적으로 실행해 봅시다.
surf.Rotate, 30, /ZAXIS
이 내용은 Rotate 메서드를 사용하는 예제로서, Z축을 중심으로 30도 회전시키라는 의미입니다. 그런데 어느 방향으로 회전시키냐는 오른손 법칙을 따릅니다. 즉 축의 화살표 방향이 오른손 엄지손가락 방향이라고 할 때, 나머지 손가락들이 향하는 방향이 바로 회전하는 방향이 됩니다. 회전 각도가 (+)이면 정방향이고 (-)이면 역방향입니다. 그래서 이와 같이 회전을 시키면 다음과 같이 표출됩니다.
그런데 이 그림을 보면 분명히 시선 방향이 달라진 것은 느껴진 것 같긴 한데, 아주 느낌이 확 오지는 않을 수도 있습니다. 그래서 위와 같이 한번에 많은 각도를 회전시키는 대신, 다음과 같이 반복형 구문을 사용하여 30회에 걸처 1도씩 야금야금 회전시켜보면 좀 더 느낌이 올 것 같습니다.
FOR j = 0, 29 DO surf.Rotate, 1, /ZAXIS
그리고 같은 요령으로 다음과 같이 X축이나 Y축을 중심으로 회전시키면, 다른 축들에 대해서는 어떤 방식으로 회전이 되는지 이해하기가 훨씬 쉽습니다.바로 위 내용에서 키워드만 /ZAXIS 대신 /XAXIS 또는 /YAXIS를 사용하면 됩니다. 실제로 이렇게 회전을 시켜보면 X축 중심의 회전은 X축 방향은 고정된 채 그 축을 중심으로 회전이 이루어진다는 것을 알 수 있습니다. Y축 중심의 회전도 같은 방식입니다.
FOR j = 0, 29 DO surf.Rotate, 1, /XAXIS
그래서 이렇게 해보면 특정한 축을 중심으로 어떤 방식으로 회전이 되는가에 대해서 그 과정을 명확히 이해할 수 있습니다. 그런데 우리가 서피스 그림을 그냥 디폴트로 표출할 때 보게 되는 시선 방향도 실제로는 나름의 회전들이 이미 적용되어 있는 상태입니다. 사실 서피스 형태의 표출이 3차원 공간상에서 구현될 때에 원래는 회전 처리가 전혀 되지 않은 원시적인(?) 상태가 존재합니다. 이러한 상태를 보려면 다음과 같이 Rotate 메서드에서 /RESET 키워드를 사용하면 됩니다.
surf.Rotate, /RESET
이렇게 시선 방향을 완전히 리셋한 상태로 표출된 그림은 다음과 같습니다.
보시는 것처럼 X축은 오른쪽 그리고 Y축은 위쪽을 향한 상태로 완전히 위에서 수직으로 내려다보는 형태입니다. 즉 시선은 Z축의 (+) 방향 어딘가에 존재하는 경우라고 보면 됩니다. 이렇게 시선 방향이 완전히 리셋된 상태에서 각 축을 중심으로 회전을 시켜봐도 그 원리를 이해하는데 도움이 됩니다. 이 상태에서 우리가 처음에 했던 것처럼 Z축을 중심으로 30도 회전을 시켜보면 그 모습은 다음과 같습니다.
surf.Rotate, 30, /ZAXIS
물론 X축이나 Y축을 중심으로도 아까와 유사한 요령으로 다양하게 테스트해볼 수 있습니다. 여러분들도 여러가지 방법으로 해보시기 바랍니다. 그런데 여기서 다음과 같이 시선 방향을 한번 리셋한 다음 몇가지 추가적인 회전들을 적용해 봅시다.
surf.Rotate, /RESET
surf.Rotate, 30, /XAXIS
surf.Rotate, 30, /YAXIS
surf.Rotate, -90, /XAXIS
그 결과는 다음 그림과 같습니다. 그런데 어디서 많이 보던 모습같지 않습니까?
그렇습니다. 우리가 서피스 그림을 그릴 때 항상 보는 시선 방향입니다. 그래서 이 디폴트 시선 방향이 사실은 위와 같이 완전히 리셋된 상태에서 X축을 중심으로 30도, Y축을 중심으로 30도, Z축을 중심으로 -90도의 회전들이 결합된 형태입니다. 이러한 사실도 알아두면 분명 도움이 될 것입니다. 그래서 이 정도의 내용들만 잘 이해하면 서피스 형태의 표출에 있어서 시선 방향을 여러분이 원하는 방식으로 처리하는 것도 충분히 가능하리라 생각됩니다. 여기서 한가지 예제만 더 살펴보겠습니다. 먼저 다음 그림을 봅시다.
이 그림을 얼핏 보면 디폴트 시선 방향과 비슷하게 느껴질 수도 있지만 사실은 시점이 디폴트보다 좀 더 내려가 있는 상태입니다. 그래서 디폴트 시선 방향에서는 보이지 않던 Z축 (-) 방향의 골짜기 부분이 여기서는 잘 보입니다. 이와 같이 디폴트 시선 방향과 비슷하되 시점만 내려서(또는 올려서) 봐야 할 경우도 있습니다. 이렇게 하려면 회전을 어떤 식으로 처리해야 할까요? 사실 그 방법이 금방 떠오르지는 않습니다. 왜냐하면 Z축이 수직 방향으로 유지된 채 시점만 내리려면, X축 및 Y축 기준의 회전 방향이나 각도 등이 약간 미묘해지기 때문입니다. 그래서 여기서 그냥 정답(사실은 정답에 매우 가까운 답)을 바로 드리면 다음과 같습니다.
surf.Rotate, -1.75*6, /XAXIS
surf.Rotate, 1.0*6, /YAXIS
이와 같이 X축 및 Y축 기준의 회전을 처리하면 됩니다. 각도의 부호 및 서로간의 비율만 이와 같이 맞춰주면, Z축이 수직인 상태로 시점만 내리거나 올리는 것이 가능합니다. 만약 시점을 오히려 올리려면 다음과 같이 하면 됩니다.
surf.Rotate, 1.75*6, /XAXIS
surf.Rotate, -1.0*6, /YAXIS
그러면 다음과 같은 그림을 얻을 수 있습니다.
그리고 다음과 같이 반복문을 사용하여 야금야금 회전을 시켜보면, 위 방법이 과연 괜찮은 것인지에 대해서 확인해보는 것도 가능할 것 같습니다. 혹시라도 Z축 방향이 깔끔하게 직선이 나오지 않는 경우가 있다면, 각도 배율을 미세하게 조정하는 것이 필요할지도 모르겠습니다.
FOR j = 0, 30 DO BEGIN
surf.Rotate, -1.75, /XAXIS
surf.Rotate, 1.0, /YAXIS
ENDFOR
어쨌든 이러한 팁도 알아두시면 좋을 것 같습니다. 앞서 언급했던 것처럼 서피스 형태의 표출은 XYZ축으로 이루어진 3차원 공간상에 구현된 입체적인 폴리곤을 평면상의 그림으로 보여주는 형태이기 때문에, 데이터의 형태에 따라서는 시선 방향을 디폴트와 다르게 처리해야 할 경우도 있습니다. 그러한 처리에 있어서 이 내용을 참조해두시면 될 것 같습니다. 그리고 이 요령은 PLOT3D, SCATTERPLOT3D 등과 같은 3차원 기반의 다른 표출 기능에서도 동일한 방식으로 적용이 가능하다는 점도 참조해두시기 바랍니다.
'IDL > New Graphics' 카테고리의 다른 글
NG 체계에서 서피스(Surface)와 타 그래픽 요소의 중첩 표출 [2] (2) | 2018.12.21 |
---|---|
NG 체계에서 서피스(Surface)와 타 그래픽 요소의 중첩 표출 [1] (0) | 2018.12.10 |
NG 체계에서도 POLAR_CONTOUR를? (0) | 2018.09.03 |
SCATTERPLOT 함수를 이용하여 격자점 표시하기 (0) | 2018.05.18 |
2차원 데이터 표출시 축(axis)에 대한 로그 스케일(log scale) 적용 방법 (0) | 2018.03.19 |