误差理论与测量平差
课程设计报告
l 课程名称:误差理论与测量平差
l 课程题目: 平差计算器
l 姓名: 江记洲
l 专业: 测绘工程
l 学号: 20104166
l 学院: 土木与水利工程学院
l 学校: 合肥工业大学
l 指导老师: 陶庭叶
一、 实验目的与要求
1) 实验目的:此次的课程设计可以用任何一种计算机语言来编写,这样给我们每个人很多的选择。同时这样也是为了练习同学们对于一门语言的掌握和运用,大大的提高了我们的编程能力。同时,通过对测量数据的误差处理,增强学生对《误差理论与测量平差基础》课程的理解,使学生牢固掌握测量数据处理的基本原理和公式,熟悉测量数据处理的基本技能和计算方法。要求学生综合运用测绘知识、测量平差知识、数学知识和计算机知识,设计数学模型和程序算法,编制程序实现测量数据的自动化处理。
2) 实验要求:要求每位同学独立完成给定测量数据处理的数学模型和算法的设计,编写程序,调测程序,并编写程序设计文档。要求数学模型和算法正确、程序运行正确、设计文档完备。
二、 课程设计主要内容
课程设计的主要内容主要有:
1. 新建一个基于单文档的MFC应用程序。
这只是基本的框架结构,里面包含了几个已知的类,在这些类的基础上,可以增加对象和变量。
然后是增加一个操作矩阵的类 CMatrix 的实现文件,Matrix.cpp和Matrix.h文件是从网上下载的,然后添加工程,创建了一个类,进行矩阵的计算。通过运算符的重载,可以进行加减乘除计算,还可以进行矩阵的转置和求逆等运算。现将该程序的Matrix.cpp文件附录如下:
// Matrix.cpp
#include "StdAfx.h"
#include "Matrix.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// Construction/Destruction
// 基本构造函数
CMatrix::CMatrix()
{
m_nNumColumns = 1;
m_nNumRows = 1;
m_pData = NULL;
BOOL bSuccess = Init(m_nNumRows, m_nNumColumns);
ASSERT(bSuccess);
}
// 指定行列构造函数
// 参数:
// 1. int nRows - 指定的矩阵行数
// 2. int nCols - 指定的矩阵列数
CMatrix::CMatrix(int nRows, int nCols)
{
m_nNumRows = nRows;
m_nNumColumns = nCols;
m_pData = NULL;
BOOL bSuccess = Init(m_nNumRows, m_nNumColumns);
ASSERT(bSuccess);
}
// 初始化函数
// 参数:
// 1. int nRows - 指定的矩阵行数
// 2. int nCols - 指定的矩阵列数
//
// 返回值:BOOL 型,初始化是否成功
BOOL CMatrix::Init(int nRows, int nCols)
{
if (m_pData)
{
delete[] m_pData;
m_pData = NULL;
}
m_nNumRows = nRows;
m_nNumColumns = nCols;
int nSize = nCols*nRows;
if (nSize < 0)
return FALSE;
// 分配内存
m_pData = new double[nSize];
if (m_pData == NULL)
return FALSE; // 内存分配失败
if (IsBadReadPtr(m_pData, sizeof(double) * nSize))
return FALSE;
// 将各元素值置0
memset(m_pData, 0, sizeof(double) * nSize);
return TRUE;
}
// 指定值构造函数
// 参数:
// 1. int nRows - 指定的矩阵行数
// 2. int nCols - 指定的矩阵列数
// 3. double value[] - 一维数组,长度为nRows*nCols,存储矩阵各元素的值
CMatrix::CMatrix(int nRows, int nCols, double value[])
{
m_nNumRows = nRows;
m_nNumColumns = nCols;
m_pData = NULL;
BOOL bSuccess = Init(m_nNumRows, m_nNumColumns);
ASSERT(bSuccess);
SetData(value);
}
// 设置矩阵各元素的值
// 参数:
// 1. double value[] - 一维数组,长度为m_nNumColumns*m_nNumRows,存储
// 矩阵各元素的值
// 返回值:无
void CMatrix::SetData(double value[])
{
// empty the memory
memset(m_pData, 0, sizeof(double) * m_nNumColumns*m_nNumRows);
// copy data
memcpy(m_pData, value, sizeof(double)*m_nNumColumns*m_nNumRows);
}
// 方阵构造函数
// 参数:
// 1. int nSize - 方阵行列数
CMatrix::CMatrix(int nSize)
{
m_nNumRows = nSize;
m_nNumColumns = nSize;
m_pData = NULL;
BOOL bSuccess = Init(nSize, nSize);
ASSERT (bSuccess);
}
// 方阵构造函数
// 参数:
// 1. int nSize - 方阵行列数
// 2. double value[] - 一维数组,长度为nRows*nRows,存储方阵各元素的值
CMatrix::CMatrix(int nSize, double value[])
{
m_nNumRows = nSize;
m_nNumColumns = nSize;
m_pData = NULL;
BOOL bSuccess = Init(nSize, nSize);
ASSERT (bSuccess);
SetData(value);
}
// 拷贝构造函数
// 参数:
// 1. const CMatrix& other - 源矩阵
CMatrix::CMatrix(const CMatrix& other)
{
m_nNumColumns = other.GetNumColumns();
m_nNumRows = other.GetNumRows();
m_pData = NULL;
BOOL bSuccess = Init(m_nNumRows, m_nNumColumns);
ASSERT(bSuccess);
// copy the pointer
memcpy(m_pData, other.m_pData, sizeof(double)*m_nNumColumns*m_nNumRows);
}
// 析构函数
CMatrix::~CMatrix()
{
if (m_pData)
{
delete[] m_pData;
m_pData = NULL;
}
}
// 将方阵初始化为单位矩阵
// 参数:
// 1. int nSize - 方阵行列数
// 返回值:BOOL 型,初始化是否成功
BOOL CMatrix::MakeUnitMatrix(int nSize)
{
if (! Init(nSize, nSize))
return FALSE;
for (int i=0; i<nSize; ++i)
for (int j=0; j<nSize; ++j)
if (i == j)
SetElement(i, j, 1);
return TRUE;
}
// 将字符串转化为矩阵的值
// 参数:
// 1. CString s - 数字和分隔符构成的字符串
// 2. const CString& sDelim - 数字之间的分隔符,默认为空格
// 3. BOOL bLineBreak - 行与行之间是否有回车换行符,默认为真(有换行符)
// 当该参数为FALSE时,所有元素值都在一行中输入,字符串的第一个
// 数值应为矩阵的行数,第二个数值应为矩阵的列数
// 返回值:BOOL 型,转换是否成功
BOOL CMatrix::FromString(CString s, const CString& sDelim /*= " "*/, BOOL bLineBreak /*= TRUE*/)
{
if (s.IsEmpty())
return FALSE;
// 分行处理
if (bLineBreak)
{
CTokenizer tk(s, "\r\n");
CStringList ListRow;
CString sRow;
while (tk.Next(sRow))
{
sRow.TrimLeft();
sRow.TrimRight();
if (sRow.IsEmpty())
break;
ListRow.AddTail(sRow);
}
// 行数
m_nNumRows = ListRow.GetCount();
sRow = ListRow.GetHead();
CTokenizer tkRow(sRow, sDelim);
CString sElement;
// 列数
m_nNumColumns = 0;
while (tkRow.Next(sElement))
{
m_nNumColumns++;
}
// 初始化矩阵
if (! Init(m_nNumRows, m_nNumColumns))
return FALSE;
// 设置值
POSITION pos = ListRow.GetHeadPosition();
for (int i=0; i<m_nNumRows; i++)
{
sRow = ListRow.GetNext(pos);
int j = 0;
CTokenizer tkRow(sRow, sDelim);
while (tkRow.Next(sElement))
{
sElement.TrimLeft();
sElement.TrimRight();
double v = atof(sElement);
SetElement(i, j++, v);
}
}
return TRUE;
}
// 不分行(单行)处理
CTokenizer tk(s, sDelim);
CString sElement;
// 行数
tk.Next(sElement);
sElement.TrimLeft();
sElement.TrimRight();
m_nNumRows = atoi(sElement);
// 列数
tk.Next(sElement);
sElement.TrimLeft();
sElement.TrimRight();
m_nNumColumns = atoi(sElement);
// 初始化矩阵
if (! Init(m_nNumRows, m_nNumColumns))
return FALSE;
// 设置值
int i = 0, j = 0;
while (tk.Next(sElement))
{
sElement.TrimLeft();
sElement.TrimRight();
double v = atof(sElement);
SetElement(i, j++, v);
if (j == m_nNumColumns)
{
j = 0;
i++;
if (i == m_nNumRows)
break;
}
}
return TRUE;
}
// 将矩阵各元素的值转化为字符串
//
// 参数:
// 1. const CString& sDelim - 数字之间的分隔符,默认为空格
// 2 BOOL bLineBreak - 行与行之间是否有回车换行符,默认为真(有换行符)
//
// 返回值:CString 型,转换得到的字符串
CString CMatrix::ToString(const CString& sDelim /*= " "*/, BOOL bLineBreak /*= TRUE*/) const
{
CString s="";
for (int i=0; i<m_nNumRows; ++i)
{
for (int j=0; j<m_nNumColumns; ++j)
{
CString ss;
ss.Format("%f", GetElement(i, j));
s += ss;
if (bLineBreak)
{
if (j != m_nNumColumns-1)
s += sDelim;
}
else
{
if (i != m_nNumRows-1 || j != m_nNumColumns-1)
s += sDelim;
}
}
if (bLineBreak)
if (i != m_nNumRows-1)
s += "\r\n";
}
return s;
}
// 将矩阵指定行中各元素的值转化为字符串
// 参数:
// 1. int nRow - 指定的矩阵行,nRow = 0表示第一行
// 2. const CString& sDelim - 数字之间的分隔符,默认为空格
// 返回值:CString 型,转换得到的字符串
CString CMatrix::RowToString(int nRow, const CString& sDelim /*= " "*/) const
{
CString s = "";
if (nRow >= m_nNumRows)
return s;
for (int j=0; j<m_nNumColumns; ++j)
{
CString ss;
ss.Format("%f", GetElement(nRow, j));
s += ss;
if (j != m_nNumColumns-1)
s += sDelim;
}
return s;
}
// 将矩阵指定列中各元素的值转化为字符串
// 参数:
// 1. int nCol - 指定的矩阵行,nCol = 0表示第一列
// 2. const CString& sDelim - 数字之间的分隔符,默认为空格
// 返回值:CString 型,转换得到的字符串
CString CMatrix::ColToString(int nCol, const CString& sDelim /*= " "*/) const
{
CString s = "";
if (nCol >= m_nNumColumns)
return s;
for (int i=0; i<m_nNumRows; ++i)
{
CString ss;
ss.Format("%f", GetElement(i, nCol));
s += ss;
if (i != m_nNumRows-1)
s += sDelim;
}
return s;
}
// 设置指定元素的值
// 参数:
// 1. int nRows - 指定的矩阵行数
// 2. int nCols - 指定的矩阵列数
// 3. double value - 指定元素的值
// 返回值:BOOL 型,说明设置是否成功
BOOL CMatrix::SetElement(int nRow, int nCol, double value)
{
if (nCol < 0 || nCol >= m_nNumColumns || nRow < 0 || nRow >= m_nNumRows)
return FALSE; // array bounds error
if (m_pData == NULL)
return FALSE; // bad pointer error
m_pData[nCol + nRow * m_nNumColumns] = value;
return TRUE;
}
// 设置指定元素的值
// 参数:
// 1. int nRows - 指定的矩阵行数
// 2. int nCols - 指定的矩阵列数
// 返回值:double 型,指定元素的值
double CMatrix::GetElement(int nRow, int nCol) const
{
ASSERT(nCol >= 0 && nCol < m_nNumColumns && nRow >= 0 && nRow < m_nNumRows); // array bounds error
ASSERT(m_pData); // bad pointer error
return m_pData[nCol + nRow * m_nNumColumns] ;
}
// 获取矩阵的列数
// 参数:无
// 返回值:int 型,矩阵的列数
int CMatrix::GetNumColumns() const
{
return m_nNumColumns;
}
// 获取矩阵的行数
// 参数:无
// 返回值:int 型,矩阵的行数
int CMatrix::GetNumRows() const
{
return m_nNumRows;
}
// 获取矩阵的数据
// 参数:无
// 返回值:double型指针,指向矩阵各元素的数据缓冲区
double* CMatrix::GetData() const
{
return m_pData;
}
// 获取指定行的向量
// 参数:
// 1. int nRows - 指定的矩阵行数
// 2. double* pVector - 指向向量中各元素的缓冲区
// 返回值:int 型,向量中元素的个数,即矩阵的列数
int CMatrix::GetRowVector(int nRow, double* pVector) const
{
if (pVector == NULL)
delete pVector;
pVector = new double[m_nNumColumns];
ASSERT(pVector != NULL);
for (int j=0; j<m_nNumColumns; ++j)
pVector[j] = GetElement(nRow, j);
return m_nNumColumns;
}
// 获取指定列的向量
// 参数:
// 1. int nCols - 指定的矩阵列数
// 2. double* pVector - 指向向量中各元素的缓冲区
// 返回值:int 型,向量中元素的个数,即矩阵的行数
int CMatrix::GetColVector(int nCol, double* pVector) const
{
if (pVector == NULL)
delete pVector;
pVector = new double[m_nNumRows];
ASSERT(pVector != NULL);
for (int i=0; i<m_nNumRows; ++i)
pVector[i] = GetElement(i, nCol);
return m_nNumRows;
}
// 重载运算符=,给矩阵赋值
// 参数:
// 1. const CMatrix& other - 用于给矩阵赋值的源矩阵
// 返回值:CMatrix型的引用,所引用的矩阵与other相等
CMatrix& CMatrix::operator=(const CMatrix& other)
{
if (&other != this)
{
BOOL bSuccess = Init(other.GetNumRows(), other.GetNumColumns());
ASSERT(bSuccess);
// copy the pointer
memcpy(m_pData, other.m_pData, sizeof(double)*m_nNumColumns*m_nNumRows);
}
// finally return a reference to ourselves
return *this ;
}
// 重载运算符==,判断矩阵是否相等
// 参数:
// 1. const CMatrix& other - 用于比较的矩阵
// 返回值:BOOL 型,两个矩阵相等则为TRUE,否则为FALSE
BOOL CMatrix::operator==(const CMatrix& other) const
{
// 首先检查行列数是否相等
if (m_nNumColumns != other.GetNumColumns() || m_nNumRows != other.GetNumRows())
return FALSE;
for (int i=0; i<m_nNumRows; ++i)
{
for (int j=0; j<m_nNumColumns; ++j)
{
if (GetElement(i, j) != other.GetElement(i, j))
return FALSE;
}
}
return TRUE;
}
// 重载运算符!=,判断矩阵是否不相等
// 参数:
// 1. const CMatrix& other - 用于比较的矩阵
// 返回值:BOOL 型,两个不矩阵相等则为TRUE,否则为FALSE
BOOL CMatrix::operator!=(const CMatrix& other) const
{
return !(*this == other);
}
// 重载运算符+,实现矩阵的加法
// 参数:
// 1. const CMatrix& other - 与指定矩阵相加的矩阵
// 返回值:CMatrix型,指定矩阵与other相加之和
CMatrix CMatrix::operator+(const CMatrix& other) const
{
// 首先检查行列数是否相等
ASSERT (m_nNumColumns == other.GetNumColumns() && m_nNumRows == other.GetNumRows());
// 构造结果矩阵
CMatrix result(*this) ; // 拷贝构造
// 矩阵加法
for (int i = 0 ; i < m_nNumRows ; ++i)
{
for (int j = 0 ; j < m_nNumColumns; ++j)
result.SetElement(i, j, result.GetElement(i, j) + other.GetElement(i, j)) ;
}
return result ;
}
// 重载运算符-,实现矩阵的减法
// 参数:
// 1. const CMatrix& other - 与指定矩阵相减的矩阵
// 返回值:CMatrix型,指定矩阵与other相减之差
CMatrix CMatrix::operator-(const CMatrix& other) const
{
// 首先检查行列数是否相等
ASSERT (m_nNumColumns == other.GetNumColumns() && m_nNumRows == other.GetNumRows());
// 构造目标矩阵
CMatrix result(*this) ; // copy ourselves
// 进行减法操作
for (int i = 0 ; i < m_nNumRows ; ++i)
{
for (int j = 0 ; j < m_nNumColumns; ++j)
result.SetElement(i, j, result.GetElement(i, j) - other.GetElement(i, j)) ;
}
return result ;
}
// 重载运算符*,实现矩阵的数乘
// 参数:
// 1. double value - 与指定矩阵相乘的实数
// 返回值:CMatrix型,指定矩阵与value相乘之积
CMatrix CMatrix::operator*(double value) const
{
// 构造目标矩阵
CMatrix result(*this) ; // copy ourselves
// 进行数乘
for (int i = 0 ; i < m_nNumRows ; ++i)
{
for (int j = 0 ; j < m_nNumColumns; ++j)
result.SetElement(i, j, result.GetElement(i, j) * value) ;
}
return result ;
}
// 重载运算符*,实现矩阵的乘法
// 参数:
// 1. const CMatrix& other - 与指定矩阵相乘的矩阵
// 返回值:CMatrix型,指定矩阵与other相乘之积
CMatrix CMatrix::operator*(const CMatrix& other) const
{
// 首先检查行列数是否符合要求
ASSERT (m_nNumColumns == other.GetNumRows());
// construct the object we are going to return
CMatrix result(m_nNumRows, other.GetNumColumns()) ;
// 矩阵乘法,即
// [A][B][C] [G][H] [A*G + B*I + C*K][A*H + B*J + C*L]
// [D][E][F] * [I][J] = [D*G + E*I + F*K][D*H + E*J + F*L]
// [K][L]
double value ;
for (int i = 0 ; i < result.GetNumRows() ; ++i)
{
for (int j = 0 ; j < other.GetNumColumns() ; ++j)
{
value = 0.0 ;
for (int k = 0 ; k < m_nNumColumns ; ++k)
{
value += GetElement(i, k) * other.GetElement(k, j) ;
}
result.SetElement(i, j, value) ;
}
}
return result ;
}
// 矩阵的转置
// 参数:无
// 返回值:CMatrix型,指定矩阵转置矩阵
CMatrix CMatrix::Transpose() const
{
// 构造目标矩阵
CMatrix Trans(m_nNumColumns, m_nNumRows);
// 转置各元素
for (int i = 0 ; i < m_nNumRows ; ++i)
{
for (int j = 0 ; j < m_nNumColumns ; ++j)
Trans.SetElement(j, i, GetElement(i, j)) ;
}
return Trans;
}
// 实矩阵求逆的全选主元高斯-约当法
// 参数:无
// 返回值:BOOL型,求逆是否成功
BOOL CMatrix::InvertGaussJordan()
{
int *pnRow, *pnCol,i,j,k,l,u,v;
double d = 0, p = 0;
// 分配内存
pnRow = new int[m_nNumColumns];
pnCol = new int[m_nNumColumns];
if (pnRow == NULL || pnCol == NULL)
return FALSE;
// 消元
for (k=0; k<=m_nNumColumns-1; k++)
{
d=0.0;
for (i=k; i<=m_nNumColumns-1; i++)
{
for (j=k; j<=m_nNumColumns-1; j++)
{
l=i*m_nNumColumns+j; p=fabs(m_pData[l]);
if (p>d)
{
d=p;
pnRow[k]=i;
pnCol[k]=j;
}
}
}
// 失败
if (d == 0.0)
{
delete[] pnRow;
delete[] pnCol;
return FALSE;
}
if (pnRow[k] != k)
{
for (j=0; j<=m_nNumColumns-1; j++)
{
u=k*m_nNumColumns+j;
v=pnRow[k]*m_nNumColumns+j;
p=m_pData[u];
m_pData[u]=m_pData[v];
m_pData[v]=p;
}
}
if (pnCol[k] != k)
{
for (i=0; i<=m_nNumColumns-1; i++)
{
u=i*m_nNumColumns+k;
v=i*m_nNumColumns+pnCol[k];
p=m_pData[u];
m_pData[u]=m_pData[v];
m_pData[v]=p;
}
}
l=k*m_nNumColumns+k;
m_pData[l]=1.0/m_pData[l];
for (j=0; j<=m_nNumColumns-1; j++)
{
if (j != k)
{
u=k*m_nNumColumns+j;
m_pData[u]=m_pData[u]*m_pData[l];
}
}
for (i=0; i<=m_nNumColumns-1; i++)
{
if (i!=k)
{
for (j=0; j<=m_nNumColumns-1; j++)
{
if (j!=k)
{
u=i*m_nNumColumns+j;
m_pData[u]=m_pData[u]-m_pData[i*m_nNumColumns+k]*m_pData[k*m_nNumColumns+j];
}
}
}
}
for (i=0; i<=m_nNumColumns-1; i++)
{
if (i!=k)
{
u=i*m_nNumColumns+k;
m_pData[u]=-m_pData[u]*m_pData[l];
}
}
}
// 调整恢复行列次序
for (k=m_nNumColumns-1; k>=0; k--)
{
if (pnCol[k]!=k)
{
for (j=0; j<=m_nNumColumns-1; j++)
{
u=k*m_nNumColumns+j;
v=pnCol[k]*m_nNumColumns+j;
p=m_pData[u];
m_pData[u]=m_pData[v];
m_pData[v]=p;
}
}
if (pnRow[k]!=k)
{
for (i=0; i<=m_nNumColumns-1; i++)
{
u=i*m_nNumColumns+k;
v=i*m_nNumColumns+pnRow[k];
p=m_pData[u];
m_pData[u]=m_pData[v];
m_pData[v]=p;
}
}
}
// 清理内存
delete[] pnRow;
delete[] pnCol;
// 成功返回
return TRUE;
}
// 对称正定矩阵的求逆
//
// 参数:无
//
// 返回值:BOOL型,求逆是否成功
BOOL CMatrix::InvertSsgj()
{
int i, j ,k, m;
double w, g, *pTmp;
// 临时内存
pTmp = new double[m_nNumColumns];
// 逐列处理
for (k=0; k<=m_nNumColumns-1; k++)
{
w=m_pData[0];
if (w == 0.0)
{
delete[] pTmp;
return FALSE;
}
m=m_nNumColumns-k-1;
for (i=1; i<=m_nNumColumns-1; i++)
{
g=m_pData[i*m_nNumColumns];
pTmp[i]=g/w;
if (i<=m)
pTmp[i]=-pTmp[i];
for (j=1; j<=i; j++)
m_pData[(i-1)*m_nNumColumns+j-1]=m_pData[i*m_nNumColumns+j]+g*pTmp[j];
}
m_pData[m_nNumColumns*m_nNumColumns-1]=1.0/w;
for (i=1; i<=m_nNumColumns-1; i++)
m_pData[(m_nNumColumns-1)*m_nNumColumns+i-1]=pTmp[i];
}
// 行列调整
for (i=0; i<=m_nNumColumns-2; i++)
for (j=i+1; j<=m_nNumColumns-1; j++)
m_pData[i*m_nNumColumns+j]=m_pData[j*m_nNumColumns+i];
// 临时内存清理
delete[] pTmp;
return TRUE;
}
2. 创建五个新的对话框。
创建对话框相对来说比较简单,只需在菜单栏中点击New Dialog就可以创建,每个对话框都有自己的ID号。笔者课程设计中共创建了五个对话框,每个对话框都创建了一个类相对应。如图给出条件平差和历史记录的对话框的截图:
3. 在每个对话框里面添加需要的控件。
在每个不同平差类型的对话框中添加能够实现不同功能的函数,响应函数的不同决定了不同的执行结果。
4. 给每个需要实现不同功能的函数添加消息响应函数。
条件平差的计算和保存响应函数:
void CTjpc1::OnButton1()
{
// TODO: Add your control notification handler code here
UpdateData();
// 在这里义了这几个矩阵
CMatrix jza,jza1,jzw,jzq,jzv,jzv1,jzn,jzk,jza0;
double a0,r;
// 将输入的已知矩阵各元素由字符转化为数值
jza.FromString(m_1edit1);
jzw.FromString(m_1edit2);
jzq.FromString(m_1edit3);
r=1.0/(jza.GetNumRows());
jza1=jza.Transpose();
jzn=jza*jzq*jza1;
// 求jzn的逆矩阵
if(jzn.InvertGaussJordan())
m_1edit4=jzn.ToString(" ");
else
m_1edit4="失败";
jzn.FromString(m_1edit4);
jzk=jzn*jzw*(-1);
// 求出由各个数值的改正数组成的jzv
jzv=jzq*jza1*jzk;
m_1edit4=jzv.ToString(" ");
jzv1=jzv.Transpose();
// 求协因数阵的逆矩阵权阵,此处用jzq代替一下
if(jzq.InvertGaussJordan())
m_1edit5=jzq.ToString(" ");
else
m_1edit5="失败";
jzq.FromString(m_1edit5);
jza0=jzv1*jzq*jzv;
jza0=jza0*r;
m_1edit5=jza0.ToString(" ");
a0=atof(m_1edit5);
a0=sqrt(a0);
m_1edit5.Format("%f",a0);
// 将所求得的输入到第四个框和第五个框里
GetDlgItem(IDC_EDIT4)->SetWindowText(m_1edit4);
GetDlgItem(IDC_EDIT5)->SetWindowText(m_1edit5);
CFile file;
file.Open("1.txt", CFile::modeCreate | CFile::modeNoTruncate |CFile::modeWrite);
file.SeekToEnd();
CString a="\r\n";
file.Write(a,strlen(a));
file.Write("条件平差的记录数据:", strlen("条件平差的记录数据:"));
file.Write(a,strlen(a));
file.Write("A矩阵为:", strlen("A矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_1edit1, strlen(m_1edit1));
file.Write(a,strlen(a));
file.Write("W矩阵为:", strlen("A矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_1edit2, strlen(m_1edit2));
file.Write(a,strlen(a));
file.Write("Q矩阵为:", strlen("Q矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_1edit3, strlen(m_1edit3));
file.Write(a,strlen(a));
file.Write("V矩阵为:", strlen("V矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_1edit4, strlen(m_1edit4));
file.Write(a,strlen(a));
file.Write("单位中误差为:", strlen("单位中误差为:"));
file.Write(a,strlen(a));
file.Write(m_1edit5, strlen(m_1edit5));
file.Write(a,strlen(a));
file.Close();
UpdateData(FALSE);
}
清零的函数:
void CTjpc1::OnButton2()
{
// TODO: Add your control notification handler code here
GetDlgItem(IDC_EDIT1)->SetWindowText(NULL);
GetDlgItem(IDC_EDIT2)->SetWindowText(NULL);
GetDlgItem(IDC_EDIT3)->SetWindowText(NULL);
GetDlgItem(IDC_EDIT4)->SetWindowText(NULL);
GetDlgItem(IDC_EDIT5)->SetWindowText(NULL);
}
间接平差的计算和保存响应函数:
void CJjpc2::OnButton3()
{
// TODO: Add your control notification handler code here
UpdateData();
CMatrix jzb,jzb1,jzp,jzw,jzl,jzv,jzv1,jzx,jzn,jza0;
double a0,r;int i;
jzb.FromString(m_2edit1);
jzp.FromString(m_2edit2);
jzl.FromString(m_2edit3);
if((jzb.GetNumRows==jzp.GetNumRows)&(jzp.GetNumRows==jzl.GetNumRows))
{
i=(jzb.GetNumRows()-jzb.GetNumColumns());
r=1.0/i;
jzb1=jzb.Transpose();
jzn=jzb1*jzp*jzb;//m_2edit4=jzn.ToString(" ");
jzw=jzb1*jzp*jzl;
if(jzn.InvertGaussJordan())
m_2edit4=jzn.ToString(" ");
else
MessageBox("数据输入有错,请仔细查出错误,并重新输入。");
jzn.FromString(m_2edit4);
jzx=jzn*jzw;
jzv=(jzb*jzx-jzl);
jzv1=jzv.Transpose();
jza0=jzv1*jzp*jzv*r;
m_2edit5=jza0.ToString(" ");
a0=atof(m_2edit5);
a0=sqrt(a0);
m_2edit5.Format("%f",a0);
m_2edit4=jzv.ToString(" ");
GetDlgItem(IDC_EDIT4)->SetWindowText(m_2edit4);
GetDlgItem(IDC_EDIT5)->SetWindowText(m_2edit5);
}
else
{
MessageBox("矩阵输入的有错误!请重新输入!");
}
CFile file;
file.Open("2.txt", CFile::modeCreate | CFile::modeNoTruncate |CFile::modeWrite);
file.SeekToEnd();
CString a="\r\n";
file.Write(a,strlen(a));
file.Write("间接平差的记录数据:", strlen("间接平差的记录数据:"));
file.Write(a,strlen(a));
file.Write("B矩阵为:", strlen("B矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_2edit1, strlen(m_2edit1));
file.Write(a,strlen(a));
file.Write("P矩阵为:", strlen("P矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_2edit2, strlen(m_2edit2));
file.Write(a,strlen(a));
file.Write("L矩阵为:", strlen("L矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_2edit3, strlen(m_2edit3));
file.Write(a,strlen(a));
file.Write("V矩阵为:", strlen("V矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_2edit4, strlen(m_2edit4));
file.Write(a,strlen(a));
file.Write("单位中误差为:", strlen("单位中误差为:"));
file.Write(a,strlen(a));
file.Write(m_2edit5, strlen(m_2edit5));
file.Write(a,strlen(a));
file.Close();
UpdateData(FALSE);
}
附有参数条件平差的计算和保存响应函数:
void CFctjpc3::OnButton5()
{
// TODO: Add your control notification handler code here
UpdateData();
// 在这里义了这几个矩阵
CMatrix jza,jza1,jzb,jzb1,jzw,jzq,jzv,jzv1,jzn1,jzn2,jzx,jzk,jza0;
double a0,r;
// 将输入的已知矩阵各元素由字符转化为数值
jza.FromString(m_3edit1);
jzb.FromString(m_3edit2);
jzw.FromString(m_3edit3);
jzq.FromString(m_3edit4);
r=1.0/(jzb.GetNumRows()-jzb.GetNumColumns());
jza1=jza.Transpose();
jzb1=jzb.Transpose();
jzn1=jza*jzq*jza1;
// 求jzn的逆矩阵
if(jzn1.InvertGaussJordan())
m_3edit5=jzn1.ToString(" ");
else
MessageBox("数据输入有错,请仔细查出错误,并重新输入。");
jzn1.FromString(m_3edit5);
jzn2=jzb1*jzn1*jzb;
{
if(jzn2.InvertGaussJordan())
m_3edit6=jzn2.ToString(" ");
else
MessageBox("数据输入有错,请仔细查出错误,并重新输入。");
}
jzn2.FromString(m_3edit6);
jzx=jzn2*jzb1*jzn1*jzw*(-1);
jzk=jzn1*(jzb*jzx+jzw)*(-1);
// 求出由各个数值的改正数组成的jzv
jzv=jzq*jza1*jzk;
m_3edit5=jzv.ToString(" ");
jzv1=jzv.Transpose();
// 求协因数阵的逆矩阵权阵,此处用jzq代替一下
{
if(jzq.InvertGaussJordan())
m_3edit6=jzq.ToString(" ");
else
m_3edit6="失败";
}
jzq.FromString(m_3edit6);
jza0=jzv1*jzq*jzv;
jza0=jza0*r;
m_3edit6=jza0.ToString(" ");
a0=atof(m_3edit6);
a0=sqrt(a0);
m_3edit6.Format("%f",a0);
// 将所求得的输入到第四个框和第五个框里
GetDlgItem(IDC_EDIT5)->SetWindowText(m_3edit5);
GetDlgItem(IDC_EDIT6)->SetWindowText(m_3edit6);
CFile file;
file.Open("3.txt", CFile::modeCreate | CFile::modeNoTruncate |CFile::modeWrite);
file.SeekToEnd();
CString a="\r\n";
file.Write(a,strlen(a));
file.Write("附有参数的条件平差的记录数据:", strlen("附有参数的条件平差的记录数据:"));
file.Write(a,strlen(a));
file.Write("B矩阵为:", strlen("B矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_3edit1, strlen(m_3edit1));
file.Write(a,strlen(a));
file.Write("P矩阵为:", strlen("P矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_3edit2, strlen(m_3edit2));
file.Write(a,strlen(a));
file.Write("W矩阵为:", strlen("W矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_3edit3, strlen(m_3edit3));
file.Write(a,strlen(a));
file.Write("Q矩阵为:", strlen("Q矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_3edit4, strlen(m_3edit4));
file.Write(a,strlen(a));
file.Write("V矩阵为:", strlen("V矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_3edit5, strlen(m_3edit5));
file.Write(a,strlen(a));
file.Write("单位中误差为:", strlen("单位中误差为:"));
file.Write(a,strlen(a));
file.Write(m_3edit6, strlen(m_3edit6));
file.Write(a,strlen(a));
file.Close();
UpdateData(FALSE);
}
附有限制性条件间接平差的计算和保存响应函数:
void CFxjjpc::OnButton7()
{
// TODO: Add your control notification handler code here
UpdateData();
CMatrix jzb,jzb1,jzc,jzc1,jzp,jzw,jzwx,jzl,jzv,jzv1,jzx,jzn1,jzn2,jzks,jza0;
double a0,r;
jzb.FromString(m_4edit1);
jzc.FromString(m_4edit2);
jzp.FromString(m_4edit3);
jzl.FromString(m_4edit4);
jzwx.FromString(m_4edit5);
r=1.0/(jzb.GetNumRows()-jzb.GetNumColumns()+jzc.GetNumRows());
jzb1=jzb.Transpose();
jzn1=jzb1*jzp*jzb;
jzw=jzb1*jzp*jzl;
jzc1=jzc.Transpose();
if(jzn1.InvertGaussJordan())
m_4edit6=jzn1.ToString(" ");
else
MessageBox("数据输入有错,请仔细查出错误,并重新输入。");
jzn1.FromString(m_4edit6);
jzn2=jzc*jzn1*jzc1;
if(jzn2.InvertGaussJordan())
m_4edit7=jzn2.ToString(" ");
else
MessageBox("数据输入有错,请仔细查出错误,并重新输入。");
jzn2.FromString(m_4edit7);
//jzks=jzn2*(jzc*jzn1*jzw+jzwx);
jzx=(jzn1-jzn1*jzc1*jzn2*jzc*jzn1)*jzw-jzn1*jzc1*jzn2*jzwx;
jzv=jzb*jzx-jzl;
jzv1=jzv.Transpose();
jza0=jzv1*jzp*jzv*r;
m_4edit7=jza0.ToString(" ");
a0=atof(m_4edit7);
a0=sqrt(a0);
m_4edit7.Format("%f",a0);
m_4edit6=jzv.ToString(" ");
GetDlgItem(IDC_EDIT6)->SetWindowText(m_4edit6);
GetDlgItem(IDC_EDIT7)->SetWindowText(m_4edit7);
CFile file;
file.Open("4.txt", CFile::modeCreate | CFile::modeNoTruncate |CFile::modeWrite);
file.SeekToEnd();
CString a="\r\n";
file.Write(a,strlen(a));
file.Write("附有限制条件的间接平差的记录数据:", strlen("附有限制条件的间接平差的记录数据:"));
file.Write(a,strlen(a));
file.Write("B矩阵为:", strlen("B矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_4edit1, strlen(m_4edit1));
file.Write(a,strlen(a));
file.Write("C矩阵为:", strlen("C矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_4edit2, strlen(m_4edit2));
file.Write(a,strlen(a));
file.Write("P矩阵为:", strlen("P矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_4edit3, strlen(m_4edit3));
file.Write(a,strlen(a));
file.Write("L矩阵为:", strlen("L矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_4edit4, strlen(m_4edit4));
file.Write(a,strlen(a));
file.Write("Wx矩阵为:", strlen("Wx矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_4edit5, strlen(m_4edit5));
file.Write(a,strlen(a));
file.Write("V矩阵为:", strlen("V矩阵为:"));
file.Write(a,strlen(a));
file.Write(m_4edit6, strlen(m_4edit6));
file.Write(a,strlen(a));
file.Write("单位中误差为:", strlen("单位中误差为:"));
file.Write(a,strlen(a));
file.Write(m_4edit7, strlen(m_4edit7));
file.Write(a,strlen(a));
file.Close();
UpdateData(FALSE);
}
在读取历史记录的对话框中,消息响应函数是:
先看看查看历史记录对话框的分布(如下图)
各个控件的消息响应函数大同小异
void CLsjl::OnButton1()
{
// TODO: Add your control notification handler code here
CString str;
CFile f;
f.Open("1.txt",CFile::modeReadWrite);
f.Read(str.GetBuffer(f.GetLength()),f.GetLength());
f.Close();
GetDlgItem( IDC_EDIT1 )->SetWindowText(str);
}
查看不同平差类型计算历史记录控件的响应函数中的代码只是f.Open("文件名",CFile::modeReadWrite);的文件名不同而已。
5. 给主界面和其它的对话框添加图片等美化工作。
未进行处理的界面是灰色的,单调乏味,需要添加图片等进行美化。但是由于时间较短,做的不是太好。
6. 输入书本例子中的已知值,得出运算结果。比对正确的结果,查出并改正程序中的错误。
程序编完后,笔者进行了详细的验算,程序中已经保留了验证的数据和结果。
三、 实验感想
误差理论与测量平差的课程设计这件事,老师很早就和我们说了。是为了给我们充足的时间准备,然后做到最好。我们牢固掌握测量数据处理的基本原理和公式,熟练掌握测量数据处理的基本技能和计算方法。
在将近一个月的时间里,通过自己的学习,从无到有。简单的学习了C++的编程知识,主要是运用MFC,基本上实现了四种平差模型的计算。其中也遇到了很多的问题,开始最棘手的问题是如何读取对话框中编辑框中的矩阵并进行相关的计算。在这个问题上耽搁了几天。后来经过上网搜索,知道可以用一个类,在网上下了并且添加到工程。通过运算符的重载,计算上变的很简单。
后来遇到的一个问题就是在保存计算数据的时候,输入到文本中时,如何进行换行?这个在CSDN论坛上有类似的帖子,看过后如醍醐灌顶,就是定义一个字符“\r\n”,通过输入这个字符,可以实现换行。
虽然大家都说C++难,但是一个一个问题的去解决,问题都会迎刃而解。
通过这个课程设计,自己简单地掌握了C++,以后自己会更加深入地去学习,力求做到更好。
四、 参考文献
孙鑫视频[孙鑫]
《面向对象程序设计与VC程序设计入门》[主编余祖龙, 孙开琼]