资源描述
《测绘程序设计(VC.net)》
上机试验汇报
(Visual C++.Net)
班 级: 测绘0901班
学 号:
姓 名: 代娅琴
4月29日
试验八 平差程序设计基础
一、 试验目标
• 巩固过程定义和调用
• 巩固类创建和使用
• 巩固间接平差模型及平差计算
• 掌握平差程序设计基础技巧和步骤
二、 试验内容
水准网平差程序设计。设计一个水准网平差程序,要求数据从文件中读取,
计算部分和界面无关。
1. 水准网间接平差模型:
2. 计算示例:
近似高程计算:
3. 水准网平差计算通常步骤
(1)读取观察数据和已知数据;
(2)计算未知点高程近似值;
(3)列高差观察值误差方程;
(4)依据水准路线长度计算高差观察值权;
(5)组成法方程;
(6)解法方程,求得未知点高程更正数及平差后高程值;
(7)求高差观察值残差及平差后高差观察值;
(8)精度评定;
(9)输出平差结果。
4. 水准网高程近似值计算算法
5. 输入数据格式示例
试验代码:
#pragma once
class LevelControlPoint
{
public:
LevelControlPoint(void);
~LevelControlPoint(void);
public:
CString strName;//点名
CString strID;//点号
float H;
bool flag;//标识是否已经计算出近似高程值,若计算出则为,不然为
};
class CDhObs
{
public:
CDhObs(void);
~CDhObs(void);
public:
LevelControlPoint* cpBackObj;//后视点
LevelControlPoint* cpFrontObj;//前视点
double ObsValue;//高差值
double Dist;//测站距离
};
#include "StdAfx.h"
#include "LevelControlPoint.h"
LevelControlPoint::LevelControlPoint(void)
{
strName=_T("");
strID=_T("");
H=0;
flag=0;
}
LevelControlPoint::~LevelControlPoint(void)
{
}
CDhObs::CDhObs(void)
{
}
CDhObs::~CDhObs(void)
{
}
#pragma once
#include"LevelControlPoint.h"
#include "Matrix.h"
class AdjustLevel
{
public:
AdjustLevel(void);
~AdjustLevel(void);
public:
LevelControlPoint* m_pKnownPoint;//已知点数组
int m_iKnownPointCount;//已知点个数
LevelControlPoint* m_pUnknownPoint;//未知点数组
int m_iUnknownPointCount;//未知点个数
CDhObs* m_pDhObs;//高差观察值数组
int m_iDhObsCount;//高差观察值个数
public:
void SetKnownPointSize(int size);//创建大小为size已知点数组
void SetUnkonwnPointSize(int size);//创建大小为size未知点数组
void SetDhObsSize(int size);//创建大小为size观察值数组
bool LoadObsData(const CString& strFile);//读入观察文件
CString* SplitString(CString str, char split, int& iSubStrs);
void ApproHeignt(void);//计算近似值
private:
LevelControlPoint* SearchKnownPointUsingID(CString ID);
LevelControlPoint* SearchUnknownPointUsingID(CString ID);
LevelControlPoint* SearchPointUsingID(CString ID);
CMatrix LevleWeight(void);//计算权矩阵
public:
void FormErrorEquation(CMatrix &B, CMatrix &L);//组成误差方程
void EquationCompute(CMatrix &x);//计算法方程
void Accuracy_Assessment(double &r0,CMatrix &Qxx);//精度评定
void CompAdjust(double &r0,CMatrix Qx[]);
};
#include "StdAfx.h"
#include "AdjustLevel.h"
#include <locale.h>
#include "LevelControlPoint.h"
#include "math.h"
AdjustLevel::AdjustLevel(void)
{
m_pKnownPoint=NULL;//已知点数组
m_iKnownPointCount=0;//已知点个数
m_pUnknownPoint=NULL;//未知点数组
m_iUnknownPointCount=0;//未知点个数
m_pDhObs=NULL;//高差观察值数组
m_iDhObsCount=0;//高差观察值个数
}
AdjustLevel::~AdjustLevel(void)
{
if(m_pKnownPoint!=NULL)
{
delete[] m_pKnownPoint;
m_pKnownPoint=NULL;
}
if(m_pUnknownPoint!=NULL)
{
delete[] m_pUnknownPoint;
m_pUnknownPoint=NULL;
}
if(m_pDhObs!=NULL)
{
delete[] m_pDhObs;
m_pDhObs=NULL;
}
}
void AdjustLevel::SetKnownPointSize(int size)
{
m_pKnownPoint=new LevelControlPoint[size];//创建动态指针
m_iKnownPointCount=size;
}
void AdjustLevel::SetUnkonwnPointSize(int size)
{
m_pUnknownPoint=new LevelControlPoint[size];
m_iUnknownPointCount=size;
}
void AdjustLevel::SetDhObsSize(int size)
{
m_pDhObs=new CDhObs[size];
m_iDhObsCount=size;//高差观察值个数
}
bool AdjustLevel::LoadObsData(const CString& strFile)
{
CStdioFile sf;
if(!sf.Open(strFile,CFile::modeRead)) return false;//创建并打开文件对象
CString strLine;
bool bEOF=sf.ReadString(strLine);//读取第一行,即已知点数目
SetKnownPointSize(_ttoi(strLine));//依据已知点数目,创建已知点数组;
int n=0;
for(int i=0;i<m_iKnownPointCount;i++)//读取已知点点名和高程值
{
sf.ReadString(strLine);
CString *pstrData=SplitString(strLine,',',n);
m_pKnownPoint[i].strName=pstrData[0];
m_pKnownPoint[i].strID=pstrData[0];
m_pKnownPoint[i].H=_tstof(pstrData[1]);
m_pKnownPoint[i].flag=1;//已知点不用平差,故将其flag设置为
delete[] pstrData;
pstrData=NULL;
}
sf.ReadString(strLine);//读取未知点个数
SetUnkonwnPointSize(_ttoi(strLine));//依据未知点个数创建未知点数组
sf.ReadString(strLine);//读取未知点点名
CString *pstrData=SplitString(strLine,',',n);
for(int i=0;i<m_iUnknownPointCount;i++)//将未知点点名放入未知点数组
{
m_pUnknownPoint[i].strName=pstrData[i];
m_pUnknownPoint[i].strID=pstrData[i];
m_pUnknownPoint[i].H=0;//未知点高程值设置为
m_pUnknownPoint[i].flag=0;//还没有求得近似高程,故其flag设置为
}
if(pstrData!=NULL)
{
delete[] pstrData;
pstrData=NULL;
}
sf.ReadString(strLine);//读取观察值个数
SetDhObsSize(_ttoi(strLine));//根据观察值大小,创建观察值数组
for(int i=0;i<m_iDhObsCount;i++)//分行读取观察值数据,将其存入观察值数组
{
sf.ReadString(strLine);
CString *pstrData=SplitString(strLine,',',n);
m_pDhObs[i].cpBackObj=SearchPointUsingID(pstrData[0]);//后视点
m_pDhObs[i].cpFrontObj=SearchPointUsingID(pstrData[1]);//前视点
m_pDhObs[i].HObsValue=_tstof(pstrData[2]);//高差观察值
m_pDhObs[i].Dist=_tstof(pstrData[3]);//距离观察值
delete[] pstrData;
pstrData=NULL;
}
sf.Close();
return 1;
}
CString* AdjustLevel::SplitString(CString str, char split, int& iSubStrs)
{
int iPos = 0; //分割符位置
int iNums = 0; //分割符总数
CString strTemp = str;
CString strRight;
//先计算子字符串数量
while (iPos != -1)
{
iPos = strTemp.Find(split);
if (iPos == -1)
{
break;
}
strRight = strTemp.Mid(iPos + 1, str.GetLength());
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 = strTemp.Find(split);
//左子串
strLeft = strTemp.Left(iPos);
//右子串
strRight = strTemp.Mid(iPos + 1, strTemp.GetLength());
strTemp = strRight;
pStrSplit[i] = strLeft;
}
pStrSplit[iNums] = strTemp;
return pStrSplit;
}
//
LevelControlPoint* AdjustLevel::SearchKnownPointUsingID(CString ID)
{
for(int i=0;i<m_iKnownPointCount;i++)
{
if(m_pKnownPoint[i].strID==ID)
{return &m_pKnownPoint[i];}
}
return NULL;
}
//
LevelControlPoint* AdjustLevel::SearchUnknownPointUsingID(CString ID)
{
for(int i=0;i<m_iUnknownPointCount;i++)
{
if(m_pUnknownPoint[i].strID==ID)
{return &m_pUnknownPoint[i];}
}
return NULL;
}
LevelControlPoint* AdjustLevel::SearchPointUsingID(CString ID)
{
LevelControlPoint* cp;
cp=SearchKnownPointUsingID(ID);
if(cp==NULL)
cp=SearchUnknownPointUsingID(ID);
return cp;
}
void AdjustLevel::ApproHeignt(void)//用于计算高程近似值函数
{
for(int i=0;i<m_iUnknownPointCount;i++)//计算未知点高程值
{
if(m_pUnknownPoint[i].flag!=1)
{
//先在未知点作为观察值前视点情况
for(int j=0;j<m_iDhObsCount;j++)//从观察数组里找和未知点相关联点
{//假如观察值前视点是未知点且其后视点已经有高程值
if((m_pDhObs[j].cpFrontObj->strID==m_pUnknownPoint[i].strID)
&& m_pDhObs[j].cpBackObj->flag==1 )
{ //前视点=后视点-高差
/*m_pUnknownPoint[i].H=m_pDhObs[i].cpBackObj->H - m_pDhObs[i].ObsValue;*/
m_pUnknownPoint[i].H=m_pDhObs[j].cpBackObj->H + m_pDhObs[j].HObsValue;
m_pUnknownPoint[i].flag=1;
break;
}
}
if(m_pUnknownPoint[i].flag!=1)//假如经过上一步骤未知点仍没有计算出近似值
{
for(int j=0;j<m_iDhObsCount;j++)//从观察数组里找和未知点相关联点
{//假如观察值后视点是未知点且其前视点已经有高程值
if((m_pDhObs[j].cpBackObj->strID==m_pUnknownPoint[i].strID)
&& m_pDhObs[j].cpFrontObj->flag==1 )
{ //后视点=前视点+高差
m_pUnknownPoint[i].H=m_pDhObs[j].cpFrontObj->H-m_pDhObs[j].HObsValue;
/* m_pUnknownPoint[i].H=m_pDhObs[i].cpFrontObj->H+m_pDhObs[i].ObsValue;*/
m_pUnknownPoint[i].flag=1;
break;
}
}
}
}
if(i==m_iUnknownPointCount-1)//假如已经计算到最终一个未知点
{
for(int a=0;a<m_iUnknownPointCount;a++)
{
if(m_pUnknownPoint[i].flag!=1)//只要有一个未知点近似高程直没有计算
{ //则要重新进行上面步骤直到全部未知点近似高程值全部计算出
i=-1;
break;
}
}
}
}
}
CMatrix AdjustLevel::LevleWeight(void)
{
CMatrix p(m_iDhObsCount,m_iDhObsCount);
p.Unit();
double value;
for(int i=0;i<m_iDhObsCount;i++)
{
value=(1.0/m_pDhObs[i].Dist);
p(i,i)=value;
}
return p;
}
void AdjustLevel::FormErrorEquation(CMatrix &B, CMatrix &L)
{
B.SetSize(m_iDhObsCount,m_iUnknownPointCount);
L.SetSize(m_iDhObsCount,1);
for(int i=0;i<m_iDhObsCount;i++)//建立B系数阵
{
LevelControlPoint *tmpBack=NULL,*tmpFront=NULL;
tmpBack=SearchPointUsingID(m_pDhObs[i].cpBackObj->strID);
tmpFront=SearchPointUsingID(m_pDhObs[i].cpFrontObj->strID);
//找到和第i个观察值相关未知点
tmpBack->strID;
for(int j=0;j<m_iUnknownPointCount;j++)
{
if(m_pUnknownPoint[j].strID==tmpBack->strID)//假如是后视点则前面系数为-1
{ B(i,j)=-1;continue;
}
if(m_pUnknownPoint[j].strID==tmpFront->strID)//假如是前视点则前面系数为
{
B(i,j)=1;
}
}
}
//建立L矩阵
CString tmp;
for(int i=0;i<m_iDhObsCount;i++)
{
//l=高差观察值-(后视近似值-前视近似值)
/*L(i,0)=m_pDhObs[i].ObsValue-(m_pDhObs[i].cpBackObj->H-m_pDhObs[i].cpFrontObj->H);*/
L(i,0)=m_pDhObs[i].HObsValue-(m_pDhObs[i].cpFrontObj->H - m_pDhObs[i].cpBackObj->H);
tmp.Format(_T("%.3f"),L(i,0));
L(i,0)=_tstof(tmp);
L(i,0)=L(i,0)*1000;//将单位化为mm
}
}
void AdjustLevel::EquationCompute(CMatrix &x)//计算法方程
{
CMatrix P,B,l;
P=LevleWeight(); //P为权矩阵
FormErrorEquation(B,l);
ApproHeignt();
CMatrix BT(m_iUnknownPointCount,m_iDhObsCount);
BT=~B; //B转置矩阵
CMatrix NBB(m_iUnknownPointCount,m_iUnknownPointCount);
NBB=BT*P*B;
CMatrix NBBl=NBB.Inv();
x=NBBl*BT*P*l;
for(int i=0;i<m_iUnknownPointCount;i++)
{
m_pUnknownPoint[i].H+=x(i,0);//未知点高程值=近似值+更正数
}
}
void AdjustLevel::Accuracy_Assessment(double &r0,CMatrix &Qxx)//精度评定
{
CMatrix B,l,P,x;
P=LevleWeight(); //P为权矩阵
FormErrorEquation(B,l);
EquationCompute(x);
CMatrix v(m_iDhObsCount,1);
v=B*x-l;
CMatrix vT(1,m_iDhObsCount);
vT=~v;
CMatrix r/*(1,l)*/;
r=vT*P*v;
r0=sqrt(r(0,0)/(m_iDhObsCount-m_iUnknownPointCount));//单位权中误差
Qxx.SetSize(m_iUnknownPointCount,m_iUnknownPointCount);
CMatrix BT(m_iUnknownPointCount,m_iDhObsCount);
BT=~B;
CMatrix NBB(m_iUnknownPointCount,m_iUnknownPointCount);
NBB=BT*P*B;
Qxx=NBB.Inv();
}
void AdjustLevel::CompAdjust(double &r0,CMatrix Qx[])
{
ApproHeignt();//计算未知点近似高程值而且存入数组
CMatrix P(m_iDhObsCount,m_iDhObsCount);
P=LevleWeight();//p为权矩阵
CMatrix B,L;
CMatrix x,Qxx;
FormErrorEquation(B,L);//组成误差方程,B为系数矩阵,l为常数项
EquationCompute(x);//计算法方程
Accuracy_Assessment(r0,Qxx);//精度评定
for(int i=0;i<m_iUnknownPointCount;i++)//未知点高程中误差
{
Qx[i]=sqrt(Qxx(i,i))*r0;
}
}
#include "Matrix.h"
#include "locale.h"
#include "LevelControlPoint.h"
#include "AdjustLevel.h"
AdjustLevel LevelComput;
CString* SplitString(CString str, char split, int& iSubStrs)
{
int iPos = 0; //分割符位置
int iNums = 0; //分割符总数
CString strTemp = str;
CString strRight;
//先计算子字符串数量
while (iPos != -1)
{
iPos = strTemp.Find(split);
if (iPos == -1)
{
break;
}
strRight = strTemp.Mid(iPos + 1, str.GetLength());
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 = strTemp.Find(split);
//左子串
strLeft = strTemp.Left(iPos);
//右子串
strRight = strTemp.Mid(iPos + 1, strTemp.GetLength());
strTemp = strRight;
pStrSplit[i] = strLeft;
}
pStrSplit[iNums] = strTemp;
return pStrSplit;
}
void CIndircLelveDlg::OnBnClickedOpendatafile()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
CFileDialog dlgFile(TRUE,_T("txt"),NULL,OFN_ALLOWMULTISELECT|OFN_EXPLORER,
_T("(文本文件)|*.txt"));//创建文件对话框
if(dlgFile.DoModal()==IDCANCEL) return;//假如选择取消按钮则返回
CString strFileName=dlgFile.GetPathName();//打开获取文件文件名
setlocale(LC_ALL,""); //设置语言环境
CStdioFile sf;
if(!sf.Open(strFileName, CFile::modeRead)) return;
InputContent.Empty();//清空字符串str_openContent中内容
CString strLine;
BOOL bEOF=sf.ReadString(strLine);//读取第一行数据
while(bEOF)//开始读取顶点数据
{
bEOF=sf.ReadString(strLine);
if(bEOF)
InputContent+=strLine+_T("\r\n");
}
sf.Close();
UpdateData(FALSE);
}
void CIndircLelveDlg::OnBnClickedSavedata()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
CFileDialog dlgFile(FALSE,_T("txt"),NULL,OFN_EXPLORER,
_T("(Level格式)|*.txt"));
if(dlgFile.DoModal()==IDCANCEL) return;
CString strFileName=dlgFile.GetPathName();
setlocale(LC_ALL,"");
CStdioFile sf;
if(!sf.Open(strFileName, CFile::modeCreate|CFile::modeWrite)) return;
sf.WriteString(LevleContent);
sf.Close();
UpdateData(FALSE);
}
void CIndircLelveDlg::OnBnClickedComputelevel()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
setlocale(LC_ALL,"");
double *Qx=new double[LevelComput.m_iUnknownPointCount];
double r0;
LevelComput.CompAdjust(r0,Qx);
LevleContent.Format(_T("平差后高程值:\r\n"));
CString Temp;
for(int i=0;i<LevelComput.m_iUnknownPointCount;i++)
{
Temp.Empty();
Temp.Format(_T("%s,%.4f\r\n"), LevelComput.m_pUnknownPoint[i].strID,LevelComput.m_pUnknownPoint[i].H);
LevleContent+=Temp;
}
Temp.Format(_T("单位权中误差:%.1f mm\r\n"),r0*1000);
LevleContent+=Temp;
LevleContent+=_T("未知点高程中误差(mm):\r\n");
for(int i=0;i< LevelComput.m_iUnknownPointCount;i++)
{
Temp.Empty();
Temp.Format(_T("%s,%.1f\r\n"),LevelComput.m_pUnknownPoint[i].strName,Qx[i]*1000);
LevleContent+=Temp;
}
UpdateData(false);
}
void CIndircLelveDlg::OnBnClickedSavelevleresult()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
CFileDialog dlgFile(FALSE,_T("txt"),NULL,OFN_EXPLORER,
_T("(Level格式)|*.txt"));
if(dlgFile.DoModal()==IDCANCEL) return;
CString strFileName=dlgFile.GetPathName();
setlocale(LC_ALL,"");
CStdioFile sf;
if(!sf.Open(strFileName, CFile::modeCreate|CFile::modeWrite)) return;
sf.WriteString(LevleContent);
sf.Close();
UpdateData(FALSE);
}
三、 试验结果
打开文件数据:
平差结果:
四、试验心得
这从试验是我们测绘程序设计最终一次试验,即使这个学期我们做了好几次相关试验,不过我却发觉自己学东西也越来越模糊,感觉很多内容全部不了解。这次试验很大程度上我全部是根据《测绘程序设计》上面单导线简易计算来编,在加上后面相关水准网间接平差误差方程和法方程,和精度评定相关函数,来完成。而自己关键完成就是水准网数据读取,保留操作,因为这部分关键用知识是文件读取,因为前面做过,所以不是太难。不过这并不意味着这次试验很简单,最少在我心中这确实比较难,因为里面很多东西不是纯粹把代码写上去就能够完成,还要靠自己做对应代码对应,才能够真正得到想要结果。但学好编程并扎实为自己所用是需要更多学习和练习,我知道在掌握课堂知识同时,主动去寻求吸收相关知识,期望经过本门课程学习,掌握学习编程方法,使自己水平能够更深入,循序渐进掌握更多。即使这门课试验已经结束,不过我却深深地知道,我们专业对编程要求很高,而且必需含有很好编程能力,或许这些日子下来,我学到不是很多,不过我或多或少明白,编程是一个循序渐进过程,我想真能够在这方面有所突破,就更要花时间多花工夫。
展开阅读全文