一、以下图附合导线为例,图形如下:
二、第一步,读取测量数据,读取界面设计如下:
读取数据文本文件格式如下:
(1)已知点坐标数据格式:
(2)角度观测值数据格式:
(3)边长观测值数据格式:
读取文本文件的代码如下:
void TraverseAdjustment::onReadDataKnown()
{
//打开文件对话框
QString fileName = QFileDialog::getOpenFileName(this, tr("打开已知点数据"));
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
QMessageBox::StandardButton btnValue = QMessageBox::information(this, tr("提示"), tr("打开失败!"));
//读取文本文件数据
QTextStream stream(&file);
pointKnown pk1;
while (!stream.atEnd())
{
QString str = stream.readLine();
QStringList list=str.split(",");
pk1.number = list.at(0);
pk1.x = list.at(1).toDouble();
pk1.y = list.at(2).toDouble();
ui.textEdit->append(str);
vpKnown.push_back(pk1);
}
ui.lineEdit->setText(fileName);
}
说明:需要先创建一个字符串变量用于存储文件对话框返回的路径,然后创建一个文件操作对象,用返回路径进行初始化。使用open()函数打开文本文件,随后设置一个读写流对象,用于逐行读取文本,将单行文本分割后,赋值给创建的结构体对象,然后添加到vecctor中。
三、第二步,计算角度闭合差
观测值为左角时,有
其中n为导线转折角数,这里如图1的附合导线,n=8.
注意1:观测角度值之和应为各个观测角度(DMS度分秒格式)的十进制度数的总和,因此,需要将原始观测值逐一转换成十进制度,再求和。(原始角度观测数据为度分秒格式的)
注意2:等方位角的计算,由于atan()等三角函数返回的是弧度值,因此需要将结果转化成十进制度值再输出。利用坐标反算方法,得到已知边的方位角,如下:
(1)方位角计算代码如下:
double TraverseAdjustment::CoordinateInverse(double xa, double ya, double xb, double yb)
{
double arfa_ab = atan(abs(yb - ya) / abs(xb - xa));//返回的是弧度值
arfa_ab = Radian2Angle(arfa_ab);
if (ya<yb&&xa>xb)
{
arfa_ab=180 - arfa_ab;
}
if (ya > yb && xa > xb)
{
arfa_ab = 180 + arfa_ab;
}
if (ya > yb && xa < xb)
{
arfa_ab = 360 - arfa_ab;
}
return arfa_ab;//返回十进制度数
}
(2)闭合差计算代码如下:
void TraverseAdjustment::onAngleClosureError()
{
double arfa_1=0;//角度观测值之和
for (auto& val : vA)
{
double a = val.value;
a = DMS2Angle(a);
arfa_1 = arfa_1 + a;
}
qDebug() << arfa_1;
qDebug() << DMS2Angle(1644.2828);
double arfa_ab;//AB方位角值
double arfa_cd;//CD方位角值
arfa_ab = CoordinateInverse(vpKnown.at(0).x, vpKnown.at(0).y, vpKnown.at(1).x, vpKnown.at(1).y);
arfa_cd = CoordinateInverse(vpKnown.at(2).x, vpKnown.at(2).y, vpKnown.at(3).x, vpKnown.at(3).y);
qDebug() << arfa_ab;
qDebug() << arfa_cd;
qDebug() << DMS2Angle(303.2728);
qDebug() << DMS2Angle(147.5628);
Rab = arfa_ab;
Rcd = arfa_cd;
n = vA.size();
double arfa_cd1 = 0;//理论角度值
arfa_cd1 = arfa_ab - n * 180+arfa_1;
if (arfa_cd1 > 360)
{
int t1 = arfa_cd1 / 360;
arfa_cd1 = arfa_cd1 - t1 * 360;
}
double f_beta = arfa_cd1-arfa_cd;
f_beta = f_beta * 3600;
f = f_beta;
ui.textEdit_2->append("角度闭合差:");
ui.textEdit_2->append(QString::number(f_beta));
ui.textEdit_2->append("限差:");
ui.textEdit_2->append(QString::number(24*sqrt(n)));
if (f_beta <= 24 * sqrt(n))
{
ui.textEdit_2->append("合格");
}
else
{
ui.textEdit_2->append("不合格");
}
}
四、第三步,计算方位角
若角度闭合差附合限差,则将角度闭合差均分至各角度观测值(即求改正数),然后使用改正后的角度观测值计算各测站的方位角信息。观测值为左角时,有如下:
以此推算各测站方位角。
(1)方位角计算代码如下:
void TraverseAdjustment::CalculateAzimuth()
{
//计算角度观测值改正数
double t1 = -f / n;
t1 = t1 / 3600;
Angle a1;
for (auto& val : vA)
{
a1.value = DMS2Angle(val.value)+t1;
a1.number = val.number;
a1.number1 = val.number1;
a1.number2 = val.number2;
va.push_back(a1);
}
ui.textEdit_2->clear();
ui.textEdit_2->append("方位角结果:");
Angle a2; double R1 = Rab;
for (int i = 0; i < va.size(); i++)
{
double R = R1 + va.at(i).value-180;
if (R > 360)
{
int t2 = R / 360;
R = R - t2 * 360;
}
a2.number = va.at(i).number;
a2.number1 = va.at(i).number1;
a2.number2 = va.at(i).number2;
a2.value = R;
ui.textEdit_2->append(QString::number(R));
vAzi.push_back(a2);
R1 = R;
}
}
五、第四步,计算坐标增量
注意:这里的cos()函数等三角函数的输入值为弧度,应把方位角转化成护弧度在计算,否则结果错误。
(1)计算坐标增量的代码如下:
void TraverseAdjustment::onCalIncrement()
{
Side s1; ui.textEdit_2->clear();
ui.textEdit_2->append("X坐标增量:");
for (int i = 0; i < vAzi.size(); i++)
{
s1.number1 = vAzi.at(i).number;
s1.number2 = vAzi.at(i).number2;
for (int j = 0; j < vS.size(); j++)
{
if (vAzi.at(i).number == vS.at(j).number1 && vAzi.at(i).number2 == vS.at(j).number2)
{
double b1 = vAzi.at(i).value;
b1 = Angle2Radian(b1);
s1.value = vS.at(j).value * cos(b1);//cos函数输入值需为弧度
ui.textEdit_2->append(QString::number(s1.value));
vXIn.push_back(s1);
s1.value = vS.at(j).value * sin(b1);//sin函数输入值需为弧度
vYIn.push_back(s1);
break;
}
}
}
ui.textEdit_2->append("Y坐标增量:");
for (auto& val : vYIn)
{
ui.textEdit_2->append(QString::number(val.value));
}
}
六、第五步,计算坐标改正数
这里只需按照上述公式计算即可。
(1)计算坐标改正数代码如下:
void TraverseAdjustment::onCalCorrection()
{
ui.textEdit_2->clear();
ui.textEdit_2->append("X增量改正数:");
//计算坐标增量之和
double detax = 0;
double detay = 0;
for (auto& val : vXIn)
{
double b1 = val.value;
detax = detax + b1;
}
for (auto& val : vYIn)
{
double b1 = val.value;
detay = detay + b1;
}
//计算坐标增量闭合差
fx = detax - (vpKnown.at(2).x - vpKnown.at(1).x);
fy = detay - (vpKnown.at(2).y - vpKnown.at(1).y);
//计算坐标改正数
double s1 = 0;//导线边距离之和
for (auto& val : vS)
{
s1 = s1 + val.value;
}
Side s2;
for (int i = 0; i<vXIn.size(); i++)
{
double d;
for (int j=0; j < vS.size(); j++)
{
if (vXIn.at(i).number1 == vS.at(j).number1 && vXIn.at(i).number2 == vS.at(j).number2)
{
d = vS.at(j).value;
}
}
s2.number1 = vXIn.at(i).number1;
s2.number2 = vXIn.at(i).number2;
s2.value = -fx / s1 * d;
ui.textEdit_2->append(QString::number(s2.value));
vX.push_back(s2);
}
ui.textEdit_2->append("Y增量改正数:");
for (int i = 0; i < vYIn.size(); i++)
{
double d;
for (int j = 0; j < vS.size(); j++)
{
if (vYIn.at(i).number1 == vS.at(j).number1 && vYIn.at(i).number2 == vS.at(j).number2)
{
d = vS.at(j).value;
}
}
s2.number1 = vXIn.at(i).number1;
s2.number2 = vXIn.at(i).number2;
s2.value = -fy / s1 * d;
ui.textEdit_2->append(QString::number(s2.value));
vY.push_back(s2);
}
}
七、第六步,计算未知点坐标值
按公式计算即可。
(1)计算坐标值代码如下:
void TraverseAdjustment::onCalCoordinate()
{
ui.textEdit_2->clear();
ui.textEdit_2->append("改正后X增量:");
double x0 = vpKnown.at(1).x;
double y0 = vpKnown.at(1).y;
for (int i=0;i<vXIn.size();i++)
{
vXIn.at(i).value = vXIn.at(i).value + vX.at(i).value;
ui.textEdit_2->append(QString::number(vXIn.at(i).value));
}
ui.textEdit_2->append("改正后Y增量:");
for (int i = 0; i < vYIn.size(); i++)
{
vYIn.at(i).value = vYIn.at(i).value + vY.at(i).value;
ui.textEdit_2->append(QString::number(vYIn.at(i).value));
}
ui.textEdit_2->append("X坐标:");
pointKnown pk1; int t2 = 0;
for (auto& val : vXIn)
{
pk1.number = val.number1;
pk1.x = x0 + val.value;
pk1.y = y0 + vYIn.at(t2).value;
vp.push_back(pk1);
x0 = pk1.x;
y0 = pk1.y;
if (t2 <= vYIn.size()-2)
{
ui.textEdit_2->append(QString::number(pk1.x, 'f', 8));
}
t2++;
}
ui.textEdit_2->append("Y坐标:");
vp.pop_back();
for (auto& val : vp)
{
ui.textEdit_2->append(QString::number(val.y,'f',8));
}
}
八、程序运行结果如下:
九、上述计算结果均校对过,结果准确。附上完整代码
//.cpp文件
#include "TraverseAdjustment.h"
TraverseAdjustment::TraverseAdjustment(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(onReadDataKnown()));
connect(ui.pushButton_2, SIGNAL(clicked()), this, SLOT(onReadDataAngle()));
connect(ui.pushButton_3, SIGNAL(clicked()), this, SLOT(onReadDataSide()));
connect(ui.pushButton_5, SIGNAL(clicked()), this, SLOT(onAngleClosureError()));
connect(ui.pushButton_4, SIGNAL(clicked()), this, SLOT(CalculateAzimuth()));
connect(ui.pushButton_6, SIGNAL(clicked()), this, SLOT(onCalIncrement()));
connect(ui.pushButton_7, SIGNAL(clicked()), this, SLOT(onCalCorrection()));
connect(ui.pushButton_8, SIGNAL(clicked()), this, SLOT(onCalCoordinate()));
ui.lineEdit->setReadOnly(true);
ui.lineEdit_2->setReadOnly(true);
ui.lineEdit_3->setReadOnly(true);
ui.textEdit->setReadOnly(true);
ui.textEdit_2->setReadOnly(true);
ui.textEdit->append("读入数据展示:");
}
TraverseAdjustment::~TraverseAdjustment()
{}
void TraverseAdjustment::onCalCoordinate()
{
ui.textEdit_2->clear();
ui.textEdit_2->append("改正后X增量:");
double x0 = vpKnown.at(1).x;
double y0 = vpKnown.at(1).y;
for (int i=0;i<vXIn.size();i++)
{
vXIn.at(i).value = vXIn.at(i).value + vX.at(i).value;
ui.textEdit_2->append(QString::number(vXIn.at(i).value));
}
ui.textEdit_2->append("改正后Y增量:");
for (int i = 0; i < vYIn.size(); i++)
{
vYIn.at(i).value = vYIn.at(i).value + vY.at(i).value;
ui.textEdit_2->append(QString::number(vYIn.at(i).value));
}
ui.textEdit_2->append("X坐标:");
pointKnown pk1; int t2 = 0;
for (auto& val : vXIn)
{
pk1.number = val.number1;
pk1.x = x0 + val.value;
pk1.y = y0 + vYIn.at(t2).value;
vp.push_back(pk1);
x0 = pk1.x;
y0 = pk1.y;
if (t2 <= vYIn.size()-2)
{
ui.textEdit_2->append(QString::number(pk1.x, 'f', 8));
}
t2++;
}
ui.textEdit_2->append("Y坐标:");
vp.pop_back();
for (auto& val : vp)
{
ui.textEdit_2->append(QString::number(val.y,'f',8));
}
}
void TraverseAdjustment::onCalCorrection()
{
ui.textEdit_2->clear();
ui.textEdit_2->append("X增量改正数:");
//计算坐标增量之和
double detax = 0;
double detay = 0;
for (auto& val : vXIn)
{
double b1 = val.value;
detax = detax + b1;
}
for (auto& val : vYIn)
{
double b1 = val.value;
detay = detay + b1;
}
//计算坐标增量闭合差
fx = detax - (vpKnown.at(2).x - vpKnown.at(1).x);
fy = detay - (vpKnown.at(2).y - vpKnown.at(1).y);
//计算坐标改正数
double s1 = 0;//导线边距离之和
for (auto& val : vS)
{
s1 = s1 + val.value;
}
Side s2;
for (int i = 0; i<vXIn.size(); i++)
{
double d;
for (int j=0; j < vS.size(); j++)
{
if (vXIn.at(i).number1 == vS.at(j).number1 && vXIn.at(i).number2 == vS.at(j).number2)
{
d = vS.at(j).value;
}
}
s2.number1 = vXIn.at(i).number1;
s2.number2 = vXIn.at(i).number2;
s2.value = -fx / s1 * d;
ui.textEdit_2->append(QString::number(s2.value));
vX.push_back(s2);
}
ui.textEdit_2->append("Y增量改正数:");
for (int i = 0; i < vYIn.size(); i++)
{
double d;
for (int j = 0; j < vS.size(); j++)
{
if (vYIn.at(i).number1 == vS.at(j).number1 && vYIn.at(i).number2 == vS.at(j).number2)
{
d = vS.at(j).value;
}
}
s2.number1 = vXIn.at(i).number1;
s2.number2 = vXIn.at(i).number2;
s2.value = -fy / s1 * d;
ui.textEdit_2->append(QString::number(s2.value));
vY.push_back(s2);
}
}
void TraverseAdjustment::onCalIncrement()
{
Side s1; ui.textEdit_2->clear();
ui.textEdit_2->append("X坐标增量:");
for (int i = 0; i < vAzi.size(); i++)
{
s1.number1 = vAzi.at(i).number;
s1.number2 = vAzi.at(i).number2;
for (int j = 0; j < vS.size(); j++)
{
if (vAzi.at(i).number == vS.at(j).number1 && vAzi.at(i).number2 == vS.at(j).number2)
{
double b1 = vAzi.at(i).value;
b1 = Angle2Radian(b1);
s1.value = vS.at(j).value * cos(b1);//cos函数输入值需为弧度
ui.textEdit_2->append(QString::number(s1.value));
vXIn.push_back(s1);
s1.value = vS.at(j).value * sin(b1);//sin函数输入值需为弧度
vYIn.push_back(s1);
break;
}
}
}
ui.textEdit_2->append("Y坐标增量:");
for (auto& val : vYIn)
{
ui.textEdit_2->append(QString::number(val.value));
}
}
void TraverseAdjustment::onReadDataKnown()
{
//打开文件对话框
QString fileName = QFileDialog::getOpenFileName(this, tr("打开已知点数据"));
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
QMessageBox::StandardButton btnValue = QMessageBox::information(this, tr("提示"), tr("打开失败!"));
//读取文本文件数据
QTextStream stream(&file);
pointKnown pk1;
while (!stream.atEnd())
{
QString str = stream.readLine();
QStringList list=str.split(",");
pk1.number = list.at(0);
pk1.x = list.at(1).toDouble();
pk1.y = list.at(2).toDouble();
ui.textEdit->append(str);
vpKnown.push_back(pk1);
}
ui.lineEdit->setText(fileName);
}
void TraverseAdjustment::onReadDataAngle()
{
//打开文件对话框
QString fileName = QFileDialog::getOpenFileName(this, tr("打开角度观测数据"));
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
QMessageBox::StandardButton btnValue = QMessageBox::information(this, tr("提示"), tr("打开失败!"));
//读取数据
QTextStream stream(&file);
Angle va1;
while (!stream.atEnd())
{
QString str = stream.readLine();
QStringList list = str.split(",");
va1.number = list.at(0);
va1.number1 = list.at(1);
va1.number2 = list.at(2);
va1.value = list.at(3).toDouble();
ui.textEdit->append(str);
vA.push_back(va1);
}
ui.lineEdit_2->setText(fileName);
}
void TraverseAdjustment::onReadDataSide()
{
//打开文件对话框
QString fileName = QFileDialog::getOpenFileName(this, tr("打开边长观测数据"));
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
QMessageBox::StandardButton btnValue = QMessageBox::information(this, tr("提示"), tr("打开失败!"));
//读取数据
QTextStream stream(&file);
Side vs1;
while (!stream.atEnd())
{
QString str = stream.readLine();
QStringList list = str.split(",");
vs1.number1 = list.at(0);
vs1.number2 = list.at(1);
vs1.value = list.at(2).toDouble();
ui.textEdit->append(str);
vS.push_back(vs1);
}
ui.lineEdit_3->setText(fileName);
}
void TraverseAdjustment::CalculateAzimuth()
{
//计算角度观测值改正数
double t1 = -f / n;
t1 = t1 / 3600;
Angle a1;
for (auto& val : vA)
{
a1.value = DMS2Angle(val.value)+t1;
a1.number = val.number;
a1.number1 = val.number1;
a1.number2 = val.number2;
va.push_back(a1);
}
ui.textEdit_2->clear();
ui.textEdit_2->append("方位角结果:");
Angle a2; double R1 = Rab;
for (int i = 0; i < va.size(); i++)
{
double R = R1 + va.at(i).value-180;
if (R > 360)
{
int t2 = R / 360;
R = R - t2 * 360;
}
a2.number = va.at(i).number;
a2.number1 = va.at(i).number1;
a2.number2 = va.at(i).number2;
a2.value = R;
ui.textEdit_2->append(QString::number(R));
vAzi.push_back(a2);
R1 = R;
}
}
double TraverseAdjustment::Angle2Radian(double a)
{
a = a * 0.017453293;
return a;
}
double TraverseAdjustment::Radian2Angle(double a)
{
a = a * 57.29578;
return a;
}
double TraverseAdjustment::DMS2Angle(double a)
{
int deg; double min, sed;
deg = int(a);
min = int((a - deg) * 100);
sed = ((a - deg) * 100 - min) * 100;
return deg + min / 60 + sed / 3600;
}
void TraverseAdjustment::onAngleClosureError()
{
double arfa_1=0;//角度观测值之和
for (auto& val : vA)
{
double a = val.value;
a = DMS2Angle(a);
arfa_1 = arfa_1 + a;
}
qDebug() << arfa_1;
qDebug() << DMS2Angle(1644.2828);
double arfa_ab;//BA方位角值
double arfa_cd;//CD方位角值
arfa_ab = CoordinateInverse(vpKnown.at(0).x, vpKnown.at(0).y, vpKnown.at(1).x, vpKnown.at(1).y);
arfa_cd = CoordinateInverse(vpKnown.at(2).x, vpKnown.at(2).y, vpKnown.at(3).x, vpKnown.at(3).y);
qDebug() << arfa_ab;
qDebug() << arfa_cd;
qDebug() << DMS2Angle(303.2728);
qDebug() << DMS2Angle(147.5628);
Rab = arfa_ab;
Rcd = arfa_cd;
n = vA.size();
double arfa_cd1 = 0;//理论角度值
arfa_cd1 = arfa_ab - n * 180+arfa_1;
if (arfa_cd1 > 360)
{
int t1 = arfa_cd1 / 360;
arfa_cd1 = arfa_cd1 - t1 * 360;
}
double f_beta = arfa_cd1-arfa_cd;
f_beta = f_beta * 3600;
f = f_beta;
ui.textEdit_2->append("角度闭合差:");
ui.textEdit_2->append(QString::number(f_beta));
ui.textEdit_2->append("限差:");
ui.textEdit_2->append(QString::number(24*sqrt(n)));
if (f_beta <= 24 * sqrt(n))
{
ui.textEdit_2->append("合格");
}
else
{
ui.textEdit_2->append("不合格");
}
}
double TraverseAdjustment::CoordinateInverse(double xa, double ya, double xb, double yb)
{
double arfa_ab = atan(abs(yb - ya) / abs(xb - xa));//返回的是弧度值
arfa_ab = Radian2Angle(arfa_ab);
if (ya<yb&&xa>xb)
{
arfa_ab=180 - arfa_ab;
}
if (ya > yb && xa > xb)
{
arfa_ab = 180 + arfa_ab;
}
if (ya > yb && xa < xb)
{
arfa_ab = 360 - arfa_ab;
}
return arfa_ab;//返回十进制度数
}
//.h文件
#pragma once
#include <QtWidgets/QWidget>
#include "ui_TraverseAdjustment.h"
#include<QFileDialog>
#include<QFile>
#include<QMessageBox>
#include<QTextStream>
#include<QStringList>
#pragma execution_character_set("UTF-8")
#include"math.h"
#include<qDebug>
struct pointKnown
{
QString number;
double x;
double y;
};
struct Angle
{
QString number;
QString number1;
QString number2;
double value;
};
struct Side
{
QString number1;
QString number2;
double value;
};
class TraverseAdjustment : public QWidget
{
Q_OBJECT
public:
TraverseAdjustment(QWidget *parent = nullptr);
~TraverseAdjustment();
public:
std::vector<pointKnown> vpKnown;//已知点坐标
std::vector<Angle> vA;//角度观测值
std::vector<Side> vS;//边长观测值
double f;//角度闭合差
int n;//导线边数
std::vector<Angle> va;//添加改正数后的角度值
std::vector<Angle> vAzi;//方位角值
double Rab, Rcd;//已知起始、终止边对应方位角
std::vector<Side> vXIn;//坐标增量X
std::vector<Side> vYIn;//坐标增量Y
double fx, fy;//坐标增量闭合差
std::vector<Side> vX;//X增量改正数
std::vector<Side> vY;//Y增量改正数
std::vector<pointKnown> vp;//各测点最终坐标值
public slots:
void onReadDataKnown();
void onReadDataAngle();
void onReadDataSide();
void onAngleClosureError();
void CalculateAzimuth();
void onCalIncrement();
void onCalCorrection();
void onCalCoordinate();
public:
double Angle2Radian(double a);
double DMS2Angle(double a);
double Radian2Angle(double a);
double CoordinateInverse(double xa, double ya, double xb, double yb);
private:
Ui::TraverseAdjustmentClass ui;
};