|
|
#include "nmWxPropertyInterpolationDlg.h"
|
|
|
|
|
|
#include <QAbstractItemView>
|
|
|
#include <QApplication>
|
|
|
#include <QCheckBox>
|
|
|
#include <QComboBox>
|
|
|
#include <QCoreApplication>
|
|
|
#include <QDoubleSpinBox>
|
|
|
#include <QEvent>
|
|
|
#include <QFormLayout>
|
|
|
#include <QGroupBox>
|
|
|
#include <QHBoxLayout>
|
|
|
#include <QHeaderView>
|
|
|
#include <QIcon>
|
|
|
#include <QLabel>
|
|
|
#include <QLineEdit>
|
|
|
#include <QMessageBox>
|
|
|
#include <QMouseEvent>
|
|
|
#include <QPainter>
|
|
|
#include <QPolygonF>
|
|
|
#include <QPushButton>
|
|
|
#include <QSize>
|
|
|
#include <QTableWidget>
|
|
|
#include <QTableWidgetItem>
|
|
|
#include <QTransform>
|
|
|
#include <QVBoxLayout>
|
|
|
#include <QtCore/qmath.h>
|
|
|
|
|
|
#include "nmCalculationUtils.h"
|
|
|
#include "nmDataOutline.h"
|
|
|
#include "nmGuiPlot.h"
|
|
|
#include "nmObjPoint.h"
|
|
|
#include "nmWxPropertyInterpolationPreviewDlg.h"
|
|
|
#include "tCurvePlotView.h"
|
|
|
#include "ZxObjText.h"
|
|
|
#include "ZxPlot.h"
|
|
|
|
|
|
namespace
|
|
|
{
|
|
|
// 使用独立翻译上下文,便于统一维护对话框文本.
|
|
|
QString interpolationText(const char* sourceText)
|
|
|
{
|
|
|
return QCoreApplication::translate("nmWxPropertyInterpolationDlg", sourceText);
|
|
|
}
|
|
|
|
|
|
// 创建统一格式的非负数值输入框.
|
|
|
QDoubleSpinBox* createNumberSpinBox(QWidget* parent, double value)
|
|
|
{
|
|
|
QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
|
|
|
spinBox->setRange(0.0, 1.0e12);
|
|
|
spinBox->setDecimals(6);
|
|
|
spinBox->setValue(value);
|
|
|
spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
|
|
return spinBox;
|
|
|
}
|
|
|
|
|
|
// 插值测点使用独立的小方块标记,避免与井图元混淆.
|
|
|
class PropertyInterpolationMarker : public nmObjPoint
|
|
|
{
|
|
|
public:
|
|
|
PropertyInterpolationMarker(const QString& name,
|
|
|
ZxSubAxisX* axisX,
|
|
|
ZxSubAxisY* axisY)
|
|
|
: nmObjPoint(name, axisX, axisY)
|
|
|
{
|
|
|
setDotRadius(1.0);
|
|
|
}
|
|
|
|
|
|
virtual bool drawWellPos(QPainter* painter, QPointF point) override
|
|
|
{
|
|
|
if(painter == NULL) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
const QTransform transform = painter->combinedTransform();
|
|
|
qreal scaleX = qAbs(transform.m11());
|
|
|
qreal scaleY = qAbs(transform.m22());
|
|
|
|
|
|
if(scaleX < 0.0001) {
|
|
|
scaleX = 1.0;
|
|
|
}
|
|
|
|
|
|
if(scaleY < 0.0001) {
|
|
|
scaleY = 1.0;
|
|
|
}
|
|
|
|
|
|
const qreal halfPixelSize = 3.0;
|
|
|
QRectF markerRect(point.x() - halfPixelSize / scaleX,
|
|
|
point.y() - halfPixelSize / scaleY,
|
|
|
halfPixelSize * 2.0 / scaleX,
|
|
|
halfPixelSize * 2.0 / scaleY);
|
|
|
|
|
|
painter->save();
|
|
|
QPen pen(QColor(0, 25, 100));
|
|
|
pen.setWidthF(1.0);
|
|
|
pen.setCosmetic(true);
|
|
|
painter->setPen(pen);
|
|
|
painter->setBrush(QColor(0, 70, 200));
|
|
|
painter->drawRect(markerRect);
|
|
|
painter->restore();
|
|
|
return true;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
void setMarkerLabel(nmObjPoint* marker, const QString& text)
|
|
|
{
|
|
|
if(marker == NULL || marker->getChildren().isEmpty()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
ZxObjText* label = dynamic_cast<ZxObjText*>(marker->at(0));
|
|
|
if(label != NULL) {
|
|
|
label->setText(text);
|
|
|
label->setTextColor(QColor(30, 30, 30));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 将储层边界转换成预览裁剪使用的多边形,并计算规则采样范围.
|
|
|
bool createPreviewOutline(nmDataOutline* outline,
|
|
|
QVector<QPointF>& outlinePoints,
|
|
|
QRectF& bounds)
|
|
|
{
|
|
|
outlinePoints.clear();
|
|
|
bounds = QRectF();
|
|
|
if(outline == NULL) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if(outline->getOutlineType() == NM_Round_Outline_Type) {
|
|
|
// 圆形边界离散成多边形,便于预览窗口统一裁剪.
|
|
|
const QPointF center = outline->getCenter();
|
|
|
const double radius = outline->getRadius();
|
|
|
if(radius <= 0.0) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
const int segmentCount = 72;
|
|
|
const double fullCircle = 6.28318530717958647692;
|
|
|
for(int i = 0; i < segmentCount; ++i) {
|
|
|
const double angle = fullCircle * i / segmentCount;
|
|
|
outlinePoints.append(QPointF(center.x() + radius * qCos(angle),
|
|
|
center.y() + radius * qSin(angle)));
|
|
|
}
|
|
|
} else {
|
|
|
outlinePoints = outline->getOutlinePoints();
|
|
|
if(outlinePoints.size() > 3 &&
|
|
|
outlinePoints.first() == outlinePoints.last()) {
|
|
|
outlinePoints.remove(outlinePoints.size() - 1);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if(outlinePoints.size() < 3) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
bounds = QPolygonF(outlinePoints).boundingRect().normalized();
|
|
|
return bounds.width() > 0.0 && bounds.height() > 0.0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
nmWxPropertyInterpolationDlg::nmWxPropertyInterpolationDlg(
|
|
|
nmGuiPlot* plot,
|
|
|
nmDataAnalyzeManager* dataManager,
|
|
|
QWidget* parent)
|
|
|
: iDlgBase(parent),
|
|
|
m_pPlot(plot),
|
|
|
m_pDataManager(dataManager),
|
|
|
m_pDataSetCombo(NULL),
|
|
|
m_pAddDataSetButton(NULL),
|
|
|
m_pDeleteDataSetButton(NULL),
|
|
|
m_nCurrentDataSetIndex(-1),
|
|
|
m_nNextPointId(0),
|
|
|
m_bUpdatingUi(true),
|
|
|
m_pPropertyCombo(NULL),
|
|
|
m_pNameEdit(NULL),
|
|
|
m_pNewValueSpin(NULL),
|
|
|
m_pMapPickButton(NULL),
|
|
|
m_pPointTable(NULL),
|
|
|
m_pDeletePointButton(NULL),
|
|
|
m_pClearPointsButton(NULL),
|
|
|
m_pShowPointsCheck(NULL),
|
|
|
m_pShowLabelsCheck(NULL),
|
|
|
m_pNuggetSpin(NULL),
|
|
|
m_pSillSpin(NULL),
|
|
|
m_pRangeSpin(NULL),
|
|
|
m_pModelCombo(NULL),
|
|
|
m_pPreviewButton(NULL),
|
|
|
m_pApplyButton(NULL)
|
|
|
{
|
|
|
setWindowTitle(interpolationText("Property Interpolation"));
|
|
|
setWindowModality(Qt::NonModal);
|
|
|
setModal(false);
|
|
|
setMinimumSize(520, 620);
|
|
|
resize(560, 680);
|
|
|
initInterpolationUI();
|
|
|
initializeDataSets();
|
|
|
|
|
|
if(qApp != NULL) {
|
|
|
qApp->installEventFilter(this);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
nmWxPropertyInterpolationDlg::~nmWxPropertyInterpolationDlg()
|
|
|
{
|
|
|
if(qApp != NULL) {
|
|
|
qApp->removeEventFilter(this);
|
|
|
}
|
|
|
|
|
|
onMapPickToggled(false);
|
|
|
saveCurrentDataSet();
|
|
|
syncDataSetsToManager(false);
|
|
|
removeAllMarkers();
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::initInterpolationUI()
|
|
|
{
|
|
|
QVBoxLayout* mainLayout = new QVBoxLayout(this);
|
|
|
|
|
|
// 数据组创建、切换及删除.
|
|
|
QHBoxLayout* dataSetSelectLayout = new QHBoxLayout;
|
|
|
dataSetSelectLayout->addWidget(new QLabel(interpolationText("Dataset:"), this));
|
|
|
m_pDataSetCombo = new QComboBox(this);
|
|
|
dataSetSelectLayout->addWidget(m_pDataSetCombo, 1);
|
|
|
|
|
|
QString iconDir = QCoreApplication::applicationDirPath();
|
|
|
iconDir = iconDir.section('/', 0, -2) + "/Res/Icon/";
|
|
|
|
|
|
m_pAddDataSetButton = new QPushButton(this);
|
|
|
m_pAddDataSetButton->setIcon(QIcon(iconDir + "Add.png"));
|
|
|
m_pAddDataSetButton->setIconSize(QSize(18, 18));
|
|
|
m_pAddDataSetButton->setFixedSize(28, 28);
|
|
|
m_pAddDataSetButton->setToolTip(interpolationText("Add dataset"));
|
|
|
dataSetSelectLayout->addWidget(m_pAddDataSetButton);
|
|
|
|
|
|
m_pDeleteDataSetButton = new QPushButton(this);
|
|
|
m_pDeleteDataSetButton->setIcon(QIcon(iconDir + "NmDelete.png"));
|
|
|
m_pDeleteDataSetButton->setIconSize(QSize(18, 18));
|
|
|
m_pDeleteDataSetButton->setFixedSize(28, 28);
|
|
|
m_pDeleteDataSetButton->setToolTip(interpolationText("Delete dataset"));
|
|
|
dataSetSelectLayout->addWidget(m_pDeleteDataSetButton);
|
|
|
mainLayout->addLayout(dataSetSelectLayout);
|
|
|
|
|
|
// 当前数据组的名称和属性.
|
|
|
QFormLayout* dataSetLayout = new QFormLayout;
|
|
|
m_pNameEdit = new QLineEdit(this);
|
|
|
dataSetLayout->addRow(interpolationText("Name:"), m_pNameEdit);
|
|
|
|
|
|
m_pPropertyCombo = new QComboBox(this);
|
|
|
m_pPropertyCombo->addItem(interpolationText("Permeability k"), QString("k"));
|
|
|
m_pPropertyCombo->addItem(interpolationText("Porosity phi"), QString("phi"));
|
|
|
m_pPropertyCombo->addItem(interpolationText("Reservoir thickness h"), QString("h"));
|
|
|
dataSetLayout->addRow(interpolationText("Property:"), m_pPropertyCombo);
|
|
|
mainLayout->addLayout(dataSetLayout);
|
|
|
|
|
|
// 测点数据录入区域.
|
|
|
QGroupBox* pointGroup = new QGroupBox(interpolationText("Measurement Points"), this);
|
|
|
QVBoxLayout* pointLayout = new QVBoxLayout(pointGroup);
|
|
|
|
|
|
QHBoxLayout* newPointLayout = new QHBoxLayout;
|
|
|
newPointLayout->addWidget(new QLabel(interpolationText("New value:"), pointGroup));
|
|
|
m_pNewValueSpin = createNumberSpinBox(pointGroup, 0.0);
|
|
|
newPointLayout->addWidget(m_pNewValueSpin, 1);
|
|
|
m_pMapPickButton = new QPushButton(interpolationText("Select on Map"), pointGroup);
|
|
|
m_pMapPickButton->setCheckable(true);
|
|
|
m_pMapPickButton->setEnabled(!m_pPlot.isNull() &&
|
|
|
m_pPlot->m_pPlotView != NULL &&
|
|
|
m_pPlot->m_pPlot != NULL);
|
|
|
newPointLayout->addWidget(m_pMapPickButton);
|
|
|
pointLayout->addLayout(newPointLayout);
|
|
|
|
|
|
m_pPointTable = new QTableWidget(0, 3, pointGroup);
|
|
|
QStringList headers;
|
|
|
headers << interpolationText("X") << interpolationText("Y") << interpolationText("Value");
|
|
|
m_pPointTable->setHorizontalHeaderLabels(headers);
|
|
|
m_pPointTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
|
|
|
m_pPointTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
|
m_pPointTable->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
|
m_pPointTable->setAlternatingRowColors(true);
|
|
|
pointLayout->addWidget(m_pPointTable, 1);
|
|
|
|
|
|
QHBoxLayout* pointButtonLayout = new QHBoxLayout;
|
|
|
pointButtonLayout->addStretch();
|
|
|
m_pDeletePointButton = new QPushButton(interpolationText("Delete Selected"), pointGroup);
|
|
|
m_pDeletePointButton->setEnabled(false);
|
|
|
pointButtonLayout->addWidget(m_pDeletePointButton);
|
|
|
m_pClearPointsButton = new QPushButton(interpolationText("Clear"), pointGroup);
|
|
|
m_pClearPointsButton->setEnabled(false);
|
|
|
pointButtonLayout->addWidget(m_pClearPointsButton);
|
|
|
pointLayout->addLayout(pointButtonLayout);
|
|
|
|
|
|
QHBoxLayout* displayLayout = new QHBoxLayout;
|
|
|
m_pShowPointsCheck = new QCheckBox(interpolationText("Show measurement points"), pointGroup);
|
|
|
m_pShowPointsCheck->setChecked(true);
|
|
|
displayLayout->addWidget(m_pShowPointsCheck);
|
|
|
m_pShowLabelsCheck = new QCheckBox(interpolationText("Show labels"), pointGroup);
|
|
|
m_pShowLabelsCheck->setChecked(true);
|
|
|
displayLayout->addWidget(m_pShowLabelsCheck);
|
|
|
displayLayout->addStretch();
|
|
|
pointLayout->addLayout(displayLayout);
|
|
|
mainLayout->addWidget(pointGroup, 1);
|
|
|
|
|
|
// Kriging插值参数设置.
|
|
|
QGroupBox* parameterGroup = new QGroupBox(interpolationText("Kriging Parameters"), this);
|
|
|
QFormLayout* parameterLayout = new QFormLayout(parameterGroup);
|
|
|
m_pNuggetSpin = createNumberSpinBox(parameterGroup, 0.01);
|
|
|
parameterLayout->addRow(interpolationText("Nugget:"), m_pNuggetSpin);
|
|
|
m_pSillSpin = createNumberSpinBox(parameterGroup, 100.0);
|
|
|
parameterLayout->addRow(interpolationText("Sill:"), m_pSillSpin);
|
|
|
m_pRangeSpin = createNumberSpinBox(parameterGroup, 1000.0);
|
|
|
parameterLayout->addRow(interpolationText("Range:"), m_pRangeSpin);
|
|
|
m_pModelCombo = new QComboBox(parameterGroup);
|
|
|
m_pModelCombo->addItem(interpolationText("Spherical (0)"), 0);
|
|
|
m_pModelCombo->addItem(interpolationText("Exponential (1)"), 1);
|
|
|
m_pModelCombo->addItem(interpolationText("Gaussian (2)"), 2);
|
|
|
parameterLayout->addRow(interpolationText("Model:"), m_pModelCombo);
|
|
|
mainLayout->addWidget(parameterGroup);
|
|
|
|
|
|
// 底部操作按钮.
|
|
|
QHBoxLayout* buttonLayout = new QHBoxLayout;
|
|
|
m_pPreviewButton = new QPushButton(interpolationText("Preview"), this);
|
|
|
m_pPreviewButton->setEnabled(false);
|
|
|
buttonLayout->addWidget(m_pPreviewButton);
|
|
|
buttonLayout->addStretch();
|
|
|
m_pApplyButton = new QPushButton(interpolationText("Apply"), this);
|
|
|
m_pApplyButton->setEnabled(false);
|
|
|
buttonLayout->addWidget(m_pApplyButton);
|
|
|
QPushButton* closeButton = new QPushButton(interpolationText("Close"), this);
|
|
|
buttonLayout->addWidget(closeButton);
|
|
|
mainLayout->addLayout(buttonLayout);
|
|
|
|
|
|
connect(m_pDataSetCombo, SIGNAL(currentIndexChanged(int)),
|
|
|
this, SLOT(onDataSetChanged(int)));
|
|
|
connect(m_pAddDataSetButton, SIGNAL(clicked()), this, SLOT(onAddDataSet()));
|
|
|
connect(m_pDeleteDataSetButton, SIGNAL(clicked()), this, SLOT(onDeleteDataSet()));
|
|
|
connect(m_pNameEdit, SIGNAL(textChanged(QString)),
|
|
|
this, SLOT(onDataSetNameChanged(QString)));
|
|
|
connect(m_pPropertyCombo, SIGNAL(currentIndexChanged(int)),
|
|
|
this, SLOT(onCurrentDataSetEdited()));
|
|
|
connect(m_pNuggetSpin, SIGNAL(valueChanged(double)),
|
|
|
this, SLOT(onCurrentDataSetEdited()));
|
|
|
connect(m_pSillSpin, SIGNAL(valueChanged(double)),
|
|
|
this, SLOT(onCurrentDataSetEdited()));
|
|
|
connect(m_pRangeSpin, SIGNAL(valueChanged(double)),
|
|
|
this, SLOT(onCurrentDataSetEdited()));
|
|
|
connect(m_pModelCombo, SIGNAL(currentIndexChanged(int)),
|
|
|
this, SLOT(onCurrentDataSetEdited()));
|
|
|
connect(m_pMapPickButton, SIGNAL(toggled(bool)), this, SLOT(onMapPickToggled(bool)));
|
|
|
connect(m_pPointTable, SIGNAL(itemSelectionChanged()),
|
|
|
this, SLOT(onPointSelectionChanged()));
|
|
|
connect(m_pPointTable, SIGNAL(itemChanged(QTableWidgetItem*)),
|
|
|
this, SLOT(onPointItemChanged(QTableWidgetItem*)));
|
|
|
connect(m_pDeletePointButton, SIGNAL(clicked()), this, SLOT(onDeleteSelectedPoint()));
|
|
|
connect(m_pClearPointsButton, SIGNAL(clicked()), this, SLOT(onClearPoints()));
|
|
|
connect(m_pShowPointsCheck, SIGNAL(toggled(bool)), this, SLOT(onShowPointsToggled(bool)));
|
|
|
connect(m_pShowLabelsCheck, SIGNAL(toggled(bool)), this, SLOT(onShowLabelsToggled(bool)));
|
|
|
connect(m_pPreviewButton, SIGNAL(clicked()), this, SLOT(onPreview()));
|
|
|
connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::initializeDataSets()
|
|
|
{
|
|
|
m_bUpdatingUi = true;
|
|
|
|
|
|
if(!m_pDataManager.isNull()) {
|
|
|
m_vecDataSets = m_pDataManager->getPropertyInterpolationDataSets();
|
|
|
}
|
|
|
|
|
|
bool dataChanged = false;
|
|
|
for(int i = 0; i < m_vecDataSets.size(); ++i) {
|
|
|
if(m_vecDataSets[i].name.isEmpty()) {
|
|
|
m_vecDataSets[i].name = nextDataSetName();
|
|
|
dataChanged = true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
m_vecMarkerNames.resize(m_vecDataSets.size());
|
|
|
// 测点标记不参与持久化,打开对话框时根据已保存测点重新创建.
|
|
|
createMarkersForAllDataSets();
|
|
|
|
|
|
bool oldBlock = m_pDataSetCombo->blockSignals(true);
|
|
|
m_pDataSetCombo->clear();
|
|
|
for(int i = 0; i < m_vecDataSets.size(); ++i) {
|
|
|
m_pDataSetCombo->addItem(m_vecDataSets[i].name);
|
|
|
}
|
|
|
const int initialIndex = m_vecDataSets.isEmpty() ? -1 : 0;
|
|
|
m_pDataSetCombo->setCurrentIndex(initialIndex);
|
|
|
m_pDataSetCombo->blockSignals(oldBlock);
|
|
|
|
|
|
m_nCurrentDataSetIndex = initialIndex;
|
|
|
loadDataSet(initialIndex);
|
|
|
m_bUpdatingUi = false;
|
|
|
updateDataSetButtons();
|
|
|
|
|
|
if(dataChanged) {
|
|
|
syncDataSetsToManager(false);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
nmPropertyInterpolationDataSet nmWxPropertyInterpolationDlg::createDefaultDataSet()
|
|
|
{
|
|
|
nmPropertyInterpolationDataSet dataSet;
|
|
|
dataSet.name = nextDataSetName();
|
|
|
dataSet.property = "k";
|
|
|
dataSet.showPoints = true;
|
|
|
dataSet.showLabels = true;
|
|
|
dataSet.nugget = 0.01;
|
|
|
dataSet.sill = 100.0;
|
|
|
dataSet.range = 1000.0;
|
|
|
dataSet.model = 0;
|
|
|
return dataSet;
|
|
|
}
|
|
|
|
|
|
QString nmWxPropertyInterpolationDlg::nextDataSetName()
|
|
|
{
|
|
|
for(int number = 1; ; ++number) {
|
|
|
const QString name = interpolationText("Dataset #%1").arg(number);
|
|
|
bool exists = false;
|
|
|
for(int i = 0; i < m_vecDataSets.size(); ++i) {
|
|
|
if(m_vecDataSets[i].name == name) {
|
|
|
exists = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if(!exists) {
|
|
|
return name;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::loadDataSet(int index)
|
|
|
{
|
|
|
if(index < 0 || index >= m_vecDataSets.size()) {
|
|
|
clearCurrentDataSet();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 切换数据组时批量刷新控件,避免控件信号被误判为用户修改.
|
|
|
bool wasUpdating = m_bUpdatingUi;
|
|
|
m_bUpdatingUi = true;
|
|
|
const nmPropertyInterpolationDataSet& dataSet = m_vecDataSets[index];
|
|
|
|
|
|
m_pNameEdit->setText(dataSet.name);
|
|
|
int propertyIndex = m_pPropertyCombo->findData(dataSet.property);
|
|
|
m_pPropertyCombo->setCurrentIndex(propertyIndex < 0 ? 0 : propertyIndex);
|
|
|
m_pNuggetSpin->setValue(dataSet.nugget);
|
|
|
m_pSillSpin->setValue(dataSet.sill);
|
|
|
m_pRangeSpin->setValue(dataSet.range);
|
|
|
int modelIndex = m_pModelCombo->findData(dataSet.model);
|
|
|
m_pModelCombo->setCurrentIndex(modelIndex < 0 ? 0 : modelIndex);
|
|
|
m_pShowPointsCheck->setChecked(dataSet.showPoints);
|
|
|
m_pShowLabelsCheck->setChecked(dataSet.showLabels);
|
|
|
|
|
|
bool oldTableBlock = m_pPointTable->blockSignals(true);
|
|
|
m_pPointTable->setRowCount(0);
|
|
|
const QStringList markerNames = m_vecMarkerNames.value(index);
|
|
|
for(int i = 0; i < dataSet.points.size(); ++i) {
|
|
|
appendPointRow(dataSet.points[i], markerNames.value(i));
|
|
|
}
|
|
|
m_pPointTable->blockSignals(oldTableBlock);
|
|
|
|
|
|
clearTableSelection();
|
|
|
updatePointButtons();
|
|
|
updateCurrentMarkerVisibility();
|
|
|
m_bUpdatingUi = wasUpdating;
|
|
|
updateDataSetButtons();
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::clearCurrentDataSet()
|
|
|
{
|
|
|
bool wasUpdating = m_bUpdatingUi;
|
|
|
m_bUpdatingUi = true;
|
|
|
|
|
|
if(m_pMapPickButton->isChecked()) {
|
|
|
m_pMapPickButton->setChecked(false);
|
|
|
}
|
|
|
m_pNameEdit->clear();
|
|
|
m_pPropertyCombo->setCurrentIndex(-1);
|
|
|
m_pNewValueSpin->setValue(0.0);
|
|
|
m_pPointTable->setRowCount(0);
|
|
|
m_pShowPointsCheck->setChecked(false);
|
|
|
m_pShowLabelsCheck->setChecked(false);
|
|
|
m_pNuggetSpin->setValue(0.01);
|
|
|
m_pSillSpin->setValue(100.0);
|
|
|
m_pRangeSpin->setValue(1000.0);
|
|
|
m_pModelCombo->setCurrentIndex(-1);
|
|
|
|
|
|
clearTableSelection();
|
|
|
m_bUpdatingUi = wasUpdating;
|
|
|
updateDataSetButtons();
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::saveCurrentDataSet()
|
|
|
{
|
|
|
if(m_nCurrentDataSetIndex < 0 ||
|
|
|
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
nmPropertyInterpolationDataSet& dataSet = m_vecDataSets[m_nCurrentDataSetIndex];
|
|
|
dataSet.name = m_pNameEdit->text();
|
|
|
dataSet.property = m_pPropertyCombo->itemData(m_pPropertyCombo->currentIndex()).toString();
|
|
|
dataSet.nugget = m_pNuggetSpin->value();
|
|
|
dataSet.sill = m_pSillSpin->value();
|
|
|
dataSet.range = m_pRangeSpin->value();
|
|
|
dataSet.model = m_pModelCombo->itemData(m_pModelCombo->currentIndex()).toInt();
|
|
|
dataSet.showPoints = m_pShowPointsCheck->isChecked();
|
|
|
dataSet.showLabels = m_pShowLabelsCheck->isChecked();
|
|
|
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::syncDataSetsToManager(bool markModified)
|
|
|
{
|
|
|
if(!m_pDataManager.isNull()) {
|
|
|
m_pDataManager->setPropertyInterpolationDataSets(m_vecDataSets);
|
|
|
}
|
|
|
|
|
|
if(markModified && !m_pPlot.isNull()) {
|
|
|
m_pPlot->setModified(true);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::updateDataSetButtons()
|
|
|
{
|
|
|
const bool hasCurrent = m_nCurrentDataSetIndex >= 0 &&
|
|
|
m_nCurrentDataSetIndex < m_vecDataSets.size();
|
|
|
const bool canPickOnMap = hasCurrent && !m_pPlot.isNull() &&
|
|
|
m_pPlot->m_pPlotView != NULL && m_pPlot->m_pPlot != NULL;
|
|
|
|
|
|
m_pDataSetCombo->setEnabled(hasCurrent);
|
|
|
m_pDeleteDataSetButton->setEnabled(hasCurrent);
|
|
|
m_pNameEdit->setEnabled(hasCurrent);
|
|
|
m_pPropertyCombo->setEnabled(hasCurrent);
|
|
|
m_pNewValueSpin->setEnabled(hasCurrent);
|
|
|
m_pMapPickButton->setEnabled(canPickOnMap);
|
|
|
m_pPointTable->setEnabled(hasCurrent);
|
|
|
m_pShowPointsCheck->setEnabled(hasCurrent);
|
|
|
m_pShowLabelsCheck->setEnabled(hasCurrent);
|
|
|
m_pNuggetSpin->setEnabled(hasCurrent);
|
|
|
m_pSillSpin->setEnabled(hasCurrent);
|
|
|
m_pRangeSpin->setEnabled(hasCurrent);
|
|
|
m_pModelCombo->setEnabled(hasCurrent);
|
|
|
updatePointButtons();
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onDataSetChanged(int index)
|
|
|
{
|
|
|
if(m_bUpdatingUi || index < 0 || index >= m_vecDataSets.size() ||
|
|
|
index == m_nCurrentDataSetIndex) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
saveCurrentDataSet();
|
|
|
syncDataSetsToManager(false);
|
|
|
m_nCurrentDataSetIndex = index;
|
|
|
loadDataSet(index);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onAddDataSet()
|
|
|
{
|
|
|
saveCurrentDataSet();
|
|
|
m_vecDataSets.append(createDefaultDataSet());
|
|
|
m_vecMarkerNames.append(QStringList());
|
|
|
|
|
|
int newIndex = m_vecDataSets.size() - 1;
|
|
|
bool oldBlock = m_pDataSetCombo->blockSignals(true);
|
|
|
m_pDataSetCombo->addItem(m_vecDataSets[newIndex].name);
|
|
|
m_pDataSetCombo->setCurrentIndex(newIndex);
|
|
|
m_pDataSetCombo->blockSignals(oldBlock);
|
|
|
|
|
|
m_nCurrentDataSetIndex = newIndex;
|
|
|
loadDataSet(newIndex);
|
|
|
updateDataSetButtons();
|
|
|
syncDataSetsToManager(true);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onDeleteDataSet()
|
|
|
{
|
|
|
if(m_nCurrentDataSetIndex < 0 ||
|
|
|
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
int removedIndex = m_nCurrentDataSetIndex;
|
|
|
removeDataSetMarkers(removedIndex);
|
|
|
m_vecDataSets.remove(removedIndex);
|
|
|
m_vecMarkerNames.remove(removedIndex);
|
|
|
|
|
|
const int newIndex = m_vecDataSets.isEmpty() ? -1 :
|
|
|
qMin(removedIndex, m_vecDataSets.size() - 1);
|
|
|
bool oldBlock = m_pDataSetCombo->blockSignals(true);
|
|
|
m_pDataSetCombo->removeItem(removedIndex);
|
|
|
m_pDataSetCombo->setCurrentIndex(newIndex);
|
|
|
m_pDataSetCombo->blockSignals(oldBlock);
|
|
|
|
|
|
m_nCurrentDataSetIndex = newIndex;
|
|
|
loadDataSet(newIndex);
|
|
|
updateDataSetButtons();
|
|
|
syncDataSetsToManager(true);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onDataSetNameChanged(const QString& name)
|
|
|
{
|
|
|
if(m_bUpdatingUi || m_nCurrentDataSetIndex < 0 ||
|
|
|
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
m_vecDataSets[m_nCurrentDataSetIndex].name = name;
|
|
|
m_pDataSetCombo->setItemText(m_nCurrentDataSetIndex, name);
|
|
|
syncDataSetsToManager(true);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onCurrentDataSetEdited()
|
|
|
{
|
|
|
if(m_bUpdatingUi) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
saveCurrentDataSet();
|
|
|
syncDataSetsToManager(true);
|
|
|
}
|
|
|
|
|
|
bool nmWxPropertyInterpolationDlg::eventFilter(QObject* watched, QEvent* event)
|
|
|
{
|
|
|
// 点击表格空白处或其他控件时取消测点行的选中状态.
|
|
|
if(event != NULL && event->type() == QEvent::MouseButtonPress && m_pPointTable != NULL) {
|
|
|
QWidget* clickedWidget = qobject_cast<QWidget*>(watched);
|
|
|
|
|
|
if(clickedWidget != NULL) {
|
|
|
bool isTableViewport = clickedWidget == m_pPointTable->viewport() ||
|
|
|
m_pPointTable->viewport()->isAncestorOf(clickedWidget);
|
|
|
|
|
|
if(clickedWidget == m_pPointTable->viewport()) {
|
|
|
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
|
|
|
|
|
|
if(m_pPointTable->itemAt(mouseEvent->pos()) == NULL) {
|
|
|
clearTableSelection();
|
|
|
}
|
|
|
} else if(!isTableViewport && clickedWidget != m_pDeletePointButton) {
|
|
|
clearTableSelection();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return iDlgBase::eventFilter(watched, event);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onMapPickToggled(bool checked)
|
|
|
{
|
|
|
if(m_pPlot.isNull() || m_pPlot->m_pPlotView == NULL) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 每次切换前先断开旧连接,防止一次地图点击被重复处理.
|
|
|
disconnect(m_pPlot->m_pPlotView, SIGNAL(sigLeftClick(QPointF)),
|
|
|
this, SLOT(onMapClicked(QPointF)));
|
|
|
|
|
|
if(checked) {
|
|
|
m_pPlot->cancelActiveTools();
|
|
|
connect(m_pPlot->m_pPlotView, SIGNAL(sigLeftClick(QPointF)),
|
|
|
this, SLOT(onMapClicked(QPointF)));
|
|
|
m_pPlot->m_pPlotView->setCursor(Qt::CrossCursor);
|
|
|
} else {
|
|
|
m_pPlot->m_pPlotView->restoreCursor();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onMapClicked(const QPointF& position)
|
|
|
{
|
|
|
if(!m_pMapPickButton->isChecked() || m_pPlot.isNull() ||
|
|
|
m_pPlot->m_pPlot == NULL || m_nCurrentDataSetIndex < 0) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if(!m_pPlot->m_pPlot->getInnerRectF().contains(position)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 点击位置为绘图区坐标,需要转换成实际数据坐标后保存.
|
|
|
QPointF plotPosition = position;
|
|
|
QPointF valuePoint = m_pPlot->m_pPlot->getValueForPos(plotPosition);
|
|
|
appendPoint(valuePoint);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::appendPoint(const QPointF& valuePoint)
|
|
|
{
|
|
|
if(m_nCurrentDataSetIndex < 0 ||
|
|
|
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
nmPropertyInterpolationDataSet& dataSet = m_vecDataSets[m_nCurrentDataSetIndex];
|
|
|
double pointValue = m_pNewValueSpin->value();
|
|
|
nmPropertyInterpolationPointData point(valuePoint.x(), valuePoint.y(), pointValue);
|
|
|
QString markerName = createMarker(valuePoint, pointValue,
|
|
|
dataSet.showPoints, dataSet.showLabels);
|
|
|
|
|
|
// 测点数据、地图标记和表格行按相同顺序同步追加.
|
|
|
dataSet.points.append(point);
|
|
|
m_vecMarkerNames[m_nCurrentDataSetIndex].append(markerName);
|
|
|
|
|
|
bool oldBlock = m_pPointTable->blockSignals(true);
|
|
|
appendPointRow(point, markerName);
|
|
|
m_pPointTable->blockSignals(oldBlock);
|
|
|
m_pPointTable->scrollToBottom();
|
|
|
updatePointButtons();
|
|
|
syncDataSetsToManager(true);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::appendPointRow(
|
|
|
const nmPropertyInterpolationPointData& point,
|
|
|
const QString& markerName)
|
|
|
{
|
|
|
int row = m_pPointTable->rowCount();
|
|
|
m_pPointTable->insertRow(row);
|
|
|
|
|
|
QTableWidgetItem* xItem = new QTableWidgetItem(QString::number(point.x, 'g', 15));
|
|
|
xItem->setFlags(xItem->flags() & ~Qt::ItemIsEditable);
|
|
|
xItem->setData(Qt::UserRole, markerName);
|
|
|
m_pPointTable->setItem(row, 0, xItem);
|
|
|
|
|
|
QTableWidgetItem* yItem = new QTableWidgetItem(QString::number(point.y, 'g', 15));
|
|
|
yItem->setFlags(yItem->flags() & ~Qt::ItemIsEditable);
|
|
|
m_pPointTable->setItem(row, 1, yItem);
|
|
|
|
|
|
m_pPointTable->setItem(row, 2,
|
|
|
new QTableWidgetItem(QString::number(point.value, 'f', 6)));
|
|
|
}
|
|
|
|
|
|
QString nmWxPropertyInterpolationDlg::createMarker(const QPointF& valuePosition,
|
|
|
double value,
|
|
|
bool showPoints,
|
|
|
bool showLabels)
|
|
|
{
|
|
|
if(m_pPlot.isNull() || m_pPlot->m_pPlot == NULL) {
|
|
|
return QString();
|
|
|
}
|
|
|
|
|
|
QString markerName;
|
|
|
do {
|
|
|
markerName = QString("__PropertyInterpolationPoint_%1").arg(++m_nNextPointId);
|
|
|
} while(m_pPlot->m_pPlot->getObjByName(markerName) != NULL);
|
|
|
|
|
|
// 地图标记仅用于临时显示,不应单独改变工程修改状态.
|
|
|
bool wasModified = m_pPlot->isModified();
|
|
|
PropertyInterpolationMarker* marker = new PropertyInterpolationMarker(
|
|
|
markerName,
|
|
|
m_pPlot->m_pPlot->getMainAxisX(),
|
|
|
m_pPlot->m_pPlot->getMainAxisY());
|
|
|
m_pPlot->bindObjSignals(marker);
|
|
|
|
|
|
if(!m_pPlot->m_pPlot->addOneObj(marker)) {
|
|
|
delete marker;
|
|
|
m_pPlot->setModified(wasModified);
|
|
|
return QString();
|
|
|
}
|
|
|
|
|
|
QVector<QPointF> values;
|
|
|
values.append(valuePosition);
|
|
|
marker->setAllValues(values);
|
|
|
m_pPlot->slotObjCompleted(marker);
|
|
|
setMarkerLabel(marker, QString::number(value, 'g', 10));
|
|
|
marker->setReadOnly(true);
|
|
|
marker->setLockPos(true);
|
|
|
marker->showSubObjs(showPoints && showLabels);
|
|
|
marker->setVisible(showPoints);
|
|
|
marker->deselect(true);
|
|
|
marker->update();
|
|
|
m_pPlot->setModified(wasModified);
|
|
|
return markerName;
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::createMarkersForAllDataSets()
|
|
|
{
|
|
|
if(m_pPlot.isNull() || m_pPlot->m_pPlot == NULL) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
for(int dataSetIndex = 0; dataSetIndex < m_vecDataSets.size(); ++dataSetIndex) {
|
|
|
const nmPropertyInterpolationDataSet& dataSet = m_vecDataSets[dataSetIndex];
|
|
|
QStringList markerNames;
|
|
|
|
|
|
for(int pointIndex = 0; pointIndex < dataSet.points.size(); ++pointIndex) {
|
|
|
const nmPropertyInterpolationPointData& point = dataSet.points[pointIndex];
|
|
|
QPointF valuePosition(point.x, point.y);
|
|
|
markerNames.append(createMarker(valuePosition, point.value,
|
|
|
dataSet.showPoints, dataSet.showLabels));
|
|
|
}
|
|
|
|
|
|
m_vecMarkerNames[dataSetIndex] = markerNames;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::removeDataSetMarkers(int dataSetIndex)
|
|
|
{
|
|
|
if(dataSetIndex < 0 || dataSetIndex >= m_vecMarkerNames.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
const QStringList markerNames = m_vecMarkerNames[dataSetIndex];
|
|
|
for(int i = 0; i < markerNames.size(); ++i) {
|
|
|
removeMarkerByName(markerNames[i]);
|
|
|
}
|
|
|
m_vecMarkerNames[dataSetIndex].clear();
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::removeAllMarkers()
|
|
|
{
|
|
|
for(int i = 0; i < m_vecMarkerNames.size(); ++i) {
|
|
|
removeDataSetMarkers(i);
|
|
|
}
|
|
|
m_vecMarkerNames.clear();
|
|
|
}
|
|
|
|
|
|
QString nmWxPropertyInterpolationDlg::markerNameAt(int row) const
|
|
|
{
|
|
|
if(m_pPointTable == NULL || row < 0 || row >= m_pPointTable->rowCount()) {
|
|
|
return QString();
|
|
|
}
|
|
|
|
|
|
QTableWidgetItem* item = m_pPointTable->item(row, 0);
|
|
|
return item == NULL ? QString() : item->data(Qt::UserRole).toString();
|
|
|
}
|
|
|
|
|
|
nmObjPoint* nmWxPropertyInterpolationDlg::markerByName(const QString& markerName) const
|
|
|
{
|
|
|
if(m_pPlot.isNull() || m_pPlot->m_pPlot == NULL || markerName.isEmpty()) {
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
return dynamic_cast<nmObjPoint*>(m_pPlot->m_pPlot->getObjByName(markerName));
|
|
|
}
|
|
|
|
|
|
nmObjPoint* nmWxPropertyInterpolationDlg::markerAt(int row) const
|
|
|
{
|
|
|
return markerByName(markerNameAt(row));
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::removeMarkerByName(const QString& markerName)
|
|
|
{
|
|
|
if(m_pPlot.isNull() || m_pPlot->m_pPlot == NULL || markerName.isEmpty() ||
|
|
|
m_pPlot->m_pPlot->getObjByName(markerName) == NULL) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
bool wasModified = m_pPlot->isModified();
|
|
|
m_pPlot->m_pPlot->removeObjByName(markerName);
|
|
|
m_pPlot->setModified(wasModified);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onPointSelectionChanged()
|
|
|
{
|
|
|
updatePointButtons();
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onPointItemChanged(QTableWidgetItem* item)
|
|
|
{
|
|
|
if(m_bUpdatingUi || item == NULL || item->column() != 2 ||
|
|
|
m_nCurrentDataSetIndex < 0 ||
|
|
|
m_nCurrentDataSetIndex >= m_vecDataSets.size() ||
|
|
|
item->row() >= m_vecDataSets[m_nCurrentDataSetIndex].points.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 数值修改后同步更新数据组和地图标签,坐标列保持只读.
|
|
|
m_vecDataSets[m_nCurrentDataSetIndex].points[item->row()].value = item->text().toDouble();
|
|
|
nmObjPoint* marker = markerAt(item->row());
|
|
|
if(marker != NULL) {
|
|
|
setMarkerLabel(marker, item->text());
|
|
|
marker->update();
|
|
|
}
|
|
|
syncDataSetsToManager(true);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onDeleteSelectedPoint()
|
|
|
{
|
|
|
int row = m_pPointTable->currentRow();
|
|
|
if(row < 0 || m_nCurrentDataSetIndex < 0 ||
|
|
|
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
removeMarkerByName(markerNameAt(row));
|
|
|
if(row < m_vecDataSets[m_nCurrentDataSetIndex].points.size()) {
|
|
|
m_vecDataSets[m_nCurrentDataSetIndex].points.remove(row);
|
|
|
}
|
|
|
if(row < m_vecMarkerNames[m_nCurrentDataSetIndex].size()) {
|
|
|
m_vecMarkerNames[m_nCurrentDataSetIndex].removeAt(row);
|
|
|
}
|
|
|
m_pPointTable->removeRow(row);
|
|
|
clearTableSelection();
|
|
|
updatePointButtons();
|
|
|
syncDataSetsToManager(true);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onClearPoints()
|
|
|
{
|
|
|
if(m_nCurrentDataSetIndex < 0 ||
|
|
|
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
removeDataSetMarkers(m_nCurrentDataSetIndex);
|
|
|
m_vecDataSets[m_nCurrentDataSetIndex].points.clear();
|
|
|
m_pPointTable->setRowCount(0);
|
|
|
clearTableSelection();
|
|
|
updatePointButtons();
|
|
|
syncDataSetsToManager(true);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onShowPointsToggled(bool checked)
|
|
|
{
|
|
|
if(m_bUpdatingUi || m_nCurrentDataSetIndex < 0 ||
|
|
|
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
m_vecDataSets[m_nCurrentDataSetIndex].showPoints = checked;
|
|
|
updateCurrentMarkerVisibility();
|
|
|
syncDataSetsToManager(true);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onShowLabelsToggled(bool checked)
|
|
|
{
|
|
|
if(m_bUpdatingUi || m_nCurrentDataSetIndex < 0 ||
|
|
|
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
m_vecDataSets[m_nCurrentDataSetIndex].showLabels = checked;
|
|
|
updateCurrentMarkerVisibility();
|
|
|
syncDataSetsToManager(true);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::clearTableSelection()
|
|
|
{
|
|
|
m_pPointTable->clearSelection();
|
|
|
m_pPointTable->setCurrentCell(-1, -1);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::updatePointButtons()
|
|
|
{
|
|
|
const bool hasCurrent = m_nCurrentDataSetIndex >= 0 &&
|
|
|
m_nCurrentDataSetIndex < m_vecDataSets.size();
|
|
|
m_pDeletePointButton->setEnabled(hasCurrent && m_pPointTable->currentRow() >= 0);
|
|
|
m_pClearPointsButton->setEnabled(hasCurrent && m_pPointTable->rowCount() > 0);
|
|
|
m_pPreviewButton->setEnabled(hasCurrent &&
|
|
|
m_vecDataSets[m_nCurrentDataSetIndex].points.size() >= 2);
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::onPreview()
|
|
|
{
|
|
|
if(m_nCurrentDataSetIndex < 0 ||
|
|
|
m_nCurrentDataSetIndex >= m_vecDataSets.size() ||
|
|
|
m_pDataManager.isNull()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
saveCurrentDataSet();
|
|
|
const nmPropertyInterpolationDataSet& dataSet =
|
|
|
m_vecDataSets[m_nCurrentDataSetIndex];
|
|
|
|
|
|
// 预览范围直接使用储层边界,与地图中的数据坐标保持一致.
|
|
|
QVector<QPointF> outlinePoints;
|
|
|
QRectF previewBounds;
|
|
|
if(!createPreviewOutline(m_pDataManager->getOutlineData(),
|
|
|
outlinePoints, previewBounds)) {
|
|
|
QMessageBox::warning(this,
|
|
|
interpolationText("Preview Failed"),
|
|
|
interpolationText("Please create a valid reservoir boundary before previewing."));
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
QVector<QPointF> measurementPoints;
|
|
|
QVector<double> measurementValues;
|
|
|
measurementPoints.reserve(dataSet.points.size());
|
|
|
measurementValues.reserve(dataSet.points.size());
|
|
|
for(int i = 0; i < dataSet.points.size(); ++i) {
|
|
|
measurementPoints.append(QPointF(dataSet.points[i].x,
|
|
|
dataSet.points[i].y));
|
|
|
measurementValues.append(dataSet.points[i].value);
|
|
|
}
|
|
|
|
|
|
// 按行生成规则待插值点,输出下标与预览网格下标保持一致;
|
|
|
// 较疏采样可使分级色带边界更清晰.
|
|
|
const int columnCount = 31;
|
|
|
const int rowCount = 31;
|
|
|
QVector<QPointF> targetPoints;
|
|
|
targetPoints.reserve(columnCount * rowCount);
|
|
|
for(int row = 0; row < rowCount; ++row) {
|
|
|
const double y = previewBounds.top() +
|
|
|
previewBounds.height() * row / (rowCount - 1);
|
|
|
for(int column = 0; column < columnCount; ++column) {
|
|
|
const double x = previewBounds.left() +
|
|
|
previewBounds.width() * column / (columnCount - 1);
|
|
|
targetPoints.append(QPointF(x, y));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
QVector<double> interpolationValues;
|
|
|
QString errorMessage;
|
|
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
|
// 通过统一封装调用Kriging接口,返回值顺序与待插值点一致.
|
|
|
const bool calculationSucceeded = nmCalculationUtils::calculateKriging(
|
|
|
targetPoints,
|
|
|
measurementPoints,
|
|
|
measurementValues,
|
|
|
dataSet.nugget,
|
|
|
dataSet.sill,
|
|
|
dataSet.range,
|
|
|
dataSet.model,
|
|
|
m_pDataManager->getLicensePath(),
|
|
|
interpolationValues,
|
|
|
&errorMessage);
|
|
|
QApplication::restoreOverrideCursor();
|
|
|
|
|
|
if(!calculationSucceeded) {
|
|
|
QMessageBox::warning(this,
|
|
|
interpolationText("Preview Failed"),
|
|
|
errorMessage);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 预览窗口只负责裁剪和渲染,不修改数据组及正式求解参数.
|
|
|
nmWxPropertyInterpolationPreviewDlg previewDialog(
|
|
|
dataSet.name,
|
|
|
m_pPropertyCombo->currentText(),
|
|
|
previewBounds,
|
|
|
columnCount,
|
|
|
rowCount,
|
|
|
interpolationValues,
|
|
|
measurementPoints,
|
|
|
measurementValues,
|
|
|
outlinePoints,
|
|
|
dataSet.showPoints,
|
|
|
dataSet.showLabels,
|
|
|
this);
|
|
|
previewDialog.exec();
|
|
|
}
|
|
|
|
|
|
void nmWxPropertyInterpolationDlg::updateCurrentMarkerVisibility()
|
|
|
{
|
|
|
// 地图上只显示当前数据组的测点,其他数据组统一隐藏.
|
|
|
for(int dataSetIndex = 0;
|
|
|
dataSetIndex < m_vecMarkerNames.size(); ++dataSetIndex) {
|
|
|
const bool isCurrentDataSet = dataSetIndex == m_nCurrentDataSetIndex &&
|
|
|
dataSetIndex < m_vecDataSets.size();
|
|
|
const bool showPoints = isCurrentDataSet &&
|
|
|
m_vecDataSets[dataSetIndex].showPoints;
|
|
|
const bool showLabels = showPoints &&
|
|
|
m_vecDataSets[dataSetIndex].showLabels;
|
|
|
const QStringList markerNames = m_vecMarkerNames[dataSetIndex];
|
|
|
|
|
|
for(int markerIndex = 0; markerIndex < markerNames.size(); ++markerIndex) {
|
|
|
nmObjPoint* marker = markerByName(markerNames[markerIndex]);
|
|
|
if(marker != NULL) {
|
|
|
marker->setVisible(showPoints);
|
|
|
marker->showSubObjs(showLabels);
|
|
|
marker->update();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if(!m_pPlot.isNull() && m_pPlot->m_pPlotView != NULL) {
|
|
|
m_pPlot->m_pPlotView->updateViewport();
|
|
|
}
|
|
|
}
|