From d36bf92b553dde71d2b8811632208a46add37d28 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 9 Aug 2023 07:51:17 +0200 Subject: [PATCH] Adjust value ranges using floor and ceil * Use regression curve icon in grid cross plot * #10481 Use ceil and floor when adjusting precision for ranges --- .../Application/Tools/RiaNumericalTools.cpp | 35 +++++++-- .../Application/Tools/RiaNumericalTools.h | 10 ++- .../RimGridCrossPlotDataSet.cpp | 2 +- .../RimGridCrossPlotRegressionCurve.cpp | 8 +- .../RimRegularLegendConfig.cpp | 24 +++--- .../RimTernaryLegendConfig.cpp | 8 +- .../UnitTests/CMakeLists_files.cmake | 1 + .../UnitTests/RiaNumericalTools-Test.cpp | 76 +++++++++++++++++++ .../UnitTests/RifColorLegendData-Test.cpp | 45 ----------- 9 files changed, 137 insertions(+), 72 deletions(-) create mode 100644 ApplicationLibCode/UnitTests/RiaNumericalTools-Test.cpp diff --git a/ApplicationLibCode/Application/Tools/RiaNumericalTools.cpp b/ApplicationLibCode/Application/Tools/RiaNumericalTools.cpp index a248b0cfad..ade9a3d82b 100644 --- a/ApplicationLibCode/Application/Tools/RiaNumericalTools.cpp +++ b/ApplicationLibCode/Application/Tools/RiaNumericalTools.cpp @@ -70,7 +70,23 @@ double RiaNumericalTools::computeTenExponentFloor( double value ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RiaNumericalTools::roundToNumSignificantDigits( double value, double numSignificantDigits ) +double RiaNumericalTools::roundToNumSignificantDigitsFloor( double value, double numSignificantDigits ) +{ + return roundToNumSignificantDigits( value, numSignificantDigits, RoundToSignificantDigitsMode::FLOOR ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RiaNumericalTools::roundToNumSignificantDigitsCeil( double value, double numSignificantDigits ) +{ + return roundToNumSignificantDigits( value, numSignificantDigits, RoundToSignificantDigitsMode::CEIL ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RiaNumericalTools::roundToNumSignificantDigits( double value, double numSignificantDigits, RoundToSignificantDigitsMode mode ) { double absoluteValue = cvf::Math::abs( value ); if ( absoluteValue == 0.0 ) @@ -83,11 +99,20 @@ double RiaNumericalTools::roundToNumSignificantDigits( double value, double numS double factor = pow( 10.0, numSignificantDigits - logDecValue ); - double tmp = value * factor; - double integerPart; - double fraction = modf( tmp, &integerPart ); + double tmp = value * factor; + double integerPart = 0.0; + modf( tmp, &integerPart ); - if ( cvf::Math::abs( fraction ) >= 0.5 ) ( integerPart >= 0 ) ? integerPart++ : integerPart--; + double candidateValue = integerPart / factor; + + if ( mode == RoundToSignificantDigitsMode::CEIL && candidateValue < value ) + { + integerPart++; + } + else if ( mode == RoundToSignificantDigitsMode::FLOOR && value < candidateValue ) + { + integerPart--; + } double roundedValue = integerPart / factor; diff --git a/ApplicationLibCode/Application/Tools/RiaNumericalTools.h b/ApplicationLibCode/Application/Tools/RiaNumericalTools.h index eb97732b7f..6411c36946 100644 --- a/ApplicationLibCode/Application/Tools/RiaNumericalTools.h +++ b/ApplicationLibCode/Application/Tools/RiaNumericalTools.h @@ -25,6 +25,14 @@ double roundToClosestPowerOfTenFloor( double value ); double computeTenExponentCeil( double value ); double computeTenExponentFloor( double value ); -double roundToNumSignificantDigits( double value, double numSignificantDigits ); +double roundToNumSignificantDigitsFloor( double value, double numSignificantDigits ); +double roundToNumSignificantDigitsCeil( double value, double numSignificantDigits ); + +enum class RoundToSignificantDigitsMode +{ + CEIL, + FLOOR +}; +double roundToNumSignificantDigits( double value, double numSignificantDigits, RoundToSignificantDigitsMode mode ); }; // namespace RiaNumericalTools diff --git a/ApplicationLibCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp b/ApplicationLibCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp index e3ef6c4ae4..4c8b199a79 100644 --- a/ApplicationLibCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp +++ b/ApplicationLibCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp @@ -127,7 +127,7 @@ RimGridCrossPlotDataSet::RimGridCrossPlotDataSet() CAF_PDM_InitFieldNoDefault( &m_crossPlotCurves, "CrossPlotCurves", "Curves" ); m_crossPlotCurves.uiCapability()->setUiTreeHidden( true ); - CAF_PDM_InitFieldNoDefault( &m_crossPlotRegressionCurves, "CrossPlotRegressionCurves", "Regression Curves" ); + CAF_PDM_InitFieldNoDefault( &m_crossPlotRegressionCurves, "CrossPlotRegressionCurves", "Regression Curves", ":/regression-curve.svg" ); CAF_PDM_InitField( &m_useCustomColor, "UseCustomColor", false, "Use Custom Color" ); CAF_PDM_InitField( &m_customColor, "CustomColor", cvf::Color3f( cvf::Color3f::BLACK ), "Custom Color" ); diff --git a/ApplicationLibCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotRegressionCurve.cpp b/ApplicationLibCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotRegressionCurve.cpp index cdc5548be5..2d6d73e0fb 100644 --- a/ApplicationLibCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotRegressionCurve.cpp +++ b/ApplicationLibCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotRegressionCurve.cpp @@ -376,8 +376,8 @@ void RimGridCrossPlotRegressionCurve::defineEditorAttribute( const caf::PdmField if ( auto* myAttr = dynamic_cast( attribute ) ) { auto [min, max] = m_dataRangeX; - myAttr->m_minimum = RiaNumericalTools::roundToNumSignificantDigits( min, 2 ); - myAttr->m_maximum = RiaNumericalTools::roundToNumSignificantDigits( max, 2 ); + myAttr->m_minimum = RiaNumericalTools::roundToNumSignificantDigitsFloor( min, 2 ); + myAttr->m_maximum = RiaNumericalTools::roundToNumSignificantDigitsCeil( max, 2 ); myAttr->m_decimals = 3; } } @@ -386,8 +386,8 @@ void RimGridCrossPlotRegressionCurve::defineEditorAttribute( const caf::PdmField if ( auto* myAttr = dynamic_cast( attribute ) ) { auto [min, max] = m_dataRangeY; - myAttr->m_minimum = RiaNumericalTools::roundToNumSignificantDigits( min, 2 ); - myAttr->m_maximum = RiaNumericalTools::roundToNumSignificantDigits( max, 2 ); + myAttr->m_minimum = RiaNumericalTools::roundToNumSignificantDigitsFloor( min, 2 ); + myAttr->m_maximum = RiaNumericalTools::roundToNumSignificantDigitsCeil( max, 2 ); myAttr->m_decimals = 3; } } diff --git a/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.cpp b/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.cpp index c65f0986e5..33762ea36b 100644 --- a/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.cpp @@ -258,11 +258,11 @@ void RimRegularLegendConfig::fieldChangedByUi( const caf::PdmFieldHandle* change { if ( m_userDefinedMaxValue == m_userDefinedMaxValue.defaultValue() && m_globalAutoMax != cvf::UNDEFINED_DOUBLE ) { - m_userDefinedMaxValue = RiaNumericalTools::roundToNumSignificantDigits( m_globalAutoMax, m_precision ); + m_userDefinedMaxValue = RiaNumericalTools::roundToNumSignificantDigitsCeil( m_globalAutoMax, m_precision ); } if ( m_userDefinedMinValue == m_userDefinedMinValue.defaultValue() && m_globalAutoMin != cvf::UNDEFINED_DOUBLE ) { - m_userDefinedMinValue = RiaNumericalTools::roundToNumSignificantDigits( m_globalAutoMin, m_precision ); + m_userDefinedMinValue = RiaNumericalTools::roundToNumSignificantDigitsFloor( m_globalAutoMin, m_precision ); } } updateFieldVisibility(); @@ -403,24 +403,24 @@ void RimRegularLegendConfig::updateLegend() if ( m_rangeMode == RangeModeType::AUTOMATIC_ALLTIMESTEPS ) { - adjustedMin = RiaNumericalTools::roundToNumSignificantDigits( m_globalAutoMin, m_precision ); - adjustedMax = RiaNumericalTools::roundToNumSignificantDigits( m_globalAutoMax, m_precision ); + adjustedMin = RiaNumericalTools::roundToNumSignificantDigitsFloor( m_globalAutoMin, m_precision ); + adjustedMax = RiaNumericalTools::roundToNumSignificantDigitsCeil( m_globalAutoMax, m_precision ); posClosestToZero = m_globalAutoPosClosestToZero; negClosestToZero = m_globalAutoNegClosestToZero; } else if ( m_rangeMode == RangeModeType::AUTOMATIC_CURRENT_TIMESTEP ) { - adjustedMin = RiaNumericalTools::roundToNumSignificantDigits( m_localAutoMin, m_precision ); - adjustedMax = RiaNumericalTools::roundToNumSignificantDigits( m_localAutoMax, m_precision ); + adjustedMin = RiaNumericalTools::roundToNumSignificantDigitsFloor( m_localAutoMin, m_precision ); + adjustedMax = RiaNumericalTools::roundToNumSignificantDigitsCeil( m_localAutoMax, m_precision ); posClosestToZero = m_localAutoPosClosestToZero; negClosestToZero = m_localAutoNegClosestToZero; } else { - adjustedMin = RiaNumericalTools::roundToNumSignificantDigits( m_userDefinedMinValue, m_precision ); - adjustedMax = RiaNumericalTools::roundToNumSignificantDigits( m_userDefinedMaxValue, m_precision ); + adjustedMin = RiaNumericalTools::roundToNumSignificantDigitsFloor( m_userDefinedMinValue, m_precision ); + adjustedMax = RiaNumericalTools::roundToNumSignificantDigitsCeil( m_userDefinedMaxValue, m_precision ); posClosestToZero = m_globalAutoPosClosestToZero; negClosestToZero = m_globalAutoNegClosestToZero; @@ -626,11 +626,11 @@ void RimRegularLegendConfig::disableAllTimeStepsRange( bool doDisable ) //-------------------------------------------------------------------------------------------------- void RimRegularLegendConfig::setAutomaticRanges( double globalMin, double globalMax, double localMin, double localMax ) { - double candidateGlobalAutoMin = RiaNumericalTools::roundToNumSignificantDigits( globalMin, m_precision ); - double candidateGlobalAutoMax = RiaNumericalTools::roundToNumSignificantDigits( globalMax, m_precision ); + double candidateGlobalAutoMin = RiaNumericalTools::roundToNumSignificantDigitsFloor( globalMin, m_precision ); + double candidateGlobalAutoMax = RiaNumericalTools::roundToNumSignificantDigitsCeil( globalMax, m_precision ); - double candidateLocalAutoMin = RiaNumericalTools::roundToNumSignificantDigits( localMin, m_precision ); - double candidateLocalAutoMax = RiaNumericalTools::roundToNumSignificantDigits( localMax, m_precision ); + double candidateLocalAutoMin = RiaNumericalTools::roundToNumSignificantDigitsFloor( localMin, m_precision ); + double candidateLocalAutoMax = RiaNumericalTools::roundToNumSignificantDigitsCeil( localMax, m_precision ); m_globalAutoMin = candidateGlobalAutoMin; m_globalAutoMax = candidateGlobalAutoMax; diff --git a/ApplicationLibCode/ProjectDataModel/RimTernaryLegendConfig.cpp b/ApplicationLibCode/ProjectDataModel/RimTernaryLegendConfig.cpp index d622886ba8..45df0d9e93 100644 --- a/ApplicationLibCode/ProjectDataModel/RimTernaryLegendConfig.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimTernaryLegendConfig.cpp @@ -205,11 +205,11 @@ void RimTernaryLegendConfig::updateLegend() //-------------------------------------------------------------------------------------------------- void RimTernaryLegendConfig::setAutomaticRanges( TernaryArrayIndex ternaryIndex, double globalMin, double globalMax, double localMin, double localMax ) { - double candidateGlobalAutoMin = RiaNumericalTools::roundToNumSignificantDigits( globalMin, precision ); - double candidateGlobalAutoMax = RiaNumericalTools::roundToNumSignificantDigits( globalMax, precision ); + double candidateGlobalAutoMin = RiaNumericalTools::roundToNumSignificantDigitsFloor( globalMin, precision ); + double candidateGlobalAutoMax = RiaNumericalTools::roundToNumSignificantDigitsCeil( globalMax, precision ); - double candidateLocalAutoMin = RiaNumericalTools::roundToNumSignificantDigits( localMin, precision ); - double candidateLocalAutoMax = RiaNumericalTools::roundToNumSignificantDigits( localMax, precision ); + double candidateLocalAutoMin = RiaNumericalTools::roundToNumSignificantDigitsFloor( localMin, precision ); + double candidateLocalAutoMax = RiaNumericalTools::roundToNumSignificantDigitsCeil( localMax, precision ); m_globalAutoMin[ternaryIndex] = candidateGlobalAutoMin; m_globalAutoMax[ternaryIndex] = candidateGlobalAutoMax; diff --git a/ApplicationLibCode/UnitTests/CMakeLists_files.cmake b/ApplicationLibCode/UnitTests/CMakeLists_files.cmake index 7ec80e7d4d..67d65905c6 100644 --- a/ApplicationLibCode/UnitTests/CMakeLists_files.cmake +++ b/ApplicationLibCode/UnitTests/CMakeLists_files.cmake @@ -95,6 +95,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimSummaryRegressionAnalysisCurve-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellLogCalculatedCurve-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RigWellLogCurveData-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaNumericalTools-Test.cpp ) if(RESINSIGHT_ENABLE_GRPC) diff --git a/ApplicationLibCode/UnitTests/RiaNumericalTools-Test.cpp b/ApplicationLibCode/UnitTests/RiaNumericalTools-Test.cpp new file mode 100644 index 0000000000..177056b065 --- /dev/null +++ b/ApplicationLibCode/UnitTests/RiaNumericalTools-Test.cpp @@ -0,0 +1,76 @@ +#include "gtest/gtest.h" + +#include "RiaNumericalTools.h" + +TEST( RiaNumericalTools, LogTenFunctions ) +{ + { + // Negative values will return zero + double value = -0.0015; + + auto exponentCeil = RiaNumericalTools::computeTenExponentCeil( value ); + EXPECT_EQ( 0.0f, exponentCeil ); + + auto exponentFloor = RiaNumericalTools::computeTenExponentFloor( value ); + EXPECT_EQ( 0.0f, exponentFloor ); + } + + { + double value = 0.15; + + auto exponentCeil = RiaNumericalTools::computeTenExponentCeil( value ); + EXPECT_EQ( 0.0f, exponentCeil ); + + auto exponentFloor = RiaNumericalTools::computeTenExponentFloor( value ); + EXPECT_EQ( -1.0f, exponentFloor ); + } + + { + double value = 1.5; + + auto exponentCeil = RiaNumericalTools::computeTenExponentCeil( value ); + EXPECT_EQ( 1.0f, exponentCeil ); + + auto exponentFloor = RiaNumericalTools::computeTenExponentFloor( value ); + EXPECT_EQ( 0.0f, exponentFloor ); + } + + { + double value = 15; + + auto exponentCeil = RiaNumericalTools::computeTenExponentCeil( value ); + EXPECT_EQ( 2.0f, exponentCeil ); + + auto exponentFloor = RiaNumericalTools::computeTenExponentFloor( value ); + EXPECT_EQ( 1.0f, exponentFloor ); + } +} + +TEST( RiaNumericalTools, RoundToSignificant ) +{ + struct TestValues + { + double value; + double expectedCeil; + double expectedFloor; + }; + + TestValues testValues[] = { + { -0.00152, -0.0015, -0.0016 }, + { -15, -15, -15 }, + { -159, -150, -160 }, + { 0.02, 0.02, 0.02 }, + { 152, 160.0, 150.0 }, + { 1520, 1600.0, 1500.0 }, + { 15913, 16000.0, 15000.0 }, + }; + + for ( const auto& testValue : testValues ) + { + auto valueCeil = RiaNumericalTools::roundToNumSignificantDigitsCeil( testValue.value, 2 ); + EXPECT_EQ( testValue.expectedCeil, valueCeil ); + + auto valueFloor = RiaNumericalTools::roundToNumSignificantDigitsFloor( testValue.value, 2 ); + EXPECT_EQ( testValue.expectedFloor, valueFloor ); + } +} diff --git a/ApplicationLibCode/UnitTests/RifColorLegendData-Test.cpp b/ApplicationLibCode/UnitTests/RifColorLegendData-Test.cpp index a3031c94e4..8d6a02e4e4 100644 --- a/ApplicationLibCode/UnitTests/RifColorLegendData-Test.cpp +++ b/ApplicationLibCode/UnitTests/RifColorLegendData-Test.cpp @@ -1,6 +1,5 @@ #include "gtest/gtest.h" -#include "RiaNumericalTools.h" #include "RiaTestDataDirectory.h" #include "RifColorLegendData.h" #include "RigFormationNames.h" @@ -84,47 +83,3 @@ TEST( RifColorLegendData, ReadLYRFileWithColorHTML ) EXPECT_EQ( 0.0f, formationColor.g() ); EXPECT_EQ( 0.0f, formationColor.b() ); } - -TEST( RiaNumericalTools, LogTenFunctions ) -{ - { - // Negative values will return zero - double value = -0.0015; - - auto exponentCeil = RiaNumericalTools::computeTenExponentCeil( value ); - EXPECT_EQ( 0.0f, exponentCeil ); - - auto exponentFloor = RiaNumericalTools::computeTenExponentFloor( value ); - EXPECT_EQ( 0.0f, exponentFloor ); - } - - { - double value = 0.15; - - auto exponentCeil = RiaNumericalTools::computeTenExponentCeil( value ); - EXPECT_EQ( 0.0f, exponentCeil ); - - auto exponentFloor = RiaNumericalTools::computeTenExponentFloor( value ); - EXPECT_EQ( -1.0f, exponentFloor ); - } - - { - double value = 1.5; - - auto exponentCeil = RiaNumericalTools::computeTenExponentCeil( value ); - EXPECT_EQ( 1.0f, exponentCeil ); - - auto exponentFloor = RiaNumericalTools::computeTenExponentFloor( value ); - EXPECT_EQ( 0.0f, exponentFloor ); - } - - { - double value = 15; - - auto exponentCeil = RiaNumericalTools::computeTenExponentCeil( value ); - EXPECT_EQ( 2.0f, exponentCeil ); - - auto exponentFloor = RiaNumericalTools::computeTenExponentFloor( value ); - EXPECT_EQ( 1.0f, exponentFloor ); - } -}