C语言写的SHAPEFILE

合集下载

纯C#读取SHAPEFILE

纯C#读取SHAPEFILE

综合性实验报告一、实验名称:Shapefile文件的读写二、实验目的:能够熟悉基本的原理,掌握基本技能,并能综合运用课程所学的基本知识和技能解决实践中的问题。

根据此目标,特设计本综合性实验,作为该课程的完整组成部分。

为后续课程有的放矢地开展与安排提供参考。

三、实验准备(数据与软件):开发环境安装:开发环境采用Visual studio ,开发语言为C#相关文档阅读:教材《C#程序设计》教程,孙践知等编著,清华大学出版社;实验指导书自编;ESRI公开的Shapefile白皮书《ESRI Shapefile Technical Description》;IBM公开的DBF文件格式。

四、实验原理(方法):一个.shp文件由文件头和记录组成。

文件头大小为100个字节,其布局如下表:* Unused, with value 0.0, if not Measured or Z typeBig表示大尾(big endian)型字节顺序,即是高低位字节是反序的,主要适用于Sun® or Motorola®平台,而Little表示小尾(little endian)型字节顺序,高低位字节顺序不变,主要使用在PC or Intel®平台。

在读取的字节为Big时,需要进行字节顺序交换,才能得出正确的值。

一个把Big顺序转换为Little顺序的函数可以如下:int Big2LittleEndian(int num){int reverse; //返回结果char bit0, bit1, bit2, bit3;bit0 = (num & 0x000000ff);bit1 = (num & 0x0000ff00) >> 8;bit2 = (num & 0x00ff0000) >> 16;bit3 = (num & 0xff000000) >> 24;reverse = (bit0 << 24) | (bit1 << 16) | (bit2 << 8) | (bit3);return reverse;}文件头中第32-35位字节为一个整型,其值反映了shapefile的图形对象类型,具体值对应含义如下:第36-67个字节包含了图幅的范围大小。

shapefile包的用法

shapefile包的用法

shapefile包的用法Shapefile是一种常用的地理信息系统(GIS)数据格式,用于存储地理空间数据。

它由三个主要文件组成,包括.shp、.shx和.dbf文件,这些文件分别存储空间几何信息、索引信息和属性数据。

Shapefile包是一个用于读取和处理Shapefile文件的Python库。

它提供了一系列函数和类,可用于加载、浏览和操作Shapefile数据。

以下是Shapefile包的常见用法:1.安装Shapefile包:可以使用命令`pip install pyshp`来安装Shapefile包。

2.导入Shapefile包:在Python脚本中,使用`importshapefile`语句来导入Shapefile包。

3.打开Shapefile文件:使用`shapefile.Reader()`函数打开Shapefile文件,例如:`sf = shapefile.Reader("file.shp")`。

4.访问Shapefile的空间几何信息:使用`.shapes()`方法获取Shapefile的几何信息,例如:`shapes = sf.shapes()`。

5.访问Shapefile的属性数据:使用`.records()`方法获取Shapefile的属性数据,例如:`records = sf.records()`。

6.遍历Shapefile的空间几何信息和属性数据:可以使用循环来遍历Shapefile的空间几何信息和属性数据,例如:```pythonfor shape in shapes:#处理空间几何信息# ...for record in records:#处理属性数据# ...```7.获取Shapefile的字段信息:使用`.fields`属性获取Shapefile的字段信息,例如:`fields = sf.fields`。

8.获取Shapefile的坐标系:使用`.crs`属性获取Shapefile的坐标系信息,例如:`crs = sf.crs`。

资料:shapefile(中文版)

资料:shapefile(中文版)

ESRI shapefile 技术手册本技术手册规定了shapefile空间数据格式,阐述了为什么是一种比较重要的数据格式。

同时本技术手册还列出了直接创建shapefile数据的ESRI工具和从其它数据格式向shapefile 格式转换的软件。

对一些希望通过自己开发程序来完成数据转换或者创建shapefile格式的数据的组织来说,这份技术说明同样提供了所需的所有技术支持。

什么是shapefile?Shapefile把空间对象的非拓扑地理数据和属性信息存储在一个数据集里面。

由于其不包含拓扑结构数据结构,因此相比于其它的数据格式,具有更易于图形输出与编辑的能力。

Shapefile更易于处理单要素图形,此外shapefile还具有需要较少的磁盘储存空间与易于读写的优点。

Shapefile支持点、线、面状要素;面状要素以闭合的多线,即多边形的边界存储。

属性要素以dBASE格式记录。

且每一个属性值与相关的形记录有一对一的关系。

如何创建shapefile?可以通过以下方式创建shapefile:导入---使用ARC/INFO、PC ARC/INFO,、Spatial Database Engine(SDE)、Arc View GIS,或者是Business MAP等软件,由已有的数据源创建。

数字化---由ArcView的地理信息要素创建工具直接数字化得到。

编程---使用Avenue™ (ArcView GIS), MapObjects™, ARC Macro Language (AML™)(ARC/INFO),或者简单的宏命令,自行创建shapefile.直接生成----通过特定的程序直接生成shapefile文件。

SDE、ARC/INFO、PC ARC/INFO、Data Automation Kit (DAK), 和Arc CAD这些软件可以把shapefile格式的文件转化为coverage的文件格式,ARC/INFO还可以把coverage格式转化为shapefile 文件格式,在这份文件中详细地说明了shapefile数据与其他形式数据的转化过程。

C#读取shapefile文件

C#读取shapefile文件

C#读取shapefile文件C#读取shapefile文件using System;using System.Collections.Generic;using System.Text;using System.IO;using System.Data.Odbc; //add by hand,which is needed when load the layer attribute informationusing System.Data.OleDb;using System.Collections;using System.Data;using System.Xml;namespace CGCL.CGFiles{public class CGShapeFileParser{public class ESRI_ShxHeader{int FileCode; //9994int[] Unused2 = new int[5];int FileLength;int Version; //1000int ShapeType; // 0- Null shape// 1- Point// 3-Arc// 5-Polygon// 8-MultiPointdouble XMin;double YMin;double XMax;double YMax;int[] Unused3 = new int[8];}class ESRI_ShapeFile{int FileCode; //9994int[] Unused = new int[5];int FileLength;int Version; //1000int ShapeType; // 0- Null shape // 1- Point// 3-Arc// 5-Polygon// 8-MultiPointdouble XMin;double YMin;double XMax;double YMax;int[] Unused1 = new int[8];}class ESRI_RecordHeader {int RecNumber;int ContentLength;}class ESRI_PointContent {int ShapeType;double X;double Y;}class ESRI_IndexRec//索引文件{int Offset;int ContentLen;}class ESRI_ArcContent{int ShapeType;double xmin;double ymin;double xmax;double ymax;int NumParts;int NumPoints;}class ESRI_PolygonContent{int ShapeType;double xmin;double ymin;double xmax;double ymax;int NumParts;int NumPoints;}public bool LoadShapeFile(CGDataAdapter.CGLocalGeoDataAdapter adapter) {string connectionString;OdbcConnection connection;OdbcDataAdapter OdbcAdapter;CGMap.CGGeoLayer geolayer = adapter.getMasterGeoLayer();string shpfilepath = adapter.getPath();string shpfilename = adapter.getFileName();string shxfilepath = shpfilepath.Substring(0, stIndexOf("\\") + 1) + adapter.getFileName() + ".shx";//read out the layer attribute infomationconnectionString = "Dsn=Visual FoxProDatabase;sourcedb=" + shpfilepath + ";sourcetype=DBF;exclusive=No;backgroundfetch=Yes;collate= Machine";connection = new OdbcConnection(connectionString);connection.Open();OdbcAdapter = new OdbcDataAdapter("select * from " + shpfilename, connectionString);// Create new DataTable and DataSource objects.DataSet ds = new DataSet();OdbcAdapter.Fill(ds);connection.Close();if (geolayer == null) return false;try{//先读取.shx文件,得到文件的总字节长度FileStream fs = new FileStream(shxfilepath, FileMode.Open, FileAccess.Read); //文件流形式BinaryReader BinaryFile = new BinaryReader(fs); //二进制读取文件的对象long BytesSum = fs.Length; //得到文件的字节总长int shapecount = (int)(BytesSum - 100) / 8; //得以总记录数目BinaryFile.Close();fs.Close();//打开shp文件if (shxfilepath == ""){// MessageBox.Show("索引文件打开出错");return false;}//打开.shp文件,读取x,y坐标的信息fs = new FileStream(shpfilepath, FileMode.Open, FileAccess.Read); //文件流形式BinaryFile = new BinaryReader(fs); //打开二进制文件BinaryFile.ReadBytes(32); //先读出36个字节,紧接着是Box边界合int shapetype = BinaryFile.ReadInt32();geolayer.envlope.left = BinaryFile.ReadDouble(); //读出整个shp图层的边界合geolayer.envlope.bottom = BinaryFile.ReadDouble();geolayer.envlope.right = BinaryFile.ReadDouble();geolayer.envlope.top = BinaryFile.ReadDouble();BinaryFile.ReadBytes(32); // shp中尚未使用的边界盒//Get Shape Data From Here Onint stype;double x, y;double left, right, top, bottom;int partcount;int pointcount;switch (shapetype){case 1://single pointgeolayer.shapeType = CGConstants.CGShapeType.SHAPE_POINT;for (int i = 0; i < shapecount; i++){CGGeoShape.CGGeoPoint gps = new CGGeoShape.CGGeoPoint();BinaryFile.ReadBytes(12); //记录头8个字节和一个int(4个字节)的shapetype/* stype = BinaryFile.ReadInt32();if (stype != shapetype)continue;*/x = BinaryFile.ReadDouble();y = BinaryFile.ReadDouble();gps.objectID = i;gps.objectUID = i;gps.x = x;gps.y = y;gps.z = 0;gps.envlope.left = gps.x;gps.envlope.right = gps.x;gps.envlope.top = gps.y;gps.envlope.bottom = gps.y;geolayer.getDataContainer().Add(gps);}break;case 8://multi points layerbreak;case 3://Polyline layergeolayer.shapeType = CGConstants.CGShapeType.SHAPE_LINE;for (int i = 0; i < shapecount; i++){geolayer.getAttributeContainer().Add(ds.Tables[0].Rows[i][0] ); //read out the attribute step by stepBinaryFile.ReadBytes(12);// int pos = indexRecs[i].Offset+8;// bb0.position(pos);// stype = bb0.getInt();// if (stype!=nshapetype){// continue;// }left = BinaryFile.ReadDouble();bottom = BinaryFile.ReadDouble();right = BinaryFile.ReadDouble();top = BinaryFile.ReadDouble();partcount = BinaryFile.ReadInt32(); pointcount = BinaryFile.ReadInt32();int[] parts = new int[partcount];int[] partspos = new int[partcount];double[] xpoints = new double[pointcount]; double[] ypoints = new double[pointcount]; double[] zpoints = new double[pointcount];//firstly read out parts begin pos in filefor (int j = 0; j < partcount; j++){parts[j] = BinaryFile.ReadInt32();}//shift them to be points count included in parts if (partcount > 0)partspos[0] = 0;int newpos = 0;for (int j = 0; j <= partcount - 2; j++){parts[j] = parts[j + 1] - parts[j];newpos += parts[j];partspos[j + 1] = newpos;}parts[partcount - 1] = pointcount - parts[partcount - 1];//read out coordinatesfor (int j = 0; j < pointcount; j++){x = BinaryFile.ReadDouble();y = BinaryFile.ReadDouble();xpoints[j] = x;ypoints[j] = y;zpoints[j] = 0;}if (pointcount > 1){CGGeoShape.CGGeoLine gl = new CGGeoShape.CGGeoLine(xpoints, ypoints, zpoints, parts, partspos, pointcount, partcount);gl.envlope.left = left;gl.envlope.right = right;gl.envlope.top = top;gl.envlope.bottom = bottom;gl.objectID = i;gl.objectUID = i;geolayer.getDataContainer().Add(gl);}}break;。

C语言shape文件读取

C语言shape文件读取

读取数据
//读取之前分配了存储空间的Parts和points数据
将结构体中 用不到的变 量级指针置 空
心得体会
• 这次试验的关键点之一是要读出存储的文件数。因此我们选用 了指针跳动的方式来完成。 • 在试验过程中通过探索、试验,我们找到了用feof(file)不能判 断文件尾的原因,以及解决方法。
读 取 文 件 头
这部分数据 在文件中采 取大端存储, 从文件中读 出后要进行 位序转换才 能得到正确 数值
实验目的
判断数据类型及记录数并分配内存空间
判断记录数 循环每做一 次记录数加 一
读取数据
判断文件 尾
这里不能使用feof(file)即【 while(feof(file)==0)】 的方式来判断文件尾!因为即使已经到达了文 件尾,但file->flag仍然没有被置为_IOEOF,因 而feof()仍然没有探测到文件结尾
Shapefile文件的读取
Hale Waihona Puke 实验目的• 读取包含常规点、线、面矢量数据的.shp 文件,掌握 .shp文件的基本存储结构,并 以此为基础深入理解shapefile的矢量数据 结构。
Shapefile文件格式
每条记录长度:(8+记录长度*2字节)
文件头
信息记录
基本识 别信息
空间信 息概况
几何体空间坐标记录
100字节
记录头 shapeType 共8字节 4字节
实验方案
1 2 3 4
读文件头
判断有多少条记录 分配内存空间
读取数据
文件头说明: FileCode(文件代码=9994) 5个unused FileLength 整个文件的长度(包括文件头,以16字节为单位) FileVersion 文件版本=10

shapefile格式说明及读写代码示例

shapefile格式说明及读写代码示例

shapefile格式说明及读写代码示例Shape files数据说明Shape files是ESRI提供的一种矢量数据格式,它没有拓扑信息,一个Shape files由一组文件组成,其中必要的基本文件包括坐标文件(.shp)、索引文件(.shx)和属性文件(.dbf)三个文件。

坐标文件的结构说明坐标文件(.shp)用于记录空间坐标信息。

它由头文件和实体信息两部分构成(如图2.1所示)。

坐标文件的文件头坐标文件的文件头是一个长度固定(100 bytes)的记录段,一共有9个int型和7个double型数据,主要记录内容见表2.2。

表2.2shapefiles 头文件表注:最后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[i]='0';for(i=0;i<length;i++)ee[i+8-length]=ss[i];for(i=0;i<8;i++)ss[i]=ee[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[i];if(ss[i]=='a' ||ss[i]=='b' ||ss[i]=='c' ||ss[i]=='d' ||ss[i]=='e' ||ss[i]=='f')k=10+ss[i]-'a';elsesscanf(mass,"%d",&k);value=value+int(k*pow(16,7-i));}return (value);}Shapefile文件支持的几何类型(ShapeType)Shapefile文件所支持的几何类型如表2.3所示:表2.3shapefiles文件支持的几何类型对于一个不是记录Null Shape类型的Shapefile文件,它所记录的空间目标的几何类型必须一致,不能在一个Shapefile文件中同时记录两种不同类型的几何目标。

