导线网平差程序系统设计—CSU测绘实习

目录

一、需求分析

(一)程序总体描述

(二)程序功能需求

二、原理与系统设计

(一)文件结构设计

(二)控制网概算

(三)成果输出

1.成果报表制作

2.网图形的绘制

(四)总体计算流程

三、测试结果与分析

运行结果展示(以一级导线为例)

四、主要代码

          CLPDDlg.cpp(主对话框.cpp)主要包括全局变量 逻辑变量 按钮控件 

 angle.h (角度类)

ControlPoint.h

ControlPoint.cpp

sqz.h (自定义类头文件)

 Sqz.cpp(自定义类.cpp文件)

Piant.h(自添加的类)

Piant.cpp

List.h(此部分用于报表制作)

List.cpp

直方图绘制.h

直方图绘制.cpp

Function.h(通用的一些计算方程)

Function.cpp


一、需求分析

(一)程序总体描述

控制网平差程序对野外控制网观测数据进行平差数据处理,目的是根据最小二乘原理,消除网中的各种几何矛盾,求出全网各待定点元素如未知点的平面坐标。

程序需要的数据即输入的数据,包括已知点的点号、坐标,未知点的点号,角度观测和距离观测数据。为了得到待定点的坐标必须先通过坐标概算得到待定点的近似坐标之后才能进行平差。得到待定点的近似坐标需要通过角度观测和距离观测数据,先由已知点的方位角通过角度观测推出各点的方位角,再通过距离观测用坐标增量的公式推算近似坐标。在计算完各待定点的近似坐标之后,需要对角度观测和距离观测进行间接平差,并通过建立误差方程和解算法方程,得到观测数据的改正数和近似坐标的改正数,并予以改正。最后通过精度评定的工作得到对应点的点位精度等精度指标。最后再把这些平差后的数据输出在文件和窗口中。

(二)程序功能需求

  1. 优化设计:根据控制网的观测精度与网形,全面评定网的精度
  2. 数据输入:支持表格化输入、外部数据导入
  3. 概算:根据已知点的数据计算方位角和坐标增量等信息,求得导线网的未知点近似坐标,可以完成对方向的曲率改正以及边长的高程归化和投影改化
  4. 平差计算:对不同的观测数据进行精密平差计算,最终的到平差后的点位坐标,方向观测值,边长观测值,进行精度评定等。
  5. 成果输出:输出控制网的图形,输出平差结果以及其报表,绘制误差椭圆,打印输出等

二、原理与系统设计

(一)文件结构设计

1. 输入文件结构设计

  • Y_num已知点的数量

    ID,X,Y  点名,x坐标,y坐标

    N_num未知点的数量

    ID,X,Y  点名,坐标,y坐标

    Dist-num观测边长的数量

    st,ed,distance 开始start点号,end点号,观测边长值

    Ag_num观测角度的数量

    st,ed,angle 开始start点号,end点号,观测角度值

 2. 输出文件结构设计

      (a) 输出坐标结果文件

                N_num待定点的数量

                ID,X,Y  点名,x坐标,y坐标

       (b) 输出精度评定相关数据文件

                单位权中误差

                点位中误差

                 方位角与边长中误差

                 误差椭圆参数

                 闭合差

        (c) 绘制网形图,绘制误差椭圆,绘制方差以及残差图

