测绘程序设计基础 实验7 CSU
实验7 常用测量程序设计
(工具:VS2010)
一、 实验目的
• 巩固类的创建与使用
• 掌握数组参数的传递
• 掌握常用测绘程序设计的被巧
二、实验内容与要求
设计一个无定向导线简易计算的程序,
要求自己定义文件格式,把下图中数据编写至文件中,然后通过读取文件
的形式获取所有数据,计算结果也写入结果文件中
无定向导线基本步骤:
三、设计与实现:
3.1 设计思路:
3.2 界面设计及属性:
3.3主要代码:
3.3.1文件:<Angle.h>
#pragma once
enum AngleStyle
{
DEG,
DMS,
RAD
};
class Angle
{
public:
Angle(double value=0,AngleStyle style=DMS);
~Angle(void);
private:
double dValue;//角度值
AngleStyle nCurStyle;//当前角度值类型
private:
//设置常成员函数的作用:1.类成员不会被改变
//2.可以被常类变量调用
double Deg(double dDms) const;
double Dms(double dDeg) const;
public:
//获取指定的类型获取角度值,
//由于返回的是dValue的引用,所以该值大小可以改变,即可以进行赋值
double& operator() (AngleStyle style);
//重载,获取指定的类型获取角度值,该值不可改变,const CAngle类型变量调用
double operator() (AngleStyle style) const;
//重载运算符+/-
friend Angle operator + (const Angle& m1,const Angle& m2);
friend Angle operator - (const Angle& m1,const Angle& m2);
};
3.3.2文件:< Angle.cpp>
#include "StdAfx.h"
#include "Angle.h"
#include "math.h"
const double EPSILON=1.0E-12;
const double PI=4.0*atan(1.0);
//重载构造函数,有缺省值
Angle::Angle(double value,AngleStyle style)
{
dValue=value;
nCurStyle=style;
}
Angle::~Angle(void)
{
}
//重载()函数
double& Angle::operator() (AngleStyle style) //指定的类型获取角度值
{
//double dAngleValue;
if(style==DMS)
{
if(nCurStyle==DEG)
{
dValue=Dms(dValue);
}
else if(nCurStyle==RAD)
{
dValue=Dms(dValue*180.0/PI);
}
nCurStyle=DMS;
}
else if(style==DEG)
{
if(nCurStyle==DMS)
{
dValue=Deg(dValue);
}
else if(nCurStyle==RAD)
{
dValue=dValue*180.0/PI;
}
nCurStyle=DEG;
}
else
{
if(nCurStyle==DMS)
{
dValue=Deg(dValue)*PI/180;
}
else if(nCurStyle==DEG)
{
dValue=dValue*PI/180;
}
nCurStyle=RAD;
}
return dValue;
}
//重载()函数,该函数是常函数,只能被常CAngle对象使用
double Angle::operator() (AngleStyle style) const //指定的类型获取角度值
{
double dAngleValue;
if(style==DMS)
{
if(nCurStyle==DEG)
{
dAngleValue=Dms(dValue);
}
else if(nCurStyle==RAD)
{
dAngleValue=Dms(dValue*180.0/PI);
}
else
{
dAngleValue=dValue;
}
}
else if(style==DEG)
{
if(nCurStyle==DMS)
{
dAngleValue=Deg(dValue);
}
else if(nCurStyle==RAD)
{
dAngleValue=dValue*180.0/PI;
}
else
{
dAngleValue=dValue;
}
}
else
{
if(nCurStyle==DMS)
{
dAngleValue=Deg(dValue)*PI/180;
}
else if(nCurStyle==DEG)
{
dAngleValue=dValue*PI/180;
}
else
{
dAngleValue=dValue;
}
}
return dAngleValue;
}
//私有成员,度分秒向十进制度转换
double Angle::Deg(double dDms) const
{
int iDeg,iMin;
double dSec;
iDeg = int(dDms + EPSILON);//度//加一个很小的数,以防止取整时的出错
iMin = int((dDms - iDeg) * 100+ EPSILON);//分
dSec = ((dDms - iDeg) * 100 - iMin) * 100 ;//秒
return iDeg + (double)iMin / 60 + dSec / 3600;
}
//私有成员,十进制度向度分秒转换
double Angle::Dms(double dDeg) const
{
int iDeg,iMin;
double dSec;
double dTmp;
iDeg = int(dDeg + EPSILON);//整数部分度
dTmp = (dDeg - iDeg) * 60;//小数部分转换成分
iMin = int(dTmp+ EPSILON);//取分的整数部分
dSec = (dTmp - iMin) * 60;//截取秒
return iDeg + (double)iMin / 100 + dSec / 10000;
}
//友元重载+函数
Angle operator + (const Angle& m1,const Angle& m2)
{
Angle addAngle(0,RAD);
addAngle(RAD)=m1(RAD)+m2(RAD);
return addAngle;
}
//友元重载-函数
Angle operator - (const Angle& m1,const Angle& m2)
{
Angle subAngle(0,RAD);
subAngle(RAD)=m1(RAD)-m2(RAD);
return subAngle;
}
3.3.3文件:<CData.h>
/***************************************************************************
* 文件名:<Data.h> *
* *
* 描述:用来储存数据 使用了角度辅助类:Angle *
* *
* 历史:**日期** **理由** **签名** *
* 2019年5月5日 创建 *** *
* *
* 外部过程: *
* *
/**************************************************************************/
#pragma once
#include"Angle.h"
class CData
{
public:
CData(void);
~CData(void);
//未修正------------------------------------------未修正
Angle p;//储存角度
double s;//边长
Angle _a;//储存方位角
double _dx;//储存坐标X增量
double _dy;//储存坐标Y增量
double _X;//储存未修正原始X
double _Y;//储存未修正原始Y
//修正------------------------------------------修正
Angle a;//储存改正后方位角
double X;//储存修正后X
double Y;//储存修正后Y
//------------------------------------------数据仅仅储存至开头元素 即P[0]中
Angle Sum_a;//总方位角
Angle _Sum_a;//假定总方位角
Angle alfa;// 总方位角-假定总方位角
double S;//总长度
double _S;//观测值总长度
double k;// 总长度/观测值总长度
int iSum;
};
3.3.4文件:<CData.cpp>
#include "StdAfx.h"
#include "Data.h"
CData::CData(void)
{
}
CData::~CData(void)
{
}
3.3.5文件:<CSupport.h>
/***************************************************************************
* 文件名:<CSupport.h> *
* *
* 描述:操纵主要函数 使用了类CData *
* *
* 历史:**日期** **理由** **签名** *
* 2019年5月5日 创建 *** *
* *
* 外部过程: *
* *
/**************************************************************************/
#pragma once
#include"Data.h"
#include <locale.h>
#include"math.h"
class CSupport
{
public:
CSupport(void);
~CSupport(void);
void main();//主要函数
CString * SplitString(CString str, char split, int& iSubStrs);//字符串分割函数
private:
double Process_Rad(double dx1,double dy1,double dx2,double dy2);//角度转换
double length(double x1,double y1,double x2,double y2);//求距离
void read();//读取函数
void Pocess();//过程函数
void Out();//输出函数
private:
CData *P;
};
3.3.6文件:<CSupport.cpp>
#include "StdAfx.h"
#include "Support.h"
#define PI 4.0*atan(1.0)
CSupport::CSupport(void)
{
}
CSupport::~CSupport(void)
{
delete [] P;
}
/***************************************************************************
* 名字:CString * CSupport::SplitString(CString str, char split, int& iSubStrs)*
* *
* 描述:字符串分割函数2 *
* *
* 历史:**日期** **理由** **签名** *
* 2019年5月5日 引用该函数 *** *
* 参数: 1.CString str *
* 2.char split *
* 3.int& iSubStrs *
* 返回值:返回指针 指针带有动态数组的内容 *
* *
* 注: *
/**************************************************************************/
CString * CSupport::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;
}
/***************************************************************************
* 名字:double Process_Rad(double dx1,double dy1,double dx2,double dy2) *
* *
* 描述:4个坐标值--》弧度式方位角 *
* *
* 历史:**日期** **理由** **签名** *
* 2019年3月8日 创建该函数 *** *
* 2019年5月5日 引用该函数 *** *
* *
* 参数: 1.double dx1 *
* 2.double dy1 *
* 3.double dx2 *
* 4.double dy2 *
* *
* 返回值:double类型数据 转换后的rad型方位角 *
* *
* 注:该函数在输入两坐标值相同时,会有一对话框弹出,且此时返回值为0 *
/**************************************************************************/
double CSupport::Process_Rad(double dx1,double dy1,double dx2,double dy2)
{
double dx=dx2-dx1;
double dy=dy2-dy1;
double dRad;
if(dy>0){
if(dx<0){
dRad=atan(dy/dx)+PI;//第二象限
}
else if(dx>0){
dRad=atan(dy/dx);//第一象限
}
else{
dRad=PI/2;//位于Y轴正方向
}
}
else if(dy<0){
if(dx<0){
dRad=atan(dy/dx)+PI;//第三象限
}
else if(dx>0){
dRad=atan(dy/dx)+2*PI;//第四象限
}
else{
dRad=PI*3/2;//位于Y轴负方向
}
}
else{
if(dx>0){
dRad=0;//位于X正半轴
}
else if(dx<0){
dRad=PI;//位于X负半轴
}
else{
AfxMessageBox(_T("您不能输入相同的坐标。"));//(x1,y1)==(x2,y2)的情况
return 0;
}
}
return dRad;
}
/***************************************************************************
* 名字:double length(double x1,double y1,double x2,double y2) *
* *
* 描述:由(x1,y1)和(x2,y2)计算两点之间距离 长度 *
* *
* 历史:**日期** **理由** **签名** *
* 2019年3月20日 创建该函数 *** *
* 2019年5月5日 引用该函数 *** *
* 参数: 1.double x1 *
* 2.double y1 *
* 3.double x2 *
* 4.double y2 *
* 返回值:double类型数据 返回距离 *
* *
* 注: *
/**************************************************************************/
double CSupport::length(double x1,double y1,double x2,double y2)
{
double tmp=((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
return sqrt(tmp);
}
/***************************************************************************
* 名字:void CSupport::read() *
* *
* 描述:读取函数 调用函数SplitString 开辟动态数组P *
* *
* 历史:**日期** **理由** **签名** *
* 2019年5月5日 创建该函数 *** *
* 参数: 1. *
* 返回值:无 *
* *
* 注: *
/**************************************************************************/
void CSupport::read()
{
CFileDialog dlgFile(TRUE,_T("txt"),NULL,
OFN_ALLOWMULTISELECT|OFN_EXPLORER,
//_T("(文本文件)|*.txt"));
_T(""));
if(dlgFile.DoModal()==IDCANCEL) return ;
CString strName=dlgFile.GetPathName();//获取打开文件文件名(路径)
setlocale(LC_ALL,"");
CStdioFile sf;
if(! sf.Open(strName,CFile::modeRead)) return ;
CString strLine;
CString strContent;//接受内容字符串
strContent.Empty();
BOOL bEOF =sf.ReadString (strLine);
bEOF =sf.ReadString (strLine);//运行两次
if(!bEOF)
{
AfxMessageBox(_T("数据有误,请检查数据文件!"));
return ;
}
int iPointCount;
iPointCount=_ttoi(strLine);//读取点数
P=new CData [iPointCount+1];//创建动态数组
P[0].iSum=iPointCount;
int i1=0;
int i2=0;
int i3=0;
int n=0;//为下文读取做铺垫
int counter=0;
while (counter<2*P[0].iSum+1)
{
bEOF=sf.ReadString(strLine);
CString *pstrData =SplitString(strLine,',',n);
//if(pstrData==NULL) continue;
if(counter<P[0].iSum)
{
P[i1].s = _tstof(pstrData[2]);
i1++;
}
else if(counter<(2*P[0].iSum-1))
{
P[i2].p=Angle(_tstof(strLine),DMS);
i2++;
}
else
{
if(i3==0)
{
P[0].X = _tstof(pstrData[0]);
P[0].Y = _tstof(pstrData[1]);
}
if(i3!=0)
{
i3=P[0].iSum;
P[i3].X = _tstof(pstrData[0]);
P[i3].Y = _tstof(pstrData[1]);
}
i3++;
}
counter++;
}
sf.Close();
//AfxMessageBox(_T("成功读取数据!"));
}
/***************************************************************************
* 名字:void CSupport::Pocess() *
* *
* 描述:过程函数 调用函数length()、Process_Rad()函数 加工数组P中元素 *
* *
* 历史:**日期** **理由** **签名** *
* 2019年5月5日 创建该函数 *** *
* 参数: *
* 返回值:无 *
* *
* 注: *
/**************************************************************************/
void CSupport::Pocess()
{
//----------------------------------------------------------------------未修正----------------------------------------------------------------------
//计算方位角
P[0]._a=Angle(87.0053,DMS);
for(int i=1;i<P[0].iSum;i++)
{
P[i]._a=Angle(P[i-1]._a(DEG)+P[i-1].p(DEG)-180,DEG);
}
//计算坐标增量
for(int i=0;i<P[0].iSum;i++)
{
P[i]._dx=P[i].s*cos(P[i]._a(RAD));
P[i]._dy=P[i].s*sin(P[i]._a(RAD));
}
//计算假定坐标
P[0]._X=0;
P[0]._Y=0;
for(int i=1;i<P[0].iSum+1;i++)
{
P[i]._X=P[i-1]._X+P[i-1]._dx;
P[i]._Y=P[i-1]._Y+P[i-1]._dy;
}
//---------------------------------------------------------------------修正过程----------------------------------------------------------------------
//计算角度偏移状况
P[0]._Sum_a=Angle(Process_Rad(P[0]._X,P[0]._Y,P[P[0].iSum]._X,P[P[0].iSum]._Y),RAD);
P[0].Sum_a=Angle(Process_Rad(P[0].X,P[0].Y,P[P[0].iSum].X,P[P[0].iSum].Y),RAD);
P[0].alfa=Angle(P[0].Sum_a(DEG)-P[0]._Sum_a(DEG),DEG);
//长度缩放状况
P[0]._S=length(P[0]._X,P[0]._Y,P[P[0].iSum]._X,P[P[0].iSum]._Y);
P[0].S=length(P[0].X,P[0].Y,P[P[0].iSum].X,P[P[0].iSum].Y);
P[0].k=P[0].S/P[0]._S;
for(int i=0;i<P[0].iSum;i++)
{
P[i].a=Angle(P[i]._a(DMS)+P[0].alfa(DMS),DMS);
}
for(int i=0;i<P[0].iSum+1;i++)
{
P[i].X=P[0].X+P[0].k*(P[i]._X*cos(P[0].alfa(RAD))-P[i]._Y*sin(P[0].alfa(RAD)));
P[i].Y=P[0].Y+P[0].k*(P[i]._X*sin(P[0].alfa(RAD))+P[i]._Y*cos(P[0].alfa(RAD)));
}
}
/***************************************************************************
* 名字:void CSupport::Out() *
* *
* 描述:输出函数 将P中元素输出 *
* *
* 历史:**日期** **理由** **签名** *
* 2019年5月5日 创建该函数 *** *
* 参数: *
* 返回值:无 *
* *
* 注: *
/**************************************************************************/
void CSupport::Out()
{
CStdioFile SF;
CString Result;
CString strOut;
setlocale(LC_ALL,"");
if(!SF.Open(_T("Result.txt"), CFile::modeCreate|CFile::modeWrite)) return;
Result.Format(_T("%s\r\n%s\r\n"),
_T("----------------------------原始数据----------------------------"),
_T("---------- 边长")
);
strOut+=Result;
for(int i=0;i<P[0].iSum;i++)
{
Result.Format(_T("%.4f\r\n"),
P[i].s
);
strOut+=Result;
}
Result.Format(_T("%s\r\n"),
_T("---------- 角度")
);
strOut+=Result;
for(int i=0;i<P[0].iSum-1;i++)
{
Result.Format(_T("%f\r\n"),
P[i].p(DMS)
);
strOut+=Result;
}
Result.Format(_T("%s\r\n"),
_T("---------- 假定方位角,坐标增量dx,dy")
);
strOut+=Result;
for(int i=0;i<P[0].iSum;i++)
{
Result.Format(_T("%f,%f,%f\r\n"),
P[i]._a(DMS),P[i]._dx,P[i]._dy
);
strOut+=Result;
}
Result.Format(_T("%s\r\n"),
_T("---------- 假定坐标")
);
strOut+=Result;
for(int i=0;i<P[0].iSum+1;i++)
{
Result.Format(_T("%f,%f\r\n"),
P[i]._X,P[i]._Y
);
strOut+=Result;
}
Result.Format(_T("%s\r\n%s%f\r\n%s%f\r\n%s%f\r\n"),
_T("----------------------------修正过程----------------------------"),
_T("---------- 导线总假设方位角 "),P[0]._Sum_a(DMS),
_T("---------- 导线总真方位角 "),P[0].Sum_a(DMS),
_T("---------- 角度闭合差 "),P[0].alfa(DMS)
);
strOut+=Result;
Result.Format(_T("%s%f\r\n%s%f\r\n%s%f\r\n"),
_T("---------- 导线总长"),P[0].S,
_T("---------- 观测值总长度"),P[0]._S,
_T("---------- 闭合边长度比:导线总长/观测值总长度 "),P[0].k
);
strOut+=Result;
Result.Format(_T("%s\r\n"),
_T("---------- 修正后方位角")
);
strOut+=Result;
for(int i=0;i<P[0].iSum;i++)
{
Result.Format(_T("%f\r\n"),
P[i].a
);
strOut+=Result;
}
Result.Format(_T("%s\r\n"),
_T("---------- 修正后坐标")
);
strOut+=Result;
for(int i=0;i<P[0].iSum+1;i++)
{
Result.Format(_T("%f,%f\r\n"),
P[i].X,P[i].Y
);
strOut+=Result;
}
SF.WriteString(strOut);
SF.Close();
AfxMessageBox(_T("成功!已输入至“Result.txt”中"));
}
/***************************************************************************
* 名字:void CSupport::main() *
* *
* 描述:main函数 调用函数read()、Pocess()、Out()函数 *
* *
* 历史:**日期** **理由** **签名** *
* 2019年5月5日 创建该函数 *** *
* 参数: *
* 返回值:无 *
* *
* 注: *
/**************************************************************************/
void CSupport::main()
{
CSupport temp;
temp.read();
temp.Pocess();
temp.Out();
}
3.3.7文件: < RS_110_zhangruixiang_SY7Dlg.cpp > (只摘取部分)
/***************************************************************************
* 文件名:<RS_110_zhangruixiang_SY7Dlg.cpp> *
* *
* 描述:对话框 *
* *
* 历史:**日期** **理由** **签名** *
* 2019年5月5日 创建 *** *
* *
* 外部过程: *
* *
/**************************************************************************/
void CRS_110_zhangruixiang_SY7Dlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
//CDialogEx::OnOK();
CSupport k;
k.main();
}
3.4运行结果
3.5设计技巧:
创建多个类,层次分明。
调用角度Angle类,省了较多力气
使用指针动态开辟数组,较为方便
使用文件操作输入与输出