3d Cross Plot: First implementation (#4127)

* First cross plot commit

* Made cross plot deal with "all time steps" and categorise curves based on time step

* Support STATIC vs DYNAMIC plotting

* #4115 Avoid updating plots in RimEclipseCase::computeCachedData()

* Make sure loading of Cross plot from file works

* Show Legend in Cross Plot

* Uncheck / Check curves to disable/enable

* Axis titles and checkable data set

* Name config and setting of common plot look

* Fix category indentation in GeoMech results

* Support name configuration for Grid Cross Plot

* Support adding new curve sets

* Improve colors and symbols with better cycling

* Moved GridCrossPlot files to sub directory in ProjectDataModel and Commands

* #4111 3D calculations : Always show difference options

* Whitespace

* #4111 Move resultDefinition field to private

* Whitespace

* #4087 Ensemble : When importing and ensemble, show by default an ensemble plot

* #4085 3D view: Improve overlay item colors

* #4106 Crash on Linux

Temporary workaround to avoid crash

* #4106 Stop trying to do recursive setting tab order widget

* The double pointer was handled wrongly and shift-tab order isn't working anyway.

* #4114 Regression Test : Remove cached pointer to eclipse case

* Revert "#4114 Regression Test : Remove cached pointer to eclipse case"

This reverts commit f2146c6007.

* #4114 Regression Test : Missing data for flow diag property filter

* #4085 3D view: Add check box for version info text

* Whtespace

* Improve labelling of static results

* Fix update of result property when changing type
This commit is contained in:
Gaute Lindkvist
2019-02-21 12:52:23 +01:00
committed by GitHub
parent 8182421fb5
commit a010fc03d7
41 changed files with 1929 additions and 85 deletions

View File

@@ -50,6 +50,8 @@
#include "RimGeoMechCellColors.h"
#include "RimGeoMechModels.h"
#include "RimGeoMechView.h"
#include "RimGridCrossPlot.h"
#include "RimGridCrossPlotCollection.h"
#include "RimIdenticalGridCaseGroup.h"
#include "RimMainPlotCollection.h"
#include "RimObservedData.h"
@@ -653,6 +655,7 @@ void RiaApplication::loadAndUpdatePlotData()
RimFlowPlotCollection* flowColl = nullptr;
RimRftPlotCollection* rftColl = nullptr;
RimPltPlotCollection* pltColl = nullptr;
RimGridCrossPlotCollection* gcpColl = nullptr;
if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->wellLogPlotCollection())
{
@@ -678,6 +681,10 @@ void RiaApplication::loadAndUpdatePlotData()
{
pltColl = m_project->mainPlotCollection()->pltPlotCollection();
}
if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->gridCrossPlotCollection())
{
gcpColl = m_project->mainPlotCollection()->gridCrossPlotCollection();
}
size_t plotCount = 0;
plotCount += wlpColl ? wlpColl->wellLogPlots().size() : 0;
@@ -686,6 +693,7 @@ void RiaApplication::loadAndUpdatePlotData()
plotCount += flowColl ? flowColl->plotCount() : 0;
plotCount += rftColl ? rftColl->rftPlots().size() : 0;
plotCount += pltColl ? pltColl->pltPlots().size() : 0;
plotCount += gcpColl ? gcpColl->gridCrossPlots().size() : 0;
if (plotCount > 0)
{
@@ -741,6 +749,15 @@ void RiaApplication::loadAndUpdatePlotData()
plotProgress.incrementProgress();
}
}
if (gcpColl)
{
for (const auto& gcpPlot : gcpColl->gridCrossPlots())
{
gcpPlot->loadDataAndUpdate();
plotProgress.incrementProgress();
}
}
}
}

View File

