(整理)测绘程序设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
测绘程序设计课程实习报告
一、实习目的
《测量平差程序设计》是在我们学习了专业基础课《误差理论与测量平差基础》课程后将测量平差和计算机程序设计等课程的综合实践与应用的一门课程。
其目的是在我们学习过平差这门课后增强我们对误差理论与测量平差基础理论的理解,巩固已掌握的测量平差的基本原理和基本公式以及计算方法,熟悉测量数据处理的基本技能,培养我们正确应用公式、综合分析问题和解决问题的能力,并能能够熟练运用所学过的C++语言,使平差理论与计算机结合起来,将主要的条件平差、间接平差以及水准网平差计算方法过程编写成一般形式的程序用于数据处理,灵活准确的应用于解决各类数据处理的实际问题当中,为我们今后步入工作岗位打下了一定的基础。
二、实习内容
本课程要求我们熟练运用测量平差的基本公式与计算方法和拥有基本的C++编程能力,以自由组成3-4人小组的方式共同学习,在老师的指导下能够按照要求由简至繁完成以下程序。
(一)角弧之间的相互转化
复习基本的C++内容、程序结构及编写方法,保证任意角度弧度之间可转化及其转化精度。
(二)文件的读入输出
在程序外部建立文本文档输入数据使程序具有一般性并且不需要在执行程序时进行输入,同时在程序运行后结果自动生成文件保存。
(三)概率运算
根据已知题目以及程序进行加以更改调试,建立文本文档读入文件计算标准正态分布函数、B分布的分布函数等概率函数。
(四)矩阵运算
实现矩阵的基本加、减、乘、转置及求逆运算,为接下来平差运算程序解决基本运算问题。
(五)条件平差与间接平差
利用之前以编写过的基本程序,以及平差的公式与算法,根据例题编写程序计算条件平差与间接平差(二者具有一定相似度)。
(六)水准网平差
首先利用已知的例题以及水准网计算公式和算法编写特殊可解的水准网平差,再在其基础上编写一般形式具有广泛应用的普通程序。
在将以上基本任务都完成之后还可以进一步编写GPS向量网等。
三、实习过程
(一)角弧之间的相互转化
1.编程思路:
首先在头文件中要注明#include<cmath>保证程序中的数学运算合理,然后建立一个角度是否合理判断的函数,在其中将角度的度、分、秒分别用三个double型变量a、b、c表示,将输入或计算出的角度改正成合理的形式(分和秒都小于60大于0),如将30°66´27"化成31°6´27" 以及角度的正负。
然后在主函数中选择进行角度转化为弧度或弧度转化为角度,再输入数值时,为了使接下来的运算能够计算正确,如果输入复制现将负值提出flag=(a<0.0)?-1.0:1.0,其中a为角度中的度数,在程序所有计算都运行完毕后在加上其负值-1,角弧转化最根本的是利用公式θ=L×180÷π,其中θ为角度,L为弧度。
在角度化弧度中表示为L=(a+b/60.0+c/3600.0)/180.0*s*4*atan(1),在弧度化角度中表示为m=L*180/(4*atan(1)),其中m为将度分秒化为度的形式,在利用取整’/’将m化为度分秒的形式。
2.计算结果:
(二)文件的读入输出
1.编程思路:
文件可在计算机外部储存,且能长期保存可读取,也可重新刷写,对文件进行操作可随时进行数据更换。
在角弧相互转化程序的基础上进行更编,在原本输入角度和弧度地方使用文件操作,首先在头文件处要标明#include<fstream>,使我们对程序进行文件操作时的行为合法,在进行打开文件处写上ifstream infile("jiao.txt"),括号中要打开的文件名称和格式为txt,并且用if(!infile)判断文件是否成功打开了,成功打开后,并且在程序结束时要关闭读入的文件infile.close(),解除该磁盘文件与文件流的关系,就不能再通过文件流对文件进行输入或输出。
在输出计算结果到文件中时写为ofstream outfile;outfile.open("jiao_out.txt");括号中的为文件输出后所在的文件文件名及其格式,结果所在的文件可以在程序运行前就建好空白文件,也可不建立,在程序运行后会自动生成一个如括号里写的文件。
其他程序具体操作不进行任何改变,但将输入数值改换为文件的输入输出后,其结果可以更好的保存,输入数据时更方便,而程序更具有一般性。
2.计算结果:
(三)概率计算
1.编程思路
根据已知的probability.cpp程序对照实际例题改编程序,进行文件输入输出操作和函数的调用练习,将已知数据输入到程序中求得结果。
2.计算结果:
(四)矩阵运算
1.矩阵的表示方法
在程序中矩阵要依靠创建动态数组来表示,创建动态数组是为了储存未知阶数m×n的二维矩阵,定义动态数组包含两个步骤:第一步,定义与数组元素类型相同的指针变量;第二步,申请内存并将内存地址赋给指针变量。
用动态数组来表示矩阵的方法有很多例如将二维数组作为一维数组储存本次程序编译就采用了这种方法将矩阵表示为:
double *P=new double [n];此时P指针指向一个元素个数为n的一维数组。
地址new的作用是动态分配内存,在程序运行过程中申请分配用于存放初值列表类型数据的空间,并进行初始化。
在所有运算进行完毕之后,要用delete 将动态分配建立的对象删除,从而释放空间。
除了这种方法之外,还可以直接定义二维数组,或调用函数创建来表示矩阵。
2.矩阵的运算
(1)矩阵加法与减法
矩阵的加法与减法相似,比较简单。
首先还是要进行文件操作,读入两个矩阵的数值,因为其基本要求是两矩阵的行数与列数对应相等,所以在此程序中首先需要对两个矩阵进行判断,表示为if(p!=n*m||k!=n*m),若是行列数不相等,则输出错误信息表示不能进行运算。
若是能够进行运算,则只需要两矩阵对应元素进行一一加减,即*(a+i*hang+j)+*(b+i*hang+j),得到的结果输出即可。
在结束运算后关闭文件输入操作,若是单独作为一个函数,无需文件操作,则只需要返回指针。
(2)矩阵乘法
矩阵的乘法比起矩阵的加减法要稍稍有一点难度,因为其基本要求是第一个矩阵的行数和第二个矩阵的列数相同,所以对n×m阶矩阵A和p×q阶矩阵B 来说,在进行编程时首先要进行判断的是第一个矩阵的列数m是否与第二个矩阵的行数p是否相等,若不相等,输出错误信息,提示不能进行运算;若是符合条件,首先要定义一个新的动态数组C其长度为n×q(n,q要分别与第一个矩阵的行数和第二个矩阵的列数相同),并将数组C的每一个元素都赋予一个初始值0。
数组C的第i行第j列的元素值等于数组A的第i行元素与数组B的第j列元素对应相乘后累加。
因此*(C+i*m+j)+=(*(A+i*m+k))*(*(B+k*q+j));这里运用了多次for循环来实现运算。
(3)矩阵的转置
矩阵的转置表达较为简单,进行文件操作,读入两个矩阵的数值,定义一个与已知矩阵相同长度的数组,使得*(a+i*hang+j)=*(b+j*hang+i),然后将转置后的数组输出即可。
若是单独作为一个函数,无需文件操作,则只需要返回指针。
(4)矩阵求逆
矩阵求逆在几种矩阵运算当中是最难的一种。
由于在平差计算中,一般是对权值进行求逆,权阵的特点是对称矩阵,因而对于特殊的对称正定矩阵,在求逆函数中矩阵的存储是仅存下三角矩阵元素。
对称正定矩阵求逆
设A为一个n×n阶对称正定矩阵,求A的逆矩阵Aˉ¹。
矩阵求逆分一般分三步进行:第一步求约化系数,第二步求下三角阵的逆阵,第三步求原矩阵的逆阵。
每一步计算均采用原位替换求解法,即将矩阵中不同位置的元素表达为相应位置的位置函数值,每一步计算是用新的位置函数值替换相应位置的原有位置函数值,最终将原矩阵中各位置的元素替换为其逆矩阵中相应位置的元素。
计算公式如下:
a’
n-1,n-1=1/a
0,0
a’
n-1,j-1=-a
0,j
/a
0,0
(j=1,2,...,n-k-1)
a’
n-1,n-1=a
0,j
/a
0,0
(j=n-k,n-k+1,...,n-1)
a’
i-1,n-1=a
i,j
-a
0,i
a
0,j
/a
0,0
(i=1,2,..,n-1;j=1,2,...,n-k-1)
a’
i-1,n-1=a
i,j
-a
0,i
a
0,j
/a
0,0
(i=1,2,..,n-1;j=n-k,n-k-1,...,n-1)
k=0,1,2,...,n-1,表示循环变换次数。
1.计算结果:
(五)条件平差与间接平差
1.间接平差
⑴公式及算法:
间接平差与条件平差有一定的相似度间接平差法(参数平差法)是通过选定t 个与观测值有一定关系的独立未知量作为参数,将每个观测值都分别表达成这t 个参数的函数,建立函数模型,按最小二乘原理,用求自由极值的方法解出参数的最或然值,从而求得个观测值的平差值。
间接平差的函数模型为: L=F(X);
参数的平差值 X=X 0+x ;
随机模型:D=σ02Q=σ02P -1
误差方程:V=Bx-L ;
法方程:B T PBx-B T PL=0;
法方程解:x=(B T PB )-1B T PL ;
单位权中误差:μ=±t
-n VTPV ; 参数平差值的协因数阵Qxx=(B T PB )-1;x=(B T PB )-1B T PL
B 是一个t ×n 的矩阵;
P 是一个n ×n 的对称矩阵;
L 、x 、V 都是一个n ×1的矩阵;
⑵编程思路:
间接平差的程序编译与条件平差有相似之处,尤其是主函数之前的之前的基础调用函数矩阵的乘法multipy ,矩阵转置函数transpose ,和矩阵求逆是完全相同的。
在主函数中,依旧是先进行文件操作读入存在txt文档中的B,P,L的数据,然后进行调用multipy 及transpose 函数由B 、P 、L 计算计算BᵀPB和B T PL ;数组B 的长度为t*n ,数组P 的长度为n ,数组L 的长度也n ,所以从文本中直接读入的三个矩阵还不能直接进行运算,为了进行运算我们要将P 变化一下,所以我们将定义一个长度为n*n 的动态数组P ’,使得*(P ’+i*n+i )=*(P+i ),这样,便可以调用矩阵运算的函数计算出B T PB 和B T PL ,然后调用矩阵求逆函数求B T PB 的逆矩阵(B T PB )-1;由Qxx 求得参数x ,计算参数的平差值 X ,残差V ;单位权中误差μ。
最后求得某参数平差值X j 的中误差σXj =μ
J J X X Q 。
其中开根
号用sqrt函数求得。
⑶计算结果:
2.条件平差
⑴公式及算法:
条件平差法是在满足r个条件方程要求下,根据最小二乘原理VᵀPV=min,按照求函数的条件极值的方法,求出观测量的改正数V,进而求出观测的最或然值(平差值),条件方程个数等于多余观测数r=n-t,n为观测值总数,t为必要观测数。
条件平差中设条件方程式为BV+W=0;
V为n维观测值改正数向量;(n为观测值总数);
B为r×n阶系数矩阵;(r为条件方程个数);
W为r维条件方程自由向量;
有最小二乘法可得联系数法方程为BPˉ¹BᵀK+W=0;
P为观测值的权矩阵并设观测值独立,P为对角矩阵,数组长度为n;
K 为联系数向量,K=-(BP ˉ¹B ᵀ)W ;
法方程:BPBT K+W=0;
随机模型:D=σ02Q=σ02P -1
改正数向量V=Pˉ¹BᵀK;
单位权中误差公式μ=±r
VTPV ; 观测值平差值的权逆阵QL=Pˉ¹-Pˉ¹Bᵀ(BPˉ¹Bᵀ)ˉ¹BP ˉ¹;
⑵编程思路:
首先,在程序头文件处广泛定义一个N 在下面程序中都为一个其确定的值3,因为在计算过程中需要计算大量的矩阵乘法,所以先定义一个矩阵乘法的函数multipy,将矩阵用一维动态数组表示出来,a3[i*r+x]+=a1[i*q+j]*a2[j*r+x]表示相乘后的矩阵元素,在定义矩阵转置函数transpose ,利用for 循环将矩阵元素逐一转置表示为a1[i*m+j]=a[j*n+i];矩阵求逆的程序是查找资料找到的一段固定代码。
在主函数中首先利用动态数组定义B ,W ,Q ,P ,然后进行文件操作进行数据的输入,文件中已经写好的矩阵元素一一对应输入,开始计算,首先调用multiply 函数计算AQ ,在调用transpose 计算A 的转置,对A 进行求逆,然后前两项计算得AQA ˉ¹,再与W相乘算出K =—(AQˉ¹Aᵀ)W ,再调用乘法及转置函数计算V=Qˉ¹AᵀK,进而计算出V ᵀPV 求得中误差μ。
计算完所有数据之后进行文件操作输出所求的中误差等值,利用for 循环将矩阵内的元素一一对应输入,在结束数据应用后关闭文件的输入,释放空间。
⑶计算结果:
(六)水准网平差
1.公式及算法:
水准网平差程序是在间接平差程序的基础上进行进一步改进而成的。
在间接平差时,我们将B、P、L直接输入到了txt文本当中,同间接平差一样,水准网平差所需要的已知数据和观观测数据全部从数据文本文档中读取,并且其中的数据是最原始的数据。
水准网的原始数据内容分为网的概况、已知数据、观测数据三部分。
网的概况包括:总点数,已知点数,观测值总数,验前单位权中误差。
(在txt文本中以上数据放在一行中)
已知数据包括:已知点的点名和对应的已知的高程值。
(在txt文本中每个已知点和它的高程值占一行)
观测数据包括:对应的起点点名、终点点名、高差观测值、高差线路的长度。
(在txt文本中点名包含字符串所以不能用空格)
根据最原始的数据,将误差方程式的系数阵B、常数项L以及权阵P求出,组成误差方程式V=Bx+L;之后几步同间接平差相同单位权中误差μ,求得某参
数平差值X
j 的中误差σ
Xj
=μJ J X X
Q。
,然后求观测值改正值V之后的值L=L0+v,
最后求各未知点的高程值H=H0+x。
2.编程思路:
在水准网平差中还是要运用矩阵运算,矩阵的运算在前几次实习中已经编写过并应用过了,但是由于不同程序的要求不同,为了使矩阵的运算更加通用,同时为了调用时的方式更加简单,在这里我们采用运算符的重载的形式,采用基本一般格式定义函数的重载
在本程序当中进行文件读取操作比起之前的操作变得复杂许多。
定义ifstream fin,将存在文本中的网的概况信息依次读取,为了计算方便我们将已知数据定义为double型。
定义长度为动态字符串一维数组string **A=new string *[yy];存储读入已知点矩阵的点号与高程,利用两段for循环来实现,依次读入已知点名与已知高程。
定义一段的动态字符串数组string **AA=new string *[m];存储读入未知点矩阵的点号与高程存储起点名,定义长度为n的string **XX=new string *[n];存储未知点号。
求系数矩阵B,将矩阵B定义为一个n×r的动态二维数组(n为观测数,r为未知点个数,即为未知参数的个数),表示为:double **b=new double*[n];先将已知点的点名存储到存放总点名的字符串数组中,先初始化系数矩阵A[m][n]为0矩阵;然后控制循环条件,依次输入各段水准路线的起点、终点;依次判断各水准路线的起点、终点在矩阵A中的位置,在计算B时利用if(AA[i][0]==A[j][0]||AA[i][1]==A[j][0]);判断是否有已知点;
系数矩阵B表示的是未知参数的系数,当起点是未知点时,系数为-1,当终
点是未知点时,即其系数为1,B矩阵的其他元素赋值为0.
求常数项矩阵L:
常数项L是观测值与近似值之差,L=H-H0 观测值:H即为由各高差组成的数组val中的值,H为n×1的列向量。
P矩阵中只有对角线上有非零元素,当P矩阵不只对角线上有非零元素,而是成为一个普通的对称矩阵,那么可有另一种解法。
设N=B T PB,N、P均为对称矩阵,只存储下三角元素,长度为n×(n+1)/2,从一个长度为n*n的矩阵变为长度为n×(n+1)/2的一维数组。
⑶计算结果:
在水准网平差中我没有完成一般形式的程序只完成了特殊的水准网。
四、实习总结
经过本次为期六周的测量平差课程设计,我得到了许多收获。
首先本次课程设计课程使我对误差理论与测量平差有了更加深刻的理解和认识,加深了对测量平差基本理论的理解和具体的计算机实际操作能力,使我意识到我现在还有很多的不足,更加使我深刻的认识到学习测量平差的重要性。
作为一个即将要走向社会与工作岗位的测绘专业的大学生,我们现在所学习掌握的知识只是我们未来
需要的一小部分,而误差平差理论及将误差平差编写成程序就是最基本的部分,而现在我的基础知识并不是非常牢固,编程能力也并不出色,会应用的软件相对于我们以后会应用到的还很少,通过本次课程巩固了我基础知识,在上个学期的平差学习后但是由于课时的紧张和课程本身的难度,在学习的过程当中有许多当时并未并未完全理解的问题,但是在考完试之后我并没有继续解决,然而在本次课程的学习过程中我把在当时学习理论课中遇到的很多问题和盲点都搞清楚了,比如导线网的条件平差方程的列法,间接平差方程的建立等,除此之外我的编程能力也有所提升,不仅将以前学习过的编程方法更加牢固的掌握了,还学习到许多以前不会的技巧,例如文件的读入输出,利用动态数组表示二维矩阵等等。
本次课程以小组形式进行增进了同学间的凝聚力,在编程过程中遇到的许多的问题,大家在一起讨论使得问题更快的得以解决,并且有了更多的解决方法和思路。