diff --git a/ApplicationLibCode/Application/Tools/CMakeLists_files.cmake b/ApplicationLibCode/Application/Tools/CMakeLists_files.cmake index a161adf604..20f855efee 100644 --- a/ApplicationLibCode/Application/Tools/CMakeLists_files.cmake +++ b/ApplicationLibCode/Application/Tools/CMakeLists_files.cmake @@ -51,6 +51,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryStringTools.h ${CMAKE_CURRENT_LIST_DIR}/RiaNetworkTools.h ${CMAKE_CURRENT_LIST_DIR}/RiaOpenMPTools.h + ${CMAKE_CURRENT_LIST_DIR}/RiaNumericalTools.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -99,6 +100,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryStringTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaNetworkTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaOpenMPTools.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaNumericalTools.cpp ) list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES}) diff --git a/ApplicationLibCode/Application/Tools/RiaNumericalTools.cpp b/ApplicationLibCode/Application/Tools/RiaNumericalTools.cpp new file mode 100644 index 0000000000..a248b0cfad --- /dev/null +++ b/ApplicationLibCode/Application/Tools/RiaNumericalTools.cpp @@ -0,0 +1,95 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2022 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RiaNumericalTools.h" + +#include "cvfMath.h" + +#include +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RiaNumericalTools::roundToClosestPowerOfTenCeil( double value ) +{ + auto exponent = computeTenExponentCeil( value ); + return pow( 10.0, exponent ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RiaNumericalTools::roundToClosestPowerOfTenFloor( double value ) +{ + auto exponent = computeTenExponentFloor( value ); + return pow( 10.0, exponent ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RiaNumericalTools::computeTenExponentCeil( double value ) +{ + if ( value < 0.0 ) return 0.0; + + double logDecValueMax = log10( value ); + logDecValueMax = cvf::Math::ceil( logDecValueMax ); + + return logDecValueMax; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RiaNumericalTools::computeTenExponentFloor( double value ) +{ + if ( value < 0.0 ) return 0.0; + + double logDecValueMin = log10( value ); + logDecValueMin = cvf::Math::floor( logDecValueMin ); + + return logDecValueMin; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RiaNumericalTools::roundToNumSignificantDigits( double value, double numSignificantDigits ) +{ + double absoluteValue = cvf::Math::abs( value ); + if ( absoluteValue == 0.0 ) + { + return 0.0; + } + + double logDecValue = log10( absoluteValue ); + logDecValue = cvf::Math::ceil( logDecValue ); + + double factor = pow( 10.0, numSignificantDigits - logDecValue ); + + double tmp = value * factor; + double integerPart; + double fraction = modf( tmp, &integerPart ); + + if ( cvf::Math::abs( fraction ) >= 0.5 ) ( integerPart >= 0 ) ? integerPart++ : integerPart--; + + double roundedValue = integerPart / factor; + + return roundedValue; +} diff --git a/ApplicationLibCode/Application/Tools/RiaNumericalTools.h b/ApplicationLibCode/Application/Tools/RiaNumericalTools.h new file mode 100644 index 0000000000..eb97732b7f --- /dev/null +++ b/ApplicationLibCode/Application/Tools/RiaNumericalTools.h @@ -0,0 +1,30 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2022 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +namespace RiaNumericalTools +{ +double roundToClosestPowerOfTenCeil( double value ); +double roundToClosestPowerOfTenFloor( double value ); +double computeTenExponentCeil( double value ); +double computeTenExponentFloor( double value ); + +double roundToNumSignificantDigits( double value, double numSignificantDigits ); + +}; // namespace RiaNumericalTools diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp b/ApplicationLibCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp index de24fc2c02..d50fc91a68 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp @@ -18,6 +18,7 @@ #include "RimWellAllocationPlot.h" +#include "RiaNumericalTools.h" #include "RiaPreferences.h" #include "RigAccWellFlowCalculator.h" @@ -374,9 +375,7 @@ void RimWellAllocationPlot::updateFromWell() double depthSpan = 0.1 * cvf::Math::abs( availableMinDepth - availableMaxDepth ); // Round off value to floored decade - double logDecValue = log10( depthSpan ); - logDecValue = cvf::Math::floor( logDecValue ); - depthSpan = pow( 10.0, logDecValue ); + depthSpan = RiaNumericalTools::roundToClosestPowerOfTenFloor( depthSpan ); double dummyNegativeDepthValue = curveDepthValues.back() - depthSpan; diff --git a/ApplicationLibCode/ProjectDataModel/RimPlotAxisLogRangeCalculator.cpp b/ApplicationLibCode/ProjectDataModel/RimPlotAxisLogRangeCalculator.cpp index b10d648262..57c59a2729 100644 --- a/ApplicationLibCode/ProjectDataModel/RimPlotAxisLogRangeCalculator.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimPlotAxisLogRangeCalculator.cpp @@ -18,6 +18,7 @@ #include "RimPlotAxisLogRangeCalculator.h" +#include "RiaNumericalTools.h" #include "RiaPlotDefines.h" #include "RimPlotCurve.h" @@ -51,16 +52,11 @@ void RimPlotAxisLogRangeCalculator::computeAxisRange( double* minPositive, doubl if ( curveValueRange( curve, &minPosCurveValue, &maxCurveValue ) ) { - if ( minPosCurveValue < minPosValue ) - { - CVF_ASSERT( minPosCurveValue > 0.0 ); - minPosValue = minPosCurveValue; - } + minPosCurveValue = RiaNumericalTools::roundToClosestPowerOfTenFloor( minPosCurveValue ); + maxCurveValue = RiaNumericalTools::roundToClosestPowerOfTenCeil( maxCurveValue ); - if ( maxCurveValue > maxValue ) - { - maxValue = maxCurveValue; - } + minPosValue = std::min( minPosValue, minPosCurveValue ); + maxValue = std::max( maxValue, maxCurveValue ); } } diff --git a/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.cpp b/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.cpp index 7dd2f753eb..0bcc183eb2 100644 --- a/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.cpp @@ -23,6 +23,7 @@ #include "RiaApplication.h" #include "RiaColorTables.h" #include "RiaNumberFormat.h" +#include "RiaNumericalTools.h" #include "RiaPreferences.h" #include "RimCellEdgeColors.h" @@ -266,11 +267,11 @@ void RimRegularLegendConfig::fieldChangedByUi( const caf::PdmFieldHandle* change { if ( m_userDefinedMaxValue == m_userDefinedMaxValue.defaultValue() && m_globalAutoMax != cvf::UNDEFINED_DOUBLE ) { - m_userDefinedMaxValue = roundToNumSignificantDigits( m_globalAutoMax, m_precision ); + m_userDefinedMaxValue = RiaNumericalTools::roundToNumSignificantDigits( m_globalAutoMax, m_precision ); } if ( m_userDefinedMinValue == m_userDefinedMinValue.defaultValue() && m_globalAutoMin != cvf::UNDEFINED_DOUBLE ) { - m_userDefinedMinValue = roundToNumSignificantDigits( m_globalAutoMin, m_precision ); + m_userDefinedMinValue = RiaNumericalTools::roundToNumSignificantDigits( m_globalAutoMin, m_precision ); } } updateFieldVisibility(); @@ -417,24 +418,24 @@ void RimRegularLegendConfig::updateLegend() if ( m_rangeMode == RangeModeType::AUTOMATIC_ALLTIMESTEPS ) { - adjustedMin = roundToNumSignificantDigits( m_globalAutoMin, m_precision ); - adjustedMax = roundToNumSignificantDigits( m_globalAutoMax, m_precision ); + adjustedMin = RiaNumericalTools::roundToNumSignificantDigits( m_globalAutoMin, m_precision ); + adjustedMax = RiaNumericalTools::roundToNumSignificantDigits( m_globalAutoMax, m_precision ); posClosestToZero = m_globalAutoPosClosestToZero; negClosestToZero = m_globalAutoNegClosestToZero; } else if ( m_rangeMode == RangeModeType::AUTOMATIC_CURRENT_TIMESTEP ) { - adjustedMin = roundToNumSignificantDigits( m_localAutoMin, m_precision ); - adjustedMax = roundToNumSignificantDigits( m_localAutoMax, m_precision ); + adjustedMin = RiaNumericalTools::roundToNumSignificantDigits( m_localAutoMin, m_precision ); + adjustedMax = RiaNumericalTools::roundToNumSignificantDigits( m_localAutoMax, m_precision ); posClosestToZero = m_localAutoPosClosestToZero; negClosestToZero = m_localAutoNegClosestToZero; } else { - adjustedMin = roundToNumSignificantDigits( m_userDefinedMinValue, m_precision ); - adjustedMax = roundToNumSignificantDigits( m_userDefinedMaxValue, m_precision ); + adjustedMin = RiaNumericalTools::roundToNumSignificantDigits( m_userDefinedMinValue, m_precision ); + adjustedMax = RiaNumericalTools::roundToNumSignificantDigits( m_userDefinedMaxValue, m_precision ); posClosestToZero = m_globalAutoPosClosestToZero; negClosestToZero = m_globalAutoNegClosestToZero; @@ -632,11 +633,11 @@ void RimRegularLegendConfig::disableAllTimeStepsRange( bool doDisable ) //-------------------------------------------------------------------------------------------------- void RimRegularLegendConfig::setAutomaticRanges( double globalMin, double globalMax, double localMin, double localMax ) { - double candidateGlobalAutoMin = roundToNumSignificantDigits( globalMin, m_precision ); - double candidateGlobalAutoMax = roundToNumSignificantDigits( globalMax, m_precision ); + double candidateGlobalAutoMin = RiaNumericalTools::roundToNumSignificantDigits( globalMin, m_precision ); + double candidateGlobalAutoMax = RiaNumericalTools::roundToNumSignificantDigits( globalMax, m_precision ); - double candidateLocalAutoMin = roundToNumSignificantDigits( localMin, m_precision ); - double candidateLocalAutoMax = roundToNumSignificantDigits( localMax, m_precision ); + double candidateLocalAutoMin = RiaNumericalTools::roundToNumSignificantDigits( localMin, m_precision ); + double candidateLocalAutoMax = RiaNumericalTools::roundToNumSignificantDigits( localMax, m_precision ); m_globalAutoMin = candidateGlobalAutoMin; m_globalAutoMax = candidateGlobalAutoMax; @@ -770,33 +771,6 @@ void RimRegularLegendConfig::onRecreateLegend() updateLegend(); } -//-------------------------------------------------------------------------------------------------- -/// Rounding the double value to given number of significant digits -//-------------------------------------------------------------------------------------------------- -double RimRegularLegendConfig::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; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -872,8 +846,8 @@ void RimRegularLegendConfig::updateTickCountAndUserDefinedRange() { if ( m_mappingMode() == MappingType::LOG10_CONTINUOUS || m_mappingMode() == MappingType::LOG10_DISCRETE ) { - double exponentMax = computeTenExponentCeil( m_globalAutoMax ); - double exponentMin = computeTenExponentFloor( m_globalAutoPosClosestToZero ); + double exponentMax = RiaNumericalTools::computeTenExponentCeil( m_globalAutoMax ); + double exponentMin = RiaNumericalTools::computeTenExponentFloor( m_globalAutoPosClosestToZero ); m_userDefinedMaxValue = pow( 10, exponentMax ); m_userDefinedMinValue = pow( 10, exponentMin ); @@ -1171,32 +1145,6 @@ RimColorLegend* RimRegularLegendConfig::mapToColorLegend( ColorRangesType colorT return project->colorLegendCollection()->findByName( RimRegularLegendConfig::ColorRangeEnum::uiText( colorType ) ); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -double RimRegularLegendConfig::computeTenExponentCeil( double value ) -{ - if ( value < 0.0 ) return 0.0; - - double logDecValueMax = log10( value ); - logDecValueMax = cvf::Math::ceil( logDecValueMax ); - - return logDecValueMax; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -double RimRegularLegendConfig::computeTenExponentFloor( double value ) -{ - if ( value < 0.0 ) return 0.0; - - double logDecValueMin = log10( value ); - logDecValueMin = cvf::Math::floor( logDecValueMin ); - - return logDecValueMin; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.h b/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.h index 19cbb1fbcc..2d6c458d8d 100644 --- a/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.h +++ b/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.h @@ -163,9 +163,6 @@ public: static cvf::Color3ubArray colorArrayFromColorType( ColorRangesType colorType ); static RimColorLegend* mapToColorLegend( ColorRangesType colorType ); - static double computeTenExponentCeil( double value ); - static double computeTenExponentFloor( double value ); - void updateFonts() override; QString valueToText( double value ) const; @@ -184,9 +181,8 @@ private: void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; - void updateLegend(); - void updateFieldVisibility(); - double roundToNumSignificantDigits( double value, double precision ); + void updateLegend(); + void updateFieldVisibility(); void updateCategoryItems(); void configureCategoryMapper(); diff --git a/ApplicationLibCode/ProjectDataModel/RimTernaryLegendConfig.cpp b/ApplicationLibCode/ProjectDataModel/RimTernaryLegendConfig.cpp index 9c05d725fe..1f57107a15 100644 --- a/ApplicationLibCode/ProjectDataModel/RimTernaryLegendConfig.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimTernaryLegendConfig.cpp @@ -21,6 +21,7 @@ #include "RiaApplication.h" #include "RiaColorTables.h" +#include "RiaNumericalTools.h" #include "RiaPreferences.h" #include "RiaResultNames.h" @@ -221,11 +222,11 @@ void RimTernaryLegendConfig::setAutomaticRanges( TernaryArrayIndex ternaryIndex, double localMin, double localMax ) { - double candidateGlobalAutoMin = roundToNumSignificantDigits( globalMin, precision ); - double candidateGlobalAutoMax = roundToNumSignificantDigits( globalMax, precision ); + double candidateGlobalAutoMin = RiaNumericalTools::roundToNumSignificantDigits( globalMin, precision ); + double candidateGlobalAutoMax = RiaNumericalTools::roundToNumSignificantDigits( globalMax, precision ); - double candidateLocalAutoMin = roundToNumSignificantDigits( localMin, precision ); - double candidateLocalAutoMax = roundToNumSignificantDigits( localMax, precision ); + double candidateLocalAutoMin = RiaNumericalTools::roundToNumSignificantDigits( localMin, precision ); + double candidateLocalAutoMax = RiaNumericalTools::roundToNumSignificantDigits( localMax, precision ); m_globalAutoMin[ternaryIndex] = candidateGlobalAutoMin; m_globalAutoMax[ternaryIndex] = candidateGlobalAutoMax; @@ -262,33 +263,6 @@ void RimTernaryLegendConfig::setUiValuesFromLegendConfig( const RimTernaryLegend this->updateLegend(); } -//-------------------------------------------------------------------------------------------------- -/// Rounding the double value to given number of significant digits -//-------------------------------------------------------------------------------------------------- -double RimTernaryLegendConfig::roundToNumSignificantDigits( double domainValue, double numSignificantDigits ) -{ - double absDomainValue = cvf::Math::abs( domainValue ); - if ( absDomainValue == 0.0 ) - { - return 0.0; - } - - double logDecValue = log10( absDomainValue ); - logDecValue = cvf::Math::ceil( logDecValue ); - - double factor = pow( 10.0, numSignificantDigits - logDecValue ); - - double tmp = domainValue * factor; - double integerPart; - double fraction = modf( tmp, &integerPart ); - - if ( cvf::Math::abs( fraction ) >= 0.5 ) ( integerPart >= 0 ) ? integerPart++ : integerPart--; - - double newDomainValue = integerPart / factor; - - return newDomainValue; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimTernaryLegendConfig.h b/ApplicationLibCode/ProjectDataModel/RimTernaryLegendConfig.h index 1ad9f469d1..12f8628916 100644 --- a/ApplicationLibCode/ProjectDataModel/RimTernaryLegendConfig.h +++ b/ApplicationLibCode/ProjectDataModel/RimTernaryLegendConfig.h @@ -73,9 +73,8 @@ private: caf::PdmUiEditorAttribute* attribute ) override; caf::PdmFieldHandle* objectToggleField() override; - void updateLegend(); - void updateLabelText(); - double roundToNumSignificantDigits( double value, double precision ); + void updateLegend(); + void updateLabelText(); void ternaryRanges( double& soilLower, double& soilUpper, diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp index 8d68993cd5..4d6a2f6d6f 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp @@ -984,11 +984,11 @@ void RimSummaryCaseCollection::computeMinMax( const RifEclipseSummaryAddress& ad double minimumValue( std::numeric_limits::infinity() ); double maximumValue( -std::numeric_limits::infinity() ); - std::vector values; for ( const auto& s : m_cases() ) { if ( !s->summaryReader() ) continue; + std::vector values; s->summaryReader()->values( address, &values ); if ( values.empty() ) continue; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp index 0904705892..8b171cbf0b 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp @@ -19,6 +19,7 @@ #include "RimSummaryMultiPlot.h" #include "RiaApplication.h" +#include "RiaNumericalTools.h" #include "RiaPlotDefines.h" #include "RiaSummaryAddressAnalyzer.h" #include "RiaSummaryStringTools.h" @@ -210,10 +211,17 @@ void RimSummaryMultiPlot::insertPlot( RimPlot* plot, size_t index ) sumPlot->curvesChanged.connect( this, &RimSummaryMultiPlot::onSubPlotChanged ); sumPlot->plotZoomedByUser.connect( this, &RimSummaryMultiPlot::onSubPlotZoomed ); sumPlot->titleChanged.connect( this, &RimSummaryMultiPlot::onSubPlotChanged ); + sumPlot->axisChangedReloadRequired.connect( this, &RimSummaryMultiPlot::onSubPlotAxisReloadRequired ); bool isMinMaxOverridden = m_axisRangeAggregation() != AxisRangeAggregation::NONE; setAutoValueStatesForPlot( sumPlot, isMinMaxOverridden, m_autoAdjustAppearance() ); + auto plots = summaryPlots(); + if ( !plots.empty() && m_linkTimeAxis ) + { + sumPlot->copyAxisPropertiesFromOther( RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM, *plots.front() ); + } + RimMultiPlot::insertPlot( plot, index ); } @@ -447,11 +455,7 @@ void RimSummaryMultiPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedFi } else if ( changedField == &m_linkTimeAxis ) { - auto plots = summaryPlots(); - if ( !plots.empty() ) - { - syncTimeAxisRanges( plots.front() ); - } + updateTimeAxisRangesFromFirstPlot(); } else if ( changedField == &m_linkSubPlotAxes || changedField == &m_axisRangeAggregation || changedField == &m_linkTimeAxis ) @@ -717,6 +721,7 @@ void RimSummaryMultiPlot::initAfterRead() plot->curvesChanged.connect( this, &RimSummaryMultiPlot::onSubPlotChanged ); plot->plotZoomedByUser.connect( this, &RimSummaryMultiPlot::onSubPlotZoomed ); plot->titleChanged.connect( this, &RimSummaryMultiPlot::onSubPlotChanged ); + plot->axisChangedReloadRequired.connect( this, &RimSummaryMultiPlot::onSubPlotAxisReloadRequired ); } updateStepDimensionFromDefault(); } @@ -751,6 +756,8 @@ void RimSummaryMultiPlot::zoomAll() updateZoom(); + updateTimeAxisRangesFromFirstPlot(); + return; } @@ -758,6 +765,20 @@ void RimSummaryMultiPlot::zoomAll() RimMultiPlot::zoomAll(); syncAxisRanges(); + + updateTimeAxisRangesFromFirstPlot(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryMultiPlot::updateTimeAxisRangesFromFirstPlot() +{ + if ( m_linkTimeAxis && !summaryPlots().empty() ) + { + setAutoScaleXEnabled( false ); + syncTimeAxisRanges( summaryPlots().front() ); + } } //-------------------------------------------------------------------------------------------------- @@ -894,15 +915,15 @@ void RimSummaryMultiPlot::syncAxisRanges() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimSummaryMultiPlot::syncTimeAxisRanges( RimSummaryPlot* summaryPlot ) +void RimSummaryMultiPlot::syncTimeAxisRanges( RimSummaryPlot* sourceSummaryPlot ) { - if ( m_linkTimeAxis ) + if ( sourceSummaryPlot && m_linkTimeAxis() ) { for ( auto plot : summaryPlots() ) { - if ( plot != summaryPlot ) + if ( plot != sourceSummaryPlot ) { - plot->copyAxisPropertiesFromOther( RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM, *summaryPlot ); + plot->copyAxisPropertiesFromOther( RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM, *sourceSummaryPlot ); plot->updateAll(); } } @@ -925,16 +946,28 @@ void RimSummaryMultiPlot::computeAggregatedAxisRange() return values; }; - auto findMinMaxForSummaryCase = [readValues]( RimSummaryCase* summaryCase, RifEclipseSummaryAddress addr ) { - auto values = readValues( summaryCase, addr ); - if ( values.empty() ) return std::make_pair( HUGE_VAL, -HUGE_VAL ); + auto findMinMaxForSummaryCase = + [readValues]( RimSummaryCase* summaryCase, RifEclipseSummaryAddress addr, bool onlyPositiveValues ) { + auto values = readValues( summaryCase, addr ); + if ( onlyPositiveValues ) + { + std::vector positiveValues; - auto minMaxPair = std::minmax_element( values.begin(), values.end() ); - double caseMinimum = *minMaxPair.first; - double caseMaximum = *minMaxPair.second; + for ( const auto& v : values ) + { + if ( v > 0.0 ) positiveValues.push_back( v ); + } - return std::make_pair( caseMinimum, caseMaximum ); - }; + values = positiveValues; + } + if ( values.empty() ) return std::make_pair( HUGE_VAL, -HUGE_VAL ); + + auto minMaxPair = std::minmax_element( values.begin(), values.end() ); + double caseMinimum = *minMaxPair.first; + double caseMaximum = *minMaxPair.second; + + return std::make_pair( caseMinimum, caseMaximum ); + }; auto summaryCasesForCurve = []( RimSummaryCurve* curve, AxisRangeAggregation axisRangeAggregation ) { std::vector summaryCases; @@ -1019,14 +1052,15 @@ void RimSummaryMultiPlot::computeAggregatedAxisRange() auto findMinMaxForAddressesInSummaryCases = [findMinMaxForSummaryCase]( const std::vector& addresses, - const std::vector& summaryCases ) { + const std::vector& summaryCases, + bool onlyPositiveValues ) { double minimum = HUGE_VAL; double maximum = -HUGE_VAL; for ( auto summaryCase : summaryCases ) { for ( const auto& addr : addresses ) { - auto [caseMinimum, caseMaximum] = findMinMaxForSummaryCase( summaryCase, addr ); + auto [caseMinimum, caseMaximum] = findMinMaxForSummaryCase( summaryCase, addr, onlyPositiveValues ); minimum = std::min( minimum, caseMinimum ); maximum = std::max( maximum, caseMaximum ); } @@ -1049,7 +1083,10 @@ void RimSummaryMultiPlot::computeAggregatedAxisRange() std::vector summaryCases = summaryCasesForCurve( curve, m_axisRangeAggregation() ); std::vector addresses = addressesForCurve( curve, m_axisRangeAggregation() ); - auto [minimum, maximum] = findMinMaxForAddressesInSummaryCases( addresses, summaryCases ); + bool onlyPositiveValues = axis->isLogarithmicScaleEnabled(); + + auto [minimum, maximum] = + findMinMaxForAddressesInSummaryCases( addresses, summaryCases, onlyPositiveValues ); if ( axisRanges.count( axis->plotAxisType() ) == 0 ) { @@ -1381,6 +1418,28 @@ void RimSummaryMultiPlot::onSubPlotAxisChanged( const caf::SignalEmitter* emitte syncAxisRanges(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryMultiPlot::onSubPlotAxisReloadRequired( const caf::SignalEmitter* emitter, RimSummaryPlot* summaryPlot ) +{ + if ( !summaryPlot ) return; + + if ( m_linkTimeAxis() ) + { + syncTimeAxisRanges( summaryPlot ); + + for ( auto plot : summaryPlots() ) + { + plot->loadDataAndUpdate(); + } + } + else + { + summaryPlot->loadDataAndUpdate(); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1411,7 +1470,10 @@ std::pair RimSummaryMultiPlot::adjustedMinMax( const RimPlotAxis return { adjustedMin, adjustedMax }; } - return { min, max }; + auto adjustedMin = RiaNumericalTools::roundToClosestPowerOfTenFloor( min ); + auto adjustedMax = RiaNumericalTools::roundToClosestPowerOfTenCeil( max ); + + return { adjustedMin, adjustedMax }; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.h index af6c01d315..d0e70e92a1 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.h @@ -84,7 +84,7 @@ public: std::vector fieldsToShowInToolbar() override; void syncAxisRanges(); - void syncTimeAxisRanges( RimSummaryPlot* summaryPlot ); + void syncTimeAxisRanges( RimSummaryPlot* sourceSummaryPlot ); void handleDroppedObjects( const std::vector& objects ); @@ -148,6 +148,9 @@ private: void onSubPlotChanged( const caf::SignalEmitter* emitter ); void onSubPlotZoomed( const caf::SignalEmitter* emitter ); void onSubPlotAxisChanged( const caf::SignalEmitter* emitter, RimSummaryPlot* summaryPlot ); + void onSubPlotAxisReloadRequired( const caf::SignalEmitter* emitter, RimSummaryPlot* summaryPlot ); + + void updateTimeAxisRangesFromFirstPlot(); void updateReadOnlyState(); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index d2842b45fc..10eca3971c 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -108,6 +108,7 @@ RimSummaryPlot::RimSummaryPlot( bool isCrossPlot ) , plotZoomedByUser( this ) , titleChanged( this ) , m_isValid( true ) + , axisChangedReloadRequired( this ) { CAF_PDM_InitScriptableObject( "Summary Plot", ":/SummaryPlotLight16x16.png", "", "A Summary Plot" ); @@ -144,6 +145,7 @@ RimSummaryPlot::RimSummaryPlot( bool isCrossPlot ) { auto* timeAxisProperties = new RimSummaryTimeAxisProperties; timeAxisProperties->settingsChanged.connect( this, &RimSummaryPlot::axisSettingsChanged ); + timeAxisProperties->requestLoadDataAndUpdate.connect( this, &RimSummaryPlot::axisSettingsChangedReloadRequired ); m_axisProperties.push_back( timeAxisProperties ); } @@ -1740,24 +1742,20 @@ void RimSummaryPlot::updateZoomFromParentPlot() for ( RimPlotAxisPropertiesInterface* axisProperties : m_axisProperties ) { + if ( !axisProperties ) continue; + auto [axisMin, axisMax] = plotWidget()->axisRange( axisProperties->plotAxisType() ); if ( axisProperties->isAxisInverted() ) std::swap( axisMin, axisMax ); - auto propertyAxis = dynamic_cast( axisProperties ); - - if ( propertyAxis ) + if ( auto propertyAxis = dynamic_cast( axisProperties ) ) { propertyAxis->setAutoValueVisibleRangeMax( axisMax ); propertyAxis->setAutoValueVisibleRangeMin( axisMin ); - axisProperties->setVisibleRangeMax( axisMax ); - axisProperties->setVisibleRangeMin( axisMin ); - } - else - { - axisProperties->setVisibleRangeMax( axisMax ); - axisProperties->setVisibleRangeMin( axisMin ); } + axisProperties->setVisibleRangeMax( axisMax ); + axisProperties->setVisibleRangeMin( axisMin ); + axisProperties->updateConnectedEditors(); } } @@ -1868,6 +1866,14 @@ void RimSummaryPlot::axisSettingsChanged( const caf::SignalEmitter* emitter ) updateAxes(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::axisSettingsChangedReloadRequired( const caf::SignalEmitter* emitter ) +{ + axisChangedReloadRequired.send( this ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -2568,6 +2574,7 @@ void RimSummaryPlot::initAfterRead() if ( timeAxis ) { timeAxis->settingsChanged.connect( this, &RimSummaryPlot::axisSettingsChanged ); + timeAxis->requestLoadDataAndUpdate.connect( this, &RimSummaryPlot::axisSettingsChangedReloadRequired ); } } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h index 577d1bd69c..c46e98b8de 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h @@ -83,6 +83,7 @@ public: caf::Signal axisChanged; caf::Signal<> plotZoomedByUser; caf::Signal<> titleChanged; + caf::Signal axisChangedReloadRequired; public: RimSummaryPlot( bool isCrossPlot = false ); @@ -282,6 +283,7 @@ private: void connectAxisSignals( RimPlotAxisProperties* axis ); void axisSettingsChanged( const caf::SignalEmitter* emitter ); + void axisSettingsChangedReloadRequired( const caf::SignalEmitter* emitter ); void axisLogarithmicChanged( const caf::SignalEmitter* emitter, bool isLogarithmic ); void axisPositionChanged( const caf::SignalEmitter* emitter, RimPlotAxisProperties* axisProperties, diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp index da2d732e8c..93ab9cf8b3 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp @@ -71,6 +71,7 @@ CAF_PDM_SOURCE_INIT( RimSummaryTimeAxisProperties, "SummaryTimeAxisProperties" ) /// //-------------------------------------------------------------------------------------------------- RimSummaryTimeAxisProperties::RimSummaryTimeAxisProperties() + : requestLoadDataAndUpdate( this ) { CAF_PDM_InitObject( "Time Axis", ":/BottomAxis16x16.png" ); @@ -472,7 +473,7 @@ void RimSummaryTimeAxisProperties::setTimeMode( TimeModeType val ) } //-------------------------------------------------------------------------------------------------- -/// +/// https://www.unitconverters.net/time-converter.html //-------------------------------------------------------------------------------------------------- double RimSummaryTimeAxisProperties::fromTimeTToDisplayUnitScale() { @@ -490,9 +491,13 @@ double RimSummaryTimeAxisProperties::fromTimeTToDisplayUnitScale() case DAYS: scale = 1.0 / ( 60.0 * 60.0 * 24.0 ); break; + case MONTHS: + scale = 3.805175038E-7; + break; case YEARS: scale = 1.0 / 31556952.0; break; + default: CVF_ASSERT( false ); break; @@ -502,7 +507,7 @@ double RimSummaryTimeAxisProperties::fromTimeTToDisplayUnitScale() } //-------------------------------------------------------------------------------------------------- -/// +/// https://www.unitconverters.net/time-converter.html //-------------------------------------------------------------------------------------------------- double RimSummaryTimeAxisProperties::fromDaysToDisplayUnitScale() { @@ -520,6 +525,9 @@ double RimSummaryTimeAxisProperties::fromDaysToDisplayUnitScale() break; case DAYS: break; + case MONTHS: + scale = 1.0 / 30.416666667; + break; case YEARS: scale = 1.0 / 365.2425; break; @@ -712,21 +720,12 @@ void RimSummaryTimeAxisProperties::fieldChangedByUi( const caf::PdmFieldHandle* updateDateVisibleRange(); m_isAutoZoom = false; } - else if ( changedField == &m_timeMode ) + else if ( changedField == &m_timeMode || changedField == &m_timeUnit || changedField == &m_dateFormat || + changedField == &m_timeFormat ) { - rimSummaryPlot->loadDataAndUpdate(); - } - else if ( changedField == &m_timeUnit ) - { - updateTimeVisibleRange(); // Use the stored max min dates to update the visible time range to new unit - rimSummaryPlot->loadDataAndUpdate(); - updateDateVisibleRange(); - } - else if ( changedField == &m_dateFormat || changedField == &m_timeFormat ) - { - updateTimeVisibleRange(); // Use the stored max min dates to update the visible time range to new unit - rimSummaryPlot->loadDataAndUpdate(); - updateDateVisibleRange(); + // Changing these settings requires a full update of the plot + requestLoadDataAndUpdate.send(); + return; } rimSummaryPlot->updateAxes(); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h index b0d4c3e6fc..f7d18bff03 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h @@ -60,6 +60,8 @@ public: typedef caf::AppEnum DateFormatEnum; typedef caf::AppEnum TimeFormatEnum; + caf::Signal<> requestLoadDataAndUpdate; + public: RimSummaryTimeAxisProperties(); diff --git a/ApplicationLibCode/UnitTests/RifColorLegendData-Test.cpp b/ApplicationLibCode/UnitTests/RifColorLegendData-Test.cpp index 1e2af76430..a3031c94e4 100644 --- a/ApplicationLibCode/UnitTests/RifColorLegendData-Test.cpp +++ b/ApplicationLibCode/UnitTests/RifColorLegendData-Test.cpp @@ -1,9 +1,9 @@ #include "gtest/gtest.h" +#include "RiaNumericalTools.h" #include "RiaTestDataDirectory.h" #include "RifColorLegendData.h" #include "RigFormationNames.h" -#include "RimRegularLegendConfig.h" #include "cvfColor3.h" @@ -85,46 +85,46 @@ TEST( RifColorLegendData, ReadLYRFileWithColorHTML ) EXPECT_EQ( 0.0f, formationColor.b() ); } -TEST( RimRegularLegendConfig, LogTenFunctions ) +TEST( RiaNumericalTools, LogTenFunctions ) { { // Negative values will return zero double value = -0.0015; - auto exponentCeil = RimRegularLegendConfig::computeTenExponentCeil( value ); + auto exponentCeil = RiaNumericalTools::computeTenExponentCeil( value ); EXPECT_EQ( 0.0f, exponentCeil ); - auto exponentFloor = RimRegularLegendConfig::computeTenExponentFloor( value ); + auto exponentFloor = RiaNumericalTools::computeTenExponentFloor( value ); EXPECT_EQ( 0.0f, exponentFloor ); } { double value = 0.15; - auto exponentCeil = RimRegularLegendConfig::computeTenExponentCeil( value ); + auto exponentCeil = RiaNumericalTools::computeTenExponentCeil( value ); EXPECT_EQ( 0.0f, exponentCeil ); - auto exponentFloor = RimRegularLegendConfig::computeTenExponentFloor( value ); + auto exponentFloor = RiaNumericalTools::computeTenExponentFloor( value ); EXPECT_EQ( -1.0f, exponentFloor ); } { double value = 1.5; - auto exponentCeil = RimRegularLegendConfig::computeTenExponentCeil( value ); + auto exponentCeil = RiaNumericalTools::computeTenExponentCeil( value ); EXPECT_EQ( 1.0f, exponentCeil ); - auto exponentFloor = RimRegularLegendConfig::computeTenExponentFloor( value ); + auto exponentFloor = RiaNumericalTools::computeTenExponentFloor( value ); EXPECT_EQ( 0.0f, exponentFloor ); } { double value = 15; - auto exponentCeil = RimRegularLegendConfig::computeTenExponentCeil( value ); + auto exponentCeil = RiaNumericalTools::computeTenExponentCeil( value ); EXPECT_EQ( 2.0f, exponentCeil ); - auto exponentFloor = RimRegularLegendConfig::computeTenExponentFloor( value ); + auto exponentFloor = RiaNumericalTools::computeTenExponentFloor( value ); EXPECT_EQ( 1.0f, exponentFloor ); } } diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 1b905a5588..afefd58c31 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -5,7 +5,7 @@ set(RESINSIGHT_PATCH_VERSION 0) # Opional text with no restrictions #set(RESINSIGHT_VERSION_TEXT "-dev") -set(RESINSIGHT_VERSION_TEXT "-RC_01") +set(RESINSIGHT_VERSION_TEXT "-RC_02") # Optional text # Must be unique and increasing within one combination of major/minor/patch version