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. 实验总结 这次的实验让我对于面对对象的编程思想有了进一步的理解。以前的自己对于这个概念仅仅停留在了解层面,完全没有深入理解,更没有将之运用于编程实践中。这次实验的工作量是很庞大的,将我们所学的很多知识都串联起来了,因此收获也很大。 原来的我对数组很抵触,依次对内存的动态分配也不是很清楚,而这次试验中需要永达大量的动态数组,我也以为这方面的欠缺在程序运行时犯了很多内存溢出的错误。如下错误提示就出现过很多。 现在我明白了再给每一个数组或者矩阵赋值时,都要先给它分配内存,否则就会造成内存溢出而使程序中断。 由于对错误的恐惧,我编译时前都会将程序实现过程琢磨清除,编写时也会经常调试,因此编译基本上都能通过,但经常运行都会出现问题,这样我原来都不知道怎么去找错误的地方。现在通过断点调试,我能成功的找到出错的地方,再加上对变量的监测,调试不再是那么令人烦躁的了。 通过测绘程序设计课程,我从连编译都不会的菜鸟到现在能完成简单的程序设计,并顺利通过了计算机二级考试。真的很感谢这门课程,感谢这么负责任的戴老师,我以后也会更加努力的。谢谢!


发布评论