原始資料(格式)
界面設計
點選畫圖按鈕後彈出的對話框
類的設計
Data類:存放點号、坐标、未知點誤差橢圓元素
Gangle類:存儲起測站、照準點、角度觀測值
Length類:存儲起測站、照準點、邊長觀測值
support類:存放各種函數和矩陣
Eigen類:用于矩陣運算
源代碼
<Data.h>
#pragma once
#include <afxext.h>
#include <math.h>
#include <locale.h>
class Data
{
public:
Data();
~Data();
bool whether;//判斷點坐标是否已存在
CString dianhao;//點号
double X;
double Y;//坐标
//未知點的點位誤差和誤差橢圓元素
double mx;//x點位誤差
double my;//y點位誤差
double mk;//距離誤差
double E;//長半軸
double F;//短半軸
double Q;//長半徑方位角
};
<Data.cpp>
#include "pch.h"
#include "Data.h"
Data::Data()
{
}
Data::~Data()
{
}
<Gangle.h>
#pragma once
#include "Data.h"
class Gangle
{
public:
Gangle();
~Gangle();
Data* Qizhan;//起測站
Data* Zhaozhan;//照準點
double GCangle;//角度觀測值
};
<Gangle.cpp>
#include "pch.h"
#include "Gangle.h"
Gangle::Gangle()
{
}
Gangle::~Gangle()
{
}
<Length.h>
#pragma once
#include "Data.h"
class Length
{
public:
Length();
~Length();
Data* Qdian;//起點号
Data* Zdian;//終點号
double Glength;//邊長觀測值
};
<Length.cpp>
<Length.cpp>
#include "pch.h"
#include "Length.h"
Length::Length()
{
}
Length::~Length()
{
}
<support.h>
#pragma once
#include<iostream>
#include"Data.h"
#include"Length.h"
#include"Gangle.h"
#include<gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib,"gdiplus.lib")
#include <Eigen/Dense>//引用eigen類
using namespace Eigen; //引用eigen類 操作步驟:屬性 包含檔案的路徑
class support
{
private:
Data *KZD;//定義已知點指針
Data *WZD;//定義未知點指針
juli *GCB;//定義觀測邊指針
Gangle *GCJ;//定義觀測角
int KZDsums;//控制點個數
int unkownsunms;//未知點個數
int diansums;//總點數
int Glengthsums;//觀測邊數目
int Ganglesums;//觀測角度數目
int CZsums = 0;//測站數
public:
support();
~support();
bool panduan = 0;//判斷是否讀入資料
CString cunchu;//存儲資料
CString cunchu1;//存儲概算資料
CString cunchu2;//存儲平差資料
CString cunchu3;
double tak;//方向觀測值
double tab;//方向觀測值
double A_;//A'
double A;
double Tab;
double Tak;
double T_ak;//T_ak=Tab+a
//初始化矩陣
MatrixXd B;//系數陣
MatrixXd L;//常數陣
MatrixXd P;//權陣
MatrixXd Nbb;
MatrixXd fe;
MatrixXd XX;//坐标、角度改正數
MatrixXd V;//改正數
MatrixXd Qxx;//協因數陣
MatrixXd Min;
double m0;//機關權中誤差
double min;//最小二乘準則
double read();//讀入資料函數
double gaisuan();//概算函數
double pingcha();//平差函數CMatrix& B, CMatrix& L
void huitu(CDC * pDc, CRect rect, double karfa);//繪圖函數
double Maxmin1x(Data *KZD, int KZDsums, int tag);
double Maxmin1y(Data *KZD, int KZDsums, int tag);
double Maxmin2x(Data *WZD, int unkownsunms, int tag);//确定X、Y最值
double Maxmin2y(Data *WZD, int unkownsunms, int tag);
void huiKZD(CDC* pDC, double x, double y, double length, double a);//畫出控制點位置
double dms2rad(double dDms);
double rad2dms(double dDeg);
double fangweijiao(double x1, double y1, double x2, double y2);//求方位角
CString * SplitString(CString str, char split, int& iSubStrs);//字元串分割函數
Data* zhuanhuan(CString dianhao);//傳回點對應站儲存的位址,否則讀入資料時CString變量無法轉換為指針變量
};
<support.cpp>
#include "pch.h"
#include "support.h"
#include <Eigen/Dense>//引用eigen類
support::support()
{
}
support::~support()
{
}
const double pi = 4.0*atan(1.0);//定義pi
double p_ = 206265;//定義p''
//度分秒轉弧度函數
double hanshu::dms2rad(double dDms)
{
int iDegree, iMin;
double dSec;//存放度分秒
double dDeg;
iDegree = int(dDms);
iMin = int((dDms - iDegree) * 100);
dSec = ((dDms - iDegree) * 100 - iMin) * 100;
dDeg = iDegree + double(iMin) / 60 + dSec / 3600;
dDeg = dDeg / 180.0 * pi;
return dDeg;
}
double support::rad2dms(double dDeg)
{
int iDegree, iMin;
double dSec;//存放度分秒
double dDms;
dDeg = dDeg / pi * 180;
iDegree = int(dDeg);
iMin = int((dDeg - iDegree) * 60);
dSec = ((dDeg - iDegree) * 60 - iMin) * 60;
dDms = iDegree + double(iMin) / 100 + dSec / 10000;
return dDms;
}
//字元串分割函數
CString * support::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 support::fangweijiao(double x1, double y1, double x2, double y2)
{
double dTmp;//設定臨時變量用于傳回方位角弧度
double x0 = x2 - x1;
double y0 = y2 - y1;
if (x0 > 0)
{
if (y0 > 0)
{
dTmp = atan(y0 / x0);//第一象限
}
else if (y0 < 0)
{
dTmp = atan(y0 / x0) + 2 * pi;//第四象限
}
else
dTmp = 0;//在x軸正半軸上
}
else if (x0 < 0)
{
if (y0 > 0)
{
dTmp = atan(y0 / x0) + pi;//第二象限
}
else if (y0 < 0)
{
dTmp = atan(y0 / x0) + pi;//第三象限
}
else
dTmp = pi;//在x軸負半軸上
}
else
{
if (y0 > 0)
dTmp = pi / 2;//Y軸正半軸
else
dTmp = 3 * pi / 2;//Y軸負半軸
}
return dTmp;
}
//CString變量轉換為指針變量轉換函數(将起點、終點、測站、照準點綁定坐标和點号用)
Data* support::zhuanhuan(CString dianhao)
{
Data* Temp;//建立一個Data*指針型臨時變量
Temp = nullptr;//初始化指針
for (int i = 0; i < KZDsums; i++)
{
if (dianhao == KZD[i].dianhao)
{
Temp = &KZD[i];
}
else
{
for (int j = 0; j < unkownsunms; j++)
{
if (dianhao == WZD[j].dianhao)
{
Temp = &WZD[j];
}
}
}
}
return Temp;//傳回指針變量
}
//讀取資料并輸出函數
double support::read()
{
CFileDialog dlgFile(TRUE, _T("dat/txt"), NULL, OFN_EXPLORER, _T("(文本檔案)|*.dat|(文本檔案)|*.txt"));//打開檔案對話框
if (dlgFile.DoModal() == IDCANCEL) return 0;//如果選擇取消按鈕則退出
CString strFileName = dlgFile.GetPathName();//擷取選擇檔案的名稱
setlocale(LC_ALL, "");//對程式進行地域設定
CStdioFile sf;//建立檔案對象
if (!sf.Open(strFileName, CFile::modeRead)) return 0;//打開strName檔案路徑中的内容
CString strLine;
BOOL bEOF = sf.ReadString(strLine);//讀取第一行
cunchu += strLine;
cunchu += _T("\r\n");
if (!bEOF)//如果讀取失敗,則資料格式有問題,退出
{
AfxMessageBox(_T("資料有誤!"));
return 0;
}
//讀取控制點
KZDsums = _ttoi(strLine);
KZD = new Data[KZDsums];
int i = 0;
int n = 0;
while (i < KZDsums)
{
bEOF = sf.ReadString(strLine);
CString *dushu = SplitString(strLine, ',', n);
KZD[i].dianhao = dushu[0];
KZD[i].X = _tstof(dushu[1]);
KZD[i].Y = _tstof(dushu[2]);
KZD[i].whether = 1;//已知點坐标已知
cunchu += strLine;
cunchu += _T("\r\n");
i++;
}
bEOF = sf.ReadString(strLine);
cunchu += strLine;
cunchu += _T("\r\n");
if (!bEOF)//如果讀取失敗,則資料格式有問題,退出
{
AfxMessageBox(_T("資料有誤!"));
return 0;
}
//讀取未知點
unkownsunms = _ttoi(strLine);
WZD = new Data[unkownsunms];
bEOF = sf.ReadString(strLine);
cunchu += strLine;
cunchu += _T("\r\n");
i = 0;
while (i < unkownsunms)
{
CString *dianshu = SplitString(strLine, ',', n);
WZD[i].dianhao = dianshu[i];
WZD[i].whether = 0;//未知點坐标未知
i++;
}
//讀取觀測邊長
bEOF = sf.ReadString(strLine);
cunchu += strLine;
cunchu += _T("\r\n");
if (!bEOF)//如果讀取失敗,則資料格式有問題,退出
{
AfxMessageBox(_T("資料有誤!"));
return 0;
}
Glengthsums = _ttoi(strLine);
GCB = new juli[Glengthsums];
i = 0;
while (i < Glengthsums)
{
bEOF = sf.ReadString(strLine);
CString *bianshu = SplitString(strLine, ',', n);
GCB[i].Qdian = zhuanhuan(bianshu[0]);
GCB[i].Zdian = zhuanhuan(bianshu[1]);
GCB[i].Glength = _tstof(bianshu[2]);
cunchu += strLine;
cunchu += _T("\r\n");
i++;
}
//讀取角度
bEOF = sf.ReadString(strLine);
if (!bEOF)//如果讀取失敗,則資料格式有問題,退出
{
AfxMessageBox(_T("資料有誤!"));
return 0;
}
Ganglesums = _ttoi(strLine);
GCJ = new Gangle[Ganglesums];
cunchu += strLine;
cunchu += _T("\r\n");
i = 0;
while (i < Ganglesums)
{
bEOF = sf.ReadString(strLine);
CString *jiaoshu = SplitString(strLine, ',', n);
GCJ[i].Qizhan = zhuanhuan(jiaoshu[0]);
GCJ[i].Zhaozhan = zhuanhuan(jiaoshu[1]);
GCJ[i].GCangle = _tstof(jiaoshu[2]);
cunchu += strLine;
cunchu += _T("\r\n");
i++;
}
panduan = 1;//證明以讀入資料
diansums = KZDsums + unkownsunms;
CZsums = 0;//計算測站數
for (int i = 0; i < Ganglesums; i++)
{
if (GCJ[i].GCangle == 0)
{
CZsums++;
}
}
sf.Close();
return 0;
}
bool panduan1 = 0;//用于判定是否概算
//概算函數并輸出結果
double support::gaisuan()
{
if (panduan == 0)
{
AfxMessageBox(_T("請輸入資料"));
}
else
{
AfxMessageBox(_T("進行概算"));
/*********計算近似坐标********/
int yisuan = 0;//記錄已算點資料
while (yisuan < unkownsunms)//所有位置點坐标近似值算出後結束循環
{
for (int i = 0; i < Ganglesums; i++)
{
if (GCJ[i].Qizhan->whether == 1 && GCJ[i].Zhaozhan->whether == 1)//如果起測站和一個照準點已知
{
for (int j = 0; j < Ganglesums; j++)
{
if (GCJ[j].Qizhan == GCJ[i].Qizhan &&GCJ[j].Zhaozhan->whether == 0)//起測站和上面一樣,但照準點未知
{//此時可以算Tab、A_、A
A_ = dms2rad(GCJ[j].GCangle) - dms2rad(GCJ[i].GCangle);
if (A_ < 0)
{
A = A_ + 2 * pi;
}
else
{
A = A_;
}
Tab = fangweijiao(GCJ[i].Qizhan->X, GCJ[i].Qizhan->Y, GCJ[i].Zhaozhan->X, GCJ[i].Zhaozhan->Y);
T_ak = Tab + A;//計算T'ak
if (T_ak > 2 * pi)
{
Tak = T_ak - 2 * pi;
}
else
{
Tak = T_ak;
}
//下面找尋d
for (int k = 0; k < Glengthsums; k++)
{
if ((GCJ[j].Qizhan->dianhao == GCB[k].Qdian->dianhao && GCJ[j].Zhaozhan->dianhao == GCB[k].Zdian->dianhao)
|| (GCJ[j].Qizhan->dianhao == GCB[k].Zdian->dianhao && GCJ[j].Zhaozhan->dianhao == GCB[k].Qdian->dianhao))
//如果起測站和位置點在觀測邊長中有對應的邊長
{
double length = 0;
length = GCB[k].Glength;
GCJ[j].Zhaozhan->X = GCJ[j].Qizhan->X + length * cos(Tak);
GCJ[j].Zhaozhan->Y = GCJ[j].Qizhan->Y + length * sin(Tak);
GCJ[j].Zhaozhan->whether = 1;
yisuan = yisuan + 1;
}
}
}
}
}
}//對應while
//while循環結束後,此時所有點的近似坐标已知
//下面對近似坐标進行輸出
}
}//對應else
panduan1 = 1;
CString tem;//此部分用于輸出概算結果
cunchu1 += "已知點坐标:\r\n";
for (int i = 0; i < KZDsums; i++)
{
tem.Format(_T("%s\t%.4f\t%.4f\r\n"), KZD[i].dianhao, KZD[i].X, KZD[i].Y);
cunchu1 += tem;
}//輸出已知點
cunchu1 += "未知點概算後坐标:\r\n";
for (int i = 0; i < unkownsunms; i++)
{
tem.Format(_T("%s\t%.4f\t%.4f\r\n"), WZD[i].dianhao, WZD[i].X, WZD[i].Y);
cunchu1 += tem;
}//輸出未知點近似坐标
return 0;
}
bool panduan2 = 0;//用于判斷是否進行平差
double support::pingcha()
{
B.resize(Glengthsums + Ganglesums, 2 * unkownsunms + CZsums);//系數陣
L.resize(Glengthsums + Ganglesums, 1);//常數項
B.setZero();
double a1, b1, a2, b2;//改正系數
int DDsums = 0;//疊代次數
if (panduan == 0)
{
AfxMessageBox(_T("請輸入資料"));
}
else
{
if (panduan1 == 0)
{
AfxMessageBox(_T("請先進行概算"));
}
else//開始平差
{
//方向觀測誤差方程式
AfxMessageBox(_T("開始平差"));
double T0, Z0, L0, l1;
double dx, dy, ds;//方向坐标差
P.resize(Glengthsums + Ganglesums, Glengthsums + Ganglesums);//權矩陣
//求權矩陣
for (int i = 0; i < (Glengthsums + Ganglesums); i++)
{
for (int j = 0; j < (Glengthsums + Ganglesums); j++)
{
if (i != j)//将非對角部分轉為零
{
P(i, j) = 0;
}
else if (i < Ganglesums)//由于是等精度觀測,故将方向觀測值的權定為1
{
P(i, j) = 1;
}
else//下面為邊長觀測的權
{
P(i, j) = 100 / GCB[i - Ganglesums].Glength;
}
}
}
do {
int iStation = 1;//表示目前第幾個測站
int iLocation = 0;//表示前一測站所在位置
for (int i = 0; i < Ganglesums; i++)
{
if (GCJ[i].Qizhan->dianhao != GCJ[iLocation].Qizhan->dianhao)//如果換站
{
//右為角度坐标:GCJ[i].Qizhan、GCJ[i].Zhaozhan、GCJ[i].GCangle
//右為邊長坐标:GCB[i].Qdian、GCB[i].Zdian、GCB[i].Glength
iStation++; iLocation = i;
}
B(i, 2 * unkownsunms + iStation - 1) = -1;//方向改正數
//B矩陣方向指派
dx = GCJ[i].Zhaozhan->X - GCJ[i].Qizhan->X;
dy = GCJ[i].Zhaozhan->Y - GCJ[i].Qizhan->Y;
ds = sqrt(dx*dx + dy * dy);
a1 = p_ * dy / (ds*ds * 1000.0);//由于ds機關為毫米,故需乘以1000
b1 = -p_ * dx / (ds*ds * 1000.0);
for (int j = 0; j < unkownsunms; j++)
{
if (GCJ[i].Qizhan->dianhao == WZD[j].dianhao)//如果觀測值測站是第j個未知點
{
B(i, 2 * j) = a1; B(i, 2 * j + 1) = b1;
}
if (GCJ[i].Zhaozhan->dianhao == WZD[j].dianhao)//如果觀測值測站是第j個未知點
{
B(i, 2 * j) = -a1; B(i, 2 * j + 1) = -b1;
}
}
//L陣方向指派
T0 = fangweijiao(GCJ[i].Qizhan->X, GCJ[i].Qizhan->Y, GCJ[i].Zhaozhan->X, GCJ[i].Zhaozhan->Y);
Z0 = fangweijiao(GCJ[iLocation].Qizhan->X, GCJ[iLocation].Qizhan->Y, GCJ[iLocation].Zhaozhan->X, GCJ[iLocation].Zhaozhan->Y);
L0 = T0 - Z0;
if (L0 < 0)
{
L0 = L0 + 2 * pi;
}
l1 = (dms2rad(GCJ[i].GCangle) - L0) * 180 * 3600 / pi;//轉換為秒
L(i, 0) = l1;
}
//B矩陣距離指派
double dX0, dY0, dS;//邊長坐标差
for (int i = 0; i < Glengthsums; i++)
{
double l2;//距離系數陣
dX0 = GCB[i].Zdian->X - GCB[i].Qdian->X;
dY0 = GCB[i].Zdian->Y - GCB[i].Qdian->Y;
dS = sqrt(dX0*dX0 + dY0 * dY0);
a2 = dX0 / dS;
b2 = dY0 / dS;
for (int j = 0; j < unkownsunms; j++)
{
if (GCB[i].Qdian->dianhao == WZD[j].dianhao)//如果觀測值測站是第j個未知點
{
B(i + Ganglesums, 2 * j) = -a2; B(i + Ganglesums, 2 * j + 1) = -b2;
}
if (GCB[i].Zdian->dianhao == WZD[j].dianhao)//如果觀測值照準點是第j個未知點
{
B(i + Ganglesums, 2 * j) = a2; B(i + Ganglesums, 2 * j + 1) = b2;
}
}
//L陣距離部分指派
l2 = (GCB[i].Glength - dS)*1000.0;//換算成毫米
L(i + Ganglesums, 0) = l2;
}
//開始平差
Nbb.resize(2 * unkownsunms + CZsums, 2 * unkownsunms + CZsums);//Nbb=B'PB
fe.resize(2 * unkownsunms + CZsums, 1);//fe=B'PL
XX.resize(2 * unkownsunms + CZsums, 1);//XX=Nbb^-1*fe
Nbb = B.transpose()*P*B;
fe = B.transpose()*P*L;
XX = Nbb.inverse()*fe;
V.resize(Glengthsums + Ganglesums, 1);//初始化V陣
V = B * XX - L;
for (int i = 0; i < unkownsunms; i++)
{
WZD[i].X = WZD[i].X + XX(2 * i, 0) / 1000;//計算坐标
WZD[i].Y = WZD[i].Y + XX(2 * i + 1, 0) / 1000;
}
DDsums++;
} while (DDsums < 4);
}//平差結束
//精度評定
Qxx.resize(2 * unkownsunms + CZsums, 2 * unkownsunms + CZsums);
Qxx = Nbb.inverse();//未知數協因數陣
Min = V.transpose()*P*V;
min = Min(0, 0);
m0 = sqrt(abs(min / (Glengthsums + Ganglesums - 2 * unkownsunms - CZsums)));//機關權中誤差
for (int i = 0; i < unkownsunms; i++)//進行循環計算每個位置點的點位誤差和誤差橢圓元素
{
double Qx = Qxx(2 * i, 2 * i);
double Qy = Qxx(2 * i + 1, 2 * i + 1);
double Qxy = Qxx(2 * i, 2 * i + 1);
WZD[i].mx = m0 * sqrt(abs(Qx));
WZD[i].my = m0 * sqrt(abs(Qy));
WZD[i].mk = sqrt(WZD[i].mx*WZD[i].mx + WZD[i].my * WZD[i].my);
WZD[i].Q = atan(2 * Qxy / (Qx - Qy)) / 2;//長半徑方位角
WZD[i].E = m0 * sqrt(Qx + Qxy * tan(WZD[i].Q));//長半軸
WZD[i].F = m0 * sqrt(Qx + Qxy * tan(WZD[i].Q + pi / 2));//短半軸
}
//對平差結果進行輸出
CString com;//輸出平差結果
//com.Format(_T("%s\t%s%f\r\n"), _T("最終所有點的坐标:"));
cunchu2 += "已知點坐标:\r\n";
for (int i = 0; i < KZDsums; i++)
{
com.Format(_T("%s\t%.4f\t%.4f\r\n"), KZD[i].dianhao, KZD[i].X, KZD[i].Y);
cunchu2 += com;
}//輸出已知點
cunchu2 += "未知點平差後坐标:\r\n";
for (int i = 0; i < unkownsunms; i++)
{
com.Format(_T("%s\t%.4f\t%.4f\r\n"), WZD[i].dianhao, WZD[i].X, WZD[i].Y);
cunchu2 += com;
}//輸出未知點近似坐标
com.Format(_T("%s%d\r\n"), _T("疊代次數:"), DDsums);
cunchu2 += com;
com.Format(_T("%s\t%s%f\r\n"), _T("機關中誤差(mm):"), _T("±"), m0);
cunchu2 += com;
cunchu2 += "距離觀測成果:\r\n";
cunchu2 += "測站\t照準\t距離觀測值(m)\t改正數(m)\t平差後值(m)\t方位角(dms)\r\n";
for (int i = 0; i < Glengthsums; i++)
{
com.Format(_T("%s\t%s\t%.6f %.6f %.6f %.6f\r\n"),
GCB[i].Qdian->dianhao,
GCB[i].Zdian->dianhao,
GCB[i].Glength,
V(i + Ganglesums, 0) / 1000,
GCB[i].Glength + V(i + Ganglesums, 0) / 1000,
rad2dms(fangweijiao(GCB[i].Qdian->X, GCB[i].Qdian->Y, GCB[i].Zdian->X, GCB[i].Zdian->Y)));
cunchu2 += com;
}
cunchu2 += "方向觀測成果:\r\n";
cunchu2 += "測站 找準 觀測方向值(dms)\t改正數(s)\t改正後的值\r\n";
for (int i = 0; i < Ganglesums; i++)
{
com.Format(_T("%s\t%s %.4f %.4f %.4f\r\n"),
GCJ[i].Qizhan->dianhao,
GCJ[i].Zhaozhan->dianhao,
GCJ[i].GCangle,
V(i, 0) / 1000,
GCJ[i].GCangle + V(i, 0) / 1000);
cunchu2 += com;
}
}
panduan2 = 1;//證明已完成平差
return 0;
}
//求控制點x最值
double support::Maxmin1x(Data *KZD, int KZDsums, int tag)
{
double Temp = KZD[0].X;
if (tag == 2)//傳回最大值
{
for (int i = 0; i < KZDsums - 1; i++)
{
if (KZD[i + 1].X > Temp)
{
Temp = KZD[i + 1].X;
}
}
}
else if (tag == 1)
{
for (int i = 0; i < KZDsums - 1; i++)
{
if (KZD[i + 1].X < Temp)
{
Temp = KZD[i + 1].X;
}
}
}
return Temp;
}
//求控制點y最值
double support::Maxmin1y(Data *KZD, int KZDsums, int tag)
{
double Temp = KZD[0].Y;
if (tag == 2)//傳回最大值
{
for (int i = 0; i < KZDsums - 1; i++)
{
if (KZD[i + 1].Y > Temp)
{
Temp = KZD[i + 1].Y;
}
}
}
else if (tag == 1)
{
for (int i = 0; i < KZDsums - 1; i++)
{
if (KZD[i + 1].Y < Temp)
{
Temp = KZD[i + 1].Y;
}
}
}
return Temp;
}
//求未知點x最值
double support::Maxmin2x(Data *WZD, int unkownsunms, int tag)
{
double Temp = WZD[0].X;
if (tag == 2)//傳回最大值
{
for (int i = 0; i < unkownsunms - 1; i++)
{
if (WZD[i + 1].X > Temp)
{
Temp = WZD[i + 1].X;
}
}
}
else if (tag == 1)
{
for (int i = 0; i < unkownsunms - 1; i++)
{
if (WZD[i + 1].X < Temp)
{
Temp = WZD[i + 1].X;
}
}
}
return Temp;
}
//求未知點y最值
double support::Maxmin2y(Data *WZD, int unkownsunms, int tag)
{
double Temp = WZD[0].Y;
if (tag == 2)//傳回最大值
{
for (int i = 0; i < unkownsunms - 1; i++)
{
if (WZD[i + 1].Y > Temp)
{
Temp = WZD[i + 1].Y;
}
}
}
else if (tag == 1)
{
for (int i = 0; i < unkownsunms - 1; i++)
{
if (WZD[i + 1].Y < Temp)
{
Temp = WZD[i + 1].Y;
}
}
}
return Temp;
}
//畫控制點位置
void support::huiKZD(CDC* pDC, double x, double y, double length, double a)//y軸向下
{
double l = length * 0.5*a;
CPen pen;
pen.CreatePen(PS_SOLID, 1.8, RGB(0, 255, 0));//實作畫筆
CPen *pOldPen;
pOldPen = pDC->SelectObject(&pen);
pDC->MoveTo(x - l, y + l / sqrt(3));
pDC->LineTo(x + l, y + l / sqrt(3));
pDC->LineTo(x, y - 2 * sqrt(3)*l / 3);
pDC->LineTo(x - l, y + l / sqrt(3));
}
void support::huitu(CDC * pDC, CRect rect, double karfa)
{
int X01 = 0;//螢幕的左上角x
int Y01 = 0;//螢幕的左上角y
int X02 = rect.Width()-300;//螢幕的右下角x
int Y02 = rect.Height() - 175; //螢幕的右下角y
if (panduan == 0)
{
AfxMessageBox(_T("請輸入資料"));
}
else if (panduan1 == 0)
{
AfxMessageBox(_T("請先進行概算"));
}
else if (panduan2 == 0)
{
AfxMessageBox(_T("請先進行平差"));
}
else
{
CPen pen;
pen.CreatePen(PS_SOLID, 3.6, RGB(0, 0, 255));//實線畫筆
CPen *pOldPen;
pOldPen = pDC->SelectObject(&pen);
double ylength = karfa * (X02 - X01)/*-300*/;//y坐标軸長度
double xlength = karfa * (Y02 - Y01)/*-50*/;//x坐标軸長度
double Xmax, Xmin, Ymax, Ymin;
Xmax = Maxmin1x(KZD, KZDsums, 2) > Maxmin2x(WZD, unkownsunms, 2) ? Maxmin1x(KZD, KZDsums, 2) : Maxmin2x(WZD, unkownsunms, 2);
Xmin = Maxmin1x(KZD, KZDsums, 1) < Maxmin2x(WZD, unkownsunms, 1) ? Maxmin1x(KZD, KZDsums, 1) : Maxmin2x(WZD, unkownsunms, 1);
Ymax = Maxmin1y(KZD, KZDsums, 2) > Maxmin2y(WZD, unkownsunms, 2) ? Maxmin1y(KZD, KZDsums, 2) : Maxmin2y(WZD, unkownsunms, 2);
Ymin = Maxmin1y(KZD, KZDsums, 1) < Maxmin2y(WZD, unkownsunms, 1) ? Maxmin1y(KZD, KZDsums, 1) : Maxmin2y(WZD, unkownsunms, 1);//确定X、Y最值
double karfa2 = ((Xmax - Xmin) > (Ymax - Ymin)) ? ((Xmax - Xmin) / xlength) : ((Ymax - Ymin) / ylength);//實際坐标投影至圖中的系數
double x0 = Y02 - (1 - karfa)*0.3*(Y02 - Y01)+30;
double y0 = X01 + (1 - karfa)*0.3*(X02 - X01)+100;//起始坐标 原點
CString str;//原點
str.Format(_T("%.f %.f"), Xmin , Ymin);
//繪制X軸
double temp_x001 = y0;
double temp_x002 = y0;
double temp_x003 = y0;
double temp_x004 = y0 - 7;
double temp_x005 = y0;
double temp_x006 = y0 + 7;
double temp_x007 = y0 - 10;
double temp_y001 = x0;
double temp_y002 = x0 - (0.25 + 0.75*karfa)*(Y02 - Y01);
double temp_y003 = x0 - (0.25 + 0.75*karfa)*(Y02 - Y01);
double temp_y004 = x0 - (0.25 + 0.75*karfa)*(Y02 - Y01) + 7;
double temp_y005 = x0 - (0.25 + 0.75*karfa)*(Y02 - Y01);
double temp_y006 = x0 - (0.25 + 0.75*karfa)*(Y02 - Y01) + 7;
double temp_y007 = x0 - (0.25 + 0.75*karfa)*(Y02 - Y01) -20;
pDC->MoveTo(temp_x001, temp_y001);
pDC->LineTo(temp_x002, temp_y002);
pDC->MoveTo(temp_x003, temp_y003);
pDC->LineTo(temp_x004, temp_y004);
pDC->MoveTo(temp_x005, temp_y005);
pDC->LineTo(temp_x006, temp_y006);
pDC->TextOut(temp_x007, temp_y007, _T("X"));
//繪制Y軸
temp_x001 = y0;
temp_x002 = y0 + (0.25 + 0.75*karfa)*(X02 - X01);
temp_x003 = y0 + (0.25 + 0.75*karfa)*(X02 - X01);
temp_x004 = y0 + (0.25 + 0.75*karfa)*(X02 - X01) - 7;
temp_x005 = y0 + (0.25 + 0.75*karfa)*(X02 - X01);
temp_x006 = y0 + (0.25 + 0.75*karfa)*(X02 - X01) -7;
temp_x007 = y0 + (0.25 + 0.75*karfa)*(X02 - X01);
temp_y001 = x0;
temp_y002 = x0;
temp_y003 = x0;
temp_y004 = x0 - 7;
temp_y005 = x0;
temp_y006 = x0+7 ;
temp_y007 = x0 -20;
pDC->MoveTo(temp_x001, temp_y001);
pDC->LineTo(temp_x002, temp_y002);
pDC->MoveTo(temp_x003, temp_y003);
pDC->LineTo(temp_x004, temp_y004);
pDC->MoveTo(temp_x005, temp_y005);
pDC->LineTo(temp_x006, temp_y006);
pDC->TextOut(temp_x007, temp_y007, _T("Y"));
//畫平行Y軸的刻度
int tag_x = 5;//5條線
double temp_tag_x = xlength / tag_x;
double temp_x = temp_tag_x;
for (int i = 0; i < 5; i++)
{
double t_x = y0;
double t_y = x0 - temp_x;
double t_x2 = y0 + ylength;
double t_y2 = x0 - temp_x;
pDC->MoveTo(t_x , t_y );
pDC->LineTo(t_x2 , t_y2 );
CString str;
str.Format(_T("%.f"), Xmin + (i + 1)*(Xmax - Xmin) / 5);
double t_x3 = y0 - 75;
double t_y3 = x0 - temp_x;
pDC->TextOut(t_x3, t_y3, str);
temp_x += temp_tag_x;
}
//畫平行X軸的刻度
int tag_y = 5;//5條線
double temp_tag_y = ylength / tag_y;
double temp_y = temp_tag_y;
for (int i = 0; i < 5; i++)
{
double t_x = y0 + temp_y;
double t_y = x0;
double t_x2 = y0 + temp_y;
double t_y2 = x0 - xlength;//錯誤
pDC->MoveTo(t_x, t_y );
pDC->LineTo(t_x2 , t_y2 );
CString str;
str.Format(_T("%.f"), Ymin + (i + 1)*(Ymax - Ymin) / 5);
double t_x3 = y0 + temp_y;
double t_y3 = x0 ;
pDC->TextOut(t_x3, t_y3, str);
temp_y += temp_tag_y;
}
//方向觀測值連線
for (int i = 0; i < Ganglesums; i++)
{
CPen pen;
pen.CreatePen(PS_SOLID, 0.8, RGB(255, 0, 0));//實線畫筆
CPen *pOldPen;
pOldPen = pDC->SelectObject(&pen);
double t_x = (GCJ[i].Qizhan->Y - Ymin) / karfa2 + y0;
double t_y = x0 - (GCJ[i].Qizhan->X - Xmin) / karfa2;
double t_x2 = (GCJ[i].Zhaozhan->Y - Ymin) / karfa2 + y0 ;
double t_y2 = x0 - (GCJ[i].Zhaozhan->X - Xmin) / karfa2;
pDC->MoveTo(t_x, t_y );
pDC->LineTo(t_x2, t_y2);
pen.DeleteObject();
}
//畫誤差橢圓
double karfa3 = (0.8 / karfa) *(WZD[0].E) / 5;//比例系數
for (int i = 0; i < unkownsunms; i++)
{
CPen pen;
pen.CreatePen(PS_SOLID, 1.8, RGB(20, 20, 20));//實線畫筆
CPen *pOldPen;
pOldPen = pDC->SelectObject(&pen);
for (int j = 0; j < 120; j ++)
{
//畫橢圓
double dAlf = j * 2 * pi / 120;
double xae, ybf;
double c = 0;
double tralatazi;
xae = WZD[i].E / karfa3 * cos(dAlf);
ybf = WZD[i].F / karfa3 * sin(dAlf);
tralatazi = WZD[i].Q + pi / 2;
double temp_1 = xae * cos(tralatazi) + ybf * sin(tralatazi) + (WZD[i].Y - Ymin) / karfa2 + y0 ;
double temp_2 = -ybf * cos(tralatazi) + xae * sin(tralatazi) + x0 - (WZD[i].X - Xmin) / karfa2 ;
if (j == 0)
{
pDC->MoveTo(temp_1 , temp_2 );
}//防止從橢圓的長短軸而不是中心連接配接下一個點
pDC->LineTo(temp_1 , temp_2 );
}
double temp1 = (WZD[i].Y - Ymin) / karfa2 + y0 + (WZD[i].F*sin(WZD[i].Q + pi / 2)) / karfa3 ;//短軸右上角 x
double temp2 = x0 - (WZD[i].X - Xmin) / karfa2 - (WZD[i].F*cos(WZD[i].Q + pi / 2)) / karfa3 ;//短軸右上角 y
double temp3 = (WZD[i].Y - Ymin) / karfa2 + y0 - (WZD[i].F*sin(WZD[i].Q + pi / 2)) / karfa3 ;//短軸左下角 x
double temp4 = x0 - (WZD[i].X - Xmin) / karfa2 + (WZD[i].F*cos(WZD[i].Q + pi / 2)) / karfa3 ;//短軸左下角 y
pDC->MoveTo(temp1 , temp2);
pDC->LineTo(temp3 , temp4);
pen.DeleteObject();
double _temp1 = (WZD[i].Y - Ymin) / karfa2 + y0 + (WZD[i].E*cos(WZD[i].Q + pi / 2)) / karfa3 ;//長軸右下角 x
double _temp2 = x0 - (WZD[i].X - Xmin) / karfa2 + (WZD[i].E*sin(WZD[i].Q + pi / 2)) / karfa3 ;//長軸右上角 y
double _temp3 = (WZD[i].Y - Ymin) / karfa2 + y0 - (WZD[i].E*cos(WZD[i].Q + pi / 2)) / karfa3 ;//長軸左上角 x
double _temp4 = x0 - (WZD[i].X - Xmin) / karfa2 - (WZD[i].E*sin(WZD[i].Q + pi / 2)) / karfa3 ;//長軸左上角 y
pDC->MoveTo(_temp1, _temp2);
pDC->LineTo(_temp3, _temp4 );
}
for (int i = 0; i < unkownsunms; i++)//畫未知點點号
{
CString str;
str.Format(_T("%s"), WZD[i].dianhao);
double temp_1 = (WZD[i].Y - Ymin) / karfa2 + y0 ;
double temp_2 = x0 - (WZD[i].X - Xmin) / karfa2 ;
pDC->TextOut(temp_1 , temp_2 , str);
}
for (int i = 0; i < KZDsums; i++)//畫已知點點号
{
CString str;
str.Format(_T("%s"), KZD[i].dianhao);
double temp_1 = (KZD[i].Y - Ymin) / karfa2 + y0 ;
double temp_2 = x0 - (KZD[i].X - Xmin) / karfa2;
huiKZD(pDC, temp_1, temp_2 , 50, karfa-0.5 );
pDC->TextOut(temp_1 , temp_2, str);
}
}
}
<主對話框.cpp>
#include "Data.h"
#include"Length.h"
#include"Gangle.h"
#include"support.h"
#include"Draw.h"//畫圖對話框名稱
support k;
Draw o;
//文本顯示框綁定的為的Cstring變量為out
void CSHIXIDSDlg::OnBnClickedButton1()//讀取資料并顯示
{
// TODO: 在此添加控件通知處理程式代碼
UpdateData(TRUE);
k.cunchu.Empty();
double a = k.read();
out = k.cunchu;
UpdateData(FALSE);
}
void CSHIXIDSDlg::OnBnClickedButton2()//輸出概算結果
{
// TODO: 在此添加控件通知處理程式代碼
UpdateData(TRUE);
k.cunchu1.Empty();
double b = k.gaisuan();//先運作概算
out = k.cunchu1;
UpdateData(FALSE);
}
void CSHIXIDSDlg::OnBnClickedButton3()//輸出平差結果
{
// TODO: 在此添加控件通知處理程式代碼
UpdateData(TRUE);
k.cunchu2.Empty();
double c = k.pingcha();//先運作平差
out = k.cunchu2;
UpdateData(FALSE);
}
void CSHIXIDSDlg::OnBnClickedButton4()//進行畫圖
{
// TODO: 在此添加控件通知處理程式代碼
Draw abc;
abc.o = k;
abc.DoModal();
}
void CSHIXIDSDlg::OnBnClickedButton5()//退出
{
// TODO: 在此添加控件通知處理程式代碼
CDialogEx::OnCancel();
}
<Draw.cpp>
//頭檔案自行添加
support o;
void Draw::OnBnClickedButton1()//畫圖
{
// TODO: 在此添加控件通知處理程式代碼
UpdateData(TRUE);
CDC* pDC = GetDlgItem(IDC_STATIC)->GetDC();
GetDlgItem(IDC_STATIC)->UpdateWindow();
CRect rc;
GetDlgItem(IDC_STATIC)->GetWindowRect(&rc);
GetWindowRect(&rc);
o.huitu(pDC, rc, 0.9);
UpdateData(FALSE);
}
void Draw::OnBnClickedButton2()//退出
{
// TODO: 在此添加控件通知處理程式代碼
CDialogEx::OnCancel();
}
運作結果
答辯高分總結
答辯分為兩部分:
1、修改程式(時間最好控制在三十分鐘以内可以保證A,時間越長分越低,重點在畫圖部分,修改程式完成後,老師隻看運作結果,或者問原理,不會看代碼)
2、老師問問題(隻要程式是自己做的,幾乎沒有問題,老師一般隻問五六行代碼是什麼意思且集中在畫圖前的部分,是以重點在修改程式)
修改程式問題彙總:
每人改兩個程式
1、一個簡單的:諸如修改資料格式後讀取資料、輸出權矩陣P的對角線元素等等随機選一個,不必準備。
2、一個稍複雜的:集中在畫圖部分,主要是将誤差橢圓呈現在畫圖區域中心、誤差橢圓放大縮小、誤差橢圓旋轉、将圖像呈現在新的對話框中(本程式已改)等随機選一個,可以提前練習一下,十分簡單。
修改程式提前練習一下,至少可以得A(優)。
設計時間配置設定
一周時間足夠将程式寫完,重點要了解概算和平差的詳細步驟,畫圖部分代碼可以直接粘貼,不過要仔細了解每個變量所對應的圖像内容。
程式遇到問題時要學會設斷點調試!!!
隻要認為自己的算法沒問題,一般問題就是代碼的變量順序反了,或者是<和>搞錯了等問題。