내가 사랑한 유럽 TOP 20

대한항공의 광고를 보고 제목을 비슷하게 뽑아 보았습니다만, “내가 아는 유럽 국가 이름 모두 다 합쳐 보니 20개” 라고 하는 것이 진실에 가깝습니다. ^_^. 그려놓고 보니 물론 바다인 부분도 있지만 빠진 나라들이 많은 것 같네요.

이번 글은 D. Fanning 박사님의 멋진 라이브러리를 이용하여 Shape 파일이라는 지도 전용 벡터 파일을 조회하고 이를 이용하여 지도를 그리는 과정을 소개하고자 합니다. 사실상의 내용은 모두 Fanning 박사님의 글(링크)에서 가져 온 것이며 제가 처한 상황에 맞추어 조금 바꾸어 본 것에 불과합니다.

몇 번 소개가 되었는데요, Shape 파일(확장자 shp)은 ESRI 사가 ArcGIS 등의 지도 자료 제작용으로 확립한 포맷으로 지도의 벡터 데이터와 투영법, 각 폴리곤에 해당하는 데이터들을 내포하고 있습니다. “우리 시의 동별 예비군 현황” 같은 것을 그리고자 할 때, 비록 IDL에 내장된 이런 지도 데이터는 없지만, 동 경계선 정보를 가지는 Shape 파일이 아마도 있을 것이고, 이 파일만 있다면 그리는 것은 이제 어렵지 않게 될 것입니다. 다시말해, 필요한 정보를 가지는 Shape 파일만 구하면 지도는 그릴 수 있습니다. Shape 파일을 구한 이후의 내용을 아래에 소개하는 것입니다.

그거 아시나요? IDL의 New Graphics에서는 MAP() 함수를 이용하여 지도를 그릴 때 Shape 파일로 처리하고 있다는 사실을? Direct Graphics의 MAP_CONTINENTS에서 사용하던 지도 파일은 New Graphics에서 사용하지 않습니다. 그래서, IDL의 최근 버전에는 Shape 파일들 몇개가 들어 있습니다. IDL설치디렉토리/resources/maps/shape 디렉토리를 보시면 확인하실 수 있습니다.

C:\Program Files\Exelis\IDL83\resource\maps\shape\GSHHS_h_L1.shp
C:\Program Files\Exelis\IDL83\resource\maps\shape\canadaprovince.shp
C:\Program Files\Exelis\IDL83\resource\maps\shape\cntry08.shp
C:\Program Files\Exelis\IDL83\resource\maps\shape\continents.shp
C:\Program Files\Exelis\IDL83\resource\maps\shape\country.shp
C:\Program Files\Exelis\IDL83\resource\maps\shape\lakes.shp
C:\Program Files\Exelis\IDL83\resource\maps\shape\rivers.shp
C:\Program Files\Exelis\IDL83\resource\maps\shape\states.shp
C:\Program Files\Exelis\IDL83\resource\maps\shape\states_high.shp

GSHHS 프로젝트의 해안선 데이터도 있고요(프로젝트 홈페이지에 가면 훨씬 상세한 데이터도 있습니다 – 일반적으로는 필요하지 않지만), Canada 주 경계, 미국 주 경계, 국경선, 강, 호수 등의 정보가 보입니다. 미국 state 데이터 있듯이 우리나라도 도 경계선이나, 시군구 경계선이 있으면 요긴할 것 같은데요, IDL 기본 배포판에 들어가기를 기대하긴 어렵고, 우리가 shape 파일을 구해다 쓰면 됩니다. 여기서는 IDL에 이미 설치되어 있는 country.shp를 이용할 거예요.

D. Fanning 박사님의 원본 글은 미국 state 경계선을 이용해서 주마다 다른 색으로 채워 넣어 미국 지도를 그리는 과정을 보여 주고 있습니다. 이 글에서는 IDL에 기본적으로 들어있는 country.shp 파일을 이용하여 나라마다 다른 색으로 색상을 입히는 과정을 보여드릴 것입니다. 그래서 내용이 대동소이합니다. IDL에는 IDLffShape 라는 클래스가 있어 Shape와 관련된 모든 일들을 처리합니다. 그런데 이 클래스는 너무 범용으로 만들어서 간단한 일을 할 때 사용하기에는 좀 번거롭거든요. 그래서 D. Fanning 박사님이 몇가지 Shape 관련 루틴들을 만들어 놓으셨고 우리는 이것을 쓸 것입니다.

일단 이 Shape 파일에 어떤 속성들이 있는지 알아야 합니다.  cgShapeInfo 프로시저를 이용합니다.

cgShapeInfo

cgShapeInfo

ISO_2DIGIT, ISO_3DIGIT 같은 2글자 국가명, 3글자 국가명 등의 속성이 있고 각 속성을 선택하면 존재하는 속성값들을 보여줍니다. 설명하자면 국경선 정보가 각 나라마다 있는데, 각 국경선 정보(다각형)마다 여러가지 식별값이나 정보(면적, 인구 같은 것)가 포함되어 있는 것입니다. 우리는 여기서 CNTRY_NAME이라는 속성을 활용할 계획입니다.

자, 사용할 Shape 파일은 IDL 배포판에 이미 들어 있기 때문에 다음과 같이 지정할 수 있습니다.

