天天看點

導線網平差程式系統設計

原始資料(格式)

導線網平差程式系統設計

界面設計 

導線網平差程式系統設計

 點選畫圖按鈕後彈出的對話框

導線網平差程式系統設計

類的設計

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(優)。

設計時間配置設定

       一周時間足夠将程式寫完,重點要了解概算和平差的詳細步驟,畫圖部分代碼可以直接粘貼,不過要仔細了解每個變量所對應的圖像内容。

       程式遇到問題時要學會設斷點調試!!!

       隻要認為自己的算法沒問題,一般問題就是代碼的變量順序反了,或者是<和>搞錯了等問題。

繼續閱讀