完善网格属性插值测点管理功能

- 支持多数据组创建、删除及插值参数保存读取
- 支持地图选点、测点标记和当前数据组显隐管理
feature/Interpolation-20260803
lvjunjie 2 weeks ago
parent 19ed90ce86
commit 0e091ff593

Binary file not shown.

@ -6554,6 +6554,22 @@ Average pressure in contour: %2 MPa</source>
<source>Property Interpolation</source> <source>Property Interpolation</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Dataset:</source>
<translation></translation>
</message>
<message>
<source>Add dataset</source>
<translation></translation>
</message>
<message>
<source>Delete dataset</source>
<translation></translation>
</message>
<message>
<source>Dataset #%1</source>
<translation> #%1</translation>
</message>
<message> <message>
<source>Property:</source> <source>Property:</source>
<translation></translation> <translation></translation>
@ -6610,6 +6626,14 @@ Average pressure in contour: %2 MPa</source>
<source>Clear</source> <source>Clear</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Show measurement points</source>
<translation></translation>
</message>
<message>
<source>Show labels</source>
<translation></translation>
</message>
<message> <message>
<source>Kriging Parameters</source> <source>Kriging Parameters</source>
<translation>Kriging</translation> <translation>Kriging</translation>

@ -51,6 +51,47 @@ struct BackgroundImageInfo {
QImage objImage; // 具体的QImage对象 QImage objImage; // 具体的QImage对象
}; };
/* 插值测点数据 */
struct NM_DATA_EXPORT nmPropertyInterpolationPointData {
nmPropertyInterpolationPointData()
: x(0.0), y(0.0), value(0.0)
{
}
nmPropertyInterpolationPointData(double xValue, double yValue, double propertyValue)
: x(xValue), y(yValue), value(propertyValue)
{
}
double x;
double y;
double value;
};
/* 一组属性插值数据及其Kriging参数 */
struct NM_DATA_EXPORT nmPropertyInterpolationDataSet {
nmPropertyInterpolationDataSet()
: property("k"),
showPoints(true),
showLabels(true),
nugget(0.01),
sill(100.0),
range(1000.0),
model(0)
{
}
QString name;
QString property;
QVector<nmPropertyInterpolationPointData> points;
bool showPoints;
bool showLabels;
double nugget;
double sill;
double range;
int model;
};
enum NM_SOLVER_MODEL_TYPE { enum NM_SOLVER_MODEL_TYPE {
SMT_Oil_ConstPvt = 1, SMT_Oil_ConstPvt = 1,
SMT_Oil_VariablePvt = 2, SMT_Oil_VariablePvt = 2,
@ -433,6 +474,10 @@ class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin
// 获取背景图片信息 // 获取背景图片信息
const BackgroundImageInfo& getBackgroundImageInfo() const; const BackgroundImageInfo& getBackgroundImageInfo() const;
/* 获取及设置属性插值数据组 */
QVector<nmPropertyInterpolationDataSet> getPropertyInterpolationDataSets() const;
void setPropertyInterpolationDataSets(const QVector<nmPropertyInterpolationDataSet>& dataSets);
// 统一的读写整个项目数据的方法 // 统一的读写整个项目数据的方法
// @param filePath JSON文件的路径 // @param filePath JSON文件的路径
// @return 读取成功返回 true否则返回 false // @return 读取成功返回 true否则返回 false
@ -647,6 +692,9 @@ class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin
// 显示设置信息 // 显示设置信息
QVector<DisplaySetting> m_vecDisplaySettings; QVector<DisplaySetting> m_vecDisplaySettings;
/* 属性插值数据组 */
QVector<nmPropertyInterpolationDataSet> m_vecPropertyInterpolationDataSets;
// 背景图片信息 // 背景图片信息
BackgroundImageInfo m_backgroundImageInfo; BackgroundImageInfo m_backgroundImageInfo;

@ -42,6 +42,9 @@ class NM_PLOT_EXPORT nmGuiPlot : public iGuiPlot {
// Action命令执行 // Action命令执行
virtual bool runAction(QString sAction) override; virtual bool runAction(QString sAction) override;
// 取消当前地图绘图操作.
void cancelActiveTools();
// 创建添加一个Obj // 创建添加一个Obj
nmObjBase* appendOneObj(NM_Obj_Type o, QString& sName, QVector<QPointF>& vec); nmObjBase* appendOneObj(NM_Obj_Type o, QString& sName, QVector<QPointF>& vec);
nmObjBase* _createOneObj(NM_Obj_Type o, QString& sName); nmObjBase* _createOneObj(NM_Obj_Type o, QString& sName);

@ -19,6 +19,9 @@ public:
virtual bool runAction(QString sAction) override; virtual bool runAction(QString sAction) override;
// 取消当前地图绘图操作,并恢复默认操作状态.
void cancelActiveTools();
// 插入背景 // 插入背景
void insertBkImg(); void insertBkImg();

@ -2,42 +2,118 @@
#define NMWXPROPERTYINTERPOLATIONDLG_H #define NMWXPROPERTYINTERPOLATIONDLG_H
#include "iDlgBase.h" #include "iDlgBase.h"
#include "nmDataAnalyzeManager.h"
#include "nmSubWxs_global.h" #include "nmSubWxs_global.h"
#include <QPointer>
#include <QStringList>
#include <QVector>
class QCheckBox;
class QComboBox; class QComboBox;
class QDoubleSpinBox; class QDoubleSpinBox;
class QEvent;
class QLineEdit; class QLineEdit;
class QPointF;
class QPushButton; class QPushButton;
class QTableWidget; class QTableWidget;
class QTableWidgetItem;
class nmGuiPlot;
class nmObjPoint;
class NM_SUB_WXS_EXPORT nmWxPropertyInterpolationDlg : public iDlgBase class NM_SUB_WXS_EXPORT nmWxPropertyInterpolationDlg : public iDlgBase
{ {
Q_OBJECT
public: public:
explicit nmWxPropertyInterpolationDlg(QWidget* parent = 0); explicit nmWxPropertyInterpolationDlg(nmGuiPlot* plot,
nmDataAnalyzeManager* dataManager,
QWidget* parent = 0);
~nmWxPropertyInterpolationDlg();
protected:
bool eventFilter(QObject* watched, QEvent* event);
private slots:
void onDataSetChanged(int index);
void onAddDataSet();
void onDeleteDataSet();
void onDataSetNameChanged(const QString& name);
void onCurrentDataSetEdited();
void onMapPickToggled(bool checked);
void onMapClicked(const QPointF& position);
void onPointSelectionChanged();
void onPointItemChanged(QTableWidgetItem* item);
void onDeleteSelectedPoint();
void onClearPoints();
void onShowPointsToggled(bool checked);
void onShowLabelsToggled(bool checked);
private: private:
// 初始化属性插值界面 // 初始化界面及持久化数据组.
void initInterpolationUI(); void initInterpolationUI();
void initializeDataSets();
nmPropertyInterpolationDataSet createDefaultDataSet();
QString nextDataSetName();
void loadDataSet(int index);
void clearCurrentDataSet();
void saveCurrentDataSet();
void syncDataSetsToManager(bool markModified);
void updateDataSetButtons();
// 管理测点表格和地图上的临时标记.
void appendPoint(const QPointF& valuePoint);
void appendPointRow(const nmPropertyInterpolationPointData& point,
const QString& markerName);
QString createMarker(const QPointF& valuePosition,
double value,
bool showPoints,
bool showLabels);
void createMarkersForAllDataSets();
void removeDataSetMarkers(int dataSetIndex);
void removeAllMarkers();
QString markerNameAt(int row) const;
nmObjPoint* markerByName(const QString& markerName) const;
nmObjPoint* markerAt(int row) const;
void removeMarkerByName(const QString& markerName);
void clearTableSelection();
void updatePointButtons();
void updateCurrentMarkerVisibility();
private: private:
// 插值属性及名称 QPointer<nmGuiPlot> m_pPlot;
QPointer<nmDataAnalyzeManager> m_pDataManager;
// 多组插值数据.
QComboBox* m_pDataSetCombo;
QPushButton* m_pAddDataSetButton;
QPushButton* m_pDeleteDataSetButton;
QVector<nmPropertyInterpolationDataSet> m_vecDataSets;
QVector<QStringList> m_vecMarkerNames;
int m_nCurrentDataSetIndex;
int m_nNextPointId;
bool m_bUpdatingUi;
// 当前数据组的属性及名称.
QComboBox* m_pPropertyCombo; QComboBox* m_pPropertyCombo;
QLineEdit* m_pNameEdit; QLineEdit* m_pNameEdit;
// 测点数据录入 // 测点数据录入.
QDoubleSpinBox* m_pNewValueSpin; QDoubleSpinBox* m_pNewValueSpin;
QPushButton* m_pMapPickButton; QPushButton* m_pMapPickButton;
QTableWidget* m_pPointTable; QTableWidget* m_pPointTable;
QPushButton* m_pDeletePointButton; QPushButton* m_pDeletePointButton;
QPushButton* m_pClearPointsButton; QPushButton* m_pClearPointsButton;
QCheckBox* m_pShowPointsCheck;
QCheckBox* m_pShowLabelsCheck;
// Kriging插值参数 // Kriging插值参数.
QDoubleSpinBox* m_pNuggetSpin; QDoubleSpinBox* m_pNuggetSpin;
QDoubleSpinBox* m_pSillSpin; QDoubleSpinBox* m_pSillSpin;
QDoubleSpinBox* m_pRangeSpin; QDoubleSpinBox* m_pRangeSpin;
QComboBox* m_pModelCombo; QComboBox* m_pModelCombo;
// 结果预览及应用 // 结果预览及应用.
QPushButton* m_pPreviewButton; QPushButton* m_pPreviewButton;
QPushButton* m_pApplyButton; QPushButton* m_pApplyButton;
}; };

@ -65,6 +65,7 @@
#include "nmDataTimeStepSetting.h" #include "nmDataTimeStepSetting.h"
#include <QByteArray>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDebug> #include <QDebug>
#include <QDir> #include <QDir>
@ -3353,6 +3354,17 @@ const BackgroundImageInfo& nmDataAnalyzeManager::getBackgroundImageInfo() const
return m_backgroundImageInfo; return m_backgroundImageInfo;
} }
QVector<nmPropertyInterpolationDataSet> nmDataAnalyzeManager::getPropertyInterpolationDataSets() const
{
return m_vecPropertyInterpolationDataSets;
}
void nmDataAnalyzeManager::setPropertyInterpolationDataSets(
const QVector<nmPropertyInterpolationDataSet>& dataSets)
{
m_vecPropertyInterpolationDataSets = dataSets;
}
// 从 JSON 文件读取数据到 C++ 对象 // 从 JSON 文件读取数据到 C++ 对象
bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath) bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath)
{ {
@ -3400,6 +3412,7 @@ bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath)
} }
m_vecLayers.clear(); m_vecLayers.clear();
m_vecPropertyInterpolationDataSets.clear();
if(m_reservoirData) { if(m_reservoirData) {
delete m_reservoirData; delete m_reservoirData;
@ -3517,7 +3530,66 @@ bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath)
} }
} }
// 解析 "Reservoir" 对象 /* 读取属性插值数据组;旧成果没有该节点时保持为空 */
if(doc.HasMember("PropertyInterpolationDataSets") &&
doc["PropertyInterpolationDataSets"].IsArray()) {
const rapidjson::Value& dataSetsJson = doc["PropertyInterpolationDataSets"];
for(rapidjson::SizeType i = 0; i < dataSetsJson.Size(); ++i) {
const rapidjson::Value& dataSetJson = dataSetsJson[i];
if(!dataSetJson.IsObject()) {
continue;
}
nmPropertyInterpolationDataSet dataSet;
if(dataSetJson.HasMember("Name") && dataSetJson["Name"].IsString()) {
dataSet.name = QString::fromUtf8(dataSetJson["Name"].GetString());
}
if(dataSetJson.HasMember("Property") && dataSetJson["Property"].IsString()) {
dataSet.property = QString::fromUtf8(dataSetJson["Property"].GetString());
}
if(dataSetJson.HasMember("ShowPoints") && dataSetJson["ShowPoints"].IsBool()) {
dataSet.showPoints = dataSetJson["ShowPoints"].GetBool();
}
if(dataSetJson.HasMember("ShowLabels") && dataSetJson["ShowLabels"].IsBool()) {
dataSet.showLabels = dataSetJson["ShowLabels"].GetBool();
}
if(dataSetJson.HasMember("Nugget") && dataSetJson["Nugget"].IsNumber()) {
dataSet.nugget = dataSetJson["Nugget"].GetDouble();
}
if(dataSetJson.HasMember("Sill") && dataSetJson["Sill"].IsNumber()) {
dataSet.sill = dataSetJson["Sill"].GetDouble();
}
if(dataSetJson.HasMember("Range") && dataSetJson["Range"].IsNumber()) {
dataSet.range = dataSetJson["Range"].GetDouble();
}
if(dataSetJson.HasMember("Model") && dataSetJson["Model"].IsInt()) {
dataSet.model = dataSetJson["Model"].GetInt();
}
if(dataSetJson.HasMember("Points") && dataSetJson["Points"].IsArray()) {
const rapidjson::Value& pointsJson = dataSetJson["Points"];
for(rapidjson::SizeType pointIndex = 0; pointIndex < pointsJson.Size(); ++pointIndex) {
const rapidjson::Value& pointJson = pointsJson[pointIndex];
if(!pointJson.IsObject() ||
!pointJson.HasMember("X") || !pointJson["X"].IsNumber() ||
!pointJson.HasMember("Y") || !pointJson["Y"].IsNumber() ||
!pointJson.HasMember("Value") || !pointJson["Value"].IsNumber()) {
continue;
}
dataSet.points.append(nmPropertyInterpolationPointData(
pointJson["X"].GetDouble(),
pointJson["Y"].GetDouble(),
pointJson["Value"].GetDouble()));
}
}
m_vecPropertyInterpolationDataSets.append(dataSet);
}
}
/* 解析 "Reservoir" 对象 */
if(doc.HasMember("Reservoir") && doc["Reservoir"].IsObject()) { if(doc.HasMember("Reservoir") && doc["Reservoir"].IsObject()) {
m_reservoirData = new nmDataReservoir; m_reservoirData = new nmDataReservoir;
m_reservoirData->FromJsonValue(doc["Reservoir"]); m_reservoirData->FromJsonValue(doc["Reservoir"]);
@ -3736,6 +3808,42 @@ bool nmDataAnalyzeManager::WriteProjectData(const QString & filePath)
doc.AddMember("Layers", layersJsonArray, allocator); doc.AddMember("Layers", layersJsonArray, allocator);
/* 保存属性插值数据组 */
rapidjson::Value interpolationDataSetsJson(rapidjson::kArrayType);
for(int dataSetIndex = 0;
dataSetIndex < m_vecPropertyInterpolationDataSets.size();
++dataSetIndex) {
const nmPropertyInterpolationDataSet& dataSet =
m_vecPropertyInterpolationDataSets[dataSetIndex];
rapidjson::Value dataSetJson(rapidjson::kObjectType);
QByteArray nameUtf8 = dataSet.name.toUtf8();
QByteArray propertyUtf8 = dataSet.property.toUtf8();
dataSetJson.AddMember("Name",
rapidjson::Value(nameUtf8.constData(), allocator).Move(), allocator);
dataSetJson.AddMember("Property",
rapidjson::Value(propertyUtf8.constData(), allocator).Move(), allocator);
dataSetJson.AddMember("ShowPoints", dataSet.showPoints, allocator);
dataSetJson.AddMember("ShowLabels", dataSet.showLabels, allocator);
dataSetJson.AddMember("Nugget", dataSet.nugget, allocator);
dataSetJson.AddMember("Sill", dataSet.sill, allocator);
dataSetJson.AddMember("Range", dataSet.range, allocator);
dataSetJson.AddMember("Model", dataSet.model, allocator);
rapidjson::Value pointsJson(rapidjson::kArrayType);
for(int pointIndex = 0; pointIndex < dataSet.points.size(); ++pointIndex) {
const nmPropertyInterpolationPointData& point = dataSet.points[pointIndex];
rapidjson::Value pointJson(rapidjson::kObjectType);
pointJson.AddMember("X", point.x, allocator);
pointJson.AddMember("Y", point.y, allocator);
pointJson.AddMember("Value", point.value, allocator);
pointsJson.PushBack(pointJson, allocator);
}
dataSetJson.AddMember("Points", pointsJson, allocator);
interpolationDataSetsJson.PushBack(dataSetJson, allocator);
}
doc.AddMember("PropertyInterpolationDataSets", interpolationDataSetsJson, allocator);
// 序列化 "Reservoir" // 序列化 "Reservoir"
if(m_reservoirData) { if(m_reservoirData) {
rapidjson::Value reservoirJson(rapidjson::kObjectType); rapidjson::Value reservoirJson(rapidjson::kObjectType);

@ -7,7 +7,6 @@
// RapidJSON 内部使用 char*,这里需要转换为 std::string // RapidJSON 内部使用 char*,这里需要转换为 std::string
#include <string> #include <string>
#include <QFile> #include <QFile>
#include <QTextStream>
#include <QString> #include <QString>
#include "rapidjson/document.h" #include "rapidjson/document.h"
@ -211,39 +210,34 @@ bool nmDataJsonTools::WriteDomToFile(const rapidjson::Document& doc, const QStri
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer); // 使用 PrettyWriter 进行美化输出 rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer); // 使用 PrettyWriter 进行美化输出
doc.Accept(writer); doc.Accept(writer);
// 将字符串写入文件 /* RapidJSON输出为UTF-8字节直接写入可避免中文被本地编码再次转换 */
QFile file(filePath); QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "Error: Could not open file for writing:" << filePath; qDebug() << "Error: Could not open file for writing:" << filePath;
return false; return false;
} }
QTextStream out(&file); const qint64 bufferSize = static_cast<qint64>(buffer.GetSize());
out << buffer.GetString(); const qint64 writtenSize = file.write(buffer.GetString(), bufferSize);
file.close(); file.close();
return true; return writtenSize == bufferSize;
} }
// 从文件读取 JSON 并解析到 RapidJSON Document // 从文件读取 JSON 并解析到 RapidJSON Document
bool nmDataJsonTools::ReadDomFromFile(const QString& filePath, rapidjson::Document& doc) bool nmDataJsonTools::ReadDomFromFile(const QString& filePath, rapidjson::Document& doc)
{ {
QFile file(filePath); QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "Error: Could not open file for reading:" << filePath; qDebug() << "Error: Could not open file for reading:" << filePath;
return false; return false;
} }
QTextStream in(&file); const QByteArray jsonData = file.readAll();
QString jsonString = in.readAll();
file.close(); file.close();
// 将 QString 转换为 std::string /* 文件内容保持RapidJSON所需的UTF-8编码 */
QByteArray byteArray = jsonString.toUtf8(); doc.Parse(jsonData.constData());
std::string stdJsonString = byteArray.constData();
// 解析 JSON 字符串到 RapidJSON Document
doc.Parse(stdJsonString.c_str());
if (doc.HasParseError()) { if (doc.HasParseError()) {
qDebug() << "Error parsing JSON from file:" << filePath << "Error:" << doc.GetParseError(); qDebug() << "Error parsing JSON from file:" << filePath << "Error:" << doc.GetParseError();
@ -251,4 +245,4 @@ bool nmDataJsonTools::ReadDomFromFile(const QString& filePath, rapidjson::Docume
} }
return true; return true;
} }