@@ -163,6 +163,16 @@ const caf::ColorTable& RiaColorTables::categoryPaletteColors()
return colorTable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const caf::ColorTable& RiaColorTables::contrastCategoryPaletteColors()
{
static caf::ColorTable colorTable = caf::ColorTable(contrastCategoryColors());
return colorTable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -563,6 +573,42 @@ std::vector<cvf::Color3ub> RiaColorTables::categoryColors()
return colors;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<cvf::Color3ub> RiaColorTables::contrastCategoryColors()
{
// Based on http://stackoverflow.com/questions/470690/how-to-automatically-generate-n-distinct-colors
// and Kelly Colors and sorted by hue
// See also http://www.w3schools.com/colors/ for palettes etc.
static std::vector<cvf::Color3ub> colors{
cvf::Color3ub(244, 200, 0), // hwb( 49, 0%, 4%) vivid_greenish_yellow
cvf::Color3ub(128, 62, 117), // hwb(310, 24%, 50%) strong_purple
cvf::Color3ub(255, 104, 0), // hwb( 24, 0%, 0%) vivid_orange
cvf::Color3ub(166, 189, 215), // hwb(212, 65%, 16%) very_light_blue
cvf::Color3ub(193, 0, 32), // hwb(350, 0%, 24%) vivid_red
cvf::Color3ub(206, 162, 98), // hwb( 36, 38%, 19%) grayish_yellow
cvf::Color3ub(129, 112, 102), // hwb( 22, 40%, 49%) medium_gray
cvf::Color3ub(0, 125, 52), // hwb(145, 0%, 51%) vivid_green
cvf::Color3ub(246, 118, 142), // hwb(349, 46%, 4%) strong_purplish_pink
cvf::Color3ub(0, 83, 138), // hwb(204, 0%, 46%) strong_blue
cvf::Color3ub(255, 122, 92), // hwb( 11, 36%, 0%) strong_yellowish_pink
cvf::Color3ub(212, 28, 132), // hwb(326, 11%, 17%) strong_purplish_red
cvf::Color3ub(255, 142, 0), // hwb( 33, 0%, 0%) vivid_orange_yellow
cvf::Color3ub(59, 84, 23), // hwb( 85, 9%, 67%) dark_olive_green
cvf::Color3ub(127, 24, 13), // hwb( 6, 5%, 50%) strong_reddish_brown
cvf::Color3ub(54, 125, 123), // hwb(178, 21%, 51%) vivid_blueish_green
cvf::Color3ub(241, 58, 19), // hwb( 11, 7%, 5%) vivid_reddish_orange
cvf::Color3ub(147, 170, 0), // hwb( 68, 0%, 33%) vivid_yellowish_green
cvf::Color3ub(46, 76, 224), // hwb(230, 18%, 12%) medium_blue
cvf::Color3ub(89, 51, 21), // hwb( 26, 8%, 65%) deep_yellowish_brown
cvf::Color3ub(0, 0, 0) // hwb(0, 0%, 100%) black
};
return colors;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -40,6 +40,7 @@ public:
static const caf::ColorTable& blueWhiteRedPaletteColors();
static const caf::ColorTable& redWhiteBluePaletteColors();
static const caf::ColorTable& categoryPaletteColors();
static const caf::ColorTable& contrastCategoryPaletteColors();
static const caf::ColorTable& tensorWhiteGrayBlackPaletteColors();
static const caf::ColorTable& tensorOrangeBlueWhitePaletteColors();
static const caf::ColorTable& tensorsMagentaBrownGrayPaletteColors();
@@ -65,5 +66,6 @@ public:
private:
static std::vector<cvf::Color3ub> categoryColors();
static std::vector<cvf::Color3ub> contrastCategoryColors();
static std::vector<cvf::Color3ub> invertedCategoryColors();
};

View File

@@ -57,6 +57,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Annotations
${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Completions
${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Flow
${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/GridCrossPlots
${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Measurement
${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Summary
@@ -107,6 +108,7 @@ list( APPEND REFERENCED_CMAKE_FILES
FileInterface/CMakeLists_files.cmake
ProjectDataModel/CMakeLists_files.cmake
ProjectDataModel/GridCrossPlots/CMakeLists_files.cmake
ProjectDataModel/Summary/CMakeLists_files.cmake
ProjectDataModel/Flow/CMakeLists_files.cmake
ProjectDataModel/Annotations/CMakeLists_files.cmake
@@ -132,6 +134,7 @@ list( APPEND REFERENCED_CMAKE_FILES
Commands/EclipseCommands/EclipseWell/CMakeLists_files.cmake
Commands/ExportCommands/CMakeLists_files.cmake
Commands/FlowCommands/CMakeLists_files.cmake
Commands/GridCrossPlotCommands/CMakeLists_files.cmake
Commands/HoloLensCommands/CMakeLists_files.cmake
Commands/IntersectionBoxCommands/CMakeLists_files.cmake
Commands/IntersectionViewCommands/CMakeLists_files.cmake

View File

@@ -0,0 +1,19 @@
set (SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RicCreateGridCrossPlotFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicCreateGridCrossPlotCurveSetFeature.h
)
set (SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RicCreateGridCrossPlotFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicCreateGridCrossPlotCurveSetFeature.cpp)
list(APPEND CODE_HEADER_FILES
${SOURCE_GROUP_HEADER_FILES}
)
list(APPEND CODE_SOURCE_FILES
${SOURCE_GROUP_SOURCE_FILES}
)
source_group( "CommandFeature\\GridCrossPlot" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists_files.cmake )

View File

@@ -0,0 +1,64 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicCreateGridCrossPlotCurveSetFeature.h"
#include "RiaApplication.h"
#include "RimGridCrossPlot.h"
#include "RimGridCrossPlotCurveSet.h"
#include "RimProject.h"
#include "RiuPlotMainWindowTools.h"
#include "cafSelectionManager.h"
#include <QAction>
CAF_CMD_SOURCE_INIT(RicCreateGridCrossPlotCurveSetFeature, "RicCreateGridCrossPlotCurveSetFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicCreateGridCrossPlotCurveSetFeature::isCommandEnabled()
{
return caf::SelectionManager::instance()->selectedItemOfType<RimGridCrossPlot>() != nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateGridCrossPlotCurveSetFeature::onActionTriggered(bool isChecked)
{
RimGridCrossPlot* crossPlot = caf::SelectionManager::instance()->selectedItemOfType<RimGridCrossPlot>();
RimGridCrossPlotCurveSet* curveSet = crossPlot->createCurveSet();
curveSet->loadDataAndUpdate(true);
RiaApplication::instance()->project()->updateConnectedEditors();
RiaApplication::instance()->getOrCreateMainPlotWindow();
RiuPlotMainWindowTools::selectAsCurrentItem(curveSet);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateGridCrossPlotCurveSetFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setText("New Cross Plot Curve Set");
actionToSetup->setIcon(QIcon(":/WellLogCurve16x16.png"));
}

View File

@@ -0,0 +1,38 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
#include <vector>
//==================================================================================================
///
//==================================================================================================
class RicCreateGridCrossPlotCurveSetFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
bool isCommandEnabled() override;
void onActionTriggered(bool isChecked) override;
void setupActionLook(QAction* actionToSetup) override;
};

View File

@@ -0,0 +1,67 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicCreateGridCrossPlotFeature.h"
#include "RiaApplication.h"
#include "RimGridCrossPlot.h"
#include "RimGridCrossPlotCollection.h"
#include "RimMainPlotCollection.h"
#include "RimProject.h"
#include "RiuPlotMainWindowTools.h"
#include "cafSelectionManager.h"
#include <QAction>
CAF_CMD_SOURCE_INIT(RicCreateGridCrossPlotFeature, "RicCreateGridCrossPlotFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicCreateGridCrossPlotFeature::isCommandEnabled()
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateGridCrossPlotFeature::onActionTriggered(bool isChecked)
{
RimProject* project = RiaApplication::instance()->project();
RimGridCrossPlotCollection* collection = project->mainPlotCollection()->gridCrossPlotCollection();
RimGridCrossPlot* plot = collection->createGridCrossPlot();
plot->loadDataAndUpdate();
plot->updateConnectedEditors();
RiaApplication::instance()->project()->updateConnectedEditors();
RiaApplication::instance()->getOrCreateMainPlotWindow();
RiuPlotMainWindowTools::selectAsCurrentItem(plot);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateGridCrossPlotFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setText("New Grid Cross Plot");
actionToSetup->setIcon(QIcon(":/SummaryXPlotsLight16x16.png"));
}

View File

@@ -0,0 +1,37 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
#include <vector>
//==================================================================================================
///
//==================================================================================================
class RicCreateGridCrossPlotFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
bool isCommandEnabled() override;
void onActionTriggered(bool isChecked) override;
void setupActionLook(QAction* actionToSetup) override;
};

View File

@@ -34,6 +34,8 @@
#include "RimGeoMechPropertyFilter.h"
#include "RimGeoMechView.h"
#include "RimGridTimeHistoryCurve.h"
#include "RimGridCrossPlot.h"
#include "RimGridCrossPlotCurveSet.h"
#include "RimIdenticalGridCaseGroup.h"
#include "RimIntersection.h"
#include "RimIntersectionBox.h"
@@ -131,6 +133,8 @@ bool isDeletable(caf::PdmUiItem* uiItem)
if (dynamic_cast<RimTextAnnotation*>(uiItem)) return true;
if (dynamic_cast<RimReachCircleAnnotation*>(uiItem)) return true;
if (dynamic_cast<RimPolylinesAnnotation*>(uiItem)) return true;
if (dynamic_cast<RimGridCrossPlot*>(uiItem)) return true;
if (dynamic_cast<RimGridCrossPlotCurveSet*>(uiItem)) return true;
return false;
}

View File

@@ -0,0 +1,23 @@
set (SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimGridCrossPlot.h
${CMAKE_CURRENT_LIST_DIR}/RimGridCrossPlotCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimGridCrossPlotCurve.h
${CMAKE_CURRENT_LIST_DIR}/RimGridCrossPlotCurveSet.h
)
set (SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimGridCrossPlot.cpp
${CMAKE_CURRENT_LIST_DIR}/RimGridCrossPlotCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimGridCrossPlotCurve.cpp
${CMAKE_CURRENT_LIST_DIR}/RimGridCrossPlotCurveSet.cpp)
list(APPEND CODE_HEADER_FILES
${SOURCE_GROUP_HEADER_FILES}
)
list(APPEND CODE_SOURCE_FILES
${SOURCE_GROUP_SOURCE_FILES}
)
source_group( "ProjectDataModel\\GridCrossPlots" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists_files.cmake )

View File

@@ -0,0 +1,371 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimGridCrossPlot.h"
#include "RiuQwtPlotTools.h"
#include "RimGridCrossPlotCurveSet.h"
#include "cafPdmUiCheckBoxEditor.h"
#include "cvfAssert.h"
#include "qwt_legend.h"
#include "qwt_plot.h"
#include "qwt_plot_curve.h"
#include <QDebug>
CAF_PDM_SOURCE_INIT(RimGridCrossPlot, "RimGridCrossPlot");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlot::RimGridCrossPlot()
{
CAF_PDM_InitObject("Grid Cross Plot", ":/SummaryXPlotLight16x16.png", "", "");
CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Show Legend", "", "", "");
CAF_PDM_InitField(&m_legendFontSize, "LegendFontSize", 10, "Legend Font Size", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_nameConfig, "NameConfig", "Name Config", "", "", "");
m_nameConfig.uiCapability()->setUiTreeHidden(true);
m_nameConfig.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_crossPlotCurveSets, "CrossPlotCurve", "Cross Plot Data Set", "", "", "");
m_crossPlotCurveSets.uiCapability()->setUiHidden(true);
m_nameConfig = new RimGridCrossPlotNameConfig(this);
createCurveSet();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlotCurveSet* RimGridCrossPlot::createCurveSet()
{
RimGridCrossPlotCurveSet* curveSet = new RimGridCrossPlotCurveSet();
m_crossPlotCurveSets.push_back(curveSet);
return curveSet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimGridCrossPlot::indexOfCurveSet(const RimGridCrossPlotCurveSet* curveSet) const
{
for (size_t i = 0; i < m_crossPlotCurveSets.size(); ++i)
{
if (curveSet == m_crossPlotCurveSets[i])
{
return static_cast<int>(i);
}
}
return -1;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimGridCrossPlot::viewWidget()
{
return m_qwtPlot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QImage RimGridCrossPlot::snapshotWindowContent()
{
QImage image;
if (m_qwtPlot)
{
QPixmap pix = QPixmap::grabWidget(m_qwtPlot);
image = pix.toImage();
}
return image;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::zoomAll()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::calculateZoomRangeAndUpdateQwt()
{
// this->calculateXZoomRange();
m_qwtPlot->replot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::reattachCurvesToQwtAndReplot()
{
for (auto curveSet : m_crossPlotCurveSets)
{
curveSet->setParentQwtPlotNoReplot(m_qwtPlot);
}
m_qwtPlot->replot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGridCrossPlot::createAutoName() const
{
QStringList autoName;
if (!m_nameConfig->customName().isEmpty())
{
autoName += m_nameConfig->customName();
}
if (m_nameConfig->addDataSetNames())
{
QStringList dataSets;
for (auto curveSet : m_crossPlotCurveSets)
{
dataSets += curveSet->createAutoName();
}
if (!dataSets.isEmpty())
{
autoName += QString("(%1)").arg(dataSets.join(", "));
}
}
return autoName.join(" ");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimGridCrossPlot::userDescriptionField()
{
return m_nameConfig->nameField();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimGridCrossPlot::createViewWidget(QWidget* mainWindowParent)
{
if (!m_qwtPlot)
{
m_qwtPlot = new QwtPlot(QString("Grid Cross Plot"), mainWindowParent);
}
return m_qwtPlot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::deleteViewWidget()
{
if (m_qwtPlot)
{
m_qwtPlot->deleteLater();
m_qwtPlot = nullptr;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::onLoadDataAndUpdate()
{
updateMdiWindowVisibility();
CVF_ASSERT(m_qwtPlot);
for (auto curveSet : m_crossPlotCurveSets)
{
curveSet->loadDataAndUpdate(false);
curveSet->setParentQwtPlotNoReplot(m_qwtPlot);
}
performAutoNameUpdate();
m_qwtPlot->setAxisAutoScale(QwtPlot::xBottom);
m_qwtPlot->setAxisAutoScale(QwtPlot::yLeft);
m_qwtPlot->setAxisTitle(QwtPlot::xBottom, QwtText(xAxisParameterString()));
m_qwtPlot->setAxisTitle(QwtPlot::yLeft, QwtText(yAxisParameterString()));
RiuQwtPlotTools::setCommonPlotBehaviour(m_qwtPlot);
RiuQwtPlotTools::setDefaultAxes(m_qwtPlot);
if (m_showLegend())
{
// Will be released in plot destructor or when a new legend is set
QwtLegend* legend = new QwtLegend(m_qwtPlot);
auto font = legend->font();
font.setPixelSize(m_legendFontSize());
legend->setFont(font);
m_qwtPlot->insertLegend(legend, QwtPlot::BottomLegend);
}
else
{
m_qwtPlot->insertLegend(nullptr);
}
m_qwtPlot->replot();
m_qwtPlot->show();
this->updateAllRequiredEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
uiOrdering.add(&m_showLegend);
if (m_showLegend())
{
uiOrdering.add(&m_legendFontSize);
}
caf::PdmUiGroup* nameGroup = uiOrdering.addNewGroup("Name Configuration");
m_nameConfig->uiOrdering(uiConfigName, *nameGroup);
uiOrdering.skipRemainingFields(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue)
{
onLoadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimGridCrossPlot::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
if (fieldNeedingOptions == &m_legendFontSize)
{
std::vector<int> fontSizes;
fontSizes.push_back(8);
fontSizes.push_back(10);
fontSizes.push_back(12);
fontSizes.push_back(14);
fontSizes.push_back(16);
for (int value : fontSizes)
{
QString text = QString("%1").arg(value);
options.push_back(caf::PdmOptionItemInfo(text, value));
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::performAutoNameUpdate()
{
if (m_qwtPlot)
{
m_qwtPlot->setTitle(this->createAutoName());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGridCrossPlot::xAxisParameterString() const
{
QStringList xAxisParams;
for (auto curveSet : m_crossPlotCurveSets)
{
xAxisParams.push_back(curveSet->xAxisName());
}
xAxisParams.removeDuplicates();
if (xAxisParams.size() > 5)
{
return QString("%1 parameters").arg(xAxisParams.size());
}
return xAxisParams.join(", ");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGridCrossPlot::yAxisParameterString() const
{
QStringList yAxisParams;
for (auto curveSet : m_crossPlotCurveSets)
{
yAxisParams.push_back(curveSet->yAxisName());
}
yAxisParams.removeDuplicates();
if (yAxisParams.size() > 5)
{
return QString("%1 parameters").arg(yAxisParams.size());
}
return yAxisParams.join(", ");
}
//--------------------------------------------------------------------------------------------------
/// Name Configuration
///
//--------------------------------------------------------------------------------------------------
CAF_PDM_SOURCE_INIT(RimGridCrossPlotNameConfig, "RimGridCrossPlotNameConfig");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlotNameConfig::RimGridCrossPlotNameConfig(RimNameConfigHolderInterface* holder /*= nullptr*/)
: RimNameConfig(holder)
{
CAF_PDM_InitObject("Cross Plot Name Generator", "", "", "");
CAF_PDM_InitField(&addDataSetNames, "AddDataSetNames", true, "Add Data Set Names", "", "", "");
setCustomName("Cross Plot");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotNameConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
RimNameConfig::defineUiOrdering(uiConfigName, uiOrdering);
uiOrdering.add(&addDataSetNames);
}

View File

@@ -0,0 +1,89 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
#include "cafPdmObject.h"
#include "RimNameConfig.h"
#include "RimViewWindow.h"
#include <QPointer>
class RimGridCrossPlotCurveSet;
class QwtPlot;
class RimGridCrossPlotNameConfig : public RimNameConfig
{
CAF_PDM_HEADER_INIT;
public:
RimGridCrossPlotNameConfig(RimNameConfigHolderInterface* holder = nullptr);
public:
caf::PdmField<bool> addDataSetNames;
protected:
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
};
class RimGridCrossPlot : public RimViewWindow, public RimNameConfigHolderInterface
{
CAF_PDM_HEADER_INIT;
public:
RimGridCrossPlot();
~RimGridCrossPlot() = default;
RimGridCrossPlotCurveSet* createCurveSet();
int indexOfCurveSet(const RimGridCrossPlotCurveSet* curveSet) const;
QWidget* viewWidget() override;
QImage snapshotWindowContent() override;
void zoomAll() override;
void calculateZoomRangeAndUpdateQwt();
void reattachCurvesToQwtAndReplot();
QString createAutoName() const override;
caf::PdmFieldHandle* userDescriptionField() override;
protected:
QWidget* createViewWidget(QWidget* mainWindowParent) override;
void deleteViewWidget() override;
void onLoadDataAndUpdate() override;
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly) override;
void performAutoNameUpdate() override;
QString xAxisParameterString() const;
QString yAxisParameterString() const;
private:
caf::PdmField<bool> m_showLegend;
caf::PdmField<int> m_legendFontSize;
caf::PdmChildField<RimGridCrossPlotNameConfig*> m_nameConfig;
caf::PdmChildArrayField<RimGridCrossPlotCurveSet*> m_crossPlotCurveSets;
QPointer<QwtPlot> m_qwtPlot;
};

View File

@@ -0,0 +1,75 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimGridCrossPlotCollection.h"
#include "RimGridCrossPlot.h"
CAF_PDM_SOURCE_INIT(RimGridCrossPlotCollection, "RimGridCrossPlotCollection");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlotCollection::RimGridCrossPlotCollection()
{
CAF_PDM_InitObject("Grid Cross Plots", ":/SummaryXPlotsLight16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&m_gridCrossPlots, "GridCrossPlots", "Grid Cross Plots", "", "", "");
m_gridCrossPlots.uiCapability()->setUiHidden(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlotCollection::~RimGridCrossPlotCollection() {}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCollection::deleteAllChildObjects()
{
m_gridCrossPlots.deleteAllChildObjectsAsync();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimGridCrossPlot*> RimGridCrossPlotCollection::gridCrossPlots() const
{
return m_gridCrossPlots.childObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlot* RimGridCrossPlotCollection::createGridCrossPlot()
{
RimGridCrossPlot* plot = new RimGridCrossPlot();
plot->setAsPlotMdiWindow();
//plot->setDescription(QString("Summary Cross Plot %1").arg(m_gridCrossPlots.size()));
addGridCrossPlot(plot);
return plot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCollection::addGridCrossPlot(RimGridCrossPlot* plot)
{
m_gridCrossPlots().push_back(plot);
}

View File

@@ -0,0 +1,50 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafPdmChildArrayField.h"
#include "cafPdmObject.h"
class RimGridCrossPlot;
//==================================================================================================
///
///
//==================================================================================================
class RimGridCrossPlotCollection : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimGridCrossPlotCollection();
~RimGridCrossPlotCollection() override;
void deleteAllChildObjects();
std::vector<RimGridCrossPlot*> gridCrossPlots() const;
RimGridCrossPlot* createGridCrossPlot();
void addGridCrossPlot(RimGridCrossPlot* plot);
private:
caf::PdmChildArrayField<RimGridCrossPlot*> m_gridCrossPlots;
public:
};

View File

@@ -0,0 +1,135 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimGridCrossPlotCurve.h"
#include "RiaColorTables.h"
#include "RigCaseCellResultCalculator.h"
#include "RimCase.h"
#include "RimEclipseCase.h"
#include "RimEclipseResultDefinition.h"
#include "RimGridCrossPlot.h"
#include "RimTools.h"
#include "cafPdmUiComboBoxEditor.h"
#include <QDebug>
#include <QPointF>
#include <QVector>
#include "qwt_plot.h"
#include "qwt_plot_curve.h"
#include <random>
CAF_PDM_SOURCE_INIT(RimGridCrossPlotCurve, "GridCrossPlotCurve");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurve::determineColorAndSymbol(int curveSetIndex, int categoryIndex, bool contrastColors)
{
const caf::ColorTable& colors = RiaColorTables::contrastCategoryPaletteColors();
int colorIndex = categoryIndex + curveSetIndex; // Offset cycle for each curve set
setColor(colors.cycledColor3f(colorIndex));
int numColors = (int) colors.size();
// Retain same symbol until we've gone full cycle in colors
int symbolIndex = categoryIndex / numColors;
RiuQwtSymbol::PointSymbolEnum symbol = RiuQwtSymbol::cycledSymbolStyle(curveSetIndex, symbolIndex);
setSymbol(symbol);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlotCurve::RimGridCrossPlotCurve()
{
CAF_PDM_InitObject("Cross Plot Points", ":/WellLogCurve16x16.png", "", "");
setLineStyle(RiuQwtPlotCurve::STYLE_NONE);
setSymbolSize(6);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurve::setSamples(const QVector<QPointF>& samples)
{
m_qwtPlotCurve->setSamples(samples);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurve::updateZoomInParentPlot()
{
RimGridCrossPlot* plot;
this->firstAncestorOrThisOfTypeAsserted(plot);
plot->calculateZoomRangeAndUpdateQwt();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurve::updateLegendsInPlot()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGridCrossPlotCurve::createCurveAutoName()
{
return m_customCurveName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurve::onLoadDataAndUpdate(bool updateParentPlot)
{
if (updateParentPlot)
{
RimGridCrossPlot* crossPlot;
firstAncestorOrThisOfTypeAsserted(crossPlot);
crossPlot->reattachCurvesToQwtAndReplot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurve::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup("Appearance");
RimPlotCurve::appearanceUiOrdering(*appearanceGroup);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimGridCrossPlotCurve::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
return options;
}

View File

@@ -0,0 +1,54 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimPlotCurve.h"
#include "cafPdmChildField.h"
#include "cafPdmPtrField.h"
#include <QPointF>
#include <QVector>
class RimCase;
class RimEclipseResultDefinition;
class QwtPlotCurve;
//==================================================================================================
///
///
//==================================================================================================
class RimGridCrossPlotCurve : public RimPlotCurve
{
CAF_PDM_HEADER_INIT;
public:
RimGridCrossPlotCurve();
~RimGridCrossPlotCurve() override = default;
void determineColorAndSymbol(int curveSetIndex, int categoryIndex, bool contrastColors = false);
void setSamples(const QVector<QPointF>& samples);
protected:
void updateZoomInParentPlot() override;
void updateLegendsInPlot() override;
QString createCurveAutoName() override;
void onLoadDataAndUpdate(bool updateParentPlot) override;
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;
};

View File

@@ -0,0 +1,401 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimGridCrossPlotCurveSet.h"
#include "RigActiveCellInfo.h"
#include "RigActiveCellsResultAccessor.h"
#include "RigCaseCellResultCalculator.h"
#include "RigMainGrid.h"
#include "RimCase.h"
#include "RimEclipseCase.h"
#include "RimEclipseResultDefinition.h"
#include "RimGridCrossPlot.h"
#include "RimGridCrossPlotCurve.h"
#include "RimTools.h"
#include "cafPdmUiComboBoxEditor.h"
CAF_PDM_SOURCE_INIT(RimGridCrossPlotCurveSet, "GridCrossPlotCurveSet");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlotCurveSet::RimGridCrossPlotCurveSet()
{
CAF_PDM_InitObject("Cross Plot Data Set", ":/WellLogCurve16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&m_case, "Case", "Case", "", "", "");
m_case.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitField(&m_timeStep, "TimeStep", -1, "Time Step", "", "", "");
m_timeStep.uiCapability()->setUiEditorTypeName(caf::PdmUiComboBoxEditor::uiEditorTypeName());
CAF_PDM_InitFieldNoDefault(&m_xAxisProperty, "XAxisProperty", "X-Axis Property", "", "", "");
m_xAxisProperty = new RimEclipseResultDefinition;
m_xAxisProperty.uiCapability()->setUiHidden(true);
m_xAxisProperty.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_yAxisProperty, "YAxisProperty", "Y-Axis Property", "", "", "");
m_yAxisProperty = new RimEclipseResultDefinition;
m_yAxisProperty.uiCapability()->setUiHidden(true);
m_yAxisProperty.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_nameConfig, "NameConfig", "Name", "", "", "");
m_nameConfig = new RimGridCrossPlotCurveSetNameConfig(this);
m_nameConfig.uiCapability()->setUiTreeHidden(true);
m_nameConfig.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_crossPlotCurves, "CrossPlotCurves", "Curves", "", "", "");
m_crossPlotCurves.uiCapability()->setUiTreeHidden(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurveSet::loadDataAndUpdate(bool updateParentPlot)
{
onLoadDataAndUpdate(updateParentPlot);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurveSet::setParentQwtPlotNoReplot(QwtPlot* parent)
{
for (auto& curve : m_crossPlotCurves())
{
curve->setParentQwtPlotNoReplot(m_isChecked() ? parent : nullptr);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGridCrossPlotCurveSet::xAxisName() const
{
return m_xAxisProperty->resultVariableUiShortName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGridCrossPlotCurveSet::yAxisName() const
{
return m_yAxisProperty->resultVariableUiShortName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimGridCrossPlotCurveSet::indexInPlot() const
{
RimGridCrossPlot* parent;
this->firstAncestorOrThisOfTypeAsserted(parent);
return parent->indexOfCurveSet(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGridCrossPlotCurveSet::createAutoName() const
{
if (m_case() == nullptr)
{
return "Undefined";
}
QStringList nameTags;
if (!m_nameConfig->customName().isEmpty())
{
nameTags += m_nameConfig->customName();
}
if (m_nameConfig->addCaseName())
{
nameTags += m_case->caseUserDescription();
}
if (m_nameConfig->addAxisVariables())
{
nameTags += QString("%1 x %2").arg(xAxisName(), yAxisName());
}
if (m_nameConfig->addTimestep())
{
if (m_timeStep() == -1)
{
nameTags += "All Time Steps";
}
else
{
QStringList timeStepNames = m_case->timeStepStrings();
nameTags += timeStepNames[m_timeStep()];
}
}
return nameTags.join(", ");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurveSet::initAfterRead()
{
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>(m_case());
if (eclipseCase)
{
m_xAxisProperty->setEclipseCase(eclipseCase);
m_yAxisProperty->setEclipseCase(eclipseCase);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurveSet::onLoadDataAndUpdate(bool updateParentPlot)
{
performAutoNameUpdate();
m_crossPlotCurves.deleteAllChildObjects();
std::map<int, QVector<QPointF>> samples;
if (m_case())
{
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>(m_case.value());
if (eclipseCase)
{
RigCaseCellResultsData* resultData = eclipseCase->results(RiaDefines::MATRIX_MODEL);
RigEclipseResultAddress xAddress(m_xAxisProperty->resultType(), m_xAxisProperty->resultVariable());
RigEclipseResultAddress yAddress(m_yAxisProperty->resultType(), m_yAxisProperty->resultVariable());
if (xAddress.isValid() && yAddress.isValid())
{
RigActiveCellInfo* activeCellInfo = resultData->activeCellInfo();
const RigMainGrid* mainGrid = eclipseCase->mainGrid();
resultData->ensureKnownResultLoaded(xAddress);
resultData->ensureKnownResultLoaded(yAddress);
const std::vector<std::vector<double>>& xValuesForAllSteps = resultData->cellScalarResults(xAddress);
const std::vector<std::vector<double>>& yValuesForAllSteps = resultData->cellScalarResults(yAddress);
std::set<int> timeStepsToInclude;
if (m_timeStep() == -1)
{
size_t nStepsInData = std::max(xValuesForAllSteps.size(), yValuesForAllSteps.size());
CVF_ASSERT(xValuesForAllSteps.size() == 1u || xValuesForAllSteps.size() == nStepsInData);
CVF_ASSERT(yValuesForAllSteps.size() == 1u || yValuesForAllSteps.size() == nStepsInData);
for (size_t i = 0; i < nStepsInData; ++i)
{
timeStepsToInclude.insert((int) i);
}
}
else
{
timeStepsToInclude.insert(static_cast<size_t>(m_timeStep()));
}
for (int timeStep : timeStepsToInclude)
{
int xIndex = timeStep >= (int) xValuesForAllSteps.size() ? 0 : timeStep;
int yIndex = timeStep >= (int) yValuesForAllSteps.size() ? 0 : timeStep;
RigActiveCellsResultAccessor xAccessor(mainGrid, &xValuesForAllSteps[xIndex], activeCellInfo);
RigActiveCellsResultAccessor yAccessor(mainGrid, &yValuesForAllSteps[yIndex], activeCellInfo);
for (size_t j = 0; j < activeCellInfo->reservoirCellCount(); ++j)
{
double xValue = xAccessor.cellScalarGlobIdx(j);
double yValue = yAccessor.cellScalarGlobIdx(j);
if (xValue != HUGE_VAL && yValue != HUGE_VAL)
{
samples[timeStep].push_back(QPointF(xValue, yValue));
}
}
}
}
}
}
QStringList timeStepNames;
if (m_case)
{
timeStepNames = m_case->timeStepStrings();
}
int curveSetIndex = indexInPlot();
for (const auto& sampleCategory : samples)
{
RimGridCrossPlotCurve* curve = new RimGridCrossPlotCurve();
QString timeStepName = QString::number(sampleCategory.first);
if (sampleCategory.first < timeStepNames.size())
{
timeStepName = timeStepNames[sampleCategory.first];
}
bool staticResultsOnly = staticResultsOnly = m_xAxisProperty->hasStaticResult() && m_yAxisProperty->hasStaticResult();
if (staticResultsOnly)
{
curve->setCustomName(createAutoName());
}
else
{
curve->setCustomName(QString("%1 : %2").arg(createAutoName()).arg(timeStepName));
}
curve->determineColorAndSymbol(curveSetIndex, sampleCategory.first);
curve->setSamples(sampleCategory.second);
curve->updateCurveAppearance();
curve->updateCurveNameAndUpdatePlotLegendAndTitle();
m_crossPlotCurves.push_back(curve);
}
if (updateParentPlot)
{
triggerReplotAndTreeRebuild();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurveSet::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
uiOrdering.add(&m_case);
if (m_case)
{
uiOrdering.add(&m_timeStep);
caf::PdmUiGroup* xAxisGroup = uiOrdering.addNewGroup("X-Axis Property");
m_xAxisProperty->uiOrdering(uiConfigName, *xAxisGroup);
caf::PdmUiGroup* yAxisGroup = uiOrdering.addNewGroup("Y-Axis Property");
m_yAxisProperty->uiOrdering(uiConfigName, *yAxisGroup);
}
caf::PdmUiGroup* nameGroup = uiOrdering.addNewGroup("Name Configuration");
m_nameConfig->uiOrdering(uiConfigName, *nameGroup);
uiOrdering.skipRemainingFields(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurveSet::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue)
{
if (changedField == &m_case)
{
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>(m_case.value());
if (eclipseCase)
{
m_xAxisProperty->setEclipseCase(eclipseCase);
m_yAxisProperty->setEclipseCase(eclipseCase);
m_xAxisProperty->updateConnectedEditors();
m_yAxisProperty->updateConnectedEditors();
triggerReplotAndTreeRebuild();
}
}
else if (changedField == &m_timeStep)
{
triggerReplotAndTreeRebuild();
}
else if (changedField == &m_isChecked)
{
triggerReplotAndTreeRebuild();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimGridCrossPlotCurveSet::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
if (fieldNeedingOptions == &m_case)
{
RimTools::caseOptionItems(&options);
options.push_front(caf::PdmOptionItemInfo("None", nullptr));
}
else if (fieldNeedingOptions == &m_timeStep)
{
QStringList timeStepNames;
if (m_case)
{
timeStepNames = m_case->timeStepStrings();
}
options.push_back(caf::PdmOptionItemInfo("All Time Steps", -1));
for (int i = 0; i < timeStepNames.size(); i++)
{
options.push_back(caf::PdmOptionItemInfo(timeStepNames[i], i));
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurveSet::triggerReplotAndTreeRebuild()
{
RimGridCrossPlot* parent;
this->firstAncestorOrThisOfTypeAsserted(parent);
parent->loadDataAndUpdate();
parent->updateAllRequiredEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurveSet::performAutoNameUpdate()
{
this->setName(createAutoName());
}
CAF_PDM_SOURCE_INIT(RimGridCrossPlotCurveSetNameConfig, "RimGridCrossPlotCurveSetNameConfig");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlotCurveSetNameConfig::RimGridCrossPlotCurveSetNameConfig(RimNameConfigHolderInterface* parent)
: RimNameConfig(parent)
{
CAF_PDM_InitObject("Cross Plot Curve Set NameGenerator", "", "", "");
CAF_PDM_InitField(&addCaseName, "AddCaseName", false, "Add Case Name", "", "", "");
CAF_PDM_InitField(&addAxisVariables, "AddAxisVariables", true, "Add Axis Variables", "", "", "");
CAF_PDM_InitField(&addTimestep, "AddTimeStep", false, "Add Time Step", "", "", "");
setCustomName("");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotCurveSetNameConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
uiOrdering.add(&addCaseName);
uiOrdering.add(&addAxisVariables);
uiOrdering.add(&addTimestep);
}

View File

@@ -0,0 +1,90 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimCheckableNamedObject.h"
#include "RimNameConfig.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPtrField.h"
class RimCase;
class RimGridCrossPlotCurve;
class RimEclipseResultDefinition;
class QwtPlot;
class QwtPlotCurve;
class RimGridCrossPlotCurveSetNameConfig : public RimNameConfig
{
CAF_PDM_HEADER_INIT;
public:
RimGridCrossPlotCurveSetNameConfig(RimNameConfigHolderInterface* parent = nullptr);
caf::PdmField<bool> addCaseName;
caf::PdmField<bool> addAxisVariables;
caf::PdmField<bool> addTimestep;
protected:
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
};
//==================================================================================================
///
///
//==================================================================================================
class RimGridCrossPlotCurveSet : public RimCheckableNamedObject, public RimNameConfigHolderInterface
{
CAF_PDM_HEADER_INIT;
public:
RimGridCrossPlotCurveSet();
~RimGridCrossPlotCurveSet() = default;
void loadDataAndUpdate(bool updateParentPlot);
void setParentQwtPlotNoReplot(QwtPlot* parent);
QString xAxisName() const;
QString yAxisName() const;
int indexInPlot() const;
QString createAutoName() const override;
protected:
void initAfterRead() override;
void onLoadDataAndUpdate(bool updateParentPlot);
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly) override;
void triggerReplotAndTreeRebuild();
void performAutoNameUpdate() override;
private:
caf::PdmPtrField<RimCase*> m_case;
caf::PdmField<int> m_timeStep;
caf::PdmChildField<RimEclipseResultDefinition*> m_xAxisProperty;
caf::PdmChildField<RimEclipseResultDefinition*> m_yAxisProperty;
caf::PdmChildField<RimGridCrossPlotCurveSetNameConfig*> m_nameConfig;
caf::PdmChildArrayField<RimGridCrossPlotCurve*> m_crossPlotCurves;
};

View File

@@ -900,7 +900,7 @@ void Rim3dView::applyBackgroundColor()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rim3dView::performHolderUpdate()
void Rim3dView::performAutoNameUpdate()
{
updateMdiWindowTitle();
}

View File

@@ -180,7 +180,7 @@ protected:
void applyBackgroundColor();
// Implementation of RimNameConfigHolderInterface
void performHolderUpdate() override;
void performAutoNameUpdate() override;
// Abstract methods to implement in subclasses

View File

@@ -58,6 +58,8 @@
#include "RimGeoMechPropertyFilterCollection.h"
#include "RimGeoMechView.h"
#include "RimGridCollection.h"
#include "RimGridCrossPlot.h"
#include "RimGridCrossPlotCollection.h"
#include "RimIdenticalGridCaseGroup.h"
#include "RimIntersection.h"
#include "RimIntersectionBox.h"
@@ -461,6 +463,14 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
{
menuBuilder << "RicPasteWellLogCurveFeature";
}
else if (dynamic_cast<RimGridCrossPlotCollection*>(uiItem))
{
menuBuilder << "RicCreateGridCrossPlotFeature";
}
else if (dynamic_cast<RimGridCrossPlot*>(uiItem))
{
menuBuilder << "RicCreateGridCrossPlotCurveSetFeature";
}
else if (dynamic_cast<RimSummaryPlot*>(uiItem)) // This is also the definition for RimSummaryCrossPlot
{
RimSummaryCrossPlot* summaryCrossPlot = dynamic_cast<RimSummaryCrossPlot*>(uiItem);

View File

@@ -39,6 +39,8 @@
#include "RimEclipseResultCase.h"
#include "RimEclipseView.h"
#include "RimFlowDiagSolution.h"
#include "RimGridCrossPlot.h"
#include "RimGridCrossPlotCurveSet.h"
#include "RimGridTimeHistoryCurve.h"
#include "RimIntersectionCollection.h"
#include "RimPlotCurve.h"
@@ -365,6 +367,13 @@ void RimEclipseResultDefinition::updateAnyFieldHasChanged()
cellColors->updateConnectedEditors();
}
RimGridCrossPlotCurveSet* crossPlotCurveSet = nullptr;
this->firstAncestorOrThisOfType(crossPlotCurveSet);
if (crossPlotCurveSet)
{
crossPlotCurveSet->updateConnectedEditors();
}
RimPlotCurve* curve = nullptr;
this->firstAncestorOrThisOfType(curve);
if (curve)
@@ -473,6 +482,13 @@ void RimEclipseResultDefinition::loadDataAndUpdate()
}
}
RimGridCrossPlot* crossPlot = nullptr;
this->firstAncestorOrThisOfType(crossPlot);
if (crossPlot)
{
crossPlot->loadDataAndUpdate();
}
RimPlotCurve* curve = nullptr;
this->firstAncestorOrThisOfType(curve);
if (curve)

View File

@@ -19,6 +19,8 @@
#include "RimMainPlotCollection.h"
#include "RimGridCrossPlot.h"
#include "RimGridCrossPlotCollection.h"
#include "RimFlowCharacteristicsPlot.h"
#include "RimFlowPlotCollection.h"
#include "RimPltPlotCollection.h"
@@ -65,13 +67,16 @@ RimMainPlotCollection::RimMainPlotCollection()
CAF_PDM_InitFieldNoDefault(&m_flowPlotCollection, "FlowPlotCollection", "Flow Diagnostics Plots", "", "", "");
m_flowPlotCollection.uiCapability()->setUiHidden(true);
CAF_PDM_InitFieldNoDefault(&m_gridCrossPlotCollection, "Rim3dCrossPlotCollection", "3d Cross Plots", "", "", "");
m_gridCrossPlotCollection.uiCapability()->setUiHidden(true);
m_wellLogPlotCollection = new RimWellLogPlotCollection();
m_rftPlotCollection = new RimRftPlotCollection();
m_pltPlotCollection = new RimPltPlotCollection();
m_summaryPlotCollection = new RimSummaryPlotCollection();
m_summaryCrossPlotCollection = new RimSummaryCrossPlotCollection();
m_flowPlotCollection = new RimFlowPlotCollection();
m_gridCrossPlotCollection = new RimGridCrossPlotCollection;
}
//--------------------------------------------------------------------------------------------------
@@ -79,13 +84,6 @@ RimMainPlotCollection::RimMainPlotCollection()
//--------------------------------------------------------------------------------------------------
RimMainPlotCollection::~RimMainPlotCollection()
{
if (m_wellLogPlotCollection()) delete m_wellLogPlotCollection();
if (m_rftPlotCollection()) delete m_rftPlotCollection();
if (m_pltPlotCollection()) delete m_pltPlotCollection();
if (m_summaryPlotCollection()) delete m_summaryPlotCollection();
if (m_summaryCrossPlotCollection()) delete m_summaryCrossPlotCollection();
if (m_flowPlotCollection()) delete m_flowPlotCollection();
}
//--------------------------------------------------------------------------------------------------
@@ -152,6 +150,14 @@ RimFlowPlotCollection* RimMainPlotCollection::flowPlotCollection()
return m_flowPlotCollection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlotCollection* RimMainPlotCollection::gridCrossPlotCollection()
{
return m_gridCrossPlotCollection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -162,7 +168,7 @@ void RimMainPlotCollection::deleteAllContainedObjects()
m_pltPlotCollection()->deleteAllPlots();
m_summaryPlotCollection()->summaryPlots.deleteAllChildObjects();
m_summaryCrossPlotCollection()->deleteAllChildObjects();
m_gridCrossPlotCollection->deleteAllChildObjects();
m_flowPlotCollection()->closeDefaultPlotWindowAndDeletePlots();
}
@@ -208,6 +214,14 @@ void RimMainPlotCollection::updatePlotsWithFormations()
{
m_flowPlotCollection->loadDataAndUpdate();
}
if (m_gridCrossPlotCollection)
{
for (RimGridCrossPlot* crossPlot : m_gridCrossPlotCollection->gridCrossPlots())
{
crossPlot->loadDataAndUpdate();
}
}
}
//--------------------------------------------------------------------------------------------------

View File

@@ -30,6 +30,7 @@
class RimWellLogPlotCollection;
class RimRftPlotCollection;
class RimPltPlotCollection;
class RimGridCrossPlotCollection;
class RimSummaryPlotCollection;
class RimSummaryCrossPlotCollection;
class RimSummaryPlot;
@@ -55,6 +56,7 @@ public:
RimSummaryPlotCollection* summaryPlotCollection();
RimSummaryCrossPlotCollection* summaryCrossPlotCollection();
RimFlowPlotCollection* flowPlotCollection();
RimGridCrossPlotCollection* gridCrossPlotCollection();
void deleteAllContainedObjects();
void updateCurrentTimeStepInPlots();
@@ -74,6 +76,7 @@ private:
caf::PdmChildField<RimSummaryPlotCollection*> m_summaryPlotCollection;
caf::PdmChildField<RimSummaryCrossPlotCollection*> m_summaryCrossPlotCollection;
caf::PdmChildField<RimFlowPlotCollection*> m_flowPlotCollection;
caf::PdmChildField<RimGridCrossPlotCollection*> m_gridCrossPlotCollection;
caf::PdmField<bool> m_show;
};

View File

@@ -30,10 +30,10 @@ class RimNameConfigHolderInterface
{
public:
virtual QString createAutoName() const = 0;
void updateHolder() { performHolderUpdate(); }
void updateHolder() { performAutoNameUpdate(); }
protected:
virtual void performHolderUpdate() {}
virtual void performAutoNameUpdate() {}
};
//==================================================================================================
@@ -56,7 +56,7 @@ public:
void uiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering);
protected:
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
QString autoName() const;
virtual void updateAllSettings();

View File

@@ -287,6 +287,10 @@ void RimPlotCurve::setParentQwtPlotNoReplot(QwtPlot* plot)
{
m_qwtPlotCurve->attach(m_parentQwtPlot);
}
else
{
m_qwtPlotCurve->detach();
}
}
//--------------------------------------------------------------------------------------------------
@@ -418,6 +422,14 @@ void RimPlotCurve::updateLegendsInPlot()
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPlotCurve::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
throw std::logic_error("The method or operation is not implemented.");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -93,12 +93,14 @@ protected:
virtual QString createCurveAutoName() = 0;
virtual void updateZoomInParentPlot() = 0;
virtual void onLoadDataAndUpdate(bool updateParentPlot) = 0;
void initAfterRead() override;
void initAfterRead() override;
void updateCurvePresentation(bool updatePlotLegendAndTitle);
void updateOptionSensitivity();
void updatePlotTitle();
virtual void updateLegendsInPlot();
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
protected:
// Overridden PDM methods

View File

@@ -47,6 +47,7 @@
#include "RimFormationNamesCollection.h"
#include "RimFractureTemplate.h"
#include "RimFractureTemplateCollection.h"
#include "RimGridCrossPlotCollection.h"
#include "RimValveTemplate.h"
#include "RimValveTemplateCollection.h"
#include "RimGeoMechCase.h"
@@ -1240,6 +1241,11 @@ void RimProject::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QS
{
itemCollection->add(mainPlotCollection->flowPlotCollection());
}
if (mainPlotCollection->gridCrossPlotCollection())
{
itemCollection->add(mainPlotCollection->gridCrossPlotCollection());
}
}
}
else

View File

@@ -32,6 +32,8 @@
#include "RimEclipseContourMapViewCollection.h"
#include "RimEclipseView.h"
#include "RimFlowPlotCollection.h"
#include "RimGridCrossPlot.h"
#include "RimGridCrossPlotCollection.h"
#include "RimMainPlotCollection.h"
#include "RimProject.h"
#include "RimSummaryCaseMainCollection.h"
@@ -160,6 +162,15 @@ void RimReloadCaseTools::updateAllPlots()
}
}
RimGridCrossPlotCollection* gridCrossPlotCollection = project->mainPlotCollection()->gridCrossPlotCollection();
if (gridCrossPlotCollection)
{
for (RimGridCrossPlot* crossPlot : gridCrossPlotCollection->gridCrossPlots())
{
crossPlot->loadDataAndUpdate();
}
}
RimFlowPlotCollection* flowPlotCollection = project->mainPlotCollection()->flowPlotCollection();
if (flowPlotCollection)
{

View File

@@ -698,7 +698,7 @@ QString RimWellLogPlot::createAutoName() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogPlot::performHolderUpdate()
void RimWellLogPlot::performAutoNameUpdate()
{
this->m_commonDataSource->updateDefaultOptions();
this->updatePlotTitle();

View File

@@ -127,7 +127,7 @@ public:
void handleKeyPressEvent(QKeyEvent* keyEvent);
RimWellLogCurveCommonDataSource* commonDataSource() const;
protected:
void performHolderUpdate() override;
void performAutoNameUpdate() override;
// Overridden PDM methods
void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;

View File

@@ -0,0 +1,41 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RigEclipseCrossPlotDataExtractor.h"
#include "RigEclipseCaseData.h"
#include "RigCaseCellResultsData.h"
#include "RigEclipseResultAddress.h"
#include "RigActiveCellInfo.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::pair<double, double>> RigEclipseCrossPlotDataExtractor::extract(RigEclipseCaseData* caseData,
int timeStep,
const RigEclipseResultAddress& xAxisProperty,
const RigEclipseResultAddress& yAxisProperty)
{
RigCaseCellResultsData* resultData = caseData->results(RiaDefines::MATRIX_MODEL);
std::vector<double> xValues = resultData->cellScalarResults(xAxisProperty)[timeStep];
std::vector<double> yValues = resultData->cellScalarResults(xAxisProperty)[timeStep];
size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex);
size_t resultValueIndex = m_activeCellInfo->cellResultIndex(reservoirCellIndex);
if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL;
if (resultValueIndex < m_reservoirResultValues->size()) return m_reservoirResultValues->at(resultValueIndex);
}

View File

@@ -0,0 +1,33 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <utility>
#include <vector>
class RigEclipseCaseData;
class RigEclipseResultAddress;
class RigEclipseCrossPlotDataExtractor
{
static std::vector<std::pair<double, double>> extract(RigEclipseCaseData* caseData,
int timeStep,
const RigEclipseResultAddress& xAxisProperty,
const RigEclipseResultAddress& yAxisProperty);
};

View File

@@ -75,6 +75,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuPlotMainWindowTools.h
${CMAKE_CURRENT_LIST_DIR}/Riu3DMainWindowTools.h
${CMAKE_CURRENT_LIST_DIR}/RiuDockWidgetTools.h
${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotItemGroup.h
${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotTools.h
${CMAKE_CURRENT_LIST_DIR}/RiuWellPathComponentPlotItem.h
${CMAKE_CURRENT_LIST_DIR}/RiuMeasurementViewEventFilter.h
)
@@ -152,6 +153,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuPlotMainWindowTools.cpp
${CMAKE_CURRENT_LIST_DIR}/Riu3DMainWindowTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuDockWidgetTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotItemGroup.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuWellPathComponentPlotItem.cpp
)

View File

@@ -325,7 +325,7 @@ void RiuQwtPlotCurve::setAppearance(LineStyleEnum lineStyle,
const QColor& curveColor)
{
QwtPlotCurve::CurveStyle curveStyle = QwtPlotCurve::NoCurve;
Qt::PenStyle penStyle = Qt::SolidLine;
Qt::PenStyle penStyle = Qt::NoPen;
if (lineStyle != STYLE_NONE)
{

View File

@@ -0,0 +1,102 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiuQwtPlotTools.h"
#include "qwt_plot.h"
#include "qwt_plot_grid.h"
#include "qwt_plot_layout.h"
#include <vector>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotTools::setCommonPlotBehaviour(QwtPlot* plot)
{
// Plot background and frame look
QPalette newPalette(plot->palette());
newPalette.setColor(QPalette::Background, Qt::white);
plot->setPalette(newPalette);
plot->setAutoFillBackground(true);
plot->setCanvasBackground(Qt::white);
QFrame* canvasFrame = dynamic_cast<QFrame*>(plot->canvas());
if (canvasFrame)
{
canvasFrame->setFrameShape(QFrame::NoFrame);
}
// Grid
QwtPlotGrid* grid = new QwtPlotGrid;
grid->attach(plot);
QPen gridPen(Qt::SolidLine);
gridPen.setColor(Qt::lightGray);
grid->setPen(gridPen);
// Axis number font
QFont axisFont = plot->axisFont(QwtPlot::xBottom);
axisFont.setPixelSize(11);
plot->setAxisFont(QwtPlot::xBottom, axisFont);
plot->setAxisFont(QwtPlot::xTop, axisFont);
plot->setAxisFont(QwtPlot::yLeft, axisFont);
plot->setAxisFont(QwtPlot::yRight, axisFont);
// Axis title font
std::vector<QwtPlot::Axis> axes = { QwtPlot::xBottom, QwtPlot::xTop, QwtPlot::yLeft, QwtPlot::yRight };
for (QwtPlot::Axis axis : axes)
{
QwtText axisTitle = plot->axisTitle(axis);
QFont axisTitleFont = axisTitle.font();
axisTitleFont.setPixelSize(11);
axisTitleFont.setBold(false);
axisTitle.setFont(axisTitleFont);
axisTitle.setRenderFlags(Qt::AlignRight);
plot->setAxisTitle(axis, axisTitle);
}
// Set a focus policy to allow it taking key press events.
// This is not strictly necessary since this widget inherit QwtPlot
// which already has a focus policy.
// However, for completeness we still do it here.
plot->setFocusPolicy(Qt::WheelFocus);
// Enable mousetracking and event filter
plot->canvas()->setMouseTracking(true);
plot->canvas()->installEventFilter(plot);
plot->plotLayout()->setAlignCanvasToScales(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotTools::setDefaultAxes(QwtPlot* plot)
{
plot->enableAxis(QwtPlot::xBottom, true);
plot->enableAxis(QwtPlot::yLeft, true);
plot->enableAxis(QwtPlot::xTop, false);
plot->enableAxis(QwtPlot::yRight, false);
plot->setAxisMaxMinor(QwtPlot::xBottom, 2);
plot->setAxisMaxMinor(QwtPlot::yLeft, 3);
}

View File

@@ -0,0 +1,28 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
class QwtPlot;
class RiuQwtPlotTools
{
public:
static void setCommonPlotBehaviour(QwtPlot* plot);
static void setDefaultAxes(QwtPlot* plot);
};

View File

@@ -102,6 +102,18 @@ RiuQwtSymbol::RiuQwtSymbol(PointSymbolEnum riuStyle, const QString& label, Label
setPinPoint(QPointF(0, 10));
}
break;
case SYMBOL_UP_TRIANGLE:
style = QwtSymbol::UTriangle;
break;
case SYMBOL_STAR1:
style = QwtSymbol::Star1;
break;
case SYMBOL_STAR2:
style = QwtSymbol::Star2;
break;
case SYMBOL_HEXAGON:
style = QwtSymbol::Hexagon;
break;
default:
break;
}
@@ -144,6 +156,27 @@ void RiuQwtSymbol::setLabelPosition(LabelPosition labelPosition)
m_labelPosition = labelPosition;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuQwtSymbol::PointSymbolEnum RiuQwtSymbol::cycledSymbolStyle(int indexLevel1, int indexLevel2)
{
std::vector<std::vector<PointSymbolEnum>> categorisedStyles =
{
{SYMBOL_ELLIPSE, SYMBOL_RECT, SYMBOL_DIAMOND},
{SYMBOL_TRIANGLE, SYMBOL_DOWN_TRIANGLE, SYMBOL_UP_TRIANGLE},
{SYMBOL_LEFT_TRIANGLE, SYMBOL_RIGHT_TRIANGLE},
{SYMBOL_LEFT_ANGLED_TRIANGLE, SYMBOL_RIGHT_ANGLED_TRIANGLE},
{SYMBOL_CROSS, SYMBOL_XCROSS},
{SYMBOL_STAR1, SYMBOL_STAR2},
};
int level1Category = indexLevel1 % int(categorisedStyles.size());
int level2Category = indexLevel2 % int(categorisedStyles[level1Category].size());
return categorisedStyles[level1Category][level2Category];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -44,22 +44,28 @@ public:
SYMBOL_RECT,
SYMBOL_DIAMOND,
SYMBOL_TRIANGLE,
SYMBOL_DOWN_TRIANGLE,
SYMBOL_CROSS,
SYMBOL_XCROSS,
SYMBOL_DOWN_TRIANGLE,
SYMBOL_LEFT_TRIANGLE,
SYMBOL_RIGHT_TRIANGLE,
SYMBOL_LEFT_ANGLED_TRIANGLE,
SYMBOL_RIGHT_ANGLED_TRIANGLE
SYMBOL_RIGHT_ANGLED_TRIANGLE,
SYMBOL_UP_TRIANGLE,
SYMBOL_STAR1,
SYMBOL_STAR2,
SYMBOL_HEXAGON
};
RiuQwtSymbol(PointSymbolEnum riuStyle, const QString& label, LabelPosition labelPosition = LabelAboveSymbol);
void renderSymbols(QPainter *painter, const QPointF *points, int numPoints) const override;
void renderSymbolLabel(QPainter *painter, const QPointF& position) const;
QString label() const { return m_label; }
void setLabelPosition(LabelPosition labelPosition);
static PointSymbolEnum cycledSymbolStyle(int indexLevel1, int indexLevel2);
private:
QRect labelBoundingRect(const QPainter* painter, const QRect& symbolRect) const;

View File

@@ -28,6 +28,7 @@
#include "RiuPlotMainWindowTools.h"
#include "RiuQwtCurvePointTracker.h"
#include "RiuQwtPlotTools.h"
#include "RiuQwtPlotWheelZoomer.h"
#include "RiuQwtPlotZoomer.h"
#include "RiuQwtScalePicker.h"
@@ -305,17 +306,10 @@ QSize RiuSummaryQwtPlot::sizeHint() const
void RiuSummaryQwtPlot::setDefaults()
{
setCommonPlotBehaviour(this);
enableAxis(QwtPlot::xBottom, true);
enableAxis(QwtPlot::yLeft, true);
enableAxis(QwtPlot::xTop, false);
enableAxis(QwtPlot::yRight, false);
RiuQwtPlotTools::setDefaultAxes(this);
useDateBasedTimeAxis();
setAxisMaxMinor(QwtPlot::xBottom, 2);
setAxisMaxMinor(QwtPlot::yLeft, 3);
// The legend will be deleted in the destructor of the plot or when
// another legend is inserted.
QwtLegend* legend = new QwtLegend(this);
@@ -324,62 +318,8 @@ void RiuSummaryQwtPlot::setDefaults()
void RiuSummaryQwtPlot::setCommonPlotBehaviour(QwtPlot* plot)
{
// Plot background and frame look
QPalette newPalette(plot->palette());
newPalette.setColor(QPalette::Background, Qt::white);
plot->setPalette(newPalette);
plot->setAutoFillBackground(true);
plot->setCanvasBackground(Qt::white);
QFrame* canvasFrame = dynamic_cast<QFrame*>(plot->canvas());
if (canvasFrame)
{
canvasFrame->setFrameShape(QFrame::NoFrame);
}
// Grid
QwtPlotGrid* grid = new QwtPlotGrid;
grid->attach(plot);
QPen gridPen(Qt::SolidLine);
gridPen.setColor(Qt::lightGray);
grid->setPen(gridPen);
// Axis number font
QFont axisFont = plot->axisFont(QwtPlot::xBottom);
axisFont.setPixelSize(11);
plot->setAxisFont(QwtPlot::xBottom, axisFont);
plot->setAxisFont(QwtPlot::xTop, axisFont);
plot->setAxisFont(QwtPlot::yLeft, axisFont);
plot->setAxisFont(QwtPlot::yRight, axisFont);
// Axis title font
QwtText axisTitle = plot->axisTitle(QwtPlot::xBottom);
QFont axisTitleFont = axisTitle.font();
axisTitleFont.setPixelSize(11);
axisTitleFont.setBold(false);
axisTitle.setFont(axisTitleFont);
axisTitle.setRenderFlags(Qt::AlignRight);
plot->setAxisTitle(QwtPlot::xBottom, axisTitle);
plot->setAxisTitle(QwtPlot::xTop, axisTitle);
plot->setAxisTitle(QwtPlot::yLeft, axisTitle);
plot->setAxisTitle(QwtPlot::yRight, axisTitle);
// Set a focus policy to allow it taking key press events.
// This is not strictly necessary since this widget inherit QwtPlot
// which already has a focus policy.
// However, for completeness we still do it here.
plot->setFocusPolicy(Qt::WheelFocus);
// Enable mousetracking and event filter
plot->canvas()->setMouseTracking(true);
plot->canvas()->installEventFilter(plot);
plot->plotLayout()->setAlignCanvasToScales(true);
RiuQwtPlotTools::setCommonPlotBehaviour(plot);
new RiuQwtCurvePointTracker(plot, true, &ensembleCurveInfoTextProvider);
}