텍스트 효과 단위기능 테스트

구글맵이나 네이버지도, 다음지도 등등 모든 포털 지도사이트에서 제공하는 지도 서비스는 지도 이미지를 256×256 픽셀 크기로 잘려진 타일이미지 형태로 서비스되고 있습니다. 자사만의 지도 타일이미지 렌더링 프로그램을 직접 개발한 곳도 있을테고…. 구글처럼 오픈소스 라이브러리를 이용해 구축한 곳도 있을테고….

현재  RIA 기반의 지도 솔루션 개발에 필요한 지도 타일 이미지 렌더러를 개발하고 있습니다. 오픈소스를 활용하여 개발할까… 생각도 해보았지만… 다양한 사용자가 원하는 자신만의 지도 스타일의 충족이라는 틈새 시장을 놓고 볼때… 오픈소스의 획일화된 지도 이미지 스타일은 제 기획 의도와 맞지 않다고 판단하여 직접 개발하기로 결정하게 되었습니다.

사용자 삽입 이미지
위의 결과 이미지는 현재 개발중인 지도 타일이미지 렌더러에서 텍스트 표현을 위해 고민해본 텍스트 효과입니다. 실제 종이 지도를 살펴보고 글자에 적용된 효과를 살펴보면서 위의 3가지 효과정도면 될듯하여 하나 하나 구현해 보았습니다.

추후 타일 이미지 렌더러… 개발이 완료되면 위의 텍스트 효과가 적용된 지도를 통해 좀더 분명한 결과를 알릴 수 있겠지만.. 지금 단계에서 현재 제 스스로가 무엇을 하고 있는지… 어느 방향으로 가고 있는지에 대해 한 조각이라도 구체화하기 위한 과정으로써의 글을 올려봅니다.

사무실에서 쓸 작용업 PC

개발과 작업을 노트북에서 하던 중에.. 널직한 해상도와 쓸만한 퍼포먼스를 가진 컴퓨터가 필요하여 요 몇일 동안 알아보던 중.. 이왕 제대로 된 녀석을 구비할 것이면 역시 데스크탑이 어떨까 싶어 알아 본 컴퓨터입니다.

원래는 직접 부품을 하나 하나 살펴보고 조사해서 직접 조립할 기세였으나…. 그냥 완제품으로 구입하기 맘 먹고 결정한 녀석입니다. 짧게는 3년… 길게는 6년정도 사용할 PC이며 문서 작업과 코딩… 그리고 지도 이미지 렌더러 및 개발용 서버 등 매우 다양하게 활용될 녀석인지라… 그 목적에 부족함이 없도록 메모리나 하드 디스크 용량 그리고 CPU 및 그래픽 카드가 어느 정도 상급으로 구성된 녀석입니다.

하지만… 이왕이면 대학교 시절처럼 직접 조립해서 사용했으면 더 좋은 사양으로 더 저렴하게 조립할 수 있었을텐데….. 하는 아쉬움이 남습니다..

사용자 삽입 이미지
사양은 위와 같습니다. 제조사는 DELL이구요.. 대략 4년 정도 DELL 노트북 2종과 데스크탑 PC를 사용하면서 AS는 물론 사용하는데도 만족스러웠던 경험에서 제조사의 선택에 별다른 미련이 남지는 않습니다. 아래는 PC의 외관입니다.

사용자 삽입 이미지
사용자 삽입 이미지
사용자 삽입 이미지
그리고 모니터는 DELL이 아닌 LG 제품을 구입했습니다.. 실제 가장 많이 사용하는 작업이 코딩인지라 가독성이 높으면서 그런대로 해상도(1920 x 1080)로 선택했고.. 가격은 저렴한 녀석으로 선택했습니다. 이 녀석은 실제 매장에 들려 직접 눈으로 확인한 다음에 구입을 결정했습니다만…. 다른 기종들을 살펴보지 않은지라… 조금 미련이 남긴합니다..

사용자 삽입 이미지
의도하지는 않았지만 다행히… 본체와 모니터가 마치 한 패키지처럼 잘 어울리는듯합니다..

[GIS] ArcObjects, 속성값으로 쿼리(Query)하기

GIS의 강력한 기능 중에 하나는 속성 데이터에 기반한 공간적인 처리 및 가시화인데, 이 글은 ArcObjects에서 속성값 조건에 대해 쿼리(Query)하는 방법에 대해 설명하겠습니다. 일단…. 속성값에 대한 쿼리가 목적이므로 먼저 속성값에 접근할 수 있는 ITable 인터페이스에 접근할 필요가 있습니다. 다음은 d:\__data__ 폴더 안의 seoul.dbf 파일로부터 ITable 인터페이스의 구체 클래스 인스턴스를 얻는 코드입니다.