(二)控制网概算

   1. 数据输入概算

  • 对外业观测成果的整理和检查,将已知点的数量、点号、坐标,未知点的数量、点号角度观测和距离观测数据导入到程序中。(可以利用有向图的方式来储存坐标信息
  • 绘制网的略图,编制观测数据表和已知数据表。

   2.坐标概算(整体解算,局部解算)

  •   按方向观测值计算近似坐标,使用前方交会的方法
  •   按边长观测值计算近似坐标,使用边长交会的方法
  •   按照方向和边长得到方法计算导线网中待定点的近似坐标
  •   将观测结果划归到标石的中心
  •   将椭球面规划到高斯平面

   3. 平差部分

  •  计算完待定坐标后,根据待定坐标进行求取误差方程(方向、边长)
  • 根据观测的粗差进行迭代定权,减弱粗差的影响(方向为1,边长根据距离公式定权)
  • 组成法方程并解算x值
  • 进行精度评定并且计算误差椭圆元素(计算中误差、计算未知数的协因数阵、评定边长和坐标方位角精度、评定点位误差、计算误差椭圆元素)

(三)成果输出

1.成果报表制作

  • 控制点的成果表
  • 距离观测成果表
  • 方向观测成果表
  • 平面点位误差表
  • 距离观测表
  • 方向观测表

2.网图形的绘制

  • 控制网的图形
  • 坐标等比例尺的绘制
  • 点位误差椭圆的绘制
  • 图例的绘制

(四)总体计算流程

  • 首先根据已知点将存入的数据进行初步概算
  • 根据概算的数据建立间接误差方程
  • 求间接误差方程的参数并将其存入点位数据中
  • 将各个参数汇总建立B矩阵
  • 建立P矩阵并且迭代定权寻找粗差加以剔除

三、测试结果与分析

(一)运行结果展示(以一级导线为例)

 数据读入

 坐标概算

 

 图形绘制

误差的简单直方图统计图的绘制

                    

 成果报表展示

                                

输出文件展示

四、主要代码

CLPDDlg.cpp(主对话框.cpp)主要包括全局变量 逻辑变量 按钮控件 

ControlNet Q;//定义全局变量

int iflg = 0;
int gsflg = 0;
int pcflag = 0;
//判断逻辑性用的变量


void CCLPCDlg::OnBnClickedBtread()
{
	// TODO: 在此添加控件通知处理程序代码
	if (iflg)
	{
		Q.del(Q);
		iflg = 0;
	}

	

	if(iflg==0)
	Q.Read(dlgInput);
	CString str;
	if (iflg)
	{
		str.Format(_T("数据已经读入,可以开始概算\r\n"));
		message += str;
		UpdateData(FALSE);
	}
	else
	{
		str.Format(_T("数据读入失败\r\n"));
		message += str;
		UpdateData(FALSE);
	}
}


void CCLPCDlg::OnBnClickedBtcal()
{
	// TODO: 在此添加控件通知处理程序代码
	if (iflg ==0) {
		AfxMessageBox(_T("请先读入数据"));
		return;
	}
	Q.gaisuan();
	dlgInput.Format(_T(""));
	UpdateData(false);
	Q.show(dlgInput);
	CString str;
	str.Format(_T("数据已经概算完成,可以开始平差\r\n"));
	message += str;
	UpdateData(false);
	gsflg = 1;
}


void CCLPCDlg::OnBnClickedBtadjust()
{
	if (iflg == 0)
	{
		AfxMessageBox(_T("请先读入数据"));
		return;
	}
	if (gsflg == 0)
	{
		AfxMessageBox(_T("请先概算"));
		return;
	}
	Q.Adjust();
	CString str;
	str.Format(_T("平差完成,可以开始输出以及报表展示\r\n"));
	message += str;
	UpdateData(false);
	pcflag = 1;

}


void CCLPCDlg::OnBnClickedBtpaint()
{
	if (iflg == 0)
	{
		AfxMessageBox(_T("请先读入数据"));
		return;
	}
	if (gsflg == 0)
	{
		AfxMessageBox(_T("请先进行概算"));
		return;
	}
	if (pcflag == 0)
	{
		AfxMessageBox(_T("请先进行平差"));
		return;
	}
	INT_PTR PT;
	PICPAINT PTDLG;
	PT = PTDLG.DoModal();
}


void CCLPCDlg::OnBnClickedBtshowexcel()
{
	if (iflg == 0)
	{
		AfxMessageBox(_T("请先读入数据"));
		return;
	}
	if (gsflg == 0)
	{
		AfxMessageBox(_T("请先进行概算"));
		return;
	}
	if (pcflag == 0)
	{
		AfxMessageBox(_T("请先进行平差"));
		return;
	}
	INT_PTR LIST1;
	LIST LIST1DLG;
	LIST1 = LIST1DLG.DoModal();
}


void CCLPCDlg::OnBnClickedBtpush()
{
	if (iflg == 0)
	{
		AfxMessageBox(_T("请先读入数据"));
		return;
	}
	if (gsflg == 0)
	{
		AfxMessageBox(_T("请先进行概算"));
		return;
	}
	if (pcflag == 0)
	{
		AfxMessageBox(_T("请先进行平差"));
		return;
	}
	CString str1;
	Q.output(str1);
	message += str1;
	UpdateData(false);
}


void CCLPCDlg::OnBnClickedBtpainte()
{

	if (iflg == 0)
	{
		AfxMessageBox(_T("请先读入数据"));
		return;
	}
	if (gsflg == 0)
	{
		AfxMessageBox(_T("请先进行概算"));
		return;
	}
	if (pcflag == 0)
	{
		AfxMessageBox(_T("请先进行平差"));
		return;
	}
	if (Q.iUknum < 8)
	{
		AfxMessageBox(_T("数据过少,不能进行统计"));
		return;
	}
	INT_PTR ZFT1;
	ZFT ZFTDLG;
	ZFT1 = ZFTDLG.DoModal();

}

 angle.h (角度类)

#pragma once

enum AngleStyle
{
	DEG,
	DMS,
	RAD
};
class CAngle
{
	public:
		CAngle(double value = 0, AngleStyle style = DMS);
		~CAngle(void);
		double val;
		
	private:
		double dValue;//角度值
		AngleStyle  nCurStyle;//当前角度值类型
	private:
		//设置常成员函数的作用:1.类成员不会被改变
		//2.可以被常类变量调用
		double Deg(double dDms) const;
		double Dms(double dDeg) const;

	public:
		//获取指定的类型获取角度值,
		//由于返回的是dValue的引用,所以该值大小可以改变,即可以进行赋值
		double& operator() (AngleStyle style);

		//重载,获取指定的类型获取角度值,该值不可改变,const CAngle类型变量调用
		double operator() (AngleStyle style) const;
		//重载运算符+/-
		friend CAngle operator + (const CAngle & m1, const CAngle & m2);
		friend CAngle operator - (const CAngle & m1, const CAngle & m2);
	};

 angle.cpp (角度.cpp)

#include "pch.h"
#include "Angle.h"
#include "math.h"
const double EPSILON = 1.0E-12;
const double PI = 4.0 * atan(1.0);

//重载构造函数,有缺省值
CAngle::CAngle(double value, AngleStyle style)
{
	dValue = value;
	nCurStyle = style;
}

CAngle::~CAngle(void)
{
}
//重载()函数
double& CAngle::operator() (AngleStyle style) //指定的类型获取角度值
{
	//double dAngleValue;
	if (style == DMS)
	{
		if (nCurStyle == DEG)
		{
			dValue = Dms(dValue);
		}
		else if (nCurStyle == RAD)
		{
			dValue = Dms(dValue * 180.0 / PI);
		}
		nCurStyle = DMS;

	}
	else if (style == DEG)
	{
		if (nCurStyle == DMS)
		{
			dValue = Deg(dValue);
		}
		else if (nCurStyle == RAD)
		{
			dValue = dValue * 180.0 / PI;
		}
		nCurStyle = DEG;
	}
	else
	{
		if (nCurStyle == DMS)
		{
			dValue = Deg(dValue) * PI / 180;
		}
		else if (nCurStyle == DEG)
		{
			dValue = dValue * PI / 180;
		}
		nCurStyle = RAD;
	}
	return dValue;
}
//重载()函数,该函数是常函数,只能被常CAngle对象使用
double CAngle::operator() (AngleStyle style) const //指定的类型获取角度值
{
	double dAngleValue;
	if (style == DMS)
	{
		if (nCurStyle == DEG)
		{
			dAngleValue = Dms(dValue);
		}
		else if (nCurStyle == RAD)
		{
			dAngleValue = Dms(dValue * 180.0 / PI);
		}
		else
		{
			dAngleValue = dValue;
		}

	}
	else if (style == DEG)
	{
		if (nCurStyle == DMS)
		{
			dAngleValue = Deg(dValue);
		}
		else if (nCurStyle == RAD)
		{
			dAngleValue = dValue * 180.0 / PI;
		}
		else
		{
			dAngleValue = dValue;
		}
	}
	else
	{
		if (nCurStyle == DMS)
		{
			dAngleValue = Deg(dValue) * PI / 180;
		}
		else if (nCurStyle == DEG)
		{
			dAngleValue = dValue * PI / 180;
		}
		else
		{
			dAngleValue = dValue;
		}
	}
	return dAngleValue;
}


//私有成员,度分秒向十进制度转换
double CAngle::Deg(double dDms) const
{
	int iDeg, iMin;
	double dSec;

	iDeg = int(dDms + EPSILON);//度//加一个很小的数,以防止取整时的出错
	iMin = int((dDms - iDeg) * 100 + EPSILON);//分
	dSec = ((dDms - iDeg) * 100 - iMin) * 100;//秒

	return iDeg + (double)iMin / 60 + dSec / 3600;
}

//私有成员,十进制度向度分秒转换
double CAngle::Dms(double dDeg) const
{
	int iDeg, iMin;
	double dSec;
	double dTmp;

	iDeg = int(dDeg + EPSILON);//整数部分度
	dTmp = (dDeg - iDeg) * 60;//小数部分转换成分
	iMin = int(dTmp + EPSILON);//取分的整数部分
	dSec = (dTmp - iMin) * 60;//截取秒

	return iDeg + (double)iMin / 100 + dSec / 10000;
}

//友元重载+函数
CAngle operator + (const CAngle& m1, const CAngle& m2)
{
	CAngle addAngle(0, RAD);
	addAngle(RAD) = m1(RAD) + m2(RAD);
	return addAngle;
}
//友元重载-函数
CAngle operator - (const CAngle& m1, const CAngle& m2)
{
	CAngle subAngle(0, RAD);
	subAngle(RAD) = m1(RAD) - m2(RAD);
	return subAngle;
}

ControlPoint.h

#pragma once
#include"Angle.h"
enum Controllevel
{
	FIRST, SECOND, THIRD, FORTH,
	ONE, TWO,
	A, B, C, D, E
};

enum ControlPtype
{
	HZ,VT,TZ
};

struct point
{
	double x, y, z;
	double X, Y, H;//坐标值
	CString strName;//控制点名
	CString strID;//点号 
	Controllevel emLevel;//控制点等级
	ControlPtype emType;//控制点类型
	double dE, dF;//误差椭圆的长半轴和短半轴
	double dAlfa;//误差椭圆长半轴的方位角
	double dMx, dMy, dMk;//点位误差
	point* next;
};

class ControlPoint
{
public:
	ControlPoint();
	~ControlPoint(){};
public:
	double X, Y, H;//坐标值
	CString strPName;//控制点名
	int ID;
	CString strPID;//点号 
	Controllevel emCPLevel;//控制点等级
	ControlPtype emCPType;//控制点类型
	double dE, dF;//误差椭圆的长半轴和短半轴
	double dAlfa;//误差椭圆长半轴的方位角
	double dMx, dMy, dMk;//点位误差

	bool bflag;

	//ControlPoint & operator =(ControlPoint &a)//重载运算符
	//{

	//	this->bflag = a.bflag;
	//	this->X = a.X;
	//	this->Y = a.Y;
	//	this->dE = a.dE;
	//	this->dF = a.dF;

	//	return *this;
	//}

};

class OBDis
{
public:
	OBDis() { dDist = 0; };
	~OBDis() {};
public:
	ControlPoint* pStart, * pEnd;//起点和终点
	double dDist;//距离观测值

	double dS;
	double daftDis;
	double dAzi;
};

class OBAng
{
public:
	OBAng();
	~OBAng();
public:
	ControlPoint* pStation;//测站点
	ControlPoint* pStartObj;//起始定向点
	ControlPoint* pEndObj;//观测点
	CAngle  ObsValue;//角度观测值
};

class OBDri
{
public:
	OBDri(void) {};
	~OBDri(void) {};
public:
	ControlPoint* pStation;//测站点
	ControlPoint* pObject;//照准点
	CAngle angleObsValue;//方向观测值
	double dS;
	double daftDriVal;

	
};

ControlPoint.cpp

#include "pch.h"
#include "ControlPoint.h"


ControlPoint::ControlPoint()
{
	X = Y = H = 0;
	strPName = _T("");
	strPID = _T("");
	emCPLevel = FORTH;
	emCPType= HZ;
	dE = dF = 0;
	dAlfa = 0;
	dMx = dMy = dMk = 0;
	bflag = 0;
}

sqz.h (自定义类头文件)

#pragma once
#include"Function.h"
#include"Matrix.h"
#include"ControlPoint.h"
const double Ro = 206264.806247; //一弧度对应的秒数

class ControlNet
{

public:
	CString strIFname,strOFname,strInstr;
	void OPenfile();
	void Read(CString& INP);
	void show(CString& INP);
	double xmax, ymax, xmin, ymin, dx, dy, bili;//画图用函数

	ControlPoint* pUkpoint2,*pKpoint2;//画图以及报表用的公有变量
	int iKnum, iUknum;
	OBDis* pDis2;
	OBDri* pDri2;
	int iDisnum;
	int iDrinum;
	//以上为画图专用的公有变量
	void del(ControlNet& Q);

private:
	

	ControlPoint* pKpoint,*pUkpoint,*p;
	
	OBAng* pAngle;
	int iAngnum;
	
	OBDis* pDis;

	OBDri* pDri;
	//以上为计算专用的私有变量
public:
	ControlPoint* SearchKnownPointUsingname(CString strname);//根据点号查找已知点,返回该点的指针
	ControlPoint* SearchUnknownPointUsingname(CString strname);//根据点号查找未知知点,返回该点的指针
	ControlPoint* SearchPointUsingname(CString strname);根据点号查找控制点(包括已知点和未知点),返回该点的指针

public:
	void gaisuan();//概算
	void Adjust();//平差
	void output(CString &out);//输出
};

 Sqz.cpp(自定义类.cpp文件)

#include "pch.h"
#include "sqz.h"
extern int iflg;

//根据名字从已知点数组中找到控制点,并返回该点的指针
ControlPoint* ControlNet::SearchKnownPointUsingname(CString strname)
{
	for (int i = 0; i < iKnum; i++)
	{
		if (strname == pKpoint[i].strPName)
		{
			return &pKpoint[i];
		}
	}
	return NULL;
}
//根据名字从未知点数组中找到控制点,并返回该点的指针
ControlPoint* ControlNet::SearchUnknownPointUsingname(CString strname)
{
	for (int i = 0; i < iUknum; i++)
	{
		if (strname == pUkpoint[i].strPName)
		{
			return &pUkpoint[i];
		}
	}
	return NULL;
}
//根据名字从未知点和已知点数组中找到控制点,并返回该点的指针
ControlPoint* ControlNet::SearchPointUsingname(CString strname)
{
	ControlPoint* pCP = NULL;
	pCP = SearchKnownPointUsingname(strname);
	if (pCP == NULL)
	{
		pCP = SearchUnknownPointUsingname(strname);
	}
	return pCP;
}
// 打开文件函数
void ControlNet::OPenfile()
{
	CFileDialog dlgFile(TRUE, _T("dat"), NULL,
		OFN_EXPLORER, _T("(数据文件)|*.dat"));
	if (dlgFile.DoModal() == IDCANCEL) return;
	strIFname = dlgFile.GetPathName();
	
}
//展示读入数据函数
void ControlNet::show(CString& INP)
{
	CString ino;
	for (int i = 0; i < iUknum; i++)
	{
		ino.Format(_T("%s %lf %lf \r\n"), pUkpoint[i].strPName, pUkpoint[i].X, pUkpoint[i].Y);
		INP += ino;
	}
}
//读文件函数
void ControlNet::Read(CString& INP)
{
	INP.Format(_T(""));
	OPenfile();
	CStdioFile Q;
	if (!Q.Open(strIFname, CFile::modeRead))
	{
		iflg = 0;
		return;

	}
	else iflg = 1;
	CString strLine;
	Q.ReadString(strLine);
	while (strLine != "END Header")
	{
		Q.ReadString(strLine);
	}
	strInstr.Empty();
	BOOL bEOF = Q.ReadString(strLine);
	while (bEOF)
	{
		INP= INP + strLine;
		strInstr = strInstr + strLine;
		bEOF = Q.ReadString(strLine);
		if (bEOF)strInstr += _T("\n");
		if (bEOF)INP += _T("\r\n");
	}
	Q.Close();
	
	CStringArray temp,temp2;
	temp.RemoveAll();
	int hang=splitstrarr(strInstr, '\n', temp);
	if (hang < 3)
	{
		AfxMessageBox(_T("数据过少"));
		return;
	}

	iKnum = _tstoi(temp[0]);
	pKpoint = new ControlPoint[iKnum];
	pKpoint2 = new ControlPoint[iKnum];

	xmax = -9999999999999;
	ymax = -999999999999;
	xmin = 9999999999999;
	ymin = 9999999999999;

	for (int i = 1; i <= iKnum; i++)
	{
		temp2.RemoveAll();
		splitstrarr(temp[i], ',', temp2);
		pKpoint[i-1].strPName= temp2[0];
		
		pKpoint[i-1].X= _tstof(temp2[1]);

		pKpoint[i-1].Y= _tstof(temp2[2]);
		pKpoint[i - 1].bflag = 1;
		pKpoint[i - 1].ID = i - 1;
		if (xmax < pKpoint[i - 1].X)xmax = pKpoint[i - 1].X;
		if (ymax < pKpoint[i - 1].Y)ymax = pKpoint[i - 1].Y;
		if (xmin > pKpoint[i - 1].X)xmin = pKpoint[i - 1].X;
		if (ymin > pKpoint[i - 1].Y)ymin = pKpoint[i - 1].Y;
	}
	pKpoint2 = pKpoint;
	iUknum = _tstoi(temp[iKnum + 1]);
	pUkpoint = new ControlPoint[iUknum];
	temp2.RemoveAll();
	splitstrarr(temp[iKnum + 2], ',', temp2);
	for (int i = 0; i < iUknum; i++)
	{
		CString pop = temp2[i];
		pUkpoint[i].strPName = temp2[i];
		pUkpoint[i].ID = i + iKnum;
	}

	
	iDisnum = _tstoi(temp[iKnum + 3]);
	pDis = new OBDis[iDisnum];
	pDis2=new OBDis[iDisnum];
	for (int i = 0; i < iDisnum; i++)
	{
		temp2.RemoveAll();
		splitstrarr(temp[iKnum + 4+i],',',temp2);
		
		CString mmm = temp2[1];
		double leng = _tstof(temp2[2]);
		pDis[i].pStart = (SearchPointUsingname(temp2[0]));
		pDis[i].pEnd = (SearchPointUsingname(temp2[1]));
		pDis[i].dDist= _tstof(temp2[2]);

	}
	pDis2 = pDis;
	iDrinum = _tstoi(temp[iKnum + 4+ iDisnum]);
	pDri = new OBDri[iDrinum];
	for (int i = 0; i < iDrinum; i++)
	{
		temp2.RemoveAll();
		splitstrarr(temp[i + iKnum + 5 + iDisnum], ',', temp2);

		pDri[i].pStation= SearchPointUsingname(temp2[0]);
		pDri[i].pObject = SearchPointUsingname(temp2[1]);
		double vvva = (_tstof(temp2[2]));
		pDri[i].angleObsValue.val= DmS(_tstof(temp2[2]));
		//pDri[i].angleObsValue(DEG);
	}

}
//坐标概算函数
void  ControlNet::gaisuan()
{
	int num = iKnum;
	p = new ControlPoint[iKnum + iUknum];
	for (int i = 0; i < iKnum; i++)
	{
		p[i] = pKpoint[i];
	}
	//for (int i = iKnum,k=0; i < iKnum+iUknum; i++)
	//{
	//	p[i] = pUkpoint[k];
	//}
	double azi1, azi2;
	int calnum = iUknum;
	
	while (calnum != 0)//计数器
	{

		for (int i = 0; i < iUknum; i++)//从未知点开始遍历
		{

			if (pUkpoint[i].bflag == 0)//代表没有经过概算flag=0
			{
				bool ofg = 0;//下层循环停止变量
				for (int k = 0; (k<iDisnum&&ofg==0); k++)
				{
					if (pUkpoint[i].strPName == pDis[k].pEnd->strPName && pDis[k].pStart->bflag)//匹配寻找以该点为终点的距离观测,且起点已经被概算或者已知
					{
						bool kfg = 0;//下层循环停止变量
						for (int j = 0; j < iDrinum&&kfg==0; j++)
						{

							if (pDri[j].pStation->strPName == pDis[k].pStart->strPName)//匹配和距离起点相同的方向测站点
							{
								bool  bfg = 0;//下层循环停止变量
								for (int jj = 0; (jj < iDrinum&&bfg==0); jj++)
								{
									//寻找观测点起点已知的点
									if ((pDri[jj].pObject->bflag && pDri[jj].pStation->strPName == pDri[j].pStation->strPName))
									{
										bool kkkflag = 0;
										//所有点位已经找到,开始进行第三种方法的概算
										for (int kkk = 0; kkk < iDrinum && kkkflag == 0; kkk++)
											if ((pDri[kkk].pObject->strPName == pUkpoint[i].strPName && pDri[kkk].pStation->strPName == pDri[j].pStation->strPName))
											{

												azi1 = Azimuth(pDri[jj].pStation->X, pDri[jj].pStation->Y, pDri[jj].pObject->X, pDri[jj].pObject->Y);
												azi2 = (azi1 / PI * 180  + (pDri[kkk].angleObsValue.val) - (pDri[jj].angleObsValue.val)) * PI / 180;
												pUkpoint[i].X = pDri[jj].pStation->X + pDis[k].dDist * cos(azi2);
												pUkpoint[i].Y = pDri[jj].pStation->Y + pDis[k].dDist * sin(azi2);

										

												for (int di = 0; di < iDisnum; di++)
												{
													
													if (pDis[di].pStart->strPName == pUkpoint[i].strPName)pDis[di].pStart->bflag = 1;
													if (pDis[di].pEnd->strPName == pUkpoint[i].strPName)pDis[di].pEnd->bflag = 1;

												}
												for (int gc = 0; gc < iDrinum; gc++)
												{
													if (pDri[gc].pObject->strPName == pUkpoint[i].strPName)pDri->pObject->bflag = 1;
													if (pDri[gc].pStation->strPName == pUkpoint[i].strPName)pDri->pStation->bflag = 1;
												}

												pUkpoint[i].bflag = 1;
												calnum--;
												bfg = 1;

												break;
											}
									}
								}
								kfg = 1;
							}
						}
						ofg = 1;
					}
				}
			}
		}

	}
	//for (int i = 0; i < iUknum; i++)
	//{
	//	p[i+iKnum] = pKpoint[i];
	//}
}
//输出矩阵函数
void OutputMatrixBox(CMatrix mat)
{
	CString strOutput;
	CString strTmp;

	for (int i = 0; i < mat.Row(); i++)
	{
		for (int j = 0; j < mat.Col(); j++)
		{
			strTmp.Format(_T("%.4f  "), mat(i, j));
			strOutput += strTmp;
		}
		strOutput += _T("\n");
	}

	AfxMessageBox(strOutput);
}
//平差函数
void ControlNet::Adjust()
{
	CMatrix B(iDrinum+iDisnum, 3 * iUknum + iKnum);
	CMatrix F(iDrinum + iDisnum, 1);//初始化矩阵
	int i, j,kk;
	double a, b, t, d,l,L,Zi;
	ControlPoint I, J;
	for (int k = 0; k < iDrinum; k++)
	{

		
		i = pDri[k].pStation->ID;
		B(k, 2 * iUknum + i) = -1;
		j = pDri[k].pObject->ID;
		L = pDri[k].angleObsValue.val * PI / 180;
		for (int i0 = 0; i0 < iDrinum; i0++)
		{
			if (i == pDri[i0].pStation->ID)
			{
				Zi = Azimuth(pDri[i0].pStation->X, pDri[i0].pStation->Y, pDri[i0].pObject->X, pDri[i0].pObject->Y);
				break;
			}
		}
		
		for (kk = 0; kk < iDisnum; kk++)
		{
			if (i == pDis[kk].pStart->ID && j == pDis[kk].pEnd->ID)
			{
				d = pDis[kk].dDist;
				break;
			}
			else if (i< iKnum && j< iKnum)
			{
				d = Dis(pDis[k].pStart->X, pDis[k].pStart->Y, pDis[k].pEnd->X, pDis[k].pEnd->X);
				break;
			}
		}

		t = Azimuth(pDri[k].pStation->X, pDri[k].pStation->Y, pDri[k].pObject->X, pDri[k].pObject->Y);
		double pp = Zi + L;
		if ((Zi + L) > 2 * PI) { pp = pp - 2 * PI; }
		l = -pp+t;
		F(k, 0) = l;
		
		a = Ro * sin(t) / d;
		b = -Ro * cos(t) / d;
		if (i < iKnum && j < iKnum) {}//分为四种情况
		else if (i < iKnum && j >= iKnum)
		{
			B(k, 2 * (j - iKnum) ) = -a;
			B(k, 2 * (j - iKnum)+1) = -b;
		}
		else if (i >= iKnum && j < iKnum)
		{
			B(k, 2 * (i - iKnum)) = a;
			B(k, 2 * (i - iKnum)+1) = b;
		}
		else if (i >= iKnum && j >= iKnum)
		{
			B(k, 2*(i-iKnum))=a;
			B(k, 2 * (j-iKnum)) = -a;
			B(k, 2 * (i - iKnum)+1) = b;
			B(k, 2 * (j - iKnum)+1) = -b;
		}
	}
	//上面为距离观测定权 下面为方向观测定权
	for (int k = 0; k < iDisnum; k++)
	{
		
		i = pDis[k].pStart->ID;
		j = pDis[k].pEnd->ID;
		t = Azimuth(pDis[k].pStart->X , pDis[k].pStart->Y, pDis[k].pEnd->X,  pDis[k].pEnd->Y);
		l = Dis(pDis[k].pStart->X, pDis[k].pStart->Y, pDis[k].pEnd->X, pDis[k].pEnd->Y)-pDis[k].dDist;
		F(k + iDrinum, 0) = -l;
		//分为四种情况
		if (i < iKnum && j < iKnum) {}
		else if (i < iKnum && j >= iKnum)
		{
			B(k + iDrinum, 2 * (j - iKnum) ) = cos(t);
			B(k + iDrinum, 2 * (j - iKnum)+1) = sin(t);
		}
		else if (i >= iKnum && j < iKnum)
		{
			B(k + iDrinum , 2 * (i - iKnum)) = -cos(t);
			B(k + iDrinum, 2 * (i - iKnum)+1) = -sin(t);
		}
		else if (i >= iKnum && j >= iKnum)
		{
			B(k + iDrinum, 2 * (i - iKnum) ) = -cos(t);
			B(k + iDrinum, 2 * (j - iKnum) ) = cos(t);
			B(k + iDrinum, 2 * (i - iKnum)+1) = -sin(t);
			B(k + iDrinum, 2 * (j - iKnum)+1) = sin(t);
		}
		
	}


	CMatrix P(iDrinum + iDisnum, iDrinum + iDisnum);//定权
	for (int ii = 0; ii < iDrinum; ii++)
	{
		P(ii, ii) = 1;
	}
	for (int ii = iDrinum,iii=0; ii < iDrinum + iDisnum; ii++,iii++)
	{
		P(ii, ii) = 100 / (pDis[iii].dDist );
	}

	CMatrix Nbb = (~B)*P * B;
	

	CMatrix Fe = (~B) * P * F;
	CMatrix xx = Nbb.Inv()*Fe;
	CMatrix V = B * xx - F;
	
	CMatrix Qxx = Nbb.Inv();

	CMatrix xigema = ~V*P*V;
	xigema(0, 0) = xigema(0, 0) / (iDisnum + iDrinum -2*iUknum);
	double m0 = sqrt(xigema(0, 0));
	//精度评定参数

	CMatrix X(iKnum+3*iUknum,1);
	for (int u = 0; u < 3 * iKnum + iUknum; u++)
	{
		X(u, 0) = 1;
	}

	for (int u = 0; u < iUknum; u++)
	{
		X(2 * u, 0) = xx(2 * u+1, 0);
			
		X(2*u+1, 0) = xx(2 * u + 1, 0);
	}
	CMatrix ft(2 * iUknum, 1);
	CMatrix QX(2 * iUknum, 2 * iUknum);

	for (int uio = 0; uio < 2 * iUknum; uio++)
	{
		for (int ift = 0; ift < 2 * iUknum; ift++)
		{
			QX(uio, ift) = Qxx(uio, ift);

		}
	}

	for (int uio = 0; uio < iDrinum; uio++)
	{
		for (int ift = 0; ift < 2*iUknum; ift++)
		{
			ft(ift, 0) = B(uio, ift + 1);

		}
		CMatrix QF = ~ft * QX * ft;
		double m;
		m = m0 * sqrt(QF(0,0));
	}
	//求点位中误差
	//误差椭圆方面
	double Qx, Qy, Qxy;
	for(int iex=0;iex<iUknum;iex++)
		for (int iey = 0; iey < iUknum; iey++)
		{
			int ex = 2 * iex,ey=2*iey+1;
			Qx = Qxx(ex, ex);
			Qy = Qxx(ey,ey);
			Qxy = Qxx(ex, ey);
			pUkpoint[iex].dMx = m0 * sqrt(Qx);
			pUkpoint[iex].dMy = m0 * sqrt(Qy);
			pUkpoint[iex].dMk = m0 * sqrt(m0 * sqrt(Qx) * m0 * sqrt(Qx) + m0 * sqrt(Qy) * m0 * sqrt(Qy));
			double Qq = 0.5 * atan(2 * Qxy / (Qx - Qy));
			
			pUkpoint[iex].dAlfa =Qq ;
			pUkpoint[iex].dE = m0 * sqrt(Qx + Qxy * tan(Qq + PI / 2));
			pUkpoint[iex].dF =  m0* sqrt(Qx + Qxy * tan(Qq));
		}

	pUkpoint2 = new ControlPoint[iUknum];
	CMatrix px(iUknum, 1);
	
	for (int it = 0; it < iUknum; it++)
	{
		pUkpoint2[it] = pUkpoint[it];
		pUkpoint2[it].X += X(2*it, 0);
		pUkpoint2[it].Y += X(2 * it+1, 0);
		if (xmax < pUkpoint2[it].X)xmax = pUkpoint2[it].X;
		if (ymax < pUkpoint2[it].Y)ymax = pUkpoint2[it].Y;
		if (xmin > pUkpoint2[it].X)xmin = pUkpoint2[it].X;
		if (ymin > pUkpoint2[it].Y)ymin = pUkpoint2[it].Y;
		px(it, 0) = pUkpoint2[it].X;
	}
	dx = xmax - xmin;
	dy = ymax - ymin;


	//一下为报表输出前的数据准备
	for (int ids = 0,pds=iDrinum; ids < iDisnum; ids++)
	{
		pDis[ids].dS = V(pds, 0);
		pDis[ids].daftDis = V(pds, 0)+pDis[ids].dDist;
		pDis[ids].dAzi = Azimuth(pDis[ids].pStart->X, pDis[ids].pStart->Y, pDis[ids].pEnd->X, pDis[ids].pEnd->Y);
	}
	pDis2 = new OBDis[iDisnum];
	pDis2 = pDis;

	//以下为方向观测报表的输出方式
	for (int idri = 0; idri < iDrinum; idri++)
	{
		pDri[idri].dS = V(idri, 0)*1000;
		pDri[idri].daftDriVal = (V(idri, 0)+ pDri[idri].angleObsValue.val);
	}
	pDri2 = new OBDri[iDrinum];
	pDri2 = pDri;
}
//输出到文件函数
void ControlNet::output(CString &out)
{
	

	strOFname = strIFname.Left(strIFname.ReverseFind(_T('\\')));//反向查找第一个\\位置
	CString  strOFname1 = strOFname + _T("\\已知数据.dat");
	CStdioFile Z;
	if (!Z.Open(strOFname1, CFile::modeWrite | CFile::modeCreate | CFile::modeNoTruncate | CFile::typeText))
		return;
	Z.SeekToEnd();
	CString strline;
	strline.Format(_T(" *********已知点*********\n"));
	Z.WriteString(strline);
	strline.Format(_T("点名\tX(m)\tY(m)\n"));
	Z.WriteString(strline);
	for (int ipos = 0; ipos < iKnum; ipos++)
	{
		strline.Format(_T("%s\t%5f\t%5f\n"),pKpoint[ipos].strPName, pKpoint[ipos].X, pKpoint[ipos].Y);
		Z.WriteString(strline);
	}
	strline.Format(_T(" *********distance ob data*********\n"));
	Z.WriteString(strline);
	strline.Format(_T("测站\t照准\t距离\n"));
	Z.WriteString(strline);
	for (int ipos = 0; ipos < iDisnum; ipos++)
	{
		strline.Format(_T("%s\t%s\t%5f\n"), pDis[ipos].pStart->strPName, pDis[ipos].pEnd->strPName, pDis[ipos].daftDis);
		Z.WriteString(strline);
	}
	strline.Format(_T(" ********* dri ob data *********\n"));
	Z.WriteString(strline);
	strline.Format(_T("测站\t照准\t方向值\n"));
	for (int ipos = 0; ipos < iDrinum; ipos++)
	{
		strline.Format(_T("%s\t%s\t%5f\n"), pDri[ipos].pStation->strPName, pDri[ipos].pObject->strPName, pDri[ipos].daftDriVal);
		Z.WriteString(strline);
	}
	Z.Close();
	

	//成果输出
	CString  strOFname2 = strOFname + _T("\\方向距离点位误差观测成果.dat");//继续使用随机数命名输出文件名
	CStdioFile S;
	if (!S.Open(strOFname2, CFile::modeWrite | CFile::modeCreate | CFile::modeNoTruncate | CFile::typeText))
		return;
	S.SeekToEnd();
	strline.Format(_T("测站\t照准\t方向值\t方向改正\t平差后值\n"));
	S.WriteString(strline);
	 int count =iDrinum;
	for (int i = 0, j = 0; count != 0; i++, j++)
	{
		strline.Format(_T("%s\t%s\t%4f\t%4f\t%4f\n"), pDri[i].pStation->strPName, pDri[i].pObject->strPName, pDri[i].angleObsValue.val, pDri[i].dS, pDri[i].daftDriVal);
		S.WriteString(strline);
		if (i + 1 < iDrinum && pDri2[i + 1].pStation->ID != pDri2[i].pStation->ID)
		{
			strline.Format(_T("\n"));
			S.WriteString(strline);
			j = j + 1;
		}
		count--;
	}
	strline.Format(_T("测站\t照准\t距离\t改正\t平差后值\t方位角r\n"));
	S.WriteString(strline);
	for (int ipos = 0; ipos < iDisnum; ipos++)
	{
		strline.Format(_T("%s\t%s\t%4f\t%4f\t%4f\t%f\n"), pDis[ipos].pStart->strPName, pDis[ipos].pEnd->strPName, pDis[ipos].dDist, pDis[ipos].dS, pDis[ipos].daftDis, pDis[ipos].dAzi*180/PI);
		S.WriteString(strline);
	}
	strline.Format(_T("点名\t长轴\t短轴\t长轴方位\t点位中误差\t备注\n"));
	S.WriteString(strline);
	for (int ipos = 0; ipos < iUknum; ipos++)
	{
		strline.Format(_T("%s\t%4f\t%4f\t%4f\t%4f\n"), pUkpoint[ipos].strPName, pUkpoint[ipos].dE, pUkpoint[ipos].dF, pUkpoint[ipos].dAlfa, pUkpoint[ipos].dMx);
		S.WriteString(strline);
	}
	S.Close();
	CString  strOFname3 = strOFname + _T("\\计算成果.dat");//继续使用随机数命名输出文件名
	CStdioFile R;
	if (!R.Open(strOFname3, CFile::modeWrite | CFile::modeCreate | CFile::modeNoTruncate | CFile::typeText))
		return;
	R.SeekToEnd();
	strline.Format(_T("END Header\n"));
	R.WriteString(strline);
	strline.Format(_T("%d\n"), iKnum);
	R.WriteString(strline);
	for (int ipos = 0; ipos < iKnum; ipos++)
	{
		strline.Format(_T("%s,%4f,%4f\n"), pKpoint[ipos].strPName, pKpoint[ipos].X, pKpoint[ipos].Y);
		R.WriteString(strline);
	}
	strline.Format(_T("%d\n"), iUknum);
	R.WriteString(strline);
	strline.Format(_T("%s"), pUkpoint[0].strPName);
	R.WriteString(strline);
	for (int ipos = 1; ipos < iUknum; ipos++)
	{
		strline.Format(_T(",%s"),pUkpoint[ipos].strPName);
		R.WriteString(strline);
	}
	strline.Format(_T("\n%d\n"),iDisnum);
	R.WriteString(strline);
	for (int ipos = 0; ipos < iDisnum; ipos++)
	{
		strline.Format(_T("%s,%s,%4f\n"), pDis[ipos].pStart->strPName, pDis[ipos].pEnd->strPName, pDis[ipos].daftDis);
		R.WriteString(strline);
	}
	strline.Format(_T("%d\n"), iDrinum);
	R.WriteString(strline);
	for (int ipos = 0; ipos < iDrinum-1; ipos++)
	{
		strline.Format(_T("%s,%s,%f\n"), pDri[ipos].pStation->strPName, pDri[ipos].pObject->strPName, DeG(pDri[ipos].angleObsValue.val));
		R.WriteString(strline);
	}
	strline.Format(_T("%s,%s,%f"), pDri[iDrinum-1].pStation->strPName, pDri[iDrinum - 1].pObject->strPName, DeG(pDri[iDrinum - 1].angleObsValue.val));
	R.WriteString(strline);
	R.Close();
	out.Format(_T("成功!文件夹路径为:%s"), strOFname);

}

void ControlNet::del(ControlNet& Q)
{
	
	ControlNet Z;
	Q = Z;

}
//实现连续读入功能

Piant.h(自添加的类)

#pragma once
#include "afxdialogex.h"


// PICPAINT 对话框

class PICPAINT : public CDialogEx
{
	DECLARE_DYNAMIC(PICPAINT)

public:
	PICPAINT(CWnd* pParent = nullptr);   // 标准构造函数
	virtual ~PICPAINT();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_DIALOG1 };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedBttx();
	afx_msg void draw_ellipse(CDC*& pDC, int x0, int y0, int a, int b);
	afx_msg void OnPaint();
	afx_msg void OnBnClickedBtty();
	afx_msg void OnBnClickedBtfd();
	afx_msg void OnBnClickedBtsx();
	afx_msg void OnBnClickedBtxz();
};