@ -167,6 +167,14 @@ bool nmGuiPlot::runAction(QString sAction)
return m_pCmdHelper->runAction(sAction); return m_pCmdHelper->runAction(sAction);
} }
void nmGuiPlot::cancelActiveTools()
{
nmGuiPlotCmdHelper* helper = dynamic_cast<nmGuiPlotCmdHelper*>(m_pCmdHelper);
if(helper != NULL) {
helper->cancelActiveTools();
}
}
void nmGuiPlot::initDefultGeoObj() void nmGuiPlot::initDefultGeoObj()
{ {

@ -161,6 +161,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool); pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \ connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \
this, SLOT(slotObjPtsFinished(QVector<QPointF>&))); this, SLOT(slotObjPtsFinished(QVector<QPointF>&)));
m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true; return true;
} else if (_isSame(sAction, "nmInsertObjPointWell")) { } else if (_isSame(sAction, "nmInsertObjPointWell")) {
nmObjToolBase* pObjTool = new nmObjPointWellTool(); nmObjToolBase* pObjTool = new nmObjPointWellTool();
@ -169,6 +170,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool); pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \ connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \
this, SLOT(slotObjPtsFinished(QVector<QPointF>&))); this, SLOT(slotObjPtsFinished(QVector<QPointF>&)));
m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true; return true;
} else if (_isSame(sAction, "nmInsertObjLine")) { } else if (_isSame(sAction, "nmInsertObjLine")) {
nmObjToolBase* pObjTool = new nmObjLineTool(); nmObjToolBase* pObjTool = new nmObjLineTool();
@ -176,6 +178,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool); pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \ connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \
this, SLOT(slotObjPtsFinished(QVector<QPointF>&))); this, SLOT(slotObjPtsFinished(QVector<QPointF>&)));
m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true; return true;
} else if (_isSame(sAction, "nmInsertObjPolygon")) { } else if (_isSame(sAction, "nmInsertObjPolygon")) {
nmObjToolBase* pObjTool = new nmObjPolygonTool(); nmObjToolBase* pObjTool = new nmObjPolygonTool();
@ -183,6 +186,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool); pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \ connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \
this, SLOT(slotObjPtsFinished(QVector<QPointF>&))); this, SLOT(slotObjPtsFinished(QVector<QPointF>&)));
m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true; return true;
} else if (_isSame(sAction, "nmInsertObjPolygonOutline")) { } else if (_isSame(sAction, "nmInsertObjPolygonOutline")) {
nmObjToolBase* pObjTool = new nmObjPolygonOutlineTool(); nmObjToolBase* pObjTool = new nmObjPolygonOutlineTool();
@ -190,6 +194,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool); pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \ connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \
this, SLOT(slotObjPtsFinished(QVector<QPointF>&))); this, SLOT(slotObjPtsFinished(QVector<QPointF>&)));
m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true; return true;
} else if (_isSame(sAction, "nmInsertObjRect")) { } else if (_isSame(sAction, "nmInsertObjRect")) {
nmObjToolBase* pObjTool = new nmObjRectTool(); //矩形对象工具类 nmObjToolBase* pObjTool = new nmObjRectTool(); //矩形对象工具类
@ -197,6 +202,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool); pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \ connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \
this, SLOT(slotObjPtsFinished(QVector<QPointF>&))); this, SLOT(slotObjPtsFinished(QVector<QPointF>&)));
m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true; return true;
} else if (_isSame(sAction, "nmInsertObjRectOutline")) { } else if (_isSame(sAction, "nmInsertObjRectOutline")) {
nmObjToolBase* pObjTool = new nmObjRectOutlineTool(); //矩形边界工具类 nmObjToolBase* pObjTool = new nmObjRectOutlineTool(); //矩形边界工具类
@ -204,6 +210,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool); pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \ connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \
this, SLOT(slotObjPtsFinished(QVector<QPointF>&))); this, SLOT(slotObjPtsFinished(QVector<QPointF>&)));
m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true; return true;
} else if (_isSame(sAction, "nmInsertObjRound")) { } else if (_isSame(sAction, "nmInsertObjRound")) {
nmObjToolBase* pObjTool = new nmObjRoundTool(); //圆形对象工具类 nmObjToolBase* pObjTool = new nmObjRoundTool(); //圆形对象工具类
@ -211,6 +218,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool); pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \ connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \
this, SLOT(slotObjPtsFinished(QVector<QPointF>&))); this, SLOT(slotObjPtsFinished(QVector<QPointF>&)));
m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true; return true;
} else if (_isSame(sAction, "nmInsertObjRoundOutline")) { } else if (_isSame(sAction, "nmInsertObjRoundOutline")) {
nmObjToolBase* pObjTool = new nmObjRoundOutlineTool(); //圆形边界工具类 nmObjToolBase* pObjTool = new nmObjRoundOutlineTool(); //圆形边界工具类
@ -218,6 +226,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool); pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \ connect(pObjTool, SIGNAL(sigPtsFinished(QVector<QPointF>&)), \
this, SLOT(slotObjPtsFinished(QVector<QPointF>&))); this, SLOT(slotObjPtsFinished(QVector<QPointF>&)));
m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true; return true;
} else if (_isSame(sAction, "nmInsertObjLineCrack")) { } else if (_isSame(sAction, "nmInsertObjLineCrack")) {
nmObjToolBase* pObjTool = new nmObjLineCrackTool(); nmObjToolBase* pObjTool = new nmObjLineCrackTool();
@ -298,6 +307,21 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
return iGuiPlotCmdHelper::runAction(sAction); return iGuiPlotCmdHelper::runAction(sAction);
} }
void nmGuiPlotCmdHelper::cancelActiveTools()
{
nmGuiPlot* pWxPlot = dynamic_cast<nmGuiPlot*>(m_pGuiPlot);
if(pWxPlot == nullptr || pWxPlot->m_pPlot == nullptr ||
pWxPlot->m_pPlotView == nullptr) {
return;
}
foreach (nmObjToolBase* activeTool, m_activeTools.values()) {
pWxPlot->m_pPlot->removeTools(activeTool);
}
m_activeTools.clear();
finalWithAcm(true, true);
}
void nmGuiPlotCmdHelper::slotObjPtsFinished(QVector<QPointF>& vec) { void nmGuiPlotCmdHelper::slotObjPtsFinished(QVector<QPointF>& vec) {
nmObjToolBase* pTool = dynamic_cast<nmObjToolBase*>(sender()); nmObjToolBase* pTool = dynamic_cast<nmObjToolBase*>(sender());
if (NULL == pTool) { if (NULL == pTool) {

@ -1446,7 +1446,8 @@ QWidget* nmSubWndMain::showPointerPosDialog()
QWidget* nmSubWndMain::showPropertyInterpolationDialog() QWidget* nmSubWndMain::showPropertyInterpolationDialog()
{ {
nmWxPropertyInterpolationDlg* interpolationDlg = new nmWxPropertyInterpolationDlg(this); nmWxPropertyInterpolationDlg* interpolationDlg = new nmWxPropertyInterpolationDlg(
m_pWxPlot, nmDataAnalyzeManager::getCurrentInstance(), this);
markDialogCmdOpened(5126); markDialogCmdOpened(5126);
interpolationDlg->setObjectName("nmPropertyInterpolationDialog"); interpolationDlg->setObjectName("nmPropertyInterpolationDialog");
// 关闭窗口时自动释放,并恢复菜单命令的可用状态 // 关闭窗口时自动释放,并恢复菜单命令的可用状态

@ -1,28 +1,43 @@
#include "nmWxPropertyInterpolationDlg.h" #include "nmWxPropertyInterpolationDlg.h"
#include <QAbstractItemView> #include <QAbstractItemView>
#include <QApplication>
#include <QCheckBox>
#include <QComboBox> #include <QComboBox>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QEvent>
#include <QFormLayout> #include <QFormLayout>
#include <QGroupBox> #include <QGroupBox>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QHeaderView> #include <QHeaderView>
#include <QIcon>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QMouseEvent>
#include <QPainter>
#include <QPushButton> #include <QPushButton>
#include <QSize>
#include <QTableWidget> #include <QTableWidget>
#include <QTableWidgetItem>
#include <QTransform>
#include <QVBoxLayout> #include <QVBoxLayout>
#include "nmGuiPlot.h"
#include "nmObjPoint.h"
#include "tCurvePlotView.h"
#include "ZxObjText.h"
#include "ZxPlot.h"
namespace namespace
{ {
// 使用独立翻译上下文,便于统一维护对话框文本 // 使用独立翻译上下文,便于统一维护对话框文本.
QString interpolationText(const char* sourceText) QString interpolationText(const char* sourceText)
{ {
return QCoreApplication::translate("nmWxPropertyInterpolationDlg", sourceText); return QCoreApplication::translate("nmWxPropertyInterpolationDlg", sourceText);
} }
// 创建统一格式的非负数值输入框 // 创建统一格式的非负数值输入框.
QDoubleSpinBox* createNumberSpinBox(QWidget* parent, double value) QDoubleSpinBox* createNumberSpinBox(QWidget* parent, double value)
{ {
QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent); QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
@ -32,10 +47,82 @@ QDoubleSpinBox* createNumberSpinBox(QWidget* parent, double value)
spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons); spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
return spinBox; 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));
}
}
} }
nmWxPropertyInterpolationDlg::nmWxPropertyInterpolationDlg(QWidget* parent) nmWxPropertyInterpolationDlg::nmWxPropertyInterpolationDlg(
nmGuiPlot* plot,
nmDataAnalyzeManager* dataManager,
QWidget* parent)
: iDlgBase(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_pPropertyCombo(NULL),
m_pNameEdit(NULL), m_pNameEdit(NULL),
m_pNewValueSpin(NULL), m_pNewValueSpin(NULL),
@ -43,6 +130,8 @@ nmWxPropertyInterpolationDlg::nmWxPropertyInterpolationDlg(QWidget* parent)
m_pPointTable(NULL), m_pPointTable(NULL),
m_pDeletePointButton(NULL), m_pDeletePointButton(NULL),
m_pClearPointsButton(NULL), m_pClearPointsButton(NULL),
m_pShowPointsCheck(NULL),
m_pShowLabelsCheck(NULL),
m_pNuggetSpin(NULL), m_pNuggetSpin(NULL),
m_pSillSpin(NULL), m_pSillSpin(NULL),
m_pRangeSpin(NULL), m_pRangeSpin(NULL),
@ -56,25 +145,66 @@ nmWxPropertyInterpolationDlg::nmWxPropertyInterpolationDlg(QWidget* parent)
setMinimumSize(520, 620); setMinimumSize(520, 620);
resize(560, 680); resize(560, 680);
initInterpolationUI(); 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() void nmWxPropertyInterpolationDlg::initInterpolationUI()
{ {
QVBoxLayout* mainLayout = new QVBoxLayout(this); 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; QFormLayout* dataSetLayout = new QFormLayout;
m_pNameEdit = new QLineEdit(this);
dataSetLayout->addRow(interpolationText("Name:"), m_pNameEdit);
m_pPropertyCombo = new QComboBox(this); m_pPropertyCombo = new QComboBox(this);
m_pPropertyCombo->addItem(interpolationText("Permeability k"), QString("k")); m_pPropertyCombo->addItem(interpolationText("Permeability k"), QString("k"));
m_pPropertyCombo->addItem(interpolationText("Porosity phi"), QString("phi")); m_pPropertyCombo->addItem(interpolationText("Porosity phi"), QString("phi"));
m_pPropertyCombo->addItem(interpolationText("Reservoir thickness h"), QString("h")); m_pPropertyCombo->addItem(interpolationText("Reservoir thickness h"), QString("h"));
dataSetLayout->addRow(interpolationText("Property:"), m_pPropertyCombo); dataSetLayout->addRow(interpolationText("Property:"), m_pPropertyCombo);
m_pNameEdit = new QLineEdit(interpolationText("Permeability"), this);
dataSetLayout->addRow(interpolationText("Name:"), m_pNameEdit);
mainLayout->addLayout(dataSetLayout); mainLayout->addLayout(dataSetLayout);
// 测点数据录入区域 // 测点数据录入区域.
QGroupBox* pointGroup = new QGroupBox(interpolationText("Measurement Points"), this); QGroupBox* pointGroup = new QGroupBox(interpolationText("Measurement Points"), this);
QVBoxLayout* pointLayout = new QVBoxLayout(pointGroup); QVBoxLayout* pointLayout = new QVBoxLayout(pointGroup);
@ -84,12 +214,12 @@ void nmWxPropertyInterpolationDlg::initInterpolationUI()
newPointLayout->addWidget(m_pNewValueSpin, 1); newPointLayout->addWidget(m_pNewValueSpin, 1);
m_pMapPickButton = new QPushButton(interpolationText("Select on Map"), pointGroup); m_pMapPickButton = new QPushButton(interpolationText("Select on Map"), pointGroup);
m_pMapPickButton->setCheckable(true); m_pMapPickButton->setCheckable(true);
// 地图选点功能将在后续阶段接入 m_pMapPickButton->setEnabled(!m_pPlot.isNull() &&
m_pMapPickButton->setEnabled(false); m_pPlot->m_pPlotView != NULL &&
m_pPlot->m_pPlot != NULL);
newPointLayout->addWidget(m_pMapPickButton); newPointLayout->addWidget(m_pMapPickButton);
pointLayout->addLayout(newPointLayout); pointLayout->addLayout(newPointLayout);
// 每个测点保存坐标及对应的属性值
m_pPointTable = new QTableWidget(0, 3, pointGroup); m_pPointTable = new QTableWidget(0, 3, pointGroup);
QStringList headers; QStringList headers;
headers << interpolationText("X") << interpolationText("Y") << interpolationText("Value"); headers << interpolationText("X") << interpolationText("Y") << interpolationText("Value");
@ -100,7 +230,6 @@ void nmWxPropertyInterpolationDlg::initInterpolationUI()
m_pPointTable->setAlternatingRowColors(true); m_pPointTable->setAlternatingRowColors(true);
pointLayout->addWidget(m_pPointTable, 1); pointLayout->addWidget(m_pPointTable, 1);
// 测点列表管理按钮
QHBoxLayout* pointButtonLayout = new QHBoxLayout; QHBoxLayout* pointButtonLayout = new QHBoxLayout;
pointButtonLayout->addStretch(); pointButtonLayout->addStretch();
m_pDeletePointButton = new QPushButton(interpolationText("Delete Selected"), pointGroup); m_pDeletePointButton = new QPushButton(interpolationText("Delete Selected"), pointGroup);
@ -110,9 +239,19 @@ void nmWxPropertyInterpolationDlg::initInterpolationUI()
m_pClearPointsButton->setEnabled(false); m_pClearPointsButton->setEnabled(false);
pointButtonLayout->addWidget(m_pClearPointsButton); pointButtonLayout->addWidget(m_pClearPointsButton);
pointLayout->addLayout(pointButtonLayout); 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); mainLayout->addWidget(pointGroup, 1);
// Kriging插值参数设置 // Kriging插值参数设置.
QGroupBox* parameterGroup = new QGroupBox(interpolationText("Kriging Parameters"), this); QGroupBox* parameterGroup = new QGroupBox(interpolationText("Kriging Parameters"), this);
QFormLayout* parameterLayout = new QFormLayout(parameterGroup); QFormLayout* parameterLayout = new QFormLayout(parameterGroup);
m_pNuggetSpin = createNumberSpinBox(parameterGroup, 0.01); m_pNuggetSpin = createNumberSpinBox(parameterGroup, 0.01);
@ -128,10 +267,9 @@ void nmWxPropertyInterpolationDlg::initInterpolationUI()
parameterLayout->addRow(interpolationText("Model:"), m_pModelCombo); parameterLayout->addRow(interpolationText("Model:"), m_pModelCombo);
mainLayout->addWidget(parameterGroup); mainLayout->addWidget(parameterGroup);
// 底部操作按钮 // 底部操作按钮.
QHBoxLayout* buttonLayout = new QHBoxLayout; QHBoxLayout* buttonLayout = new QHBoxLayout;
m_pPreviewButton = new QPushButton(interpolationText("Preview"), this); m_pPreviewButton = new QPushButton(interpolationText("Preview"), this);
// 插值计算和预览功能将在后续阶段接入
m_pPreviewButton->setEnabled(false); m_pPreviewButton->setEnabled(false);
buttonLayout->addWidget(m_pPreviewButton); buttonLayout->addWidget(m_pPreviewButton);
buttonLayout->addStretch(); buttonLayout->addStretch();
@ -142,5 +280,640 @@ void nmWxPropertyInterpolationDlg::initInterpolationUI()
buttonLayout->addWidget(closeButton); buttonLayout->addWidget(closeButton);
mainLayout->addLayout(buttonLayout); 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(closeButton, SIGNAL(clicked()), this, SLOT(close())); 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);
}
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();
}
}

Loading…
Cancel
Save