mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#4157 Grid Cross Plot: Make categorisation legend more like ensemble legend
This commit is contained in:
parent
be95eefd69
commit
ac7eccee88
@ -27,10 +27,11 @@ void RiaGridCrossPlotCurveNameHelper::addCurveSet(RimGridCrossPlotCurveSet* curv
|
||||
m_caseNameSet.insert(curveSet->caseNameString());
|
||||
m_axisVariablesSet.insert(curveSet->axisVariableString());
|
||||
m_timeStepSet.insert(curveSet->timeStepString());
|
||||
for (QString categoryName : curveSet->categoryStrings())
|
||||
for (auto category : curveSet->categoryStrings())
|
||||
{
|
||||
m_categoryNameSet.insert(categoryName);
|
||||
m_categoriesSet.insert(category);
|
||||
}
|
||||
|
||||
m_curveSets.push_back(curveSet);
|
||||
}
|
||||
|
||||
@ -41,7 +42,7 @@ void RiaGridCrossPlotCurveNameHelper::applyCurveNames()
|
||||
{
|
||||
for (auto curveSet : m_curveSets)
|
||||
{
|
||||
curveSet->updateCurveNames(m_caseNameSet.size() > 1u, m_axisVariablesSet.size() > 1u, m_timeStepSet.size() > 1u, m_categoryNameSet.size() > 1u);
|
||||
curveSet->updateCurveNames(m_caseNameSet.size() > 1u, m_axisVariablesSet.size() > 1u, m_timeStepSet.size() > 1u, m_categoriesSet.size() > 1u);
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,6 +54,6 @@ void RiaGridCrossPlotCurveNameHelper::reset()
|
||||
m_caseNameSet.clear();
|
||||
m_axisVariablesSet.clear();
|
||||
m_timeStepSet.clear();
|
||||
m_categoryNameSet.clear();
|
||||
m_categoriesSet.clear();
|
||||
m_curveSets.clear();
|
||||
}
|
||||
|
@ -35,8 +35,8 @@ private:
|
||||
std::set<QString> m_caseNameSet;
|
||||
std::set<QString> m_axisVariablesSet;
|
||||
std::set<QString> m_timeStepSet;
|
||||
std::set<QString> m_categoryNameSet;
|
||||
|
||||
std::set<QString> m_categoriesSet;
|
||||
|
||||
std::vector<RimGridCrossPlotCurveSet*> m_curveSets;
|
||||
|
||||
};
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include "RiaGridCrossPlotCurveNameHelper.h"
|
||||
|
||||
#include "RiuSummaryQwtPlot.h"
|
||||
#include "RiuGridCrossQwtPlot.h"
|
||||
#include "RiuPlotMainWindowTools.h"
|
||||
#include "RiuQwtPlotTools.h"
|
||||
|
||||
@ -106,6 +106,14 @@ int RimGridCrossPlot::indexOfCurveSet(const RimGridCrossPlotCurveSet* curveSet)
|
||||
return -1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimGridCrossPlotCurveSet*> RimGridCrossPlot::curveSets() const
|
||||
{
|
||||
return m_crossPlotCurveSets.childObjects();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -168,7 +176,7 @@ void RimGridCrossPlot::reattachCurvesToQwtAndReplot()
|
||||
curveSet->setParentQwtPlotNoReplot(m_qwtPlot);
|
||||
}
|
||||
}
|
||||
m_qwtPlot->replot();
|
||||
updateAxisDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,7 +196,10 @@ QString RimGridCrossPlot::createAutoName() const
|
||||
QStringList dataSets;
|
||||
for (auto curveSet : m_crossPlotCurveSets)
|
||||
{
|
||||
dataSets += curveSet->createAutoName();
|
||||
if (curveSet->isChecked())
|
||||
{
|
||||
dataSets += curveSet->createAutoName();
|
||||
}
|
||||
}
|
||||
if (!dataSets.isEmpty())
|
||||
{
|
||||
@ -298,7 +309,7 @@ QWidget* RimGridCrossPlot::createViewWidget(QWidget* mainWindowParent)
|
||||
{
|
||||
if (!m_qwtPlot)
|
||||
{
|
||||
m_qwtPlot = new RiuQwtPlot(this, mainWindowParent);
|
||||
m_qwtPlot = new RiuGridCrossQwtPlot(this, mainWindowParent);
|
||||
|
||||
for (auto curveSet : m_crossPlotCurveSets)
|
||||
{
|
||||
@ -468,6 +479,14 @@ void RimGridCrossPlot::updateCurveNamesAndPlotTitle()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiuGridCrossQwtPlot* RimGridCrossPlot::qwtPlot() const
|
||||
{
|
||||
return m_qwtPlot;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -476,7 +495,10 @@ QString RimGridCrossPlot::xAxisParameterString() const
|
||||
QStringList xAxisParams;
|
||||
for (auto curveSet : m_crossPlotCurveSets)
|
||||
{
|
||||
xAxisParams.push_back(curveSet->xAxisName());
|
||||
if (curveSet->isChecked())
|
||||
{
|
||||
xAxisParams.push_back(curveSet->xAxisName());
|
||||
}
|
||||
}
|
||||
|
||||
xAxisParams.removeDuplicates();
|
||||
@ -497,7 +519,10 @@ QString RimGridCrossPlot::yAxisParameterString() const
|
||||
QStringList yAxisParams;
|
||||
for (auto curveSet : m_crossPlotCurveSets)
|
||||
{
|
||||
yAxisParams.push_back(curveSet->yAxisName());
|
||||
if (curveSet->isChecked())
|
||||
{
|
||||
yAxisParams.push_back(curveSet->yAxisName());
|
||||
}
|
||||
}
|
||||
|
||||
yAxisParams.removeDuplicates();
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
class RimPlotAxisProperties;
|
||||
class RimGridCrossPlotCurveSet;
|
||||
class RiuQwtPlot;
|
||||
class RiuGridCrossQwtPlot;
|
||||
|
||||
class RimGridCrossPlotNameConfig : public RimNameConfig
|
||||
{
|
||||
@ -56,6 +56,8 @@ public:
|
||||
|
||||
RimGridCrossPlotCurveSet* createCurveSet();
|
||||
int indexOfCurveSet(const RimGridCrossPlotCurveSet* curveSet) const;
|
||||
|
||||
std::vector<RimGridCrossPlotCurveSet*> curveSets() const;
|
||||
|
||||
QWidget* viewWidget() override;
|
||||
QImage snapshotWindowContent() override;
|
||||
@ -69,6 +71,7 @@ public:
|
||||
void performAutoNameUpdate() override;
|
||||
void updateCurveNamesAndPlotTitle();
|
||||
|
||||
RiuGridCrossQwtPlot* qwtPlot() const;
|
||||
public:
|
||||
// Rim2dPlotInterface overrides
|
||||
void updateAxisScaling() override;
|
||||
@ -97,7 +100,7 @@ protected:
|
||||
|
||||
void updateAxisInQwt(RiaDefines::PlotAxis axisType);
|
||||
void updateAxisFromQwt(RiaDefines::PlotAxis axisType);
|
||||
std::pair<double, double> getAxisRangeFromData(RiaDefines::PlotAxis axisType);
|
||||
|
||||
private:
|
||||
caf::PdmField<bool> m_showLegend;
|
||||
caf::PdmField<int> m_legendFontSize;
|
||||
@ -108,7 +111,7 @@ private:
|
||||
|
||||
caf::PdmChildArrayField<RimGridCrossPlotCurveSet*> m_crossPlotCurveSets;
|
||||
|
||||
QPointer<RiuQwtPlot> m_qwtPlot;
|
||||
QPointer<RiuGridCrossQwtPlot> m_qwtPlot;
|
||||
RiaGridCrossPlotCurveNameHelper m_curveNameHelper;
|
||||
};
|
||||
|
||||
|
@ -48,7 +48,6 @@ CAF_PDM_SOURCE_INIT(RimGridCrossPlotCurve, "GridCrossPlotCurve");
|
||||
RimGridCrossPlotCurve::RimGridCrossPlotCurve()
|
||||
: m_curveSetIndex(0)
|
||||
, m_categoryIndex(0)
|
||||
, m_categoryCount(0)
|
||||
{
|
||||
CAF_PDM_InitObject("Cross Plot Points", ":/WellLogCurve16x16.png", "", "");
|
||||
|
||||
@ -60,19 +59,10 @@ RimGridCrossPlotCurve::RimGridCrossPlotCurve()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGridCrossPlotCurve::setCategoryInformation(int curveSetIndex, int categoryIndex, int categoryCount)
|
||||
void RimGridCrossPlotCurve::setCategoryInformation(int curveSetIndex, int categoryIndex)
|
||||
{
|
||||
m_curveSetIndex = curveSetIndex;
|
||||
m_categoryIndex = categoryIndex;
|
||||
m_categoryCount = categoryCount;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGridCrossPlotCurve::setUseContrastColors(bool useContrastColors)
|
||||
{
|
||||
m_useContrastColors = useContrastColors;
|
||||
m_categoryIndex = categoryIndex;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -90,7 +80,7 @@ void RimGridCrossPlotCurve::setSamples(const std::vector<double>& xValues, const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGridCrossPlotCurve::updateCurveAppearance()
|
||||
{
|
||||
determineColorAndSymbol();
|
||||
determineSymbol();
|
||||
RimPlotCurve::updateCurveAppearance();
|
||||
}
|
||||
|
||||
@ -105,30 +95,10 @@ int RimGridCrossPlotCurve::categoryIndex() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGridCrossPlotCurve::determineColorAndSymbol()
|
||||
void RimGridCrossPlotCurve::determineSymbol()
|
||||
{
|
||||
if (m_useContrastColors)
|
||||
{
|
||||
const caf::ColorTable& colors = RiaColorTables::categoryPaletteColors();
|
||||
int colorIndex = m_categoryIndex + m_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 = m_categoryIndex / numColors;
|
||||
|
||||
RiuQwtSymbol::PointSymbolEnum symbol = RiuQwtSymbol::cycledSymbolStyle(m_curveSetIndex, symbolIndex);
|
||||
setSymbol(symbol);
|
||||
}
|
||||
else
|
||||
{
|
||||
const caf::ColorTable& colors = RiaColorTables::contrastCategoryPaletteColors();
|
||||
cvf::Color3ub cycledBaseColor = colors.cycledColor3ub(m_curveSetIndex);
|
||||
caf::ColorTable hueConstColTable = RiaColorTables::createBrightnessBasedColorTable(cycledBaseColor, m_categoryCount);
|
||||
setColor(hueConstColTable.cycledColor3f(m_categoryIndex));
|
||||
RiuQwtSymbol::PointSymbolEnum symbol = RiuQwtSymbol::cycledFilledSymbolStyle(m_curveSetIndex);
|
||||
setSymbol(symbol);
|
||||
}
|
||||
RiuQwtSymbol::PointSymbolEnum symbol = RiuQwtSymbol::cycledFilledSymbolStyle(m_curveSetIndex);
|
||||
setSymbol(symbol);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -40,15 +40,14 @@ class RimGridCrossPlotCurve : public RimPlotCurve
|
||||
public:
|
||||
RimGridCrossPlotCurve();
|
||||
~RimGridCrossPlotCurve() override = default;
|
||||
void setCategoryInformation(int curveSetIndex, int categoryIndex, int categoryCount);
|
||||
void setUseContrastColors(bool useContrastColors);
|
||||
void setCategoryInformation(int curveSetIndex, int categoryIndex);
|
||||
void setSamples(const std::vector<double>& xValues, const std::vector<double>& yValues);
|
||||
void updateCurveAppearance() override;
|
||||
int categoryIndex() const;
|
||||
|
||||
protected:
|
||||
|
||||
void determineColorAndSymbol();
|
||||
void determineSymbol();
|
||||
void updateZoomInParentPlot() override;
|
||||
void updateLegendsInPlot() override;
|
||||
QString createCurveAutoName() override;
|
||||
@ -56,9 +55,7 @@ protected:
|
||||
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
|
||||
|
||||
private:
|
||||
int m_curveSetIndex;
|
||||
int m_categoryIndex;
|
||||
int m_categoryCount;
|
||||
bool m_useContrastColors;
|
||||
int m_curveSetIndex;
|
||||
int m_categoryIndex;
|
||||
};
|
||||
|
||||
|
@ -18,16 +18,20 @@
|
||||
#include "RimGridCrossPlotCurveSet.h"
|
||||
|
||||
#include "RiaApplication.h"
|
||||
#include "RiaColorTables.h"
|
||||
#include "RiaLogging.h"
|
||||
|
||||
#include "RigActiveCellInfo.h"
|
||||
#include "RigActiveCellsResultAccessor.h"
|
||||
#include "RigCaseCellResultCalculator.h"
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseCrossPlotDataExtractor.h"
|
||||
|
||||
#include "RigFormationNames.h"
|
||||
#include "RigMainGrid.h"
|
||||
|
||||
#include "RiuGridCrossQwtPlot.h"
|
||||
|
||||
#include "RimCase.h"
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseView.h"
|
||||
@ -36,10 +40,14 @@
|
||||
#include "RimGridCrossPlotCurve.h"
|
||||
#include "RimGridView.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimRegularLegendConfig.h"
|
||||
#include "RimTools.h"
|
||||
|
||||
#include "cafColorTable.h"
|
||||
#include "cafPdmUiComboBoxEditor.h"
|
||||
#include "cafPdmUiSliderEditor.h"
|
||||
#include "cafPdmUiTreeOrdering.h"
|
||||
#include "cvfScalarMapper.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
@ -89,9 +97,6 @@ RimGridCrossPlotCurveSet::RimGridCrossPlotCurveSet()
|
||||
m_categoryProperty.uiCapability()->setUiHidden(true);
|
||||
m_categoryProperty.uiCapability()->setUiTreeChildrenHidden(true);
|
||||
|
||||
CAF_PDM_InitField(&m_categoryBinCount, "CategoryBinCount", 2, "Number of Data Groups", "", "", "");
|
||||
m_categoryBinCount.uiCapability()->setUiEditorTypeName(caf::PdmUiSliderEditor::uiEditorTypeName());
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_nameConfig, "NameConfig", "Name", "", "", "");
|
||||
m_nameConfig = new RimGridCrossPlotCurveSetNameConfig(this);
|
||||
m_nameConfig.uiCapability()->setUiTreeHidden(true);
|
||||
@ -100,6 +105,12 @@ RimGridCrossPlotCurveSet::RimGridCrossPlotCurveSet()
|
||||
CAF_PDM_InitFieldNoDefault(&m_crossPlotCurves, "CrossPlotCurves", "Curves", "", "", "");
|
||||
m_crossPlotCurves.uiCapability()->setUiTreeHidden(true);
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_legendConfig, "LegendConfig", "", "", "", "");
|
||||
m_legendConfig = new RimRegularLegendConfig();
|
||||
m_legendConfig->setColorRange(RimRegularLegendConfig::CATEGORY);
|
||||
m_legendConfig->setMappingMode(RimRegularLegendConfig::CATEGORY_INTEGER);
|
||||
m_legendConfig->setTickNumberFormat(RimRegularLegendConfig::AUTO);
|
||||
|
||||
setDefaults();
|
||||
}
|
||||
|
||||
@ -189,23 +200,36 @@ QString RimGridCrossPlotCurveSet::createAutoName() const
|
||||
|
||||
if (m_nameConfig->addCategorization)
|
||||
{
|
||||
if (m_categorization() == TIME_CATEGORIZATION)
|
||||
{
|
||||
nameTags += QString("Grouped by Time");
|
||||
}
|
||||
else if (m_categorization() == FORMATION_CATEGORIZATION)
|
||||
{
|
||||
nameTags += QString("Grouped by formations");
|
||||
}
|
||||
else if (m_categorization() == RESULT_CATEGORIZATION && m_categoryProperty->hasResult())
|
||||
{
|
||||
nameTags += QString("Grouped by %1").arg(m_categoryProperty->resultVariableUiShortName());
|
||||
}
|
||||
QString catTitle = categoryTitle();
|
||||
if (!catTitle.isEmpty()) nameTags += catTitle;
|
||||
}
|
||||
|
||||
return nameTags.join(", ");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimGridCrossPlotCurveSet::categoryTitle() const
|
||||
{
|
||||
if (hasCategoryResult())
|
||||
{
|
||||
if (m_categorization() == TIME_CATEGORIZATION)
|
||||
{
|
||||
return QString("Time Steps");
|
||||
}
|
||||
else if (m_categorization() == FORMATION_CATEGORIZATION)
|
||||
{
|
||||
return QString("Formations");
|
||||
}
|
||||
else if (m_categorization() == RESULT_CATEGORIZATION && m_categoryProperty->hasResult())
|
||||
{
|
||||
return QString("%1").arg(m_categoryProperty->resultVariableUiShortName());
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -228,6 +252,14 @@ void RimGridCrossPlotCurveSet::cellFilterViewUpdated()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimRegularLegendConfig* RimGridCrossPlotCurveSet::legendConfig()
|
||||
{
|
||||
return m_legendConfig;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -281,12 +313,12 @@ QString RimGridCrossPlotCurveSet::timeStepString() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<QString> RimGridCrossPlotCurveSet::categoryStrings() const
|
||||
{
|
||||
std::vector<QString> categoryNames;
|
||||
for (auto categoryIndexNamePair : m_categoryNames)
|
||||
std::vector<QString> catStrings;
|
||||
for (auto curve : m_crossPlotCurves())
|
||||
{
|
||||
categoryNames.push_back(categoryIndexNamePair.second);
|
||||
catStrings.push_back(m_legendConfig->categoryNameFromCategoryValue(curve->categoryIndex()));
|
||||
}
|
||||
return categoryNames;
|
||||
return catStrings;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -338,28 +370,87 @@ void RimGridCrossPlotCurveSet::onLoadDataAndUpdate(bool updateParentPlot)
|
||||
|
||||
std::map<int, cvf::UByteArray> timeStepCellVisibilityMap = calculateCellVisibility(eclipseCase);
|
||||
|
||||
updateLegend();
|
||||
|
||||
RigEclipseCrossPlotResult result = RigEclipseCrossPlotDataExtractor::extract(
|
||||
eclipseCase->eclipseCaseData(), m_timeStep(), xAddress, yAddress, m_categorization(), catAddress, m_categoryBinCount, timeStepCellVisibilityMap);
|
||||
eclipseCase->eclipseCaseData(), m_timeStep(), xAddress, yAddress, m_categorization(), catAddress, timeStepCellVisibilityMap);
|
||||
|
||||
m_categoryNames = result.categoryNameMap;
|
||||
for (const auto& sampleCategory : result.categorySamplesMap)
|
||||
{
|
||||
RimGridCrossPlotCurve* curve = new RimGridCrossPlotCurve();
|
||||
curve->setCategoryInformation(indexInPlot(), sampleCategory.first, (int)result.categorySamplesMap.size());
|
||||
curve->setUseContrastColors(m_categorization() == FORMATION_CATEGORIZATION);
|
||||
curve->setSamples(sampleCategory.second.first, sampleCategory.second.second);
|
||||
curve->updateCurveAppearance();
|
||||
curve->updateUiIconFromPlotSymbol();
|
||||
createCurves(result);
|
||||
|
||||
m_crossPlotCurves.push_back(curve);
|
||||
}
|
||||
|
||||
if (updateParentPlot)
|
||||
{
|
||||
triggerPlotNameUpdateAndReplot();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGridCrossPlotCurveSet::createCurves(const RigEclipseCrossPlotResult& result)
|
||||
{
|
||||
if (m_categorization == NO_CATEGORIZATION)
|
||||
{
|
||||
const caf::ColorTable& colors = RiaColorTables::contrastCategoryPaletteColors();
|
||||
int colorIndex = indexInPlot();
|
||||
|
||||
RimGridCrossPlotCurve* curve = new RimGridCrossPlotCurve();
|
||||
curve->setColor(colors.cycledColor3f(colorIndex));
|
||||
curve->setCategoryInformation(indexInPlot(), 0);
|
||||
curve->setSamples(result.xValues, result.yValues);
|
||||
curve->updateCurveAppearance();
|
||||
curve->updateUiIconFromPlotSymbol();
|
||||
m_crossPlotCurves.push_back(curve);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::map<int, std::pair<std::vector<double>, std::vector<double>>> categorizedResults;
|
||||
|
||||
std::vector<double> tickValues;
|
||||
|
||||
if (m_categorization == TIME_CATEGORIZATION || m_categorization == FORMATION_CATEGORIZATION)
|
||||
{
|
||||
for (size_t i = 0; i < result.xValues.size(); ++i)
|
||||
{
|
||||
categorizedResults[result.catValuesDiscrete[i]].first.push_back(result.xValues[i]);
|
||||
categorizedResults[result.catValuesDiscrete[i]].second.push_back(result.yValues[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_legendConfig->scalarMapper()->majorTickValues(&tickValues);
|
||||
|
||||
for (size_t i = 0; i < result.xValues.size(); ++i)
|
||||
{
|
||||
auto upperBoundIt = std::lower_bound(tickValues.begin(), tickValues.end(), result.catValuesContinuous[i]);
|
||||
int upperBoundIndex = static_cast<int>(upperBoundIt - tickValues.begin());
|
||||
int lowerBoundIndex = std::min((int) tickValues.size() - 2, std::max(0, upperBoundIndex - 1));
|
||||
categorizedResults[lowerBoundIndex].first.push_back(result.xValues[i]);
|
||||
categorizedResults[lowerBoundIndex].second.push_back(result.yValues[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = categorizedResults.rbegin(); it != categorizedResults.rend(); ++it)
|
||||
{
|
||||
RimGridCrossPlotCurve* curve = new RimGridCrossPlotCurve();
|
||||
curve->setCategoryInformation(indexInPlot(), it->first);
|
||||
if (m_categorization == RESULT_CATEGORIZATION)
|
||||
{
|
||||
curve->setColor(cvf::Color3f(m_legendConfig->scalarMapper()->mapToColor(tickValues[it->first])));
|
||||
}
|
||||
else
|
||||
{
|
||||
curve->setColor(cvf::Color3f(m_legendConfig->scalarMapper()->mapToColor(it->first)));
|
||||
}
|
||||
curve->setSamples(it->second.first, it->second.second);
|
||||
curve->showLegend(m_crossPlotCurves.empty());
|
||||
curve->setLegendEntryTitle(createAutoName());
|
||||
curve->updateCurveAppearance();
|
||||
curve->updateUiIconFromPlotSymbol();
|
||||
m_crossPlotCurves.push_back(curve);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -414,7 +505,6 @@ void RimGridCrossPlotCurveSet::defineUiOrdering(QString uiConfigName, caf::PdmUi
|
||||
{
|
||||
caf::PdmUiGroup* categoryGroup = uiOrdering.addNewGroup("Data Grouping Property");
|
||||
m_categoryProperty->uiOrdering(uiConfigName, *categoryGroup);
|
||||
categoryGroup->add(&m_categoryBinCount);
|
||||
}
|
||||
|
||||
caf::PdmUiGroup* xAxisGroup = uiOrdering.addNewGroup("X-Axis Property");
|
||||
@ -457,8 +547,25 @@ void RimGridCrossPlotCurveSet::fieldChangedByUi(const caf::PdmFieldHandle* chang
|
||||
{
|
||||
loadDataAndUpdate(true);
|
||||
}
|
||||
else if (changedField == &m_categorization || changedField == &m_categoryBinCount)
|
||||
else if (changedField == &m_categorization)
|
||||
{
|
||||
if (m_categorization == TIME_CATEGORIZATION)
|
||||
{
|
||||
m_legendConfig->setColorRange(RimRegularLegendConfig::NORMAL);
|
||||
m_legendConfig->setMappingMode(RimRegularLegendConfig::CATEGORY_INTEGER);
|
||||
}
|
||||
else if (m_categorization == FORMATION_CATEGORIZATION)
|
||||
{
|
||||
m_legendConfig->setColorRange(RimRegularLegendConfig::CATEGORY);
|
||||
m_legendConfig->setMappingMode(RimRegularLegendConfig::CATEGORY_INTEGER);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_legendConfig->setColorRange(RimRegularLegendConfig::NORMAL);
|
||||
m_legendConfig->setMappingMode(RimRegularLegendConfig::LINEAR_DISCRETE);
|
||||
|
||||
}
|
||||
|
||||
loadDataAndUpdate(true);
|
||||
}
|
||||
else if (changedField == &m_cellFilterView)
|
||||
@ -467,6 +574,7 @@ void RimGridCrossPlotCurveSet::fieldChangedByUi(const caf::PdmFieldHandle* chang
|
||||
}
|
||||
else if (changedField == &m_isChecked)
|
||||
{
|
||||
updateLegend();
|
||||
triggerPlotNameUpdateAndReplot();
|
||||
}
|
||||
}
|
||||
@ -529,6 +637,96 @@ QList<caf::PdmOptionItemInfo> RimGridCrossPlotCurveSet::calculateValueOptions(co
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGridCrossPlotCurveSet::updateLegend()
|
||||
{
|
||||
m_legendConfig->setTitle(categoryTitle());
|
||||
|
||||
RimGridCrossPlot* parent;
|
||||
this->firstAncestorOrThisOfTypeAsserted(parent);
|
||||
if (parent->qwtPlot())
|
||||
{
|
||||
if (m_categorization() != NO_CATEGORIZATION && m_case() && isChecked() && legendConfig()->showLegend())
|
||||
{
|
||||
if (m_categorization() == FORMATION_CATEGORIZATION)
|
||||
{
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>(m_case());
|
||||
RigFormationNames* formationNames = eclipseCase->eclipseCaseData()->activeFormationNames();
|
||||
|
||||
const std::vector<QString>& categoryNames = formationNames->formationNames();
|
||||
m_legendConfig->setNamedCategories(categoryNames);
|
||||
m_legendConfig->setAutomaticRanges(0, categoryNames.size() - 1, 0, categoryNames.size() - 1);
|
||||
}
|
||||
else if (m_categorization() == TIME_CATEGORIZATION)
|
||||
{
|
||||
QStringList timeStepNames = m_case->timeStepStrings();
|
||||
std::vector<QString> categoryNames;
|
||||
for (auto name : timeStepNames)
|
||||
{
|
||||
categoryNames.push_back(name);
|
||||
}
|
||||
m_legendConfig->setNamedCategories(categoryNames);
|
||||
m_legendConfig->setAutomaticRanges(0, categoryNames.size() - 1, 0, categoryNames.size() - 1);
|
||||
}
|
||||
else if (m_categoryProperty->eclipseResultAddress().isValid())
|
||||
{
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>(m_case());
|
||||
RigEclipseCaseData* caseData = eclipseCase->eclipseCaseData();
|
||||
CVF_ASSERT(caseData);
|
||||
if (!caseData) return;
|
||||
|
||||
RigCaseCellResultsData* cellResultsData = caseData->results(RiaDefines::MATRIX_MODEL);
|
||||
CVF_ASSERT(cellResultsData);
|
||||
|
||||
double globalMin, globalMax;
|
||||
double globalPosClosestToZero, globalNegClosestToZero;
|
||||
|
||||
cellResultsData->minMaxCellScalarValues(m_categoryProperty->eclipseResultAddress(), globalMin, globalMax);
|
||||
cellResultsData->posNegClosestToZero(
|
||||
m_categoryProperty->eclipseResultAddress(), globalPosClosestToZero, globalNegClosestToZero);
|
||||
|
||||
double localMin, localMax;
|
||||
double localPosClosestToZero, localNegClosestToZero;
|
||||
if (m_categoryProperty->hasDynamicResult() && m_timeStep != -1)
|
||||
{
|
||||
cellResultsData->minMaxCellScalarValues(m_categoryProperty->eclipseResultAddress(), m_timeStep, localMin, localMax);
|
||||
cellResultsData->posNegClosestToZero(
|
||||
m_categoryProperty->eclipseResultAddress(), m_timeStep, localPosClosestToZero, localNegClosestToZero);
|
||||
}
|
||||
else
|
||||
{
|
||||
localMin = globalMin;
|
||||
localMax = globalMax;
|
||||
|
||||
localPosClosestToZero = globalPosClosestToZero;
|
||||
localNegClosestToZero = globalNegClosestToZero;
|
||||
}
|
||||
|
||||
CVF_ASSERT(m_legendConfig);
|
||||
|
||||
m_legendConfig->setClosestToZeroValues(
|
||||
globalPosClosestToZero, globalNegClosestToZero, localPosClosestToZero, localNegClosestToZero);
|
||||
m_legendConfig->setAutomaticRanges(globalMin, globalMax, localMin, localMax);
|
||||
}
|
||||
parent->qwtPlot()->addOrUpdateCurveSetLegend(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->qwtPlot()->removeCurveSetLegend(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimGridCrossPlotCurveSet::hasCategoryResult() const
|
||||
{
|
||||
return m_categorization == FORMATION_CATEGORIZATION || m_categorization == TIME_CATEGORIZATION || m_categorization == RESULT_CATEGORIZATION;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -547,7 +745,7 @@ void RimGridCrossPlotCurveSet::triggerPlotNameUpdateAndReplot()
|
||||
void RimGridCrossPlotCurveSet::updateCurveNames(bool applyCaseName,
|
||||
bool applyAxisVariables,
|
||||
bool applyTimeStep,
|
||||
bool applyCategories)
|
||||
bool applyCategory)
|
||||
{
|
||||
for (auto curve : m_crossPlotCurves())
|
||||
{
|
||||
@ -568,16 +766,30 @@ void RimGridCrossPlotCurveSet::updateCurveNames(bool applyCaseName,
|
||||
nameTags += timeStepString();
|
||||
}
|
||||
|
||||
if (applyCategories)
|
||||
if (applyCategory && m_categorization != NO_CATEGORIZATION)
|
||||
{
|
||||
QString categoryName = m_categoryNames[curve->categoryIndex()];
|
||||
if (!categoryName.isEmpty())
|
||||
if (m_categorization == RESULT_CATEGORIZATION)
|
||||
{
|
||||
nameTags += categoryName;
|
||||
std::vector<double> tickValues;
|
||||
m_legendConfig->scalarMapper()->majorTickValues(&tickValues);
|
||||
size_t catIndex = (size_t) curve->categoryIndex();
|
||||
double lowerLimit = tickValues[catIndex];
|
||||
double upperLimit = catIndex + 1u < tickValues.size()
|
||||
? tickValues[catIndex + 1u] : std::numeric_limits<double>::infinity();
|
||||
nameTags += QString("%1 [%2, %3]").arg(categoryTitle()).arg(lowerLimit).arg(upperLimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
nameTags += m_legendConfig->categoryNameFromCategoryValue(curve->categoryIndex());
|
||||
}
|
||||
}
|
||||
|
||||
curve->setCustomName(nameTags.join(", "));
|
||||
if (m_categorization != NO_CATEGORIZATION)
|
||||
{
|
||||
curve->setLegendEntryTitle(createAutoName());
|
||||
}
|
||||
|
||||
curve->updateCurveNameAndUpdatePlotLegendAndTitle();
|
||||
}
|
||||
}
|
||||
@ -631,15 +843,24 @@ void RimGridCrossPlotCurveSet::defineEditorAttribute(const caf::PdmFieldHandle*
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute)
|
||||
{
|
||||
if (field == &m_categoryBinCount)
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGridCrossPlotCurveSet::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/)
|
||||
{
|
||||
if (m_categorization() != NO_CATEGORIZATION)
|
||||
{
|
||||
auto myAttr = dynamic_cast<caf::PdmUiSliderEditorAttribute*>(attribute);
|
||||
if (myAttr)
|
||||
{
|
||||
myAttr->m_minimum = 2;
|
||||
myAttr->m_maximum = 50;
|
||||
}
|
||||
uiTreeOrdering.add(m_legendConfig());
|
||||
}
|
||||
|
||||
for (auto curve : m_crossPlotCurves())
|
||||
{
|
||||
uiTreeOrdering.add(curve);
|
||||
}
|
||||
|
||||
uiTreeOrdering.skipRemainingChildren(true);
|
||||
}
|
||||
|
||||
CAF_PDM_SOURCE_INIT(RimGridCrossPlotCurveSetNameConfig, "RimGridCrossPlotCurveSetNameConfig");
|
||||
@ -655,7 +876,7 @@ RimGridCrossPlotCurveSetNameConfig::RimGridCrossPlotCurveSetNameConfig(RimNameCo
|
||||
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", "", "", "");
|
||||
CAF_PDM_InitField(&addCategorization, "AddCategorization", false, "Add Data Categorization", "", "", "");
|
||||
CAF_PDM_InitField(&addCategorization, "AddCategorization", true, "Add Data Categorization", "", "", "");
|
||||
|
||||
setCustomName("");
|
||||
}
|
||||
|
@ -34,11 +34,13 @@
|
||||
#include <QList>
|
||||
#include <map>
|
||||
|
||||
struct RigEclipseCrossPlotResult;
|
||||
class RimCase;
|
||||
class RimGridCrossPlotCurve;
|
||||
class RimGridView;
|
||||
class RimEclipseCase;
|
||||
class RimEclipseResultDefinition;
|
||||
class RimRegularLegendConfig;
|
||||
class QwtPlot;
|
||||
class QwtPlotCurve;
|
||||
class QString;
|
||||
@ -83,8 +85,11 @@ public:
|
||||
|
||||
int indexInPlot() const;
|
||||
QString createAutoName() const override;
|
||||
QString categoryTitle() const;
|
||||
void detachAllCurves();
|
||||
void cellFilterViewUpdated();
|
||||
|
||||
RimRegularLegendConfig* legendConfig();
|
||||
|
||||
std::vector< RimGridCrossPlotCurve*> curves() const;
|
||||
|
||||
@ -93,12 +98,16 @@ public:
|
||||
QString timeStepString() const;
|
||||
std::vector<QString> categoryStrings() const;
|
||||
|
||||
void updateCurveNames(bool applyCaseName, bool applyAxisVariables, bool applyTimeStep, bool applyCategories);
|
||||
|
||||
void updateCurveNames(bool applyCaseName, bool applyAxisVariables, bool applyTimeStep, bool applyCategory);
|
||||
void updateLegend();
|
||||
bool hasCategoryResult() const;
|
||||
|
||||
protected:
|
||||
void initAfterRead() override;
|
||||
void onLoadDataAndUpdate(bool updateParentPlot);
|
||||
|
||||
void createCurves(const RigEclipseCrossPlotResult& result);
|
||||
|
||||
std::map<int, cvf::UByteArray> calculateCellVisibility(RimEclipseCase* eclipseCase) const;
|
||||
|
||||
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
|
||||
@ -111,6 +120,8 @@ protected:
|
||||
void setDefaults();
|
||||
void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override;
|
||||
|
||||
void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") override;
|
||||
|
||||
private:
|
||||
caf::PdmPtrField<RimCase*> m_case;
|
||||
caf::PdmField<int> m_timeStep;
|
||||
@ -119,11 +130,9 @@ private:
|
||||
caf::PdmChildField<RimEclipseResultDefinition*> m_xAxisProperty;
|
||||
caf::PdmChildField<RimEclipseResultDefinition*> m_yAxisProperty;
|
||||
caf::PdmChildField<RimEclipseResultDefinition*> m_categoryProperty;
|
||||
caf::PdmField<int> m_categoryBinCount;
|
||||
|
||||
caf::PdmChildField<RimGridCrossPlotCurveSetNameConfig*> m_nameConfig;
|
||||
|
||||
caf::PdmChildArrayField<RimGridCrossPlotCurve*> m_crossPlotCurves;
|
||||
|
||||
std::map<int, QString> m_categoryNames;
|
||||
caf::PdmChildField<RimRegularLegendConfig*> m_legendConfig;
|
||||
};
|
||||
|
@ -96,6 +96,9 @@ RimPlotCurve::RimPlotCurve()
|
||||
CAF_PDM_InitFieldNoDefault(&m_customCurveName, "CurveDescription", "Custom Name", "", "", "");
|
||||
m_customCurveName.uiCapability()->setUiHidden(true);
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_legendEntryTitle, "LegendDescription", "Legend Name", "", "", "");
|
||||
m_legendEntryTitle.uiCapability()->setUiHidden(true);
|
||||
|
||||
CAF_PDM_InitField(&m_isUsingAutoName, "AutoName", true, "Auto Name", "", "", "");
|
||||
|
||||
CAF_PDM_InitField(&m_curveColor, "Color", cvf::Color3f(cvf::Color3::BLACK), "Color", "", "", "");
|
||||
@ -213,6 +216,14 @@ void RimPlotCurve::setCustomName(const QString& customName)
|
||||
m_customCurveName = customName;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimPlotCurve::setLegendEntryTitle(const QString& legendEntryTitle)
|
||||
{
|
||||
m_legendEntryTitle = legendEntryTitle;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -354,9 +365,9 @@ void RimPlotCurve::setCurveVisiblity(bool visible)
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimPlotCurve::updateCurveNameAndUpdatePlotLegendAndTitle()
|
||||
void RimPlotCurve::updateCurveName()
|
||||
{
|
||||
if (m_isUsingAutoName)
|
||||
{
|
||||
@ -367,7 +378,23 @@ void RimPlotCurve::updateCurveNameAndUpdatePlotLegendAndTitle()
|
||||
m_curveName = m_customCurveName;
|
||||
}
|
||||
|
||||
m_qwtPlotCurve->setTitle(m_curveName);
|
||||
if (!m_legendEntryTitle().isEmpty())
|
||||
{
|
||||
m_qwtPlotCurve->setTitle(m_legendEntryTitle);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_qwtPlotCurve->setTitle(m_curveName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimPlotCurve::updateCurveNameAndUpdatePlotLegendAndTitle()
|
||||
{
|
||||
updateCurveName();
|
||||
updateLegendEntryVisibilityAndPlotLegend();
|
||||
}
|
||||
|
||||
@ -375,17 +402,8 @@ void RimPlotCurve::updateCurveNameAndUpdatePlotLegendAndTitle()
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimPlotCurve::updateCurveNameNoLegendUpdate()
|
||||
{
|
||||
if (m_isUsingAutoName)
|
||||
{
|
||||
m_curveName = this->createCurveAutoName();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curveName = m_customCurveName;
|
||||
}
|
||||
|
||||
m_qwtPlotCurve->setTitle(m_curveName);
|
||||
{
|
||||
updateCurveName();
|
||||
updateLegendEntryVisibilityNoPlotUpdate();
|
||||
}
|
||||
|
||||
|
@ -71,12 +71,15 @@ public:
|
||||
bool isCurveVisible() const;
|
||||
void setCurveVisiblity(bool visible);
|
||||
|
||||
void updateCurveName();
|
||||
void updateCurveNameAndUpdatePlotLegendAndTitle();
|
||||
void updateCurveNameNoLegendUpdate();
|
||||
|
||||
QString curveName() const { return m_curveName; }
|
||||
virtual QString curveExportDescription(const RifEclipseSummaryAddress& address = RifEclipseSummaryAddress()) const { return m_curveName; }
|
||||
void setCustomName(const QString& customName);
|
||||
void setLegendEntryTitle(const QString& legendEntryTitle);
|
||||
|
||||
void updateCurveVisibility(bool updateParentPlot);
|
||||
void updateLegendEntryVisibilityAndPlotLegend();
|
||||
void updateLegendEntryVisibilityNoPlotUpdate();
|
||||
@ -124,7 +127,8 @@ protected:
|
||||
caf::PdmField<bool> m_showLegend;
|
||||
QString m_symbolLabel;
|
||||
caf::PdmField<int> m_symbolSize;
|
||||
|
||||
caf::PdmField<QString> m_legendEntryTitle;
|
||||
|
||||
caf::PdmField<bool> m_isUsingAutoName;
|
||||
caf::PdmField<cvf::Color3f> m_curveColor;
|
||||
caf::PdmField<int> m_curveThickness;
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "RimEnsembleCurveSetColorManager.h"
|
||||
#include "RimEclipseView.h"
|
||||
#include "RimGeoMechResultDefinition.h"
|
||||
#include "RimGridCrossPlotCurveSet.h"
|
||||
#include "RimIntersectionCollection.h"
|
||||
#include "RimStimPlanColors.h"
|
||||
#include "RimViewLinker.h"
|
||||
@ -256,6 +257,13 @@ void RimRegularLegendConfig::fieldChangedByUi(const caf::PdmFieldHandle* changed
|
||||
{
|
||||
ensembleCurveSet->onLegendDefinitionChanged();
|
||||
}
|
||||
|
||||
RimGridCrossPlotCurveSet* crossPlotCurveSet;
|
||||
firstAncestorOrThisOfType(crossPlotCurveSet);
|
||||
if (crossPlotCurveSet)
|
||||
{
|
||||
crossPlotCurveSet->loadDataAndUpdate(true);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -439,6 +447,14 @@ void RimRegularLegendConfig::updateLegend()
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimRegularLegendConfig::setTickNumberFormat(NumberFormatType numberFormat)
|
||||
{
|
||||
m_tickNumberFormat = numberFormat;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -861,6 +877,9 @@ QList<caf::PdmOptionItemInfo> RimRegularLegendConfig::calculateValueOptions(cons
|
||||
this->firstAncestorOrThisOfType(ensembleCurveSet);
|
||||
if (ensembleCurveSet) hasEnsembleCurveSetParent = true;
|
||||
|
||||
RimGridCrossPlotCurveSet* crossPlotCurveSet = nullptr;
|
||||
this->firstAncestorOrThisOfType(crossPlotCurveSet);
|
||||
|
||||
bool isCategoryResult = false;
|
||||
{
|
||||
RimEclipseCellColors* eclCellColors = nullptr;
|
||||
@ -873,7 +892,8 @@ QList<caf::PdmOptionItemInfo> RimRegularLegendConfig::calculateValueOptions(cons
|
||||
if ( ( eclCellColors && eclCellColors->hasCategoryResult())
|
||||
|| ( gmCellColors && gmCellColors->hasCategoryResult())
|
||||
|| ( eclCellEdgColors && eclCellEdgColors->hasCategoryResult())
|
||||
|| ( ensembleCurveSet && ensembleCurveSet->currentEnsembleParameterType() == EnsembleParameter::TYPE_TEXT) )
|
||||
|| ( ensembleCurveSet && ensembleCurveSet->currentEnsembleParameterType() == EnsembleParameter::TYPE_TEXT)
|
||||
|| ( crossPlotCurveSet && crossPlotCurveSet->hasCategoryResult()))
|
||||
{
|
||||
isCategoryResult = true;
|
||||
}
|
||||
@ -886,8 +906,12 @@ QList<caf::PdmOptionItemInfo> RimRegularLegendConfig::calculateValueOptions(cons
|
||||
// This is an app enum field, see cafInternalPdmFieldTypeSpecializations.h for the default specialization of this type
|
||||
std::vector<MappingType> mappingTypes;
|
||||
mappingTypes.push_back(LINEAR_DISCRETE);
|
||||
mappingTypes.push_back(LINEAR_CONTINUOUS);
|
||||
mappingTypes.push_back(LOG10_CONTINUOUS);
|
||||
|
||||
if (!crossPlotCurveSet)
|
||||
{
|
||||
mappingTypes.push_back(LINEAR_CONTINUOUS);
|
||||
mappingTypes.push_back(LOG10_CONTINUOUS);
|
||||
}
|
||||
mappingTypes.push_back(LOG10_DISCRETE);
|
||||
|
||||
if (isCategoryResult)
|
||||
|
@ -103,6 +103,8 @@ public:
|
||||
ColorRangesType colorRange() { return m_colorRangeMode();}
|
||||
void setMappingMode(MappingType mappingType);
|
||||
MappingType mappingMode() { return m_mappingMode();}
|
||||
void setTickNumberFormat(NumberFormatType numberFormat);
|
||||
|
||||
void disableAllTimeStepsRange(bool doDisable);
|
||||
|
||||
void setAutomaticRanges(double globalMin, double globalMax, double localMin, double localMax);
|
||||
|
@ -40,12 +40,9 @@ RigEclipseCrossPlotResult RigEclipseCrossPlotDataExtractor::extract(RigEclipseCa
|
||||
const RigEclipseResultAddress& yAddress,
|
||||
RigGridCrossPlotCurveCategorization categorizationType,
|
||||
const RigEclipseResultAddress& catAddress,
|
||||
int categoryBinCount,
|
||||
std::map<int, cvf::UByteArray> timeStepCellVisibilityMap)
|
||||
{
|
||||
RigEclipseCrossPlotResult result;
|
||||
RigEclipseCrossPlotResult::CategorySamplesMap& categorySamplesMap = result.categorySamplesMap;
|
||||
RigEclipseCrossPlotResult::CategoryNameMap& categoryNameMap = result.categoryNameMap;
|
||||
|
||||
RigCaseCellResultsData* resultData = caseData->results(RiaDefines::MATRIX_MODEL);
|
||||
RigFormationNames* activeFormationNames = resultData->activeFormationNames();
|
||||
@ -68,7 +65,6 @@ RigEclipseCrossPlotResult RigEclipseCrossPlotDataExtractor::extract(RigEclipseCa
|
||||
{
|
||||
resultData->ensureKnownResultLoaded(catAddress);
|
||||
catValuesForAllSteps = &resultData->cellScalarResults(catAddress);
|
||||
catBinSorter.reset(new RigEclipseResultBinSorter(*catValuesForAllSteps, categoryBinCount));
|
||||
}
|
||||
|
||||
std::set<int> timeStepsToInclude;
|
||||
@ -119,61 +115,38 @@ RigEclipseCrossPlotResult RigEclipseCrossPlotDataExtractor::extract(RigEclipseCa
|
||||
double xValue = xAccessor.cellScalarGlobIdx(globalCellIdx);
|
||||
double yValue = yAccessor.cellScalarGlobIdx(globalCellIdx);
|
||||
|
||||
int category = 0;
|
||||
if (xValue == HUGE_VAL || yValue == HUGE_VAL) continue;
|
||||
|
||||
result.xValues.push_back(xValue);
|
||||
result.yValues.push_back(yValue);
|
||||
|
||||
if (categorizationType == TIME_CATEGORIZATION)
|
||||
{
|
||||
category = timeStep;
|
||||
result.catValuesDiscrete.push_back(timeStep);
|
||||
}
|
||||
else if (categorizationType == FORMATION_CATEGORIZATION && activeFormationNames)
|
||||
else if (categorizationType == FORMATION_CATEGORIZATION)
|
||||
{
|
||||
CVF_ASSERT(activeFormationNames);
|
||||
int category = 0;
|
||||
size_t i(cvf::UNDEFINED_SIZE_T), j(cvf::UNDEFINED_SIZE_T), k(cvf::UNDEFINED_SIZE_T);
|
||||
if (mainGrid->ijkFromCellIndex(globalCellIdx, &i, &j, &k))
|
||||
{
|
||||
category = activeFormationNames->formationIndexFromKLayerIdx(k);
|
||||
}
|
||||
result.catValuesDiscrete.push_back(category);
|
||||
}
|
||||
else if (catAccessor && catBinSorter)
|
||||
else if (categorizationType == RESULT_CATEGORIZATION)
|
||||
{
|
||||
double catValue = catAccessor->cellScalarGlobIdx(globalCellIdx);
|
||||
category = catBinSorter->binNumber(catValue);
|
||||
}
|
||||
if (xValue != HUGE_VAL && yValue != HUGE_VAL)
|
||||
{
|
||||
categorySamplesMap[category].first.push_back(xValue);
|
||||
categorySamplesMap[category].second.push_back(yValue);
|
||||
double catValue = HUGE_VAL;
|
||||
if (catAccessor)
|
||||
{
|
||||
catValue = catAccessor->cellScalarGlobIdx(globalCellIdx);
|
||||
}
|
||||
result.catValuesContinuous.push_back(catValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<QDateTime> timeStepDates = resultData->timeStepDates();
|
||||
QString timeFormatString = RiaQDateTimeTools::createTimeFormatStringFromDates(timeStepDates);
|
||||
|
||||
for (const auto& sampleCategory : categorySamplesMap)
|
||||
{
|
||||
QString categoryName;
|
||||
if (categorizationType == TIME_CATEGORIZATION && categorySamplesMap.size() > 1u)
|
||||
{
|
||||
if (sampleCategory.first < static_cast<int>(timeStepDates.size()))
|
||||
{
|
||||
categoryName = RiaQDateTimeTools::toStringUsingApplicationLocale(timeStepDates[sampleCategory.first], timeFormatString);
|
||||
}
|
||||
}
|
||||
else if (categorizationType == FORMATION_CATEGORIZATION && activeFormationNames)
|
||||
{
|
||||
categoryName = activeFormationNames->formationNameFromKLayerIdx(sampleCategory.first);
|
||||
}
|
||||
else if (catBinSorter)
|
||||
{
|
||||
std::pair<double, double> binRange = catBinSorter->binRange(sampleCategory.first);
|
||||
|
||||
categoryName = QString("%1 [%2, %3]")
|
||||
.arg(catAddress.m_resultName)
|
||||
.arg(binRange.first)
|
||||
.arg(binRange.second);
|
||||
}
|
||||
categoryNameMap.insert(std::make_pair(sampleCategory.first, categoryName));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -33,13 +33,10 @@ class QString;
|
||||
|
||||
struct RigEclipseCrossPlotResult
|
||||
{
|
||||
typedef std::pair<std::vector<double>, std::vector<double>> ResultXYValues;
|
||||
|
||||
typedef std::map<int, ResultXYValues> CategorySamplesMap;
|
||||
typedef std::map<int, QString> CategoryNameMap;
|
||||
|
||||
CategorySamplesMap categorySamplesMap;
|
||||
CategoryNameMap categoryNameMap;
|
||||
std::vector<double> xValues;
|
||||
std::vector<double> yValues;
|
||||
std::vector<double> catValuesContinuous;
|
||||
std::vector<int> catValuesDiscrete;
|
||||
};
|
||||
|
||||
class RigEclipseCrossPlotDataExtractor
|
||||
@ -51,6 +48,5 @@ public:
|
||||
const RigEclipseResultAddress& yAddress,
|
||||
RigGridCrossPlotCurveCategorization categorizationType,
|
||||
const RigEclipseResultAddress& categoryAddress,
|
||||
int categoryBinCount,
|
||||
std::map<int, cvf::UByteArray> timeStepCellVisibilityMap);
|
||||
};
|
||||
|
@ -37,6 +37,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuSelectionChangedHandler.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/Riu3dSelectionManager.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuSimpleHistogramWidget.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuGridCrossQwtPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuSummaryQwtPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuTextDialog.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuTimeStepChangedHandler.h
|
||||
@ -118,6 +119,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuSelectionChangedHandler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/Riu3dSelectionManager.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuSimpleHistogramWidget.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlot.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuGridCrossQwtPlot.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuSummaryQwtPlot.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuTextDialog.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuTimeStepChangedHandler.cpp
|
||||
@ -185,6 +187,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuWellLogPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuWellLogTrack.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuRecentFileActionProvider.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuGridCrossQwtPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuSummaryQwtPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuTofAccumulatedPhaseFractionsPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiuQwtScalePicker.h
|
||||
|
140
ApplicationCode/UserInterface/RiuGridCrossQwtPlot.cpp
Normal file
140
ApplicationCode/UserInterface/RiuGridCrossQwtPlot.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "RiuGridCrossQwtPlot.h"
|
||||
|
||||
#include "RiuCvfOverlayItemWidget.h"
|
||||
#include "RiuWidgetDragger.h"
|
||||
|
||||
#include "RimGridCrossPlot.h"
|
||||
#include "RimGridCrossPlotCurveSet.h"
|
||||
#include "RimRegularLegendConfig.h"
|
||||
|
||||
#include "cafTitledOverlayFrame.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiuGridCrossQwtPlot::RiuGridCrossQwtPlot(RimViewWindow* ownerViewWindow, QWidget* parent /*= nullptr*/)
|
||||
: RiuQwtPlot(ownerViewWindow, parent)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiuGridCrossQwtPlot::addOrUpdateCurveSetLegend(RimGridCrossPlotCurveSet* curveSetToShowLegendFor)
|
||||
{
|
||||
RiuCvfOverlayItemWidget* overlayWidget = nullptr;
|
||||
|
||||
auto it = m_legendWidgets.find(curveSetToShowLegendFor);
|
||||
if (it == m_legendWidgets.end() || it->second == nullptr)
|
||||
{
|
||||
overlayWidget = new RiuCvfOverlayItemWidget(this);
|
||||
|
||||
new RiuWidgetDragger(overlayWidget);
|
||||
|
||||
m_legendWidgets[curveSetToShowLegendFor] = overlayWidget;
|
||||
}
|
||||
else
|
||||
{
|
||||
overlayWidget = it->second;
|
||||
}
|
||||
|
||||
if (overlayWidget)
|
||||
{
|
||||
caf::TitledOverlayFrame* overlayItem = curveSetToShowLegendFor->legendConfig()->titledOverlayFrame();
|
||||
overlayItem->setRenderSize(overlayItem->preferredSize());
|
||||
|
||||
overlayWidget->updateFromOverlayItem(curveSetToShowLegendFor->legendConfig()->titledOverlayFrame());
|
||||
}
|
||||
|
||||
this->updateLegendLayout();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiuGridCrossQwtPlot::removeCurveSetLegend(RimGridCrossPlotCurveSet* curveSetToShowLegendFor)
|
||||
{
|
||||
auto it = m_legendWidgets.find(curveSetToShowLegendFor);
|
||||
if (it != m_legendWidgets.end())
|
||||
{
|
||||
if (it->second != nullptr) it->second->deleteLater();
|
||||
|
||||
m_legendWidgets.erase(it);
|
||||
}
|
||||
|
||||
this->updateLegendLayout();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiuGridCrossQwtPlot::updateLayout()
|
||||
{
|
||||
QwtPlot::updateLayout();
|
||||
updateLegendLayout();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiuGridCrossQwtPlot::updateLegendLayout()
|
||||
{
|
||||
const int spacing = 5;
|
||||
int startMarginX = this->canvas()->pos().x() + spacing;
|
||||
int startMarginY = this->canvas()->pos().y() + spacing;
|
||||
|
||||
int xpos = startMarginX;
|
||||
int ypos = startMarginY;
|
||||
int maxColumnWidth = 0;
|
||||
|
||||
RimGridCrossPlot* crossPlot = dynamic_cast<RimGridCrossPlot*>(ownerPlotDefinition());
|
||||
|
||||
if (!crossPlot) return;
|
||||
|
||||
std::set<QString> legendTypes;
|
||||
|
||||
for (RimGridCrossPlotCurveSet* curveSet : crossPlot->curveSets())
|
||||
{
|
||||
if (!curveSet->isChecked() || !curveSet->legendConfig()->showLegend()) continue;
|
||||
|
||||
auto pairIt = m_legendWidgets.find(curveSet);
|
||||
if (pairIt != m_legendWidgets.end())
|
||||
{
|
||||
RiuCvfOverlayItemWidget* overlayWidget = pairIt->second;
|
||||
// Show only one copy of each legend type
|
||||
if (!legendTypes.count(curveSet->categoryTitle()))
|
||||
{
|
||||
if (ypos + overlayWidget->height() + spacing > this->canvas()->height())
|
||||
{
|
||||
xpos += spacing + maxColumnWidth;
|
||||
ypos = startMarginY;
|
||||
maxColumnWidth = 0;
|
||||
}
|
||||
|
||||
overlayWidget->show();
|
||||
overlayWidget->move(xpos, ypos);
|
||||
|
||||
ypos += pairIt->second->height() + spacing;
|
||||
maxColumnWidth = std::max(maxColumnWidth, pairIt->second->width());
|
||||
legendTypes.insert(curveSet->categoryTitle());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
52
ApplicationCode/UserInterface/RiuGridCrossQwtPlot.h
Normal file
52
ApplicationCode/UserInterface/RiuGridCrossQwtPlot.h
Normal file
@ -0,0 +1,52 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "RiuInterfaceToViewWindow.h"
|
||||
#include "RiuQwtPlot.h"
|
||||
|
||||
#include "cafPdmPointer.h"
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
class RimGridCrossPlotCurveSet;
|
||||
class RiuCvfOverlayItemWidget;
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class RiuGridCrossQwtPlot : public RiuQwtPlot
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
RiuGridCrossQwtPlot(RimViewWindow* ownerViewWindow, QWidget* parent = nullptr);
|
||||
|
||||
void addOrUpdateCurveSetLegend(RimGridCrossPlotCurveSet* curveSetToShowLegendFor);
|
||||
void removeCurveSetLegend(RimGridCrossPlotCurveSet* curveSetToShowLegendFor);
|
||||
|
||||
protected:
|
||||
void updateLayout() override;
|
||||
void updateLegendLayout();
|
||||
|
||||
private:
|
||||
std::map<caf::PdmPointer<RimGridCrossPlotCurveSet>, QPointer<RiuCvfOverlayItemWidget>> m_legendWidgets;
|
||||
};
|
@ -143,7 +143,7 @@ void RiuSummaryQwtPlot::addOrUpdateEnsembleCurveSetLegend(RimEnsembleCurveSet* c
|
||||
overlayWidget->show();
|
||||
}
|
||||
|
||||
this->updateEnsembleLegendLayout();
|
||||
this->updateLegendLayout();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -159,7 +159,7 @@ void RiuSummaryQwtPlot::removeEnsembleCurveSetLegend(RimEnsembleCurveSet* curveS
|
||||
m_ensembleLegendWidgets.erase(it);
|
||||
}
|
||||
|
||||
this->updateEnsembleLegendLayout();
|
||||
this->updateLegendLayout();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -215,13 +215,13 @@ void RiuSummaryQwtPlot::setDefaults()
|
||||
void RiuSummaryQwtPlot::updateLayout()
|
||||
{
|
||||
QwtPlot::updateLayout();
|
||||
updateEnsembleLegendLayout();
|
||||
updateLegendLayout();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiuSummaryQwtPlot::updateEnsembleLegendLayout()
|
||||
void RiuSummaryQwtPlot::updateLegendLayout()
|
||||
{
|
||||
const int spacing = 5;
|
||||
int startMarginX = this->canvas()->pos().x() + spacing;
|
||||
|
@ -23,15 +23,8 @@
|
||||
|
||||
#include "cafPdmPointer.h"
|
||||
|
||||
#include "qwt_plot.h"
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
class QwtInterval;
|
||||
class QwtPlotZoomer;
|
||||
|
||||
class RimGridCrossPlot;
|
||||
class RimSummaryPlot;
|
||||
class RimEnsembleCurveSet;
|
||||
class RiuCvfOverlayItemWidget;
|
||||
|
||||
@ -59,7 +52,7 @@ protected:
|
||||
void setDefaults();
|
||||
void updateLayout() override;
|
||||
private:
|
||||
void updateEnsembleLegendLayout();
|
||||
void updateLegendLayout();
|
||||
std::map<caf::PdmPointer<RimEnsembleCurveSet>, QPointer<RiuCvfOverlayItemWidget>> m_ensembleLegendWidgets;
|
||||
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user