IDL/Object Graphics

Object Graphics in IDL [23]

이상우_idl 2011. 1. 31. 15:06
728x90
반응형

 이제 좀 더 본격적인 예제에 한번 도전해보자. 이 예제에서는 이미지 객체를 만들고 이를 그래픽 윈도우상에서 가운데에 위치하도록 해주는 두 가지 방법을 제시하고 있다. 첫번째 방법에서는 먼저 뷰 객체내에 뷰플레인 사각형을 설정한다. 그리고 이미지 객체를 만들어 모델 객체에 포함시키고, 이 모델 객체를  윈도우 객체의 중심으로 이동시킨다. 두번째 방법에서는 뷰플레인 사각형을 만들지 않는다. 그 대신 좌표변환을 이미지 객체에 적용하여 모델 객체내에서 가운데에 위치하도록 하는데, 이 방법은 모델 객체의 normal 좌표계에서 이루어지게 된다. 이번 예제에서 사용되는 이미지 자료는 IDL이 설치된 폴더내에서 examples/data라는 하위폴더안에 있는 worldely.dat 파일이다.


먼저 이미지 자료파일의 이름 및 경로에 대한 문자열을 설정한다.

worldelvFile = FILEPATH('worldelv.dat', $

  SUBDIRECTORY = ['examples', 'data'])

파일로부터 읽어들일 이미지 배열과 관련된 인자들을 설정한다. 

worldelvSize = [360, 360]

worldelvImage = BYTARR(worldelvSize[0], worldelvSize[1])

파일을 열고 자료파일의 내용을 읽은 다음 파일을 닫는다. 

OPENR, unit, worldelvFile, /GET_LUN

READU, unit, worldelvImage

FREE_LUN, unit

표출할 윈도우와 관련된 인자들을 설정한다. 윈도우의 크기는 [400, 400]이고 이미지의 크기는 [360, 360]이므로, 이미지가 윈도우의 가운데 표출되려면 상하좌우로 남겨야할 여백의 크기를 winMargin이란 변수에 저장함에 유의한다. 

winSize = [400, 400]

winMargin = (winSize - worldelvSize) / 2

이제 우선 첫번째 방법부터 수행해보도록 하자. 이를 위하여 윈도우, 뷰, 모델 등 기본적으로 필요한 그래픽 객체들을 먼저 선언한다. 여기서 뷰 객체의 VIEWPLANE_RECT 속성에 부여된 값을 보면, 윈도우의 크기인 [400, 400]을 그대로 반영하여, X방향 및 Y방향 모두 0에서 400의 범위를 갖는 좌표계로 설정되었다는 점을 유의하기 바란다. 

oWindow = OBJ_NEW('IDLgrWindow', RETAIN = 2, $

  DIMENSIONS = winSize, $

  TITLE = 'World Elevation: First Method')

oView = OBJ_NEW('IDLgrView', $

  VIEWPLANE_RECT = [0., 0., winSize])

oModel = OBJ_NEW('IDLgrModel')

생성될 이미지 객체에 적용할 컬러테이블 객체를 선언하여 이미지 객체 선언시 사용한다. 여기서는 5번 컬러테이블에 해당되는 객체를 선언하고 이를 이미지 객체 선언시 PALETTE라는 속성으로 부여하였다. 

oPalette = OBJ_NEW('IDLgrPalette')

oPalette -> LOADCT, 5

oImage = OBJ_NEW('IDLgrImage', worldelvImage, $

  PALETTE = oPalette)

이미지 객체를 모델 객체에 넣고, 이 모델 객체는 뷰 객체에 넣는다. 그리고 이 모델 객체를 윈도우의 가운데 영역으로 이동시키고, 뷰 객체를 가시화한다. 이동시 Translate 메서드를 모델 객체에 대하여 사용하며, 이동거리는 X 및 Y 방향으로 앞서 계산했던 필요 여백만큼이라는 점을 상기한다. 2차원 이미지의 표출작업이므로 Z방향의 이동은 불필요하여 이동거리는 0이다. 

oModel -> Add, oImage

oView -> Add, oModel

oModel -> Translate, winMargin[0], winMargin[1], 0

oWindow -> Draw, oView

그러면 다음 그림과 같이, 이미지가 윈도우상의 한가운데에 위치하도록 구현되었음을 볼 수 있다.


작업이 다 끝나면 더 이상 필요없는 객체들을 모두 제거한다. 

OBJ_DESTROY, [oView, oPalette]


이번에는 두번째 방법을 시도해보자. 이를 위하여 새로운 윈도우 객체를 선언하고 이를 위한 뷰, 모델 등 기본적으로 필요한 그래픽 객체들도 함께 선언한다. 단, 여기서는 첫번째 방법때와는 달리 VIEWPLANE_RECT 속성을 [0, 0, 1, 1]로 지정하였다는 점을 주목한다. 이는 곧 뷰 객체상의 좌표계가 X, Y 방향 모두 0에서 1의 범위를 따른다는 의미이다. 

oWindow = OBJ_NEW('IDLgrWindow', RETAIN = 2, $

  DIMENSIONS = winSize, $

  TITLE = 'World Elevation: First Method')

oView = OBJ_NEW('IDLgrView', VIEWPLANE_RECT=[0, 0, 1, 1])

oModel = OBJ_NEW('IDLgrModel')

