測繪程序設計基礎 實驗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類,省了較多力氣
使用指針動態開闢數組,較爲方便
使用文件操作輸入與輸出