一、以下图附合导线为例,图形如下:
二、第一步,读取测量数据,读取界面设计如下:
读取数据文本文件格式如下:
(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_OBJECTpublic: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;//坐标增量Xstd::vector<Side> vYIn;//坐标增量Ydouble 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;
};