생성될 이미지 객체에 적용할 컬러테이블 객체를 선언하여 이미지 객체 선언시 사용한다. 여기서는 5번 컬러테이블에 해당되는 객체를 선언하고 이를 이미지 객체 선언시 PALETTE라는 속성으로 부여하였다.

oPalette = OBJ_NEW('IDLgrPalette')

oPalette -> LOADCT, 5

oImage = OBJ_NEW('IDLgrImage', worldelvImage, $

  PALETTE = oPalette)

생성된 이미지 객체로부터 [XY]COORD_CONV 및 [XY]RANGE 속성에 부여된 초기 설정값을 가져온다. 그리고 좌표변환과 관련된 인자들을 일단 출력해본다.

oImage -> GetProperty, XCOORD_CONV = xConv, $

  YCOORD_CONV = yConv, XRANGE = xRange, YRANGE = yRange

PRINT, 'Initial xConv: ', xConv

PRINT, 'Initial yConv: ', yConv

출력결과를 보면 xConv, yConv 모두 초기 설정은 [0, 1]로 되어있다. 첫번쨰 인자는 이동, 두번째 인자는 스케일과 관련된 인자임을 상기하면, 아무 이동도 안시키고 스케일은 그냥 액면 그대로 받아들인다는 뜻이다. 물론 이대로 사용하면 안될 것이고, 적당한 값들로 구성된 새로운 xConv, yConv를 만들어야 할 것이다. 좌표변환에 있어서 상하좌우의 여백을 고려한 인자들을 계산한다. 모델 객체에 대하여 Translate 및 Scale 메서드에 적용할 인자들을 X, Y 각 방향으로 계산하고, 이것들이 합쳐져 결국 [XY]COORD_CONV 속성에 다시 부여될 것이다. 이렇게 부여될 좌표변환 관련 인자들을 출력한다.

xTranslation = FLOAT(winMargin[0])/winSize[0]

xScale = 1./winSize[0]

xConv = [xTranslation, xScale]

yTranslation = FLOAT(winMargin[1])/winSize[1]

yScale = 1./winSize[1]

yConv = [yTranslation, yScale]

PRINT, 'Resulting xConv: ', xConv

PRINT, 'Resulting yConv: ', yConv

새로운 출력결과를 보면 xConv, yConv 모두 [0.05, 0.0025]로 되어있을 것이다. 일단 스케일 관련값인 0.0025의 의미는, 이미지의 크기는 360이지만 스케일 자체는 400을 기준으로 하기 때문에 1./400에 해당되는 값이 나온 것이다. 그리고 이렇게 400을 기준으로 스케일 조정된 이미지는 윈도우상에 꽉 차지않고 왼쪽 구석에 쳐박힐 것이다. 따라서 이를 이동시켜야 하는데, 필요한 이동거리는 여백에 해당되는 20을 윈도우 크기인 400으로 나눠준 값이 되어야 한다. 이와 같이 계산된 변환인자들을 이미지 객체의 속성으로 다시 부여한다.

oImage -> SetProperty, $

  XCOORD_CONV = xConv, YCOORD_CONV = yConv

이미지 객체를 모델 객체에 넣고, 이 모델 객체는 뷰 객체에 넣는다. 그리고 이 뷰 객체를 가시화한다.

oModel -> Add, oImage

oView -> Add, oModel

oWindow -> Draw, oView


작업이 다 끝나면 객체들을 모두 제거한다.

OBJ_DESTROY, [oView, oPalette]

이와 같은 작업을 수행하면 두 가지 방법으로 구현된 결과가 다음과 같이 앞의 그림과 같다는 것을 알 수 있을 것이다(물론 상단 윈도우바의 타이틀만 First냐 Second냐의 차이일 뿐이다).


여기서 [XYZ]COORD_CONV에 대한 이해도를 높이기 위하여 다음과 같이 xConv, yConv의 첫번째 인자인 이동과 관련된 값을 그냥 0으로 설정하고 그림을 그려보자.

xConv = [0, xScale]

yConv = [0, yScale]

그러면 다음과 같이 이동이 전혀 없이 그냥 왼쪽 구석에 쳐박힌 채로 그림이 나올 것이다. 따라서 이동 관련 인자의 역할이 어떤 것인지 이러한 그림을 보면 아마 어느 정도 이해가 될 것으로 믿는다.


둘 중 어느쪽 방법이 더 좋으냐에 대한 판단기준은 따로 없으므로, 사용자 입장에서 더 좋은 쪽을 택하면 된다. 얼른 이해하기에는 첫번째 방법이 좀 나아보이긴 하다. 실제로 [XYZ]COORD_CONV의 개념은 익숙해지기 위해서는 어느 정도 시간이 필요한 것은 사실이다. 필자 역시 Object Graphics에서의 작업을 하는데 있어서, 이 부분이 지금도 쉽지않다고 느낄 때가 많다. 하지만 궁극적으로는 여기에 익숙해져야 차후에 Object Graphics 프로그래밍에서의 작업이 좀 더 수월해질 것이다. 

반응형

'IDL > Object Graphics' 카테고리의 다른 글

IDL 8.0에서 새로 도입된 Object 관련 문법  (0) 2011.02.07
Object Graphics in IDL [24]  (0) 2011.02.05
Object Graphics in IDL [22]  (0) 2011.01.24
Object Graphics in IDL [21]  (0) 2011.01.18
Object Graphics in IDL [20]  (0) 2011.01.11