Piant.cpp

(通过各个按钮控件修改判断变量值,进而控制绘图的元素,然后来调用onpaint函数实现功能)可以根据图片添加对应的按钮控件

// PICPAINT.cpp: 实现文件
//

#include "pch.h"
#include "CLPC.h"
#include"CLPCDlg.h"
#include "afxdialogex.h"
#include "PICPAINT.h"
#include"ControlPoint.h"
#include"sqz.h"

// PICPAINT 对话框

IMPLEMENT_DYNAMIC(PICPAINT, CDialogEx)

PICPAINT::PICPAINT(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG1, pParent)
{

}

PICPAINT::~PICPAINT()
{
}

void PICPAINT::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(PICPAINT, CDialogEx)
	//ON_BN_CLICKED(IDC_BTTX, &PICPAINT::OnBnClickedBttx)
	ON_WM_PAINT()
	ON_BN_CLICKED(IDC_BTTY, &PICPAINT::OnBnClickedBtty)
	ON_BN_CLICKED(IDC_BTFD, &PICPAINT::OnBnClickedBtfd)
	ON_BN_CLICKED(IDC_BTSX, &PICPAINT::OnBnClickedBtsx)
	ON_BN_CLICKED(IDC_BTXZ, &PICPAINT::OnBnClickedBtxz)
