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++

#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;
}