좌표 변환 (Coordinate Conversion)
앞서 설명했듯이 Object Graphics에서 ‘변환(Transformation)’이라는 것은 주로 모델 객체의 수준에서 이루어진다. 그러나 모델 객체에 포함되어 있는 하위 그래픽 객체들의 경우도 나름대로 제한적으로 위치와 스케일에 대한 변환은 가능하다. 이러한 변환기능은 서로 다른 좌표계 사이의 변환의 측면에서 특히 유용하다.
예를 들어 어떤 뷰 객체가 있는데 뷰포트의 좌표계가 0부터 1까지의 범위를 갖는 normal 좌표계를 따르도록 설정이 되어있다고 하자. 그런데 이 안에 이미지 객체 하나를 생성하여 포함시키고자 한다. 이와 같은 하위 그래픽 객체의 경우 기본적으로는 DATA 좌표계를 따르도록 되어있다. 즉, 이미지 객체의 기반이 되는 2차원 배열자료가 X 및 Y 방향으로 갖는 값의 크기를 그대로 따른다는 뜻이다.
예를 들어, 그 배열자료가 [100, 100]의 크기를 갖는다고 하면, 이 자료를 기반으로 생성된 이미지 객체는 뷰포트의 크기를 훨씬 뛰어넘는 무지막지한 크기로 구현이 될 것이다. 왜냐하면 뷰 객체의 좌표계는 X 및 Y 방향으로 0부터 1까지의 범위로 정의가 되어있는 상태이기 때문이다. 이 상태에서는 이미지 객체가 구현이 되더라도 관찰자의 눈에는 안보일 것이다. 뷰 볼륨을 훨씬 초과하는 크기로 존재하기 때문에 이미 가시적으로 볼 수 있는 범위를 넘어선 상태이기 때문이다. 다음 그림을 보면 이 설명이 도식적으로 이해가 될 것이다.
사실 이러한 상황은 Object Graphics를 처음 경험하는 프로그래머라면 누구나 한번쯤(그 이상이 될 수도 있다) 겪는 일이다. 필자 역시 이와 같은 경우를 여러번 겪었으며, 그 때마다 ‘내가 대체 뭘 잘못한거지?‘라는 의문을 품고 한참을 고민하다가 나중에 그 원인을 알고나면 그렇게 허망할 수가 없던 그런 아픈 기억이 있다. 그렇다면 어떻게 해야 이와 같은 난감한 상황을 헤쳐나갈 수 있을까? 방법은 사실 의외로 간단하다. 뷰 객체와 이미지 객체 둘 중 어느 한쪽으로 좌표계를 맞춰주면 된다. 대개는 하위 그래픽 객체의 좌표계를 상위 뷰 객체의 좌표계에 맞춰주는 방식을 따르는 것이 일반적이다. 여러 종류의 하위 그래픽 객체마다 갖게되는 속성들 중 [XYZ]COORD_CONV라는 것이 바로 이러한 역할을 한다. 다음 예제를 통하여 그 방법을 살펴보도록 하자.
먼저 [100, 100] 크기를 갖는 임의의 2차원 배열 자료를 생성한다.
myData = DIST(100)
SIZE 함수를 사용하여 이 배열의 차원별 크기를 알아낸다.
sz = SIZE(myData, /DIMENSION)
X방향의 스케일 조정인자를 다음과 같이 생성한다.
xs = 1.0 / sz[0]
Y 방향에 대해서도 마찬가지 요령으로 스케일 조정인자를 생성한다.
ys = 1.0 / sz[1]
이제 이미지 객체를 생성하면서 [XYZ]COORD_CONV 키워드를 사용하여 적절한 스케일로 생성되도록 한다.
oImage = OBJ_NEW(‘IDLgrImage’, myData, $
XCOORD_CONV=[0, xs], YCOORD_CONV=[0, ys]
참고로 XCOORD_CONV 키워드에 부여되는 값은 다음과 같이 두 개의 원소로 이루어진 배열이 되는 것이 일반적이다.
[ (-Xmin)/(Xmax-Xmin), 1/(Xmax-Xmin) ]
현재 고려중인 2차원 자료인 myData를 생각하면 X방향으로 최소값은 0이고 최대값은 100이 될 것이다. 이를 생각해보면 왜 XCOORD_CONV 키워드의 값이 저렇게 부여되었는지 알 수 있을 것이다. YCOORD_CONV의 경우도 방향만 Y일뿐 요령은 같다. 이 키워드에 부여될 벡터를 산출하기 위하여 편리하게 사용할 수 있는 NORM_COORD라는 함수가 IDL이 설치된 폴더내에서 examples/visual/utility라는 하위폴더안에 마련되어 있다. 이 함수 프로그램의 내용은 다른 주석문들을 제외하면 다음과 같이 매우 간단하다.
FUNCTION NORM_COORD, range
scale = [-range[0]/([range[1]-range[0]), $
1/(range[1]-range[0])]
RETURN, scale
END
따라서 이 함수를 이용한다면 조금 더 편하게 작업을 할 수 있을 것이다.
oImage = OBJ_NEW(‘IDLgrImage’, myData)
oImage -> GetProperty, XRANGE=xr, YRANGE=yr)
oImage -> SetProperty, XCOORD_CONV=NORM_COORD(xr), $
YCOORD_CONV=NORM_COORD(yr)
즉, 이 함수를 이용한다면 위와 같이 프로그램을 만들어 실행해도 같은 결과를 얻을 수 있다. 그러면 윈도우, 뷰, 모델 객체들을 다음과 같이 생성하자. 물론 뷰 객체를 생성할 때 뷰플레인 사각형의 위치 및 크기를 다음과 같이 설정해주는 것도 잊지말자.
oWindow = OBJ_NEW(‘IDLgrWindow’, DIMENSION=[400,400])
oView = OBJ_NEW(‘IDLgrView’, VIEWPLANE_RECT=[0,0,1,1])
oModel = OBJ_NEW(‘IDLgrModel’)
이제 이미지 객체를 모델 객체에 넣고, 모델 객체를 뷰 객체에 넣은 다음, 윈도우에 그림을 그리면 그 결과는 다음과 같다. 이미지의 크기가 뷰의 크기에 꼭 맞도록 조절되었기 때문에, 이미지가 윈도우 화면에 꽉 차도록 구현되었음을 알 수 있다.
oModel -> Add, oImage
oView -> Add, oModel
oWindow -> Draw, oView
'IDL > Object Graphics' 카테고리의 다른 글
Object Graphics in IDL [24] (0) | 2011.02.05 |
---|---|
Object Graphics in IDL [23] (0) | 2011.01.31 |
Object Graphics in IDL [21] (0) | 2011.01.18 |
Object Graphics in IDL [20] (0) | 2011.01.11 |
Object Graphics in IDL [19] (0) | 2011.01.04 |