导线网平差的程序。
Tab’=Tab+A, 为前进方向的左角 Tab可由a,b两点的坐标反算而得
A’=t_ak-t_ab,t_ak,t_ab为方向观测值
3.3.3 平差部分:
平差计算原理:
设:观测值为L,其权为P,相应的改正数为V,必要观测数为t。
如图B矩阵可分为4部分:左上角、右上角、左下角、右下角部分。
B矩阵对应的行是:方向角度观测数+边长观测数
对应的列是:未知点个数*2(本题平面维度x,y)+基础测站数。
1)关于基础测站数,即右上角数据的说明:以样例数据一为说明(样例数据在后文有完整版)
由于降低了难度,并没有采取史赖伯一次约化,而采取了最小二乘算法。
2)关于方向角度观测数的系数,即左上角数据的说明
根据先验方向观测中误差和边长观测中误差来定权
1)方向观测值的权
在等精度方向观测的控制网中,可把方向观测值的权定为1,不同精度的观测网中,则选择其中一种作为单位权中误差u(单位:秒),其它方向观测值中误差为m(单位:秒),则p=μ2/m2
2)边长观测值的权
p_s=μ2/(m_s2 ),其中边长中误差可由m_s=±(A+B⋅S⋅0.1)或m_s=±√S B (单位:厘米)计算,A为测距仪常数误差,B为测距仪比例误差因子,S为边长的长度(单位:公里)。在导线网中一般取方向观测值中误差为单位权中误差。例:观测方向中误差 .边长测量中误差 ,可假设单位权中误差则方向观测权 ,则方向观测值的权为1,观测边权为=100/Si。
以上定权的方式还不是严密的,因为角度和边长是不同的观测量,可采用赫尔默特方差份量估计,迭代定权。
四、界面展示及实例数据
#include "stdafx.h"
#include "Data_P.h"
Data_P::Data_P()
{
}
Data_P::~Data_P()
{
}
#pragma once
#include"Data_P.h"
class Data_Obslength
{
public:
Data_Obslength();
~Data_Obslength();
Data_P *pFront_id;//观测前站
Data_P *pBack_id;//观测后站
double dFB_dist;//观测距离
};
#include "stdafx.h"
#include "Data_Obslength.h"
Data_Obslength::Data_Obslength()
{
pFront_id = NULL;
pBack_id = NULL;
dFB_dist = 0;
}
Data_Obslength::~Data_Obslength()
{
}
#pragma once
//储存角类信息
#include "Angle.h"
#include "Data_Obslength.h"
class Data_Obsangle
{
public:
Data_Obsangle();
~Data_Obsangle();
Data_P *pStation;//测站
Data_P *pEnd;//照准
Angle ObsAngel;//观测角度
};
#include "stdafx.h"
#include "Data_Obsangle.h"
Data_Obsangle::Data_Obsangle()
{
}
Data_Obsangle::~Data_Obsangle()
{
}
#pragma once
class Data_P
{
public:
Data_P();
~Data_P();
CString strID;
double dx;
double dy;
int flag;
//下列元素仅未知点有
double dmx;
double dmy;
double dmk;
double dQ;//长半径方位角
double dE;//长半径
double dF;//短半径
};
#include "stdafx.h"
#include "Data_P.h"
Data_P::Data_P()
{
}
Data_P::~Data_P()
{
}
//进行导线网水准网操作类
//2019/07/02
#pragma once
#include
#include //引用eigen类
//#include"Data_P.h"//引用已知控制点类
//#include "Data_Obslength.h"//引用观测边类
#include "Data_Obsangle.h"//引用观测角类
using namespace Eigen; //引用eigen类 操作步骤:属性 包含文件的路径
using namespace std;
class Do
{
//私有数据成员
private:
Data_P *cp;//定义已知点指针
Data_P *up;//定义未知点指针
Data_Obslength *Dist_obs;//定义观测边指针
Data_Obsangle *Angle_obs;//定义观测角
int iSum_cp;//定义已知点总个数
int iSum_up;//定义未知点总个数
int iAngle_Station;//定义测站数 需修改鲁棒性
int iSum_Dist_obs;//定义观测值总边长个数
int iSum_Angle_obs;//定义观测角总个数
double alfa_wrong;//定义角度误差 鲁棒性
double length_wrong;//定义边长误差 鲁棒性
//平差成员
MatrixXd B;//矩阵B
MatrixXd F;//矩阵f
MatrixXd P;//矩阵P
MatrixXd v;//矩阵v
MatrixXd Nbb;//矩阵Nbb
MatrixXd Qxx;//矩阵Qxx
double r0;//单位权中误差
//供输出用
CString Result;
CString EstrOut;//Excel模式
//私有成员函数
private:
int Div(const CString strLine, char split, CStringArray &strArray);//字符串分割函数
void LinetoCString(CString Result, CString &strOut, CString &EstrOut);//输出一行数据
void MatrixtoCstring(MatrixXd A, CString &Result, CString &strOut, CString &EstrOut);//输出矩阵至CString中
Data_P *Search_cp(CString strID);//搜索已知点返回对应站储存的地址
Data_P *Search_up(CString strID);//返回已知点对应站储存的地址
Data_P *Search_allp(CString strID);//返回所有点对应站储存的地址
double Process_Rad(double dx1, double dy1, double dx2, double dy2);//由(dx1,dy1)、(dx2,dy2)求方位角 返回弧度
//平差
void BF_angle_abcd(Data_Obsangle Angle_obs, double &a, double &b, double &_a, double &_b);//计算角度
void BF_angle_f(Data_Obsangle Angle_ob, double &f);//计算角度值对应的f
void BF_dist_abcdf(Data_Obslength Dist_ob, double &a, double &b, double &_a, double &_b,double &f);//计算边长观测值对应的f
void Adjustment_BF();//计算B、F系数阵
void Adjustment_P();//计算P矩阵
void Adjustment_accuracy();//经度评定
//画图排序模块
double Min1_max2_x(Data_P *cp, int iSum_cp, int tag);//求x最小值最大值
double Min1_max2_y(Data_P *cp, int iSum_cp, int tag);//求x最小值最大值
//画图
void Draw_tri(CDC* pDC, double x, double y, double length,double a);//画三角形
void Draw_ro(double &x, double &y, double alfa, CRect &rect, double dx, double dy,double ro1, double ro2);//坐标旋转转换
public:
Do();
~Do();
int estimate();//数据概算
void adjustment_main();//平差主函数
bool read();//读取函数
void out();//输出计算函数
void ReportExcel();//输出至excel
void Reporttxt();//输出至txt
//void main();//主函数进行综合操作
void draw(CDC* pDC, CRect rect,double coefficient,double alfa,double dx,double dy, double ro1, double ro2);//画图
CString strOut;//txt
};
#include "stdafx.h"
#include "Do.h"
#define PI 3.14159265358979323846
Do::Do()
{
cp = NULL;
this->iSum_cp = 0;
this->iSum_up = 0;
strOut = (_T(""));
EstrOut = (_T(""));
}
//***********************************
//析构函数 删除指针
//***********************************
Do::~Do()
{/*
delete [] cp;
delete[] up;
delete[] Dist_obs;
delete[] Angle_obs;*/
}
//***********************************
//字符分割函数
//***********************************
int Do::Div(const CString strLine, char split, CStringArray &strArray)
{
strArray.RemoveAll();//自带清空属性
CString temp = strLine;
int tag = 0;
while (1)
{
tag = temp.Find(split);
if (tag >= 0)
{
strArray.Add(temp.Left(tag));
temp = temp.Right(temp.GetLength() - tag - 1);
}
else { break; }
}
strArray.Add(temp);
return strArray.GetSize();
}
//***********************************
//输出一行数据,并赋值给strOut、EstrOut
//***********************************
void Do::LinetoCString(CString Result, CString &strOut, CString &EstrOut)//输出一行数据
{
CString temp;
temp.Format(Result);
strOut += temp;
strOut += "\r\n";
EstrOut += temp;
EstrOut += "\n";
}
//***********************************
//输出矩阵,并赋值给strOut、EstrOut
//***********************************
void Do::MatrixtoCstring(MatrixXd A, CString &Result, CString &strOut,CString &EstrOut)
{
Result.Format(_T("%s%d%s%d\r\n"), _T("----------(支持matlab矩阵)矩阵大小(行列):"), A.rows(), _T("X"), A.cols());
strOut += Result;
Result.Format(_T("%s\t%d%s%d\n"), _T("(支持matlab矩阵)矩阵大小(行列):"), A.rows(), _T("X"), A.cols());
EstrOut += Result;
for (int i = 0; i < A.rows(); i++)
{
for (int j = 0; j < A.cols(); j++)
{
Result.Format(_T(" %.6f"), A(i, j));
strOut += Result;
}
if (i != A.rows() - 1)
{
strOut += ";\r\n";
}
else
{
strOut += "\r\n";
}
}
for (int i = 0; i < A.rows(); i++)
{
for (int j = 0; j < A.cols(); j++)
{
Result.Format(_T(" %.6f\t"), A(i, j));
EstrOut += Result;
}
if (i != A.rows() - 1)
{
EstrOut += ";\n";
}
else
{
EstrOut += "\n";
}
}
}
//***********************************
//ID已知点点位搜索
//***********************************
Data_P *Do::Search_cp(CString strID)
{
for (int i = 0; i < iSum_cp; i++)
{
if (strID == cp[i].strID)
{
return &cp[i];
}
}
return NULL;
}
//***********************************
//ID未知点点位搜索
//***********************************
Data_P *Do::Search_up(CString strID)
{
for (int i = 0; i < iSum_up; i++)
{
if (strID == up[i].strID)
{
return &up[i];
}
}
return NULL;
}
//***********************************
//所有点点位搜索
//***********************************
Data_P *Do::Search_allp(CString strID)
{
Data_P *temp_p;
temp_p = Search_cp(strID);
if (temp_p == NULL)
{
temp_p = Search_up(strID);
}
return temp_p;
}
//***********************************
//由(dx1,dy1)、(dx2,dy2)求方位角 返回弧度
//***********************************
double Do::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;
}
//***********************************
//读取函数
//***********************************
bool Do::read()
{
CFileDialog dlgFile(TRUE, _T("txt"), NULL,
OFN_ALLOWMULTISELECT | OFN_EXPLORER,
//_T("(文本文件)|*.txt"));
_T(""));
if (dlgFile.DoModal() == IDCANCEL) return 0;
CString strName = dlgFile.GetPathName();//获取打开文件文件名(路径)
setlocale(LC_ALL, "");
CStdioFile sf;
if (!sf.Open(strName, CFile::modeRead)) return 0;//打开strName文件路径中的内容
CString strLine;
CString strContent;//接受内容字符串
CStringArray array;//供下文分割使用
strContent.Empty();//strContent中内容清空
//开始读数据
BOOL bEOF = sf.ReadString(strLine);//第一行
if (bEOF == 0) { AfxMessageBox(_T("空数据")); return 0; }
if (strLine!=_T("[ControlPoint]")) { AfxMessageBox(_T("数据错误")); return 0; }
//读取控制点
bEOF = sf.ReadString(strLine);//第二行
if (bEOF == 0) { AfxMessageBox(_T("数据不规范")); return 0; }
iSum_cp= _ttoi(strLine);//读取控制点个数
cp = new Data_P[iSum_cp];
int i = 0;
while (iflag == 1 && Angle_obs[i].pEnd->flag == 1)//如果观测的前后站都是找到了
{
//寻找符合某个基站算出位置的 找准站没位置的
//计算其方位角后,交给下个for循坏
for (int j = 0; j < iSum_Angle_obs; j++)
{
if (Angle_obs[j].pStation->strID == Angle_obs[i].pStation->strID&&Angle_obs[j].pEnd->flag == -1)
{
Angle ji_alfa = Angle_obs[j].ObsAngel - Angle_obs[i].ObsAngel;
Angle i_alfa = Angle(Process_Rad(Angle_obs[i].pStation->dx, Angle_obs[i].pStation->dy, Angle_obs[i].pEnd->dx, Angle_obs[i].pEnd->dy), RAD);
double azi = ji_alfa(RAD) + i_alfa(RAD);//计算方位角
double dDist;
//寻找相应的边长观测是否存在 按方向和观测值来求坐标
for (int k = 0; k < iSum_Dist_obs; k++)//按边长观测值计算三边网中待定点的近似坐标
{
if (
(Dist_obs[k].pFront_id->strID == Angle_obs[j].pStation->strID
&&Dist_obs[k].pBack_id->strID == Angle_obs[j].pEnd->strID) ||
(Dist_obs[k].pFront_id->strID == Angle_obs[j].pEnd->strID
&&Dist_obs[k].pBack_id->strID == Angle_obs[j].pStation->strID)
)//寻找边长是否存在
{
dDist = Dist_obs[k].dFB_dist;
Angle_obs[j].pEnd->dx = Angle_obs[j].pStation->dx + dDist * cos(azi);
Angle_obs[j].pEnd->dy = Angle_obs[j].pStation->dy + dDist * sin(azi);
Angle_obs[j].pEnd->flag = 1;//做标记为已确定的观测值
icount++;
}
}
}
}
}
}
} while (icount < iSum_up);
is = 1;
}
//输出概算数据
LinetoCString(_T("----------------------------坐标概算----------------------------"), strOut, EstrOut);
for (int i = 0; i < iSum_up; i++)
{
Result.Format(_T("%s\t%.4f\t%.4f\r\n"), up[i].strID, up[i].dx, up[i].dy);
strOut += Result;
}
for (int i = 0; i < iSum_up; i++)
{
Result.Format(_T("%s\t%.4f\t%.4f\n"), up[i].strID, up[i].dx, up[i].dy);
EstrOut += Result;
}
return 0;
}
//***********************************
B矩阵前面的角度赋值
//***********************************
void Do::BF_angle_abcd(Data_Obsangle Angle_obs, double &a, double &b, double &_a, double &_b)
{
double dx0 = Angle_obs.pEnd->dx- Angle_obs.pStation->dx ;
double dy0 = Angle_obs.pEnd->dy- Angle_obs.pStation->dy;
double S0 = sqrt(dx0*dx0 + dy0 * dy0);
double temp_a = (180 * 3600 / PI)*dy0 / (S0*S0* 1000.0);
double temp_b = -(180 * 3600 / PI)*dx0 / (S0*S0 * 1000.0);
a = temp_a;
_a = -temp_a;
b = temp_b;
_b =- temp_b;
}
//***********************************
f赋值
//***********************************
void Do::BF_angle_f(Data_Obsangle Angle_ob,double &f)//计算角度值对应的f
{
Angle zero_1;//例如 1 3站 40度 ,1 2站 0度。求1,2站的方位角
for (int i = 0; i < iSum_Angle_obs; i++)
{
if (Angle_ob.pStation->strID == Angle_obs[i].pStation->strID
&& (Angle_obs[i].ObsAngel(DEG)< 1e-6))
{
zero_1 = Angle(Process_Rad(Angle_obs[i].pStation->dx, Angle_obs[i].pStation->dy, Angle_obs[i].pEnd->dx, Angle_obs[i].pEnd->dy),RAD);
break;
}
}
Angle zero_2= Angle(Process_Rad(Angle_ob.pStation->dx, Angle_ob.pStation->dy, Angle_ob.pEnd->dx, Angle_ob.pEnd->dy),RAD);//利用1,3站坐标推算其方位角
Angle zero_3 = Angle((zero_2(RAD) - zero_1(RAD)),RAD);//两方位角相减
zero_3 = Angle(((zero_3(DMS) < 0) ? (2 * PI + zero_3(RAD)) : zero_3(RAD)),RAD);//若小于零+2*pi
Angle temp_obs = Angle(Angle_ob.ObsAngel(RAD),RAD);//观测值
double temp_obs_DMS = temp_obs(RAD);
f = temp_obs(RAD) - zero_3(RAD);
f = f * 180 * 3600 / PI;//换算成秒
}
//***********************************
//B矩阵距离赋值
//***********************************
void Do::BF_dist_abcdf(Data_Obslength Dist_ob, double &a, double &b, double &_a, double &_b, double &f)//计算边长观测值对应的f
{
double temp_a, temp_b, dX0, dY0, dS0;
dX0 = Dist_ob.pBack_id->dx - Dist_ob.pFront_id->dx;
dY0 = Dist_ob.pBack_id->dy - Dist_ob.pFront_id->dy;
dS0 = sqrt(dX0*dX0 + dY0 * dY0);//观测边长距离
temp_a = dX0 / dS0;
temp_b = dY0 / dS0;
a = -temp_a;
b = -temp_b;
_a = temp_a;
_b = temp_b;
f = (Dist_ob.dFB_dist - dS0)*1000;//换算成毫米
}
//***********************************
//BF矩阵 调用上面的函数
//***********************************
void Do::Adjustment_BF()//计算B系数阵
{
//B.resize(iSum_Dist_obs + iSum_Angle_obs, iSum_up * 2 );
B.resize(iSum_Dist_obs + iSum_Angle_obs, iSum_up * 2 + iAngle_Station);//定义B矩阵的大小
B.setZero();//全部置为零
F.resize(iSum_Dist_obs + iSum_Angle_obs,1);
int iStation = 1;
int iLocation = 0;
//计算方向值
//这段目的是为了给B方向观测的B的右上角的矩阵
for (int i = 0; i < iSum_Angle_obs ; i++)
{
if (Angle_obs[i].pStation->strID != Angle_obs[iLocation].pStation->strID)
{
iStation++;
iLocation = i;
}
double a, b, _a, _b,f;
BF_angle_abcd(Angle_obs[i],a, b, _a, _b);//调用相应的函数 计算相应的 a,b,_a,_b;
BF_angle_f(Angle_obs[i],f);//求对应的f
B(i, 2 * iSum_up - 1 + iStation)=-1;//方向改正数 加-1
//下面这段for循环作用是给B矩阵的左上角的矩阵
for (int j = 0; j < iSum_up; j++)
{
if (Angle_obs[i].pStation->strID == up[j].strID)
{
B(i, 2 * j) = a;
B(i, 2 * j + 1) = b;
}
if (Angle_obs[i].pEnd->strID == up[j].strID)
{
B(i, 2 * j) = _a;
B(i, 2 * j + 1) = _b;
}
}
F(i, 0) =f;
}
//计算边长值
for (int i = 0; i < iSum_Dist_obs; i++)
{
double a, b, _a, _b, f;
BF_dist_abcdf(Dist_obs[i],a,b,_a,_b,f);//定系数函数 并求f
for (int j = 0; j < iSum_up; j++)
{
if (Dist_obs[i].pFront_id->strID == up[j].strID)//测站ID相等定个系数
{
B(i + iSum_Angle_obs, 2 * j) = a;
B(i + iSum_Angle_obs, 2 * j + 1) = b;
}
if (Dist_obs[i].pBack_id->strID == up[j].strID)//找准站ID相等定个系数
{
B(i + iSum_Angle_obs, 2 * j) = _a;
B(i + iSum_Angle_obs, 2 * j + 1) = _b;
}
}
F(i + iSum_Angle_obs, 0) = f;
}
}
//***********************************
//P矩阵
//***********************************
void Do::Adjustment_P()//计算P矩阵
{
P.resize(iSum_Dist_obs + iSum_Angle_obs, iSum_Dist_obs + iSum_Angle_obs);//首先给矩阵全部设置为0
for (int i = 0; i < (iSum_Dist_obs + iSum_Angle_obs ); i++)
{
for(int j=0;j< (iSum_Dist_obs + iSum_Angle_obs);j++)
{
if (i != j) { P(i, j) = 0; }
else if(i < iSum_Angle_obs) { P(i, j) = 1; }
else {
//P(i, j) = (alfa_wrong * alfa_wrong )/(length_wrong *length_wrong *Dist_obs[i - iSum_Angle_obs].dFB_dist/1000);
P(i, j) = 100 / Dist_obs[i - iSum_Angle_obs].dFB_dist;
double t = P(i, j);
double k = 1;
}
}
}
}
//***********************************
//平差函数
//***********************************
void Do::adjustment_main()//平差主函数
{
int tag = 0;
MatrixXd x;//改正数矩阵x 坐标相应改正数 测站相应改正数
MatrixXd fe;//BT*P*F
LinetoCString(_T("-----------------------------迭代过程-----------------------------"), strOut,EstrOut);
do
{
Adjustment_BF();
Adjustment_P();
Nbb = B.transpose()*P*B;
fe = B.transpose()*P*F;
//Nbb = B.transpose()*P*B;
//fe = B.transpose()*P*F;
x = Nbb.inverse()*fe;
v = B * x - F;
for (int i = 0; i < iSum_up; i++)
{
up[i].dx = up[i].dx + x(2 * i, 0) / 1000;
up[i].dy = up[i].dy + x(2 * i + 1, 0) / 1000;
}
tag++;
Result.Format(_T("%s%d%s\r\n"), _T(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>迭代第\t"),tag, _T("\t次<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"));
strOut += Result;
for (int i = 0; i < 10; i++)
{
Result.Format(_T("%s\t"), _T(">>>"));
EstrOut += Result;
}
Result.Format(_T("%s\t"),_T("迭代第"));
EstrOut += Result;
Result.Format(_T("\t%d\t\t"), tag);
EstrOut += Result;
Result.Format(_T("%s\t"), _T("次"));
EstrOut += Result;
for (int i = 0; i < 10; i++)
{
Result.Format(_T("%s\t"), _T("<<<"));
EstrOut += Result;
}
Result.Format(_T("\n"));
EstrOut += Result;
//输出
LinetoCString(_T("B矩阵"), strOut,EstrOut);
MatrixtoCstring(B, Result, strOut,EstrOut);
LinetoCString(_T("P矩阵"), strOut, EstrOut);
MatrixtoCstring(P, Result, strOut, EstrOut);
LinetoCString(_T("NBB矩阵"), strOut, EstrOut);
MatrixtoCstring(Nbb, Result, strOut, EstrOut);
LinetoCString(_T("x矩阵"), strOut, EstrOut);
MatrixtoCstring(x, Result, strOut, EstrOut);
LinetoCString(_T("F矩阵"), strOut, EstrOut);
MatrixtoCstring(F, Result, strOut, EstrOut);
LinetoCString(_T("v矩阵"), strOut, EstrOut);
MatrixtoCstring(v, Result, strOut, EstrOut);
} while (tag<10);
Adjustment_accuracy();
}
//***********************************
//精度评定
//***********************************
void Do::Adjustment_accuracy()//精度评定
{
Qxx = Nbb.inverse();
double dVzero = 0;
for (int i = 0; i < iSum_Angle_obs; i++)
{
if (Angle_obs[i].ObsAngel(DEG) < 1e-6)
{
dVzero = v(i, 0);
}
v(i, 0) -= dVzero;
}
MatrixXd r;
r = v.transpose()*P*v;//VT*P*V 单位权中误差
r0 = sqrt(r(0, 0) / (iSum_Angle_obs + iSum_Dist_obs - 2 * iSum_up - iAngle_Station));//中误差计算
//全方位元素评定
for (int i = 0; i < iSum_up; i++)
{
//Q矩阵元素抠出
double temp_Qx = Qxx(2 * i, 2 * i);
double temp_Qy = Qxx(2 * i + 1, 2 * i + 1);
double temp_Qxy = Qxx(2 * i, 2 * i + 1);
//计算点位误差
up[i].dmx = r0 * sqrt(Qxx(2 * i, 2 * i));
up[i].dmy = r0 * sqrt(Qxx(2 * i + 1, 2 * i + 1));
up[i].dmk = sqrt(up[i].dmx*up[i].dmx + up[i].dmy*up[i].dmy);
//计算误差椭圆相应参数
double temp_K = sqrt((temp_Qx - temp_Qy)*(temp_Qx - temp_Qy) + 4 * temp_Qxy*temp_Qxy);
double temp_dQe = 0.5*(temp_Qx + temp_Qy + temp_K);
double temp_dQf = 0.5*(temp_Qx + temp_Qy - temp_K);
up[i].dE = r0 * sqrt(temp_dQe);
up[i].dF = r0 * sqrt(temp_dQf);
up[i].dQ = atan((temp_dQe - temp_Qx) / temp_Qxy);
up[i].dQ = up[i].dQ > 0 ? up[i].dQ : up[i].dQ + 2 * PI;//存储为弧度制
}
}
//***********************************
//输出函数
//***********************************
void Do::out()
{
//初始化
LinetoCString(_T("----------------------------原始数据----------------------------"), strOut,EstrOut);
LinetoCString(_T("已知点ID\tX\tY"), strOut,EstrOut);
//输出已知点
for (int i = 0; i < iSum_cp; i++)
{
Result.Format(_T("%s\t%.4f\t%.4f\r\n"), cp[i].strID, cp[i].dx, cp[i].dy);
strOut += Result;
}
Result.Format(_T("%s\t%s%f\r\n"), _T("角度观测值误差(s):"), _T("±"), alfa_wrong);
strOut += Result;
Result.Format(_T("%s\t%s%f\r\n"), _T("边长观测值误差(m):"), _T("±"), length_wrong);
strOut += Result;
for (int i = 0; i < iSum_cp; i++)
{
Result.Format(_T("%s\t%.4f\t%.4f\n"), cp[i].strID, cp[i].dx, cp[i].dy);
EstrOut += Result;
}
Result.Format(_T("%s\t%s%f\n"), _T("角度观测值误差(s):"), _T("±"),alfa_wrong);
EstrOut += Result;
Result.Format(_T("%s\t%s%f\n"), _T("边长观测值误差(m):"), _T("±"), length_wrong);
EstrOut += Result;
//精度评定环节
//方向观测
LinetoCString(_T("----------------------------方向观测成果表----------------------------"), strOut, EstrOut);
LinetoCString(_T("测站\t找准\t方向值(dms)\t改正数(s)\t改正后的值\t"), strOut, EstrOut);
for (int i = 0; i < iSum_Angle_obs; i++)
{
Result.Format(_T("%s\t%s\t%.6f\t%.6f\t%.6f\r\n"),
Angle_obs[i].pStation->strID,
Angle_obs[i].pEnd->strID,
Angle_obs[i].ObsAngel(DMS),
v(i, 0),
Angle_obs[i].ObsAngel(DMS) + v(i, 0) / 1000
);
strOut += Result;
}
for (int i = 0; i < iSum_Angle_obs; i++)
{
Result.Format(_T("%s\t%s\t%.6f\t%.6f\t%.6f\n"),
Angle_obs[i].pStation->strID,
Angle_obs[i].pEnd->strID,
Angle_obs[i].ObsAngel(DMS),
v(i, 0),
Angle_obs[i].ObsAngel(DMS) + v(i, 0) / 1000
);
EstrOut += Result;
}
LinetoCString(_T("----------------------------距离观测成果表----------------------------"), strOut,EstrOut);
LinetoCString(_T("测站\t照准\t距离观测值(m)\t改正数(m)\t平差后值(m)\t方位角(dms)"), strOut, EstrOut);
for (int i = 0; i < iSum_Dist_obs; i++)
{
Result.Format(_T("%s\t%s\t%.4f\t%.4f\t%.4f\t%.6f\r\n"),
Dist_obs[i].pFront_id->strID,
Dist_obs[i].pBack_id->strID,
Dist_obs[i].dFB_dist,
v(i+ iSum_Angle_obs, 0)/1000,
Dist_obs[i].dFB_dist + v(i + iSum_Angle_obs, 0) / 1000,
Angle(Process_Rad(Dist_obs[i].pFront_id->dx, Dist_obs[i].pFront_id->dy, Dist_obs[i].pBack_id->dx, Dist_obs[i].pBack_id->dy), RAD)(DMS)
);
strOut += Result;
}
for (int i = 0; i < iSum_Dist_obs; i++)
{
Result.Format(_T("%s\t%s\t%.4f\t%.4f\t%.4f\t%.6f\n"),
Dist_obs[i].pFront_id->strID,
Dist_obs[i].pBack_id->strID,
Dist_obs[i].dFB_dist,
v(i + iSum_Angle_obs, 0) / 1000,
Dist_obs[i].dFB_dist + v(i + iSum_Angle_obs, 0) / 1000,
Angle(Process_Rad(Dist_obs[i].pFront_id->dx, Dist_obs[i].pFront_id->dy, Dist_obs[i].pBack_id->dx, Dist_obs[i].pBack_id->dy), RAD)(DMS)
);
EstrOut += Result;
}
LinetoCString(_T("----------------------------平面点位误差表----------------------------"), strOut, EstrOut);
LinetoCString(_T("点名\t长轴(m)\t短轴(m)\t长轴方位(dms)\t点位中误差(m)"), strOut, EstrOut);
for (int i = 0; i < iSum_up; i++)
{
Result.Format(_T("%s\t%.4f\t%.4f\t%.6f%s%.6f\t%.4f\r\n"), up[i].strID, up[i].dE*2/1000, up[i].dF * 2/1000, Angle(up[i].dQ, RAD)(DMS),_T("或"), Angle(up[i].dQ, RAD)(DMS) >180? Angle(up[i].dQ, RAD)(DMS) -180: Angle(up[i].dQ, RAD)(DMS)+180,up[i].dmk/1000);
strOut += Result;
}
for (int i = 0; i < iSum_up; i++)
{
Result.Format(_T("%s\t%.4f\t%.4f\t%.6f%s%.6f\t%.4f\n"), up[i].strID, up[i].dE * 2 / 1000, up[i].dF * 2 / 1000, Angle(up[i].dQ, RAD)(DMS), _T("或"), Angle(up[i].dQ, RAD)(DMS) > 180 ? Angle(up[i].dQ, RAD)(DMS) - 180 : Angle(up[i].dQ, RAD)(DMS) + 180, up[i].dmk / 1000);
EstrOut += Result;
}
//输出控制点成果
LinetoCString(_T("-----------------------------控制点成果表-----------------------------"), strOut,EstrOut);
LinetoCString(_T("点名\tX(m)\tY(m)"), strOut, EstrOut);
for (int i = 0; i < iSum_cp; i++)
{
Result.Format(_T("%s\t%.4f\t%.4f\r\n"), cp[i].strID, cp[i].dx, cp[i].dy);
strOut += Result;
}
for (int i = 0; i < iSum_up; i++)
{
Result.Format(_T("%s\t%.4f\t%.4f\r\n"), up[i].strID, up[i].dx, up[i].dy);
strOut += Result;
}
for (int i = 0; i < iSum_cp; i++)
{
Result.Format(_T("%s\t%.4f\t%.4f\n"), cp[i].strID, cp[i].dx, cp[i].dy);
EstrOut += Result;
}
for (int i = 0; i < iSum_up; i++)
{
Result.Format(_T("%s\t%.4f\t%.4f\n"), up[i].strID, up[i].dx, up[i].dy);
EstrOut += Result;
}
//----------
//输出B矩阵
LinetoCString(_T("-----------------------------最后迭代 平差过程-----------------------------"), strOut, EstrOut);
LinetoCString(_T("B矩阵"), strOut, EstrOut);
MatrixtoCstring(B, Result, strOut, EstrOut);
//输出P矩阵
LinetoCString(_T("P矩阵"), strOut, EstrOut);
MatrixtoCstring(P, Result, strOut, EstrOut);
//输出F矩阵
LinetoCString(_T("F矩阵"), strOut, EstrOut);
MatrixtoCstring(F, Result, strOut, EstrOut);
//输出v矩阵
LinetoCString(_T("v矩阵"), strOut, EstrOut);
MatrixtoCstring(v, Result, strOut, EstrOut);
//输出Qxx矩阵
LinetoCString(_T("Qxx矩阵"), strOut, EstrOut);
MatrixtoCstring(Qxx, Result, strOut, EstrOut);
AfxMessageBox(_T("数据已成功录入!"));
}
//***********************************
//求最大最小值
//***********************************
double Do::Min1_max2_x(Data_P *cp, int iSum_cp, int tag)//
{
double temp=cp[0].dx;
if (tag == 2)//返回最大值
{
for (int i = 0; i < iSum_cp-1; i++)
{
if (cp[i + 1].dx > temp)
{
temp = cp[i + 1].dx;
}
}
}
else if (tag == 1)//返回最小值
{
for (int i = 0; i < iSum_cp - 1; i++)
{
if (cp[i + 1].dx < temp)
{
temp = cp[i + 1].dx;
}
}
}
return temp;
}
//***********************************
//求最大最小值
//***********************************
double Do::Min1_max2_y(Data_P *cp, int iSum_cp, int tag)//
{
double temp = cp[0].dy;
if (tag == 2)//返回最大值
{
for (int i = 0; i < iSum_cp - 1; i++)
{
if (cp[i + 1].dy > temp)
{
temp = cp[i + 1].dy;
}
}
}
else if (tag == 1)
{
for (int i = 0; i < iSum_cp - 1; i++)
{
if (cp[i + 1].dy < temp)
{
temp = cp[i + 1].dy;
}
}
}
return temp;
}
//***********************************
//画三角形
//***********************************
void Do::Draw_tri(CDC* pDC,double x, double y,double length,double a)
{
double l = length / sqrt(3)*0.5*a;
CPen pen;
pen.CreatePen(PS_SOLID, 1.8, RGB(123, 25, 123));//实线画笔
CPen *pOldPen;
pOldPen = pDC->SelectObject(&pen);
pDC->MoveTo(x - sqrt(3)*l, y + l);
pDC->LineTo(x + sqrt(3)*l, y + l);
pDC->LineTo(x , y - 2*l);
pDC->LineTo(x - sqrt(3)*l, y + l);
}
//***********************************
//旋转 平移
//***********************************
void Do::Draw_ro(double &x, double &y, double alfa,CRect &rect,double dx,double dy,double ro1,double ro2)
{
x = x - (rect.bottom - rect.top) / 2;
y = y - (rect.right - rect.left) / 2;
MatrixXd Mpoint(3, 1);
Mpoint << x,
y,
1;
MatrixXd Mro(3, 3);//旋转矩阵
Mro << cos(alfa), -sin(alfa), 0,
sin(alfa), cos(alfa), 0,
0, 0, 1;
MatrixXd Mro1(3, 3);//平移矩阵
Mro1 <<1, 0, dx,
0, 1,dy ,
0, 0, 1.000;
MatrixXd Mro2(3, 3);//绕纵、横轴旋转矩阵
Mro2 << 1,ro2, 0,
ro1, 1, 0,
0, 0, 1.000;
MatrixXd Mro3(3, 3);//绕纵、横轴旋转矩阵
Mro3 << 1, 0, 0,
0, 1, 0,
0, 0, 1.000;
Mpoint = Mro3* Mro2*Mro1*Mro * Mpoint;
x = Mpoint(0, 0) + (rect.bottom - rect.top) / 2;
y= Mpoint(1, 0) + (rect.right - rect.left) / 2;
}
//***********************************
//画图函数
//***********************************
void Do::draw(CDC* pDC, CRect rect, double coefficient, double alfa, double dx, double dy, double ro1, double ro2)//画图
{
alfa = alfa * PI / 180;//对输入角度转换
CPen pen;//定义画笔
pen.CreatePen(PS_SOLID, 3, RGB(255, 255, 255));//实线画笔 白色的
CPen *pOldPen;//定义一个画笔来接收
pOldPen = pDC->SelectObject(&pen);
int zero_x1 = 0;//矩形框的左上角元素x 计算机坐标系
int zero_y1 = 0;//矩形框的左上角元素y
int zero_x2 = rect.Width() - 25;//矩形框的右下角元素x
int zero_y2 = rect.Height()-138; //矩形框的右下角元素y
//鲁棒性检查
if (cp == NULL) { AfxMessageBox(_T("您未输入数据!")); }
else {
pDC->Rectangle(zero_x1, zero_y1, zero_x2, zero_y2);
CPen pen;
pen.CreatePen(PS_DASHDOT, 1, RGB(0, 0, 0));//实线画笔
CPen *pOldPen;
pOldPen = pDC->SelectObject(&pen);
//double coefficient = 0.2;//缩放系数为0.8
double axis_y = coefficient * (zero_x2 - zero_x1);//y坐标轴长度
double axis_x = coefficient * (zero_y2 - zero_y1);//x坐标轴长度
double Xmin, Xmax; double Ymin, Ymax;
//判断X最小值 Y最大值
Xmin = (Min1_max2_x(cp, iSum_cp, 1) > Min1_max2_x(up, iSum_up, 1)) ? Min1_max2_x(up, iSum_up, 1) : Min1_max2_x(cp, iSum_cp, 1);
Ymin = (Min1_max2_y(cp, iSum_cp, 1) > Min1_max2_y(up, iSum_up, 1)) ? Min1_max2_y(up, iSum_up, 1) : Min1_max2_y(cp, iSum_cp, 1);
Xmax = (Min1_max2_x(cp, iSum_cp, 2) < Min1_max2_x(up, iSum_up, 2)) ? Min1_max2_x(up, iSum_up, 2) : Min1_max2_x(cp, iSum_cp, 2);
Ymax = (Min1_max2_y(cp, iSum_cp, 2) < Min1_max2_y(up, iSum_up, 2)) ? Min1_max2_y(up, iSum_up, 2) : Min1_max2_y(cp, iSum_cp, 2);
double x0 = zero_y2 - (1 - coefficient)*0.5*(zero_y2 - zero_y1)-dx;
double y0 = zero_x1 + (1 - coefficient)*0.6*(zero_x2 - zero_x1)+25;//起始坐标 原点
//double y0 = zero_x1 + (1 - coefficient)*0.5*(Ymax - Ymin);//起始坐标 原点
CString str;//原点
str.Format(_T("%.f %.f"), Xmin - 75, Ymin);
double temp_01 = y0 - 75;
double temp_02 = x0 + 20;
Draw_ro(temp_01, temp_02, alfa, rect, dx, dy, ro1, ro2);
pDC->TextOut(temp_01, temp_02, str);
double coefficient2 = ((Xmax - Xmin) > (Ymax - Ymin)) ? ((Xmax - Xmin) / axis_x) : ((Ymax - Ymin) / axis_y);//这次是实际坐标投影至图中的系数
//绘制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*coefficient)*(zero_y2 - zero_y1);
double temp_y003 = x0 - (0.25 + 0.75*coefficient)*(zero_y2 - zero_y1);
double temp_y004 = x0 - (0.25 + 0.75*coefficient)*(zero_y2 - zero_y1) + 7;
double temp_y005 = x0 - (0.25 + 0.75*coefficient)*(zero_y2 - zero_y1);
double temp_y006 = x0 - (0.25 + 0.75*coefficient)*(zero_y2 - zero_y1) + 7;
double temp_y007 = x0 - (0.25 + 0.75*coefficient)*(zero_y2 - zero_y1) - 20;
Draw_ro(temp_x001, temp_y001, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x002, temp_y002, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x003, temp_y003, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x004, temp_y004, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x005, temp_y005, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x006, temp_y006, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x007, temp_y007, alfa, rect, dx, dy, ro1, ro2);
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*coefficient)*(zero_x2 - zero_x1);
temp_x003 = y0 + (0.25 + 0.75*coefficient)*(zero_x2 - zero_x1);
temp_x004 = y0 + (0.25 + 0.75*coefficient)*(zero_x2 - zero_x1) - 7;
temp_x005 = y0 + (0.25 + 0.75*coefficient)*(zero_x2 - zero_x1);
temp_x006 = y0 + (0.25 + 0.75*coefficient)*(zero_x2 - zero_x1) - 7;
temp_x007 = y0 + (0.25 + 0.75*coefficient)*(zero_x2 - zero_x1);
temp_y001 = x0;
temp_y002 = x0;
temp_y003 = x0;
temp_y004 = x0 - 7;
temp_y005 = x0;
temp_y006 = x0 + 7;
temp_y007 = x0 + 5;
Draw_ro(temp_x001, temp_y001, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x002, temp_y002, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x003, temp_y003, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x004, temp_y004, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x005, temp_y005, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x006, temp_y006, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x007, temp_y007, alfa, rect, dx, dy, ro1, ro2);
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 = axis_x / 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 + axis_y;
double t_y2 = x0 - temp_x;
Draw_ro(t_x, t_y, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(t_x2, t_y2, alfa, rect, dx, dy, ro1, ro2);
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;
Draw_ro(t_x3, t_y3, alfa, rect, dx, dy, ro1, ro2);
pDC->TextOut(t_x3, t_y3, str);
temp_x += temp_tag_x;
}
//画平行X轴的刻度
int tag_y = 5;//5条线
double temp_tag_y = axis_y / 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 - axis_y;
Draw_ro(t_x, t_y, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(t_x2, t_y2, alfa, rect, dx, dy, ro1, ro2);
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 + 20;
Draw_ro(t_x3, t_y3, alfa, rect, dx, dy, ro1, ro2);
pDC->TextOut(t_x3, t_y3, str);
temp_y += temp_tag_y;
}
//画方向观测值之间的线段
for (int i = 0; i < iSum_Angle_obs; i++)
{
//srand((unsigned)time(NULL));
CPen pen;
pen.CreatePen(PS_SOLID, 0.8, RGB(255, 0, 0));//实线画笔
CPen *pOldPen;
pOldPen = pDC->SelectObject(&pen);
double t_x = (Angle_obs[i].pStation->dy - Ymin) / coefficient2 + y0;
double t_y = x0 - (Angle_obs[i].pStation->dx - Xmin) / coefficient2;
double t_x2 = (Angle_obs[i].pEnd->dy - Ymin) / coefficient2 + y0;
double t_y2 = x0 - (Angle_obs[i].pEnd->dx - Xmin) / coefficient2;
Draw_ro(t_x, t_y, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(t_x2, t_y2, alfa, rect, dx, dy, ro1, ro2);
pDC->MoveTo(t_x, t_y);
pDC->LineTo(t_x2, t_y2);
pen.DeleteObject();
}
//画未知点之间的线段
for (int i = 0; i < iSum_Dist_obs; i++)
{
//srand((unsigned)time(NULL));
int a = (rand() % 200);
int b = (rand() % 200 + 99);
int c = (rand() % 200) - 50;
if (a > 100 || a < 0)
{
a = 255;
}
if (b > 255 || b < 0)
{
b = 88;
}
if (c > 255 || c < 0)
{
c = 188;
}
CPen pen;
pen.CreatePen(PS_DASHDOT, 2, RGB(a, b, c));//实线画笔
CPen *pOldPen;
pOldPen = pDC->SelectObject(&pen);
double t_x = (Dist_obs[i].pFront_id->dy - Ymin) / coefficient2 + y0;
double t_y = x0 - (Dist_obs[i].pFront_id->dx - Xmin) / coefficient2;
double t_x2 = (Dist_obs[i].pBack_id->dy - Ymin) / coefficient2 + y0;
double t_y2 = x0 - (Dist_obs[i].pBack_id->dx - Xmin) / coefficient2;
Draw_ro(t_x, t_y, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(t_x2, t_y2, alfa, rect, dx, dy, ro1, ro2);
pDC->MoveTo(t_x, t_y);
pDC->LineTo(t_x2, t_y2);
pen.DeleteObject();//释放资源
}
//画已知点之间的线段
for (int i = 0; i < iSum_cp - 1; i++)
{
//srand((unsigned)time(NULL));
int a = (rand() % 200);
int b = (rand() % 200 + 99);
int c = (rand() % 200) - 50;
if (a > 100 || a < 0)
{
a = 255;
}
if (b > 255 || b < 0)
{
b = 88;
}
if (c > 255 || c < 0)
{
c = 188;
}
CPen pen;
pen.CreatePen(PS_SOLID, 1, RGB(a, b, c));//实线画笔
CPen *pOldPen;
pOldPen = pDC->SelectObject(&pen);
double t_x = (cp[i].dy - Ymin) / coefficient2 + y0;
double t_y = x0 - (cp[i].dx - Xmin) / coefficient2;
double t_x2 = (cp[i + 1].dy - Ymin) / coefficient2 + y0;
double t_y2 = x0 - (cp[i + 1].dx - Xmin) / coefficient2;
double t_x_ = (cp[i].dy - Ymin) / coefficient2 + y0 + 3;
double t_y_ = x0 - (cp[i].dx - Xmin) / coefficient2 + 3;
double t_x2_ = (cp[i + 1].dy - Ymin) / coefficient2 + y0 + 3;
double t_y2_ = x0 - (cp[i + 1].dx - Xmin) / coefficient2 + 3;
Draw_ro(t_x, t_y, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(t_x2, t_y2, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(t_x_, t_y_, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(t_x2_, t_y2_, alfa, rect, dx, dy, ro1, ro2);
pDC->MoveTo(t_x, t_y);
pDC->LineTo(t_x2, t_y2);
pDC->MoveTo(t_x_, t_y_);
pDC->LineTo(t_x2_, t_y2_);
pen.DeleteObject();
}
double coefficient3 = (0.8 / coefficient) *(up[0].dE) / 20;//比例系数
for (int i = 0; i < iSum_up; i++)
{
int a = (rand() % 200);
int b = (rand() % 200 + 99);
int d = (rand() % 200) - 50;
if (a > 100 || a < 0)
{
a = 255;
}
if (b > 255 || b < 0)
{
b = 88;
}
if (d > 255 || d < 0)
{
d = 188;
}
CPen pen;
pen.CreatePen(PS_SOLID, 1.8, RGB(a, b, d));//实线画笔
CPen *pOldPen;
pOldPen = pDC->SelectObject(&pen);
for (int j = 0; j < 120; j += 3)
{
//画椭圆
double dAlf = j * 2 * PI / 120;
double xae, ybf;
double c = 0;
double tralatazi;
xae = up[i].dE / coefficient3 * cos(dAlf);
ybf = up[i].dF / coefficient3 * sin(dAlf);
tralatazi = up[i].dQ+PI/2;
//tralatazi = up[i].dQ ;
double temp_1 = xae * cos(tralatazi) + ybf * sin(tralatazi) + (up[i].dy - Ymin) / coefficient2 + y0;
double temp_2 = -ybf * cos(tralatazi) + xae * sin(tralatazi) + x0 - (up[i].dx - Xmin) / coefficient2;
Draw_ro(temp_1, temp_2, alfa, rect, dx, dy, ro1, ro2);
if (j == 0) { pDC->MoveTo(temp_1, temp_2); }
pDC->LineTo(temp_1, temp_2);
}
double temp1 = (up[i].dy - Ymin) / coefficient2 + y0 + (up[i].dF*sin(up[i].dQ+PI/2)) / coefficient3;//长轴右上角 x
double temp2 = x0 - (up[i].dx - Xmin) / coefficient2 - (up[i].dF*cos(up[i].dQ+PI/2)) / coefficient3;//长轴右上角 y
double temp3 = (up[i].dy - Ymin) / coefficient2 + y0 - (up[i].dF*sin(up[i].dQ+PI/2) )/ coefficient3;//长轴左下角 x
double temp4 = x0 - (up[i].dx - Xmin) / coefficient2 + (up[i].dF*cos(up[i].dQ+PI/2) )/ coefficient3;//长轴左下角 y
Draw_ro(temp1, temp2, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp3, temp4, alfa, rect, dx, dy, ro1, ro2);
pDC->MoveTo(temp1, temp2);
pDC->LineTo(temp3, temp4);
pen.DeleteObject();
double _temp1 = (up[i].dy - Ymin) / coefficient2 + y0 + (up[i].dE*cos(up[i].dQ + PI / 2)) / coefficient3;//短轴右下角 x
double _temp2 = x0 - (up[i].dx - Xmin) / coefficient2 + (up[i].dE*sin(up[i].dQ + PI / 2)) / coefficient3;//短轴右上角 y
double _temp3 = (up[i].dy - Ymin) / coefficient2 + y0 - (up[i].dE*cos(up[i].dQ + PI / 2)) / coefficient3;//短轴左上角 x
double _temp4 = x0 - (up[i].dx - Xmin) / coefficient2 - (up[i].dE*sin(up[i].dQ + PI / 2)) / coefficient3;//短轴左上角 y
Draw_ro(_temp1, _temp2, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(_temp3, _temp4, alfa, rect, dx, dy, ro1, ro2);
pDC->MoveTo(_temp1, _temp2);
pDC->LineTo(_temp3, _temp4);
}
//画ID
for (int i = 0; i < iSum_up; i++)
{
CString str;
str.Format(_T("%s"), up[i].strID);
double temp_1 = (up[i].dy - Ymin) / coefficient2 + y0;
double temp_2 = x0 - (up[i].dx - Xmin) / coefficient2;
Draw_ro(temp_1, temp_2, alfa, rect, dx, dy, ro1, ro2);
pDC->TextOut(temp_1, temp_2, str);
}
for (int i = 0; i < iSum_cp; i++)
{
CString str;
str.Format(_T("%s"), cp[i].strID);
double temp_1 = (cp[i].dy - Ymin) / coefficient2 + y0;
double temp_2 = x0 - (cp[i].dx - Xmin) / coefficient2;
Draw_ro(temp_1, temp_2, alfa, rect, dx, dy, ro1, ro2);
Draw_tri(pDC, temp_1, temp_2, 50, coefficient / 0.8);
pDC->TextOut(temp_1, temp_2, str);
}
//画比例尺
double ruler = axis_y * 500 / (Ymax - Ymin);//图上长度代表实际500M
temp_x001 = (zero_x1 + zero_x2) / 2 - ruler / 2;
temp_x002 = (zero_x1 + zero_x2) / 2 - ruler / 2;
temp_x003 = (zero_x1 + zero_x2) / 2 + ruler / 2;
temp_x004 = (zero_x1 + zero_x2) / 2 + ruler / 2;
temp_x005 = (zero_x1 + zero_x2) / 2;
temp_y001 = 20;
temp_y002 = 23;
temp_y003 = 23;
temp_y004 = 20;
temp_y005 = 26;
Draw_ro(temp_x001, temp_y001, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x002, temp_y002, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x003, temp_y003, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x004, temp_y004, alfa, rect, dx, dy, ro1, ro2);
Draw_ro(temp_x005, temp_y005, alfa, rect, dx, dy, ro1, ro2);
pDC->MoveTo(temp_x001, temp_y001);
pDC->LineTo(temp_x002, temp_y002);
pDC->LineTo(temp_x003, temp_y003);
pDC->LineTo(temp_x004, temp_y004);
pDC->TextOut(temp_x005, temp_y005, _T("1:500"));
}
}
//***********************************
//导出数据到excel中
//***********************************
void Do::ReportExcel()
{
if (strOut == _T("")) { AfxMessageBox(_T("请先输入数据!")); }
else {
CString strPath;
CFileDialog dlg(false, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("Excel Files(*.xls)|*.xls|All Files(*.*)|*.*|"), AfxGetMainWnd());
if (dlg.DoModal() == IDCANCEL) return;
else
{
strPath = dlg.GetPathName();
if (strPath.Find(_T(".xls")) < 0)
{
strPath += _T(".xls");
}
}
TRY
{
CString cs;
CStdioFile file(strPath, CFile::shareExclusive | CFile::modeWrite | CFile::modeCreate);
setlocale(LC_CTYPE, ("chs")); //设置中文输出
file.WriteString(EstrOut);
file.Close();
CString temp;
temp.Format(_T("%s%s"), _T("已导出至"),strPath);
AfxMessageBox(temp);
}
CATCH_ALL(e)
{
e->ReportError();
return;
}
END_CATCH_ALL
}
}
//***********************************
//导出数据到txt dat中
//***********************************
void Do::Reporttxt()
{
if (EstrOut == _T("")) { AfxMessageBox(_T("请先输入数据!")); }
else {
CFileDialog dlg(false, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("Txt Files(*.txt)|*.txt|All Files(*.*)|*.*|"), AfxGetMainWnd());
CString strPath;
if (dlg.DoModal() == IDCANCEL) return;
else
{
strPath = dlg.GetPathName();
if (strPath.Find(_T(".txt")) < 0)
{
if (strPath.Find(_T(".dat")) < 0)
{
strPath += _T(".txt");//默认储存为txt模式
}
}
}
TRY
{
CString cs;
CStdioFile file(strPath, CFile::shareExclusive | CFile::modeWrite | CFile::modeCreate);
setlocale(LC_CTYPE, ("chs")); //设置中文输出
file.WriteString(strOut);
file.Close();
CString temp;
temp.Format(_T("%s%s"), _T("已导出至"),strPath);
AfxMessageBox(temp);
}
CATCH_ALL(e)
{
e->ReportError();
return;
}
END_CATCH_ALL
}
}
//对话框所在类
#include "stdafx.h"
#include "Traverse_network_10_zrx.h"
#include "Traverse_network_10_zrxDlg.h"
#include "afxdialogex.h"
#include "do.h"
#include"DrawEx.h"
#include"DrawSup.h"
#include "Helpyou.h"
//…
Do k;//在.h文件中
int tag=0;
//按钮 导入数据 ( txt或dat)
void CTraversenetwork10zrxDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
//CDialogEx::OnOK();
UpdateData(TRUE);
out = ":)";
k.strOut=":)";
tag = k.read();
if ( tag== 1)
{
k.estimate();
k.adjustment_main();
k.out();
out = k.strOut;
}
UpdateData(FALSE);
}
//按钮 退出
void CTraversenetwork10zrxDlg::OnBnClickedCancel()
{
// TODO: 在此添加控件通知处理程序代码
CDialogEx::OnCancel();
}
//按钮 画图
void CTraversenetwork10zrxDlg::OnBnClickedButton1draw()
{
// TODO: 在此添加控件通知处理程序代码
if (tag == 1)
{
DrawEx dui;
dui.d = k;
dui.DoModal();
}
else AfxMessageBox(_T("请输入数据"));
}
//按钮 帮助
void CTraversenetwork10zrxDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
Helpyou h;
h.DoModal();
}
//按钮 导出 txt 或 dat
void CTraversenetwork10zrxDlg::OnBnClickedButton3()//输出至txt
{
// TODO: 在此添加控件通知处理程序代码
if (tag == 1)
{
k.Reporttxt();
}
else AfxMessageBox(_T("请输入数据"));
}
//按钮 导出excel
void CTraversenetwork10zrxDlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
if (tag == 1)
{
k.ReportExcel();
}
else AfxMessageBox(_T("请输入数据"));
}
void CTraversenetwork10zrxDlg::OnBnClickedButton5()
{
// TODO: 在此添加控件通知处理程序代码
if (tag == 1)
{
DrawSup dui;
dui.d = k;
dui.DoModal();
}
else AfxMessageBox(_T("请输入数据"));
}
//对话框所在类
#pragma once
#include"Do.h"
// DrawEx 对话框
class DrawEx : public CDialogEx
{
DECLARE_DYNAMIC(DrawEx)
public:
DrawEx(CWnd* pParent = nullptr); // 标准构造函数
virtual ~DrawEx();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_DrawEx };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedOk();
public:
Do d;
double coefficient;
double alfa;
double dx;
double dy;
double roi1;
double roi2;
double tag1;
afx_msg void OnBnClickedOk2();
afx_msg void OnSize(UINT nType, int cx, int cy);
};
#include "stdafx.h"
#include "Traverse_network_10_zrx.h"
#include "DrawEx.h"
#include "afxdialogex.h"
//按钮 二维画图
void DrawEx::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
//CDialogEx::OnOK();
UpdateData(TRUE);
CDC* pDC = GetDlgItem(IDC_STATIC)->GetDC();
GetDlgItem(IDC_STATIC)->UpdateWindow();
CRect rc;
GetDlgItem(IDC_STATIC)->GetWindowRect(&rc);
GetWindowRect(&rc);
if (tag1 != 0) { AfxMessageBox(_T(错误")); }
d.draw(pDC, rc, coefficient, alfa,-dx,-dy,roi1,roi2);
UpdateData(FALSE);
}
//按钮 三维画图
void DrawEx::OnBnClickedOk2()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
CDC* pDC = GetDlgItem(IDC_STATIC)->GetDC();
GetDlgItem(IDC_STATIC)->UpdateWindow();
CRect rc;
GetDlgItem(IDC_STATIC)->GetWindowRect(&rc);
GetWindowRect(&rc);
d.draw(pDC, rc, coefficient-0.35, alfa-15,-dx+200, -(dy-200), roi1+0.1, roi2+0.8);
UpdateData(FALSE);
}
5.11 控件ID及其属性
暂且让我以每天记日记的方法写下自己的设计心程。我希望这些能够帮助处理某些过程遇到的bug,怎样克服。当然能不看就不看,干就完了。
2019年中旬进行,2020年1月整理上传。
这天是听报告、做计划的一天,是较为轻松的一天。
这次的报告比较的大的收获之一就是,解决了上次考试的指针的使用(float swap(float *a, float &b),为下文站点匹配做出铺垫。
按照我昨天计划的内容,4天是能做完的。我还是比较自信自己的C++基础,于是在早上我便兴致冲冲地做了起来。
关于对话框的选择。上来要做的便是确认下对话框形式还是文档形式。这点自己还是犹豫了下,尽管在后来我做完这一切想起文档形式或许更加地直观。问了旁边的其他人,都还没定,我还是选择了经验比较多的对话框形式,事实证明这是一条群众路线,我没遇到用对话框做的人。
关于类的设计。类设计得不好,越做越难受。我参照了下以前水准网的实验,但我当时用的是ID匹配,需要加自定义的remove()函数,因为自身的读出来的整个CString字符会读入换行符。所以这次我决定使用指针。
在晚上,我初步解决了数据的读入,因为读入即需要判断指针,这相当与要将搜索函数等辅助函数写出。
同时,我选择了边读入边输出的模式,即同时将结输出至txt中,方便我查看每一步过程的bug。我选择将数据的地址返回,同一测站的地址都是一样,数据正确。
这一天,我心里很踏实的,因为已经超过了大多数同学的进度。
我开始写概算函数。选择了《测绘程序设计基础》书上末的那段概算函数为实例。但这上午只有最后20分钟我才开始催自己写这些函数。这里,说下自己的一点感想。我远没有达到能够自己编算法的高度,只是算法的搬运工。但是要想做算法的搬运工,前提是要能理解这段代码的思想,才能驾驭这段代码为己所用。读懂代码的意思比较难,我花了一上午的时间来读懂了书中的概算的思想,我脑子才比较放心这段代码可以移入。
中午回到宿舍,我趁着上午的热度,一鼓作气将代码写出,当时才1点多。
然后我更改了输出至txt的格式。同时开始思考接下来的平差。
但是还是有点错误,晚上11点多的时候发现是一个指针未指向导致的。一个bug还是可以接受的。
这天的早上,我检查了下无bug,可以进行下一步平差内容了。
有了前一天的经验,我就照葫芦画瓢,要想写出平差内容,脑子里要先有个框架。
这里说下我对平差中碰的比较大的一个困难是,B矩阵的理解。因为进度比较快,附近并没找到理解B矩阵的同学。作为第一个吃螃蟹的人,上面的B矩阵是我花了大量时间才懂了的,印象极其深刻。关于B矩阵右上角的iStation部分,我当时怎么也想不出来是应该赋值多少,花了好长时间才想明白,明白的同时,也对平差内容更加深刻了。
然后花了一下午BFP函数写出,解决了部分bug,程序能够正常运行。
这天问了老师的潘老师的改正数迭代问题,由于采取的是方向值,改正数V只需改正前 位置坐标*2 的个数。
精度平定参照平差的书中部分,使用K的方法做出。
下午两点左右,我将所有部分都完整txt输出了,当然这是对较少数据的示例数据,其中还有若干bug几天后才发现。这一刻是比较兴奋的。
这天晚上,我开始着手画图的,在CSDN上搜索了一整个晚上,最后只会在主对话框画图,略微失望。
我自己开始一步步地检索自己的bug,尽管找到了些,但对最大那份数据仍不成立。我甚至开始怀疑最大那份数据有问题,为此花了不少时间,将里面的点用展开。
下午,在解决自己最后的程序bug同时,在帮助同学解决bug。相当于过了好几遍,我也更加熟悉概算的思想。这同时我也在对照自己的程序。
今天极其令人兴奋的一天。
同学做到平差的部分了,当然也出现了bug。万万没想到,找同学的bug同时解决了我的bug!B、P、F矩阵一一对照,尽管同学的bug是别的地方出错,我竟然发现是BF_angle_f(Data_Obsangle Angle_ob,double &f)中给F赋值时应该转成206265应该是弧度制206265,我竟然是DEG206265!
当时我在边躺床上边想,突然脑子里晃到这一处赋值代码我们不同,尽管同学的代码是别处的bug。我立马手机百度确认了下。跳下床来,换了6个字母。那份的较多数据的成了!画图结果也成功运行!
这天算是解决了所有的大bug了。
上午图书馆,下午4**。
整整一天,我开始进行界面优化、txt格式、绘画优化。同时进行了鲁棒性检查。
上午图书馆,下午4**。初步写了实验报告。
增加了excel形式。自定义了几个输出函数,excel中输出关键:\t是空一格 \n是另起一行。
下午又问了张老师如何解决弹出对话框画图、给子对话框添加消息函数及类之间传递信息。子对话框画在静态文本。添加消息函数是通过类向导。类之间传递信息通过声明类内对象实现。(上文有相应代码)。
这里感叹一下,一晚上百度都没解决的对话框画图问题,问老师10分钟就解决了。有困难找老师!
同时,问了问测绘同学的图像旋转。回去以后就想我画图有个最大的失误就是没把要画的点保存成矩阵。这就导致我后续给所有的点旋转时出现许多多余操作。这种重复操作,导致我改了将近一个小时,而且代码冗余。
在给图像旋转的同时,我就想既然已经把所有点位信息都实现通过一个旋转函数旋转,为什么不用一下数字图像处理里的那种齐次坐标。所以,我定义了3×3的矩阵,来此实现图像的旋转、平移、缩放、投影等操作。
这一天进行了最后的鲁棒性检查、界面美化及编写部分课程设计报告,为明日考核做准备。
答辩。
有以下几点的收获:
理论知识要牢固,还需要加强下C++的学习。
Debug能力较以前有很大的提升,不慌而有条理。
自己尝试过解决还解决不了的东西要像高中一样,多问问老师,老师知道很多。
不要闭门造车,和同学多多交流,比自己出色的想法要加以运用。
同学之间相互帮助,共同提升。
读程序更加顺利,学会读程序,化它为己。
写大型程序要做计划,搭框架,模块化,一一击垮,省时省力。
自己还是太菜,要好好努力,学习更多知识。同时要有自信心。