shapefile包的用法 -回复

shapefile包的用法 -回复

shapefile包的用法-回复Shapefile是一种经常被使用的地理信息系统(GIS)文件格式,它可以用来存储和传输地理位置、空间对象和属性信息。

它由几个文件组成,包括.shp、.shx、.dbf和.prj文件。

这篇文章将一步一步地介绍如何使用shapefile包来读取、创建和编辑shapefile文件。

第一步:安装shapefile包首先,在Python环境中安装shapefile包。

可以使用以下命令在终端或命令提示符中安装:pip install pyshp安装完成后,你就可以在Python程序中使用shapefile包了。

第二步:导入shapefile包在Python程序的开头,导入shapefile包:pythonimport shapefile第三步:读取shapefile文件使用以下代码来读取一个shapefile文件:pythonsf = shapefile.Reader("path/to/shapefile.shp")这将创建一个`ShapefileReader`对象,用于读取shapefile文件的几何形状、属性以及其他相关信息。

第四步:访问shapefile的几何对象和属性可以使用以下代码来访问shapefile中的几何对象和属性:pythonshapes = sf.shapes() # 获取所有几何形状records = sf.records() # 获取所有属性记录通过迭代遍历这些几何形状和属性记录,可以获取每个几何形状的坐标和每个属性记录的值:pythonfor shape in shapes:points = shape.points # 获取几何形状的坐标列表# 处理坐标数据...for record in records:attributes = record.attributes # 获取属性记录的值# 处理属性数据...第五步:创建shapefile文件shapefile包还允许创建新的shapefile文件并添加几何对象和属性。

