///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017 Statoil 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 #include // Needed for HUGE_VAL on Linux //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template bool XValueComparator::operator()( const XValueType& lhs, const XValueType& rhs ) const { if ( XValueComparator::equals( lhs, rhs ) ) { return false; } return lhs < rhs; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template double XValueComparator::diff( const XValueType& lhs, const XValueType& rhs ) { return lhs - rhs; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template bool XValueComparator::equals( const XValueType& lhs, const XValueType& rhs ) { return lhs == rhs; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template RiaCurveMerger::RiaCurveMerger() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template void RiaCurveMerger::addCurveData( const std::vector& xValues, const std::vector& yValues ) { CVF_ASSERT( xValues.size() == yValues.size() ); m_originalValues.push_back( std::make_pair( xValues, yValues ) ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template size_t RiaCurveMerger::curveCount() const { return m_interpolatedValuesForAllCurves.size(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template RiaCurveDataTools::CurveIntervals RiaCurveMerger::validIntervalsForAllXValues() const { return m_validIntervalsForAllXValues; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template const std::vector& RiaCurveMerger::allXValues() const { return m_allXValues; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template const std::vector& RiaCurveMerger::interpolatedYValuesForAllXValues( size_t curveIdx ) const { CVF_ASSERT( curveIdx < m_interpolatedValuesForAllCurves.size() ); return m_interpolatedValuesForAllCurves[curveIdx]; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template std::vector& RiaCurveMerger::interpolatedYValuesForAllXValues( size_t curveIdx ) { CVF_ASSERT( curveIdx < m_interpolatedValuesForAllCurves.size() ); return m_interpolatedValuesForAllCurves[curveIdx]; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template void RiaCurveMerger::computeInterpolatedValues( bool includeValuesFromPartialCurves ) { m_validIntervalsForAllXValues.clear(); m_allXValues.clear(); m_interpolatedValuesForAllCurves.clear(); computeUnionOfXValues( includeValuesFromPartialCurves ); const size_t curveCount = m_originalValues.size(); if ( curveCount == 0 ) { return; } const size_t dataValueCount = m_allXValues.size(); if ( dataValueCount == 0 ) { return; } m_interpolatedValuesForAllCurves.resize( curveCount ); std::vector accumulatedValidValues( dataValueCount, 1.0 ); for ( size_t curveIdx = 0; curveIdx < curveCount; curveIdx++ ) { std::vector& curveValues = m_interpolatedValuesForAllCurves[curveIdx]; curveValues.resize( dataValueCount ); for ( size_t valueIndex = 0; valueIndex < dataValueCount; valueIndex++ ) { double interpolValue = interpolatedYValue( m_allXValues[valueIndex], m_originalValues[curveIdx].first, m_originalValues[curveIdx].second ); if ( !RiaCurveDataTools::isValidValue( interpolValue, false ) ) { accumulatedValidValues[valueIndex] = HUGE_VAL; } curveValues[valueIndex] = interpolValue; } } m_validIntervalsForAllXValues = RiaCurveDataTools::calculateIntervalsOfValidValues( accumulatedValidValues, false ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template void RiaCurveMerger::computeUnionOfXValues( bool includeValuesForPartialCurves ) { m_allXValues.clear(); std::set unionOfXValues; std::vector> originalXBounds; for ( const auto& curveData : m_originalValues ) { for ( const auto& x : curveData.first ) { unionOfXValues.insert( x ); } auto minmax_it = std::minmax_element( curveData.first.begin(), curveData.first.end() ); originalXBounds.push_back( std::make_pair( *( minmax_it.first ), *( minmax_it.second ) ) ); } if ( !includeValuesForPartialCurves ) { for ( auto it = unionOfXValues.begin(); it != unionOfXValues.end(); ) { bool outsideBounds = false; for ( const auto& curveXBounds : originalXBounds ) { if ( *it < curveXBounds.first || *it > curveXBounds.second ) { outsideBounds = true; break; } } if ( outsideBounds ) { it = unionOfXValues.erase( it ); } else { ++it; } } } m_allXValues = std::vector( unionOfXValues.begin(), unionOfXValues.end() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template double RiaCurveMerger::interpolatedYValue( const XValueType& interpolationXValue, const std::vector& xValues, const std::vector& yValues ) { if ( yValues.size() != xValues.size() ) return HUGE_VAL; const bool removeInterpolatedValues = false; for ( size_t firstI = 0; firstI < xValues.size(); firstI++ ) { if ( XComparator::equals( xValues.at( firstI ), interpolationXValue ) ) { const double& firstValue = yValues.at( firstI ); if ( !RiaCurveDataTools::isValidValue( firstValue, removeInterpolatedValues ) ) { return HUGE_VAL; } return firstValue; } size_t secondI = firstI + 1; if ( secondI < xValues.size() ) { if ( XComparator::equals( xValues.at( secondI ), interpolationXValue ) ) { const double& secondValue = yValues.at( secondI ); if ( !RiaCurveDataTools::isValidValue( secondValue, removeInterpolatedValues ) ) { return HUGE_VAL; } return secondValue; } if ( xValues.at( firstI ) < interpolationXValue && xValues.at( secondI ) > interpolationXValue ) { const double& firstValue = yValues.at( firstI ); const double& secondValue = yValues.at( secondI ); bool isFirstValid = RiaCurveDataTools::isValidValue( firstValue, removeInterpolatedValues ); if ( !isFirstValid ) return HUGE_VAL; bool isSecondValid = RiaCurveDataTools::isValidValue( secondValue, removeInterpolatedValues ); if ( !isSecondValid ) return HUGE_VAL; double firstDiff = fabs( XComparator::diff( interpolationXValue, xValues.at( firstI ) ) ); double secondDiff = fabs( XComparator::diff( xValues.at( secondI ), interpolationXValue ) ); double firstWeight = secondDiff / ( firstDiff + secondDiff ); double secondWeight = firstDiff / ( firstDiff + secondDiff ); double val = ( firstValue * firstWeight ) + ( secondValue * secondWeight ); CVF_ASSERT( RiaCurveDataTools::isValidValue( val, removeInterpolatedValues ) ); return val; } } } return HUGE_VAL; }