그림을 그릴 나라 이름을 다음과 같이 배열로 만들었습니다. 실무적인 상황이라면 이 이름들이 DB에서 읽혀 오거나, File에서 읽혀올 가능성이 높습니다만 여기서는 그냥 배열로 직접 지정해 주었습니다.

cg로 시작하는 루틴들은 Coyote Graphics를 의미하는 D. Fanning 박사님의 루틴들입니다. IDL의 기본 제공 루틴보다 사용이 간편하거나 기능이 더 많습니다. Window에 해당하는 루틴은 cgDisplay입니다. map_set 에 해당하는 루틴은 cgMap_set 입니다. 즉, 다음과 같이 창을 열어 지도 좌표계 설정을 합니다.

지정한 Shape 파일에서 지정 속성에 해당하는 다각형을 그리는 것이 cgDrawShapes 입니다. 다음과 같이 씁니다.

cgDrawShapes (색을 각각 문자열로 지정)

cgDrawShapes (색을 각각 문자열로 지정)

CNTRY_NAME 속성에서 AttrValues 즉 Country 변수에 있는 지정한 국가 20개에 대해서 그리되, 20개 모두 색칠을 하고(FILL=replicate(1, 20)), 칠하는 색의 이름 20개를 각각 문자열로 지정해 주었습니다. 이 색 이름은 IDL 표준 색이름 체계와는 좀 다릅니다. Coyote Graphics Color 체계의 색이름이며 cgPickColorName() 함수를 이용하면 확인할 수 있습니다.

이후 cgMap_Grid 도 눈금선을 그렸습니다. 이렇게 해서 한 세트를 완성했습니다.

의도적으로 색을 선택하고자 하는 경우, 그리고 그러한 선택이 몇 개 정도로 충분한 경우라면 일일이 색을 지정해 주는 것이 어렵지 않겠지만, 수십개의 국경선(주 경계선, 도 경계선 등)을 채우는 색을 일일이 이렇게 지정할 생각은 없습니다. 또는 마지막에 소개하겠지만, 채우는 색이 다각형의 면적이라든지 거주하는 인구수 등을 의미하는 것이라면 위와 같이 색 이름으로 색을 배정해 사용하지는 않겠지요. cgDrawShapes의 FCOLORS나 COLORS는 그래서 문자열 색이름 외에도 Byte 타입의 숫자(0~255)를 받거나 또는 이 숫자의 문자열(예를 들어, ‘255’) 을 수용할 수 있게 되어 있습니다. 다음과 같이 사용할 수 있는 거예요.

cgDrawShapes (컬러테이블 번호로 색을 지정:0~255)

cgDrawShapes (컬러테이블 번호로 색을 지정:0~255)

위 예제이서는 FCOLORS=BINDGEN(n_country)*10을 지정하여 0, 10, 20, 30, 40, …., 190번 컬러를 각각 사용하게 되었습니다. 실험을 해 보니 이 숫자가 실수형일 경우에는 에러가 나옵니다. 그러므로 Byte형이나 Integer형으로 숫자를 사용하십시오. ,  ‘0’, ’10’, ’20’ 과 같은 문자열이지만 사실은 정수값인 리터럴도 인식합니다. 그리고 현재 사용하는 그래픽 설정이 Device, Decomposed=0 이든 Decomposed=1 이든 상관 없이 현재 탑재된 컬러테이블을 사용한다는 것도 기억하십시오. 마음에 드는 컬러테이블을 불러 사용해도 좋고(Loadct), 직접 컬러테이블을 만들어서 적재해도 됩니다(TVLCT, 또는 Colortable).

별 차이는 없지만 마지막으로 칠하는 색이 어떤 양을 의미하는 상황일 때를 가정해 보겠습니다. 예를 들면 나라마다 인구수에 따른 색을 칠하고 싶은 상황 같은 것입니다. 이 때는 BYTSCL() 함수를 적절히 활용하면 됩니다.

cgDrawShapes (인구 수를 의미하는 색으로 채움)

cgDrawShapes (인구 수를 의미하는 색으로 채움)

59번 컬러테이블을 사용하기로 했고(그림의 컬러바를 보시면 됩니다), 인구의 범위는 최소 0에서 최대 1억으로 했습니다.(bytscl(popularity, max=1억, min=0)). 이렇게 하면 0에서 1억 사이의 값들이 0~255 사이의 Byte 값에서 해당하는 값으로 변환됩니다. 꼭 0~255가 아니어도 됩니다. TOP=99라고 키워드를 쓰면 0~99 사이의 값으로 스케일링합니다. 중국이나 인도를 끼우게 되면 다른 나라들은 모두 사람 안사는 거랑 비슷해지기 때문에, 유럽 지도에서는 이정도 범위가 적당해 보입니다. 마지막으로 cgColorbar를 이용해서 컬러바를 그립니다. 컬러바 값의 범위도 똑같이 지정해 주면 되겠습니다.

이제 Shape 파일만 있으면 이를 이용해서 지도로 표출하는 것은 어려운 일이 아닙니다. IDLffShape를 직접 쓰면 번거로운 일이겠지만, Coyote Graphics의 cgDrawShapes 덕분에 일이 많이 간단해 졌습니다.