END_MESSAGE_MAP()


// PICPAINT 消息处理程序
double bili;


//定义点结构体方便绘图
struct dot
{
	double x;
	double y;
};

extern ControlNet Q;
//坐标转换
void trans(dot &p, double x, double y)
{
	//p.x = (x - Q.xmin) * bili;
	//p.y = (Q.ymax-y) * bili;

	p.y = (Q.dx + Q.xmin - x) * bili+50;
	p.x = (y - Q.ymin) * bili+50;
}
//设置比例
void setbili(CRect& rect)
{
	double ry = double(rect.Width()) * 0.8 / Q.dy;
	double rx = double(rect.Height())*0.8 / Q.dx;
	bili = rx < ry ? rx : ry;
	
}

//
void PICPAINT::OnBnClickedBttx()
{
	CWnd* pWin = GetDlgItem(IDC_PAINT);//获取Picture控件的指针
	CRect rect;
	pWin->GetClientRect(rect);//把控件的长宽、坐标等信息保存在rect里
	CDC* pDC = pWin->GetDC();//获取该控件的画布
	setbili(rect);

	CPen myPen(PS_SOLID, 2, RGB(0, 0, 0));
	CPen* oldPen = pDC->SelectObject(&myPen);
	int num = Q.iDisnum;
	dot* p; p = new dot[num,2];
	for (int i = 0; i < Q.iDisnum; i++)
	{
		trans(p[i,0], Q.pDis2[i].pStart->X, Q.pDis2[i].pStart->Y);
		trans(p[i,1], Q.pDis2[i].pEnd->X, Q.pDis2[i].pEnd->Y);
		
	}

	for (int i = 0; i < Q.iDisnum; i++)
	{
		pDC->MoveTo(p[i,0].x, p[i,0].y);
		pDC->LineTo(p[i,1].x, p[i,1].y);
	}
	myPen.DeleteObject();
	myPen.CreatePen(PS_SOLID, 0.2, RGB(255, 0, 0));
	oldPen = pDC->SelectObject(&myPen);

}


