logo资料库

读取shp文件中数据.doc

第1页 / 共21页
第2页 / 共21页
第3页 / 共21页
第4页 / 共21页
第5页 / 共21页
第6页 / 共21页
第7页 / 共21页
第8页 / 共21页
资料共21页,剩余部分请下载后查看
读写shpapefile文件
读写 shpapefile 文件 Shape files 数据说明 Shape files 是 ESRI 提供的一种矢量数据格式,它没有拓扑信息,一个 Shape files 由 一组文件组成,其中必要的基本文件包括坐标文件( .shp )、索引文件( .shx )和属性 文件( .dbf )三个文件。 坐标文件的结构说明 坐标文件 (.shp) 用于记录空间坐标信息。它由头文件和实体信息两部分构成(如图 2.1 所 示)。 坐标文件的文件头 坐标文件的文件头是一个长度固定 (100 bytes) 的记录段,一共有 9 个 int 型和 7 个 double 型数据,主要记录内容见表 2.2 。 文件头 ---------------------- 记录头 记录内容 记录头 记录内容 记录头 记录内容 记录头 记录内容 图 2.1 坐标文件的结构 起始位置 名称 数值 类型 位序 ----------------------------------------- 0 File Code 9994 Integer big 4 Unused 0 Integer big 8 Unused 0 Integer big 12 Unused 0 Integer big 16 Unused 0 Integer big 20 Unused 0 Integer big 24 文件长度 文件的实际长度 Integer big 28 版本号 1000 Integer Little 32 几何类型 表示这个 Shapefile 文件所记录的空间数据的几何类型 Integer Little 36 Xmin 空间数据所占空间范围的 X 方向最小值 Double Little
44 Ymin 空间数据所占空间范围的 Y 方向最小值 Double Little 52 Xmax 空间数据所占空间范围的 X 方向最大值 Double Little 60 Ymax 空间数据所占空间范围的 Y 方向最大值 Double Little 68* Zmin 空间数据所占空间范围的 Z 方向最小值 Double Little 76* Zmax 空间数据所占空间范围的 Z 方向最大值 Double Little 84* Mmin 最小 Measure 值 Double Little 92* Mmax 最大 Measure 值 Double Little 注:最后 4 个加星号特别标示的四个数据只有当这个 Shapefile 文件包含 Z 方向 坐标或 者具有 Measure 值时才有值,否则为 0.0 。所谓 Measure 值,是用于存储需要的 附加数 据,可以用来记录各种数据,例如权值、道路长度等信息。 位序 细心的读者会注意到表 2.2 中的数值的位序有 Little 和 big 的区别,对于位序是 big 的数据我们在读取时要小心。通常,数据的位序都是 Little ,但在有些情况下可能会是 big ,二者的区别在于它们位序的顺序相反。一个位序为 big 的数据,如果我们想得到它 的真实数值,需要将它的位序转换成 Little 即可。转换原理非常简单,就是交换字节顺序, 下面是作者实现的在两者间进行转换的程序,代码如下: // 位序转换程序 unsigned long OnChangeByteOrder (int indata) { char ss[8]; char ee[8]; unsigned long val = unsigned long(indata); _ultoa( val, ss, 16 );// 将十六进制的数 (val) 转到一个字符串 (ss) 中 int i; int length=strlen(ss); if(length!=8) { for(i=0;i<8-length;i++) ee='0'; for(i=0;i
int t; t =ss[0]; ss[0] =ss[6]; ss[6] t =t; =ss[1]; ss[1] =ss[7]; ss[7] t =t; =ss[2]; ss[2] =ss[4]; ss[4] t =t; =ss[3]; ss[3] =ss[5]; ss[5] ////****** =t; //****** 将存有十六进制数 (val) 的字符串 (ss) 中的十六进制数转成十进制数 int value=0; for(i=0;i<8;i++) { int k; CString mass; mass=ss; if(ss=='a' || ss=='b' || ss=='c' || ss=='d' || ss=='e' || ss=='f') k=10+ss-'a'; else sscanf(mass,"%d",&k); value=value+int(k*pow(16,7-i)); } return (value); }
Shapefile 文件支持的几何类型( ShapeType ) Shapefile 文件所支持的几何类型如表 2.3 所示: 编号 几何类型 0 Null Shape (表示这个 Shapefile 文件不含坐标) 1 Point (表示 Shapefile 文件记录的是点状目标,但不是多点) 3 PolyLine (表示 Shapefile 文件记录的是线状目标) 5 Polygon (表示 Shapefile 文件记录的是面状目标) 8 MultiPoint (表示 Shapefile 文件记录的是多点,即点集合) 11 PointZ (表示 Shapefile 文件记录的是三维点状目标) 13 PolyLineZ (表示 Shapefile 文件记录的是三维线状目标) 15 PolygonZ (表示 Shapefile 文件记录的是三维面状目标) 18 MultiPointZ (表示 Shapefile 文件记录的是三维点集合目标) 21 PointM (表示含有 Measure 值的点状目标) 23 PolyLineM (表示含有 Measure 值的线状目标) 25 PolygonM (表示含有 Measure 值的面状目标) 28 MultiPointM (表示含有 Measure 值的多点目标) 31 MultiPatch (表示复合目标) 表 2.3shapefiles 文件支持的几何类型 对于一个不是记录 Null Shape 类型的 Shapefile 文件,它所记录的空间目标的几何类型 必须一致,不能在一个 Shapefile 文件中同时记录两种不同类型的几何目标。 读取坐标文件( .shp )的文件头的代码 如下: void OnReadShp ( CString ShpFileName ) { FILE* m_ShpFile_fp; //****Shp 文件指针 // 打开坐标文件 if((m_ShpFile_fp=fopen(ShpFileName,"rb"))==NULL) { return; } // 读取坐标文件头的内容开始 int FileCode; int Unused; int FileLength; int Version; int ShapeType;
double Xmin; double Ymin; double Xmax; double Ymax; double Zmin; double Zmax; double Mmin; double Mmax; fread(&FileCode, sizeof(int), 1,m_ShpFile_fp); FileCode = OnChangeByteOrder(FileCode); for(i=0;i<5;i++) fread(&Unused,sizeof(int), 1,m_ShpFile_fp); sizeof(int), 1,m_ShpFile_fp); = OnChangeByteOrder(FileLength); fread(&FileLength, FileLength fread(&Version, fread(&ShapeType, fread(&Xmin, fread(&Ymin, fread(&Xmax, fread(&Ymax, fread(&Zmin, fread(&Zmax, fread(&Mmin, fread(&Mmax, sizeof(int), 1,m_ShpFile_fp); sizeof(int), 1,m_ShpFile_fp); sizeof(double),1,m_ShpFile_fp); sizeof(double),1,m_ShpFile_fp); sizeof(double),1,m_ShpFile_fp); sizeof(double),1,m_ShpFile_fp); sizeof(double),1,m_ShpFile_fp); sizeof(double),1,m_ShpFile_fp); sizeof(double),1,m_ShpFile_fp); sizeof(double),1,m_ShpFile_fp); // 读取坐标文件头的内容结束 // 根据几何类型读取实体信息 } 实体信息的内容 实体信息负责记录坐标信息,它以记录段为基本单位,每一个记录段记录一个地理实体目标 的坐标信息,每个记录段分为记录头和记录内容两部分。 记录头的内容包括记录号( Record Number )和坐标记录长度 (Content Length) 两 个记录项。它们的位序都是 big 。记录号( Record Number )和坐标记录长度 (Content Length) 两个记录项都是 int 型,并且 shapefile 文件中的记录号都是从 1 开始的。 记录内容包括目标的几何类型( ShapeType )和具体的坐标记录 (X 、 Y) ,记录内容因 要素几何类型的不同其具体的内容及格式都有所不同。下面分别介绍点状目标( Point )、 线状目标( PolyLine )和面状目标( Polygon )三种几何类型的 .shp 文件的记录内容:
shapefile 中的点状目标由一对 X 、 Y 坐标构成,坐标值为双精度型( double )。点状 点状目标 目标的记录内容如表 2.4 : 记录项 数值 数据类型 长度 个数 位序 几何类型( ShapeType ) 1 (表示点状目标) int 型 4 1 Little X 方向坐标 X 方向坐标值 double 型 8 1 Little Y 方向坐标 Y 方向坐标值 double 型 8 1 Little 下面是 读取点状目标的记录内容的代码: OnReadPointShp(CString ShpFileName) { // 打开坐标文件 …… // 读取坐标文件头的内容开始 …… // 读取点状目标的实体信息 int RecordNumber; int ContentLength; int num =0; while((fread(&RecordNumber, sizeof(int), 1,ShpFile_fp)!=0)) num++; fread(&ContentLength,sizeof(int), 1,ShpFile_fp); RecordNumber = OnChangeByteOrder(RecordNumber); ContentLength = OnChangeByteOrder(ContentLength); int shapeType; double x; double y; fread(&shapeType, sizeof(int), 1,ShpFile_fp); fread(&x, sizeof(double), 1,ShpFile_fp); fread(&y, sizeof(double), 1,ShpFile_fp); } } 线状目标 shapefile 中的线状目标是由一系列点坐标串构成,一个线目标可能包括多个子线段,子线
段之间可以是相离的,同时子线段之间也可以相交。 Shapefile 允许出现多个坐标完全相 同的连续点,当读取文件时一定要注意这种情况,但是不允许出现某个退化的、长度为 0 的 子线段出现。线状目标的记录内容如表 2.5 : 记录项 数值 数据类型 长度 个数 位序 几何类型( ShapeType ) 3 (表示线状目标) int 型 4 1 Little 坐标范围( Box ) 表示当前线目标的坐标范围 double 型 32 4 Little 子线段个数( NumParts ) 表示构成当前线目标的子线段的个数 int 型 4 1 Little 坐标点数( NumPoints ) 表示构成当前线目标所包含的坐标点个数 int 型 4 1 Little Parts 数组 记录了每个子线段的坐标在 Points 数组中的起始位置 int 型 4×NumParts Points 数组 记录了所有的坐标信息 Point 型 根据点个数来确定 NumPoints Little NumParts Little 表 2.5 线状目标的记录内容 具体的数据结构如下: PolyLine { Box 坐标范围 // 当前线状目标的 NumParts // 当前线目标所包含的子 线段的个数 NumPoints // 当前线目标所包含的顶点个 数 Double[4] Integer Integer Integer[NumParts] Parts // 每个子线段的第一个坐标点在 Point[NumPoints] Points // 记录所有坐标点的数组 Points 的位置 } 这些记录项的具体含义如下: Box 记录了当前的线目标的坐标范围,它是一个 double 型的数组,按照 Xmin 、 Ymin 、 Xmax 、 Ymax 的顺序记录了坐标范围; NumParts 记录了当前线目标所包含的子线段的个数; NumPoints 记录了当前线目标的坐标点总数; Parts 记录了每个子线段的第一个坐标点在坐标数组 points 中的位置,以便读取数据; Points 是用于存放当前线目标的 X 、 Y 坐标的数组。 下面是读取线状目标的记录内容的代码: OnReadLineShp(CString ShpFileName) { // 打开坐标文件
…… // 读取坐标文件头的内容开始 …… // 读取线状目标的实体信息 int RecordNumber; int ContentLength; int num =0; while((fread(&RecordNumber, sizeof(int), 1,ShpFile_fp)!=0)) { fread(&ContentLength,sizeof(int), 1,ShpFile_fp); RecordNumber = OnChangeByteOrder (RecordNumber); ContentLength = OnChangeByteOrder (ContentLength); int shapeType; double Box[4]; int NumParts; int NumPoints; int *Parts; fread(&shapeType, sizeof(int), 1,ShpFile_fp); // 读 Box for(i=0;i<4;i++) fread(Box+i, sizeof(double),1,ShpFil e_fp); // 读 NumParts 和 NumPoints fread(&NumParts, sizeof(int), 1,ShpFile_fp); fread(&NumPoints, sizeof(int), 1,ShpFile_fp); // 读 Parts 和 Points Parts = new int[NumParts]; for(i=0;i
分享到:
收藏