diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 0fd2c81b9e..4bcb6a0f1a 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -31,6 +31,7 @@ #include "RigCaseData.h" #include "RiaApplication.h" #include "RiaPreferences.h" +#include "RimTernaryLegendConfig.h" #include "RimCase.h" #include "RimWellCollection.h" @@ -664,53 +665,22 @@ void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t ti double swatMin = 0.0; double swatMax = 1.0; + cellResultSlot->ternaryLegendConfig()->ternaryRanges(soilMin, soilMax, sgasMin, sgasMax, swatMin, swatMax); + cvf::ref dataAccessObjectSoil = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, soilScalarSetIndex); - if (dataAccessObjectSoil.notNull()) - { - if (cellResultSlot->legendConfig()->rangeMode() == RimLegendConfig::AUTOMATIC_CURRENT_TIMESTEP) - { - gridCellResults->cellResults()->minMaxCellScalarValues(soilScalarSetIndex, timeStepIndex, soilMin, soilMax); - } - else - { - gridCellResults->cellResults()->minMaxCellScalarValues(soilScalarSetIndex, soilMin, soilMax); - } - } - else + if (dataAccessObjectSoil.isNull()) { dataAccessObjectSoil = new ScalarDataAccessZeroForAllCells; } cvf::ref dataAccessObjectSgas = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, sgasScalarSetIndex); - if (dataAccessObjectSgas.notNull()) - { - if (cellResultSlot->legendConfig()->rangeMode() == RimLegendConfig::AUTOMATIC_CURRENT_TIMESTEP) - { - gridCellResults->cellResults()->minMaxCellScalarValues(sgasScalarSetIndex, timeStepIndex, sgasMin, sgasMax); - } - else - { - gridCellResults->cellResults()->minMaxCellScalarValues(sgasScalarSetIndex, sgasMin, sgasMax); - } - } - else + if (dataAccessObjectSgas.isNull()) { dataAccessObjectSgas = new ScalarDataAccessZeroForAllCells; } cvf::ref dataAccessObjectSwat = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, swatScalarSetIndex); - if (dataAccessObjectSwat.notNull()) - { - if (cellResultSlot->legendConfig()->rangeMode() == RimLegendConfig::AUTOMATIC_CURRENT_TIMESTEP) - { - gridCellResults->cellResults()->minMaxCellScalarValues(swatScalarSetIndex, timeStepIndex, swatMin, swatMax); - } - else - { - gridCellResults->cellResults()->minMaxCellScalarValues(swatScalarSetIndex, swatMin, swatMax); - } - } - else + if (dataAccessObjectSwat.isNull()) { dataAccessObjectSwat = new ScalarDataAccessZeroForAllCells; } diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 4e0d185f37..1b265e3dd2 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -47,6 +47,7 @@ ${CEE_CURRENT_LIST_DIR}RimTools.h ${CEE_CURRENT_LIST_DIR}RimFault.h ${CEE_CURRENT_LIST_DIR}RimFaultCollection.h ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.h +${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -92,6 +93,7 @@ ${CEE_CURRENT_LIST_DIR}RimTools.cpp ${CEE_CURRENT_LIST_DIR}RimFault.cpp ${CEE_CURRENT_LIST_DIR}RimFaultCollection.cpp ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.cpp +${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 58e81185a3..6e83c97a77 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -45,6 +45,7 @@ #include "RimCaseCollection.h" #include "RimOilField.h" #include "RimAnalysisModels.h" +#include "RimTernaryLegendConfig.h" #include "RiuMainWindow.h" #include "RigGridBase.h" @@ -232,6 +233,7 @@ void RimReservoirView::updateViewerWidget() RiuMainWindow::instance()->addViewer(m_viewer); m_viewer->setMinNearPlaneDistance(10); this->cellResult()->legendConfig->recreateLegend(); + this->cellResult()->ternaryLegendConfig->recreateLegend(); this->cellEdgeResult()->legendConfig->recreateLegend(); m_viewer->setColorLegend1(this->cellResult()->legendConfig->legend()); m_viewer->setColorLegend2(this->cellEdgeResult()->legendConfig->legend()); @@ -1448,21 +1450,55 @@ void RimReservoirView::updateLegends() this->cellEdgeResult()->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); } - if (m_ternarySaturationOverlayItem.notNull()) - { - viewer()->removeOverlayItem(m_ternarySaturationOverlayItem.p()); - } + + viewer()->removeOverlayItem(this->cellResult()->ternaryLegendConfig->legend()); if (this->cellResult()->isTernarySaturationSelected()) { - if (m_ternarySaturationOverlayItem.isNull()) + RimReservoirCellResultsStorage* gridCellResults = this->cellResult()->currentGridCellResults(); { - cvf::Font* standardFont = RiaApplication::instance()->standardFont(); - m_ternarySaturationOverlayItem = new RivTernarySaturationOverlayItem(standardFont); - m_ternarySaturationOverlayItem->setLayout(cvf::OverlayItem::VERTICAL, cvf::OverlayItem::BOTTOM_LEFT); + double globalMin = 0.0; + double globalMax = 1.0; + double localMin = 0.0; + double localMax = 1.0; + + size_t scalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL"); + results->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); + results->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); + + this->cellResult()->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SOIL_IDX, globalMin, globalMax, localMin, localMax); } - viewer()->addOverlayItem(m_ternarySaturationOverlayItem.p()); + { + double globalMin = 0.0; + double globalMax = 1.0; + double localMin = 0.0; + double localMax = 1.0; + + size_t scalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SGAS"); + results->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); + results->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); + + this->cellResult()->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SGAS_IDX, globalMin, globalMax, localMin, localMax); + } + + { + double globalMin = 0.0; + double globalMax = 1.0; + double localMin = 0.0; + double localMax = 1.0; + + size_t scalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SWAT"); + results->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); + results->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); + + this->cellResult()->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SWAT_IDX, globalMin, globalMax, localMin, localMax); + } + + if (this->cellResult()->ternaryLegendConfig->legend()) + { + viewer()->addOverlayItem(this->cellResult()->ternaryLegendConfig->legend()); + } } } diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 955eeada1b..a45a6c2e1d 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -201,8 +201,6 @@ private: cvf::ref m_reservoirGridPartManager; cvf::ref m_pipesPartManager; - cvf::ref m_ternarySaturationOverlayItem; - // Overridden PDM methods: public: virtual caf::PdmFieldHandle* userDescriptionField() { return &name; } diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp index e7bdec4640..7c5b888179 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp @@ -36,6 +36,7 @@ #include "Rim3dOverlayInfoConfig.h" #include "RimReservoirCellResultsCacher.h" +#include "RimTernaryLegendConfig.h" CAF_PDM_SOURCE_INIT(RimResultSlot, "ResultSlot"); @@ -51,6 +52,9 @@ RimResultSlot::RimResultSlot() m_legendConfigData.setUiHidden(true); m_legendConfigData.setUiChildrenHidden(true); + CAF_PDM_InitFieldNoDefault(&ternaryLegendConfig, "TernaryLegendDefinition", "Ternary Legend Definition", "", "", ""); + ternaryLegendConfig = new RimTernaryLegendConfig(); + legendConfig = new RimLegendConfig(); } @@ -60,6 +64,7 @@ RimResultSlot::RimResultSlot() RimResultSlot::~RimResultSlot() { delete legendConfig(); + delete ternaryLegendConfig(); } //-------------------------------------------------------------------------------------------------- @@ -91,36 +96,52 @@ void RimResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, co //-------------------------------------------------------------------------------------------------- void RimResultSlot::changeLegendConfig(QString resultVarNameOfNewLegend) { - if (this->legendConfig()->resultVariableName() == resultVarNameOfNewLegend) return; - - std::list >::iterator it; - bool found = false; - for (it = m_legendConfigData.v().begin(); it != m_legendConfigData.v().end(); ++it) + if (resultVarNameOfNewLegend == RimDefines::ternarySaturationResultName()) { - if ((*it)->resultVariableName() == resultVarNameOfNewLegend) + this->ternaryLegendConfig.setUiHidden(false); + this->ternaryLegendConfig.setUiChildrenHidden(false); + this->legendConfig.setUiHidden(true); + this->legendConfig.setUiChildrenHidden(true); + } + else + { + this->ternaryLegendConfig.setUiHidden(true); + this->ternaryLegendConfig.setUiChildrenHidden(true); + + if (this->legendConfig()->resultVariableName() != resultVarNameOfNewLegend) { - RimLegendConfig* newLegend = *it; + std::list >::iterator it; + bool found = false; + for (it = m_legendConfigData.v().begin(); it != m_legendConfigData.v().end(); ++it) + { + if ((*it)->resultVariableName() == resultVarNameOfNewLegend) + { + RimLegendConfig* newLegend = *it; - m_legendConfigData.v().erase(it); - m_legendConfigData.v().push_back(this->legendConfig()); - this->legendConfig = newLegend; - RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); - found = true; - break; + m_legendConfigData.v().erase(it); + m_legendConfigData.v().push_back(this->legendConfig()); + this->legendConfig = newLegend; + found = true; + break; + } + } + + // Not found ? + if (!found) + { + RimLegendConfig* newLegend = new RimLegendConfig; + newLegend->setReservoirView(m_reservoirView); + newLegend->resultVariableName = resultVarNameOfNewLegend; + m_legendConfigData.v().push_back(this->legendConfig()); + this->legendConfig = newLegend; + } } + + this->legendConfig.setUiHidden(false); + this->legendConfig.setUiChildrenHidden(false); } - // Not found ? - if (!found) - { - RimLegendConfig* newLegend = new RimLegendConfig; - newLegend->setReservoirView(m_reservoirView); - newLegend->resultVariableName = resultVarNameOfNewLegend; - m_legendConfigData.v().push_back(this->legendConfig()); - this->legendConfig = newLegend; - RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); - - } + RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); } //-------------------------------------------------------------------------------------------------- @@ -134,6 +155,8 @@ void RimResultSlot::initAfterRead() { this->legendConfig()->resultVariableName = this->resultVariable(); } + + changeLegendConfig(this->resultVariable()); } //-------------------------------------------------------------------------------------------------- @@ -148,4 +171,7 @@ void RimResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) { (*it)->setReservoirView(ownerReservoirView); } + + if (ternaryLegendConfig) ternaryLegendConfig->setReservoirView(ownerReservoirView); } + diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.h b/ApplicationCode/ProjectDataModel/RimResultSlot.h index 29c91a68f2..97e84ff8b6 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.h @@ -24,6 +24,8 @@ #include "RimDefines.h" #include "RimResultDefinition.h" +class RimTernaryLegendConfig; + //================================================================================================== /// /// @@ -37,6 +39,7 @@ public: virtual void setReservoirView(RimReservoirView* ownerReservoirView); caf::PdmField legendConfig; + caf::PdmField ternaryLegendConfig; // Overridden methods virtual void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ); @@ -46,7 +49,6 @@ protected: private: void changeLegendConfig(QString resultVarNameOfNewLegend); - caf::PdmField > > m_legendConfigData; - + caf::PdmField > > m_legendConfigData; }; diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp new file mode 100644 index 0000000000..77a78b9e6a --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp @@ -0,0 +1,405 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimTernaryLegendConfig.h" + +#include "cafPdmUiPushButtonEditor.h" +#include "cafPdmUiTextEditor.h" + +#include "RiaApplication.h" +#include "RimReservoirView.h" + +#include "RivTernarySaturationOverlayItem.h" + + +CAF_PDM_SOURCE_INIT(RimTernaryLegendConfig, "RimTernaryLegendConfig"); + +namespace caf { + template<> + void AppEnum::setUp() + { + addItem(RimTernaryLegendConfig::AUTOMATIC_ALLTIMESTEPS, "AUTOMATIC_ALLTIMESTEPS", "Global range"); + addItem(RimTernaryLegendConfig::AUTOMATIC_CURRENT_TIMESTEP,"AUTOMATIC_CURRENT_TIMESTEP", "Local range"); + addItem(RimTernaryLegendConfig::USER_DEFINED, "USER_DEFINED_MAX_MIN", "User defined range"); + setDefault(RimTernaryLegendConfig::AUTOMATIC_ALLTIMESTEPS); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimTernaryLegendConfig::RimTernaryLegendConfig() +{ + CAF_PDM_InitObject("Ternary Legend Definition", ":/Legend.png", "", ""); + + CAF_PDM_InitField(&precision, "Precision", 2, "Significant digits", "", "The number of significant digits displayed in the legend numbers",""); + CAF_PDM_InitField(&rangeMode, "RangeType", RangeModeEnum(USER_DEFINED), "Range type", "", "Switches between automatic and user defined range on the legend", ""); + + CAF_PDM_InitFieldNoDefault(&applyLocalMinMax, "m_applyLocalMinMax", "", "", "", ""); + applyLocalMinMax.setIOWritable(false); + applyLocalMinMax.setIOReadable(false); + applyLocalMinMax.setUiEditorTypeName(caf::PdmUiPushButtonEditor::uiEditorTypeName()); + applyLocalMinMax.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + applyLocalMinMax = false; + + CAF_PDM_InitFieldNoDefault(&applyGlobalMinMax, "m_applyGlobalMinMax", "", "", "", ""); + applyGlobalMinMax.setIOWritable(false); + applyGlobalMinMax.setIOReadable(false); + applyGlobalMinMax.setUiEditorTypeName(caf::PdmUiPushButtonEditor::uiEditorTypeName()); + applyGlobalMinMax.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + applyGlobalMinMax = false; + + CAF_PDM_InitFieldNoDefault(&applyFullRangeMinMax, "m_applyFullRangeMinMax", "", "", "", ""); + applyFullRangeMinMax.setIOWritable(false); + applyFullRangeMinMax.setIOReadable(false); + applyFullRangeMinMax.setUiEditorTypeName(caf::PdmUiPushButtonEditor::uiEditorTypeName()); + applyFullRangeMinMax.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + applyFullRangeMinMax = false; + + CAF_PDM_InitFieldNoDefault(&ternaryRangeSummary, "ternaryRangeSummary", "Range summary", "", "", ""); + ternaryRangeSummary.setUiEditorTypeName(caf::PdmUiTextEditor::uiEditorTypeName()); + ternaryRangeSummary.setUiLabelPosition(caf::PdmUiItemInfo::TOP); + + + CAF_PDM_InitField(&userDefinedMaxValueSoil, "UserDefinedMaxSoil", 1.0, "Max", "", "Min value of the legend", ""); + CAF_PDM_InitField(&userDefinedMinValueSoil, "UserDefinedMinSoil", 0.0, "Min", "", "Max value of the legend", ""); + + CAF_PDM_InitField(&userDefinedMaxValueSgas, "UserDefinedMaxSgas", 1.0, "Max", "", "Min value of the legend", ""); + CAF_PDM_InitField(&userDefinedMinValueSgas, "UserDefinedMinSgas", 0.0, "Min", "", "Max value of the legend", ""); + + CAF_PDM_InitField(&userDefinedMaxValueSwat, "UserDefinedMaxSwat", 1.0, "Max", "", "Min value of the legend", ""); + CAF_PDM_InitField(&userDefinedMinValueSwat, "UserDefinedMinSwat", 0.0, "Min", "", "Max value of the legend", ""); + + m_globalAutoMin.resize(3, 0.0); + m_globalAutoMax.resize(3, 1.0); + m_localAutoMin.resize(3, 0.0); + m_localAutoMax.resize(3, 1.0); + + recreateLegend(); + updateLegend(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimTernaryLegendConfig::~RimTernaryLegendConfig() +{ + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTernaryLegendConfig::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +{ + if (changedField == &applyLocalMinMax) + { + userDefinedMaxValueSoil = m_localAutoMax[TERNARY_SOIL_IDX]; + userDefinedMinValueSoil = m_localAutoMin[TERNARY_SOIL_IDX]; + userDefinedMaxValueSgas = m_localAutoMax[TERNARY_SGAS_IDX]; + userDefinedMinValueSgas = m_localAutoMin[TERNARY_SGAS_IDX]; + userDefinedMaxValueSwat = m_localAutoMax[TERNARY_SWAT_IDX]; + userDefinedMinValueSwat = m_localAutoMin[TERNARY_SWAT_IDX]; + + applyLocalMinMax = false; + } + else if (changedField == &applyGlobalMinMax) + { + userDefinedMaxValueSoil = m_globalAutoMax[TERNARY_SOIL_IDX]; + userDefinedMinValueSoil = m_globalAutoMin[TERNARY_SOIL_IDX]; + userDefinedMaxValueSgas = m_globalAutoMax[TERNARY_SGAS_IDX]; + userDefinedMinValueSgas = m_globalAutoMin[TERNARY_SGAS_IDX]; + userDefinedMaxValueSwat = m_globalAutoMax[TERNARY_SWAT_IDX]; + userDefinedMinValueSwat = m_globalAutoMin[TERNARY_SWAT_IDX]; + + applyGlobalMinMax = false; + } + else if (changedField == &applyFullRangeMinMax) + { + userDefinedMaxValueSoil = 1.0; + userDefinedMinValueSoil = 0.0; + userDefinedMaxValueSgas = 1.0; + userDefinedMinValueSgas = 0.0; + userDefinedMaxValueSwat = 1.0; + userDefinedMinValueSwat = 0.0; + + applyFullRangeMinMax = false; + } + + updateLabelText(); + updateLegend(); + + if (m_reservoirView) m_reservoirView->updateCurrentTimeStepAndRedraw(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTernaryLegendConfig::updateLegend() +{ + // TODO: Update text on ternary legend +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTernaryLegendConfig::setAutomaticRanges(TernaryArrayIndex ternaryIndex, double globalMin, double globalMax, double localMin, double localMax) +{ + double candidateGlobalAutoMin = roundToNumSignificantDigits(globalMin, precision); + double candidateGlobalAutoMax = roundToNumSignificantDigits(globalMax, precision); + + double candidateLocalAutoMin = roundToNumSignificantDigits(localMin, precision); + double candidateLocalAutoMax = roundToNumSignificantDigits(localMax, precision); + + m_globalAutoMin[ternaryIndex] = candidateGlobalAutoMin; + m_globalAutoMax[ternaryIndex] = candidateGlobalAutoMax; + m_localAutoMin[ternaryIndex] = candidateLocalAutoMin; + m_localAutoMax[ternaryIndex] = candidateLocalAutoMax; + + updateLabelText(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTernaryLegendConfig::recreateLegend() +{ + // Due to possible visualization bug, we need to recreate the legend if the last viewer + // has been removed, (and thus the opengl resources has been deleted) The text in + // the legend disappeared because of this, so workaround: recreate the legend when needed: + + cvf::Font* standardFont = RiaApplication::instance()->standardFont(); + m_legend = new RivTernarySaturationOverlayItem(standardFont); + m_legend->setLayout(cvf::OverlayItem::VERTICAL, cvf::OverlayItem::BOTTOM_LEFT); + + updateLegend(); +} + +//-------------------------------------------------------------------------------------------------- +/// Rounding the double value to given number of significant digits +//-------------------------------------------------------------------------------------------------- +double RimTernaryLegendConfig::roundToNumSignificantDigits(double domainValue, double numSignificantDigits) +{ + double absDomainValue = cvf::Math::abs(domainValue); + if (absDomainValue == 0.0) + { + return 0.0; + } + + double logDecValue = log10(absDomainValue); + logDecValue = cvf::Math::ceil(logDecValue); + + double factor = pow(10.0, numSignificantDigits - logDecValue); + + double tmp = domainValue * factor; + double integerPart; + double fraction = modf(tmp, &integerPart); + + if (cvf::Math::abs(fraction)>= 0.5) (integerPart >= 0) ? integerPart++: integerPart-- ; + + double newDomainValue = integerPart / factor; + + return newDomainValue; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTernaryLegendConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ + caf::PdmUiOrdering* formatGr = uiOrdering.addNewGroup("Format"); + formatGr->add(&precision); + formatGr->add(&rangeMode); + + if (rangeMode == USER_DEFINED) + { + caf::PdmUiOrdering* ternaryGroupContainer = uiOrdering.addNewGroup("Ternary "); + { + caf::PdmUiOrdering* ternaryGroup = ternaryGroupContainer->addNewGroup("SOIL"); + ternaryGroup->add(&userDefinedMinValueSoil); + ternaryGroup->add(&userDefinedMaxValueSoil); + } + + { + caf::PdmUiOrdering* ternaryGroup = ternaryGroupContainer->addNewGroup("SGAS"); + ternaryGroup->add(&userDefinedMinValueSgas); + ternaryGroup->add(&userDefinedMaxValueSgas); + } + + { + caf::PdmUiOrdering* ternaryGroup = ternaryGroupContainer->addNewGroup("SWAT"); + ternaryGroup->add(&userDefinedMinValueSwat); + ternaryGroup->add(&userDefinedMaxValueSwat); + } + + ternaryGroupContainer->add(&applyLocalMinMax); + ternaryGroupContainer->add(&applyGlobalMinMax); + ternaryGroupContainer->add(&applyFullRangeMinMax); + } + else + { + caf::PdmUiOrdering* group = uiOrdering.addNewGroup("Summary"); + group->add(&ternaryRangeSummary); + } + + uiOrdering.setForgetRemainingFields(true); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::OverlayItem* RimTernaryLegendConfig::legend() +{ + return m_legend.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTernaryLegendConfig::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) +{ + if (&applyLocalMinMax == field) + { + caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast (attribute); + if (attrib) + { + attrib->m_buttonText = "Apply local min/max values"; + } + } + else if (&applyGlobalMinMax == field) + { + caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast (attribute); + if (attrib) + { + attrib->m_buttonText = "Apply global min/max values"; + } + } + else if (&applyFullRangeMinMax == field) + { + caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast (attribute); + if (attrib) + { + attrib->m_buttonText = "Apply full range"; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTernaryLegendConfig::ternaryRanges(double& soilLower, double& soilUpper, double& sgasLower, double& sgasUpper, double& swatLower, double& swatUpper) const +{ + if (rangeMode() == AUTOMATIC_CURRENT_TIMESTEP) + { + soilLower = m_localAutoMin[TERNARY_SOIL_IDX]; + soilUpper = m_localAutoMax[TERNARY_SOIL_IDX]; + sgasLower = m_localAutoMin[TERNARY_SGAS_IDX]; + sgasUpper = m_localAutoMax[TERNARY_SGAS_IDX]; + swatLower = m_localAutoMin[TERNARY_SWAT_IDX]; + swatUpper = m_localAutoMax[TERNARY_SWAT_IDX]; + } + else if (rangeMode() == AUTOMATIC_ALLTIMESTEPS) + { + soilLower = m_globalAutoMin[TERNARY_SOIL_IDX]; + soilUpper = m_globalAutoMax[TERNARY_SOIL_IDX]; + sgasLower = m_globalAutoMin[TERNARY_SGAS_IDX]; + sgasUpper = m_globalAutoMax[TERNARY_SGAS_IDX]; + swatLower = m_globalAutoMin[TERNARY_SWAT_IDX]; + swatUpper = m_globalAutoMax[TERNARY_SWAT_IDX]; + } + else + { + soilLower = userDefinedMinValueSoil; + soilUpper = userDefinedMaxValueSoil; + sgasLower = userDefinedMinValueSgas; + sgasUpper = userDefinedMaxValueSgas; + swatLower = userDefinedMinValueSwat; + swatUpper = userDefinedMaxValueSwat; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTernaryLegendConfig::updateLabelText() +{ + { + userDefinedMinValueSoil.setUiName("Min"); + userDefinedMaxValueSoil.setUiName("Max"); + + if (m_globalAutoMin[TERNARY_SOIL_IDX] != cvf::UNDEFINED_DOUBLE ) + { + userDefinedMinValueSoil.setUiName(QString("Min ") + "(" + QString::number(m_globalAutoMin[TERNARY_SOIL_IDX], 'g', precision) + ")"); + } + + if (m_globalAutoMax[TERNARY_SOIL_IDX] != cvf::UNDEFINED_DOUBLE ) + { + userDefinedMaxValueSoil.setUiName(QString("Max ") + "(" + QString::number(m_globalAutoMax[TERNARY_SOIL_IDX], 'g', precision) + ")"); + } + } + + { + userDefinedMinValueSgas.setUiName("Min"); + userDefinedMaxValueSgas.setUiName("Max"); + + if (m_globalAutoMin[TERNARY_SGAS_IDX] != cvf::UNDEFINED_DOUBLE ) + { + userDefinedMinValueSgas.setUiName(QString("Min ") + "(" + QString::number(m_globalAutoMin[TERNARY_SGAS_IDX], 'g', precision) + ")"); + } + + if (m_globalAutoMax[TERNARY_SGAS_IDX] != cvf::UNDEFINED_DOUBLE ) + { + userDefinedMaxValueSgas.setUiName(QString("Max ") + "(" + QString::number(m_globalAutoMax[TERNARY_SGAS_IDX], 'g', precision) + ")"); + } + } + + { + userDefinedMinValueSwat.setUiName("Min"); + userDefinedMaxValueSwat.setUiName("Max"); + + if (m_globalAutoMin[TERNARY_SWAT_IDX] != cvf::UNDEFINED_DOUBLE ) + { + userDefinedMinValueSwat.setUiName(QString("Min ") + "(" + QString::number(m_globalAutoMin[TERNARY_SWAT_IDX], 'g', precision) + ")"); + } + + if (m_globalAutoMax[TERNARY_SWAT_IDX] != cvf::UNDEFINED_DOUBLE ) + { + userDefinedMaxValueSwat.setUiName(QString("Max ") + "(" + QString::number(m_globalAutoMax[TERNARY_SWAT_IDX], 'g', precision) + ")"); + } + } + + if (rangeMode == AUTOMATIC_ALLTIMESTEPS) + { + QString tmpString; + tmpString = QString("SOIL : ") + QString::number(m_globalAutoMin[TERNARY_SOIL_IDX], 'g', precision) + " - " + QString::number(m_globalAutoMax[TERNARY_SOIL_IDX], 'g', precision) + "\n"; + tmpString += QString("SGAS : ") + QString::number(m_globalAutoMin[TERNARY_SGAS_IDX], 'g', precision) + " - " + QString::number(m_globalAutoMax[TERNARY_SGAS_IDX], 'g', precision) + "\n"; + tmpString += QString("SWAT : ") + QString::number(m_globalAutoMin[TERNARY_SWAT_IDX], 'g', precision) + " - " + QString::number(m_globalAutoMax[TERNARY_SWAT_IDX], 'g', precision) + "\n"; + + ternaryRangeSummary = tmpString; + } + else if (rangeMode == AUTOMATIC_CURRENT_TIMESTEP) + { + QString tmpString; + tmpString = QString("SOIL : ") + QString::number(m_localAutoMin[TERNARY_SOIL_IDX], 'g', precision) + " - " + QString::number(m_localAutoMax[TERNARY_SOIL_IDX], 'g', precision) + "\n"; + tmpString += QString("SGAS : ") + QString::number(m_localAutoMin[TERNARY_SGAS_IDX], 'g', precision) + " - " + QString::number(m_localAutoMax[TERNARY_SGAS_IDX], 'g', precision) + "\n"; + tmpString += QString("SWAT : ") + QString::number(m_localAutoMin[TERNARY_SWAT_IDX], 'g', precision) + " - " + QString::number(m_localAutoMax[TERNARY_SWAT_IDX], 'g', precision) + "\n"; + + ternaryRangeSummary = tmpString; + } +} + diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h new file mode 100644 index 0000000000..0e21420d84 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h @@ -0,0 +1,107 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfObject.h" + +#include "cafAppEnum.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" + +class RimReservoirView; +class RivTernarySaturationOverlayItem; + +namespace cvf +{ + class OverlayItem; +} + + + +//================================================================================================== +/// +/// +//================================================================================================== +class RimTernaryLegendConfig : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + enum TernaryArrayIndex + { + TERNARY_SOIL_IDX = 0, + TERNARY_SGAS_IDX, + TERNARY_SWAT_IDX + }; + + enum RangeModeType + { + AUTOMATIC_ALLTIMESTEPS, + AUTOMATIC_CURRENT_TIMESTEP, + USER_DEFINED + }; + typedef caf::AppEnum RangeModeEnum; + +public: + RimTernaryLegendConfig(); + virtual ~RimTernaryLegendConfig(); + + void setReservoirView(RimReservoirView* ownerReservoirView) {m_reservoirView = ownerReservoirView; } + + void setAutomaticRanges(TernaryArrayIndex ternaryIndex, double globalMin, double globalMax, double localMin, double localMax); + void ternaryRanges(double& soilLower, double& soilUpper, double& sgasLower, double& sgasUpper, double& swatLower, double& swatUpper) const; + + void recreateLegend(); + cvf::OverlayItem* legend(); + +protected: + virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); + virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering ); + virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute); + +private: + void updateLegend(); + void updateLabelText(); + double roundToNumSignificantDigits(double value, double precision); + + +private: + caf::PdmField precision; + caf::PdmField rangeMode; + + caf::PdmField userDefinedMaxValueSoil; + caf::PdmField userDefinedMinValueSoil; + caf::PdmField userDefinedMaxValueSgas; + caf::PdmField userDefinedMinValueSgas; + caf::PdmField userDefinedMaxValueSwat; + caf::PdmField userDefinedMinValueSwat; + + caf::PdmField applyLocalMinMax; + caf::PdmField applyGlobalMinMax; + caf::PdmField applyFullRangeMinMax; + caf::PdmField ternaryRangeSummary; + + std::vector m_globalAutoMax; + std::vector m_globalAutoMin; + std::vector m_localAutoMax; + std::vector m_localAutoMin; + + caf::PdmPointer m_reservoirView; + cvf::ref m_legend; +};