ESRI.ArcGIS.Geodatabase.IWorkspaceFactory pWF;
ESRI.ArcGIS.Geodatabase.IFeatureWorkspace pFW;

pWF = new ESRI.ArcGIS.DataSourcesFile.ShapefileWorkspaceFactory();
pFW = pWF.OpenFromFile("d:/__data__", 0) 
                as ESRI.ArcGIS.Geodatabase.IFeatureWorkspace;

ESRI.ArcGIS.Geodatabase.ITable pTable;
pTable = pFW.OpenTable("seoul");

ITable의 구체 클래스의 인스턴스인 pTable은 속성값으로 검색할 수 있는 매서드인 Search 함수를 가지고 있습니다. 이 Search 함수는 두개의 인수를 가지며 첫번째 인수의 타입은 IQueryFilter로써 SQL 문의 WHERE 절의 조건문을 지정하기 위해 사용됩니다. 그리고 두번째 인수는 검색 결과에 대한 Row에 대한 재활용 여부에 대한 bool 형입니다. 이에 대해서는 이 글의 마지막에 간단히 다시 설명하겠습니다.

속성값으로 쿼리하기 위하여 조건문을 만들기 위해서… 먼저 앞의 코드를 통해 오픈한 seoul.dbf 파일의 필드 구조를 알 필요가 있습니다. 힌트를 준다면 seoul.dbf의 속성 중의 하나는 SGG_NM으로써 서울시를 구성하는 행정구의 이름값이 저장되어 있습니다. 여기서는 행정구 이름에 ‘동’자가 들어가는 모든 Row를 검색하려고 합니다. 이런 조건을 위한 ITable의 Search의 첫번째 인자인 IQueryFilter의 CoClass(구체 클래스)의 정의는 다음과 같습니다.

ESRI.ArcGIS.Geodatabase.IQueryFilter pQF;
pQF = new ESRI.ArcGIS.Geodatabase.QueryFilter();
pQF.WhereClause = "SGG_NM LIKE '%동%'";

IQueryFilter의 WhereClause 프로퍼티가 바로 ‘그것’인데.. 일반적인 SQL의 SELECT 문의 WHERE 절의 바로 정확히 ‘그것’에 해당합니다. SQL문의 SELECT문을 알고 있는 개발자라면 아~!라는 탄식이 나올정도로 ArcObjects는 속성값으로 데이터를 쿼리하는 탁월한 방법을 사용하고 있습니다. 이렇게 만든 IQueryFilter를 이용하여 쿼리하는 코드는 다음과 같습니다.

ESRI.ArcGIS.Geodatabase.IFeatureCursor pFC;
pFC = pTable.Search(pQF, true) as ESRI.ArcGIS.Geodatabase.IFeatureCursor;

ITable의 Search 함수를 사용하며 검색 결과 Row는 IFeatureCursor 타입으로 반환됩니다. 검색 조건과 일치하는 Row를 얻기 위해 IFeatureCursor 타입의 인스턴스 변수인 pFC를 사용하는데.. 아래의 코드가 바로 그것이며, listBox1 이름의 ListBox 컨트롤에 그 결과를 채웁니다.

ESRI.ArcGIS.Geodatabase.IFeature pFeature;
int cntFields = pFC.Fields.FieldCount;