C#读取shapefile文件

C#读取shapefile文件

C#读取shapefile文件(不用AE)1.创建工程文件,选窗体应用程序,命名为:EsriShpReader2.添加SplitContainer控件到窗体3.在SplitContainer.panel1中添加两个按钮Button,text属性分别改为“打开”,“刷新”4. 在SplitContainer.panel2中添加panel容器,用来显示图像Dock设置为Fill,背景颜色设置为白色5.界面图如下:6.在过程文件中添加类文件,命名为ShpClass编写点、线、面、三个类class Point//点类{public double X;public double Y;}class Polyline//线类{public double[] Box=new double[4];public int NumParts;public int NumPoints;public ArrayList Parts; //在部分中第一个点的索引public ArrayList Points; //所有部分的点}class Polygon : Polyline//面类{ }7.在Form1中添加ArrayList polygons = new ArrayList();//面集合ArrayList polylines = new ArrayList();//线集合ArrayList points = new ArrayList();//点集合Pen pen = new Pen(Color.Black, 1);//定义画笔int ShapeType;//shp文件类型int count;//计数double xmin, ymin, xmax, ymax;double n1, n2;//x,y轴放大倍数8.添加button1的Click事件,添加代码string shpfilepath = "";openFileDialog1.Filter = "shapefiles(*.shp)|*.shp|All files(*.*)|*.*";//打开文件路径if (openFileDialog1.ShowDialog() == DialogResult.OK){shpfilepath = openFileDialog1.FileName;BinaryReader br = new BinaryReader(openFileDialog1.OpenFile());//读取文件过程br.ReadBytes(24);int FileLength = br.ReadInt32();//<0代表数据长度未知int FileBanben = br.ReadInt32();ShapeType = br.ReadInt32();xmin = br.ReadDouble();ymax = -1 * br.ReadDouble();xmax = br.ReadDouble();ymin = -1 * br.ReadDouble();double width = xmax - xmin;double height = ymax - ymin;n1 = (float)(this.panel1.Width * 0.9 / width);//x轴放大倍数n2 = (float)(this.panel1.Height * 0.9 / height);//y轴放大倍数br.ReadBytes(32);switch (ShapeType){case 1:points.Clear();while (br.PeekChar() != -1){Point point = new Point();uint RecordNum = br.ReadUInt32();int DataLength = br.ReadInt32();//读取第i个记录br.ReadInt32();point.X = br.ReadDouble();point.Y = -1 * br.ReadDouble();points.Add(point);}StreamWriter sw = new StreamWriter("point.txt");foreach (Point p in points){sw.WriteLine("{0},{1},{2} ", p.X, -1 * p.Y, 0);}sw.Close();break;case 3:polylines.Clear();while (br.PeekChar() != -1){Polyline polyline = new Polyline();polyline.Box = new double[4];polyline.Parts = new ArrayList();polyline.Points = new ArrayList();uint RecordNum = br.ReadUInt32();int DataLength = br.ReadInt32();//读取第i个记录br.ReadInt32();polyline.Box[0] = br.ReadDouble();polyline.Box[1] = br.ReadDouble();polyline.Box[2] = br.ReadDouble();polyline.Box[3] = br.ReadDouble();polyline.NumParts = br.ReadInt32();polyline.NumPoints = br.ReadInt32();for (int i = 0; i < polyline.NumParts; i++) {int parts = new int();parts = br.ReadInt32();polyline.Parts.Add(parts);}for (int j = 0; j < polyline.NumPoints; j++){Point pointtemp = new Point();pointtemp.X = br.ReadDouble();pointtemp.Y = -1 * br.ReadDouble();polyline.Points.Add(pointtemp);}polylines.Add(polyline);}StreamWriter sw2 = new StreamWriter("line.txt");count = 1;foreach (Polyline p in polylines){for (int i = 0; i < p.NumParts; i++){int startpoint;int endpoint;if (i == p.NumParts - 1){startpoint = (int)p.Parts[i];endpoint = p.NumPoints;}else{startpoint = (int)p.Parts[i];endpoint = (int)p.Parts[i + 1];}sw2.WriteLine("线" + count.ToString() + ":");for (int k = 0, j = startpoint; j < endpoint; j++, k++){Point ps = (Point)p.Points[j];sw2.WriteLine(" {0},{1},{2} ", ps.X, -1 * ps.Y, 0);}count++;}}sw2.Close();break;case 5:polygons.Clear();while (br.PeekChar() != -1){Polygon polygon = new Polygon();polygon.Parts = new ArrayList();polygon.Points = new ArrayList();uint RecordNum = br.ReadUInt32();int DataLength = br.ReadInt32();//读取第i个记录int m = br.ReadInt32();for (int i = 0; i < 4; i++){polygon.Box[i] = br.ReadDouble();}polygon.NumParts = br.ReadInt32();polygon.NumPoints = br.ReadInt32();for (int j = 0; j < polygon.NumParts; j++){int parts = new int();parts = br.ReadInt32();polygon.Parts.Add(parts);}for (int j = 0; j < polygon.NumPoints; j++){Point pointtemp = new Point();pointtemp.X = br.ReadDouble();pointtemp.Y = -1 * br.ReadDouble();polygon.Points.Add(pointtemp);}polygons.Add(polygon);}StreamWriter sw1 = new StreamWriter("polygon.txt");count = 1;foreach (Polygon p in polygons){for (int i = 0; i < p.NumParts; i++){int startpoint;int endpoint;if (i == p.NumParts - 1){startpoint = (int)p.Parts[i];endpoint = p.NumPoints;}else{startpoint = (int)p.Parts[i];endpoint= (int)p.Parts[i + 1];}sw1.WriteLine("多边形" + count.ToString() + ":");for (int k = 0, j = startpoint; j < endpoint; j++, k++){Point ps = (Point)p.Points[j];sw1.WriteLine(" {0},{1},{2} ", ps.X, -1 * ps.Y, 0);}count++;}}sw1.Close();break;}}9. 添加button2的Click事件,添加代码double width = xmax - xmin;//图像宽double height = ymax - ymin;//图像高n1 = (float)(this.panel1.Width * 0.9 / width);//x轴放大倍数n2 = (float)(this.panel1.Height * 0.9 / height);//y轴放大倍数this.panel1.Refresh();10.添加panel1的paint事件private void panel1_Paint(object sender, PaintEventArgs e){PointF[] point;switch (ShapeType){case 1://点类型foreach (Point p in points){PointF pp = new PointF();pp.X = (float)(10 + (p.X - xmin) * n1);pp.Y = (float)(10 + (p.Y - ymin) * n2);e.Graphics.DrawEllipse(pen, pp.X, pp.Y, 1.5f, 1.5f);break;case 3://线类型foreach (Polyline p in polylines){for (int i = 0; i < p.NumParts; i++){int startpoint;int endpoint;point = null;if (i == p.NumParts - 1){startpoint = (int)p.Parts[i];endpoint = p.NumPoints;}else{startpoint = (int)p.Parts[i];endpoint = (int)p.Parts[i + 1];}point = new PointF[endpoint - startpoint];for (int k = 0, j = startpoint; j < endpoint; j++, k++){Point ps = (Point)p.Points[j];point[k].X = (float)(10 + (ps.X - xmin) * n1);point[k].Y = (float)(10 + (ps.Y - ymin) * n2);}e.Graphics.DrawLines(pen, point);}break;case 5://面类型foreach (Polygon p in polygons){for (int i = 0; i < p.NumParts; i++){int startpoint;int endpoint;point = null;if (i == p.NumParts - 1){startpoint = (int)p.Parts[i];endpoint = p.NumPoints;}else{startpoint = (int)p.Parts[i];endpoint = (int)p.Parts[i + 1];}point = new PointF[endpoint - startpoint];for (int k = 0, j = startpoint; j < endpoint; j++, k++) {Point ps = (Point)p.Points[j];point[k].X = (float)(10 + (ps.X - xmin) * n1);point[k].Y = (float)(10 + (ps.Y - ymin) * n2);}e.Graphics.DrawPolygon(pen, point);}}break;}}11.编译运行。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

