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

#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)
: QDialog(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
QDialog::accept();
}
void nmWxGeoRefDlg::cancelReject()
{
// 调用基类的reject
QDialog::reject();
}