测绘程序设计技术基础.docx
《测绘程序设计技术基础.docx》由会员分享,可在线阅读,更多相关《测绘程序设计技术基础.docx(169页珍藏版)》请在冰豆网上搜索。
测绘程序设计技术基础
测绘程序设计技术基础
测绘工程专业
第一章绪论
第一节本课程的相关内容
1.本课程主要内容
测绘程序设计是大题目,在测绘工作与科学研究中,很多情况下都可以使用计算机。
测绘工程所涉及的数据计算、绘图、数据库管理、数据分析等,都可以使用计算机来完成。
从一般含义上说,测绘工作包含计算和绘图两个方面的内容。
关于计算机绘图有相关课程讲述,所以,这门课程的主要内容集中在测绘工程的相关计算上面,而其中,主要讲述关于平差计算的程序设计问题。
本课程主要讲述以下内容:
(1)数据结构在控制网数据处理中,数据组织是非常重要的内容,在这里我们主要讲述图的概念,以及使用图表示控制网的数据。
(2)常用工具函数编写这里主要讲数据处理中经常需要用到的一些工具函数,如角度-弧度互化的函数,测量正反算函数,矩阵计算函数等。
(3)基本平差程序使用计算机的方法处理间接平差的结构与过程。
(4)高程网平差将高程网平差表示为基本平差结构,使用基本平差程序处理水准网、三角高程网平差的相关问题。
(5)边角网平差处理边角网平差的过程与问题。
(6)GPS向量网平差处理观测值为GPS基线向量的三维坐标平差问题。
(7)测量坐标系转化
2.平差程序计算特点
相对于手工计算,平差程序计算的主要特点是计算速度快、精度高、数据处理自动化,从而把人从繁重的计算工作中解放出来。
从程序设计的角度看,程序设计与平差计算相对独立。
在平差手工计算时,我们总是面对需要计算的具体问题,所以其数据是特定的,计算过程由人实时控制;在计算机程序计算中,在程序设计时数据是抽象的,必须考虑到实际计算中问题的多样性,以及数据计算过程的自动化,所以在程序设计时必须考虑需要处理的所有问题的普遍性和规律性。
另外,相对于手工计算,在程序计算时,选择平差方法的依据不同。
在手工计算时,我们通常希望尽量降低计算工作量。
当必要观测数t>多余观测数r时,我们可以选择条件平差;当必要观测数t<多余观测数r时,我们可以选择间接平差,这样,可以降低平差计算量。
然而,在计算机程序计算时,由于计算机计算的快速高效性,我们不是很关心计算量的问题,而把主要精力集中于方法实现的现实性方面,也就是要求该方法具有较强的规律性,便于程序设计的技术实现。
在平差程序设计中,使用间接平差,对于一般控制网,误差方程形式统一、规律性强、便于程序设计;而使用条件平差,误差方程形式多样,规律性差,不利于程序设计。
所以,在本课程中,我们主要使用间接平差方法进行程序设计。
总之,我们在选择数学模型的时候,一定要考虑算法同计算机程序设计的特点相统一。
3.平差程序的基本要求
平差程序设计与其它程序设计相同,应当满足一定的要求。
(1)程序逻辑结构简单,清晰易读,符合结构化程序设计要求,便于扩展;
(2)运算速度快,占用内存小,内外存之间的交换不宜过于频繁;
(3)数学模型及计算方法正确、先进,计算结果精度高;
(4)适应性强,便于移植,充分考虑各种可能形式,尽量满足不同要求与需要;
(5)方便用户,操作简便。
数据输入与用户作业方式与习惯相统一,输出明了、齐全;尽量减少手工处理工作量,操作简便;人机交互性要强。
上述要求,既体现在平差程序的总体设计中,也贯穿于平差程序设计的各个环节中。
4.平差程序的设计步骤
(1)结构总体设计
(2)数据结构设计
(3)确定软件各组成部分的算法及数据组织
(4)选定某种表达式来描述各种算法
(5)程序编写
(6)程序调试
(7)编写用户使用说明
5.学习本课程的基本要求
6.
(1)掌握C语言基本技术,并应用于测绘程序的编写中;
7.
(2)熟悉《测量平差基础》、《控制网平差基础》等理论知识;
8.(3)基本掌握结构化程序设计方法;
9.(4)勤思考,勤动手,多练、多问,阅读、编写相关功能程序。
第二节结构化程序设计
结构化程序设计是计算机软件技术高度发展的产物,是大规模、工业化软件开发的基础。
C语言是结构化程序设计思想成熟与完善的标志,至今,仍然是计算机软件开发的主要语言之一。
模块的概念是软件工程的基本概念之一。
1.模块化程序设计相关概念
模块——执行某一特定任务的数据结构和程序代码。
在C语言中,每个模块与一个函数(function)相对应。
模块化——将待开发的软件分解成若干个小的模块,以使每个模块可以独立地开发、测试,最后组装成完整的软件。
软件模块化的目的在于使软件的结构清晰,降低软件开发难度、容易阅读理解、测试和修改。
划分模块的原则:
(1)按功能划分模块,要求每个模块包含单一、具体的功能
(2)使每个模块独立性好,这就要求一个模块具有较强的内聚性和较弱的耦合性。
方便于模块的独立开发、调试,同时,使模块具有很好的移植性。
划分模块时,应当尽量减小模块间的耦合性,例如尽可能地使用局部变量就可以减小模块之间的耦合性。
划分模块时,采用层次结构进行分析:
(1)最上层模块是对系统整体功能的抽象;
(2)下层模块是对上层模块的逐步细化描述;
(3)重复
(2),得出便于实现的独立性好的模块,直到下层模块不可再分为止。
在最下层,对“怎么做”作出精确的描述。
2.平差程序模块化
图1.1平差程序模块化
第三节控制网的数据结构
1.基本概念
测量平差程序处理的对象是程序所适应的各种测量控制网问题。
因此,这类程序总是同一定的网形相联系的。
一个具体的控制网通常是以图形方式直接绘出的,为了用计算机进行控制网的平差计算,就需要将具体的网形转化为一系列的数据,然后才能输入计算机进行处理。
这种将网形转化为一系列数据的工作和过程称为“网形数字化”。
网形数字化所得到的一组数据就是控制网的数据结构。
数据结构所涉及的范围是广泛的。
在每个具体问题中,数据元素及其关系是确定的,而且都有其特定的含义。
对测量平差而言,其数据结构就是表达一个控制网的全部数据的集合,包括已知数据、观测数据、网形数据(网图数据)及其关系。
为了使用数学方法表示控制网的结构,需要用到图论的相关概念。
图论是研究事物之间关系的一种数学方法,下面对之一概念作简单的介绍。
2.图及其数字化
2.1图的定义
图论是研究事物之间关系的一种数学方法,在图论中,用点表示事物,用线段表示事物之间的联系,这些点称为图的顶点,线段称为图的边。
对于控制网,其中元素及其关系可以使用图论的方法进行研究。
图是由点和边构成的,可以定义为定点集V与边集E的和,记为
G=(V,E)
例如对于图1.2所示问题,可以得出如下图论分析结果
上述边集中元素(1,2),(2,3)等称为点偶。
若点偶中顶点的顺序可以任意,称这种图为无向图,反之,称为有向图。
图1.2具有四个点的无向图
对于有向图采用符号G=表示。
其中点偶也采用尖括弧表示,尖括弧中顶点的顺序是固定的。
对于图1.3,可以表示如下:
图1.3具有四个点的有向图
对于有n个顶点的无向图,边的最大数目为:
对于有n个顶点的有向图,边的最大数目为:
2.2图的数学表示方法
对图的数学表示方法有以下三种:
相关矩阵,邻接表和边目录。
1)相关矩阵:
如果i,j两点有边相连,则矩阵第i行、第j列元素为1,反之为0;对角线上元素永远为零。
对于如图1.2所示的无向图,用相关矩阵表示如下:
无向图特点:
关于主对角线对称,通常只需写出一半即可。
对于如图1.3所示的有向图,用相关矩阵表示如下:
有向图特点:
通常不是对称矩阵,需要写出矩阵全部元素。
2)邻接表:
按照图中的顶点顺序,将与该点边相连的所有点(可达顶点)排成一行,所有这些行所构成的表叫邻接表。
对于如图1.3所示的有向图,用邻接表表示如下(表1.1):
该表可由对应的相关矩阵产生。
为节省内存,通常将邻接表排成一行。
为识别可达顶点所属的行号,需要给出表1.1中每行含有的可达顶点数,从而构成可达顶点数表和可达顶点表。
如表1.2所示:
2
3
1
3
2
4
2
表1.1邻接表
2
2
2
1
2
3
1
3
2
4
2
表1.2邻接表
在表1.2中,第一行为可达顶点数表;第二行为可达顶点表。
与有向图类似,无向图的邻接表也可以由相应相关矩阵产生。
3)边目录:
按照图的定义,图由顶点集V和边集E组成。
然而,边集实际上包含了所有点集的信息(除非图中包含孤立的点,这种情况在控制网中是不会出现的),所以可以只用边集E来表示图。
这种用两端点号表示图中边所构成的表成为边目录。
下面对于有向图的例子做简单的说明。
对于如图1.3所示的有向图,用边目录表示如下(表1.3):
1
1
2
2
3
3
4
2
3
1
3
2
4
2
表1.3有向图的边目录
在表1.3中,每一列表示一条边,第一行中的点为起点号,第二行中的点为终点号。
对于无向图,表示方法与有向图类似。
需要注意的是,为了使每条边只表示一次,采用最小点号原则。
也就是起点号由小到大排列,边不重复表示。
以上三种方法,在数学上是统一的。
也就是说,只要知道一种表示,其它两种就可以相应生成。
3各种方法的比较
相关矩阵、邻接表和边目录都能表示出图的全部点和边。
其中,相关矩阵方法冗余度最大,对角线上元素全为零,其余位置上也存在大量的数据冗余。
另外,相关矩阵不能反映出各边的邻接关系,这对于控制网平差计算极为不利。
对于有向图,邻接表要比边目录节省许多内存空间。
因为这两种方法第二行元素完全相同,但在第一行,邻接表只需列出可达顶点数,所以比边目录占用存储空间少。
对于无向图,邻接表和边目录体积相当,两种方法均可以采用。
在控制网平差中,使用邻接表占用内存小,使用边目录更加直观。
所以这两种方法均可以采用,更重要的原因在于这两种方法可以根据需要调整边的邻接关系。
2.4有序邻接表和边目录
为了反映图中同一顶点上各边的邻接关系,无论是邻接表还是边目录都应该按照顶点序号和每顶点上各边的相邻次序按一定的顺序排列(顺时针方向),如此形成的邻接表和边目录称为有序邻接表和有序边目录。
控制网平差需要用到有序邻接表和有序边目录,不加说明,我们仍称为邻接表和边目录。
3.控制网的数据结构
3.1图与控制网的映射
图的元素与测量控制网元素之间存在如下所示的对应关系:
图的顶点对应于测量控制点;
有向图的边对应于控制网的有向边(方向观测值、高差线路、基线坐标分量等);
无向图的边对应于控制网的无向边(单向测距边)。
另外,图也可以用于研究控制网的其它关系,例如,图的顶点用来表示三角形,图的边则表示三角形的邻接关系等。
3.2控制网数据结构的组成
控制网的数据包括已知数据、观测数据、网形数据三个部分。
其中,前两个部分是我们所熟悉的,网形数据是需要我们用图论方法表示的信息。
根据上面的讨论,我们可以使用有向图或者无向图的方法表示控制网中数据之间存在的各种关系。
3.3控制网数据结构应满足的条件
1)充分性条件:
数据结构中应当包含足够多的数据,以保证能构成所需的控制网。
也就是要充分表示网点及其关系。
例如,对于边长交会的情况,按照数学理论方面的要求,在有两个已知点的情况下,似乎测量两条边就足够了,实际上,我们知道,这时候可以计算出两个点的坐标。
也就是说解不唯一,或者说不满足充分性要求,这时必须增加约束条件数据,从而得到唯一的计算结果。
2)必要性条件:
数据结构中只包含构网必须的数据,无冗余数据。
程序设计不大可能忽视充分性条件,因为充分性条件不满足,很容易发现。
对于必要性条件,则很可能由于算法实现的难度而转嫁于用户头上,要求用户输入一些属于冗余信息的数据,从而加重用户的工作量。
我们应当重视必要性条件,这也是软件是否完善与成熟的主要标志之一。
第四节C++特征与VisualC++6.0开发环境
在这门课中,我们需要应用C++程序设计中的一些特征,在课间实习与集中实习中,需要使用VisualC++6.0开发相关程序(dos版C++程序),在此对相关内容作简要的介绍。
.CPP
1.C++特征
1.1重载
重载是C++在C的基础上对函数功能的扩展。
利用重载机制,可以对具有相似功能的函数在定义时使用相同的函数名,从而方便用户的使用。
例如:
在C语言中,为定义不同类型数据相加的操作,必须使用不同的函数名来定义一组函数。
Iplus()整数相加;
Dplus()实数相加;
Fplus()浮点数相加;
Cplus()字符串相加。
对于不同类型的数据计算必须由用户调用不同的函数,这无疑增加了用户使用程序的负担。
在C++语言中,可以使用更简洁的方法处理这种问题。
对以上四种计算可以只使用一个函数名plus定义相关的不同函数。
计算机函数编译的区别标志在于函数的参数不同。
也就是说,计算机根据同名函数参数不同来区别相关函数。
在应用时,就可以以一个相同的函数名调用一族函数。
这就是C++语言函数重载的概念。
很明显,函数重载的应用,方便了程序的编写与用户的使用。
使用相同名字定义的一族函数叫重载函数。
使用一个已经存在的函数名定义一个新函数叫对原有函数的重载。
定义重载函数的关键在于相关函数应当具有不同的参数。
参数不同体现在两个方面:
函数参数的类型不同或函数参数的个数不同。
对于上例问题,可以定义一组重载函数(函数定义略):
intplus(inta,intb);
doubleplus(doublea,doubleb);
floatplus(floata,floatb);
char*plus(char*a,char*b);
在应用时,系统根据调用函数参数的不同直接调用相关函数,如:
intd=plus(2,14);
cout<floats=plus(4.45f,5.66f);
重载的使用使程序的编写与使用具有很强的方便性。
应当注意的是,对于在操作和概念上不具有相似性的函数尽量不要使用重载,以免引起使用者的误解。
1.2引用
引用是C++区别于C的另一个技术特征。
引用的作用在于函数的参数传递,使用引用,可以以变量名直接实现函数参数的双向传递。
那什么是引用呢?
简单地说,引用是对一个变量取的别名,也就是给一个变量取的第二个名字。
例如:
inti;
int&j=i;
这里,i是一个变量,定义j为i的引用。
系统不再为j分配存储空间,而让j与i使用相同的存储空间。
这时,在程序中任何对j的访问就是对i的访问。
引用的主要作用在于函数参数的传递,也就是定义函数的参数为引用类型。
分析下面程序
#include
intPlus(int&x,int&y)
{
x++;
y++;
returnx+y;
}
定义main()函数
voidmian()
{
Inta(5),b(10),c;
c=plus(a,b);
cout<}
该程序运行结果为
6,11,17
在该程序中,我们发现,形参的改变导致了实参的改变。
原因在于函数中定义的函数形参为实参的引用。
这种作用在程序设计的某些情况下具有很强的应用价值。
1.3动态存储(new和delete操作符)
在C语言中,允许动态地分配存储空间和动态地释放已分配的存储空间。
在C语言中,使用函数malloc()和free()动态分配和释放存储空间。
所谓动态,就是(堆)内存的使用由用户控制,在用户需要时分配,使用完毕立即释放;动态的另一个含义在于不像一般变量,动态存储技术是在程序运行时分配和释放存储空间的(一般变量在编译分配存储空间,程序运行结束时释放存储空间)。
这也是建立动态数组的技术之一,可见,使用动态存储的优势是非常明显的。
在C++中,使用两个操作符new和delete来完成相应的操作,其优越性表现在以下三个方面:
(1)new自动计算分配类型的大小,从而可避免人为分配可能造成的错误和浪费;
(2)new自动返回正确的指针类型,不必对返回类型进行类型转换;
(3)可以使用new将分配的单元初始化。
在C++中,使用new动态分配存储空间;使用delete释放new分配的空间。
(1)new的语法格式
类型指针=new类型(类型初始化值);
这里,类型可以是系统定义的基本数据类型,也可以是用户定义的结构体或者类。
例如:
int*s=newint;
double*p=newdouble(3.1415926);
double*A=newdouble[100];
此时,动态分配一个整形存储空间,并把地址返回给s;动态分配一个double类型空间,初始化为3.1415926,并把地址返回给p;动态分配一个double类型数组空间,并把地址返回给A。
这些动态分配的空间从分配后开始存在,直到delete释放它们,或者计算机关机为止(可见动态分配的存储空间具有“超”静态变量的性质)。
所以,new和delete应当配对使用,以免造成计算机内存资源的浪费。
(2)delete的语法格式
delete类型指针;
对于上面三个用new分配的动态存储单元,可用以下方法释放
deletes;
deletep;
delete[]A;
需要注意的是,释放数组空间时,不需要给出数组的大小。
这里的A可以以指针、也可以以数组的方式被使用。
1.4输入/输出流
C语言使用标准输入/输出库函数完成数据的输入与输出,在使用中,必须判断数据类型,在应用中不够方便。
C++使用面向对象的方法实现了数据的输入/输出,使用上更灵活、简便。
C++使用输入输出流定义数据的键盘输入与屏幕输出,并预定了两个应用对象cin和cout,cin用来实现数据的键盘输入;cout用来实现数据的屏幕输出,并为这两个对象分别定义了运算符>>和<<。
在程序设计中,我们可以直接使用这两个对象及其运算符来完成相关操作。
分析如下程序:
#include
voidmain()
{
inta,b,c;
doubled,e,f;
charname[20];
cout<<”pleaseinputa,b”<cin>>a>>b;
cout<<”pleaseinputd,e”<cin>>d>>e;
cout<<”pleaseinputname”<cin>>name;
c=a+b;
f=d+e;
cout<<“mynameis”<cout<<”c=”<cout<<”f=”<}
程序中,endl是输出换行符(end-line)。
运行程序:
pleaseinputa,b
34
pleaseinputd,e
3.44.3
pleaseinputname
杨建华
mynameis杨建华
c=7
f=7.7
由程序可以看出,使用输入输出流在程序设计中处理数据的输入与输出的方便性。
1.5文件流
文件流是C++以面向对象的方法定义的文件格式的数据输入/输出方法。
在需要处理大数据量时使用文件管理数据是非常必要的。
从而也可以使数据处理的结果以文件形式被永久保存。
C++有三种文件流:
输入文件流ifstream,用来处理由文件的数据输入;
输出文件流ofstream,用来处理向文件的数据输输出;
输入/输出文件流fstream,用来处理由文件的数据输入以及向文件的数据输出。
具体应用过程如下:
(以输入文件流为例)
1.5.1首先定义相关的流对象
ifstreamin;定义输入文件流对象in,处理文件数据的读入操作;
ofstreamout;定义输出文件流对象out,处理数据的文件输出操作;
fstreamio;定义输入/输出文件流对象io,处理数据的文件读入/输出操作;
1.5.2以流对象打开相关文件
in.open(“D:
\data.txt”);
1.5.3数据读入
in>>a>>b>>name;
1.5.4关闭文件
文件使用结束,应当关闭相关文件
in.close();
具体应用参照相关文献。
2.VisualC++6.0程序开发环境
VisualC++是微软使用C++语言的Windows程序程序开发平台,该平台支持C++控制台程序开发(dos以main()函数为程序主要入口)要求。
C++兼容C,所以也可以用来设计C语言的结构化程序。
本课程采用VisualC++6.0作为程序开发平台。
VisualC++6.0是Windows程序,以菜单定义相关操作功能,应用方便。
其桌面布局(图1):
客户区是代码输入、编辑区,在该区域输入、编辑C/C++程序源代码;
工作区是VC++程序开发管理区,在此系统列出软件相关的文件、Windows资源、相关函数、变量、类等结构。
在控制台程序设计中,主要用来管理相关结构、函数、定义的全局变量等。
输出区主要显示程序的编译、连接、调试等的结果或数据。
在控制台程序开发中,主要用于编译结果显示,在此查看程序编译错误。
**程序运行时,弹出Windows运行窗口(图2),默认条件下,背景为黑色,文字为白色。
文字可浏览、不可编辑。
在此可以以键盘输入程序数据。
运行完毕,点击任意键关闭此窗口。
以下在说明VisualC++6.0环境下,开发Dos程序的主要过程:
1.点击主菜单下文件选项,选择“新建”,在弹出的“新建”窗口下点击“文件”,弹出图3所示窗口:
图1VisualC++6.0开发环境
图2程序运行窗口
图3建立文件窗口
选择“C++SourceFile”,选择保存目录(因为以工程模式管理软件开发,相关文件较多,通常要求为每个开发项目建立一个文件夹,将所有相关文件放在同一个文件夹中),输入文件名。
最后点击“确定”,打开代码编辑窗口。
2.代码输入、编辑与编译连接
接下来,在图4中客户区输入C++源代码。
输入完成后,点击编译主菜单下编译选项,选择“重建全部”,编译、连接,形成可执行的.exe文件。
编译时,在输出区窗口输出编译中的错误,双击错误提示,可以找到相关行。
根据这些提示对源代码进行编辑,直到最终编译结果无错误,则可以开始运行程序。
3.程序运行
运行程序可以直接点击编译菜单下或者桌面上的红色“!
”,完成(图5),程序运行完毕,点击键盘任意键关闭程序输出窗口。
要编写新程序,点击“文件”菜单下“关闭工作区选项”,关闭原有程序,重复以上步骤。
图4代码编辑窗口与编译连接
图5运行程序
4.打开已有文件或工作区
图6打开已有工作区或文件
如图6所示,点击文件菜单下“打开”选项,可以打开.Cpp、.h等文件,也可以通过文件类型选择打开其他文件(例如.txt文件)。
点击文件菜单下“打开工作区”选项,可以打开.dsw文件,打开一个工作区文件,则已编译、连接的所有文件都会打开,包括已有的.exe文件。
所以,可以直接运行该程序;也可以重新编辑源代码,再编译、运行。
第二章通用函数模块编写
第一节矩阵的相关函数
在数据处理程序中,经常需要用到矩阵的基本计算,包括矩阵的乘积、转置、求逆等。
在测量数据处理中,还需要用到一些具体的、有规