对shapefile文件进行读写绘制实验报告概述.docx
《对shapefile文件进行读写绘制实验报告概述.docx》由会员分享,可在线阅读,更多相关《对shapefile文件进行读写绘制实验报告概述.docx(31页珍藏版)》请在冰豆网上搜索。
![对shapefile文件进行读写绘制实验报告概述.docx](https://file1.bdocx.com/fileroot1/2022-11/25/781195f6-eda8-4d0f-a3c9-242ea1ab1944/781195f6-eda8-4d0f-a3c9-242ea1ab19441.gif)
对shapefile文件进行读写绘制实验报告概述
综合性实验报告
专业地理信息系统年级11级学号201130670225姓名吴秀春
时间2013年7月4日
一、实验名称:
设计程序,实现对ESRI的Shapefile格式文件进行读取和绘制,并实现相应的地图(图形)浏览功能。
二、实验目的:
考察学生对于课程的基础知识掌握程度,以及检验学生综合运用所学课程知识和技能分析问题,解决问题的能力,为后续课程有的放矢地开展与安排提供参考。
三、实验准备(数据与软件):
1.开发环境和测试数据
开发环境采用Visualstudio2010.Net,开发语言为C#,实验测试数据为.shp类型文件
2.相关文档阅读:
ESRI公开的Shapefile白皮书《ESRIShapefileTechnicalDescription》;IBM公开的DBF文件格式。
四、实验原理(方法):
通过进行文件的操作,把.shp文件读取出来,并且通过变量把文件的信息记录下来,通过面向对象的方法,实现对图形的绘制操作,从而实现整一个实验的主要内容。
五、内容与步骤:
1、了解shapefile的文件组织形式,以及各个组成部分的数据结构
(1)一个.shp文件由文件头和记录组成。
文件头大小为100个字节,其布局如下表:
PositionFieldValueTypeOrder
Byte0FileCode9994IntegerBig
Byte4Unused0IntegerBig
Byte8Unused0IntegerBig
Byte12Unused0IntegerBig
Byte16Unused0IntegerBig
Byte20Unused0IntegerBig
Byte24FileLengthFileLengthIntegerBig
Byte28Version1000IntegerLittle
Byte32ShapeTypeShapeTypeIntegerLittle
Byte36BoundingBoxXminDoubleLittle
Byte44BoundingBoxYminDoubleLittle
Byte52BoundingBoxXmaxDoubleLittle
Byte60BoundingBoxYmaxDoubleLittle
Byte68*BoundingBoxZminDoubleLittle
Byte76*BoundingBoxZmaxDoubleLittle
Byte84*BoundingBoxMminDoubleLittle
Byte92*BoundingBoxMmaxDoubleLittle
*Unused,withvalue0.0,ifnotMeasuredorZtype
●注意其中的字节顺序,Big表示大尾(bigendian)型字节顺序,即是高低位字节是反序的,主要适用于Sun®orMotorola®平台,而Little表示小尾(littleendian)型字节顺序,高低位字节顺序不变,主要使用在PCorIntel®平台。
在读取的字节为Big时,需要进行字节顺序交换,才能得出正确的值。
一个把Big顺序转换为Little顺序的函数可以如下:
intBig2LittleEndian(intnum)
{
intreverse;//返回结果
charbit0,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);
returnreverse;
}
●文件头中第32-35位字节为一个整型,其值反映了shapefile的图形对象类型,具体值对应含义如下:
ValueShapeType
0NullShape
1Point
3PolyLine
5Polygon
8MultiPoint
11PointZ
13PolyLineZ
15PolygonZ
18MultiPointZ
21PointM
23PolyLineM
25PolygonM
28MultiPointM
31MultiPatch
●第36-67个字节包含了图幅的范围大小。
(2)、每条记录由记录头和实体内容组成,记录头格式固定,具体组成如下所示:
PositionFieldValueTypeByteOrder
Byte0RecordNumberRecordNumberIntegerBig
Byte4ContentLengthContentLengthIntegerBig
记录头包含8个字节,0-3表示记录的顺序号,4-7表示记录实体自身的大小。
实体的内容根据对象类型不同而变化,需根据具体情况处理。
关于Shapefile的.shx文件的说明
.shx文件由文件头和记录组成,文件头与前述.shp文件一致,但需注意FileLength字段的值不一样。
而每条记录由2个整型组成,具体内容如下:
PositionFieldValueTypeByteOrder
Byte0OffsetOffsetIntegerBig
Byte4ContentLengthContentLengthIntegerBig
其中,offset表示该条记录在.shp文件中的字节位置,而ContentLength说明了记录的大小。
关于.DBF文件的说明
标准的DBF文件,是由头文件和实体信息两部分构成(如图1所示)。
文件头
记录1
记录2
记录3
记录4
……
……
记录n
图1DBF文件的结构
(1)、文件头部分
文件头部分的长度是不定长的,它主要对DBF文件作了一些总体说明(表),其中最主要的是对这个DBF文件的记录项的信息进行了详细地描述,比如对每个记录项的名称、数据类型、长度等信息都有具体的说明。
在文件中的位置
内容
说明
0
1个字节
表示当前的版本信息
1-3
3个字节
表示最近的更新日期,按照YYMMDD格式。
4-7
1个32位数
文件中的记录条数。
8-9
1个16位数
文件头中的字节数。
10-11
1个16位数
一条记录中的字节长度。
12-13
2个字节
保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。
14
1个字节
表示未完成的操作。
15
1个字节
dBASEIV编密码标记。
16-27
12个字节
保留字节,用于多用户处理时使用。
28
1个字节
DBF文件的MDX标识。
在创建一个DBF表时,如果使用了MDX格式的索引文件,那么DBF表的表头中的这个字节就自动被设置了一个标志,当你下次试图重新打开这个DBF表的时候,数据引擎会自动识别这个标志,如果此标志为真,则数据引擎将试图打开相应的MDX文件。
29
1个字节
LanguagedriverID.
30-31
2个字节
保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。
32-X
(n*32)个字节
记录项信息描述数组。
n表示记录项的个数。
这个数组的结构在下表中有详细的解释。
X+1
1个字节
作为记录项终止标识。
文件(.dbf)的文件头
位置
内容
说明
0-10
11个字节
记录项名称,是ASCII码值。
11
1个字节
记录项的数据类型,是ASCII码值。
(B、C、D、G、L、M和N,具体的解释见下表)。
12-15
4个字节
保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。
16
1个字节
记录项长度,二进制型。
17
1个字节
记录项的精度,二进制型。
18-19
2个字节
保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。
20
1个字节
工作区ID。
21-30
10个字节
保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。
31
1个字节
MDX标识。
如果存在一个MDX格式的索引文件,那么这个记录项为真,否则为空。
记录项信息描述
代码
数据类型
允许输入的数据
B
二进制型
各种字符。
C
字符型
各种字符。
D
日期型
用于区分年、月、日的数字和一个字符,内部存储按照YYYYMMDD格式。
G
(GeneralorOLE)
各种字符。
N
数值型(Numeric)
-.0123456789
L
逻辑型(Logical)
?
YyNnTtFf(?
表示没有初始化)。
M
(Memo)
各种字符。
dbf文件中的数据类型
注意:
记录项的数目在文件头中没有明确给出,但是可以根据第8-9字节的整型知道文件头的大小,减去其他的固定的字节数(32),然后除以32就可以得出其值n。
(2)、实体信息
实体信息部分就是一条记录,每条记录都是由若干个记录项构成,因此只要依次循环读取每条记录就可以了。
2、系统功能需求分析:
根据要求,该程序必须满足最基本的三个功能,一个是能够对shpefile文件进行读取,另外两个分别是对文件属性的浏览还有就是绘制图形文件,所以在程序设计的过程之中,必须要让自己的系统能够满足这三个最基本的要求。
3、整个程序一共有六个模块,系统图如图所示:
本程序系统设计六个模块,分别是读取文件,查看文件属性信息,绘制图形,修改颜色,修改线宽和清空图形。
模块图如图所示:
4、打开软件,新建windows窗体项目,如图所示:
5、在FORM窗体上添加1个menustrip控件,6个label控件,1个penul控件,1个textbook控件,3个button控件,2个groupbox控件并相应的修改部分控件enabled属性,将之初始化为flase。
如图所示:
6、为项目添加一个新的窗体form2,用来实现改变线条宽度的功能,结果如图所示:
7、为项目添加一个新的类,取名为helperclass。
为即将开展的工作流程做好基础准备。
如图所示:
8、编写代码,完善程序的功能。
(1)、heleperclass程序代码段设计,主要函数部分如图所示:
(2)helperclass代码段2,如图所示:
(3)对form1的代码进行编写,主要自定义了draw的画图函数和描点的函数,其代码段如图所示:
(4)对各个控件进行代码添加,实现控件的功能,在过程之中有用到异常处理try,catch语句,让程序不至于轻易崩溃,结果如图所示:
(5)实现关闭文件功能代码撰写,此过程中把pg重新实例化,代码段如图所示:
(6)定义一个颜色的静态变量,把它赋予初值为黑色,在程序运行的时候可以对图像的颜色进行修改,其代码段如图所示:
(7)修改线条宽度代码如图所示:
六、实验成果:
1、读取文件测试
2、查看文件属性测试:
3、绘制图形测试:
4、修改线条颜色测试:
5、修改线条宽度测试:
6、清空图形测试:
七、实验总结
本次实验花费的时间挺多的,因为一开始根本就看不懂实验要处理的对象文件的属性还有格式说明。
花了两天的时间,把那一份白皮书的简略版看了,也弄懂了里面说的一些格式结构的东西。
接下来就是要开始编写程序。
虽然说我们的目标是很清晰的,就是要实现最最基本的三个功能,但是对于文件操作又不够熟悉,再加上对于.net类库接触的不够深入,很多时候要实现的方法上就很难前进。
就好像如何关闭文件,如何打开文件那一块,琢磨了好久,最后通过自己查阅资料,终于找到了方法,应该说是明白了filestream这个类的一些基本的使用方法。
对于控件的操作,本人的风格和实验三实验实现的风格比较相像。
在代码段上面采取了比较严谨的撰写,让程序运行的每一个步骤都合乎逻辑。
就好比说就算让一个什么也不懂的人去操作你的软件,你的软件也能够有足够的容纳性,不至于轻易地崩溃掉。
这也是一个软件最最基本的要求。
在这次实验中,收获最大的,就是和同学团队合作一起讨论代码,一起讨论如何构建模块,一起讨论如何解决语法和逻辑错误。
在以后的道路上,仅仅凭着一个人的力量,是很难把事情做好的,只有有一股团队合作的精神,才能够把事情做好。
在实验中,我也发现了自己存在很多不足,首先自己对于C#语言的了解太少太少,对于很多概念和知识至今都没有很清晰的认识。
对于.net里面丰富的类库,自己了解的仅仅是九牛一毛,这让自己在处理问题的时候经常都是不知如何下手。
这导致自己的效率并不算高。
但是无论怎么说,遇到困难就应该想办法解决,可以自己去找资料,可以询问老师同学,通过此次实验,自己对于c#这门语言有了更进一步的了解,在以后的学习过程中,需要更加努力,才能有所收获。
八、附录:
源程序代码:
1.form1代码:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Collections;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Diagnostics;
usingSystem.Drawing;
usingSystem.Drawing.Imaging;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Windows.Forms;
usingSystem.Drawing.Drawing2D;
usingMicrosoft.VisualBasic;
namespace对?
shapefile文?
件t读á写′绘?
制?
{
publicpartialclassForm1:
Form
{
publicForm1()
{
InitializeComponent();
button1.Enabled=false;//首骸?
先è将?
按恪?
钮¥设Θ?
置?
为a不?
可é用?
button2.Enabled=false;
button3.Enabled=false;
textBox1.Enabled=false;
}
publicstaticColorgColor=Color.Black;//静2态?
颜?
色?
变?
量?
默?
认?
为a黑ú色?
publicstaticintgLineWidth;//静2态?
线?
宽í变?
量?
stringpath;//用?
于?
传?
递蘗路·径?
名?
的?
字?
符?
串?
变?
量?
staticBitmaps=newBitmap(100,100);
Graphicstu=Graphics.FromImage(s);//定¨义?
graphics类え?
的?
对?
象ótu
helperclasspg=newhelperclass();//类え?
对?
象ó实害?
例化ˉ
privatevoidForm1_Load(objectsender,EventArgse)
{
tu=this.panel1.CreateGraphics();
label6.Text="";
timer1.Enabled=true;
timer1.Interval=1000;//设Θ?
置?
计?
时骸?
器÷的?
时骸?
间?
间?
隔?
}
publicvoiddraw()//画-图?
函ˉ数簓
{
Penpen1=newPen(gColor,gLineWidth);//通?
过ypen1实害?
现?
修T改?
颜?
色?
功|能ü
for(inti=0;i现?
对?
每?
一?
个?
多à边?
形?
进?
行D绘?
制?
{
PointF[]ps=pg.mpys[i].polygon.ToArray();//定¨义?
平?
面?
上?
面?
的?
坐?
标括?
有瓺序ò对?
tuxiang(ps);//调獭?
用?
tuxiang函ˉ数簓的?
功|能ü
tu.DrawPolygon(pen1,ps);
}
}
publicvoidtuxiang(paramsPointF[]pt)
{
for(inti=0;i{
pt[i].X=(float)((pt[i].X-pg.HBoundingBox[0])/(pg.HBoundingBox[2]-pg.HBoundingBox[0])*this.panel1.Width);//获?
取?
点?
的?
横á坐?
标括?
pt[i].Y=(float)((pg.HBoundingBox[3]-pt[i].Y)/(pg.HBoundingBox[3]-pg.HBoundingBox[1])*this.panel1.Height);//获?
取?
点?
的?
纵罽坐?
标括?
}
}
publicvoid读á入?
文?
件tToolStripMenuItem_Click(objectsender,EventArgse)
{
OpenFileDialogopenflg=newOpenFileDialog();
openflg.Filter="*.shp|*.SHP";//寻°找ò合?
适酣?
的?
.shp文?
件t
openflg.Multiselect=false;//把?
选?
择?
文?
件t类え?
型í的?
功|能ü改?
成é否?
if(openflg.ShowDialog()==DialogResult.OK)
{
path=openflg.FileName;//把?
文?
件t路·径?
用?
path保馈?
存?
button2.Enabled=true;
MessageBox.Show("文?
件t读á取?
成é功|!
?
","提?
示?
");
选?
项?
ToolStripMenuItem.Enabled=true;
关?
闭?
文?
件tToolStripMenuItem.Enabled=true;
保馈?
存?
图?
片?
ToolStripMenuItem.Enabled=true;
读á入?
文?
件tToolStripMenuItem.Enabled=false;
}
}
privatevoidbutton1_Click(objectsender,EventArgse)//绘?
图?
{
tu.Clear(this.BackColor);//绘?
图?
前°把?
当獭?
前°的?
图?
片?
区?
的?
内ú容╕清?
空?
draw();
button3.Enabled=true;
选?
项?
ToolStripMenuItem.Enabled=true;
}
privatevoidbutton2_Click(objectsender,EventArgse)//显?
示?
文?
件t属?
性?
信?
息¢
{
try//进?
行D异皑?
常£捕?
捉?
{
strings=pg.readfile(path);
textBox1.Text="这a个?
文?
件t共2有瓺个?
"+pg.PolygonNumber+"多à边?
形?
"+"\n\t"+s;
button1.Enabled=true;
button3.Enabled=true;
}
catch//异皑?
常£处鋦理え?
{
MessageBox.Show("本?
软è?
件t不?
支§持?
点?
类え?
型í文?
件t,?
请?
重?
新?
进?
行D选?
择?
!
?
","提?
示?
",MessageBoxButtons.OK,MessageBoxIcon.Exclamation);
}
}
privatevoid关?
闭?
程ì序òToolStripMenuItem_Click(objectsender,EventArgse)//退?
出?
程ì序ò
{
DialogResultresult=MessageBox.Show("确ā?
定¨要癮退?
出?
?
?
","提?
示?
",MessageBoxButtons.OKCancel);
if(result==DialogResult.OK)
Application.Exit();
}
privatevoid关?
闭?
文?
件tToolStripMenuItem_Click(objectsender,EventArgse)//更ü新?
数簓据Y
{
DialogResultresult=MessageBox.Show("确ā?
定¨要癮关?
闭?
当獭?
前°文?
件t?
?
","提?
示?
",MessageBoxButtons.OKCancel);//实害?
现?
选?
择?
功|能ü,?
选?
择?
确ā?
定¨就í退?
出?
,?
否?
就í保馈?
留?
在ú原-来ぁ?
的?
界?
面?
if(result==DialogResult.OK)
{
tu.Clear(this.BackColor);//清?
空?
当獭?
前°图?
片?
区?
的?
内ú容╕
textBox1.Text="";//清?
空?
当獭?
前°的?
文?
档苔?
区?
的?
内ú容╕
pg=newhelperclass();//类え?
对?
象ó重?
新?
实害?
例化ˉ
button1.Enabled=false;
button2.Enabled=false;
选?
项?
ToolStripMenuItem.Enabled=false;
读á入?
文?
件tToolStripMenuItem.Enabled=true;
关?
闭?
文?
件tToolSt