From 2a0ba626d71e5bc35dd4243fb02ac37b3cc66d2d Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Fri, 10 Jan 2020 16:01:02 +0100 Subject: [PATCH] #5217 Add filtering for well measurement. --- .../ModelVisualization/RivWellPathPartMgr.cpp | 9 +- .../RimWellMeasurementFilter.cpp | 66 +++++++++++-- .../RimWellMeasurementFilter.h | 10 ++ .../RimWellMeasurementInView.cpp | 92 +++++++++++++++++-- .../RimWellMeasurementInView.h | 12 +++ 5 files changed, 172 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 26ae70efaa..d8ba5170ba 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -283,13 +283,18 @@ void RivWellPathPartMgr::appendWellMeasurementsToModel( cvf::ModelBasicList* std::vector measurementKinds; measurementKinds.push_back( wellMeasurementInView->measurementKind() ); - RivPipeGeometryGenerator geoGenerator; + double lowerBound = 0.0; + double upperBound = 0.0; + wellMeasurementInView->rangeValues( &lowerBound, &upperBound ); std::vector wellMeasurements = RimWellMeasurementFilter::filterMeasurements( wellMeasurementCollection->measurements(), *wellPathCollection, *m_rimWellPath, - measurementKinds ); + measurementKinds, + lowerBound, + upperBound ); + RivPipeGeometryGenerator geoGenerator; for ( RimWellMeasurement* wellMeasurement : wellMeasurements ) { double wellPathRadius = this->wellPathRadius( characteristicCellSize, this->wellPathCollection() ); diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp index ab75f3ad56..3f62e96fb6 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp @@ -17,6 +17,8 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimWellMeasurementFilter.h" +#include "cvfMath.h" + #include "RimWellMeasurement.h" #include "RimWellMeasurementCollection.h" #include "RimWellPath.h" @@ -31,23 +33,52 @@ std::vector const RimWellPath& wellPath, const std::vector& measurementKinds ) { - std::vector filteredMeasurements; + std::vector filteredMeasurementsByKinds = filterMeasurements( measurements, measurementKinds ); - for ( auto& measurement : measurements ) + std::vector filteredMeasurements; + for ( auto& measurement : filteredMeasurementsByKinds ) { - if ( std::find( measurementKinds.begin(), measurementKinds.end(), measurement->kind() ) != measurementKinds.end() ) + RimWellPath* matchedWellPath = wellPathCollection.tryFindMatchingWellPath( measurement->wellName() ); + if ( matchedWellPath && matchedWellPath == &wellPath ) { - RimWellPath* matchedWellPath = wellPathCollection.tryFindMatchingWellPath( measurement->wellName() ); - if ( matchedWellPath && matchedWellPath == &wellPath ) - { - filteredMeasurements.push_back( measurement ); - } + filteredMeasurements.push_back( measurement ); } } return filteredMeasurements; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector + RimWellMeasurementFilter::filterMeasurements( const std::vector& measurements, + const RimWellPathCollection& wellPathCollection, + const RimWellPath& wellPath, + const std::vector& measurementKinds, + double lowerBound, + double upperBound ) +{ + std::vector filteredMeasurementsByKindsAndWellPath = filterMeasurements( measurements, + wellPathCollection, + wellPath, + measurementKinds ); + + std::vector filteredMeasurements; + for ( auto& measurement : filteredMeasurementsByKindsAndWellPath ) + { + if ( RimWellMeasurementFilter::isInsideRange( measurement->value(), lowerBound, upperBound ) ) + { + filteredMeasurements.push_back( measurement ); + } + } + + return filteredMeasurements; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- std::vector RimWellMeasurementFilter::filterMeasurements( const std::vector& measurements, const std::vector& measurementKinds ) @@ -64,3 +95,22 @@ std::vector return filteredMeasurements; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellMeasurementFilter::isInsideRange( double value, double lowerBound, double upperBound ) +{ + // Invalid range: everything is inside + if ( lowerBound == cvf::UNDEFINED_DOUBLE || cvf::UNDEFINED_DOUBLE == upperBound ) + { + return true; + } + + if ( lowerBound <= value && value <= upperBound ) + { + return true; + } + + return false; +} diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h index 1ccdf3f57f..13df1261b8 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h @@ -32,9 +32,19 @@ public: const RimWellPathCollection& wellPathCollection, const RimWellPath& rimWellPath, const std::vector& measurementKinds ); + + static std::vector filterMeasurements( const std::vector& measurements, + const RimWellPathCollection& wellPathCollection, + const RimWellPath& rimWellPath, + const std::vector& measurementKinds, + double lowerBound, + double upperBound ); + static std::vector filterMeasurements( const std::vector& measurements, const std::vector& measurementKinds ); private: RimWellMeasurementFilter(); + + static bool isInsideRange( double value, double lowerBound, double upperBound ); }; diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementInView.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementInView.cpp index 010a51b949..41257c987c 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementInView.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementInView.cpp @@ -32,6 +32,7 @@ #include "RiuViewer.h" #include "cafCmdFeatureMenuBuilder.h" +#include "cafPdmUiDoubleSliderEditor.h" #include "cafPdmUiTableViewEditor.h" #include "cafPdmUiTreeOrdering.h" #include "cafPdmUiTreeSelectionEditor.h" @@ -57,9 +58,17 @@ RimWellMeasurementInView::RimWellMeasurementInView() CAF_PDM_InitFieldNoDefault( &m_wells, "Wells", "Wells", "", "", "" ); m_wells.uiCapability()->setAutoAddingOptionFromValue( false ); m_wells.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); - m_wells.xmlCapability()->disableIO(); + + CAF_PDM_InitField( &m_lowerBound, "LowerBound", -HUGE_VAL, "Min", "", "", "" ); + m_lowerBound.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() ); + + CAF_PDM_InitField( &m_upperBound, "UpperBound", HUGE_VAL, "Max", "", "", "" ); + m_upperBound.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() ); this->setName( "Well Measurement" ); + + m_minimumResultValue = cvf::UNDEFINED_DOUBLE; + m_maximumResultValue = cvf::UNDEFINED_DOUBLE; } //-------------------------------------------------------------------------------------------------- @@ -80,6 +89,49 @@ void RimWellMeasurementInView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiT uiTreeOrdering.skipRemainingChildren( true ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementInView::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + RimCheckableNamedObject::defineUiOrdering( uiConfigName, uiOrdering ); + uiOrdering.add( &m_wells ); + + if ( !hasCategoryResult() ) + { + caf::PdmUiGroup& filterGroup = *( uiOrdering.addNewGroup( "Value Filter Settings" ) ); + filterGroup.add( &m_lowerBound ); + filterGroup.add( &m_upperBound ); + } + + uiOrdering.skipRemainingFields(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementInView::defineEditorAttribute( const caf::PdmFieldHandle* field, + QString uiConfigName, + caf::PdmUiEditorAttribute* attribute ) +{ + if ( m_minimumResultValue == cvf::UNDEFINED_DOUBLE || m_maximumResultValue == cvf::UNDEFINED_DOUBLE ) + { + return; + } + + if ( field == &m_lowerBound || field == &m_upperBound ) + { + caf::PdmUiDoubleSliderEditorAttribute* myAttr = dynamic_cast( attribute ); + if ( !myAttr ) + { + return; + } + + myAttr->m_minimum = m_minimumResultValue; + myAttr->m_maximum = m_maximumResultValue; + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -93,6 +145,15 @@ void RimWellMeasurementInView::fieldChangedByUi( const caf::PdmFieldHandle* chan rimGridView->scheduleCreateDisplayModelAndRedraw(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementInView::rangeValues( double* lowerBound, double* upperBound ) const +{ + *lowerBound = m_lowerBound; + *upperBound = m_upperBound; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -130,21 +191,38 @@ bool RimWellMeasurementInView::updateLegendData() RimWellMeasurementFilter::filterMeasurements( wellMeasurementCollection->measurements(), selectedMeasurementKinds ); - double minValue = HUGE_VAL; - double maxValue = -HUGE_VAL; + double oldMinimumResultValue = m_minimumResultValue; + double oldMaximumResultValue = m_maximumResultValue; + + m_minimumResultValue = HUGE_VAL; + m_maximumResultValue = -HUGE_VAL; double posClosestToZero = HUGE_VAL; double negClosestToZero = -HUGE_VAL; for ( auto& measurement : wellMeasurements ) { - minValue = std::min( measurement->value(), minValue ); - maxValue = std::max( measurement->value(), maxValue ); + m_minimumResultValue = std::min( measurement->value(), m_minimumResultValue ); + m_maximumResultValue = std::max( measurement->value(), m_maximumResultValue ); } - if ( minValue != HUGE_VAL ) + if ( m_minimumResultValue != HUGE_VAL ) { + // Refresh filter slider if lower or upper boundary was undefined + if ( std::isinf( m_lowerBound ) ) + { + m_lowerBound = m_minimumResultValue; + } + + if ( std::isinf( m_upperBound ) ) + { + m_upperBound = m_maximumResultValue; + } + m_legendConfig->setTitle( QString( "Well Measurement: \n" ) + selectedMeasurementKinds[0] ); - m_legendConfig->setAutomaticRanges( minValue, maxValue, minValue, maxValue ); + m_legendConfig->setAutomaticRanges( m_minimumResultValue, + m_maximumResultValue, + m_minimumResultValue, + m_maximumResultValue ); m_legendConfig->setClosestToZeroValues( posClosestToZero, negClosestToZero, posClosestToZero, negClosestToZero ); return true; } diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementInView.h b/ApplicationCode/ProjectDataModel/RimWellMeasurementInView.h index 7eb4e3e8ac..c111599983 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementInView.h +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementInView.h @@ -51,8 +51,15 @@ public: bool hasCategoryResult() const; + void rangeValues( double* lowerBound, double* upperBound ) const; + protected: void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override; + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void defineEditorAttribute( const caf::PdmFieldHandle* field, + QString uiConfigName, + caf::PdmUiEditorAttribute* attribute ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; @@ -70,4 +77,9 @@ private: caf::PdmChildField m_legendConfig; caf::PdmField m_measurementKind; caf::PdmField> m_wells; + caf::PdmField m_lowerBound; + caf::PdmField m_upperBound; + + double m_minimumResultValue; + double m_maximumResultValue; };