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/nmWxGeoRefDlg.cpp

790 lines
25 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.

#define _USE_MATH_DEFINES
#include "nmWxGeoRefDlg.h"
#include <QGroupBox>
#include <QMessageBox>
#include <QFormLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <cmath>
#include "nmDataAnalyzeManager.h"
#include "nmDataAxis.h"
nmWxGeoRefDlg::nmWxGeoRefDlg(QWidget* parent)
: iDlgBase(parent), m_bUpdating(false)
{
this->setWindowTitle(tr("Geo referencing"));
initUI();
this->resize(370, 320);
this->setFixedSize(this->size());
m_geoRefData = nmDataAnalyzeManager::getCurrentInstance()->getGeoRefDataCopy();
loadDataToUI();
}
void nmWxGeoRefDlg::initUI()
{
// Location group
QGroupBox* locationGroup = new QGroupBox(tr("Location"));
// form 布局
QFormLayout* locForm = new QFormLayout;
locForm->setLabelAlignment(Qt::AlignRight | Qt::AlignVCenter);
locForm->setVerticalSpacing(12);
locForm->setHorizontalSpacing(20);
locForm->setContentsMargins(8, 8, 8, 8);
m_pLongitudeEdit = new QLineEdit; m_pLongitudeEdit->setFixedWidth(180);
m_pLatitudeEdit = new QLineEdit; m_pLatitudeEdit ->setFixedWidth(180);
locForm->addRow(tr("Longitude:"), m_pLongitudeEdit);
locForm->addRow(tr("Latitude:"), m_pLatitudeEdit);
// 包一层 vbox用 stretch 让 form 居中
QVBoxLayout* locWrapper = new QVBoxLayout;
locWrapper->addStretch(1);
locWrapper->addLayout(locForm);
locWrapper->addStretch(1);
locWrapper->setContentsMargins(0, 0, 0, 0); // 根据需要调整 groupbox 内边距
locationGroup->setLayout(locWrapper);
// Zone group
QGroupBox* zoneGroup = new QGroupBox(tr("Zone"));
QFormLayout* zoneForm = new QFormLayout;
zoneForm->setLabelAlignment(Qt::AlignRight | Qt::AlignVCenter);
zoneForm->setVerticalSpacing(12);
zoneForm->setHorizontalSpacing(20);
zoneForm->setContentsMargins(8, 8, 8, 8);
m_pUtmZoneCombo = new QComboBox; m_pUtmZoneCombo->setFixedWidth(180);
m_pEastingEdit = new QLineEdit; m_pEastingEdit ->setFixedWidth(180);
m_pNorthingEdit = new QLineEdit; m_pNorthingEdit->setFixedWidth(180);
zoneForm->addRow(tr("UTM zone:"), m_pUtmZoneCombo);
zoneForm->addRow(tr("Easting:"), m_pEastingEdit);
zoneForm->addRow(tr("Northing:"), m_pNorthingEdit);
// 初始化 UTM Zone 下拉框格式01C~60X
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) {
// 格式化为两位数 Zone + 纬度带(例如 "01C", "02C"
QString zoneStr = QString("%1%2").arg(zone, 2, 10, QLatin1Char('0')).arg(band);
m_pUtmZoneCombo->addItem(zoneStr);
}
}
m_pUtmZoneCombo->setCurrentIndex(-1);
QVBoxLayout* zoneWrapper = new QVBoxLayout;
zoneWrapper->addStretch(1);
zoneWrapper->addLayout(zoneForm);
zoneWrapper->addStretch(1);
zoneWrapper->setContentsMargins(0, 0, 0, 0);
zoneGroup->setLayout(zoneWrapper);
// Buttons
m_pOkButton = new QPushButton(tr("OK"));
m_pCancelButton = new QPushButton(tr("Cancel"));
m_pOkButton->setDefault(true);
connect(m_pOkButton, SIGNAL(clicked()), this, SLOT(okAccept()));
connect(m_pCancelButton, SIGNAL(clicked()), this, SLOT(cancelReject()));
QHBoxLayout* btnLay = new QHBoxLayout;
btnLay->addStretch();
btnLay->addWidget(m_pOkButton);
btnLay->addWidget(m_pCancelButton);
// 主布局
QVBoxLayout* mainLay = new QVBoxLayout;
mainLay->setContentsMargins(10, 10, 10, 10);
mainLay->setSpacing(15);
mainLay->addWidget(locationGroup);
mainLay->addWidget(zoneGroup);
mainLay->addLayout(btnLay);
setLayout(mainLay);
// 初始都设成不可编辑
m_pLongitudeEdit->setEnabled(false);
m_pLatitudeEdit ->setEnabled(false);
m_pUtmZoneCombo ->setEnabled(true);
m_pEastingEdit ->setEnabled(false);
m_pNorthingEdit ->setEnabled(false);
connect(m_pUtmZoneCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onUtmZoneChanged(int)));
connect(m_pLongitudeEdit, SIGNAL(editingFinished()), this, SLOT(onLongitudeChanged()));
connect(m_pLatitudeEdit, SIGNAL(editingFinished()), this, SLOT(onLatitudeChanged()));
connect(m_pEastingEdit, SIGNAL(editingFinished()), this, SLOT(onEastingChanged()));
connect(m_pNorthingEdit, SIGNAL(editingFinished()), this, SLOT(onNorthingChanged()));
}
// 根据经纬度和UTM zone计算Northing坐标的辅助函数
double nmWxGeoRefDlg::calculateNorthing(double latitude, double longitude, int zone)
{
// UTM投影的简化计算公式
// 这里使用基本的UTM投影算法
const double a = 6378137.0; // WGS84长半轴
const double e2 = 0.00669437999014; // WGS84第一偏心率的平方
const double k0 = 0.9996; // UTM比例因子
// 转换为弧度
double lat_rad = latitude * M_PI / 180.0;
double lon_rad = longitude * M_PI / 180.0;
// 中央经线
double lon0_rad = (-183.0 + zone * 6.0) * M_PI / 180.0;
double dlon = lon_rad - lon0_rad;
// UTM投影计算
double N = a / sqrt(1 - e2 * sin(lat_rad) * sin(lat_rad));
double T = tan(lat_rad) * tan(lat_rad);
double C = e2 * cos(lat_rad) * cos(lat_rad) / (1 - e2);
double A = cos(lat_rad) * dlon;
double M = a * ((1 - e2 / 4 - 3 * e2 * e2 / 64 - 5 * e2 * e2 * e2 / 256) * lat_rad
- (3 * e2 / 8 + 3 * e2 * e2 / 32 + 45 * e2 * e2 * e2 / 1024) * sin(2 * lat_rad)
+ (15 * e2 * e2 / 256 + 45 * e2 * e2 * e2 / 1024) * sin(4 * lat_rad)
- (35 * e2 * e2 * e2 / 3072) * sin(6 * lat_rad));
double northing = k0 * (M + N * tan(lat_rad) * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A / 24
+ (61 - 58 * T + T * T + 600 * C - 330 * e2) * A * A * A * A * A * A / 720));
// 南半球需要加上假北值
if(latitude < 0) {
northing += 10000000.0;
}
return northing;
}
// 经度编辑完成时的处理
void nmWxGeoRefDlg::onLongitudeChanged()
{
if(m_bUpdating) return; // 防止递归更新
QString lonText = m_pLongitudeEdit->text();
QString latText = m_pLatitudeEdit->text();
// 检查经度值是否真的发生了变化
if(lonText == m_lastLongitude) {
return; // 值没有变化,不进行转换
}
if(!lonText.isEmpty() && !latText.isEmpty()) {
updateFromLatLon();
}
}
// 纬度编辑完成时的处理
void nmWxGeoRefDlg::onLatitudeChanged()
{
if(m_bUpdating) return; // 防止递归更新
QString lonText = m_pLongitudeEdit->text();
QString latText = m_pLatitudeEdit->text();
// 检查纬度值是否真的发生了变化
if(latText == m_lastLatitude) {
return; // 值没有变化,不进行转换
}
if(!lonText.isEmpty() && !latText.isEmpty()) {
updateFromLatLon();
}
}
// 东向坐标编辑完成时的处理
void nmWxGeoRefDlg::onEastingChanged()
{
if(m_bUpdating) return; // 防止递归更新
QString eastingText = m_pEastingEdit->text();
QString northingText = m_pNorthingEdit->text();
QString zoneText = m_pUtmZoneCombo->currentText();
// 检查东向坐标值是否真的发生了变化
if(eastingText == m_lastEasting) {
return; // 值没有变化,不进行转换
}
if(!eastingText.isEmpty() && !northingText.isEmpty() && !zoneText.isEmpty()) {
updateFromUTM();
}
}
// 北向坐标编辑完成时的处理
void nmWxGeoRefDlg::onNorthingChanged()
{
if(m_bUpdating) return; // 防止递归更新
QString eastingText = m_pEastingEdit->text();
QString northingText = m_pNorthingEdit->text();
QString zoneText = m_pUtmZoneCombo->currentText();
// 检查北向坐标值是否真的发生了变化
if(northingText == m_lastNorthing) {
return; // 值没有变化,不进行转换
}
if(!eastingText.isEmpty() && !northingText.isEmpty() && !zoneText.isEmpty()) {
updateFromUTM();
}
}
// 更新记录的值
void nmWxGeoRefDlg::updateFromLatLon()
{
m_bUpdating = true; // 设置更新标志
bool ok1, ok2;
double latitude = m_pLatitudeEdit->text().toDouble(&ok1);
double longitude = m_pLongitudeEdit->text().toDouble(&ok2);
if(!ok1 || !ok2) {
QMessageBox::warning(this, tr("Input Error"), tr("Please enter valid numbers"));
// 恢复之前的有效值
m_pLongitudeEdit->setText(m_lastLongitude);
m_pLatitudeEdit->setText(m_lastLatitude);
m_bUpdating = false;
return;
}
// 验证经纬度范围
if(!isValidLatitude(latitude)) {
QMessageBox::warning(this, tr("Input Error"), tr("Latitude must be between - 90o and + 90o"));
// 恢复之前的有效值
m_pLatitudeEdit->setText(m_lastLatitude);
m_bUpdating = false;
return;
}
if(!isValidLongitude(longitude)) {
QMessageBox::warning(this, tr("Input Error"), tr("Longitude must be between - 180o and + 180o"));
// 恢复之前的有效值
m_pLongitudeEdit->setText(m_lastLongitude);
m_bUpdating = false;
return;
}
int zone;
char band;
double easting, northing;
// 执行坐标转换
latLonToUTM(latitude, longitude, zone, band, easting, northing);
// 更新UTM Zone下拉框
QString zoneStr = QString("%1%2").arg(zone, 2, 10, QLatin1Char('0')).arg(band);
int index = m_pUtmZoneCombo->findText(zoneStr);
if(index >= 0) {
m_pUtmZoneCombo->setCurrentIndex(index);
}
// 更新东向和北向坐标
QString eastingStr = QString::number(easting, 'f', 2);
QString northingStr = QString::number(northing, 'f', 2);
m_pEastingEdit->setText(eastingStr);
m_pNorthingEdit->setText(northingStr);
// 转换成功后,更新所有记录的值
m_lastLongitude = m_pLongitudeEdit->text(); // 使用当前输入框的值
m_lastLatitude = m_pLatitudeEdit->text();
m_lastEasting = eastingStr;
m_lastNorthing = northingStr;
m_bUpdating = false; // 清除更新标志
}
// 更新记录的值
void nmWxGeoRefDlg::updateFromUTM()
{
m_bUpdating = true; // 设置更新标志
bool ok1, ok2;
double easting = m_pEastingEdit->text().toDouble(&ok1);
double northing = m_pNorthingEdit->text().toDouble(&ok2);
QString zoneText = m_pUtmZoneCombo->currentText();
if(!ok1 || !ok2) {
QMessageBox::warning(this, tr("Input Error"), tr("Please enter valid numbers"));
restoreLastValidValues();
return;
}
// 验证UTM坐标范围
if(!isValidEasting(easting)) {
QMessageBox::warning(this, tr("Input Error"), tr("Easting must be between 0 and 1,000,000 meters"));
restoreLastValidValues();
return;
}
if(!isValidNorthing(northing)) {
QMessageBox::warning(this, tr("Input Error"), tr("Northing must be between 0 and 10,000,000 meters"));
restoreLastValidValues();
return;
}
if(zoneText.isEmpty()) {
QMessageBox::warning(this, tr("Input Error"), tr("Please select a valid UTM Zone"));
m_bUpdating = false;
return;
}
// 解析UTM Zone
int zone = zoneText.left(2).toInt();
char band = zoneText.right(1).toLocal8Bit().at(0);
double latitude, longitude;
// 执行坐标转换,检查返回值
bool conversionSuccess = utmToLatLon(zone, band, easting, northing, latitude, longitude);
if (!conversionSuccess) {
// 根据具体失败原因给出不同的错误信息
if (band == 'C' || band == 'X' || zone <= 2 || zone >= 59) {
QMessageBox::warning(this, tr("Conversion Error"),
tr("The UTM coordinates you entered correspond to an extreme polar region where coordinate conversion may be inaccurate.\n"
"Please try coordinates closer to the center of the UTM zone."));
} else {
QMessageBox::warning(this, tr("Conversion Error"),
tr("UTM coordinate conversion failed.\n"
"The coordinates may be outside the valid range for this UTM zone.\n"
"Please check your input coordinates."));
}
restoreLastValidValues();
return;
}
// 验证转换结果
if(!isValidLatitude(latitude) || !isValidLongitude(longitude)) {
QMessageBox::warning(this, tr("Conversion Error"), tr("UTM coordinate conversion result is out of valid range, please check input"));
restoreLastValidValues();
return;
}
// 更新经纬度
QString longitudeStr = QString::number(longitude, 'f', 6);
QString latitudeStr = QString::number(latitude, 'f', 6);
m_pLongitudeEdit->setText(longitudeStr);
m_pLatitudeEdit->setText(latitudeStr);
// 转换成功后,更新所有记录的值
m_lastLongitude = longitudeStr;
m_lastLatitude = latitudeStr;
m_lastEasting = m_pEastingEdit->text(); // 使用当前输入框的值
m_lastNorthing = m_pNorthingEdit->text();
m_bUpdating = false; // 清除更新标志
}
// 恢复上次有效值
void nmWxGeoRefDlg::restoreLastValidValues()
{
m_pEastingEdit->setText(m_lastEasting);
m_pNorthingEdit->setText(m_lastNorthing);
m_bUpdating = false;
}
// 更新记录的值
void nmWxGeoRefDlg::onUtmZoneChanged(int index)
{
// 添加这行检查!如果正在更新过程中,直接返回
if(m_bUpdating) return;
// 设置更新标志,防止触发其他转换函数
m_bUpdating = true;
bool enabled = (index >= 0); // 选择了有效的 UTM Zone 时启用
m_pLongitudeEdit->setEnabled(enabled);
m_pLatitudeEdit ->setEnabled(enabled);
m_pEastingEdit ->setEnabled(enabled);
m_pNorthingEdit ->setEnabled(enabled);
if(enabled) {
// 获取选中的 UTM Zone
QString selectedZone = m_pUtmZoneCombo->itemText(index);
// 从选中的 UTM Zone 提取 Zone 和 Band
int zone = selectedZone.left(2).toInt();
QString band = selectedZone.right(1);
// 计算经度Longitude
double longitude = -177.0 + (zone - 1) * 6.0;
QString longitudeStr = QString::number(longitude, 'f', 6);
m_pLongitudeEdit->setText(longitudeStr);
// 计算纬度Latitude
QStringList bands;
bands << "C" << "D" << "E" << "F" << "G" << "H" << "J" << "K" << "L" << "M"
<< "N" << "P" << "Q" << "R" << "S" << "T" << "U" << "V" << "W" << "X";
int bandIndex = bands.indexOf(band);
double latitude = -76.0;
if(bandIndex >= 0) {
if(bandIndex < bands.indexOf("X")) {
// X之前的所有band每个递增8度
latitude += bandIndex * 8.0;
} else {
// X bandW到X跨度为10度
latitude += (bandIndex - 1) * 8.0 + 10.0;
}
}
QString latitudeStr = QString::number(latitude, 'f', 6);
m_pLatitudeEdit->setText(latitudeStr);
// 设置东向坐标Easting
double easting = 50000.00;
QString eastingStr = QString::number(easting, 'f', 2);
m_pEastingEdit->setText(eastingStr);
// 设置北向坐标Northing
double northing = calculateNorthing(latitude, longitude, zone);
QString northingStr = QString::number(northing, 'f', 2);
m_pNorthingEdit->setText(northingStr);
// 更新记录的所有值
m_lastLongitude = longitudeStr;
m_lastLatitude = latitudeStr;
m_lastEasting = eastingStr;
m_lastNorthing = northingStr;
}
// 清除更新标志
m_bUpdating = false;
}
// 经纬度转UTM坐标
void nmWxGeoRefDlg::latLonToUTM(double lat, double lon, int& zone, char& band, double& easting, double& northing)
{
// 确定UTM Zone
zone = getUTMZoneFromLongitude(lon);
band = getUTMBandFromLatitude(lat);
// WGS84椭球体参数
const double a = 6378137.0; // 长半轴
const double e2 = 0.00669437999014; // 第一偏心率的平方
const double k0 = 0.9996; // 比例因子
// 转换为弧度
double lat_rad = lat * M_PI / 180.0;
double lon_rad = lon * M_PI / 180.0;
// 中央经线
double lon0 = -183.0 + zone * 6.0;
double lon0_rad = lon0 * M_PI / 180.0;
double dlon = lon_rad - lon0_rad;
// UTM投影计算
double N = a / sqrt(1 - e2 * sin(lat_rad) * sin(lat_rad));
double T = tan(lat_rad) * tan(lat_rad);
double C = e2 * cos(lat_rad) * cos(lat_rad) / (1 - e2);
double A = cos(lat_rad) * dlon;
double M = a * ((1 - e2 / 4 - 3 * e2 * e2 / 64 - 5 * e2 * e2 * e2 / 256) * lat_rad
- (3 * e2 / 8 + 3 * e2 * e2 / 32 + 45 * e2 * e2 * e2 / 1024) * sin(2 * lat_rad)
+ (15 * e2 * e2 / 256 + 45 * e2 * e2 * e2 / 1024) * sin(4 * lat_rad)
- (35 * e2 * e2 * e2 / 3072) * sin(6 * lat_rad));
// 计算东向坐标
easting = k0 * N * (A + (1 - T + C) * A * A * A / 6
+ (5 - 18 * T + T * T + 72 * C - 58 * e2) * A * A * A * A * A / 120) + 500000.0;
// 计算北向坐标
northing = k0 * (M + N * tan(lat_rad) * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A / 24
+ (61 - 58 * T + T * T + 600 * C - 330 * e2) * A * A * A * A * A * A / 720));
// 南半球需要加上假北值
if(lat < 0) {
northing += 10000000.0;
}
}
// UTM坐标转经纬度
bool nmWxGeoRefDlg::utmToLatLon(int zone, char band, double easting, double northing, double& lat, double& lon)
{
// WGS84椭球体参数
const double a = 6378137.0; // 长半轴 (米)
const double f = 1.0 / 298.257223563; // 扁率
const double e2 = 2 * f - f * f; // 第一偏心率的平方
const double k0 = 0.9996; // UTM比例因子
const double e1 = (1 - sqrt(1 - e2)) / (1 + sqrt(1 - e2));
// 中央经线经度
double lon0 = -183.0 + zone * 6.0;
// 调整北向坐标(南半球处理)
double y = northing;
if(band < 'N') { // 南半球
y -= 10000000.0;
}
// 调整东向坐标
double x = easting - 500000.0;
// 计算足点纬度
double M = y / k0;
double mu = M / (a * (1 - e2 / 4 - 3 * e2 * e2 / 64 - 5 * e2 * e2 * e2 / 256));
// 使用级数展开计算足点纬度
double phi1 = mu + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * sin(2 * mu)
+ (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * sin(4 * mu)
+ (151 * e1 * e1 * e1 / 96) * sin(6 * mu)
+ (1097 * e1 * e1 * e1 * e1 / 512) * sin(8 * mu);
// cos(phi1)是否过小
if (fabs(cos(phi1)) < 1e-6) {
// 设置默认值,让调用方知道转换失败
lat = 0.0;
lon = 0.0;
return false; // 返回false表示转换失败
}
// 计算各种参数
double C1 = e2 * cos(phi1) * cos(phi1) / (1 - e2);
double T1 = tan(phi1) * tan(phi1);
double N1 = a / sqrt(1 - e2 * sin(phi1) * sin(phi1));
double R1 = a * (1 - e2) / pow(1 - e2 * sin(phi1) * sin(phi1), 1.5);
double D = x / (N1 * k0);
// 计算纬度(弧度)
double lat_rad = phi1 - (N1 * tan(phi1) / R1) *
(D * D / 2 - (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1 - 9 * e2) * D * D * D * D / 24
+ (61 + 90 * T1 + 298 * C1 + 45 * T1 * T1 - 252 * e2 - 3 * C1 * C1) * D * D * D * D * D * D / 720);
// 计算经度(弧度)
double lon_rad = (D - (1 + 2 * T1 + C1) * D * D * D / 6
+ (5 - 2 * C1 + 28 * T1 - 3 * C1 * C1 + 8 * e2 + 24 * T1 * T1) * D * D * D * D * D / 120) / cos(phi1);
// 转换为度并加上中央经线
lat = lat_rad * 180.0 / M_PI;
lon = lon0 + lon_rad * 180.0 / M_PI;
// 第二个检查:确保结果在合理范围内
if (lat != lat || lon != lon || // 检查NaN
fabs(lat) > 90.0 || // 纬度必须在-90到90之间
fabs(lon - lon0) > 180.0) { // 经度距离中央经线不应超过180度
// 设置默认值
lat = 0.0;
lon = 0.0;
return false; // 返回false表示转换失败
}
// 确保经度在有效范围内
while(lon > 180.0) lon -= 360.0;
while(lon < -180.0) lon += 360.0;
return true; // 转换成功
}
// 根据经度确定UTM Zone
int nmWxGeoRefDlg::getUTMZoneFromLongitude(double longitude)
{
return (int)floor((longitude + 180.0) / 6.0) + 1;
}
// 根据纬度确定UTM Band
char nmWxGeoRefDlg::getUTMBandFromLatitude(double latitude)
{
const char bands[] = "CDEFGHJKLMNPQRSTUVWX";
int index = (int)floor((latitude + 80.0) / 8.0);
if(index < 0) return 'C';
if(index >= 20) return 'X';
return bands[index];
}
bool nmWxGeoRefDlg::isValidLatitude(double lat)
{
return (lat >= -90.0 && lat <= 90.0);
}
// 验证经度范围
bool nmWxGeoRefDlg::isValidLongitude(double lon)
{
return (lon >= -180.0 && lon <= 180.0);
}
// 验证东向坐标范围
bool nmWxGeoRefDlg::isValidEasting(double easting)
{
// 基本UTM范围检查
if (easting < 0.0 || easting > 1000000.0) {
return false;
}
// 获取坐标轴数据,考虑画布范围
nmDataAxis* axisData = nmDataAnalyzeManager::getCurrentInstance()->getAxisData();
if (axisData) {
double xMin = axisData->getXMin().getValue().toDouble();
double xMax = axisData->getXMax().getValue().toDouble();
// 计算基准坐标的安全范围
double safeEastingMin = 160000.0 - xMin; // UTM东向最小值 - 画布最小X
double safeEastingMax = 840000.0 - xMax; // UTM东向最大值 - 画布最大X
// 确保范围有效
if (safeEastingMin < 0.0) safeEastingMin = 0.0;
if (safeEastingMax > 1000000.0) safeEastingMax = 1000000.0;
if (safeEastingMin >= safeEastingMax) {
safeEastingMin = 0.0;
safeEastingMax = 1000000.0;
}
return (easting >= safeEastingMin && easting <= safeEastingMax);
}
return true; // 如果没有坐标轴数据,使用默认验证
}
// 验证北向坐标范围
bool nmWxGeoRefDlg::isValidNorthing(double northing)
{
// 基本UTM范围检查
if (northing < 0.0 || northing > 10000000.0) {
return false;
}
// 获取坐标轴数据,考虑画布范围
nmDataAxis* axisData = nmDataAnalyzeManager::getCurrentInstance()->getAxisData();
if (axisData) {
double yMin = axisData->getYMin().getValue().toDouble();
double yMax = axisData->getYMax().getValue().toDouble();
// 计算基准坐标的安全范围
double safeNorthingMin = 0.0 - yMin; // UTM北向最小值 - 画布最小Y
double safeNorthingMax = 9000000.0 - yMax; // UTM北向最大值 - 画布最大Y
// 确保范围有效
if (safeNorthingMin < 0.0) safeNorthingMin = 0.0;
if (safeNorthingMax > 10000000.0) safeNorthingMax = 10000000.0;
if (safeNorthingMin >= safeNorthingMax) {
safeNorthingMin = 0.0;
safeNorthingMax = 10000000.0;
}
return (northing >= safeNorthingMin && northing <= safeNorthingMax);
}
return true; // 如果没有坐标轴数据,使用默认验证
}
void nmWxGeoRefDlg::loadDataToUI()
{
m_bUpdating = true;
// 检查UTM Zone是否有效
QString utmZone = m_geoRefData.getUtmZone().getValue().toString();
bool hasValidData = !utmZone.isEmpty();
if(hasValidData) {
// 有有效数据时,加载所有数据
QString lonStr = QString::number(m_geoRefData.getLongitude().getValue().toDouble(), 'f', 6);
m_pLongitudeEdit->setText(lonStr);
m_lastLongitude = lonStr;
QString latStr = QString::number(m_geoRefData.getLatitude().getValue().toDouble(), 'f', 6);
m_pLatitudeEdit->setText(latStr);
m_lastLatitude = latStr;
int index = m_pUtmZoneCombo->findText(utmZone);
if(index >= 0) {
m_pUtmZoneCombo->setCurrentIndex(index);
}
QString eastingStr = QString::number(m_geoRefData.getEasting().getValue().toDouble(), 'f', 2);
m_pEastingEdit->setText(eastingStr);
m_lastEasting = eastingStr;
QString northingStr = QString::number(m_geoRefData.getNorthing().getValue().toDouble(), 'f', 2);
m_pNorthingEdit->setText(northingStr);
m_lastNorthing = northingStr;
// 启用所有控件
m_pLongitudeEdit->setEnabled(true);
m_pLatitudeEdit->setEnabled(true);
m_pEastingEdit->setEnabled(true);
m_pNorthingEdit->setEnabled(true);
} else {
// 无有效数据时清空所有文本框初始化last值
m_pLongitudeEdit->setText("");
m_pLatitudeEdit->setText("");
m_pEastingEdit->setText("");
m_pNorthingEdit->setText("");
m_lastLongitude = "";
m_lastLatitude = "";
m_lastEasting = "";
m_lastNorthing = "";
}
m_bUpdating = false;
}
void nmWxGeoRefDlg::saveDataUI()
{
// 保存经度
nmDataAttribute longitude = m_geoRefData.getLongitude();
double lonValue = m_pLongitudeEdit->text().toDouble();
longitude.setValue(lonValue);
m_geoRefData.setLongitude(longitude);
// 保存纬度
nmDataAttribute latitude = m_geoRefData.getLatitude();
double latValue = m_pLatitudeEdit->text().toDouble();
latitude.setValue(latValue);
m_geoRefData.setLatitude(latitude);
// 保存UTM Zone
nmDataAttribute utmZone = m_geoRefData.getUtmZone();
utmZone.setValue(QVariant(m_pUtmZoneCombo->currentText()));
m_geoRefData.setUtmZone(utmZone);
// 保存东向坐标
nmDataAttribute easting = m_geoRefData.getEasting();
double estValue = m_pEastingEdit->text().toDouble();
easting.setValue(estValue);
m_geoRefData.setEasting(easting);
// 保存北向坐标
nmDataAttribute northing = m_geoRefData.getNorthing();
double norValue = m_pNorthingEdit->text().toDouble();
northing.setValue(norValue);
m_geoRefData.setNorthing(northing);
}
void nmWxGeoRefDlg::okAccept()
{
saveDataUI();
// 更新到全局数据管理器
nmDataAnalyzeManager::getCurrentInstance()->updateGeoRefData(m_geoRefData);
// 调用基类的accept
iDlgBase::accept();
}
void nmWxGeoRefDlg::cancelReject()
{
// 调用基类的reject
iDlgBase::reject();
}