【MFC】测边网平差计算

1、题目

有测边网如下图所示。网中A、B、C、D为已知点,P1、P2、P3、P4为待定点,现用某测距仪观测了13条边长,测距精度 = 3mm+1*10-6s,起算数据及观测边长见下,按间接平差法求待定点坐标平差值及其中误差。
在这里插入图片描述
起算数据

边长 坐标方位角
XYm °      ′      ″
A53743.13661003.8267804.558 138   00   08.6
B47943.00266225.854
C40049.22953782.7907889.381 113   19   50.8
D36924.72861027.086

观测数据

编号边观测值(m) 编号 边观测值(m)编号 边观测值(m)
15760.70568720.16211 5487.073
25187.34275598.57012 8884.589
37838.88087494.88113 7228.367
45483.15897493.323
55731.788105438.380

2、分析及源码

由题意有n=13,t=8,选待定点P1,P2,P3,P4的坐标为参数。
P1的近似坐标由己知点A、B和观测边S1,S2交会计算得。同理,由P1、A、S3、S4交会计算P2的近似坐标;由P1、P2、S10、S5交会计算P3的近似坐标;由P1、P3、S12、S9交会计算P4的近似坐标。
点击这里查看具体解题过程
这里不过多叙述解题过程,需要的同学请点击上方链接,我们具体讲讲程序怎么写。
首先,我们定义如下类:

  • 点类:存储点的点号,坐标,以及判断该点是否已知
  • 边观测值类:用来推算近似坐标,存储三角形的三个点以及三边长度
  • 距离类:起点和终点,以及两点间的距离
class CLevelPoint//点类															
{
public:
	CLevelPoint(void);
	~CLevelPoint(void);
public:
	CString strID;//点号
	double x;//x坐标
	double y;//y坐标
	bool flag;//判断该点是否已知,1为已知,0为未知
};
class CdHObs//边观测值类
{
public:
	CdHObs(void);
	~CdHObs(void);
public:
	CLevelPoint *PointOne, *PointTwo,*PointThree;//三角形三个点
	double S1,S2,S3;//路线长度
};
class CDistance//距离类
{
public:
	CDistance(void);
	~CDistance(void);
public:
	CLevelPoint *StartPoint, *EndPoint;//起点和终点
	double distance;//两点间距离
};

CLevelPoint::CLevelPoint(void)
{
	strID = _T("");
	x = 0;
	y = 0;
	flag = 0;
}
CLevelPoint::~CLevelPoint(void)
{

}
CdHObs::CdHObs(void)
{
	S1 = 0;
	S2 = 0;
	S3 = 0;
}
CdHObs::~CdHObs(void)
{

}
CDistance::CDistance(void)
{
	distance = 0;
}
CDistance::~CDistance(void)
{

}

然后声明存储数据的数组,以及用得到的各种方法和计算平差时用得到的变量。

