You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmSubWxs/nmWxPointerPosDlg.cpp

277 lines
8.5 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "nmWxPointerPosDlg.h"
#include "nmGUIComponentLineEdit.h"
#include "nmDataAnalyzeManager.h"
#include "nmDataAttribute.h"
#include <QPushButton>
#include <QComboBox>
#include <QLineEdit>
#include <QGroupBox>
#include <QFormLayout>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <cmath>
nmWxPointerPosDlg::nmWxPointerPosDlg(QWidget* parent)
: QDialog(parent)
{
setWindowTitle(tr("Pointer position"));
m_pAttrX = new nmDataAttribute();
m_pAttrX->setName("X");
m_pAttrX->setUnit("m");
m_pAttrX->setListUnitSelections(QStringList() << "m" << "ft" << "cm");
m_pAttrX->setValue(0.0);
m_pAttrY = new nmDataAttribute();
m_pAttrY->setName("Y");
m_pAttrY->setUnit("m");
m_pAttrY->setListUnitSelections(QStringList() << "m" << "ft" << "cm");
m_pAttrY->setValue(0.0);
m_pGeoRefData = nmDataAnalyzeManager::getCurrentInstance()->getGeoRefData();
initUI();
loadGeoRefDataToUI();
this->resize(320, 400);
this->setFixedSize(this->size());
}
void nmWxPointerPosDlg::initUI()
{
// Local grid group
QGroupBox* localGroup = new QGroupBox(tr("Local grid"));
QFormLayout* localForm = new QFormLayout;
localForm->setLabelAlignment(Qt::AlignRight | Qt::AlignVCenter);
localForm->setVerticalSpacing(10);
localForm->setHorizontalSpacing(15);
localForm->setContentsMargins(8, 8, 8, 8);
m_pX = new nmGUIComponentLineEdit(m_pAttrX, false);
m_pY = new nmGUIComponentLineEdit(m_pAttrY, false);
QLineEdit* leX = m_pX->findChild<QLineEdit*>();
if(leX) {
leX->setMinimumWidth(100);
}
QLineEdit* leY = m_pY->findChild<QLineEdit*>();
if(leY) {
leY->setMinimumWidth(100);
}
QWidget* xWidget = new QWidget;
QHBoxLayout* xLay = new QHBoxLayout(xWidget);
xLay->setContentsMargins(0, 0, 0, 0);
xLay->addWidget(m_pX);
QWidget* yWidget = new QWidget;
QHBoxLayout* yLay = new QHBoxLayout(yWidget);
yLay->setContentsMargins(0, 0, 0, 0);
yLay->addWidget(m_pY);
localForm->addRow(tr("X:"), xWidget);
localForm->addRow(tr("Y:"), yWidget);
QVBoxLayout* localWrapper = new QVBoxLayout;
localWrapper->addStretch(1);
localWrapper->addLayout(localForm);
localWrapper->addStretch(1);
localWrapper->setContentsMargins(0, 0, 0, 0);
localGroup->setLayout(localWrapper);
// Coordinates group
QGroupBox* coordGroup = new QGroupBox(tr("Coordinates"));
coordGroup->setEnabled(true);
QFormLayout* coordForm = new QFormLayout;
coordForm->setLabelAlignment(Qt::AlignRight | Qt::AlignVCenter);
coordForm->setVerticalSpacing(10);
coordForm->setHorizontalSpacing(15);
coordForm->setContentsMargins(8, 8, 8, 8);
m_pLonEdit = new QLineEdit;
m_pLatEdit = new QLineEdit;
m_pUtmZoneCombo = new QComboBox;
m_pEastingEdit = new QLineEdit;
m_pNorthingEdit = new QLineEdit;
// 初始化UTM Zone下拉框选项
QStringList bands;
bands << "C" << "D" << "E" << "F" << "G" << "H" << "J" << "K" << "L" << "M"
<< "N" << "P" << "Q" << "R" << "S" << "T" << "U" << "V" << "W" << "X";
// 外层循环Band内层循环Zone
for(int i = 0; i < bands.size(); ++i) {
QString band = bands.at(i);
for(int zone = 1; zone <= 60; ++zone) {
QString zoneStr = QString("%1%2").arg(zone, 2, 10, QLatin1Char('0')).arg(band);
m_pUtmZoneCombo->addItem(zoneStr);
}
}
m_pLonEdit->setEnabled(false);
m_pLatEdit->setEnabled(false);
m_pUtmZoneCombo->setEnabled(false); // ComboBox禁用编辑
m_pEastingEdit->setEnabled(false);
m_pNorthingEdit->setEnabled(false);
coordForm->addRow(tr("Longitude:"), m_pLonEdit);
coordForm->addRow(tr("Latitude:"), m_pLatEdit);
coordForm->addItem(new QSpacerItem(0, 20, QSizePolicy::Minimum, QSizePolicy::Fixed));
coordForm->addRow(tr("UTM zone:"), m_pUtmZoneCombo);
coordForm->addRow(tr("Easting:"), m_pEastingEdit);
coordForm->addRow(tr("Northing:"), m_pNorthingEdit);
QVBoxLayout* coordWrapper = new QVBoxLayout;
coordWrapper->addStretch(1);
coordWrapper->addLayout(coordForm);
coordWrapper->addStretch(1);
coordWrapper->setContentsMargins(0, 0, 0, 0);
coordGroup->setLayout(coordWrapper);
// Bottom button
m_pCloseButton = new QPushButton(tr("Close"));
connect(m_pCloseButton, SIGNAL(clicked()), this, SLOT(reject()));
QHBoxLayout* btnLay = new QHBoxLayout;
btnLay->addStretch();
btnLay->addWidget(m_pCloseButton);
// 整体布局
QVBoxLayout* mainLay = new QVBoxLayout;
mainLay->setContentsMargins(12, 12, 12, 12);
mainLay->setSpacing(15);
mainLay->addWidget(localGroup);
mainLay->addWidget(coordGroup);
mainLay->addLayout(btnLay);
setLayout(mainLay);
}
void nmWxPointerPosDlg::setPointerPos(double x, double y)
{
// 更新X、Y坐标显示
m_pX->setDisplayValue(x);
m_pY->setDisplayValue(y);
// 检查是否有地理参考数据
if (!m_pGeoRefData) {
return; // 提前返回,避免后续无效计算
}
// 验证地理参考数据有效性
QString utmZone = m_pGeoRefData->getUtmZone().getValue().toString();
if (utmZone.isEmpty()) {
return; // 提前返回,避免后续无效计算
}
// 获取基础地理参考坐标
double baseEasting = m_pGeoRefData->getEasting().getValue().toDouble();
double baseNorthing = m_pGeoRefData->getNorthing().getValue().toDouble();
double baseLongitude = m_pGeoRefData->getLongitude().getValue().toDouble();
double baseLatitude = m_pGeoRefData->getLatitude().getValue().toDouble();
// 计算并更新UTM坐标
double newEasting = baseEasting + x;
double newNorthing = baseNorthing + y;
m_pEastingEdit->setText(QString::number(newEasting, 'f', 2));
m_pNorthingEdit->setText(QString::number(newNorthing, 'f', 2));
// 计算并更新经纬度坐标
const double METERS_PER_DEGREE_LAT = 111111.0;
const double PI = 3.14159265358979323846;
double latitudeRadians = baseLatitude * PI / 180.0;
double metersPerDegreeLon = METERS_PER_DEGREE_LAT * cos(latitudeRadians);
double newLatitude = baseLatitude + (y / METERS_PER_DEGREE_LAT);
double newLongitude = baseLongitude + (x / metersPerDegreeLon);
// 转换为度分秒格式并更新UI
QString latStr = formatCoordinate(newLatitude, true);
QString lonStr = formatCoordinate(newLongitude, false);
m_pLatEdit->setText(latStr);
m_pLonEdit->setText(lonStr);
}
void nmWxPointerPosDlg::loadGeoRefDataToUI()
{
if (!m_pGeoRefData) {
m_pUtmZoneCombo->setCurrentIndex(-1); // 设置为空选项
return;
}
// 检查是否有有效的地理参考数据
QString utmZone = m_pGeoRefData->getUtmZone().getValue().toString();
bool hasValidData = !utmZone.isEmpty();
if (hasValidData) {
// 加载经纬度
double longitude = m_pGeoRefData->getLongitude().getValue().toDouble();
double latitude = m_pGeoRefData->getLatitude().getValue().toDouble();
// 分别转换经度和纬度并设置到UI
QString lonStr = formatCoordinate(longitude, false); // false表示经度
QString latStr = formatCoordinate(latitude, true); // true表示纬度
m_pLonEdit->setText(lonStr); // 显示转换后的经度
m_pLatEdit->setText(latStr); // 显示转换后的纬度
// 加载UTM Zone
int index = m_pUtmZoneCombo->findText(utmZone);
if (index >= 0) {
m_pUtmZoneCombo->setCurrentIndex(index);
}
// 加载UTM坐标
double easting = m_pGeoRefData->getEasting().getValue().toDouble();
double northing = m_pGeoRefData->getNorthing().getValue().toDouble();
m_pEastingEdit->setText(QString::number(easting, 'f', 2));
m_pNorthingEdit->setText(QString::number(northing, 'f', 2));
}
}
QString nmWxPointerPosDlg::formatCoordinate(double coordinate, bool isLatitude)
{
// 判断正负,确定方向
bool isPositive = coordinate >= 0;
double absCoordinate = qAbs(coordinate);
// 提取度数
int degrees = static_cast<int>(absCoordinate);
// 计算分数
double minutesFloat = (absCoordinate - degrees) * 60.0;
int minutes = static_cast<int>(minutesFloat);
// 计算秒数
double seconds = (minutesFloat - minutes) * 60.0;
// 防止浮点精度问题导致秒数≥60
if (seconds >= 60.0) {
seconds = 59.999;
}
// 确定方向字符
QString direction;
if (isLatitude) {
direction = isPositive ? "N" : "S"; // 纬度
} else {
direction = isPositive ? "E" : "W"; // 经度
}
// 分步构建字符串
QString result;
result += QString("%1").arg(degrees, 2, 10, QChar('0')); // 度数
result += QString(tr("deg")); // 度符号
result += QString("%1").arg(minutes, 2, 10, QChar('0')); // 分数
result += QString(tr("min")); // 分符号
result += QString("%1").arg(static_cast<int>(seconds), 2, 10, QChar('0')); // 秒数
result += QString(tr("sec")); // 秒符号
result += direction; // 方向
return result;
}