c++水准网间接平差法平差
环境:vs2017+qt+eigen-3.3.8矩阵库
P1点为已知点,高程100米
文件数据格式
7,4,100.00
1,5,20.344,4
1,2,10.286,4.7
5,2,-10.069,3.1
2,3,-4.954,3.5
3,5,15.020,3.2
3,4,1.227,4.4
4,5,13.801,3.8
ui界面
代码
头文件
#pragma once
#include <QtWidgets/QWidget>
#include "ui_leveling_network.h"
class leveling_network : public QWidget
{
Q_OBJECT
public:
leveling_network(QWidget *parent = nullptr);
int compute();
~leveling_network();
private:
Ui::leveling_networkClass ui;
};
mian文件
#include "leveling_network.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
leveling_network w;
w.show();
return a.exec();
}
计算文件leveling_network.cpp
#include "leveling_network.h"
#include<qpushbutton.h>
#include<qmessagebox.h>
#include <QTextEdit>
#include <QStringList>
#include<qdebug.h>
#include<cmath>
#include<Eigen/Dense>
#include<stdio.h>
#include<iostream>
#include <QFileDialog> //文件对话框
#include <fstream>
#define PI acos(-1)
using namespace std;
struct datas//侧段数据结构体
{
int b;//后视点站号
int f;//前视点站号
double hd;//高度差=前视点高程-后视点高程
double ds;//距离
};
leveling_network::leveling_network(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
//读取文件计算并输出按钮的槽函数
connect(ui.pushButton, &QPushButton::clicked, this, [=] {
compute();
});
//退出功能
connect(ui.pushButton_3, &QPushButton::clicked, this, &QWidget::close);
}
//
//计算函数
int leveling_network::compute()
{
int n, i, j, t;//往测和返侧数
datas ss[100];//声明数据结构体
double h1;//起始点高程
// 文件对话框
QString in_path = QFileDialog::getOpenFileName(this, "OPEN", "../", "TXT(*.txt)");//设置文件路径 文件格式
if (in_path.isEmpty() == false) {//路径正确
//创建文件对象 并且关联起来
QFile file(in_path);
bool isok = file.open(QIODevice::ReadOnly);//利用只读模式打开文件
if (isok) {//打开成功
QString text = file.readLine();//读取第一行
text.replace("\n", "\0");//将换行符剔除
QStringList list = text.split(',');
n = list[0].toInt();//观测值个数
t = list[1].toInt();//未知点高程个数
h1 = list[2].toDouble();//已知点高程
i = 0;
//行循环读取 file.readLine()
while (file.atEnd() == false) {
QString text = file.readLine();//换行符号也是读取的
text.replace("\n", "\0");//将换行符剔除
QStringList list1 = text.split(',');//结构体数组赋值
ss[i].b = list1[0].toInt();
ss[i].f = list1[1].toInt();
ss[i].hd = list1[2].toDouble();
ss[i].ds = list1[3].toDouble();
i++;
}
file.close();
if (i != n) { QMessageBox::critical(this, "warning", "data error"); file.close(); return 0; }
}
else {
QMessageBox::critical(this, "warning", "Failed to open observation data file, exiting function"); file.close(); return 0;
}
}else {
QMessageBox::critical(this, "warning", "The observation data file path is empty"); return 0;
}
double H[100] ;//点高程近似值(包括第一个已知点)
H[0] = h1;
j = 0;
for (i = 1; i <=t; i++) {
for (j = 0; i < n; j++) {
if (H[ss[j].b-1] != NULL && ss[j].f == i + 1)
{
H[i] = H[ss[j].b-1] + ss[j].hd;
break;
}
else if (ss[j].b == i + 1 && H[ss[j].f-1] != NULL) {
H[i] = H[ss[j].f-1] - ss[j].hd;
break;
}
}
}
//定义矩阵
Eigen::MatrixXd l = Eigen::MatrixXd::Zero( n , 1);//常数向量
Eigen::MatrixXd L = Eigen::MatrixXd::Zero(n , 1);//观测值近似阵
Eigen::MatrixXd B = Eigen::MatrixXd::Zero(n , t);//系数阵
Eigen::MatrixXd P = Eigen::MatrixXd::Zero(n, n);//权阵
Eigen::MatrixXd X = Eigen::MatrixXd::Zero(t, 1);//参数近似值矩阵
//第一点为已知点,参数矩阵第一个值从第二个高程点开始
for (i = 0; i < t; i++) X(i, 0)= H[i + 1];参数近似值矩阵赋值
//B矩阵赋值
for (i = 0; i < n; i++) {
if (ss[i].b == 1) {
L(i, 0) = X(ss[i].f - 2, 0) - h1;
B(i, ss[i].f - 2) = 1;
}
else if (ss[i].f == 1) {
L(i, 0) =h1- X(ss[i].b - 2, 0) ;
B(i, ss[i].b - 2) = -1;
}
else {
L(i, 0) = X(ss[i].f - 2, 0) - X(ss[i].b - 2, 0);
B(i, ss[i].b - 2) = -1;
B(i, ss[i].f - 2) = 1;
}
P(i, i) = 1 / ss[i].ds;//权阵赋值
l(i, 0) = ss[i].hd - L(i, 0);//l向量赋值
}
//矩阵解算
Eigen::MatrixXd NBB(t, t);
Eigen::MatrixXd x(t,1);
Eigen::MatrixXd v( n , 1);
Eigen::MatrixXd L_( n, 1);
NBB = B.transpose()*P*B;
x = NBB.inverse()*B.transpose()*P*l;
v = B * x - l;
Eigen::MatrixXd zh(1, 1);//从一行一列矩阵提取单位权中误差所需数字
zh = v.transpose()*P*v;
double jm = zh(0, 0);
double o = sqrt(jm/(n-t));//单位权中误差
//创建文件并输出
QString filePath = QFileDialog::getSaveFileName(this, "Save As", "E:/output2", tr("TXT(*.txt)"));
string path = filePath.toStdString();//将qstring转换为string
ofstream out_file(path);
if (out_file.is_open()) {
out_file << "单位权中误差为(单位米):" << std::endl;
out_file << to_string(o) << std::endl;
out_file << "--------------------------------------------------------------------" << std::endl;
out_file << "观测值近似值矩阵为(单位米):" << std::endl;
out_file << L << std::endl;
out_file << "--------------------------------------------------------------------" << std::endl;
out_file << "参数近似值矩阵为(单位米):" << std::endl;
out_file << X << std::endl;
out_file << "--------------------------------------------------------------------" << std::endl;
out_file << "B矩阵为:" << std::endl;
out_file << B << std::endl;
out_file << "--------------------------------------------------------------------" << std::endl;
out_file << "x参数改正数矩阵为:单位为米:" << std::endl;
out_file << x << std::endl;
out_file << "--------------------------------------------------------------------" << std::endl;
out_file << "v观测值改正数矩阵为(单位米):" << std::endl;
out_file << v << std::endl;
out_file << "--------------------------------------------------------------------" << std::endl;
L_ = v + L;
out_file << "改正后的观测阵矩阵为(单位米):" << std::endl;
out_file << L_ << std::endl;
out_file << "--------------------------------------------------------------------" << std::endl;
X = X + x;
out_file << "改正后的参数矩阵为(单位米):" << std::endl;
out_file << X << std::endl;
out_file << "--------------------------------------------------------------------" << std::endl;
}
else {
QMessageBox::critical(this, "warning", "The outfile is not opened!"); return 0;
};
out_file.close();
return 0;
}
leveling_network::~leveling_network()
{}