2012-05-18 09:45:23 +02:00
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RIStdInclude.h"
#include "RimLegendConfig.h"
#include "RimReservoirView.h"
2012-06-26 16:10:41 +02:00
#include "cafFactory.h"
#include "cafPdmUiLineEditor.h"
#include "cafPdmUiComboBoxEditor.h"
2012-10-02 10:17:52 +02:00
#include "cvfScalarMapperDiscreteLog.h"
2012-05-18 09:45:23 +02:00
CAF_PDM_SOURCE_INIT ( RimLegendConfig , "Legend" );
namespace caf {
template <>
void AppEnum < RimLegendConfig :: RangeModeType >:: setUp ()
{
addItem ( RimLegendConfig :: AUTOMATIC_ALLTIMESTEPS , "AUTOMATIC_ALLTIMESTEPS" , "Global range" );
addItem ( RimLegendConfig :: AUTOMATIC_CURRENT_TIMESTEP , "AUTOMATIC_CURRENT_TIMESTEP" , "Local range" );
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 :: WHITE_BLACK , "WHITE_BLACK" , "White to black" );
addItem ( RimLegendConfig :: BLACK_WHITE , "BLACK_WHITE" , "Black to white" );
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" );
2012-10-02 10:17:52 +02:00
addItem ( RimLegendConfig :: LOG10_DISCRETE , "Log10Discrete" , "Discrete Logarithmic" );
2012-05-18 09:45:23 +02:00
setDefault ( RimLegendConfig :: LINEAR_CONTINUOUS );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimLegendConfig :: RimLegendConfig ()
: m_globalAutoMax ( cvf :: UNDEFINED_DOUBLE ),
m_globalAutoMin ( cvf :: UNDEFINED_DOUBLE ),
m_localAutoMax ( cvf :: UNDEFINED_DOUBLE ),
m_localAutoMin ( cvf :: UNDEFINED_DOUBLE )
{
CAF_PDM_InitObject ( "Legend Definition" , ":/Legend.png" , "" , "" );
CAF_PDM_InitField ( & m_numLevels , "NumberOfLevels" , 8 , "Number of levels" , "" , "" , "" );
CAF_PDM_InitField ( & m_precision , "Precision" , 6 , "Precision" , "" , "" , "" );
CAF_PDM_InitField ( & m_colorRangeMode , "ColorRangeMode" , ColorRangeEnum ( NORMAL ) , "Color range" , "" , "" , "" );
CAF_PDM_InitField ( & m_mappingMode , "MappingMode" , MappingEnum ( LINEAR_CONTINUOUS ) , "Mapping" , "" , "" , "" );
CAF_PDM_InitField ( & m_rangeMode , "RangeType" , caf :: AppEnum < RimLegendConfig :: RangeModeType > ( AUTOMATIC_ALLTIMESTEPS ), "Legend 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 ( "" ), "" , "" , "" , "" );
2012-06-26 16:10:41 +02:00
resultVariableName . setUiHidden ( true );
2012-05-18 09:45:23 +02:00
2012-10-02 10:17:52 +02:00
m_linDiscreteScalarMapper = new cvf :: ScalarMapperDiscreteLinear ;
m_logDiscreteScalarMapper = new cvf :: ScalarMapperDiscreteLog ;
2012-05-18 09:45:23 +02:00
m_linSmoothScalarMapper = new cvf :: ScalarMapperContinuousLinear ;
2012-10-02 10:17:52 +02:00
m_logSmoothScalarMapper = new cvf :: ScalarMapperContinuousLog ;
2012-05-18 09:45:23 +02:00
m_currentScalarMapper = m_linDiscreteScalarMapper ;
cvf :: FixedAtlasFont * font = new cvf :: FixedAtlasFont ( cvf :: FixedAtlasFont :: STANDARD );
2012-10-02 10:17:52 +02:00
m_legend = new cvf :: OverlayScalarMapperLegend ( font );
2012-05-18 09:45:23 +02:00
m_position = cvf :: Vec2ui ( 20 , 50 );
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 )
{
if ( m_rangeMode == USER_DEFINED )
{
if ( m_userDefinedMaxValue == m_userDefinedMaxValue . defaultValue () && m_globalAutoMax != cvf :: UNDEFINED_DOUBLE )
{
m_userDefinedMaxValue = adjust ( m_globalAutoMax , m_precision );
}
if ( m_userDefinedMinValue == m_userDefinedMinValue . defaultValue () && m_globalAutoMin != cvf :: UNDEFINED_DOUBLE )
{
m_userDefinedMinValue = adjust ( m_globalAutoMin , m_precision );
}
}
updateFieldVisibility ();
}
updateLegend ();
if ( m_reservoirView ) m_reservoirView -> updateCurrentTimeStepAndRedraw ();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: updateLegend ()
{
double adjustedMin = cvf :: UNDEFINED_DOUBLE ;
double adjustedMax = cvf :: UNDEFINED_DOUBLE ;
if ( m_rangeMode == AUTOMATIC_ALLTIMESTEPS )
{
adjustedMin = adjust ( m_globalAutoMin , m_precision );
adjustedMax = adjust ( m_globalAutoMax , m_precision );
}
else if ( m_rangeMode == AUTOMATIC_CURRENT_TIMESTEP )
{
adjustedMin = adjust ( m_localAutoMin , m_precision );
adjustedMax = adjust ( m_localAutoMax , m_precision );
}
else
{
adjustedMin = adjust ( m_userDefinedMinValue , m_precision );
adjustedMax = adjust ( m_userDefinedMaxValue , m_precision );
}
2012-10-02 10:17:52 +02:00
2012-05-18 09:45:23 +02:00
m_linDiscreteScalarMapper -> setRange ( adjustedMin , adjustedMax );
2012-10-02 10:17:52 +02:00
m_logDiscreteScalarMapper -> setRange ( adjustedMin , adjustedMax );
2012-05-18 09:45:23 +02:00
m_logSmoothScalarMapper -> setRange ( adjustedMin , adjustedMax );
m_linSmoothScalarMapper -> setRange ( adjustedMin , adjustedMax );
cvf :: Color3ubArray legendColors ;
switch ( m_colorRangeMode ())
{
case NORMAL :
{
2012-10-02 10:17:52 +02:00
legendColors . reserve ( 7 );
2012-05-18 09:45:23 +02:00
legendColors . add ( cvf :: Color3ub ( 0 , 0 , 255 ));
2012-10-02 10:17:52 +02:00
legendColors . add ( cvf :: Color3ub ( 0 , 127 , 255 ));
2012-05-18 09:45:23 +02:00
legendColors . add ( cvf :: Color3ub ( 0 , 255 , 255 ));
legendColors . add ( cvf :: Color3ub ( 0 , 255 , 0 ));
legendColors . add ( cvf :: Color3ub ( 255 , 255 , 0 ));
2012-10-02 10:17:52 +02:00
legendColors . add ( cvf :: Color3ub ( 255 , 127 , 0 ));
2012-05-18 09:45:23 +02:00
legendColors . add ( cvf :: Color3ub ( 255 , 0 , 0 ));
}
break ;
case OPPOSITE_NORMAL :
{
2012-10-02 10:17:52 +02:00
legendColors . reserve ( 7 );
2012-05-18 09:45:23 +02:00
legendColors . add ( cvf :: Color3ub ( 255 , 0 , 0 ));
2012-10-02 10:17:52 +02:00
legendColors . add ( cvf :: Color3ub ( 255 , 127 , 0 ));
2012-05-18 09:45:23 +02:00
legendColors . add ( cvf :: Color3ub ( 255 , 255 , 0 ));
legendColors . add ( cvf :: Color3ub ( 0 , 255 , 0 ));
legendColors . add ( cvf :: Color3ub ( 0 , 255 , 255 ));
2012-10-02 10:17:52 +02:00
legendColors . add ( cvf :: Color3ub ( 0 , 127 , 255 ));
2012-05-18 09:45:23 +02:00
legendColors . add ( cvf :: Color3ub ( 0 , 0 , 255 ));
}
break ; case BLACK_WHITE :
case WHITE_BLACK :
{
legendColors . reserve ( 2 );
if ( m_colorRangeMode () == BLACK_WHITE )
{
legendColors . add ( cvf :: Color3ub :: BLACK );
legendColors . add ( cvf :: Color3ub :: WHITE );
}
else
{
legendColors . add ( cvf :: Color3ub :: WHITE );
legendColors . add ( cvf :: Color3ub :: BLACK );
}
}
break ;
case PINK_WHITE :
case WHITE_PINK :
{
legendColors . reserve ( 2 );
if ( m_colorRangeMode () == PINK_WHITE )
{
legendColors . add ( cvf :: Color3ub :: DEEP_PINK );
legendColors . add ( cvf :: Color3ub :: WHITE );
}
else
{
legendColors . add ( cvf :: Color3ub :: WHITE );
legendColors . add ( cvf :: Color3ub :: DEEP_PINK );
}
}
break ;
}
2012-10-02 10:17:52 +02:00
m_linDiscreteScalarMapper -> setColors ( legendColors );
m_logDiscreteScalarMapper -> setColors ( legendColors );
2012-05-18 09:45:23 +02:00
m_logSmoothScalarMapper -> setColors ( legendColors );
m_linSmoothScalarMapper -> setColors ( legendColors );
2012-10-02 10:17:52 +02:00
m_linDiscreteScalarMapper -> setLevelCount ( m_numLevels , true );
m_logDiscreteScalarMapper -> setLevelCount ( m_numLevels , true );
m_logSmoothScalarMapper -> setLevelCount ( m_numLevels , true );
m_linSmoothScalarMapper -> setLevelCount ( m_numLevels , true );
2012-05-18 09:45:23 +02:00
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 ;
2012-10-02 10:17:52 +02:00
case LOG10_DISCRETE :
m_currentScalarMapper = m_logDiscreteScalarMapper . p ();
break ;
2012-05-18 09:45:23 +02:00
default :
break ;
}
2012-10-02 10:17:52 +02:00
2012-05-18 09:45:23 +02:00
m_legend -> setScalarMapper ( m_currentScalarMapper . p ());
if ( m_globalAutoMax != cvf :: UNDEFINED_DOUBLE )
{
m_userDefinedMaxValue . setUiName ( QString ( "Max " ) + "(" + QString :: number ( m_globalAutoMax , 'g' , m_precision ) + ")" );
}
else
{
m_userDefinedMaxValue . setUiName ( QString ());
}
if ( m_globalAutoMin != cvf :: UNDEFINED_DOUBLE )
{
m_userDefinedMinValue . setUiName ( QString ( "Min " ) + "(" + QString :: number ( m_globalAutoMin , 'g' , m_precision ) + ")" );
}
else
{
m_userDefinedMinValue . setUiName ( QString ());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: setAutomaticRanges ( double globalMin , double globalMax , double localMin , double localMax )
{
m_globalAutoMin = adjust ( globalMin , m_precision );
m_globalAutoMax = adjust ( globalMax , m_precision );
m_localAutoMin = adjust ( localMin , m_precision );
m_localAutoMax = adjust ( localMax , m_precision );
updateLegend ();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: initAfterRead ()
{
updateFieldVisibility ();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: updateFieldVisibility ()
{
if ( m_rangeMode == USER_DEFINED )
{
2012-06-26 16:10:41 +02:00
m_userDefinedMaxValue . setUiHidden ( false );
m_userDefinedMinValue . setUiHidden ( false );
2012-05-18 09:45:23 +02:00
}
else
{
2012-06-26 16:10:41 +02:00
m_userDefinedMaxValue . setUiHidden ( true );
m_userDefinedMinValue . setUiHidden ( true );
2012-05-18 09:45:23 +02:00
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: setColorRangeMode ( ColorRangesType colorMode )
{
m_colorRangeMode = colorMode ;
updateLegend ();
}
2012-10-02 10:17:52 +02:00
/*
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Color3ubArray> RimLegendConfig::interpolateColorArray(const cvf::Color3ubArray& colorArray, cvf::uint targetColorCount)
{
uint inputColorCount = static_cast<uint>(colorArray.size());
CVF_ASSERT(inputColorCount > 1);
CVF_ASSERT(targetColorCount > 1);
cvf::ref<cvf::Color3ubArray> colors = new cvf::Color3ubArray;
colors->reserve(targetColorCount);
const uint inputLevelCount = inputColorCount - 1;
const uint outputLevelCount = targetColorCount - 1;
uint outputLevelIdx;
for (outputLevelIdx = 0; outputLevelIdx < outputLevelCount; outputLevelIdx++)
{
double dblInputLevelIndex = inputLevelCount * (outputLevelIdx / static_cast<double>(outputLevelCount));
const uint inputLevelIndex = static_cast<uint>(dblInputLevelIndex);
CVF_ASSERT(inputLevelIndex < inputLevelCount);
double t = dblInputLevelIndex - inputLevelIndex;
CVF_ASSERT(t >= 0 && t <= 1.0);
cvf::Color3ub c1 = colorArray[inputLevelIndex];
cvf::Color3ub c2 = colorArray[inputLevelIndex + 1];
int r = static_cast<int>(c1.r() + t*(c2.r() - c1.r()) + 0.5);
int g = static_cast<int>(c1.g() + t*(c2.g() - c1.g()) + 0.5);
int b = static_cast<int>(c1.b() + t*(c2.b() - c1.b()) + 0.5);
r = cvf::Math::clamp(r, 0, 255);
g = cvf::Math::clamp(g, 0, 255);
b = cvf::Math::clamp(b, 0, 255);
cvf::Color3ub col((cvf::ubyte)r, (cvf::ubyte)g, (cvf::ubyte)b);
colors->add(col);
}
colors->add(colorArray[colorArray.size() - 1]);
return colors;
}
2012-10-02 10:17:52 +02:00
*/
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: setPosition ( cvf :: Vec2ui position )
{
m_position = position ;
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 :: FixedAtlasFont * font = new cvf :: FixedAtlasFont ( cvf :: FixedAtlasFont :: STANDARD );
2012-10-02 10:17:52 +02:00
m_legend = new cvf :: OverlayScalarMapperLegend ( font );
2012-05-18 09:45:23 +02:00
updateLegend ();
}
//--------------------------------------------------------------------------------------------------
/// Adjust double value to given precision
//--------------------------------------------------------------------------------------------------
double RimLegendConfig :: adjust ( double domainValue , double precision )
{
2013-02-26 12:45:41 +01:00
double absDomainValue = cvf :: Math :: abs ( domainValue );
if ( absDomainValue == 0.0 )
2012-05-18 09:45:23 +02:00
{
return 0.0 ;
}
2013-02-26 12:45:41 +01:00
double logDecValue = log10 ( absDomainValue );
2012-05-18 09:45:23 +02:00
logDecValue = cvf :: Math :: ceil ( logDecValue );
double factor = pow ( 10.0 , precision - logDecValue );
double tmp = domainValue * factor ;
double integerPart ;
modf ( tmp , & integerPart );
double newDomainValue = integerPart / factor ;
return newDomainValue ;
}