2024年2月24日发(作者:)

《测绘程序设计()》

上机实验报告

(Visual C++.Net)

班 级:

学 号:

姓 名:

序 号:

二零一一年五月

实验8 平差程序设计基础

1. 实验目的:

1.1 巩固过程的定义与调用;

1.2 巩固类的创建于使用;

1.3 巩固间接平差模型与平差计算;

1.4 掌握平差程序设计的基本技巧与步骤。

2. 实验内容:

水准网平差程序设计。设计一个水准网平差的程序,要求数据从文件中读取。

计算部分也界面无关。

3. 设计思路:

在本次的实验中,我着重想表现的是一种面向对象的编程思想。于是,在程序中我设计了4个类:CPoint、CObserve、CMatrix、Leveling,分别定义点的属性、观测数据属性、矩阵和水准网平差计算的属性与方法。

水准网平差计算一般步骤为:

(1)读取观测数据和已知数据;

(2)计算未知点高程近似值;

(3)列高差观测值误差方程;

(4)根据水准路线长度计算高差观测值的权;

(5)组成法方程;

(6)解法方程,求得未知点高程改正数及平差后高程值;

(7)求高差观测值残差及平差后高差观测值;

(8)精度评定;

(9)输出平差结果。

水准网高程近似值计算算法

4. 界面设计:

仅添加了一个button按钮,单击后读取数据,并进行水准网平差计算,计算结果保存在记事本中

5. 主要代码:

文件一: CPoint.h

代码:

class ControlPoint

{

public:

};

class CObserve

{

public:

CObserve(void){};

~CObserve(void){};

ControlPoint(void){};

~ControlPoint(void){};

CString pointID; //点号

double H; //高程

public:

public:

ControlPoint *pStartObs; //后视点

ControlPoint *pEndObs; //前视点

double h; //路线长度

double dDist; //高差

};

文件二:Leveling.h

代码:

#pragma once

#include "CPoint.h"

#include "Matrix.h"

class Leveling

{

public:

private:

public:

public:

public:

//组成误差方程,B 为系数矩阵,f为常数项向量

void Weight(CMatrix& P); //求高差观测值的权阵

void FormErrorEquations(CMatrix& B, CMatrix& f);

//根据点号从已知点数组中找到控制点,并返回该点的指针

ControlPoint* SearchKnownPointUsingID(CString pointID);

//根据点号从未知点数组中找到控制点,并返回该点的指针

ControlPoint* SearchUnknownPointUsingID(CString pointID);

//根据点号从未知点和已知点数组中找到控制点,并返回该点的指针

ControlPoint* SearchPointUsingID(CString pointID);

void ComputeApproximateH(void); //求待测点高差近似值

bool LoadData(const CString &FileName); //从文件中导入数据

void OutMatrixToFile(const CMatrix& mat,CStdioFile& SF); //把矩阵输出到文void SetKownPointSize(int n); //设置已知点数据大小

void SetUnknownPointSize(int n);

void SetObsDataSize(int n);

CString* SplitString(CString str , char split, int iSubStrs); //分割字符ControlPoint *m_pKnownPoint; //已知点数组

int m_iKnownPointCount; //已知点个数

int m_iUnknownPointCount; //待测点个数

CObserve *m_pObsData; //观测数据数组

int m_iObsDataCount; //观测数据个数

Leveling(void);

~Leveling(void);

ControlPoint *m_pUnknownPoint; //待测点数组

件中

};

void IndirectlyAdjust(const CString& strFileName);//间接平差计算主函数

文件三:

代码:

#include "StdAfx.h"

#include "Leveling.h"

#include "math.h"

#include

Leveling::Leveling(void)

{

}

Leveling::~Leveling(void)

{

}

bool Leveling::LoadData(const CString &FileName)

