*** SHP 분석 2 ***


안녕하세요.


오늘은 지난 번에 이어서 shx 파일에 대해 알아보도록 하겠습니다.


1.2 shx 파일


shx 파일은 shp 파일에 대한 일종의 인덱스 파일입니다.


shx 파일은 다음과 같은 구조로 되어 있습니다.(shp 사양서 참조)


----------------------------

File Header(100Byte)
Record(8Byte)

Record(8Byte)

.

.

.

Record(8Byte)

----------------------------



가) File Header


shx 파일의 File Header의 구조는 shp 파일의 File Header와 동일한 구조입니다.


다만 File Length 부분이 shx의 File Length를 담고 있다는 차이가 있을 뿐입니다.

저번 강의 때 빼먹었는데, File Length는 Byte 단위가 아닌 16bit인 word 단위로 기록되어 있습니다. 이 점 유념하시기 바랍니다.

따라서 shx의 전체 파일 크기는 100byte(File Header) + record 개수  * 8byte(record)가 될 것입니다.


나) Record


레코드는 다음과 같은 구조로 이루어져 있습니다.

Position   Field                          Value                Type     Order
----------------------------------------------------------
Byte 0      Offset                        Offset                 Integer   Big
Byte 4      Content Length         Content Length   Integer   Big

----------------------------------------------------------


여기서 offset이 중요합니다. 이값이 shp의 같은 레코드의 위치를 포인팅하고 있습니다. 그런데 이 offset 값 역시 16bit인 word로 기록되어 있습니다. 따라서 byte로 전환할 때는 2를 곱해줘야 합니다.

Content Length는 shp 파일에 있는 Content Length와 같은 값입니다.


1.3 dbf 파일


dbf 파일은 지난 번에 설명했다시피 dBase IV의 구조의 그것과 같은 것입니다.

MFC의 DAO 클래스를 이용하셔서 접근할 수도 있으며, 공개되어 있는 많은 DBF 클래스를 이용해 접근할 수 있습니다.


dbf 파일은 별다른 제약이 없고, 속성정보의 저장순서가 shp 파일에 기록되어 있는 공간정보의 저장순서와 같기만 하면 됩니다.



2. SHP Open


앞에서 SHP 포맷에 대한 간략한 분석을 마쳤습니다.


이제 이를 Open하는 과정을 실제 소스를 통해 분석해 보도록 합시다.


어제 소스 중


 fseek(fpSHX, 24L, SEEK_SET);
 fread(&tmp, 4, 1, fpSHX);
 SwapWord(4, &tmp);  
 int m_nFileSize = tmp * 2;

 m_nRecords = (m_nFileSize - 100)/8;

 

에 대해 살펴봅시다.


SHP 포맷이 몇개의 레코드를 가지고 있는지를 계산하는 루틴입니다.


fpSHX란 shx 파일을 연 파일 포인터입니다.

여기서 24번째 BYTE부터 4byte를 읽어들인 후 이를 Big Endian에서 Little Endian으로 변경합니다. (tmp)

Big Endian은 주로 UNIX 계열에서 사용하는 Byte Ordering이며, Intel계열에서는 Little Endian을 사용합니다.

따라서 Windows환경에서 값을 정확하게 받아들이기 위해서는 이를 변환해야만 하는 것입니다. 그런 후 이값에 대해 2를 곱했습니다. (m_nFileSize)

이는 File Length가 Byte 단위가 아닌 word 단위로 기록되어 있기 때문입니다. Byte 단위로 포인팅하기 위함입니다.


레코드의 개수를 구하기 위해 간단한 산수를 합니다. 전체 shx의 파일 사이즈에서 File Header인 100byte를 빼면 나머지는 8byte씩의 record의 모임입니다. 따라서 File Length에서 100byte를 뺀 후 8로 나누면 레코드의 개수가 나오는 것입니다.


다른 방법으로 레코드의 개수를 구할 수 있지만, 이 방법이 가장 간단한 것 같습니다.


 // get shp type
 fseek(fpSHP, 32L, SEEK_SET);
 fread(&m_nShapeType, 4, 1, fpSHP);

 

이제 shp파일에 대한 파일포인터를 사용하는 fpSHP를 이용합니다. 여기서는 32byte부터 4byte를 읽어들여  SHP의 타입을 읽어들입니다. 여기서부터는 또 little endian인 관계로 byte ordering을 바꾸지 않아도 됩니다. 왜 자꾸 byte ordering이 바뀌는지는 저도 잘 모르겠습니다. ESRI의 마음이겠죠 뭐... ^^;


 // get a MBR
 fread(&m_MBR, sizeof(MBR), 1, fpSHP);

 

여기서는 MBR(Minimum Bounding Rectangle)을 읽어들입니다. double 4개로 이루어진 것입니다. 3차원 SHP는 Z값에 대해서도 값을 가지고 있습니다만 2차원 SHP에는 나머지 값들이 모두 0.0으로 기록되어 있습니다. MBR에 대한 struct는 common.h에 제가 정의해 놓았습니다.


MBR

{

       double xmin;

       double ymin;

       double xmax;

       double ymax;

}

 

이로서 shp 파일의 헤더에 있는 모든 정보를 읽어들인 것입니다. 다음 번에는 포인트, 아크, 폴리곤, 멀티포인트를 읽는 것에 대해 설명하도록 하겠습니다.


궁금한 점이 있으면 본 게시판을 통해 질문해 주시기 바랍니다.


2001년 11월 15일

Posted by 뚜와띠엔
,