diff --git a/Bin/Config/Lang/cn/nmNum_cn.qm b/Bin/Config/Lang/cn/nmNum_cn.qm
index abc015a..32bc151 100644
Binary files a/Bin/Config/Lang/cn/nmNum_cn.qm and b/Bin/Config/Lang/cn/nmNum_cn.qm differ
diff --git a/Bin/Config/Lang/cn/nmNum_cn.ts b/Bin/Config/Lang/cn/nmNum_cn.ts
index 0eb1ffe..3dc3397 100644
--- a/Bin/Config/Lang/cn/nmNum_cn.ts
+++ b/Bin/Config/Lang/cn/nmNum_cn.ts
@@ -6642,21 +6642,25 @@ Average pressure in contour: %2 MPa
Show labels
显示标签
+
+ Clear measurement points before changing the property.
+ 清空测点后可修改属性。
+
Kriging Parameters
- Kriging参数
+ 克里金参数
Nugget:
- Nugget:
+ 块金值:
Sill:
- Sill:
+ 基台值:
Range:
- Range:
+ 变程:
Model:
@@ -6682,10 +6686,6 @@ Average pressure in contour: %2 MPa
Preview
预览
-
- Apply
- 应用
-
Close
关闭
diff --git a/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.h b/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.h
index 0053cf2..c264ade 100644
--- a/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.h
+++ b/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.h
@@ -74,6 +74,7 @@ private:
void updateUnitControls(nmPropertyInterpolationDataSet& dataSet);
void updatePointDisplayValues();
void clearPointRows();
+ void updatePointRowNumbers();
void syncDataSetsToManager(bool markModified);
void updateDataSetButtons();
// 管理正式求解时k、phi和h各自使用的插值数据组.
@@ -157,9 +158,8 @@ private:
QCheckBox* m_pUseHCheck;
QComboBox* m_pHCalculationDataSetCombo;
- // 结果预览及应用.
+ // 插值结果预览.
QPushButton* m_pPreviewButton;
- QPushButton* m_pApplyButton;
QPointer m_pPreviewDialog;
QTimer* m_pPreviewRefreshTimer;
};
diff --git a/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.h b/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.h
index 3ff345d..cf1afa1 100644
--- a/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.h
+++ b/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.h
@@ -7,6 +7,7 @@
#include
#include
#include
+#include
#include
class QVTKWidget;
@@ -25,6 +26,8 @@ public:
const QVector& measurementPoints,
const QVector& measurementValues,
const QVector& outlinePoints,
+ const QVector& wellPoints,
+ const QStringList& wellNames,
bool showMeasurementPoints,
bool showMeasurementLabels,
QWidget* parent = 0);
@@ -38,6 +41,8 @@ public:
const QVector& measurementPoints,
const QVector& measurementValues,
const QVector& outlinePoints,
+ const QVector& wellPoints,
+ const QStringList& wellNames,
bool showMeasurementPoints,
bool showMeasurementLabels);
void showMessage(const QString& dataSetName, const QString& message);
@@ -51,6 +56,8 @@ private:
const QVector& measurementPoints,
const QVector& measurementValues,
const QVector& outlinePoints,
+ const QVector& wellPoints,
+ const QStringList& wellNames,
bool showMeasurementPoints,
bool showMeasurementLabels);
diff --git a/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.cpp b/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.cpp
index 44d4571..b5b8f5f 100644
--- a/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.cpp
+++ b/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.cpp
@@ -33,10 +33,12 @@
#include "nmDataOutline.h"
#include "nmGuiPlot.h"
#include "nmObjPoint.h"
+#include "nmObjPointWell.h"
#include "nmWxPropertyInterpolationPreviewDlg.h"
#include "iUnitGroup.h"
#include "iUnitHelper.h"
#include "tCurvePlotView.h"
+#include "ZxDataWell.h"
#include "ZxObjText.h"
#include "ZxPlot.h"
@@ -336,15 +338,14 @@ nmWxPropertyInterpolationDlg::nmWxPropertyInterpolationDlg(
m_pUseHCheck(NULL),
m_pHCalculationDataSetCombo(NULL),
m_pPreviewButton(NULL),
- m_pApplyButton(NULL),
m_pPreviewDialog(NULL),
m_pPreviewRefreshTimer(NULL)
{
setWindowTitle(interpolationText("Property Interpolation"));
setWindowModality(Qt::NonModal);
setModal(false);
- setMinimumSize(520, 680);
- resize(560, 740);
+ setMinimumSize(600, 620);
+ resize(640, 680);
// 合并连续编辑触发的刷新,避免每次数值变化都立即重新插值.
m_pPreviewRefreshTimer = new QTimer(this);
@@ -375,38 +376,52 @@ nmWxPropertyInterpolationDlg::~nmWxPropertyInterpolationDlg()
void nmWxPropertyInterpolationDlg::initInterpolationUI()
{
+ const int topControlWidth = 350;
+ const int compactComboWidth = 200;
+
QVBoxLayout* mainLayout = new QVBoxLayout(this);
+ mainLayout->setContentsMargins(12, 10, 12, 10);
+ mainLayout->setSpacing(8);
- // 数据组创建、切换及删除.
- QHBoxLayout* dataSetSelectLayout = new QHBoxLayout;
- dataSetSelectLayout->addWidget(new QLabel(interpolationText("Dataset:"), this));
- m_pDataSetCombo = new QComboBox(this);
+ // 数据组、名称和属性共用一个表单,保证三行标签及输入控件对齐.
+ QFormLayout* dataSetLayout = new QFormLayout;
+ dataSetLayout->setContentsMargins(0, 0, 0, 0);
+ dataSetLayout->setHorizontalSpacing(8);
+ dataSetLayout->setVerticalSpacing(6);
+ dataSetLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
+
+ QWidget* dataSetSelectWidget = new QWidget(this);
+ dataSetSelectWidget->setMaximumWidth(topControlWidth);
+ QHBoxLayout* dataSetSelectLayout = new QHBoxLayout(dataSetSelectWidget);
+ dataSetSelectLayout->setContentsMargins(0, 0, 0, 0);
+ dataSetSelectLayout->setSpacing(6);
+ m_pDataSetCombo = new QComboBox(dataSetSelectWidget);
dataSetSelectLayout->addWidget(m_pDataSetCombo, 1);
QString iconDir = QCoreApplication::applicationDirPath();
iconDir = iconDir.section('/', 0, -2) + "/Res/Icon/";
- m_pAddDataSetButton = new QPushButton(this);
+ m_pAddDataSetButton = new QPushButton(dataSetSelectWidget);
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 = new QPushButton(dataSetSelectWidget);
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);
+ dataSetLayout->addRow(interpolationText("Dataset:"), dataSetSelectWidget);
- // 当前数据组的名称和属性.
- QFormLayout* dataSetLayout = new QFormLayout;
m_pNameEdit = new QLineEdit(this);
+ m_pNameEdit->setMaximumWidth(topControlWidth);
dataSetLayout->addRow(interpolationText("Name:"), m_pNameEdit);
m_pPropertyCombo = new QComboBox(this);
+ m_pPropertyCombo->setMaximumWidth(topControlWidth);
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"));
@@ -416,17 +431,23 @@ void nmWxPropertyInterpolationDlg::initInterpolationUI()
// 测点数据录入区域.
QGroupBox* pointGroup = new QGroupBox(interpolationText("Measurement Points"), this);
QVBoxLayout* pointLayout = new QVBoxLayout(pointGroup);
+ pointLayout->setContentsMargins(10, 8, 10, 10);
+ pointLayout->setSpacing(6);
QHBoxLayout* newPointLayout = new QHBoxLayout;
+ newPointLayout->setSpacing(6);
newPointLayout->addWidget(new QLabel(interpolationText("New value:"), pointGroup));
m_pNewValueSpin = createNumberSpinBox(pointGroup, 0.0);
newPointLayout->addWidget(m_pNewValueSpin, 1);
m_pNewValueUnitCombo = new QComboBox(pointGroup);
- m_pNewValueUnitCombo->setMinimumWidth(80);
+ m_pNewValueUnitCombo->setFixedWidth(80);
populateUnitCombo(m_pNewValueUnitCombo,
PERMEABILITY_BASE_UNIT, PERMEABILITY_DISPLAY_UNIT);
newPointLayout->addWidget(m_pNewValueUnitCombo);
m_pMapPickButton = new QPushButton(interpolationText("Select on Map"), pointGroup);
+ m_pMapPickButton->setIcon(QIcon(iconDir + "AddPoint.png"));
+ m_pMapPickButton->setIconSize(QSize(16, 16));
+ m_pMapPickButton->setMinimumWidth(100);
m_pMapPickButton->setCheckable(true);
m_pMapPickButton->setEnabled(!m_pPlot.isNull() &&
m_pPlot->m_pPlotView != NULL &&
@@ -438,11 +459,17 @@ void nmWxPropertyInterpolationDlg::initInterpolationUI()
QStringList headers;
headers << interpolationText("X") << interpolationText("Y") << interpolationText("Value");
m_pPointTable->setHorizontalHeaderLabels(headers);
- m_pPointTable->verticalHeader()->setVisible(false);
+ m_pPointTable->verticalHeader()->setVisible(true);
+ m_pPointTable->verticalHeader()->setFixedWidth(36);
+ m_pPointTable->verticalHeader()->setDefaultAlignment(Qt::AlignCenter);
+ // 第0行为单位选择,不占用测点序号.
+ m_pPointTable->setVerticalHeaderItem(
+ POINT_UNIT_ROW, new QTableWidgetItem(QString()));
m_pPointTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
m_pPointTable->setSelectionBehavior(QAbstractItemView::SelectRows);
m_pPointTable->setSelectionMode(QAbstractItemView::SingleSelection);
m_pPointTable->setAlternatingRowColors(true);
+ m_pPointTable->setMinimumHeight(170);
m_pPointTable->setRowHeight(POINT_UNIT_ROW, 24);
// 第0行固定显示各列单位,数据行从第1行开始.
@@ -461,83 +488,99 @@ void nmWxPropertyInterpolationDlg::initInterpolationUI()
m_pPointTable->setCellWidget(POINT_UNIT_ROW, 2, m_pValueUnitCombo);
pointLayout->addWidget(m_pPointTable, 1);
+ // 显示选项放在左侧,当前测点操作放在右侧,减少分散的按钮行.
QHBoxLayout* pointButtonLayout = new QHBoxLayout;
+ pointButtonLayout->setSpacing(8);
+ m_pShowPointsCheck = new QCheckBox(interpolationText("Show measurement points"), pointGroup);
+ m_pShowPointsCheck->setChecked(true);
+ pointButtonLayout->addWidget(m_pShowPointsCheck);
+ m_pShowLabelsCheck = new QCheckBox(interpolationText("Show labels"), pointGroup);
+ m_pShowLabelsCheck->setChecked(true);
+ pointButtonLayout->addWidget(m_pShowLabelsCheck);
pointButtonLayout->addStretch();
m_pDeletePointButton = new QPushButton(interpolationText("Delete Selected"), pointGroup);
+ m_pDeletePointButton->setMinimumWidth(84);
m_pDeletePointButton->setEnabled(false);
pointButtonLayout->addWidget(m_pDeletePointButton);
m_pClearPointsButton = new QPushButton(interpolationText("Clear"), pointGroup);
+ m_pClearPointsButton->setMinimumWidth(72);
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插值参数设置.
+ // Kriging参数采用两行双列布局,保持信息完整并压缩纵向空间.
QGroupBox* parameterGroup = new QGroupBox(interpolationText("Kriging Parameters"), this);
- QFormLayout* parameterLayout = new QFormLayout(parameterGroup);
+ QGridLayout* parameterLayout = new QGridLayout(parameterGroup);
+ parameterLayout->setContentsMargins(10, 8, 10, 10);
+ parameterLayout->setHorizontalSpacing(8);
+ parameterLayout->setVerticalSpacing(6);
m_pNuggetSpin = createNumberSpinBox(parameterGroup, 0.01);
- parameterLayout->addRow(interpolationText("Nugget:"), m_pNuggetSpin);
+ parameterLayout->addWidget(new QLabel(interpolationText("Nugget:"), parameterGroup), 0, 0);
+ parameterLayout->addWidget(m_pNuggetSpin, 0, 1);
m_pSillSpin = createNumberSpinBox(parameterGroup, 100.0);
- parameterLayout->addRow(interpolationText("Sill:"), m_pSillSpin);
+ parameterLayout->addWidget(new QLabel(interpolationText("Sill:"), parameterGroup), 0, 2);
+ parameterLayout->addWidget(m_pSillSpin, 0, 3);
QWidget* rangeWidget = new QWidget(parameterGroup);
QHBoxLayout* rangeLayout = new QHBoxLayout(rangeWidget);
rangeLayout->setContentsMargins(0, 0, 0, 0);
rangeLayout->setSpacing(6);
- m_pRangeSpin = createNumberSpinBox(parameterGroup, 1000.0);
+ m_pRangeSpin = createNumberSpinBox(rangeWidget, 1000.0);
rangeLayout->addWidget(m_pRangeSpin, 1);
- m_pRangeUnitCombo = new QComboBox(parameterGroup);
- m_pRangeUnitCombo->setMinimumWidth(80);
+ m_pRangeUnitCombo = new QComboBox(rangeWidget);
+ m_pRangeUnitCombo->setFixedWidth(72);
populateUnitCombo(m_pRangeUnitCombo, LENGTH_BASE_UNIT, LENGTH_BASE_UNIT);
rangeLayout->addWidget(m_pRangeUnitCombo);
- parameterLayout->addRow(interpolationText("Range:"), rangeWidget);
+ parameterLayout->addWidget(new QLabel(interpolationText("Range:"), parameterGroup), 1, 0);
+ parameterLayout->addWidget(rangeWidget, 1, 1);
m_pModelCombo = new QComboBox(parameterGroup);
+ m_pModelCombo->setFixedWidth(compactComboWidth);
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);
+ parameterLayout->addWidget(new QLabel(interpolationText("Model:"), parameterGroup), 1, 2);
+ parameterLayout->addWidget(m_pModelCombo, 1, 3);
+ parameterLayout->setColumnStretch(1, 1);
+ parameterLayout->setColumnStretch(3, 1);
mainLayout->addWidget(parameterGroup);
// 分别指定正式求解时需要使用插值结果的属性和数据组.
QGroupBox* calculationGroup = new QGroupBox(
interpolationText("Use Interpolation in Solver"), this);
QGridLayout* calculationLayout = new QGridLayout(calculationGroup);
+ calculationLayout->setContentsMargins(10, 8, 10, 10);
+ calculationLayout->setHorizontalSpacing(8);
+ calculationLayout->setVerticalSpacing(6);
m_pUseKCheck = new QCheckBox(interpolationText("Permeability k"), calculationGroup);
m_pKCalculationDataSetCombo = new QComboBox(calculationGroup);
+ m_pKCalculationDataSetCombo->setFixedWidth(compactComboWidth);
calculationLayout->addWidget(m_pUseKCheck, 0, 0);
calculationLayout->addWidget(m_pKCalculationDataSetCombo, 0, 1);
m_pUsePhiCheck = new QCheckBox(interpolationText("Porosity phi"), calculationGroup);
m_pPhiCalculationDataSetCombo = new QComboBox(calculationGroup);
+ m_pPhiCalculationDataSetCombo->setFixedWidth(compactComboWidth);
calculationLayout->addWidget(m_pUsePhiCheck, 1, 0);
calculationLayout->addWidget(m_pPhiCalculationDataSetCombo, 1, 1);
m_pUseHCheck = new QCheckBox(interpolationText("Reservoir thickness h"), calculationGroup);
m_pHCalculationDataSetCombo = new QComboBox(calculationGroup);
+ m_pHCalculationDataSetCombo->setFixedWidth(compactComboWidth);
calculationLayout->addWidget(m_pUseHCheck, 2, 0);
calculationLayout->addWidget(m_pHCalculationDataSetCombo, 2, 1);
- calculationLayout->setColumnStretch(1, 1);
+ calculationLayout->setColumnMinimumWidth(1, compactComboWidth);
+ calculationLayout->setColumnStretch(2, 1);
mainLayout->addWidget(calculationGroup);
// 底部操作按钮.
QHBoxLayout* buttonLayout = new QHBoxLayout;
m_pPreviewButton = new QPushButton(interpolationText("Preview"), this);
+ m_pPreviewButton->setMinimumWidth(84);
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);
+ closeButton->setMinimumWidth(84);
buttonLayout->addWidget(closeButton);
mainLayout->addLayout(buttonLayout);
@@ -848,6 +891,28 @@ void nmWxPropertyInterpolationDlg::clearPointRows()
if(m_pPointTable != NULL && m_pPointTable->rowCount() > FIRST_POINT_ROW) {
m_pPointTable->setRowCount(FIRST_POINT_ROW);
}
+ updatePointRowNumbers();
+}
+
+void nmWxPropertyInterpolationDlg::updatePointRowNumbers()
+{
+ if(m_pPointTable == NULL) {
+ return;
+ }
+
+ // 单位行留空,测点数据行始终从1开始连续编号.
+ for(int row = POINT_UNIT_ROW; row < m_pPointTable->rowCount(); ++row) {
+ const QString number = row < FIRST_POINT_ROW ?
+ QString() : QString::number(row - FIRST_POINT_ROW + 1);
+ QTableWidgetItem* headerItem = m_pPointTable->verticalHeaderItem(row);
+ if(headerItem == NULL) {
+ m_pPointTable->setVerticalHeaderItem(row,
+ new QTableWidgetItem(number));
+ }
+ else {
+ headerItem->setText(number);
+ }
+ }
}
void nmWxPropertyInterpolationDlg::syncDataSetsToManager(bool markModified)
@@ -1277,6 +1342,9 @@ void nmWxPropertyInterpolationDlg::appendPointRow(
// rowCount已包含单位行,新插入行天然与points下标保持FIRST_POINT_ROW偏移.
int row = m_pPointTable->rowCount();
m_pPointTable->insertRow(row);
+ m_pPointTable->setVerticalHeaderItem(
+ row, new QTableWidgetItem(QString::number(
+ row - FIRST_POINT_ROW + 1)));
QString xUnit = LENGTH_BASE_UNIT;
QString yUnit = LENGTH_BASE_UNIT;
@@ -1294,14 +1362,12 @@ void nmWxPropertyInterpolationDlg::appendPointRow(
QTableWidgetItem* xItem = new QTableWidgetItem(displayValueText(
convertedUnitValue(point.x, LENGTH_BASE_UNIT, xUnit)));
- xItem->setFlags(xItem->flags() & ~Qt::ItemIsEditable);
// 将地图标记名称绑定在X列,后续可由表格行直接定位对应标记.
xItem->setData(Qt::UserRole, markerName);
m_pPointTable->setItem(row, 0, xItem);
QTableWidgetItem* yItem = new QTableWidgetItem(displayValueText(
convertedUnitValue(point.y, LENGTH_BASE_UNIT, yUnit)));
- yItem->setFlags(yItem->flags() & ~Qt::ItemIsEditable);
m_pPointTable->setItem(row, 1, yItem);
m_pPointTable->setItem(row, 2, new QTableWidgetItem(displayValueText(
@@ -1449,7 +1515,8 @@ void nmWxPropertyInterpolationDlg::onPointItemChanged(QTableWidgetItem* item)
// 表格行减去单位行偏移后,才是数据组中的测点下标.
const int pointIndex = item == NULL ? -1 :
item->row() - FIRST_POINT_ROW;
- if(m_bUpdatingUi || item == NULL || item->column() != 2 ||
+ if(m_bUpdatingUi || item == NULL || item->column() < 0 ||
+ item->column() > 2 ||
pointIndex < 0 ||
m_nCurrentDataSetIndex < 0 ||
m_nCurrentDataSetIndex >= m_vecDataSets.size() ||
@@ -1457,15 +1524,72 @@ void nmWxPropertyInterpolationDlg::onPointItemChanged(QTableWidgetItem* item)
return;
}
- // 数值修改后同步更新数据组和地图标签,坐标列保持只读.
nmPropertyInterpolationDataSet& dataSet =
m_vecDataSets[m_nCurrentDataSetIndex];
- dataSet.points[pointIndex].value = convertedUnitValue(
- item->text().toDouble(), dataSet.valueDisplayUnit,
- propertyBaseUnit(dataSet.property));
+ nmPropertyInterpolationPointData& point = dataSet.points[pointIndex];
+
+ // X、Y及属性值分别按当前显示单位换算回数据中心使用的基准单位.
+ QString baseUnit;
+ QString displayUnit;
+ double oldBaseValue = 0.0;
+ if(item->column() == 0) {
+ baseUnit = LENGTH_BASE_UNIT;
+ displayUnit = dataSet.xDisplayUnit;
+ oldBaseValue = point.x;
+ }
+ else if(item->column() == 1) {
+ baseUnit = LENGTH_BASE_UNIT;
+ displayUnit = dataSet.yDisplayUnit;
+ oldBaseValue = point.y;
+ }
+ else {
+ baseUnit = propertyBaseUnit(dataSet.property);
+ displayUnit = dataSet.valueDisplayUnit;
+ oldBaseValue = point.value;
+ }
+
+ bool valueOk = false;
+ const double displayValue = item->text().toDouble(&valueOk);
+ if(!valueOk || (item->column() == 2 && displayValue < 0.0)) {
+ // 坐标允许为负数;属性值仍要求非负,非法输入恢复为修改前的值.
+ const double oldDisplayValue = convertedUnitValue(
+ oldBaseValue, baseUnit, displayUnit);
+ const bool oldBlock = m_pPointTable->blockSignals(true);
+ item->setText(displayValueText(oldDisplayValue));
+ m_pPointTable->blockSignals(oldBlock);
+ return;
+ }
+
+ const double baseValue = convertedUnitValue(
+ displayValue, displayUnit, baseUnit);
+ if(item->column() == 0) {
+ point.x = baseValue;
+ }
+ else if(item->column() == 1) {
+ point.y = baseValue;
+ }
+ else {
+ point.value = baseValue;
+ }
+
+ const QString displayText = displayValueText(displayValue);
+ if(item->text() != displayText) {
+ const bool oldBlock = m_pPointTable->blockSignals(true);
+ item->setText(displayText);
+ m_pPointTable->blockSignals(oldBlock);
+ }
+
+ // 坐标修改后移动Map标记,属性值修改后刷新标记标签.
nmObjPoint* marker = markerAt(item->row());
if(marker != NULL) {
- setMarkerLabel(marker, item->text());
+ if(item->column() < 2) {
+ QVector positions;
+ positions.append(QPointF(point.x, point.y));
+ marker->setAllValues(positions);
+ }
+ else {
+ setMarkerLabel(marker, displayText);
+ }
marker->update();
}
syncDataSetsToManager(true);
@@ -1490,6 +1614,7 @@ void nmWxPropertyInterpolationDlg::onDeleteSelectedPoint()
m_vecMarkerNames[m_nCurrentDataSetIndex].removeAt(pointIndex);
}
m_pPointTable->removeRow(row);
+ updatePointRowNumbers();
clearTableSelection();
updatePointButtons();
syncDataSetsToManager(true);
@@ -1548,6 +1673,14 @@ void nmWxPropertyInterpolationDlg::updatePointButtons()
{
const bool hasCurrent = m_nCurrentDataSetIndex >= 0 &&
m_nCurrentDataSetIndex < m_vecDataSets.size();
+ const bool hasPoints = hasCurrent &&
+ !m_vecDataSets[m_nCurrentDataSetIndex].points.isEmpty();
+
+ // 已有测点的数值含义已经确定,需清空测点后才能切换数据组属性.
+ m_pPropertyCombo->setEnabled(hasCurrent && !hasPoints);
+ m_pPropertyCombo->setToolTip(hasPoints ?
+ interpolationText("Clear measurement points before changing the property.") :
+ QString());
m_pDeletePointButton->setEnabled(
hasCurrent && m_pPointTable->currentRow() >= FIRST_POINT_ROW);
m_pClearPointsButton->setEnabled(
@@ -1646,8 +1779,8 @@ void nmWxPropertyInterpolationDlg::updatePreviewWindow(bool activateWindow)
// 按行生成规则待插值点,输出下标与预览网格下标保持一致;
// 较疏采样可使分级色带边界更清晰.
- const int columnCount = 31;
- const int rowCount = 31;
+ const int columnCount = 19;
+ const int rowCount = 19;
QVector targetPoints;
targetPoints.reserve(columnCount * rowCount);
for(int row = 0; row < rowCount; ++row) {
@@ -1705,6 +1838,31 @@ void nmWxPropertyInterpolationDlg::updatePreviewWindow(bool activateWindow)
scalarTitle += QString(" (%1)").arg(dataSet.valueDisplayUnit);
}
+ // 直接读取Map中实际显示的井,避免“参与计算井”尚未设置时预览中没有井位.
+ QVector wellPoints;
+ QStringList wellNames;
+ const QVector wellPlots = m_pPlot.isNull() ?
+ QVector() : m_pPlot->getWellPlots();
+ for(int i = 0; i < wellPlots.size(); ++i) {
+ nmObjPointWell* wellPlot = wellPlots[i];
+ if(wellPlot == NULL || wellPlot->getWellData() == NULL) {
+ continue;
+ }
+
+ const QVector wellInformation = wellPlot->getWellInformation();
+ const QString wellName = wellPlot->getWellData()->getName();
+ if(wellInformation.size() < 2 || wellName.isEmpty() ||
+ wellNames.contains(wellName)) {
+ continue;
+ }
+
+ const QPointF wellPoint(wellInformation[0], wellInformation[1]);
+ if(previewBounds.contains(wellPoint)) {
+ wellPoints.append(wellPoint);
+ wellNames.append(wellName);
+ }
+ }
+
// 预览窗口只负责裁剪和渲染,不修改数据组及正式求解参数.
if(m_pPreviewDialog.isNull()) {
m_pPreviewDialog = new nmWxPropertyInterpolationPreviewDlg(
@@ -1717,6 +1875,8 @@ void nmWxPropertyInterpolationDlg::updatePreviewWindow(bool activateWindow)
measurementPoints,
displayMeasurementValues,
outlinePoints,
+ wellPoints,
+ wellNames,
dataSet.showPoints,
dataSet.showLabels,
this);
@@ -1733,6 +1893,8 @@ void nmWxPropertyInterpolationDlg::updatePreviewWindow(bool activateWindow)
measurementPoints,
displayMeasurementValues,
outlinePoints,
+ wellPoints,
+ wellNames,
dataSet.showPoints,
dataSet.showLabels);
}
diff --git a/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.cpp b/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.cpp
index bd2ebfa..916c22d 100644
--- a/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.cpp
+++ b/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.cpp
@@ -29,6 +29,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -85,6 +86,8 @@ nmWxPropertyInterpolationPreviewDlg::nmWxPropertyInterpolationPreviewDlg(
const QVector& measurementPoints,
const QVector& measurementValues,
const QVector& outlinePoints,
+ const QVector& wellPoints,
+ const QStringList& wellNames,
bool showMeasurementPoints,
bool showMeasurementLabels,
QWidget* parent)
@@ -113,7 +116,7 @@ nmWxPropertyInterpolationPreviewDlg::nmWxPropertyInterpolationPreviewDlg(
updatePreview(dataSetName, scalarTitle, bounds, columnCount, rowCount,
interpolationValues, measurementPoints,
- measurementValues, outlinePoints,
+ measurementValues, outlinePoints, wellPoints, wellNames,
showMeasurementPoints, showMeasurementLabels);
}
@@ -127,14 +130,16 @@ void nmWxPropertyInterpolationPreviewDlg::updatePreview(
const QVector& measurementPoints,
const QVector& measurementValues,
const QVector& outlinePoints,
+ const QVector& wellPoints,
+ const QStringList& wellNames,
bool showMeasurementPoints,
bool showMeasurementLabels)
{
setWindowTitle(previewText("Interpolation Preview") + " - " + dataSetName);
initializeRenderer(scalarTitle, bounds, columnCount, rowCount,
- interpolationValues, measurementPoints,
- measurementValues, outlinePoints,
- showMeasurementPoints, showMeasurementLabels);
+ interpolationValues, measurementPoints,
+ measurementValues, outlinePoints, wellPoints, wellNames,
+ showMeasurementPoints, showMeasurementLabels);
}
void nmWxPropertyInterpolationPreviewDlg::showMessage(
@@ -171,6 +176,8 @@ void nmWxPropertyInterpolationPreviewDlg::initializeRenderer(
const QVector& measurementPoints,
const QVector& measurementValues,
const QVector& outlinePoints,
+ const QVector& wellPoints,
+ const QStringList& wellNames,
bool showMeasurementPoints,
bool showMeasurementLabels)
{
@@ -325,8 +332,8 @@ void nmWxPropertyInterpolationPreviewDlg::initializeRenderer(
vtkSmartPointer lookupTable =
createPreviewLookupTable(displayMinimum, displayMaximum);
- // 将连续点标量划分为10级色带,Mapper按CellData进行分级着色.
- const int colorBandCount = 10;
+ // 将连续点标量划分为8级色带,Mapper按CellData进行分级着色.
+ const int colorBandCount = 8;
vtkSmartPointer bandFilter =
vtkSmartPointer::New();
bandFilter->SetInputData(visibleSurface);
@@ -439,9 +446,26 @@ void nmWxPropertyInterpolationPreviewDlg::initializeRenderer(
}
if(showMeasurementLabels) {
+ // 标签使用独立坐标上移,测点方框仍保持在原始测量位置.
+ const double labelOffset =
+ qMax(bounds.width(), bounds.height()) * 0.018;
+ vtkSmartPointer measurementLabelPoints =
+ vtkSmartPointer::New();
+ for(int i = 0; i < measurementPoints.size(); ++i) {
+ measurementLabelPoints->InsertNextPoint(
+ measurementPoints[i].x(),
+ measurementPoints[i].y() + labelOffset, 0.03);
+ }
+
+ vtkSmartPointer measurementLabelData =
+ vtkSmartPointer::New();
+ measurementLabelData->SetPoints(measurementLabelPoints);
+ measurementLabelData->GetPointData()->SetScalars(
+ measurementScalars);
+
vtkSmartPointer labelMapper =
vtkSmartPointer::New();
- labelMapper->SetInputData(measurementData);
+ labelMapper->SetInputData(measurementLabelData);
labelMapper->SetLabelModeToLabelScalars();
labelMapper->SetLabelFormat("%.6g");
labelMapper->GetLabelTextProperty()->SetColor(0.12, 0.12, 0.12);
@@ -449,15 +473,96 @@ void nmWxPropertyInterpolationPreviewDlg::initializeRenderer(
labelMapper->GetLabelTextProperty()->BoldOff();
labelMapper->GetLabelTextProperty()->ItalicOff();
labelMapper->GetLabelTextProperty()->ShadowOff();
+ labelMapper->GetLabelTextProperty()->SetJustificationToCentered();
+ labelMapper->GetLabelTextProperty()->SetVerticalJustificationToBottom();
vtkSmartPointer labelActor =
vtkSmartPointer::New();
labelActor->SetMapper(labelMapper);
- labelActor->SetPosition(0.0, 10.0);
renderer->AddActor2D(labelActor);
}
}
+ // Map中显示的井使用独立红色标记和名称叠加,不参与插值表面计算.
+ if(!wellPoints.isEmpty() && wellPoints.size() == wellNames.size()) {
+ vtkSmartPointer wellVtkPoints =
+ vtkSmartPointer::New();
+ vtkSmartPointer wellNameArray =
+ vtkSmartPointer::New();
+ wellNameArray->SetName("WellName");
+ for(int i = 0; i < wellPoints.size(); ++i) {
+ wellVtkPoints->InsertNextPoint(wellPoints[i].x(),
+ wellPoints[i].y(), 0.04);
+ wellNameArray->InsertNextValue(wellNames[i].toUtf8().constData());
+ }
+
+ vtkSmartPointer wellData =
+ vtkSmartPointer::New();
+ wellData->SetPoints(wellVtkPoints);
+ wellData->GetPointData()->AddArray(wellNameArray);
+
+ vtkSmartPointer wellGlyphFilter =
+ vtkSmartPointer::New();
+ wellGlyphFilter->SetInputData(wellData);
+
+ vtkSmartPointer wellBorderMapper =
+ vtkSmartPointer::New();
+ wellBorderMapper->SetInputConnection(wellGlyphFilter->GetOutputPort());
+ wellBorderMapper->ScalarVisibilityOff();
+ vtkSmartPointer wellBorderActor =
+ vtkSmartPointer::New();
+ wellBorderActor->SetMapper(wellBorderMapper);
+ wellBorderActor->GetProperty()->SetColor(0.12, 0.12, 0.12);
+ wellBorderActor->GetProperty()->SetPointSize(9.0);
+ renderer->AddActor(wellBorderActor);
+
+ vtkSmartPointer wellMapper =
+ vtkSmartPointer::New();
+ wellMapper->SetInputConnection(wellGlyphFilter->GetOutputPort());
+ wellMapper->ScalarVisibilityOff();
+ vtkSmartPointer wellActor = vtkSmartPointer::New();
+ wellActor->SetMapper(wellMapper);
+ wellActor->GetProperty()->SetColor(0.90, 0.12, 0.10);
+ wellActor->GetProperty()->SetPointSize(5.0);
+ wellActor->SetPosition(0.0, 0.0, 0.001);
+ renderer->AddActor(wellActor);
+
+ // 井名同样使用独立坐标,避免文字覆盖井位标记.
+ const double wellLabelOffset =
+ qMax(bounds.width(), bounds.height()) * 0.022;
+ vtkSmartPointer wellLabelPoints =
+ vtkSmartPointer::New();
+ for(int i = 0; i < wellPoints.size(); ++i) {
+ wellLabelPoints->InsertNextPoint(
+ wellPoints[i].x(),
+ wellPoints[i].y() + wellLabelOffset, 0.05);
+ }
+
+ vtkSmartPointer wellLabelData =
+ vtkSmartPointer::New();
+ wellLabelData->SetPoints(wellLabelPoints);
+ wellLabelData->GetPointData()->AddArray(wellNameArray);
+
+ vtkSmartPointer wellLabelMapper =
+ vtkSmartPointer::New();
+ wellLabelMapper->SetInputData(wellLabelData);
+ wellLabelMapper->SetLabelModeToLabelFieldData();
+ wellLabelMapper->SetFieldDataName("WellName");
+ wellLabelMapper->SetLabelFormat("%s");
+ wellLabelMapper->GetLabelTextProperty()->SetColor(0.10, 0.10, 0.10);
+ wellLabelMapper->GetLabelTextProperty()->SetFontSize(13);
+ wellLabelMapper->GetLabelTextProperty()->BoldOff();
+ wellLabelMapper->GetLabelTextProperty()->ItalicOff();
+ wellLabelMapper->GetLabelTextProperty()->ShadowOff();
+ wellLabelMapper->GetLabelTextProperty()->SetJustificationToCentered();
+ wellLabelMapper->GetLabelTextProperty()->SetVerticalJustificationToBottom();
+
+ vtkSmartPointer wellLabelActor =
+ vtkSmartPointer::New();
+ wellLabelActor->SetMapper(wellLabelMapper);
+ renderer->AddActor2D(wellLabelActor);
+ }
+
vtkSmartPointer scalarBar =
vtkSmartPointer::New();
scalarBar->SetLookupTable(lookupTable);