2012-05-18 09:45:23 +02:00
/////////////////////////////////////////////////////////////////////////////////
//
2014-09-23 15:04:57 +02:00
// Copyright (C) 2011- Statoil ASA
// Copyright (C) 2013- Ceetron Solutions AS
// Copyright (C) 2011-2012 Ceetron AS
2012-05-18 09:45:23 +02:00
//
// 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"
2013-05-06 12:02:32 +02:00
2016-08-01 22:27:03 +02:00
#include "RiaApplication.h"
2017-02-10 08:37:48 +01:00
#include "RiaColorTables.h"
2016-08-01 22:27:03 +02:00
2016-10-18 07:31:02 +02:00
#include "RimCellEdgeColors.h"
2016-08-02 10:25:55 +02:00
#include "RimEclipseCellColors.h"
2016-08-01 22:27:03 +02:00
#include "RimEclipseView.h"
2016-10-18 07:31:02 +02:00
#include "RimGeoMechResultDefinition.h"
2016-12-09 20:36:31 +01:00
#include "RimViewLinker.h"
2016-08-01 22:27:03 +02:00
2016-08-02 10:25:55 +02:00
#include "cafCategoryLegend.h"
#include "cafCategoryMapper.h"
2012-06-26 16:10:41 +02:00
#include "cafFactory.h"
2014-05-06 22:40:25 +02:00
#include "cafPdmFieldCvfColor.h"
#include "cafPdmFieldCvfMat4d.h"
2012-06-26 16:10:41 +02:00
#include "cafPdmUiComboBoxEditor.h"
2014-05-06 22:40:25 +02:00
#include "cafPdmUiLineEditor.h"
2013-05-06 12:02:32 +02:00
2013-05-06 10:55:00 +02:00
#include "cvfOverlayScalarMapperLegend.h"
2014-05-06 22:40:25 +02:00
#include "cvfScalarMapperContinuousLinear.h"
#include "cvfScalarMapperContinuousLog.h"
2013-05-06 10:55:00 +02:00
#include "cvfScalarMapperDiscreteLinear.h"
2014-05-06 22:40:25 +02:00
#include "cvfScalarMapperDiscreteLog.h"
2016-09-09 12:10:24 +02:00
#include "cvfqtUtils.h"
2014-05-06 22:40:25 +02:00
2013-05-06 12:02:32 +02:00
#include <cmath>
2012-05-18 09:45:23 +02:00
CAF_PDM_SOURCE_INIT ( RimLegendConfig , "Legend" );
namespace caf {
template <>
void AppEnum < RimLegendConfig :: RangeModeType >:: setUp ()
{
2015-06-29 10:42:56 +02:00
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" );
2012-05-18 09:45:23 +02:00
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" );
2016-08-02 10:25:55 +02:00
addItem ( RimLegendConfig :: BLUE_WHITE_RED , "BLUE_WHITE_RED" , "Blue, white, red" );
addItem ( RimLegendConfig :: RED_WHITE_BLUE , "RED_WHITE_BLUE" , "Red, white, blue" );
2012-05-18 09:45:23 +02:00
addItem ( RimLegendConfig :: WHITE_BLACK , "WHITE_BLACK" , "White to black" );
addItem ( RimLegendConfig :: BLACK_WHITE , "BLACK_WHITE" , "Black to white" );
2016-08-02 10:25:55 +02:00
addItem ( RimLegendConfig :: CATEGORY , "CATEGORY" , "Category colors" );
2016-10-13 12:13:32 +02:00
addItem ( RimLegendConfig :: ANGULAR , "ANGULAR" , "Full color cyclic" );
2012-05-18 09:45:23 +02:00
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" );
2016-08-02 10:25:55 +02:00
addItem ( RimLegendConfig :: CATEGORY_INTEGER , "Category" , "Category" );
2012-05-18 09:45:23 +02:00
setDefault ( RimLegendConfig :: LINEAR_CONTINUOUS );
}
}
2013-04-30 14:48:53 +02:00
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 );
}
}
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimLegendConfig :: RimLegendConfig ()
: m_globalAutoMax ( cvf :: UNDEFINED_DOUBLE ),
m_globalAutoMin ( cvf :: UNDEFINED_DOUBLE ),
m_localAutoMax ( cvf :: UNDEFINED_DOUBLE ),
2013-06-03 13:08:11 +02:00
m_localAutoMin ( cvf :: UNDEFINED_DOUBLE ),
m_globalAutoPosClosestToZero ( 0 ),
m_globalAutoNegClosestToZero ( 0 ),
m_localAutoPosClosestToZero ( 0 ),
2017-01-03 14:58:34 +01:00
m_localAutoNegClosestToZero ( 0 ),
m_isAllTimeStepsRangeDisabled ( false )
2012-05-18 09:45:23 +02:00
{
CAF_PDM_InitObject ( "Legend Definition" , ":/Legend.png" , "" , "" );
2013-09-26 10:44:20 +02:00
CAF_PDM_InitField ( & m_numLevels , "NumberOfLevels" , 8 , "Number of levels" , "" , "A hint on how many tick marks you whish." , "" );
2013-10-03 11:06:18 +02:00
CAF_PDM_InitField ( & m_precision , "Precision" , 4 , "Significant digits" , "" , "The number of significant digits displayed in the legend numbers" , "" );
2013-09-26 10:44:20 +02:00
CAF_PDM_InitField ( & m_tickNumberFormat , "TickNumberFormat" , caf :: AppEnum < RimLegendConfig :: NumberFormatType > ( FIXED ), "Number format" , "" , "" , "" );
2013-04-30 14:48:53 +02:00
2013-09-26 10:44:20 +02:00
CAF_PDM_InitField ( & m_colorRangeMode , "ColorRangeMode" , ColorRangeEnum ( NORMAL ) , "Colors" , "" , "" , "" );
2012-05-18 09:45:23 +02:00
CAF_PDM_InitField ( & m_mappingMode , "MappingMode" , MappingEnum ( LINEAR_CONTINUOUS ) , "Mapping" , "" , "" , "" );
2014-04-25 16:32:06 +02:00
CAF_PDM_InitField ( & m_rangeMode , "RangeType" , RangeModeEnum ( AUTOMATIC_ALLTIMESTEPS ), "Range type" , "" , "Switches between automatic and user defined range on the legend" , "" );
2012-05-18 09:45:23 +02:00
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 ( "" ), "" , "" , "" , "" );
2015-08-05 13:27:36 +02:00
resultVariableName . uiCapability () -> 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 ;
2016-08-02 10:25:55 +02:00
m_categoryMapper = new caf :: CategoryMapper ;
2013-04-19 08:02:36 +02:00
cvf :: Font * standardFont = RiaApplication :: instance () -> standardFont ();
2016-08-01 22:27:03 +02:00
m_scalarMapperLegend = new cvf :: OverlayScalarMapperLegend ( standardFont );
2016-08-02 10:25:55 +02:00
m_categoryLegend = new caf :: CategoryLegend ( standardFont , m_categoryMapper . p ());
2012-05-18 09:45:23 +02:00
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 );
}
2016-08-02 10:25:55 +02:00
else if ( changedField == & m_rangeMode ||
changedField == & m_mappingMode )
2012-05-18 09:45:23 +02:00
{
if ( m_rangeMode == USER_DEFINED )
{
if ( m_userDefinedMaxValue == m_userDefinedMaxValue . defaultValue () && m_globalAutoMax != cvf :: UNDEFINED_DOUBLE )
{
2013-09-26 01:05:09 +02:00
m_userDefinedMaxValue = roundToNumSignificantDigits ( m_globalAutoMax , m_precision );
2012-05-18 09:45:23 +02:00
}
if ( m_userDefinedMinValue == m_userDefinedMinValue . defaultValue () && m_globalAutoMin != cvf :: UNDEFINED_DOUBLE )
{
2013-09-26 01:05:09 +02:00
m_userDefinedMinValue = roundToNumSignificantDigits ( m_globalAutoMin , m_precision );
2012-05-18 09:45:23 +02:00
}
}
updateFieldVisibility ();
}
updateLegend ();
2016-12-09 20:36:31 +01:00
RimView * view = nullptr ;
this -> firstAncestorOrThisOfType ( view );
if ( view )
{
RimViewLinker * viewLinker = view -> assosiatedViewLinker ();
if ( viewLinker )
{
viewLinker -> updateCellResult ();
}
2016-12-09 21:15:24 +01:00
view -> updateCurrentTimeStepAndRedraw ();
}
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: updateLegend ()
{
double adjustedMin = cvf :: UNDEFINED_DOUBLE ;
double adjustedMax = cvf :: UNDEFINED_DOUBLE ;
2013-06-03 13:08:11 +02:00
double posClosestToZero = cvf :: UNDEFINED_DOUBLE ;
double negClosestToZero = cvf :: UNDEFINED_DOUBLE ;
2012-05-18 09:45:23 +02:00
if ( m_rangeMode == AUTOMATIC_ALLTIMESTEPS )
{
2013-09-26 01:05:09 +02:00
adjustedMin = roundToNumSignificantDigits ( m_globalAutoMin , m_precision );
adjustedMax = roundToNumSignificantDigits ( m_globalAutoMax , m_precision );
2013-06-03 13:08:11 +02:00
posClosestToZero = m_globalAutoPosClosestToZero ;
negClosestToZero = m_globalAutoNegClosestToZero ;
2012-05-18 09:45:23 +02:00
}
else if ( m_rangeMode == AUTOMATIC_CURRENT_TIMESTEP )
{
2013-09-26 01:05:09 +02:00
adjustedMin = roundToNumSignificantDigits ( m_localAutoMin , m_precision );
adjustedMax = roundToNumSignificantDigits ( m_localAutoMax , m_precision );
2013-06-03 13:08:11 +02:00
posClosestToZero = m_localAutoPosClosestToZero ;
negClosestToZero = m_localAutoNegClosestToZero ;
2012-05-18 09:45:23 +02:00
}
else
{
2013-09-26 01:05:09 +02:00
adjustedMin = roundToNumSignificantDigits ( m_userDefinedMinValue , m_precision );
adjustedMax = roundToNumSignificantDigits ( m_userDefinedMaxValue , m_precision );
2013-06-03 13:08:11 +02:00
posClosestToZero = m_globalAutoPosClosestToZero ;
negClosestToZero = m_globalAutoNegClosestToZero ;
2012-05-18 09:45:23 +02:00
}
m_linDiscreteScalarMapper -> setRange ( adjustedMin , adjustedMax );
2013-06-03 13:08:11 +02:00
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 ;
}
}
}
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 );
2017-02-10 08:37:48 +01:00
cvf :: Color3ubArray legendColors = colorArrayFromColorType ( m_colorRangeMode ());
2012-05-18 09:45:23 +02:00
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 );
2016-08-02 10:25:55 +02:00
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 ;
2016-08-02 10:25:55 +02:00
case CATEGORY_INTEGER :
2016-09-07 10:28:57 +02:00
m_categoryMapper -> setCategoriesWithNames ( m_categories , m_categoryNames );
2017-02-10 18:53:14 +01:00
if ( m_categoryColors . size () > 0 )
{
m_categoryMapper -> setCycleColors ( m_categoryColors );
}
else
{
m_categoryMapper -> setInterpolateColors ( legendColors );
}
2016-08-02 10:25:55 +02:00
m_currentScalarMapper = m_categoryMapper . p ();
break ;
2012-05-18 09:45:23 +02:00
default :
break ;
}
2012-10-02 10:17:52 +02:00
2016-08-02 10:25:55 +02:00
if ( m_currentScalarMapper != m_categoryMapper . p ())
{
m_scalarMapperLegend -> setScalarMapper ( m_currentScalarMapper . p ());
}
2013-09-26 01:05:09 +02:00
double decadesInRange = 0 ;
2013-04-30 14:48:53 +02:00
2013-09-26 01:05:09 +02:00
if ( m_mappingMode == LOG10_CONTINUOUS || m_mappingMode == LOG10_DISCRETE )
{
2013-09-26 10:44:20 +02:00
// For log mapping, use the min value as reference for num valid digits
2013-09-27 14:43:11 +02:00
decadesInRange = cvf :: Math :: abs ( adjustedMin ) < cvf :: Math :: abs ( adjustedMax ) ? cvf :: Math :: abs ( adjustedMin ) : cvf :: Math :: abs ( adjustedMax );
2013-09-26 01:05:09 +02:00
decadesInRange = log10 ( decadesInRange );
}
else
{
2013-09-26 10:44:20 +02:00
// For linear mapping, use the max value as reference for num valid digits
2013-09-27 14:43:11 +02:00
double absRange = CVF_MAX ( cvf :: Math :: abs ( adjustedMax ), cvf :: Math :: abs ( adjustedMin ));
2013-09-26 01:05:09 +02:00
decadesInRange = log10 ( absRange );
}
decadesInRange = cvf :: Math :: ceil ( decadesInRange );
// Using Fixed format
2013-04-30 14:48:53 +02:00
NumberFormatType nft = m_tickNumberFormat ();
2016-08-01 22:27:03 +02:00
m_scalarMapperLegend -> setTickFormat (( cvf :: OverlayScalarMapperLegend :: NumberFormat ) nft );
2012-05-18 09:45:23 +02:00
2013-09-26 01:05:09 +02:00
// Set the fixed number of digits after the decimal point to the number needed to show all the significant digits.
2013-09-26 10:44:20 +02:00
int numDecimalDigits = m_precision ();
if ( nft != SCIENTIFIC )
{
2013-09-27 14:43:11 +02:00
numDecimalDigits -= static_cast < int > ( decadesInRange );
2013-09-26 10:44:20 +02:00
}
2016-08-01 22:27:03 +02:00
m_scalarMapperLegend -> setTickPrecision ( cvf :: Math :: clamp ( numDecimalDigits , 0 , 20 ));
2013-09-26 01:05:09 +02:00
2012-05-18 09:45:23 +02:00
if ( m_globalAutoMax != cvf :: UNDEFINED_DOUBLE )
{
2015-08-05 13:27:36 +02:00
m_userDefinedMaxValue . uiCapability () -> setUiName ( QString ( "Max " ) + "(" + QString :: number ( m_globalAutoMax , 'g' , m_precision ) + ")" );
2012-05-18 09:45:23 +02:00
}
else
{
2015-08-05 13:27:36 +02:00
m_userDefinedMaxValue . uiCapability () -> setUiName ( QString ());
2012-05-18 09:45:23 +02:00
}
if ( m_globalAutoMin != cvf :: UNDEFINED_DOUBLE )
{
2015-08-05 13:27:36 +02:00
m_userDefinedMinValue . uiCapability () -> setUiName ( QString ( "Min " ) + "(" + QString :: number ( m_globalAutoMin , 'g' , m_precision ) + ")" );
2012-05-18 09:45:23 +02:00
}
else
{
2015-08-05 13:27:36 +02:00
m_userDefinedMinValue . uiCapability () -> setUiName ( QString ());
2012-05-18 09:45:23 +02:00
}
}
2017-01-03 14:58:34 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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 ;
}
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: setAutomaticRanges ( double globalMin , double globalMax , double localMin , double localMax )
{
2013-09-30 13:29:29 +02:00
double candidateGlobalAutoMin = roundToNumSignificantDigits ( globalMin , m_precision );
double candidateGlobalAutoMax = roundToNumSignificantDigits ( globalMax , m_precision );
2012-05-18 09:45:23 +02:00
2013-09-30 13:29:29 +02:00
double candidateLocalAutoMin = roundToNumSignificantDigits ( localMin , m_precision );
double candidateLocalAutoMax = roundToNumSignificantDigits ( localMax , m_precision );
2012-05-18 09:45:23 +02:00
2013-09-30 13:29:29 +02:00
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 ();
}
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: initAfterRead ()
{
updateFieldVisibility ();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: updateFieldVisibility ()
{
2016-08-02 10:25:55 +02:00
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 )
2012-05-18 09:45:23 +02:00
{
2015-08-05 13:27:36 +02:00
m_userDefinedMaxValue . uiCapability () -> setUiHidden ( false );
m_userDefinedMinValue . uiCapability () -> setUiHidden ( false );
2012-05-18 09:45:23 +02:00
}
else
{
2015-08-05 13:27:36 +02:00
m_userDefinedMaxValue . uiCapability () -> setUiHidden ( true );
m_userDefinedMinValue . uiCapability () -> setUiHidden ( true );
2012-05-18 09:45:23 +02:00
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: setColorRangeMode ( ColorRangesType colorMode )
{
m_colorRangeMode = colorMode ;
updateLegend ();
}
2016-09-06 14:03:02 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: setMappingMode ( MappingType mappingType )
{
m_mappingMode = mappingType ;
updateLegend ();
}
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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:
2013-04-19 08:02:36 +02:00
cvf :: Font * standardFont = RiaApplication :: instance () -> standardFont ();
2016-08-01 22:27:03 +02:00
m_scalarMapperLegend = new cvf :: OverlayScalarMapperLegend ( standardFont );
2016-08-02 10:25:55 +02:00
m_categoryLegend = new caf :: CategoryLegend ( standardFont , m_categoryMapper . p ());
2012-05-18 09:45:23 +02:00
updateLegend ();
}
//--------------------------------------------------------------------------------------------------
2013-09-26 01:05:09 +02:00
/// Rounding the double value to given number of significant digits
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
2013-09-26 01:05:09 +02:00
double RimLegendConfig :: roundToNumSignificantDigits ( double domainValue , double numSignificantDigits )
2012-05-18 09:45:23 +02:00
{
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 );
2013-09-26 01:05:09 +02:00
double factor = pow ( 10.0 , numSignificantDigits - logDecValue );
2012-05-18 09:45:23 +02:00
double tmp = domainValue * factor ;
double integerPart ;
2013-09-26 01:05:09 +02:00
double fraction = modf ( tmp , & integerPart );
2013-09-27 14:43:11 +02:00
if ( cvf :: Math :: abs ( fraction ) >= 0.5 ) ( integerPart >= 0 ) ? integerPart ++: integerPart -- ;
2012-05-18 09:45:23 +02:00
double newDomainValue = integerPart / factor ;
return newDomainValue ;
}
2013-06-03 13:08:11 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: setClosestToZeroValues ( double globalPosClosestToZero , double globalNegClosestToZero , double localPosClosestToZero , double localNegClosestToZero )
{
2013-09-30 13:29:29 +02:00
bool needsUpdate = false ;
const double epsilon = std :: numeric_limits < double >:: epsilon ();
2013-06-03 13:08:11 +02:00
2013-09-30 13:29:29 +02:00
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 ;
}
2013-06-03 13:08:11 +02:00
2013-09-30 13:29:29 +02:00
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 ();
}
2013-06-03 13:08:11 +02:00
}
2016-08-02 10:25:55 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2016-09-09 12:10:24 +02:00
void RimLegendConfig :: setIntegerCategories ( const std :: vector < int >& categories )
2016-08-02 10:25:55 +02:00
{
2016-09-07 10:28:57 +02:00
m_categories = categories ;
m_categoryNames . clear ();
2017-02-10 18:53:14 +01:00
m_categoryColors . clear ();
2016-08-02 10:25:55 +02:00
2016-09-07 10:28:57 +02:00
updateLegend ();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2016-09-09 12:10:24 +02:00
void RimLegendConfig :: setNamedCategoriesInverse ( const std :: vector < QString >& categoryNames )
2016-09-07 10:28:57 +02:00
{
2016-09-09 12:10:24 +02:00
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 ;
2017-02-10 18:53:14 +01:00
m_categoryColors . clear ();
2016-09-06 15:35:17 +02:00
2016-09-06 14:03:02 +02:00
updateLegend ();
2016-08-02 10:25:55 +02:00
}
2017-01-03 09:27:25 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-02-15 15:21:13 +01:00
void RimLegendConfig :: setCategoryItems ( const std :: vector < std :: tuple < QString , int , cvf :: Color3ub > >& categories )
2017-01-03 09:27:25 +01:00
{
2017-02-15 15:21:13 +01:00
m_categories . clear ();
m_categoryNames . clear ();
m_categoryColors . clear ();
m_categoryColors . reserve ( categories . size ());
2017-01-03 09:27:25 +01:00
2017-02-15 15:21:13 +01:00
for ( auto item : categories )
2017-01-03 09:27:25 +01:00
{
2017-02-15 15:21:13 +01:00
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 ));
2017-01-03 09:27:25 +01:00
}
updateLegend ();
}
2017-02-14 09:18:00 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-03-21 08:49:45 +01:00
QString RimLegendConfig :: categoryNameFromCategoryValue ( double categoryResultValue ) const
2017-02-14 09:18:00 +01:00
{
2017-03-21 08:49:45 +01:00
if ( categoryResultValue == HUGE_VAL ) return "Undefined" ;
2017-02-14 09:18:00 +01:00
if ( m_categoryNames . size () > 0 )
{
for ( size_t categoryIndex = 0 ; categoryIndex < m_categories . size (); categoryIndex ++ )
{
2017-03-21 08:49:45 +01:00
if ( categoryResultValue == m_categories [ categoryIndex ])
2017-02-14 09:18:00 +01:00
{
return cvfqt :: Utils :: toQString ( m_categoryNames [ categoryIndex ]);
}
}
}
2017-03-21 08:49:45 +01:00
return QString ( "%1" ). arg ( categoryResultValue );
2017-02-14 09:18:00 +01:00
}
2016-08-02 10:25:55 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: setTitle ( const cvf :: String & title )
{
m_scalarMapperLegend -> setTitle ( title );
m_categoryLegend -> setTitle ( title );
}
2016-08-01 22:27:03 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf :: OverlayItem * RimLegendConfig :: legend ()
{
2016-08-02 10:25:55 +02:00
if ( m_currentScalarMapper == m_categoryMapper )
{
return m_categoryLegend . p ();
}
else
{
return m_scalarMapperLegend . p ();
}
2016-08-01 22:27:03 +02:00
}
2016-12-09 20:36:31 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: setUiValuesFromLegendConfig ( const RimLegendConfig * otherLegendConfig )
{
2016-12-09 21:16:43 +01:00
QString serializedObjectString = otherLegendConfig -> writeObjectToXmlString ();
this -> readObjectFromXmlString ( serializedObjectString , caf :: PdmDefaultObjectFactory :: instance ());
2016-12-09 20:36:31 +01:00
}
2017-02-10 08:37:48 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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 ;
default :
break ;
}
return RiaColorTables :: normalPaletteColors (). color3ubArray ();
}
2013-09-26 10:44:20 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimLegendConfig :: defineUiOrdering ( QString uiConfigName , caf :: PdmUiOrdering & uiOrdering )
{
2014-04-14 08:04:09 +02:00
{
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 );
}
2016-09-06 14:03:02 +02:00
updateFieldVisibility ();
2014-04-14 08:04:09 +02:00
}
2016-08-02 10:25:55 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList < caf :: PdmOptionItemInfo > RimLegendConfig :: calculateValueOptions ( const caf :: PdmFieldHandle * fieldNeedingOptions , bool * useOptionsOnly )
{
bool isCategoryResult = false ;
{
2016-09-06 10:27:30 +02:00
RimEclipseCellColors * eclCellColors = nullptr ;
2016-09-21 13:59:41 +02:00
this -> firstAncestorOrThisOfType ( eclCellColors );
2016-10-18 07:31:02 +02:00
RimGeoMechResultDefinition * gmCellColors = nullptr ;
2016-09-21 13:59:41 +02:00
this -> firstAncestorOrThisOfType ( gmCellColors );
2016-09-06 12:17:02 +02:00
RimCellEdgeColors * eclCellEdgColors = nullptr ;
2016-09-21 13:59:41 +02:00
this -> firstAncestorOrThisOfType ( eclCellEdgColors );
2016-09-06 10:27:30 +02:00
2016-09-06 12:17:02 +02:00
if ( ( eclCellColors && eclCellColors -> hasCategoryResult ())
|| ( gmCellColors && gmCellColors -> hasCategoryResult ())
|| ( eclCellEdgColors && eclCellEdgColors -> hasCategoryResult ()) )
2016-09-06 10:27:30 +02:00
{
isCategoryResult = true ;
}
2016-08-02 10:25:55 +02:00
}
2017-01-05 07:57:37 +01:00
QList < caf :: PdmOptionItemInfo > options ;
2016-10-13 12:13:32 +02:00
2016-08-02 10:25:55 +02:00
if ( fieldNeedingOptions == & m_mappingMode )
{
// This is an app enum field, see cafInternalPdmFieldTypeSpecializations.h for the default specialization of this type
2016-10-13 12:13:32 +02:00
std :: vector < MappingType > mappingTypes ;
mappingTypes . push_back ( LINEAR_DISCRETE );
mappingTypes . push_back ( LINEAR_CONTINUOUS );
mappingTypes . push_back ( LOG10_CONTINUOUS );
mappingTypes . push_back ( LOG10_DISCRETE );
2016-08-02 10:25:55 +02:00
if ( isCategoryResult )
{
2016-10-13 12:13:32 +02:00
mappingTypes . push_back ( CATEGORY_INTEGER );
}
for ( MappingType mapType : mappingTypes )
{
2017-01-05 07:57:37 +01:00
options . push_back ( caf :: PdmOptionItemInfo ( MappingEnum :: uiText ( mapType ), mapType ));
2016-08-02 10:25:55 +02:00
}
}
else if ( fieldNeedingOptions == & m_colorRangeMode )
{
// This is an app enum field, see cafInternalPdmFieldTypeSpecializations.h for the default specialization of this type
2016-10-13 12:13:32 +02:00
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 );
2016-08-02 10:25:55 +02:00
if ( isCategoryResult )
{
2016-10-13 12:13:32 +02:00
rangeTypes . push_back ( CATEGORY );
2016-08-02 10:25:55 +02:00
}
2016-10-13 12:13:32 +02:00
for ( ColorRangesType colType : rangeTypes )
{
2017-01-05 07:57:37 +01:00
options . push_back ( caf :: PdmOptionItemInfo ( ColorRangeEnum :: uiText ( colType ), colType ));
2016-10-13 12:13:32 +02:00
}
2016-08-02 10:25:55 +02:00
}
2017-01-03 14:58:34 +01:00
else if ( fieldNeedingOptions == & m_rangeMode )
{
if ( ! m_isAllTimeStepsRangeDisabled ) {
2017-01-05 07:57:37 +01:00
options . push_back ( caf :: PdmOptionItemInfo ( RangeModeEnum :: uiText ( RimLegendConfig :: AUTOMATIC_ALLTIMESTEPS ), RimLegendConfig :: AUTOMATIC_ALLTIMESTEPS ));
2017-01-03 14:58:34 +01:00
}
2017-01-05 07:57:37 +01:00
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 ));
2017-01-03 14:58:34 +01:00
}
2016-10-13 12:13:32 +02:00
2017-01-05 07:57:37 +01:00
return options ;
2016-08-02 10:25:55 +02:00
}