{

if(m_pKnownPoint!=NULL)

{

}

if(m_pObsData!=NULL)

{

}

delete[] m_pObsData;

m_pObsData=NULL;

delete[] m_pKnownPoint;

m_pKnownPoint=NULL;

//释放动态数组内存

if(m_pUnknownPoint!=NULL)

{

}

delete[] m_pUnknownPoint;

m_pUnknownPoint=NULL;

m_pKnownPoint=NULL;

m_iKnownPointCount=0;

m_pUnknownPoint=NULL;

m_iUnknownPointCount=0;

m_pObsData=NULL;

m_iObsDataCount=0;

CStdioFile sf; //创建文件对象

//以读的形式打开文件,如果打开失败则返回

if(!(FileName, CFile::modeRead)) return false;

CString strLine;

BOOL bEOF=ring(strLine);//读取第一行,已知点数

m_iKnownPointCount= _ttoi((strLine)); //把读取的第一行字符串转换为数值型

SetKownPointSize(m_iKnownPointCount);//设置已知点数组大小

int n=0;

//读取并保存已知点数据

{

}

//开始读取未知知点数据

m_iUnknownPointCount= _ttoi((strLine));

SetUnknownPointSize(m_iUnknownPointCount); //设置未知点数组大小

ring(strLine);//未知点点号

//读取并保存未知点数据

CString *pstrData=SplitString(strLine,',',n);

m_pKnownPoint[i].pointID=pstrData[0];

m_pKnownPoint[i].H=_tstof(pstrData[1]);

delete[] pstrData;

pstrData=NULL;

for(int i=0;i

ring(strLine);

ring(strLine);//未知点个数

CString *pstrData=SplitString(strLine,',',n);

{

}

delete[] pstrData;

pstrData=NULL;

m_pUnknownPoint[i].pointID=pstrData[i];

m_pUnknownPoint[i].H=0;

for(int i=0;i

//开始读取观测数据个数

ring(strLine);//观测数个数

m_iObsDataCount= _ttoi((strLine));

SetObsDataSize(m_iObsDataCount);

//读取并保存观测数据

for(int i=0;i

}

void Leveling::SetKownPointSize(int n)

{

}

void Leveling::SetUnknownPointSize(int n)

{

}

void Leveling::SetObsDataSize(int n)

{

}

//字符串分割函数

CString* Leveling::SplitString(CString str , char split, int iSubStrs)

{

int iPos = 0; //分割符位置

int iNums = 0; //分割符的总数

CString strTemp = str;

CString strRight;

//先计算子字符串的数量

while (iPos != -1)

m_iObsDataCount=n;

m_pObsData=new CObserve[n];

m_iUnknownPointCount=n;

m_pUnknownPoint=new ControlPoint[n];

m_iKnownPointCount=n;

m_pKnownPoint=new ControlPoint[n];

{

}

();

return true;

CString *pstrData=SplitString(strLine,',',n);

m_pObsData[i].pStartObs=SearchPointUsingID(pstrData[0]);

m_pObsData[i].pEndObs=SearchPointUsingID(pstrData[1]);

m_pObsData[i].h=_tstof(pstrData[2]);

m_pObsData[i].dDist=_tstof(pstrData[3]);

delete[] pstrData;

pstrData=NULL;

ring(strLine);

{

iPos = (split);

if (iPos == -1)

{

break;

}

strRight = (iPos + 1, gth());

strTemp = strRight;

iNums++;

}

if (iNums == 0) //没有找到分割符

{

//子字符串数就是字符串本身

iSubStrs = 1;

return NULL;

}

//子字符串数组

iSubStrs = iNums + 1; //子串的数量= 分割符数量+ 1

CString* pStrSplit;

pStrSplit = new CString[iSubStrs];

strTemp = str;

CString strLeft;

for (int i = 0; i < iNums; i++)

{

iPos = (split);

//左子串

strLeft = (iPos);

//右子串

strRight = (iPos + 1, gth());

strTemp = strRight;

pStrSplit[i] = strLeft;

}

pStrSplit[iNums] = strTemp;

return pStrSplit;

}

//根据点号从已知点数组中找到控制点,并返回该点的指针

ControlPoint* Leveling::SearchKnownPointUsingID(CString pointID)

{

for(int i=0;i

{

if(pointID==m_pKnownPoint[i].pointID)

{

}

}

}

return &m_pKnownPoint[i];

return NULL;

//根据点号从未知点数组中找到控制点,并返回该点的指针

ControlPoint* Leveling::SearchUnknownPointUsingID(CString pointID)

{

}

//根据点号从未知点和已知点数组中找到控制点,并返回该点的指针

ControlPoint* Leveling::SearchPointUsingID(CString pointID)

{

}

void Leveling::ComputeApproximateH(void) //求待测点近似高程

{

for(int i=0;i

{

if(m_pUnknownPoint[i].pointID==m_pObsData[j].pStartObs->pointID&&

else

m_pObsData[j].pEndObs->H>0)

if(m_pUnknownPoint[i].H!=0)

{

continue;

for(int j=0;j

ControlPoint* pCP=NULL;

pCP=SearchKnownPointUsingID(pointID);

if(pCP==NULL)

{

}

return pCP;

pCP=SearchUnknownPointUsingID(pointID);

for(int i=0;i

{

}

return NULL;

if(pointID==m_pUnknownPoint[i].pointID)

{

}

return &m_pUnknownPoint[i];

m_pUnknownPoint[i].H=m_pObsData[j].pEndObs->H-m_pObsData[j].h;

if(m_pUnknownPoint[i].pointID==m_pObsData[j].pEndObs->pointID&&

}

void Leveling::FormErrorEquations(CMatrix& B, CMatrix& f)

{

}

void Leveling::Weight(CMatrix& P) //计算权阵

{

}

void Leveling::IndirectlyAdjust(const CString& strFileName)

{

e(m_iObsDataCount,m_iObsDataCount);

for(int i=0;i

for(int j=0;j

{

}

if(i==j)

P(i,j)=1.0/m_pObsData[i].dDist;

f(i,0)=m_pObsData[i].h-(m_pObsData[i].pEndObs->H-m_pObsData[i].pStartObs->H);

//计算系数阵

for(int i=0;i

for(int j=0;j

{

}

if(m_pObsData[i].pStartObs->pointID==m_pUnknownPoint[j].pointID)

B(i,j)=-1;

B(i,j)=1;

if(m_pObsData[i].pEndObs->pointID==m_pUnknownPoint[j].pointID)

e(m_iObsDataCount, m_iUnknownPointCount);

e(m_iObsDataCount, 1);

}

}

m_pObsData[j].pStartObs->H>0)

m_pUnknownPoint[i].H=m_pObsData[j].pStartObs->H+m_pObsData[j].h;

//计算常数阵

for(int i=0;i

//使用最小二乘法计算平差值

//NBB=BT*P*B

CMatrix B; //系数矩阵

CMatrix BT; //B的转置矩阵

CMatrix NBB; //NBB

CMatrix invNbb; //NBB逆阵

CMatrix W; //W=BT*P*f

CMatrix f; //常数项矩阵

CMatrix P; //权阵

CMatrix x; //近似值改正项矩阵

CMatrix V; //改正项矩阵

CMatrix X; //平差值

ComputeApproximateH();

FormErrorEquations(B,f); //系数阵

Weight(P); //权阵

BT=~B; //B的转置矩阵

NBB=BT*P*B;

invNbb=();; //NBB逆阵

W=BT*P*f;

x=invNbb*W;

e(m_iUnknownPointCount,1);

for(int i=0;i

{

}

//精度评定

V=B*x-f;

//开始输出间接平差的结果

CStdioFile SF;

CString strLine;

setlocale(LC_ALL,"");

if(!(strFileName, CFile::modeCreate|CFile::modeWrite)) return;

X(i,0)=m_pUnknownPoint[i].H+x(i,0);

CMatrix Omiga; //方差

//开始写数据

tring(_T("----------水准网间接平差结果----------n"));

//写已知点数据

(_T("已知点个数:%dn"),m_iKnownPointCount);

tring(strLine);

for(int i=0;i

//输出系数阵和常数项

tring(_T("B矩阵:rn"));

OutMatrixToFile(B,SF);

tring(_T("高差改正数x(mm):rn"));

OutMatrixToFile(x,SF);

tring(_T("NBB矩阵:rn"));

//输出观测值残差

//计算单位权中误差,并输出

Omiga=~V*P*V;

tring(_T("观测值残差(mm):rn"));

OutMatrixToFile(V,SF);

OutMatrixToFile(NBB,SF);

tring(_T("NBB矩阵的逆矩阵:rn"));

OutMatrixToFile(invNbb,SF);

tring(_T("W矩阵:rn"));

OutMatrixToFile(W,SF);

//输出权矩阵

tring(_T("rnP矩阵(对角阵):rn"));

//待测点平差值

(_T("待测点个数:%dn"),m_iUnknownPointCount);

tring(strLine);

(_T("平差结果:n"));

tring(strLine);

{

}

m_pUnknownPoint[i].pointID,X(i,0));

{

}

m_pKnownPoint[i].pointID,m_pKnownPoint[i].H);

(_T("%s,%4fn"),

tring(strLine);

for(int i=0;i

(_T("%s,%4fn"),

tring(strLine);

OutMatrixToFile(P,SF);

double Sigma;

Sigma = sqrt(Omiga(0, 0) / (m_iObsDataCount - m_iUnknownPointCount));

(_T("单位权中误差(mm):%.4frn"),Sigma);

double Qx;

tring(_T("点位误差(mm):rn"));

();

}

//把矩阵输出到文件中

void Leveling::OutMatrixToFile(const CMatrix& mat,CStdioFile& SF)

{

CString strLine,strTmp;

for(int i=0;i<();i++)

{

}

}

();

for(int j=0;j<();j++)

{

}

tring(strLine+_T("rn"));

(_T("%.4f "),mat(i,j));

strLine=strLine+strTmp;

for(int i=0;i<();i++)

{

}

tring(_T("rn"));

Qx=sqrt(invNbb(i,i))*Sigma;

(_T("%.4f "),Qx);

tring(strLine);

tring(strLine);

文件四:Matrix.h

代码:

#pragma once

class CMatrix

{

public:

CMatrix(int row=3,int col=3);

// copy constructor

CMatrix (const CMatrix& m);

~CMatrix(void);

private:

double **dMatData;//保存矩阵元素数据的二维数组

int iRow;//矩阵的行

int iCol;//矩阵的列

public:

int Row() const {return iRow;}//返回行

int Col() const {return iCol;}//返回列

void SetSize (int row, int col);//调整数组的大小,原有数据不变(未测试)

double& operator () (int row, int col);//获取矩阵元素

double operator () (int row, int col) const;//重载获取矩阵元素函数,只有const对象能访问

CMatrix& operator = (const CMatrix& m) ;

//注意:友元函数并不是类自己的成员函数

friend CMatrix operator + (const CMatrix& m1,const CMatrix& m2);

friend CMatrix operator - (const CMatrix& m1,const CMatrix& m2);

friend CMatrix operator * (const CMatrix& m1,const CMatrix& m2);

friend CMatrix operator * (const double& num, const CMatrix& m1);

friend CMatrix operator * (const CMatrix& m1,const double& num);

friend CMatrix operator ~ (const CMatrix& m);//矩阵转置

CMatrix Inv();//矩阵求逆

void Unit();//生成单位矩阵

};

文件五:

代码:

void CLevelingAdjustDlg::OnBnClickedButton2()

{

// TODO: 在此添加控件通知处理程序代码

CFileDialog dlgFile(TRUE,_T("txt"),NULL,

OFN_EXPLORER,_T("(文本文件)|*.txt")); //创建打开文件对话框

if(l()==IDCANCEL) return;//如果选择取消按钮,则退出

CString strFileName=hName();//获取选择的文件的名称

Leveling ST;

ta(strFileName);

ctlyAdjust(_T(""));

MessageBox(_T("计算完毕!rn结果保存在文件中!"));

ShellExecute(this->m_hWnd,_T("open"),_T(""),

}

_T(""),_T(""),SW_SHOW );

6. 运行结果:

实验的运行结果如下图所示:

8. 实验总结

这次的实验让我对于面对对象的编程思想有了进一步的理解。以前的自己对于这个概念仅仅停留在了解层面,完全没有深入理解,更没有将之运用于编程实践中。这次实验的工作量是很庞大的,将我们所学的很多知识都串联起来了,因此收获也很大。

原来的我对数组很抵触,依次对内存的动态分配也不是很清楚,而这次试验中需要永达大量的动态数组,我也以为这方面的欠缺在程序运行时犯了很多内存溢出的错误。如下错误提示就出现过很多。

现在我明白了再给每一个数组或者矩阵赋值时,都要先给它分配内存,否则就会造成内存溢出而使程序中断。

由于对错误的恐惧,我编译时前都会将程序实现过程琢磨清除,编写时也会经常调试,因此编译基本上都能通过,但经常运行都会出现问题,这样我原来都不知道怎么去找错误的地方。现在通过断点调试,我能成功的找到出错的地方,再加上对变量的监测,调试不再是那么令人烦躁的了。

通过测绘程序设计课程,我从连编译都不会的菜鸟到现在能完成简单的程序设计,并顺利通过了计算机二级考试。真的很感谢这门课程,感谢这么负责任的戴老师,我以后也会更加努力的。谢谢!