//判断变量
double ntimes=10000;
bool tyflag = 0;

int ttimes = 1;
int ntflag = 1;

double di = 0;

bool ptflag = 0;

//void xuanzhuan(dot&P,double DEG,double x,double y)
//{
//	DEG = DEG / PI * 180;
//	P.x = (x - xcenter) * cos(DEG) - (y - ycenter) * sin(DEG) + xcenter;
//
//	P.x = (x - xcenter) * sin(DEG) + (y - ycenter) * cos(DEG) + ycenter;
//}

void PICPAINT::OnPaint()
{
	CPaintDC dc(this); // device context for painting
					   // TODO: 在此处添加消息处理程序代码
					   // 不为绘图消息调用 CDialogEx::OnPaint()
	
	CWnd* pWin = GetDlgItem(IDC_PAINT);//获取Picture控件的指针
	CRect rect;
	pWin->GetClientRect(rect);//把控件的长宽、坐标等信息保存在rect里
	CDC* pDC = pWin->GetDC();//获取该控件的画布
	/*if (ptflag == 0)
	{
		pDC->FillSolidRect(rect, RGB(255, 255, 255));
	}*/
	setbili(rect);




	CFont Font;//创建字体
	VERIFY(Font.CreateFont(
		10,                        // nHeight
		0,                         // nWidth
		0,                         // nEscapement
		0,                         // nOrientation*
		FW_NORMAL,                 // nWeight
		FALSE,                     // bItalic
		FALSE,                     // bUnderline
		0,                         // cStrikeOut
		ANSI_CHARSET,              // nCharSet
		OUT_DEFAULT_PRECIS,        // nOutPrecision
		CLIP_DEFAULT_PRECIS,       // nClipPrecision
		DEFAULT_QUALITY,           // nQuality
		DEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily
		_T("宋体")));                 // lpszFacename

	pDC->SetTextColor(RGB(255, 0, 0));///改变字体颜色
	CFont* pOldFont = pDC->SelectObject(&Font);
	

	if (ttimes)
	{
		ntimes = 100 / (cos(Q.pUkpoint2[1].dAlfa) * Q.pUkpoint2[1].dE);
		ttimes = 0;
	}
	//设置误差椭圆较为合适的比例



	double dLenX = double(rect.Height()) / 10;//坐标轴X轴的长度
	double dLenY = double(rect.Width()) / 10;//坐标轴Y轴的长度

	//坐标轴的原点坐标
	double dOrgCoordX = rect.left + double(rect.Width()) / 20;
	double dOrgCoordY = rect.bottom - double(rect.Height()) / 20;

	//画Y轴
	pDC->MoveTo(dOrgCoordX, dOrgCoordY);
	pDC->LineTo(dOrgCoordX + dLenY, dOrgCoordY);
	pDC->LineTo(dOrgCoordX + dLenY - 5, dOrgCoordY - 5);
	pDC->MoveTo(dOrgCoordX + dLenY, dOrgCoordY);
	pDC->LineTo(dOrgCoordX + dLenY - 5, dOrgCoordY + 5);

	//画X轴
	pDC->MoveTo(dOrgCoordX, dOrgCoordY);
	pDC->LineTo(dOrgCoordX, dOrgCoordY - dLenX);
	pDC->LineTo(dOrgCoordX - 5, dOrgCoordY - dLenX + 5);
	pDC->MoveTo(dOrgCoordX, dOrgCoordY - dLenX);
	pDC->LineTo(dOrgCoordX + 5, dOrgCoordY - dLenX + 5);



	//画比例尺
	//比例尺的起点
	double dOrgScaleX = dOrgCoordX + dLenX + double(rect.Width()) / 10;
	double dOrgScaleY = dOrgCoordY;
	pDC->MoveTo(dOrgScaleX, dOrgScaleY);
	pDC->LineTo(dOrgScaleX + 200 * bili, dOrgScaleY);
	pDC->LineTo(dOrgScaleX + 200 * bili, dOrgScaleY - 2);
	pDC->MoveTo(dOrgScaleX, dOrgScaleY);
	pDC->LineTo(dOrgScaleX, dOrgScaleY - 2);

	pDC->TextOut(dOrgCoordX - 12, dOrgCoordY - dLenX - 2, _T("X"));
	pDC->TextOut(dOrgCoordX + dLenY - 3, dOrgCoordY + 5, _T("Y"));


	//写比例尺名
	pDC->TextOut(dOrgScaleX + 70 * bili, dOrgScaleY + 6, _T("200m"));




	CPen myPen(PS_SOLID, 2, RGB(0, 0, 0));
	CPen* oldPen = pDC->SelectObject(&myPen);
	int num = Q.iDisnum;
	dot* p; p = new dot[2*num];
	for (int i = 0; i < Q.iDrinum; i++)
	{
		trans(p[2*i], Q.pDri2[i].pStation->X, Q.pDri2[i].pStation->Y);
		trans(p[2*i+1], Q.pDri2[i].pObject->X, Q.pDri2[i].pObject->Y);

	}
	//转换方向观测点坐标

	for (int i = 0; i < Q.iDrinum; i++)
	{
		pDC->MoveTo(p[2*i].x, p[2*i].y);
		pDC->LineTo(p[2*i+1].x, p[2*i+ 1].y);
	}
	//通过方向观测画网图

	for (int i = 0; i < Q.iDisnum; i++)
	{
		trans(p[2 * i], Q.pDis2[i].pStart->X, Q.pDis2[i].pStart->Y);
		trans(p[2 * i + 1], Q.pDis2[i].pEnd->X, Q.pDis2[i].pEnd->Y);
	}
	//转换距离观测点坐标


	for (int i = 0; i < Q.iDisnum; i++)
	{
		int disx = (p[2 * i].x + p[2 * i + 1].x) / 2;
		int disy = (p[2 * i].y + p[2 * i + 1].y) / 2+5;
		CString strdis;
		strdis.Format(_T("%2f"), Q.pDis2[i].daftDis);
		pDC->TextOut(disx, disy, strdis);

	}
	//标注距离




	dot* p2; p2 = new dot[Q.iUknum];
	for (int i = 0; i < Q.iUknum; i++)
	{
		trans(p2[i],Q.pUkpoint2[i].X, Q.pUkpoint2[i].Y);
		pDC->TextOut(p2[i].x+5, p2[i].y,Q.pUkpoint2[i].strPName);//标号
		CString strmk;
		//strmk.Format(_T("%2f"), Q.pUkpoint2[i].dMk);
		//pDC->TextOut(p2[i].x-5, p2[i].y-5, strmk);//mk
		pDC->Ellipse(p2[i].x-3, p2[i].y-3, p2[i].x + 3, p2[i].y + 3);
	}
	//标注点号

	dot* p3; p3 = new dot[Q.iKnum];
	myPen.DeleteObject();
	myPen.CreatePen(PS_SOLID, 1.5, RGB(0, 0, 250));
	oldPen = pDC->SelectObject(&myPen);
	for (int i = 0; i < Q.iKnum; i++)
	{
		trans(p3[i], Q.pKpoint2[i].X, Q.pKpoint2[i].Y);
		pDC->MoveTo(p3[i].x, p3[i].y-5);
		pDC->LineTo(p3[i].x-5, p3[i].y+5);
		pDC->LineTo(p3[i].x+5, p3[i].y+5);
		pDC->LineTo(p3[i].x, p3[i].y-5);


		pDC->TextOut(p3[i].x + 5, p3[i].y, Q.pKpoint2[i].strPName, 1);//标号
		if (i > 0)
		{
			pDC->MoveTo(p3[i].x, p3[i].y);
			pDC->LineTo(p3[i - 1].x, p3[i - 1].y);

			pDC->MoveTo(p3[i].x+3, p3[i].y);
			pDC->LineTo(p3[i - 1].x+3, p3[i - 1].y);
		}
	}
	


	myPen.DeleteObject();
	myPen.CreatePen(PS_SOLID, 0.1, RGB(255, 0, 0));
	oldPen = pDC->SelectObject(&myPen);
	if (tyflag)
	{
		/*double ex1, ex2, ey1, ey2; int times;
		for (int ie = 0; ie < Q.iUknum; ie++)
		{
			
			ex1 = ntimes * (cos(Q.pUkpoint2[ie].dAlfa) * Q.pUkpoint2[ie].dE);
			ey1 = ntimes * (sin(Q.pUkpoint2[ie].dAlfa) * Q.pUkpoint2[ie].dE);
			ex2 = ntimes * (cos(Q.pUkpoint2[ie].dAlfa + PI / 2) * Q.pUkpoint2[ie].dF);
			ey2 = ntimes * (sin(Q.pUkpoint2[ie].dAlfa + PI / 2) * Q.pUkpoint2[ie].dF);
			dot p11; trans(p11, Q.pUkpoint2[ie].X, Q.pUkpoint2[ie].Y);
			dot p22; trans(p22, Q.pUkpoint2[ie].X, Q.pUkpoint2[ie].Y);
			dot p33; trans(p33, Q.pUkpoint2[ie].X, Q.pUkpoint2[ie].Y);
			dot p44; trans(p44, Q.pUkpoint2[ie].X, Q.pUkpoint2[ie].Y);
			myPen.DeleteObject();
			myPen.CreatePen(PS_SOLID, 2, RGB(0, 0, 255));
			oldPen = pDC->SelectObject(&myPen);
			pDC->MoveTo(p11.x + ex1, p11.y + ey1);
			pDC->LineTo(p33.x - ex1, p33.y - ey1);
			myPen.DeleteObject();
			myPen.CreatePen(PS_SOLID, 2, RGB(0, 255, 0));
			oldPen = pDC->SelectObject(&myPen);
			pDC->MoveTo(p22.x + ex2, p22.y + ey2);
			pDC->LineTo(p44.x - ex2, p44.y - ey2);
			int a = sqrt(ex1 * ex1 + ey1 * ey1);
			int b = sqrt(ex2 * ex2 + ey2 * ey2);

			draw_ellipse(pDC, p11.x, p11.y, a, b);

		}*/
		//遍历未知点,画误差椭圆
		CString nstr;
		nstr.Format(_T("当前误差椭圆倍数为:%f"), ntimes);
		pDC->TextOut(dOrgScaleX + 500 * bili, dOrgScaleY,nstr);
		for (int i = 0; i <Q.iUknum; i++)
		{
			myPen.DeleteObject();
			myPen.CreatePen(PS_SOLID, 1.5, RGB(255, 0, 255));
			oldPen = pDC->SelectObject(&myPen);
			double dStartX, dStartY, dEndX, dEndY;

			//误差椭圆的中心坐标
			dot Org;
			trans(Org, Q.pUkpoint2[i].X, Q.pUkpoint2[i].Y);//坐标转换
			double dOrgX = Org.x ;
			double dOrgY = Org.y ;
			double dScale = bili;


			double dF = Q.pUkpoint2[i].dF * ntimes;
			double dE = Q.pUkpoint2[i].dE * ntimes;
			double dAlfa = Q.pUkpoint2[i].dAlfa+di;

			//绘制短半轴
			dStartX = (dF * sin(dAlfa)) * dScale + dOrgX;
			dStartY = (-dF * cos(dAlfa)) * dScale + dOrgY;
			dEndX = (-dF * sin(dAlfa)) * dScale + dOrgX;
			dEndY = (dF * cos(dAlfa)) * dScale + dOrgY;
			pDC->MoveTo(dStartX, dStartY);
			pDC->LineTo(dEndX, dEndY);
			

			myPen.DeleteObject();
			myPen.CreatePen(PS_SOLID, 1.5, RGB(0, 255, 0));
			oldPen = pDC->SelectObject(&myPen);
			double ex, fy;
			ex = dE;
			fy = 0;
			//转换到长半轴方向上
			dStartX = (ex * cos(dAlfa)
				- fy * sin(dAlfa)
				) * dScale + dOrgX;
			dStartY = (fy * cos(dAlfa)
				+ ex * sin(dAlfa)
				) * dScale + dOrgY;
			pDC->MoveTo(dStartX, dStartY);

			for (int i = 6; i <= 360; i += 6)
			{
				//在坐标轴方向的坐标
				ex = dE * cos((i / 180.0) * PI);
				fy = dF * sin((i / 180.0) * PI);

				//转换到长半轴方向上
				dEndX = (ex * cos(dAlfa)
					- fy * sin(dAlfa)
					) * dScale + dOrgX;
				dEndY = (fy * cos(dAlfa)
					+ ex * sin(dAlfa)
					) * dScale + dOrgY;
				pDC->LineTo(dEndX, dEndY);
			}

			myPen.DeleteObject();
			myPen.CreatePen(PS_SOLID, 1.5, RGB(0, 255, 255));
			oldPen = pDC->SelectObject(&myPen);

			//绘制长半轴
			dStartX = (-dE * cos(dAlfa)) * dScale + dOrgX;
			dStartY = (-dE * sin(dAlfa)) * dScale + dOrgY;
			dEndX = (dE * cos(dAlfa)) * dScale + dOrgX;
			dEndY = (dE * sin(dAlfa)) * dScale + dOrgY;
			pDC->MoveTo(dStartX, dStartY);
			pDC->LineTo(dEndX, dEndY);
			
		}
		
	}
	
	pDC->SelectObject(pOldFont);
	Font.DeleteObject();
	
	pDC->SelectObject(oldPen);
	myPen.DeleteObject();
	/*if ( p != NULL)
	{
		delete[]p;
		p = NULL;
	}
	if (p3 != NULL)
	{
		delete[]p3;
		p3 = NULL;
	}
	if (p2 != NULL)
	{
		delete[] p2;
		p2 = NULL;
	}*/
	ptflag = 1;
}


 

