mirror of
https://github.com/OPM/ResInsight.git
synced 2025-01-24 15:26:48 -06:00
840 lines
31 KiB
C++
840 lines
31 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2011- Statoil ASA
|
|
// Copyright (C) 2013- Ceetron Solutions AS
|
|
// Copyright (C) 2011-2012 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 <http://www.gnu.org/licenses/gpl.html>
|
|
// for more details.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "RimLegendConfig.h"
|
|
|
|
#include "RiaApplication.h"
|
|
#include "RiaColorTables.h"
|
|
|
|
#include "RimCellEdgeColors.h"
|
|
#include "RimEclipseCellColors.h"
|
|
#include "RimEclipseView.h"
|
|
#include "RimGeoMechResultDefinition.h"
|
|
#include "RimStimPlanColors.h"
|
|
#include "RimViewLinker.h"
|
|
|
|
#include "cafCategoryLegend.h"
|
|
#include "cafCategoryMapper.h"
|
|
|
|
#include "cafFactory.h"
|
|
#include "cafPdmFieldCvfColor.h"
|
|
#include "cafPdmFieldCvfMat4d.h"
|
|
#include "cafPdmUiComboBoxEditor.h"
|
|
#include "cafPdmUiLineEditor.h"
|
|
|
|
#include "cvfOverlayScalarMapperLegend.h"
|
|
#include "cvfScalarMapperContinuousLinear.h"
|
|
#include "cvfScalarMapperContinuousLog.h"
|
|
#include "cvfScalarMapperDiscreteLinear.h"
|
|
#include "cvfScalarMapperDiscreteLog.h"
|
|
#include "cvfqtUtils.h"
|
|
|
|
#include <cmath>
|
|
|
|
|
|
CAF_PDM_SOURCE_INIT(RimLegendConfig, "Legend");
|
|
|
|
namespace caf {
|
|
template<>
|
|
void AppEnum<RimLegendConfig::RangeModeType>::setUp()
|
|
{
|
|
addItem(RimLegendConfig::AUTOMATIC_ALLTIMESTEPS, "AUTOMATIC_ALLTIMESTEPS", "All Timesteps");
|
|
addItem(RimLegendConfig::AUTOMATIC_CURRENT_TIMESTEP,"AUTOMATIC_CURRENT_TIMESTEP", "Current Timestep");
|
|
addItem(RimLegendConfig::USER_DEFINED, "USER_DEFINED_MAX_MIN", "User Defined Range");
|
|
setDefault(RimLegendConfig::AUTOMATIC_ALLTIMESTEPS);
|
|
}
|
|
}
|
|
|
|
namespace caf {
|
|
template<>
|
|
void RimLegendConfig::ColorRangeEnum::setUp()
|
|
{
|
|
addItem(RimLegendConfig::NORMAL, "NORMAL", "Full color, Red on top");
|
|
addItem(RimLegendConfig::OPPOSITE_NORMAL,"OPPOSITE_NORMAL", "Full color, Blue on top");
|
|
addItem(RimLegendConfig::WHITE_PINK, "WHITE_PIMK", "White to pink");
|
|
addItem(RimLegendConfig::PINK_WHITE, "PINK_WHITE", "Pink to white");
|
|
addItem(RimLegendConfig::BLUE_WHITE_RED, "BLUE_WHITE_RED", "Blue, white, red");
|
|
addItem(RimLegendConfig::RED_WHITE_BLUE, "RED_WHITE_BLUE", "Red, white, blue");
|
|
addItem(RimLegendConfig::WHITE_BLACK, "WHITE_BLACK", "White to black");
|
|
addItem(RimLegendConfig::BLACK_WHITE, "BLACK_WHITE", "Black to white");
|
|
addItem(RimLegendConfig::CATEGORY, "CATEGORY", "Category colors");
|
|
addItem(RimLegendConfig::ANGULAR, "ANGULAR", "Full color cyclic");
|
|
addItem(RimLegendConfig::STIMPLAN, "STIMPLAN", "StimPlan colors");
|
|
setDefault(RimLegendConfig::NORMAL);
|
|
}
|
|
}
|
|
|
|
namespace caf {
|
|
template<>
|
|
void RimLegendConfig::MappingEnum::setUp()
|
|
{
|
|
addItem(RimLegendConfig::LINEAR_DISCRETE, "LinearDiscrete", "Discrete Linear");
|
|
addItem(RimLegendConfig::LINEAR_CONTINUOUS, "LinearContinuous", "Continuous Linear");
|
|
addItem(RimLegendConfig::LOG10_CONTINUOUS, "Log10Continuous", "Continuous Logarithmic");
|
|
addItem(RimLegendConfig::LOG10_DISCRETE, "Log10Discrete", "Discrete Logarithmic");
|
|
addItem(RimLegendConfig::CATEGORY_INTEGER, "Category", "Category");
|
|
setDefault(RimLegendConfig::LINEAR_CONTINUOUS);
|
|
}
|
|
}
|
|
|
|
namespace caf {
|
|
template<>
|
|
void AppEnum<RimLegendConfig::NumberFormatType>::setUp()
|
|
{
|
|
addItem( RimLegendConfig::AUTO, "AUTO", "Automatic");
|
|
addItem( RimLegendConfig::FIXED, "FIXED", "Fixed, decimal");
|
|
addItem( RimLegendConfig::SCIENTIFIC, "SCIENTIFIC", "Scientific notation");
|
|
setDefault(RimLegendConfig::FIXED);
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimLegendConfig::RimLegendConfig()
|
|
: m_globalAutoMax(cvf::UNDEFINED_DOUBLE),
|
|
m_globalAutoMin(cvf::UNDEFINED_DOUBLE),
|
|
m_localAutoMax(cvf::UNDEFINED_DOUBLE),
|
|
m_localAutoMin(cvf::UNDEFINED_DOUBLE),
|
|
m_globalAutoPosClosestToZero(0),
|
|
m_globalAutoNegClosestToZero(0),
|
|
m_localAutoPosClosestToZero(0),
|
|
m_localAutoNegClosestToZero(0),
|
|
m_isAllTimeStepsRangeDisabled(false)
|
|
{
|
|
CAF_PDM_InitObject("Legend Definition", ":/Legend.png", "", "");
|
|
CAF_PDM_InitField(&m_numLevels, "NumberOfLevels", 8, "Number of levels", "", "A hint on how many tick marks you whish.","");
|
|
CAF_PDM_InitField(&m_precision, "Precision", 4, "Significant digits", "", "The number of significant digits displayed in the legend numbers","");
|
|
CAF_PDM_InitField(&m_tickNumberFormat, "TickNumberFormat", caf::AppEnum<RimLegendConfig::NumberFormatType>(FIXED), "Number format", "", "","");
|
|
|
|
CAF_PDM_InitField(&m_colorRangeMode, "ColorRangeMode", ColorRangeEnum(NORMAL) , "Colors", "", "", "");
|
|
CAF_PDM_InitField(&m_mappingMode, "MappingMode", MappingEnum(LINEAR_CONTINUOUS) , "Mapping", "", "", "");
|
|
CAF_PDM_InitField(&m_rangeMode, "RangeType", RangeModeEnum(AUTOMATIC_ALLTIMESTEPS), "Range type", "", "Switches between automatic and user defined range on the legend", "");
|
|
CAF_PDM_InitField(&m_userDefinedMaxValue, "UserDefinedMax", 1.0, "Max", "", "Min value of the legend", "");
|
|
CAF_PDM_InitField(&m_userDefinedMinValue, "UserDefinedMin", 0.0, "Min", "", "Max value of the legend", "");
|
|
CAF_PDM_InitField(&resultVariableName, "ResultVariableUsage", QString(""), "", "", "", "");
|
|
resultVariableName.uiCapability()->setUiHidden(true);
|
|
|
|
m_linDiscreteScalarMapper = new cvf::ScalarMapperDiscreteLinear;
|
|
m_logDiscreteScalarMapper = new cvf::ScalarMapperDiscreteLog;
|
|
m_linSmoothScalarMapper = new cvf::ScalarMapperContinuousLinear;
|
|
m_logSmoothScalarMapper = new cvf::ScalarMapperContinuousLog;
|
|
|
|
m_currentScalarMapper = m_linDiscreteScalarMapper;
|
|
|
|
m_categoryMapper = new caf::CategoryMapper;
|
|
|
|
cvf::Font* standardFont = RiaApplication::instance()->standardFont();
|
|
m_scalarMapperLegend = new cvf::OverlayScalarMapperLegend(standardFont);
|
|
m_categoryLegend = new caf::CategoryLegend(standardFont, m_categoryMapper.p());
|
|
|
|
updateFieldVisibility();
|
|
updateLegend();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimLegendConfig::~RimLegendConfig()
|
|
{
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
|
|
{
|
|
if (changedField == &m_numLevels)
|
|
{
|
|
int upperLimit = std::numeric_limits<int>::max();
|
|
m_numLevels = cvf::Math::clamp(m_numLevels.v(), 1, upperLimit);
|
|
}
|
|
else if (changedField == &m_rangeMode ||
|
|
changedField == &m_mappingMode)
|
|
{
|
|
if (m_rangeMode == USER_DEFINED)
|
|
{
|
|
if (m_userDefinedMaxValue == m_userDefinedMaxValue.defaultValue() && m_globalAutoMax != cvf::UNDEFINED_DOUBLE)
|
|
{
|
|
m_userDefinedMaxValue = roundToNumSignificantDigits(m_globalAutoMax, m_precision);
|
|
}
|
|
if (m_userDefinedMinValue == m_userDefinedMinValue.defaultValue() && m_globalAutoMin != cvf::UNDEFINED_DOUBLE)
|
|
{
|
|
m_userDefinedMinValue = roundToNumSignificantDigits(m_globalAutoMin, m_precision);
|
|
}
|
|
}
|
|
|
|
updateFieldVisibility();
|
|
}
|
|
|
|
updateLegend();
|
|
|
|
RimView* view = nullptr;
|
|
this->firstAncestorOrThisOfType(view);
|
|
|
|
if (view)
|
|
{
|
|
RimViewLinker* viewLinker = view->assosiatedViewLinker();
|
|
if (viewLinker)
|
|
{
|
|
viewLinker->updateCellResult();
|
|
}
|
|
|
|
view->updateCurrentTimeStepAndRedraw();
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::updateLegend()
|
|
{
|
|
double adjustedMin = cvf::UNDEFINED_DOUBLE;
|
|
double adjustedMax = cvf::UNDEFINED_DOUBLE;
|
|
|
|
double posClosestToZero = cvf::UNDEFINED_DOUBLE;
|
|
double negClosestToZero = cvf::UNDEFINED_DOUBLE;
|
|
|
|
if (m_rangeMode == AUTOMATIC_ALLTIMESTEPS)
|
|
{
|
|
adjustedMin = roundToNumSignificantDigits(m_globalAutoMin, m_precision);
|
|
adjustedMax = roundToNumSignificantDigits(m_globalAutoMax, m_precision);
|
|
|
|
posClosestToZero = m_globalAutoPosClosestToZero;
|
|
negClosestToZero = m_globalAutoNegClosestToZero;
|
|
}
|
|
else if (m_rangeMode == AUTOMATIC_CURRENT_TIMESTEP)
|
|
{
|
|
adjustedMin = roundToNumSignificantDigits(m_localAutoMin, m_precision);
|
|
adjustedMax = roundToNumSignificantDigits(m_localAutoMax, m_precision);
|
|
|
|
posClosestToZero = m_localAutoPosClosestToZero;
|
|
negClosestToZero = m_localAutoNegClosestToZero;
|
|
}
|
|
else
|
|
{
|
|
adjustedMin = roundToNumSignificantDigits(m_userDefinedMinValue, m_precision);
|
|
adjustedMax = roundToNumSignificantDigits(m_userDefinedMaxValue, m_precision);
|
|
|
|
posClosestToZero = m_globalAutoPosClosestToZero;
|
|
negClosestToZero = m_globalAutoNegClosestToZero;
|
|
}
|
|
|
|
m_linDiscreteScalarMapper->setRange(adjustedMin, adjustedMax);
|
|
m_linSmoothScalarMapper->setRange(adjustedMin, adjustedMax);
|
|
|
|
if (m_mappingMode == LOG10_CONTINUOUS || m_mappingMode == LOG10_DISCRETE)
|
|
{
|
|
if (adjustedMin != adjustedMax)
|
|
{
|
|
if (adjustedMin == 0)
|
|
{
|
|
if (adjustedMax > adjustedMin)
|
|
{
|
|
adjustedMin = posClosestToZero;
|
|
}
|
|
else
|
|
{
|
|
adjustedMin = negClosestToZero;
|
|
}
|
|
}
|
|
else if (adjustedMax == 0)
|
|
{
|
|
if (adjustedMin > adjustedMax)
|
|
{
|
|
adjustedMax = posClosestToZero;
|
|
}
|
|
else
|
|
{
|
|
adjustedMax = negClosestToZero;
|
|
}
|
|
}
|
|
else if (adjustedMin < 0 && adjustedMax > 0)
|
|
{
|
|
adjustedMin = posClosestToZero;
|
|
}
|
|
else if (adjustedMax < 0 && adjustedMin > 0)
|
|
{
|
|
adjustedMin = negClosestToZero;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_logDiscreteScalarMapper->setRange(adjustedMin, adjustedMax);
|
|
m_logSmoothScalarMapper->setRange(adjustedMin, adjustedMax);
|
|
|
|
cvf::Color3ubArray legendColors = colorArrayFromColorType(m_colorRangeMode());
|
|
|
|
m_linDiscreteScalarMapper->setColors(legendColors);
|
|
m_logDiscreteScalarMapper->setColors(legendColors);
|
|
m_logSmoothScalarMapper->setColors(legendColors);
|
|
m_linSmoothScalarMapper->setColors(legendColors);
|
|
|
|
|
|
m_linDiscreteScalarMapper->setLevelCount(m_numLevels, true);
|
|
m_logDiscreteScalarMapper->setLevelCount(m_numLevels, true);
|
|
m_logSmoothScalarMapper->setLevelCount(m_numLevels, true);
|
|
m_linSmoothScalarMapper->setLevelCount(m_numLevels, true);
|
|
|
|
switch(m_mappingMode())
|
|
{
|
|
case LINEAR_DISCRETE:
|
|
m_currentScalarMapper = m_linDiscreteScalarMapper.p();
|
|
break;
|
|
case LINEAR_CONTINUOUS:
|
|
m_currentScalarMapper = m_linSmoothScalarMapper.p();
|
|
break;
|
|
case LOG10_CONTINUOUS:
|
|
m_currentScalarMapper = m_logSmoothScalarMapper.p();
|
|
break;
|
|
case LOG10_DISCRETE:
|
|
m_currentScalarMapper = m_logDiscreteScalarMapper.p();
|
|
break;
|
|
case CATEGORY_INTEGER:
|
|
m_categoryMapper->setCategoriesWithNames(m_categories, m_categoryNames);
|
|
|
|
if (m_categoryColors.size() > 0)
|
|
{
|
|
m_categoryMapper->setCycleColors(m_categoryColors);
|
|
}
|
|
else
|
|
{
|
|
m_categoryMapper->setInterpolateColors(legendColors);
|
|
}
|
|
m_currentScalarMapper = m_categoryMapper.p();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (m_currentScalarMapper != m_categoryMapper.p())
|
|
{
|
|
m_scalarMapperLegend->setScalarMapper(m_currentScalarMapper.p());
|
|
}
|
|
double decadesInRange = 0;
|
|
|
|
if (m_mappingMode == LOG10_CONTINUOUS || m_mappingMode == LOG10_DISCRETE)
|
|
{
|
|
// For log mapping, use the min value as reference for num valid digits
|
|
decadesInRange = cvf::Math::abs(adjustedMin) < cvf::Math::abs(adjustedMax) ? cvf::Math::abs(adjustedMin) : cvf::Math::abs(adjustedMax);
|
|
decadesInRange = log10(decadesInRange);
|
|
}
|
|
else
|
|
{
|
|
// For linear mapping, use the max value as reference for num valid digits
|
|
double absRange = CVF_MAX(cvf::Math::abs(adjustedMax), cvf::Math::abs(adjustedMin));
|
|
decadesInRange = log10(absRange);
|
|
}
|
|
|
|
decadesInRange = cvf::Math::ceil(decadesInRange);
|
|
|
|
// Using Fixed format
|
|
NumberFormatType nft = m_tickNumberFormat();
|
|
m_scalarMapperLegend->setTickFormat((cvf::OverlayScalarMapperLegend::NumberFormat)nft);
|
|
|
|
// Set the fixed number of digits after the decimal point to the number needed to show all the significant digits.
|
|
int numDecimalDigits = m_precision();
|
|
if (nft != SCIENTIFIC)
|
|
{
|
|
numDecimalDigits -= static_cast<int>(decadesInRange);
|
|
}
|
|
m_scalarMapperLegend->setTickPrecision(cvf::Math::clamp(numDecimalDigits, 0, 20));
|
|
|
|
|
|
if (m_globalAutoMax != cvf::UNDEFINED_DOUBLE )
|
|
{
|
|
m_userDefinedMaxValue.uiCapability()->setUiName(QString("Max ") + "(" + QString::number(m_globalAutoMax, 'g', m_precision) + ")");
|
|
}
|
|
else
|
|
{
|
|
m_userDefinedMaxValue.uiCapability()->setUiName(QString());
|
|
}
|
|
|
|
if (m_globalAutoMin != cvf::UNDEFINED_DOUBLE )
|
|
{
|
|
m_userDefinedMinValue.uiCapability()->setUiName(QString("Min ") + "(" + QString::number(m_globalAutoMin, 'g', m_precision) + ")");
|
|
}
|
|
else
|
|
{
|
|
m_userDefinedMinValue.uiCapability()->setUiName(QString());
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::disableAllTimeStepsRange(bool doDisable)
|
|
{
|
|
// If we enable AllTimesteps, and we have used current timestep, then "restore" the default
|
|
if (m_isAllTimeStepsRangeDisabled && !doDisable && m_rangeMode == AUTOMATIC_CURRENT_TIMESTEP) m_rangeMode = AUTOMATIC_ALLTIMESTEPS;
|
|
|
|
m_isAllTimeStepsRangeDisabled = doDisable;
|
|
|
|
if (doDisable && m_rangeMode == AUTOMATIC_ALLTIMESTEPS) m_rangeMode = AUTOMATIC_CURRENT_TIMESTEP;
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::setAutomaticRanges(double globalMin, double globalMax, double localMin, double localMax)
|
|
{
|
|
double candidateGlobalAutoMin = roundToNumSignificantDigits(globalMin, m_precision);
|
|
double candidateGlobalAutoMax = roundToNumSignificantDigits(globalMax, m_precision);
|
|
|
|
double candidateLocalAutoMin = roundToNumSignificantDigits(localMin, m_precision);
|
|
double candidateLocalAutoMax = roundToNumSignificantDigits(localMax, m_precision);
|
|
|
|
bool needsUpdate = false;
|
|
const double epsilon = std::numeric_limits<double>::epsilon();
|
|
|
|
if (cvf::Math::abs(candidateGlobalAutoMax - m_globalAutoMax) > epsilon)
|
|
{
|
|
needsUpdate = true;
|
|
}
|
|
|
|
if (cvf::Math::abs(candidateGlobalAutoMin - m_globalAutoMin) > epsilon)
|
|
{
|
|
needsUpdate = true;
|
|
}
|
|
|
|
if (cvf::Math::abs(candidateLocalAutoMax - m_localAutoMax) > epsilon)
|
|
{
|
|
needsUpdate = true;
|
|
}
|
|
|
|
if (cvf::Math::abs(candidateLocalAutoMin - m_localAutoMin) > epsilon)
|
|
{
|
|
needsUpdate = true;
|
|
}
|
|
|
|
if (needsUpdate)
|
|
{
|
|
m_globalAutoMin = candidateGlobalAutoMin;
|
|
m_globalAutoMax = candidateGlobalAutoMax;
|
|
|
|
m_localAutoMin = candidateLocalAutoMin;
|
|
m_localAutoMax = candidateLocalAutoMax;
|
|
|
|
updateLegend();
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::initAfterRead()
|
|
{
|
|
updateFieldVisibility();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::updateFieldVisibility()
|
|
{
|
|
bool showRangeItems = m_mappingMode == CATEGORY_INTEGER ? false : true;
|
|
|
|
m_numLevels.uiCapability()->setUiHidden(!showRangeItems);
|
|
m_precision.uiCapability()->setUiHidden(!showRangeItems);
|
|
m_tickNumberFormat.uiCapability()->setUiHidden(!showRangeItems);
|
|
m_rangeMode.uiCapability()->setUiHidden(!showRangeItems);
|
|
|
|
if (showRangeItems && m_rangeMode == USER_DEFINED)
|
|
{
|
|
m_userDefinedMaxValue.uiCapability()->setUiHidden(false);
|
|
m_userDefinedMinValue.uiCapability()->setUiHidden(false);
|
|
}
|
|
else
|
|
{
|
|
m_userDefinedMaxValue.uiCapability()->setUiHidden(true);
|
|
m_userDefinedMinValue.uiCapability()->setUiHidden(true);
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::setColorRangeMode(ColorRangesType colorMode)
|
|
{
|
|
m_colorRangeMode = colorMode;
|
|
updateLegend();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::setMappingMode(MappingType mappingType)
|
|
{
|
|
m_mappingMode = mappingType;
|
|
updateLegend();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::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_scalarMapperLegend = new cvf::OverlayScalarMapperLegend(standardFont);
|
|
m_categoryLegend = new caf::CategoryLegend(standardFont, m_categoryMapper.p());
|
|
|
|
updateLegend();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Rounding the double value to given number of significant digits
|
|
//--------------------------------------------------------------------------------------------------
|
|
double RimLegendConfig::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 RimLegendConfig::setClosestToZeroValues(double globalPosClosestToZero, double globalNegClosestToZero, double localPosClosestToZero, double localNegClosestToZero)
|
|
{
|
|
bool needsUpdate = false;
|
|
const double epsilon = std::numeric_limits<double>::epsilon();
|
|
|
|
if (cvf::Math::abs(globalPosClosestToZero - m_globalAutoPosClosestToZero) > epsilon)
|
|
{
|
|
needsUpdate = true;
|
|
}
|
|
if (cvf::Math::abs(globalNegClosestToZero - m_globalAutoNegClosestToZero) > epsilon)
|
|
{
|
|
needsUpdate = true;
|
|
}
|
|
if (cvf::Math::abs(localPosClosestToZero - m_localAutoPosClosestToZero) > epsilon)
|
|
{
|
|
needsUpdate = true;
|
|
}
|
|
if (cvf::Math::abs(localNegClosestToZero - m_localAutoNegClosestToZero) > epsilon)
|
|
{
|
|
needsUpdate = true;
|
|
}
|
|
|
|
if (needsUpdate)
|
|
{
|
|
m_globalAutoPosClosestToZero = globalPosClosestToZero;
|
|
m_globalAutoNegClosestToZero = globalNegClosestToZero;
|
|
m_localAutoPosClosestToZero = localPosClosestToZero;
|
|
m_localAutoNegClosestToZero = localNegClosestToZero;
|
|
|
|
if (m_globalAutoPosClosestToZero == HUGE_VAL) m_globalAutoPosClosestToZero = 0;
|
|
if (m_globalAutoNegClosestToZero == -HUGE_VAL) m_globalAutoNegClosestToZero = 0;
|
|
if (m_localAutoPosClosestToZero == HUGE_VAL) m_localAutoPosClosestToZero = 0;
|
|
if (m_localAutoNegClosestToZero == -HUGE_VAL) m_localAutoNegClosestToZero = 0;
|
|
|
|
updateLegend();
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::setIntegerCategories(const std::vector<int>& categories)
|
|
{
|
|
m_categories = categories;
|
|
m_categoryNames.clear();
|
|
m_categoryColors.clear();
|
|
|
|
updateLegend();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::setNamedCategoriesInverse(const std::vector<QString>& categoryNames)
|
|
{
|
|
std::vector<int> nameIndices;
|
|
std::vector<cvf::String> names;
|
|
for(int i = static_cast<int>(categoryNames.size()) - 1; i >= 0; --i)
|
|
{
|
|
nameIndices.push_back(i);
|
|
names.push_back(cvfqt::Utils::toString(categoryNames[i]));
|
|
}
|
|
|
|
m_categories = nameIndices;
|
|
m_categoryNames = names;
|
|
m_categoryColors.clear();
|
|
|
|
updateLegend();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::setCategoryItems(const std::vector< std::tuple<QString, int, cvf::Color3ub> >& categories)
|
|
{
|
|
m_categories.clear();
|
|
m_categoryNames.clear();
|
|
m_categoryColors.clear();
|
|
m_categoryColors.reserve(categories.size());
|
|
|
|
for (auto item : categories)
|
|
{
|
|
m_categoryNames.push_back(cvfqt::Utils::toString(std::get<0>(item)));
|
|
m_categories.push_back(std::get<1>(item));
|
|
m_categoryColors.add(std::get<2>(item));
|
|
}
|
|
|
|
updateLegend();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimLegendConfig::categoryNameFromCategoryValue(double categoryResultValue) const
|
|
{
|
|
if (categoryResultValue == HUGE_VAL) return "Undefined";
|
|
|
|
if (m_categoryNames.size() > 0)
|
|
{
|
|
for (size_t categoryIndex = 0; categoryIndex < m_categories.size(); categoryIndex++)
|
|
{
|
|
if (categoryResultValue == m_categories[categoryIndex])
|
|
{
|
|
return cvfqt::Utils::toQString(m_categoryNames[categoryIndex]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return QString("%1").arg(categoryResultValue);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::setTitle(const cvf::String& title)
|
|
{
|
|
m_scalarMapperLegend->setTitle(title);
|
|
m_categoryLegend->setTitle(title);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
cvf::OverlayItem* RimLegendConfig::legend()
|
|
{
|
|
if (m_currentScalarMapper == m_categoryMapper)
|
|
{
|
|
return m_categoryLegend.p();
|
|
}
|
|
else
|
|
{
|
|
return m_scalarMapperLegend.p();
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::setUiValuesFromLegendConfig(const RimLegendConfig* otherLegendConfig)
|
|
{
|
|
QString serializedObjectString = otherLegendConfig->writeObjectToXmlString();
|
|
this->readObjectFromXmlString(serializedObjectString, caf::PdmDefaultObjectFactory::instance());
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
cvf::Color3ubArray RimLegendConfig::colorArrayFromColorType(ColorRangesType colorType)
|
|
{
|
|
switch (colorType)
|
|
{
|
|
case RimLegendConfig::NORMAL:
|
|
return RiaColorTables::normalPaletteColors().color3ubArray();
|
|
break;
|
|
case RimLegendConfig::OPPOSITE_NORMAL:
|
|
return RiaColorTables::normalPaletteOppositeOrderingColors().color3ubArray();
|
|
break;
|
|
case RimLegendConfig::WHITE_PINK:
|
|
return RiaColorTables::whitePinkPaletteColors().color3ubArray();
|
|
break;
|
|
case RimLegendConfig::PINK_WHITE:
|
|
return RiaColorTables::pinkWhitePaletteColors().color3ubArray();
|
|
break;
|
|
case RimLegendConfig::WHITE_BLACK:
|
|
return RiaColorTables::whiteBlackPaletteColors().color3ubArray();
|
|
break;
|
|
case RimLegendConfig::BLACK_WHITE:
|
|
return RiaColorTables::blackWhitePaletteColors().color3ubArray();
|
|
break;
|
|
case RimLegendConfig::BLUE_WHITE_RED:
|
|
return RiaColorTables::blueWhiteRedPaletteColors().color3ubArray();
|
|
break;
|
|
case RimLegendConfig::RED_WHITE_BLUE:
|
|
return RiaColorTables::redWhiteBluePaletteColors().color3ubArray();
|
|
break;
|
|
case RimLegendConfig::CATEGORY:
|
|
return RiaColorTables::categoryPaletteColors().color3ubArray();
|
|
break;
|
|
case RimLegendConfig::ANGULAR:
|
|
return RiaColorTables::angularPaletteColors().color3ubArray();
|
|
break;
|
|
case RimLegendConfig::STIMPLAN:
|
|
return RiaColorTables::stimPlanPaletteColors().color3ubArray();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return RiaColorTables::normalPaletteColors().color3ubArray();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimLegendConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
|
|
{
|
|
{
|
|
caf::PdmUiOrdering * formatGr = uiOrdering.addNewGroup("Format");
|
|
formatGr->add(&m_numLevels);
|
|
formatGr->add(&m_precision);
|
|
formatGr->add(&m_tickNumberFormat);
|
|
formatGr->add(&m_colorRangeMode);
|
|
|
|
caf::PdmUiOrdering * mappingGr = uiOrdering.addNewGroup("Mapping");
|
|
mappingGr->add(&m_mappingMode);
|
|
mappingGr->add(&m_rangeMode);
|
|
mappingGr->add(&m_userDefinedMaxValue);
|
|
mappingGr->add(&m_userDefinedMinValue);
|
|
}
|
|
|
|
updateFieldVisibility();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QList<caf::PdmOptionItemInfo> RimLegendConfig::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly)
|
|
{
|
|
bool hasStimPlanParent = false;
|
|
RimStimPlanColors* stimPlanColors = nullptr;
|
|
this->firstAncestorOrThisOfType(stimPlanColors);
|
|
if (stimPlanColors) hasStimPlanParent = true;
|
|
|
|
bool isCategoryResult = false;
|
|
{
|
|
RimEclipseCellColors* eclCellColors = nullptr;
|
|
this->firstAncestorOrThisOfType(eclCellColors);
|
|
RimGeoMechResultDefinition* gmCellColors = nullptr;
|
|
this->firstAncestorOrThisOfType(gmCellColors);
|
|
RimCellEdgeColors* eclCellEdgColors = nullptr;
|
|
this->firstAncestorOrThisOfType(eclCellEdgColors);
|
|
|
|
if ( ( eclCellColors && eclCellColors->hasCategoryResult())
|
|
|| ( gmCellColors && gmCellColors->hasCategoryResult())
|
|
|| ( eclCellEdgColors && eclCellEdgColors->hasCategoryResult()) )
|
|
{
|
|
isCategoryResult = true;
|
|
}
|
|
}
|
|
|
|
QList<caf::PdmOptionItemInfo> options;
|
|
|
|
if (fieldNeedingOptions == &m_mappingMode)
|
|
{
|
|
// 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);
|
|
mappingTypes.push_back(LOG10_DISCRETE);
|
|
|
|
if (isCategoryResult)
|
|
{
|
|
mappingTypes.push_back(CATEGORY_INTEGER);
|
|
}
|
|
|
|
for(MappingType mapType: mappingTypes)
|
|
{
|
|
options.push_back(caf::PdmOptionItemInfo(MappingEnum::uiText(mapType), mapType));
|
|
}
|
|
}
|
|
else if (fieldNeedingOptions == &m_colorRangeMode)
|
|
{
|
|
// This is an app enum field, see cafInternalPdmFieldTypeSpecializations.h for the default specialization of this type
|
|
std::vector<ColorRangesType> rangeTypes;
|
|
rangeTypes.push_back(NORMAL);
|
|
rangeTypes.push_back(OPPOSITE_NORMAL);
|
|
rangeTypes.push_back(WHITE_PINK);
|
|
rangeTypes.push_back(PINK_WHITE);
|
|
rangeTypes.push_back(BLUE_WHITE_RED);
|
|
rangeTypes.push_back(RED_WHITE_BLUE);
|
|
rangeTypes.push_back(WHITE_BLACK);
|
|
rangeTypes.push_back(BLACK_WHITE);
|
|
rangeTypes.push_back(ANGULAR);
|
|
if (hasStimPlanParent) rangeTypes.push_back(STIMPLAN);
|
|
|
|
if (isCategoryResult)
|
|
{
|
|
rangeTypes.push_back(CATEGORY);
|
|
}
|
|
|
|
for(ColorRangesType colType: rangeTypes)
|
|
{
|
|
options.push_back(caf::PdmOptionItemInfo(ColorRangeEnum::uiText(colType), colType));
|
|
}
|
|
}
|
|
else if (fieldNeedingOptions == &m_rangeMode)
|
|
{
|
|
if (!m_isAllTimeStepsRangeDisabled)
|
|
{
|
|
options.push_back(caf::PdmOptionItemInfo(RangeModeEnum::uiText(RimLegendConfig::AUTOMATIC_ALLTIMESTEPS), RimLegendConfig::AUTOMATIC_ALLTIMESTEPS));
|
|
}
|
|
if (!hasStimPlanParent)
|
|
{
|
|
options.push_back(caf::PdmOptionItemInfo(RangeModeEnum::uiText(RimLegendConfig::AUTOMATIC_CURRENT_TIMESTEP), RimLegendConfig::AUTOMATIC_CURRENT_TIMESTEP));
|
|
}
|
|
options.push_back(caf::PdmOptionItemInfo(RangeModeEnum::uiText(RimLegendConfig::USER_DEFINED), RimLegendConfig::USER_DEFINED));
|
|
}
|
|
|
|
return options;
|
|
}
|
|
|