{
public:
	CTrilateralNets(void);
	~CTrilateralNets(void);
	
private:
CLevelPoint *pUnknownPoint;//未知点数组
	int iUnknownPointCount;//未知点个数
	CLevelPoint *pKnownPoint;//已知点数组
	int iKnownPointCount;//已知点个数
	CdHObs *pdHObs;//边观测值数组
	int idHObsCount;//边观测值个数
	CDistance *pDistance;//边长类
	int iDistanceCount;//边长个数

private:
	CLevelPoint *SearchKnownPointUsingID(CString strID);//根据点号查找已知点,返回该点指针
	CLevelPoint *SearchUnknownPointUsingID(CString strID);//根据点号查找未知点,返回该点指针
	CLevelPoint *SearchPointUsingID(CString strID);//根据点号查找点,返回该点指针

private:
	CString *CTrilateralNets::SplitString(CString str, char split, int iSubStrs);//字符串分割函数

public:
	void SetKnownPointSize(int size);//设置已知点数组大小
	void SetUnknownPointSize(int size);//设置未知点数组大小
	void SetdHObsSize(int size);//设置边观测值数组大小
	void SetDistanceSize(int size);//设置距离值数组大小
	

public:
	BOOL LoadObsData(const CString& strFileName);//导入观测数据函数
	void CalculateApproximateH(void);//求待测点近似坐标
	void RigorousAdjust(const CString& strFileName);//平差计算主函数

public:
	void FormErrorEquation();//组成误差方程
	void CTrilateralNets::Weight();//组成权阵
	void EquationCompute();//计算法方程
	void Accuracy_Assessment();//精度评定
	void OutMatrixToFile(const CMatrix& mat, CStdioFile& SF);//把矩阵输出到文件中

private:
	/*l为常数项矩阵,B为系数矩阵,P为权阵,BT为B的转置,NBB为法方程系数阵,NBBl为NBB的逆矩阵
	x为未知数近似值的改正数,v为观测值改正数,vT为v的转置,r为vtPv,Qxx为协因数阵*/
	CMatrix l, B, P, BT, NBB, NBBl, x, v, vT, r, Qxx;
	double r0;//r0为单位权中误差
	double *Qx = new double[iUnknownPointCount];//*Qx为未知点高程中误差
};
CTrilateralNets::CTrilateralNets(void)
{

}
CTrilateralNets::~CTrilateralNets(void)
{
	//释放动态数组内存
	if (pUnknownPoint != NULL)
	{
		delete[] pUnknownPoint;
		pUnknownPoint = NULL;
	}
	if (pKnownPoint != NULL)
	{
		delete[] pKnownPoint;
		pKnownPoint = NULL;
	}
	if (pdHObs != NULL)
	{
		delete[] pdHObs;
		pdHObs = NULL;
	}
}
//设置已知点数组大小
void CTrilateralNets::SetKnownPointSize(int size)
{
	pKnownPoint = new CLevelPoint[size];//已知点数组
}
//设置未知点数组大小
void CTrilateralNets::SetUnknownPointSize(int size)
{
	pUnknownPoint = new CLevelPoint[size];//已知点数组
}
//设置边观测值数组大小
void CTrilateralNets::SetdHObsSize(int size)
{
	pdHObs = new CdHObs[size];
}
//设置边长总数数组大小
void CTrilateralNets::SetDistanceSize(int size)
{
	pDistance = new CDistance[size];
}
//根据点号从已知点数组中找到控制点,并返回该点指针
CLevelPoint *CTrilateralNets::SearchKnownPointUsingID(CString strID)
{
	for (int i = 0; i < iKnownPointCount; i++)
	{
		if (strID == pKnownPoint[i].strID)//当点号与已知点点号相同时,返回该点的指针
			return &pKnownPoint[i];
	}
	return NULL;
}
//根据点号从未知点数组中找到控制点,并返回该点指针
CLevelPoint *CTrilateralNets::SearchUnknownPointUsingID(CString strID)
{
	for (int i = 0; i < iUnknownPointCount; i++)
	{
		if (strID == pUnknownPoint[i].strID)//当点号与已知点点号相同时,返回该点的指针
			return &pUnknownPoint[i];
	}
	return NULL;
}
//根据点号从未知点和已知点中找到控制点,并返回该点指针
CLevelPoint *CTrilateralNets::SearchPointUsingID(CString strID)
{
	CLevelPoint *pCP = NULL;//定义一个空指针
	pCP = SearchKnownPointUsingID(strID);//试探该点是否已知
	if (pCP == NULL)//如果pCP为空,则pCP为未知点
		pCP = SearchUnknownPointUsingID(strID);
	return pCP;
}
//字符串分割函数
CString *CTrilateralNets::SplitString(CString str, char split, int iSubStrs)
{
	int iPos = 0;//分割符位置
	int iNums = 0;//分割符的总数
	CString strTemp = str;
	CString strRight;
	//计算子字符串的数量
	while (iPos != -1)
	{
		iPos = strTemp.Find(split);
		if (iPos == -1)
			break;
		strRight = strTemp.Mid(iPos + 1, str.GetLength());
		strTemp = strRight;
		iNums++;
	}
	if (iNums == 0)//没有找到分隔符
	{
		//子字符串数就是字符串本身
		iSubStrs = 1;
		return NULL;
	}
	//子字符串数组
	iSubStrs = iNums + 1;//子字符串的数量=分割符数量+1
	CString* pStrSplit;
	pStrSplit = new CString[iSubStrs];
	strTemp = str;
	CString strLeft;
	for (int i = 0; i < iNums; i++)
	{
		iPos = strTemp.Find(split);
		//左子串
		strLeft = strTemp.Left(iPos);
		//右子串
		strRight = strTemp.Mid(iPos + 1, strTemp.GetLength());
		strTemp = strRight;
		pStrSplit[i] = strLeft;
	}
	pStrSplit[iNums] = strTemp;
	return pStrSplit;
}
//导入观测数据函数
BOOL CTrilateralNets::LoadObsData(const CString& strFileName)
{
	CStdioFile sf;//创建文件对象
				  //以读的方式打开文件
	if (!sf.Open(strFileName, CFile::modeRead))
		return false;
	CString strLine;
	BOOL bEOF = sf.ReadString(strLine);//读取第一行,已知点个数

	iKnownPointCount = _ttoi(strLine);//存取已知点个数
	SetKnownPointSize(iKnownPointCount);//设置已知点数组大小
										//开始读取已知点数据
	int n = 0;
	for (int i = 0; i < iKnownPointCount; i++)//根据已知点个数,读取已知点数据
	{
		sf.ReadString(strLine);
		CString *pstrData = SplitString(strLine, ',', n);
		pKnownPoint[i].strID = pstrData[0];//存取已知点点号
		pKnownPoint[i].x = _tstof(pstrData[1]);//存取已知点x坐标
		pKnownPoint[i].y = _tstof(pstrData[2]);//存取已知点y坐标
		pKnownPoint[i].flag = 1;//标记为已知点
		delete[] pstrData;
		pstrData = NULL;
	}
	//开始读取未知点数据
	sf.ReadString(strLine);//读取未知点个数
	iUnknownPointCount = _ttoi(strLine);//存取未知点个数
	SetUnknownPointSize(iUnknownPointCount);//设置未知点数组大小
	sf.ReadString(strLine);
	CString *pstrData1 = SplitString(strLine, ',', n);
	//读取并保存未知点点号
	for (int i = 0; i < iUnknownPointCount; i++)//根据未知点个数,读取未知点数据
	{
		pUnknownPoint[i].strID = pstrData1[i];//存取未知点点号
	}
	delete[] pstrData1;
	pstrData1 = NULL;
	//开始读取高差观测值数据
	sf.ReadString(strLine);//读取边观测值个数
	idHObsCount = _ttoi(strLine);//存取边观测值个数
	SetdHObsSize(idHObsCount);//设置边观测值数组大小
							  //读取并保存边观测值数据
	for (int i = 0; i < idHObsCount; i++)
	{
		sf.ReadString(strLine);
		CString *pstrData2 = SplitString(strLine, ',', n);
		pdHObs[i].PointOne = SearchPointUsingID(pstrData2[0]);//存取1点信息
		pdHObs[i].PointTwo = SearchPointUsingID(pstrData2[1]);//存取2点信息
		pdHObs[i].PointThree = SearchPointUsingID(pstrData2[2]);//存取3点信息
		pdHObs[i].S1 = _tstof(pstrData2[3]);//存取12路线长度
		pdHObs[i].S2 = _tstof(pstrData2[4]);//存取13路线长度
		pdHObs[i].S3 = _tstof(pstrData2[5]);//存取23路线长度
		delete[] pstrData2;
		pstrData2 = NULL;
	}
	//开始读取两点间距离
	sf.ReadString(strLine);//读取距离个数
	iDistanceCount = _ttoi(strLine);//存取距离个数
	SetDistanceSize(iDistanceCount);//设置距离数组大小
							  //读取并保存距离数据
	for (int i = 0; i < iDistanceCount; i++)
	{
		sf.ReadString(strLine);
		CString *pstrData3 = SplitString(strLine, ',', n);
		pDistance[i].StartPoint = SearchPointUsingID(pstrData3[0]);//存取1点信息
		pDistance[i].EndPoint = SearchPointUsingID(pstrData3[1]);//存取2点信息
		pDistance[i].distance = _tstof(pstrData3[2]);//存取12距离
		delete[] pstrData3;
		pstrData3 = NULL;
	}

	sf.Close();
	return true;
}
//求待测点近似坐标
void CTrilateralNets::CalculateApproximateH(void)
{
	int i = 0;
	double s = 0, h = 0, a = 0, S = 0;
	for (i = 0; i < 3; i++)
	{
		double dy = 0, dx = 0;
		S = (pdHObs[i].S1*pdHObs[i].S1 + pdHObs[i].S2*pdHObs[i].S2 - pdHObs[i].S3*pdHObs[i].S3)/(2*pdHObs[i].S1);
		s = fabs(S);
		h = sqrt(pdHObs[i].S2*pdHObs[i].S2 - s*s);
		if (pdHObs[i].PointOne->x > pdHObs[i].PointTwo->x)
		{
			dy = pdHObs[i].PointTwo->y - pdHObs[i].PointOne->y;
			dx = pdHObs[i].PointTwo->x - pdHObs[i].PointOne->x;
		}
		else
		{
			dy = pdHObs[i].PointOne->y - pdHObs[i].PointTwo->y;
			dx = pdHObs[i].PointOne->x - pdHObs[i].PointTwo->x;
		}
		a = atan(dy / dx) * 180 / pi;
		if (dx > 0)
			a = dy > 0 ? a : a + 360;
		else
			a = a + 180;
		pdHObs[i].PointThree->x = pdHObs[i].PointOne->x + s*cos(a*pi / 180) + h*cos((a+90)*pi / 180);
		pdHObs[i].PointThree->y = pdHObs[i].PointOne->y + s*sin(a*pi / 180) + h*sin((a+90)*pi / 180);
	}
	double dy = 0, dx = 0;
	S = (pdHObs[i].S1*pdHObs[i].S1 + pdHObs[i].S2*pdHObs[i].S2 - pdHObs[i].S3*pdHObs[i].S3) / (2 * pdHObs[i].S1);
	s = fabs(S);
	h = sqrt(pdHObs[i].S2*pdHObs[i].S2 - s*s);
	if (pdHObs[i].PointOne->x > pdHObs[i].PointTwo->x)
	{
		dy = pdHObs[i].PointTwo->y - pdHObs[i].PointOne->y;
		dx = pdHObs[i].PointTwo->x - pdHObs[i].PointOne->x;
	}
	else
	{
		dy = pdHObs[i].PointOne->y - pdHObs[i].PointTwo->y;
		dx = pdHObs[i].PointOne->x - pdHObs[i].PointTwo->x;
	}
	a = atan(dy / dx) * 180 / pi;
	if (dx > 0)
		a = dy > 0 ? a : a + 360;
	else
		a = a + 180;
	pdHObs[i].PointThree->x = pdHObs[i].PointOne->x + s*cos(a*pi / 180) - h*cos((a + 90)*pi / 180);
	pdHObs[i].PointThree->y = pdHObs[i].PointOne->y + s*sin(a*pi / 180) - h*sin((a + 90)*pi / 180);
}
//组成误差方程
void CTrilateralNets::FormErrorEquation()
{
	l.SetSize(iDistanceCount, 1);//设置常数项l的大小
	for (int i = 0; i < iDistanceCount; i++)
	{
		double l0 = sqrt(pow(pDistance[i].EndPoint->x - pDistance[i].StartPoint->x, 2)
			+ pow(pDistance[i].EndPoint->y - pDistance[i].StartPoint->y, 2));
		l(i, 0) = pDistance[i].distance - l0;//计算l中各项的值
	}
	B.SetSize(iDistanceCount, iUnknownPointCount*2);//设置系数B的大小
	for (int i = 0; i < iDistanceCount; i++)
	{
		for (int j = 0; j < iUnknownPointCount*2; j++)
		{
			B(i, j) = 0;//先给B初值
		}
	}
	for (int i = 0; i < iDistanceCount; i++)
	{
		double c = 0, d = 0;
		double S0 = sqrt(pow(pDistance[i].EndPoint->x - pDistance[i].StartPoint->x, 2)
			+ pow(pDistance[i].EndPoint->y - pDistance[i].StartPoint->y, 2));
		c = (pDistance[i].EndPoint->x - pDistance[i].StartPoint->x) / S0;
		d = (pDistance[i].EndPoint->y - pDistance[i].StartPoint->y) / S0;
		int a = 0;
		for (int j = 0; j < iUnknownPointCount; j++)
		{
			if (pDistance[i].StartPoint->strID == pUnknownPoint[j].strID)
			{
				B(i, a) = -c;
				B(i, a + 1) = -d;
				break;
			}
			a += 2;
		}
		a = 0;
		for (int j = 0; j < iUnknownPointCount; j++)
		{
			if (pDistance[i].EndPoint->strID == pUnknownPoint[j].strID)
			{
				B(i, a) = c;
				B(i, a + 1) = d;
				break;
			}
			a += 2;
		}
	}
}
//组成权阵
void CTrilateralNets::Weight()
{
	P.SetSize(iDistanceCount, iDistanceCount);//设置权阵P的大小
	double a = 0.003, b = 0.000001;
	for (int i = 0; i < iDistanceCount; i++)
	{
		for (int j = 0; j < iDistanceCount; j++)
		{
			P(i, j) = 0;//先给P初值
		}
	}
	for (int i = 0; i < iDistanceCount; i++)
	{
		double ms = a + b*pDistance[i].distance;
		P(i, i) = 0.01*0.01 / (ms*ms);
	}
}
//组成法方程
void CTrilateralNets::EquationCompute()
{
	BT = ~B;//计算B的转置
	NBB = BT*P*B;//计算NBB
	NBBl = NBB.Inv();//计算NBB的逆矩阵
	x = -1 * NBBl*BT*P*l;//计算x

}
//精度评定
void CTrilateralNets::Accuracy_Assessment()
{
	v = B*x + l;//计算改正数v
	vT = ~v;
	r = vT*P*v;
	r0 = sqrt(r(0, 0)*1.0 / (iDistanceCount - iUnknownPointCount * 2));//计算单位权中误差r0
	Qxx = NBB.Inv();//计算协因数阵
	int a = 0;
	for (int i = 0; i < iUnknownPointCount; i++)//计算未知点高程中误差
	{
		Qx[i] = sqrt(pow(sqrt(Qxx(a, a))*r0, 2) + pow(sqrt(Qxx(a + 1, a + 1))*r0, 2));
		a += 2;
	}
}
//把矩阵输出到文件中
void CTrilateralNets::OutMatrixToFile(const CMatrix& mat, CStdioFile& SF)
{
	CString strLine, strTmp;
	for (int i = 0; i < mat.Row(); i++)
	{
		strLine.Empty();
		for (int j = 0; j < mat.Col(); j++)
		{
			strTmp.Format(_T("%8.4f"), mat(i, j));
			strLine = strLine + strTmp;
		}
		SF.WriteString(strLine + _T("\r\n"));
	}
}
void CTrilateralNets::RigorousAdjust(const CString& strFileName)
{
	//开始输出平差结果
	CStdioFile SF;
	CString strLine;
	setlocale(LC_ALL, "");
	if (!SF.Open(strFileName, CFile::modeCreate | CFile::modeWrite))
		return;
	CalculateApproximateH();
	FormErrorEquation();
	Weight();
	EquationCompute();
	Accuracy_Assessment();
	SF.WriteString(_T("——测边网间接平差结果——\n"));
	strLine.Format(_T("已知点个数:%d\n"), iKnownPointCount);
	SF.WriteString(strLine);
	strLine.Format(_T("已知点点号及坐标:\n"));
	SF.WriteString(strLine);
	for (int i = 0; i < iKnownPointCount; i++)
	{
		strLine.Format(_T("%s,%.4lf,%.4lf\n"), pKnownPoint[i].strID, pKnownPoint[i].x,pKnownPoint[i].y);
		SF.WriteString(strLine);
	}

	strLine.Format(_T("未知点个数:%d\n"), iUnknownPointCount);
	SF.WriteString(strLine);
	SF.WriteString(_T("未知点近似坐标:\r\n"));
	for (int i = 0; i < iUnknownPointCount; i++)
	{
		strLine.Format(_T("%s,%.4lf,%.4lf\n"), pUnknownPoint[i].strID, pUnknownPoint[i].x, pUnknownPoint[i].y);
		SF.WriteString(strLine);
	}
	SF.WriteString(_T("\r\n"));

	SF.WriteString(_T("B矩阵:\r\n"));
	OutMatrixToFile(B, SF);
	SF.WriteString(_T("常数项l矩阵(dm):\r\n"));
	OutMatrixToFile(l*10, SF);

	SF.WriteString(_T("\r\nP矩阵:\r\n"));
	OutMatrixToFile(P, SF);

	SF.WriteString(_T("N矩阵:\r\n"));
	OutMatrixToFile(NBB, SF);
	SF.WriteString(_T("N矩阵的逆矩阵:\r\n"));
	OutMatrixToFile(NBBl, SF);
	SF.WriteString(_T("x矩阵:\r\n"));
	OutMatrixToFile(x, SF);
	SF.WriteString(_T("\r\n"));

	SF.WriteString(_T("边观测值改正数(dm):\r\n"));
	OutMatrixToFile(v*10.0, SF);
	strLine.Format(_T("单位权中误差:%.2lf(dm)\r\n"), r0*10.0);
	SF.WriteString(strLine);
	SF.WriteString(_T("Qxx矩阵:\r\n"));
	OutMatrixToFile(Qxx, SF);
	SF.WriteString(_T("\r\n"));


	SF.WriteString(_T("未知点坐标中误差(dm):\r\n"));
	for (int i = 0; i < iUnknownPointCount; i++)
	{
		strLine.Format(_T("%.2lf\n"), (double)(Qx[i] * 10));
		SF.WriteString(strLine);
	}
	SF.WriteString(_T("\r\n"));

	SF.WriteString(_T("边长平差值(m):\r\n"));
	for (int i = 0; i < iDistanceCount; i++)
	{
		strLine.Format(_T("%.4lf\n"), pDistance[i].distance + v(i, 0));
		SF.WriteString(strLine);
	}
	SF.WriteString(_T("\r\n"));
	SF.WriteString(_T("坐标平差值(m):\r\n"));
	int a = 0;
	for (int i = 0; i < iUnknownPointCount; i++)
	{
		strLine.Format(_T("%s,%.4lf,%.4lf\n"), pUnknownPoint[i].strID, pUnknownPoint[i].x + x(a,0), pUnknownPoint[i].y + x(a+1,0));
		a += 2;
		SF.WriteString(strLine);
	}
	SF.WriteString(_T("\r\n"));
	SF.Close();
}