//画椭圆函数
void PICPAINT::OnBnClickedBtty()
{
	tyflag = 1;

	RedrawWindow();
}

//放大函数
void PICPAINT::OnBnClickedBtfd()
{

	ntimes = ntimes * 2;
	tyflag = 1;
	RedrawWindow();

}

//缩小函数
void PICPAINT::OnBnClickedBtsx()
{
	if(ntimes>500)
	ntimes = ntimes / 2;
	tyflag = 1;
	RedrawWindow();
}

//中点画椭圆
void  PICPAINT::draw_ellipse(CDC*& pDC, int x0, int y0, int a, int b)
{
	int x = 0, y = b;


	pDC->SetPixel(x0 + x, y0 + y, RGB(255, 0, 0));
	pDC->SetPixel(x0 - x, y0 + y, RGB(255, 0, 0));
	pDC->SetPixel(x0 + x, y0 - y, RGB(255, 0, 0));
	pDC->SetPixel(x0 - x, y0 - y, RGB(255, 0, 0));

	//上部分
	double d1 = b * b + a * a * (-b + 0.25);
	while (b * b * x < a * a * y)
	{
		if (d1 < 0)
		{
			d1 += b * b * (2 * x + 3);
			x++;
		}
		else
		{
			d1 += (b * b * (2 * x + 3) + a * a * (-2 * y + 2));
			x++; y--;
		}

		pDC->SetPixel(x0 + x, y0 + y, RGB(255, 0, 0));
		pDC->SetPixel(x0 - x, y0 + y, RGB(255, 0, 0));
		pDC->SetPixel(x0 + x, y0 - y, RGB(255, 0, 0));
		pDC->SetPixel(x0 - x, y0 - y, RGB(255, 0, 0));
	}
	//下部分
	double d2 = sqrt((double)b * (x + 0.5)) + sqrt((double)a * (y - 1)) - sqrt((double)a * b);
	while (y > 0)
	{
		if (d2 < 0)
		{
			d2 += b * b * (2 * x + 2) + a * a * (-2 * y + 3);
			x++; y--;
		}
		else
		{
			d2 += a * a * (-2 * y + 3);
			y--;
		}
		//draw_pixel_4(pDC,x0,y0,x,y,color);
		pDC->SetPixel(x0 + x, y0 + y, RGB(255,0, 0));
		pDC->SetPixel(x0 - x, y0 + y, RGB(255,0, 0));
		pDC->SetPixel(x0 + x, y0 - y, RGB(255,0, 0));
		pDC->SetPixel(x0 - x, y0 - y, RGB(255,0, 0));
	}
	
}