listBox1.Items.Clear();
pFeature = pFC.NextFeature();
while(pFeature != null) {
    for(int iField=0; iField

5번째 코드에서 가장 먼저 IFeatureClass의 NextFeature 매서드를 호출하여 첫번째 검색 결과의 Row에 해당되는 IFeature 클래스 타입의 인스턴스를 반환받고 첫번째 Row에 대한 값을 얻기 위하여 IFeature의 get_Value 매서드를 사용하여 값을 얻습니다. 그 다음 결과 Row를 얻기 위하여 다시 NextFeature를 호출합니다. NextFeature의 반환값이 null이면 더 이상 조건에 맞는 Row가 없다는 의미입니다. 실행 결과는 아래와 같습니다. 강동구, 성동구, 동작구, 동대문구와 같이 '동'자가 들어간 데이터만이 검색된 것을 알 수 있습니다.

사용자 삽입 이미지
끝으로 앞서 언급한... 이 글의 핵심 매서드인 ITable의 Search 매서드의 두번째 인자의 의미에 대해서 설명하면... 만약 true라면 IFeatureClass의 NextFeature의 결과에 대한 인스턴스를 재활용한다는 의미이며 false이면 재활용하지 않고 NextFeature를 호출할때 마다 새로운 인스턴스를 생성한다는 의미입니다. 이를 목적에 대해 생각해보면 true이면 Feature를 읽기 전용으로만 사용해야 하며 false일 경우 IFeature를 통해 속성값을 변경할 수 있습니다.

[GIS] ArcObjects, 속성 테이블(DBF)의 필드 정보 얻기

ArcGIS에서 Feature는 좌표에 대한 도형 데이터와 속성으로 묶어진 단위입니다. ESRI에서 정의한 Shape 파일의 경우 좌표에 대한 도형 데이터는 .SHP 파일에 저장되며 속성은 .DBF 파일에 저장됩니다. 속성은 하나의 DB 테이블 개념과 정확히 일치합니다. DB 테이블의 필드 정보와 각 필드에 대한 값들의 집합의 구성 요소인 로우(Row) 또는 레코드(Record)로 구성됩니다.

필드 정보라 함은 필드의 이름과 필드의 타입 그리고 필드 타입에 대한 데이터 저장 가능 길이 등으로 구성됩니다. 이 포스트는 Shape 파일에 대해서 .DBF에 저장된 필드 정보를 얻어내는 ArcObjects의 API에 대해서 설명합니다.

가장 먼저 해야할 작업은 .DBF 파일을 여는 것에서 시작합니다. 다음 코드는 .DBF 파일을 여는 방법입니다.

ESRI.ArcGIS.Geodatabase.IWorkspaceFactory pWF;
ESRI.ArcGIS.Geodatabase.IFeatureWorkspace pFW;

pWF = new ESRI.ArcGIS.DataSourcesFile.ShapefileWorkspaceFactory();
pFW = pWF.OpenFromFile("d:/__data__", 0) 
              as ESRI.ArcGIS.Geodatabase.IFeatureWorkspace;

ESRI.ArcGIS.Geodatabase.ITable pTable;
pTable = pFW.OpenTable("seoul");

.SHP 파일을 여는 것과 매우 동일하다는 것을 알 수 있습니다. 다른 부분은 8, 9번 라인에서 ITable 타입으로 하여 테이블을 여는 것입니다. 위의 예는 d:/__data__ 폴더 안에 seoul.dbf 파일을 열어 그 테이블을 ITable 타입인 pTable에 저장해 놓는 경우입니다.

이렇게 얻은 pTable을 통해 필드 정보를 얻기 위한 코드는 아래와 같습니다.

ESRI.ArcGIS.Geodatabase.IFields pFields;
pFields = pTable.Fields;

int cntFields = pFields.FieldCount;

테이블의 필드 정보는 IFields 타입에 저장되며 pTable의 Fields 속성을 통해 접근이 가능합니다. 4번째 줄은 필드의 전체 개수를 얻는 코드입니다. 이제 이렇게 얻은 pFields를 통해 각 필드의 이름, 별칭(Alias), 필드길이, 정밀도, 타입을 얻어 ListBox 컨트롤에 채워 보는 코드는 아래와 같습니다.

listBox1.Items.Clear();
for(int iField=0; iField<cntFields; ++iField) 
{
    ESRI.ArcGIS.Geodatabase.IField pField;
    pField = pFields.get_Field(iField);

    string AliasName = pField.AliasName;
    string FieldName = pField.Name;
    int Length = pField.Length;
    int Precision = pField.Precision;
    ESRI.ArcGIS.Geodatabase.esriFieldType FT = pField.Type;
                
    listBox1.Items.Add(FieldName + "(" + AliasName + ")");
    listBox1.Items.Add("  Length: " + Length.ToString());
    listBox1.Items.Add("  Precision: " + Precision.ToString());
    listBox1.Items.Add("  Type: " + FT.ToString());
    listBox1.Items.Add("");
}

참고로 ListBox 컨트롤의 이름은 listBox1입니다. 앞서 구한 전체 필드의 개수를 통해 반복문에서 필드 정보를 IField 타입으로 가져와 필드의 정보를 구할 수 있습니다. 이름은 IField 타입의 Name 속성으로 알 수 있고, 별칭명은 AliasName, 길이는 Length, 정밀도는 Precision 그리고 필드의 타입은 Type으로 알 수 있습니다. 참고로 아래는 실행 결과 화면입니다.

사용자 삽입 이미지