MFC的窗口比较简陋,如下图。
在这里插入图片描述
文件读取为Button1,平差计算为Button2。我这里写的方法是在文件读取时就进行了平差计算并输出结果,而在平差计算时就是打开输出的结果文件。

void CTrilateralNetsDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData(TRUE);
	CFileDialog dlgFile(TRUE, _T("txt"), NULL,
		OFN_EXPLORER, _T("(文本文件)|*.dat")); //创建打开文件对话框
	if (dlgFile.DoModal() == IDCANCEL) return;//如果选择取消按钮,则退出
	CString strFileName = dlgFile.GetPathName();//获取选择的文件的名称

	CTrilateralNets la;
	la.LoadObsData(strFileName);
	la.RigorousAdjust(_T("测边网间接平差计算结果.txt"));

	setlocale(LC_ALL, "");	//设置语言环境
	CStdioFile sf;  //创建文件对象

					//以读的形式打开文件,如果打开失败则返回
	if (!sf.Open(strFileName, CFile::modeRead)) return;

	CString strLine;
	strFileContent.Empty();
	BOOL bEOF = sf.ReadString(strLine);//读取第一行
	strFileContent += strLine + _T("\r\n");
	while (bEOF)
	{
		bEOF = sf.ReadString(strLine);
		if (bEOF)
			strFileContent += strLine + _T("\r\n");
	}
	sf.Close();
	UpdateData(FALSE);//关闭文件
}


void CTrilateralNetsDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData(TRUE);
	CString strFileName = (_T("测边网间接平差计算结果.txt"));//获取选择的文件的名称

	setlocale(LC_ALL, "");	//设置语言环境
	CStdioFile sf;  //创建文件对象

	//以读的形式打开文件,如果打开失败则返回
	if (!sf.Open(strFileName, CFile::modeRead)) return;

	CString strLine;
	strFileOutput1.Empty();
	BOOL bEOF = sf.ReadString(strLine);//读取第一行
	strFileOutput1 += strLine + _T("\r\n");
	while (bEOF)
	{
		bEOF = sf.ReadString(strLine);
		if (bEOF)
			strFileOutput1 += strLine + _T("\r\n");
	}
	sf.Close();
	UpdateData(FALSE);//关闭文件
}

读取的文件格式如下:
在这里插入图片描述
输出的文件格式如下(只截取了部分):
在这里插入图片描述
文中用到的计算矩阵的代码已上传,需要的自行下载。

3、随笔

写的稍微有些简陋,分享出来给大家学习讨论。这是一年前做课设时写的,也不知道会不会有学弟学妹看到,哈哈,以后有时间好好学习学习,然后把绘图功能完善一下。

  • 22
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

木灬唯紫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值