void PICPAINT::OnBnClickedBtxz()
{
	di += PI / 12;
		tyflag = 1;
	RedrawWindow();

}

List.h(此部分用于报表制作)

#pragma once
#include "afxdialogex.h"


// LIST 对话框

class LIST : public CDialogEx
{
	DECLARE_DYNAMIC(LIST)

public:
	LIST(CWnd* pParent = nullptr);   // 标准构造函数
	virtual ~LIST();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_DIALOG2 };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedButton1();
	CListCtrl m_list1;
	afx_msg void OnBnClickedBtdis();
	afx_msg void OnBnClickedBtdri();
	afx_msg void OnBnClickedBtmk();
};

List.cpp

(此部分用于报表制作)可根据图片添加对应的控件(list control:可参考站内其他博文学习如何使用)

extern ControlNet Q;

// LIST 消息处理程序


void LIST::OnBnClickedButton1()
{
	CRect rect;

	// 获取列表视图控件的位置和大小   
	m_list1.GetClientRect(&rect);

	// 添加全行选中和栅格  
	m_list1.SetExtendedStyle(m_list1.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
	m_list1.DeleteAllItems();	//清空所有表项
	while (m_list1.DeleteColumn(0));	//清空所有表头

	// 为列表视图控件添加所需要的5列   
	m_list1.InsertColumn(0, _T("点名"), LVCFMT_CENTER, rect.Width() / 5, 0);
	m_list1.InsertColumn(1, _T("X(m)"), LVCFMT_CENTER, rect.Width() / 5, 1);
	m_list1.InsertColumn(2, _T("Y(m)"), LVCFMT_CENTER, rect.Width() / 5, 2);
	m_list1.InsertColumn(3, _T("H(m)"), LVCFMT_CENTER, rect.Width() / 5, 3);
	m_list1.InsertColumn(4, _T("备注"), LVCFMT_CENTER, rect.Width() / 5, 4);

	// 在列表视图控件中插入列表项,并设置列表子项文本   
	for (int i = 0; i < Q.iKnum; i++)
	{
		m_list1.InsertItem(i,Q.pKpoint2[i].strPName);
		CString str;
		str.Format(_T("%f"), Q.pKpoint2[i].X);
		m_list1.SetItemText(i,1,str);
		str.Format(_T("%f"), Q.pKpoint2[i].Y);
		m_list1.SetItemText(i, 2, str);
		str.Format(_T("已知点"));
		m_list1.SetItemText(i, 4, str);
	}
	for (int i = 0,j=Q.iKnum; i < Q.iUknum; i++)
	{
		m_list1.InsertItem(j, Q.pUkpoint2[i].strPName);
		CString str;
		str.Format(_T("%f"), Q.pUkpoint2[i].X);
		m_list1.SetItemText(j, 1, str);
		str.Format(_T("%f"), Q.pUkpoint2[i].Y);
		m_list1.SetItemText(j, 2, str);
		str.Format(_T("未知点"));
		m_list1.SetItemText(j, 4, str);
	}
}


void LIST::OnBnClickedBtdis()
{
	CRect rect;
  
	m_list1.GetClientRect(&rect);
	m_list1.DeleteAllItems();	//清空所有表项
	while (m_list1.DeleteColumn(0));	//清空所有表头
	// 为列表视图控件添加全行选中和栅格  
	m_list1.SetExtendedStyle(m_list1.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
	m_list1.InsertColumn(0, _T("测站"), LVCFMT_CENTER, rect.Width() / 6, 0);
	m_list1.InsertColumn(1, _T("照准"), LVCFMT_CENTER, rect.Width() / 6, 1);
	m_list1.InsertColumn(2, _T("距离(m)"), LVCFMT_CENTER, rect.Width() / 6, 2);
	m_list1.InsertColumn(3, _T("改正数(m)"), LVCFMT_CENTER, rect.Width() / 6, 3);
	m_list1.InsertColumn(4, _T("平差后值(m)"), LVCFMT_CENTER, rect.Width() / 6, 4);
	m_list1.InsertColumn(5, _T("方位角(dms)"), LVCFMT_CENTER, rect.Width() / 6, 5);
	

	for (int i = 0; i < Q.iDisnum; i++)
	{
		m_list1.InsertItem(i, Q.pDis2[i].pStart->strPName);
		m_list1.SetItemText(i, 1, Q.pDis2[i].pEnd->strPName);
		CString str;
		str.Format(_T("%f"), Q.pDis2[i].dDist);
		m_list1.SetItemText(i, 2, str);
		str.Format(_T("%f"), Q.pDis2[i].dS);
		m_list1.SetItemText(i, 3, str);
		str.Format(_T("%f"),Q.pDis2[i].daftDis);
		m_list1.SetItemText(i, 4, str);
		str.Format(_T("%f"), Q.pDis2[i].dAzi);
		m_list1.SetItemText(i, 5, str);
	}


}


void LIST::OnBnClickedBtdri()
{
	CRect rect;

	m_list1.GetClientRect(&rect);
	m_list1.DeleteAllItems();	//清空所有表项
	while (m_list1.DeleteColumn(0));	//清空所有表头
   
	m_list1.SetExtendedStyle(m_list1.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
	m_list1.InsertColumn(0, _T("测站"), LVCFMT_CENTER, rect.Width() / 6, 0);
	m_list1.InsertColumn(1, _T("照准"), LVCFMT_CENTER, rect.Width() / 6, 1);
	m_list1.InsertColumn(2, _T("方向值(dms)"), LVCFMT_CENTER, rect.Width() / 6, 2);
	m_list1.InsertColumn(3, _T("改正数(m)"), LVCFMT_CENTER, rect.Width() / 6, 3);
	m_list1.InsertColumn(4, _T("平差后值(m)"), LVCFMT_CENTER, rect.Width() / 6, 4);
	m_list1.InsertColumn(5, _T("备注"), LVCFMT_CENTER, rect.Width() / 6, 5);

	CString str; int count = Q.iDrinum;
	for (int i = 0,j=0; count!=0; i++,j++)
	{
		m_list1.InsertItem(j, Q.pDri2[i].pStation->strPName);
		m_list1.SetItemText(j, 1, Q.pDri2[i].pObject->strPName);
		str.Format(_T("%f"), Q.pDri2[i].angleObsValue.val);
		m_list1.SetItemText(j, 2, str);
		

		if (Q.pDri2[i].angleObsValue.val)
		{
			str.Format(_T("%f"), Q.pDri2[i].dS);
			m_list1.SetItemText(j, 3, str);
			str.Format(_T("%f"), Q.pDri2[i].daftDriVal);
			m_list1.SetItemText(j, 4, str);
		}
		if (i + 1 < Q.iDrinum && Q.pDri2[i + 1].pStation->ID != Q.pDri2[i].pStation->ID)
		{
			m_list1.InsertItem(j + 1, _T(""));
			j = j + 1;
		}
		count--;
	}







}


void LIST::OnBnClickedBtmk()
{
	CRect rect;
 
	m_list1.GetClientRect(&rect);
	m_list1.DeleteAllItems();	//清空所有表项
	while (m_list1.DeleteColumn(0));	//清空所有表头
  
	m_list1.SetExtendedStyle(m_list1.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
	m_list1.InsertColumn(0, _T("点名"), LVCFMT_CENTER, rect.Width() / 6, 0);
	m_list1.InsertColumn(1, _T("长轴(m)"), LVCFMT_CENTER, rect.Width() / 6, 1);
	m_list1.InsertColumn(2, _T("短轴(m)"), LVCFMT_CENTER, rect.Width() / 6, 2);
	m_list1.InsertColumn(3, _T("长轴方位(dms)"), LVCFMT_CENTER, rect.Width() / 6, 3);
	m_list1.InsertColumn(4, _T("点位中误差(m)"), LVCFMT_CENTER, rect.Width() / 6, 4);
	m_list1.InsertColumn(5, _T("备注"), LVCFMT_CENTER, rect.Width() / 6, 5);

	for (int i = 0; i < Q.iUknum; i++)
	{
		m_list1.InsertItem(i, Q.pUkpoint2[i].strPName);
		CString str;
		str.Format(_T("%f"), Q.pUkpoint2[i].dE);
		m_list1.SetItemText(i, 1, str);
		str.Format(_T("%f"), Q.pUkpoint2[i].dF);
		m_list1.SetItemText(i, 2, str);
		double dalfa;
		dalfa = Q.pUkpoint2[i].dAlfa * 180 / PI;
		if (dalfa > 360)dalfa -= 360;
		if (dalfa < 0)dalfa += 180;
		str.Format(_T("%f"), dalfa);
		m_list1.SetItemText(i, 3, str);
		str.Format(_T("%f"), Q.pUkpoint2[i].dMx);
		m_list1.SetItemText(i, 4, str);
	}

}

直方图绘制.h

#pragma once
#include "afxdialogex.h"
#include"CLPCDlg.h"

// ZFT 对话框

class ZFT : public CDialogEx
{
	DECLARE_DYNAMIC(ZFT)

public:
	ZFT(CWnd* pParent = nullptr);   // 标准构造函数
	virtual ~ZFT();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_DIALOG3 };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnPaint();
};

直方图绘制.cpp

(可参考图片添加对应的控件:picture control)

// ZFT.cpp: 实现文件
//

#include "pch.h"
#include "CLPC.h"
#include "afxdialogex.h"
#include "ZFT.h"
#include"sqz.h"


// ZFT 对话框

IMPLEMENT_DYNAMIC(ZFT, CDialogEx)

ZFT::ZFT(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG3, pParent)
{

}

ZFT::~ZFT()
{
}

void ZFT::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(ZFT, CDialogEx)
	ON_WM_PAINT()
END_MESSAGE_MAP()


// ZFT 消息处理程序
extern ControlNet Q;

void ZFT::OnPaint()
{
	
	CPaintDC pDC(this); // device context for painting
					   // TODO: 在此处添加消息处理程序代码
					   // 不为绘图消息调用 CDialogEx::OnPaint()
	CWnd* pWin = GetDlgItem(IDC_STATIC);//获取Picture控件的指针
	CRect rect;
	pWin->GetClientRect(rect);//把控件的长宽、坐标等信息保存在rect里
	//CDC* pDC = pWin->GetDC();//获取该控件的画布

	CBrush brush1(HS_BDIAGONAL, RGB(96, 192, 255));
	CBrush brush2(HS_FDIAGONAL, RGB(96, 192, 255));
	CPen pen(PS_INSIDEFRAME, 2, RGB(96, 192, 255));

	int n = 5;//定义有五个区间
	int width = rect.Width() / n+1;//一个区间的宽度

	int s[] = { 0,0,0,0,0 };//区间置初值
	double* p;
	p = new double[Q.iUknum];
	double min = 999;
	double max = -999;
	double times = 10 / Q.pUkpoint2[1].dMk;
	for (int io = 0; io < Q.iUknum; io++)
	{

		p[io] = Q.pUkpoint2[io].dMk*times;
		if (min > p[io])
			min = p[io];
		if (max < p[io])
			max = p[io];
	}
	
	double dx = max - min;
	for (int i = 0; i < Q.iUknum; i++)
	{
		double td = dx / 10;

		if      (p[i] <  min + 2 * td && p[i]>=min)    s[0]++;
		else if (p[i] <  min + 4 * td&&  p[i]>=min + 2 * td  ) s[1]++;
		else if (p[i] <  min + 6 * td&&  p[i]>= min + 4 * td ) s[2]++;
		else if (p[i] <  min + 8 * td&&  p[i]>= min + 6 * td ) s[3]++;
		else s[4]++;
	}//统计各区间个数
	int max_s = s[0];
	for (int i = 0; i < n; i++)
		if (max_s < s[i]) max_s = s[i];//找出个数最多的区间
	int per_Height = rect.Height()*2/3 / max_s;//算出一个代表的矩形高度

	CRect ps_rect(rect);	//直方图的矩形
	CRect str_rect(rect);	//各区间注释矩形,用于定位
	ps_rect.right = ps_rect.left+5 + width;
	CBrush* oldBrush = pDC.SelectObject(&brush1);//保存旧的画刷设置
	CPen* oldPen = pDC.SelectObject(&pen);//保存旧的画笔设置
	CString str[5] = { _T("<2▲Mk"),_T("2-4▲Mk"),_T("4-6▲Mk"),_T("6-8▲Mk"),_T(">8▲Mk") };//将每个区间的注释先存储
	for (int i = 0; i < n; i++)
	{
		ps_rect.top = ps_rect.bottom - per_Height * s[i] - 2;	//该区间的高度
		if (i % 2)  pDC.SelectObject(&brush2);
		else pDC.SelectObject(&brush1);	//每隔一个区间用不同的斜线,左斜或右斜
		pDC.Rectangle(ps_rect);	//绘制矩形
		if (s[i] > 0)
		{
			CString str1;
			str1.Format(_T("%d个"), s[i]);//设置str1的内容
			pDC.DrawText(str1, ps_rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形中间显示
		}
		str_rect = ps_rect;
		str_rect.bottom = ps_rect.bottom + 30;
		str_rect.top = ps_rect.bottom + 12;
		pDC.DrawText(str[i], str_rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
		ps_rect.OffsetRect(width, 0);//移动矩形框的位置,水平方向移动width
	}
	pDC.SelectObject(&oldBrush);
	pDC.SelectObject(&oldPen);	//将画刷,画笔设置回原来的样子
}

Function.h(通用的一些计算方程)

#pragma once
class Function
{
};

const double EPSILON = 1.0E-10;
const double PI = 3.1415926535897932;

double Dis(double X1, double Y1, double X2, double Y2);
double Dis(double X1, double Y1, double Z1,double X2, double Y2, double Z2);
double Azimuth(const double& X1, const double& Y1,const double& X2, const double& Y2);
double DmS(double x);
double DeG(double x);

int sgn(double x);
int splitstrarr(CString str, char split, CStringArray& astr);

Function.cpp

#include "pch.h"
#include "Function.h"

double Dis(double X1, double Y1, double X2, double Y2)
{
	double d;
	d = sqrt((X2 - X1) * (X2 - X1) + (Y2 - Y1) * (Y2 - Y1));
	return d;
}
double Dis(double X1, double Y1, double Z1,
	double X2, double Y2, double Z2)
{
	double d;
	d = sqrt((X2 - X1) * (X2 - X1) + (Y2 - Y1) * (Y2 - Y1) + (Z2 - Z1) * (Z2 - Z1));
	return d;
}

double  Azimuth(const double& X1, const double& Y1,
	const double& X2, const double& Y2)
{
	double dx, dy;
	dx = X2 - X1;
	dy = Y2 - Y1 + EPSILON;
	return PI - sgn(dy) * PI / 2 - atan(dx / dy);
}

int sgn(double x)
{
	if (x >= 0)
		return(1);//非负则返回1
	else
		return(-1);//
}
int splitstrarr(CString str, char split, CStringArray& astr)
{


	int stapos = 0;
	int num = str.Find(split, stapos);
	astr.RemoveAll();//连续计算时初始化astr

	while (num != -1)
	{
		CString sTmp = str.Mid(stapos, num - stapos);
		astr.Add(sTmp);
		stapos = num + 1;
		num = str.Find(split, stapos);
	}//将/n删掉重新存放在astr中

	CString tmp = str.Right(str.GetLength() - stapos);
	if (!tmp.IsEmpty())
		astr.Add(tmp);
	return astr.GetSize();//返回行数
}

double DmS(double x)
{
	int iDeg, iMin;
	double dSec;

	iDeg = int(x + EPSILON);//度//加一个很小的数,以防止取整时的出错
	iMin = int((x- iDeg) * 100 + EPSILON);//分
	dSec = ((x - iDeg) * 100 - iMin) * 100;//秒

	return iDeg + (double)iMin / 60 + dSec / 3600;

}
double DeG(double x)
{
	int iDeg, iMin;
	double dSec;
	double dTmp;

	iDeg = int(x + EPSILON);//整数部分度
	dTmp = (x - iDeg) * 60;//小数部分转换成分
	iMin = int(dTmp + EPSILON);//取分的整数部分
	dSec = (dTmp - iMin) * 60;//截取秒

	return iDeg + (double)iMin / 100 + dSec / 10000;
}

剩余部分类(如Cmatrix)的设计借鉴并修改了实验课程以及书中的例子代码里完备的结构,由于篇幅过长就暂不展示。

  • 14
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Z7ian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值