shapefile格式说明及读写代码示例08-04-08 11:50:49不详核心提示:Shape files 数据说明Shape files 是ESRI 提供的一种矢量数据格式,它没有拓扑信息,一个Shape files 由一组文件组成,其中必要的基记录内容包括目标的几何类型(ShapeType )和具体的坐标记录(X 、Y) ,记录内容因要素几何类型的不同其具体的内容及格式都有所不同。

下面分别介绍点状目标(Point )、线状目标(PolyLine )和面状目标(Polygon )三种几何类型的.shp 文件的记录内容:点状目标shapefile 中的点状目标由一对X 、Y 坐标构成,坐标值为双精度型(double )。

点状目标的记录内容如表2.4 :下面是读取点状目标的记录内容的代码: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 :具体的数据结构如下:PolyLine{Double[4] Box // 当前线状目标的坐标范围Integer NumParts // 当前线目标所包含的子线段的个数Integer NumPoints // 当前线目标所包含的顶点个数Integer[NumParts] Parts // 每个子线段的第一个坐标点在Points 的位置Point[NumPoints] 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); // 读Boxfor(i=0;i<4;i++)fread(Box+i, sizeof(double),1,ShpFile_fp); // 读NumParts 和NumPointsfread(&NumParts, sizeof(int), 1,ShpFile_fp);fread(&NumPoints, sizeof(int), 1,ShpFile_fp); // 读Parts 和PointsParts = new int[NumParts];for(i=0;i<NumParts;i++)fread(Parts+i, sizeof(int), 1,ShpFile_fp);int pointNum;for(i=0;i<NumParts;i++){if(i!=NumParts-1)pointNum =Parts[i+1]-Parts[i];elsepointNum =NumPoints-Parts[i];double *PointsX;double *PointsY;PointsX =new double[pointNum];PointsY =new double[pointNum];for(j=0;j<pointNum;j++){fread(PointsX+j, sizeof(double),1,ShpFile_fp);fread(PointsY+j, sizeof(double),1,ShpFile_fp);}delete[] PointsX;delete[] PointsY;}delete[] Parts;}}面状目标shapefile 中的面状目标是由多个子环构成,每个子环是由至少四个顶点构成的封闭的、无自相交现象的环。

对于含有岛的多边形,构成它的环有内外环之分,每个环的顶点的排列顺序或者方向说明了这个环到底是内环还是外环。

一个内环的顶点是按照逆时针顺序排列的;而对于外环,它的顶点排列顺序是顺时针方向。

如果一个多边形只由一个环构成,那么它的顶点排列顺序肯定是顺时针方向。

每条多边形记录的数据结构与线目标的数据结构完全相同,Polygon{Double[4] Box // 当前面状目标的坐标范围Integer NumParts // 当前面目标所包含的子环的个数Integer NumPoints // 构成当前面状目标的所有顶点的个数Integer[NumParts] Parts // 每个子环的第一个坐标点在Points 的位置Point[NumPoints] Points // 记录所有坐标点的数组}对于一个shapefile 中的多边形,它必须满足下面三个条件:构成多边形的每个子环都必须是闭合的,即每个子环的第一个顶点跟最后一个顶点是同一个点;每个子环在Points 数组中的排列顺序并不重要,但每个子环的顶点必须按照一定的顺序连续排列;存储在shapefile 中的多边形必须是干净的。

所谓一个干净的多边形,它必须满足两点:没有自相交现象。

这就要求任何一个子环不能跟其它的子环相交,共线的现象也将被当作相交。

但是允许两个子环的顶点重合;对于一个不含岛的多边形或者是含岛的多边形的外环,它们的顶点排列顺序必须是顺时针方向;而对于内环,它的排列顺序必须是逆时针方向。

所谓的“脏多边形”就是指顶点排列顺序为顺时针的内环。

图2.2 中的多边形是一个典型的例子。

这个多边形包括一个岛,所有顶点的个数为8 。

NumParts 等于2 ,NumPoints 等于10 。

请注意内环(岛)的顶点的排列顺序是逆时针的(如图2.3 所示)下面是读取面状目标的记录内容的代码:void OnReadAreaShp(CString ShpFileName){// 打开坐标文件……// 读取坐标文件头的内容开始……// 读取面状目标的实体信息int RecordNumber;int ContentLength;while((fread(&RecordNumber, sizeof(int), 1,m_ShpFile_fp)!=0)){fread(&ContentLength,sizeof(int), 1,m_ShpFile_fp);RecordNumber = OnChangeByteOrder (RecordNumber);ContentLength = OnChangeByteOrder (ContentLength);int shapeType;double Box[4];int NumParts;int NumPoints;int *Parts;fread(&shapeType, sizeof(int), 1,m_ShpFile_fp);// 读Boxfor(i=0;i<4;i++)fread(Box+i, sizeof(double),1,m_ShpFile_fp);// 读NumParts 和NumPointsfread(&NumParts, sizeof(int), 1,m_ShpFile_fp);fread(&NumPoints, sizeof(int), 1,m_ShpFile_fp);// 读Parts 和PointsParts =new int[NumParts];for(i=0;i<NumParts;i++)fread(Parts+i, sizeof(int), 1,m_ShpFile_fp);int pointNum;int xx;int yy;for(i=0;i<NumParts;i++){if(i!=NumParts-1)pointNum =Parts[i+1]-Parts[i];elsepointNum =NumPoints-Parts[i];double *PointsX;double *PointsY;PointsX =new double[pointNum];PointsY =new double[pointNum];for(j=0;j<pointNum;j++){fread(PointsX+j, sizeof(double),1,m_ShpFile_fp);fread(PointsY+j, sizeof(double),1,m_ShpFile_fp);}delete[] PointsX;delete[] PointsY;}delete[] Parts;}}属性文件的文件头其中文件头部分的长度是不定长的,它主要对DBF 文件作了一些总体说明(见表2.7 ),其中最主要的是对这个DBF 文件的记录项的信息进行了详细地描述,比如对每个记录项的名称、数据类型、长度等信息都有具体的说明。

相关文档
最新文档