From 75c3e8732d175e3d1b7c10d1c41edbcb1312730f Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Mon, 11 Nov 2019 13:29:45 +0100 Subject: [PATCH 01/12] #5001 Add object definition for well measurement. --- .../ProjectDataModel/CMakeLists_files.cmake | 2 + .../ProjectDataModel/RimWellMeasurement.cpp | 169 ++++++++++++++++++ .../ProjectDataModel/RimWellMeasurement.h | 66 +++++++ 3 files changed, 237 insertions(+) create mode 100644 ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimWellMeasurement.h diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 0e05b1be15..29946c8a3e 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -26,6 +26,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimSimWellInViewCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimWellPath.h ${CMAKE_CURRENT_LIST_DIR}/RimFileWellPath.h ${CMAKE_CURRENT_LIST_DIR}/RimModeledWellPath.h +${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurement.h ${CMAKE_CURRENT_LIST_DIR}/RimWellPathGeometryDef.h ${CMAKE_CURRENT_LIST_DIR}/RimWellPathAttribute.h ${CMAKE_CURRENT_LIST_DIR}/RimWellPathAttributeCollection.h @@ -171,6 +172,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimSimWellInViewCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPath.cpp ${CMAKE_CURRENT_LIST_DIR}/RimFileWellPath.cpp ${CMAKE_CURRENT_LIST_DIR}/RimModeledWellPath.cpp +${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurement.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathGeometryDef.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathAttribute.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathAttributeCollection.cpp diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp new file mode 100644 index 0000000000..ce7b70f191 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp @@ -0,0 +1,169 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RimWellMeasurement.h" + +#include "RimWellPath.h" + +CAF_PDM_SOURCE_INIT( RimWellMeasurement, "WellMeasurement" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellMeasurement::RimWellMeasurement() +{ + CAF_PDM_InitObject( "RimWellMeasurement", "", "", "" ); + + CAF_PDM_InitFieldNoDefault( &m_wellName, "WellName", "Well Name", "", "", "" ); + CAF_PDM_InitField( &m_MD, "Depth", -1.0, "MD", "", "", "" ); + CAF_PDM_InitFieldNoDefault( &m_date, "Date", "Date", "", "", "" ); + CAF_PDM_InitField( &m_value, "Value", 0.0, "Value", "", "", "" ); + CAF_PDM_InitFieldNoDefault( &m_kind, "Kind", "Kind", "", "", "" ); + CAF_PDM_InitFieldNoDefault( &m_quality, "Quality", "Quality", "", "", "" ); + CAF_PDM_InitFieldNoDefault( &m_remark, "Remark", "Remark", "", "", "" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellMeasurement::~RimWellMeasurement() {} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimWellMeasurement::wellName() const +{ + return m_wellName(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurement::setWellName( const QString& wellName ) +{ + m_wellName = wellName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimWellMeasurement::MD() const +{ + return m_MD(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurement::setMD( double md ) +{ + m_MD = md; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QDate RimWellMeasurement::date() const +{ + return m_date(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurement::setDate( const QDate& date ) +{ + m_date = date; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimWellMeasurement::value() const +{ + return m_value(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurement::setValue( double value ) +{ + m_value = value; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimWellMeasurement::kind() const +{ + return m_kind(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurement::setKind( const QString& kind ) +{ + m_kind = kind; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RimWellMeasurement::quality() const +{ + return m_quality(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurement::setQuality( int quality ) +{ + m_quality = quality; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimWellMeasurement::remark() const +{ + return m_remark(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurement::setRemark( const QString& remark ) +{ + m_remark = remark; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurement::fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurement::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) {} diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurement.h b/ApplicationCode/ProjectDataModel/RimWellMeasurement.h new file mode 100644 index 0000000000..be264d0003 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurement.h @@ -0,0 +1,66 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2018- 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 + +#include "cafPdmObject.h" + +#include "cafPdmField.h" + +#include +#include + +class RimWellPath; + +class RimWellMeasurement : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimWellMeasurement(); + ~RimWellMeasurement() override; + + QString wellName() const; + void setWellName( const QString& wellName ); + double MD() const; + void setMD( double md ); + QDate date() const; + void setDate( const QDate& date ); + double value() const; + void setValue( double value ); + QString kind() const; + void setKind( const QString& kind ); + int quality() const; + void setQuality( int quality ); + QString remark() const; + void setRemark( const QString& remark ); + +private: + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) override; + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + +private: + caf::PdmField m_wellName; + caf::PdmField m_MD; + caf::PdmField m_date; + caf::PdmField m_value; + caf::PdmField m_kind; + caf::PdmField m_quality; + caf::PdmField m_remark; +}; From ff15ff939d92dfd92331209ac7561640c7d7e612 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Mon, 11 Nov 2019 15:07:26 +0100 Subject: [PATCH 02/12] #5001 Add object definition for well measurement collection. --- .../ProjectDataModel/CMakeLists_files.cmake | 2 + .../RimWellMeasurementCollection.cpp | 187 ++++++++++++++++++ .../RimWellMeasurementCollection.h | 59 ++++++ .../ProjectDataModel/RimWellPath.cpp | 28 +++ .../ProjectDataModel/RimWellPath.h | 4 + 5 files changed, 280 insertions(+) create mode 100644 ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 29946c8a3e..6c419ff965 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -27,6 +27,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellPath.h ${CMAKE_CURRENT_LIST_DIR}/RimFileWellPath.h ${CMAKE_CURRENT_LIST_DIR}/RimModeledWellPath.h ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurement.h +${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimWellPathGeometryDef.h ${CMAKE_CURRENT_LIST_DIR}/RimWellPathAttribute.h ${CMAKE_CURRENT_LIST_DIR}/RimWellPathAttributeCollection.h @@ -173,6 +174,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellPath.cpp ${CMAKE_CURRENT_LIST_DIR}/RimFileWellPath.cpp ${CMAKE_CURRENT_LIST_DIR}/RimModeledWellPath.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurement.cpp +${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathGeometryDef.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathAttribute.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathAttributeCollection.cpp diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.cpp new file mode 100644 index 0000000000..c862c2cc4a --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.cpp @@ -0,0 +1,187 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RimWellMeasurementCollection.h" + +#include "RimProject.h" +#include "RimWellLogTrack.h" +#include "RimWellMeasurement.h" + +#include "cafCmdFeatureMenuBuilder.h" +#include "cafPdmUiTableViewEditor.h" +#include "cafPdmUiTreeOrdering.h" + +CAF_PDM_SOURCE_INIT( RimWellMeasurementCollection, "WellMeasurements" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellMeasurementCollection::RimWellMeasurementCollection() +{ + CAF_PDM_InitObject( "Well Measurement", "", "", "" ); + + CAF_PDM_InitFieldNoDefault( &m_measurements, "Measurements", "Well Measurements", "", "", "" ); + m_measurements.uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() ); + m_measurements.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); + m_measurements.uiCapability()->setCustomContextMenuEnabled( true ); + this->setName( "Well Measurements" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellMeasurementCollection::~RimWellMeasurementCollection() {} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCollection::updateAllReferringTracks() +{ + std::vector wellLogTracks; + + this->objectsWithReferringPtrFieldsOfType( wellLogTracks ); + for ( RimWellLogTrack* track : wellLogTracks ) + { + track->loadDataAndUpdate(); + } + this->updateConnectedEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimWellMeasurementCollection::measurements() const +{ + std::vector attrs; + + for ( auto attr : m_measurements ) + { + attrs.push_back( attr.p() ); + } + return attrs; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCollection::insertMeasurement( RimWellMeasurement* insertBefore, RimWellMeasurement* measurement ) +{ + size_t index = m_measurements.index( insertBefore ); + if ( index < m_measurements.size() ) + m_measurements.insert( index, measurement ); + else + m_measurements.push_back( measurement ); + + this->updateAllReferringTracks(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCollection::appendMeasurement( RimWellMeasurement* measurement ) +{ + m_measurements.push_back( measurement ); + this->updateAllReferringTracks(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCollection::deleteMeasurement( RimWellMeasurement* measurementToDelete ) +{ + m_measurements.removeChildObject( measurementToDelete ); + delete measurementToDelete; + + this->updateAllReferringTracks(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCollection::deleteAllMeasurements() +{ + m_measurements.deleteAllChildObjects(); + this->updateAllReferringTracks(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCollection::defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, + QMenu* menu, + QWidget* fieldEditorWidget ) +{ + caf::CmdFeatureMenuBuilder menuBuilder; + + // menuBuilder << "RicNewWellMeasurementFeature"; + // menuBuilder << "Separator"; + // menuBuilder << "RicDeleteWellMeasurementFeature"; + + menuBuilder.appendToMenu( menu ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCollection::defineEditorAttribute( const caf::PdmFieldHandle* field, + QString uiConfigName, + caf::PdmUiEditorAttribute* attribute ) +{ + if ( field == &m_measurements ) + { + auto tvAttribute = dynamic_cast( attribute ); + if ( tvAttribute ) + { + tvAttribute->resizePolicy = caf::PdmUiTableViewEditorAttribute::RESIZE_TO_FILL_CONTAINER; + tvAttribute->alwaysEnforceResizePolicy = true; + tvAttribute->minimumHeight = 300; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + uiOrdering.add( &m_measurements ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCollection::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, + QString uiConfigName /*= ""*/ ) +{ + uiTreeOrdering.skipRemainingChildren( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCollection::fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) +{ + if ( changedField == &m_isChecked ) + { + RimProject* proj; + this->firstAncestorOrThisOfTypeAsserted( proj ); + proj->scheduleCreateDisplayModelAndRedrawAllViews(); + this->updateAllReferringTracks(); + } +} diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h new file mode 100644 index 0000000000..42a3466356 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h @@ -0,0 +1,59 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 + +#include "RimCheckableNamedObject.h" + +#include "cafPdmChildArrayField.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" + +class RimWellMeasurement; + +class RimWellMeasurementCollection : public RimCheckableNamedObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimWellMeasurementCollection(); + ~RimWellMeasurementCollection() override; + + std::vector measurements() const; + + void updateAllReferringTracks(); + void insertMeasurement( RimWellMeasurement* insertBefore, RimWellMeasurement* measurement ); + void appendMeasurement( RimWellMeasurement* measurement ); + void deleteMeasurement( RimWellMeasurement* measurementToDelete ); + void deleteAllMeasurements(); + +protected: + void defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, + QMenu* menu, + QWidget* fieldEditorWidget ) override; + void defineEditorAttribute( const caf::PdmFieldHandle* field, + QString uiConfigName, + caf::PdmUiEditorAttribute* attribute ) override; + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) override; + +private: + caf::PdmChildArrayField m_measurements; +}; diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index ec658990f9..446e75ff36 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -42,6 +42,7 @@ #include "RimWellLogFile.h" #include "RimWellLogFileChannel.h" #include "RimWellLogPlotCollection.h" +#include "RimWellMeasurementCollection.h" #include "RimWellPathAttributeCollection.h" #include "RimWellPathCollection.h" #include "RimWellPathCompletions.h" @@ -128,6 +129,10 @@ RimWellPath::RimWellPath() m_wellPathAttributes = new RimWellPathAttributeCollection; m_wellPathAttributes->uiCapability()->setUiTreeHidden( true ); + CAF_PDM_InitFieldNoDefault( &m_wellMeasurements, "WellMeasurements", "Measurements", "", "", "" ); + m_wellMeasurements = new RimWellMeasurementCollection; + m_wellMeasurements->uiCapability()->setUiTreeHidden( true ); + m_wellPath = nullptr; } @@ -491,6 +496,24 @@ const RimWellPathAttributeCollection* RimWellPath::attributeCollection() const return m_wellPathAttributes; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- + +RimWellMeasurementCollection* RimWellPath::measurementCollection() +{ + return m_wellMeasurements; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- + +const RimWellMeasurementCollection* RimWellPath::measurementCollection() const +{ + return m_wellMeasurements; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -607,6 +630,11 @@ void RimWellPath::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, uiTreeOrdering.add( m_wellPathAttributes() ); } + if ( !m_wellMeasurements->measurements().empty() ) + { + uiTreeOrdering.add( m_wellMeasurements() ); + } + uiTreeOrdering.skipRemainingChildren( true ); } diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.h b/ApplicationCode/ProjectDataModel/RimWellPath.h index 1a978ce839..33e48d4676 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.h +++ b/ApplicationCode/ProjectDataModel/RimWellPath.h @@ -49,6 +49,7 @@ class RimFishboneWellPathCollection; class RimFishbonesCollection; class RimPerforationCollection; class RimWellPathAttributeCollection; +class RimWellMeasurementCollection; class RimWellPathCompletions; class RigWellPathFormations; @@ -110,6 +111,8 @@ public: const RimWellPathFractureCollection* fractureCollection() const; RimWellPathAttributeCollection* attributeCollection(); const RimWellPathAttributeCollection* attributeCollection() const; + RimWellMeasurementCollection* measurementCollection(); + const RimWellMeasurementCollection* measurementCollection() const; bool showWellPathLabel() const; bool showWellPath() const; @@ -171,6 +174,7 @@ private: caf::PdmChildField m_3dWellLogCurves; caf::PdmChildField m_completions; caf::PdmChildField m_wellPathAttributes; + caf::PdmChildField m_wellMeasurements; private: static size_t simulationWellBranchCount( const QString& simWellName ); From fd862b2edaf86dad296905533be9a185716b6d8e Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Mon, 11 Nov 2019 23:07:53 +0100 Subject: [PATCH 03/12] #5001 Add Well Measurement reader. --- .../FileInterface/CMakeLists_files.cmake | 2 + .../RifWellMeasurementReader.cpp | 209 ++++++++++++++ .../FileInterface/RifWellMeasurementReader.h | 61 +++++ .../UnitTests/CMakeLists_files.cmake | 1 + .../RifWellMeasurementReader-Test.cpp | 257 ++++++++++++++++++ 5 files changed, 530 insertions(+) create mode 100644 ApplicationCode/FileInterface/RifWellMeasurementReader.cpp create mode 100644 ApplicationCode/FileInterface/RifWellMeasurementReader.h create mode 100644 ApplicationCode/UnitTests/RifWellMeasurementReader-Test.cpp diff --git a/ApplicationCode/FileInterface/CMakeLists_files.cmake b/ApplicationCode/FileInterface/CMakeLists_files.cmake index f06338536a..e0865f25e0 100644 --- a/ApplicationCode/FileInterface/CMakeLists_files.cmake +++ b/ApplicationCode/FileInterface/CMakeLists_files.cmake @@ -35,6 +35,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifDataSourceForRftPltQMetaType.h ${CMAKE_CURRENT_LIST_DIR}/RifEclipseUserDataKeywordTools.h ${CMAKE_CURRENT_LIST_DIR}/RifCsvUserData.h ${CMAKE_CURRENT_LIST_DIR}/RifCsvUserDataParser.h +${CMAKE_CURRENT_LIST_DIR}/RifWellMeasurementReader.h ${CMAKE_CURRENT_LIST_DIR}/RifWellPathFormationReader.h ${CMAKE_CURRENT_LIST_DIR}/RifWellPathFormationsImporter.h ${CMAKE_CURRENT_LIST_DIR}/RifElementPropertyTableReader.h @@ -88,6 +89,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifDataSourceForRftPlt.cpp ${CMAKE_CURRENT_LIST_DIR}/RifEclipseUserDataKeywordTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RifCsvUserData.cpp ${CMAKE_CURRENT_LIST_DIR}/RifCsvUserDataParser.cpp +${CMAKE_CURRENT_LIST_DIR}/RifWellMeasurementReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifWellPathFormationReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifWellPathFormationsImporter.cpp ${CMAKE_CURRENT_LIST_DIR}/RifElementPropertyTableReader.cpp diff --git a/ApplicationCode/FileInterface/RifWellMeasurementReader.cpp b/ApplicationCode/FileInterface/RifWellMeasurementReader.cpp new file mode 100644 index 0000000000..6786a4b5d9 --- /dev/null +++ b/ApplicationCode/FileInterface/RifWellMeasurementReader.cpp @@ -0,0 +1,209 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RifWellMeasurementReader.h" + +#include "RifFileParseTools.h" + +#include +#include +#include + +//================================================================================================== +/// +//================================================================================================== +void RifWellMeasurementReader::readWellMeasurements( std::vector& wellMeasurements, + const QStringList& filePaths ) +{ + for ( const QString& filePath : filePaths ) + { + try + { + readWellMeasurements( wellMeasurements, filePath ); + } + catch ( FileParseException& ) + { + // Delete all well measurements and rethrow exception + wellMeasurements.clear(); + throw; + } + } +} + +//================================================================================================== +/// +//================================================================================================== +void RifWellMeasurementReader::readWellMeasurements( std::vector& wellMeasurements, + const QString& filePath ) +{ + QFile file( filePath ); + if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) + { + throw FileParseException( QString( "Unable to open file: %1" ).arg( filePath ) ); + } + + QTextStream in( &file ); + int lineNumber = 1; + while ( !in.atEnd() ) + { + QString line = in.readLine(); + if ( !isEmptyLine( line ) && !isCommentLine( line ) ) + { + RifWellMeasurement wellMeasurement = parseWellMeasurement( line, lineNumber, filePath ); + wellMeasurements.push_back( wellMeasurement ); + } + + lineNumber++; + } +} + +//================================================================================================== +/// +//================================================================================================== +RifWellMeasurement + RifWellMeasurementReader::parseWellMeasurement( const QString& line, int lineNumber, const QString& filePath ) +{ + QStringList tokens = tokenize( line, "," ); + + if ( tokens.size() != 7 ) + { + throw FileParseException( QString( "Incomplete data on line %1: %2" ).arg( lineNumber ).arg( filePath ) ); + } + + // Check for unexpected empty tokens + QStringList nameOfNonEmptyTokens; + nameOfNonEmptyTokens << "Well Name" + << "Measured Depth" + << "Date" + << "Value" + << "Kind"; + verifyNonEmptyTokens( tokens, nameOfNonEmptyTokens, lineNumber, filePath ); + + RifWellMeasurement wellMeasurement; + wellMeasurement.wellName = tokens[0]; + wellMeasurement.MD = parseDouble( tokens[1], "Measured Depth", lineNumber, filePath ); + wellMeasurement.date = parseDate( tokens[2], "Date", lineNumber, filePath ); + wellMeasurement.value = parseDouble( tokens[3], "Value", lineNumber, filePath ); + wellMeasurement.kind = tokens[4]; + wellMeasurement.quality = parseInt( tokens[5], "Quality", lineNumber, filePath ); + wellMeasurement.remark = tokens[6]; + wellMeasurement.filePath = filePath; + return wellMeasurement; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QStringList RifWellMeasurementReader::tokenize( const QString& line, const QString& separator ) +{ + return RifFileParseTools::splitLineAndTrim( line, separator ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QDate RifWellMeasurementReader::parseDate( const QString& token, + const QString& propertyName, + int lineNumber, + const QString& filePath ) +{ + QDate date = QDate::fromString( token, Qt::ISODate ); + if ( !date.isValid() ) + { + throw FileParseException( QString( "Invalid date format (must be ISO 8601) for '%1' on line %2: %3" ) + .arg( propertyName ) + .arg( lineNumber ) + .arg( filePath ) ); + } + + return date; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RifWellMeasurementReader::parseDouble( const QString& token, + const QString& propertyName, + int lineNumber, + const QString& filePath ) +{ + bool isOk = false; + double value = token.toDouble( &isOk ); + if ( !isOk ) + { + throw FileParseException( + QString( "Invalid number for '%1' on line %2: %3" ).arg( propertyName ).arg( lineNumber ).arg( filePath ) ); + } + + return value; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RifWellMeasurementReader::parseInt( const QString& token, + const QString& propertyName, + int lineNumber, + const QString& filePath ) +{ + bool isOk = false; + int value = token.toInt( &isOk ); + if ( !isOk ) + { + throw FileParseException( + QString( "Invalid number for '%1' on line %2: %3" ).arg( propertyName ).arg( lineNumber ).arg( filePath ) ); + } + + return value; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifWellMeasurementReader::isEmptyLine( const QString& line ) +{ + return line.trimmed().isEmpty(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifWellMeasurementReader::isCommentLine( const QString& line ) +{ + return line.startsWith( "#" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifWellMeasurementReader::verifyNonEmptyTokens( const QStringList& tokens, + const QStringList& nameOfNonEmptyTokens, + int lineNumber, + const QString& filePath ) +{ + for ( int i = 0; i < nameOfNonEmptyTokens.size(); ++i ) + { + if ( tokens[i].isEmpty() ) + { + throw FileParseException( QString( "Unexpected empty '%1' on line %2: %3" ) + .arg( nameOfNonEmptyTokens[i] ) + .arg( lineNumber ) + .arg( filePath ) ); + } + } +} diff --git a/ApplicationCode/FileInterface/RifWellMeasurementReader.h b/ApplicationCode/FileInterface/RifWellMeasurementReader.h new file mode 100644 index 0000000000..4743d6b208 --- /dev/null +++ b/ApplicationCode/FileInterface/RifWellMeasurementReader.h @@ -0,0 +1,61 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include + +#include +#include + +struct RifWellMeasurement +{ + QString wellName; + double MD; + double value; + QDate date; + int quality; + QString kind; + QString remark; + QString filePath; +}; + +//================================================================================================== +/// +//================================================================================================== +class RifWellMeasurementReader +{ +public: + static void readWellMeasurements( std::vector& wellMeasurements, const QStringList& filePaths ); + +private: + static void readWellMeasurements( std::vector& wellMeasurements, const QString& filePath ); + static RifWellMeasurement parseWellMeasurement( const QString& line, int lineNumber, const QString& filePath ); + static QStringList tokenize( const QString& line, const QString& separator ); + static void verifyNonEmptyTokens( const QStringList& tokens, + const QStringList& nameOfNonEmptyTokens, + int lineNumber, + const QString& filePath ); + + static QDate parseDate( const QString& token, const QString& propertyName, int lineNumber, const QString& filePath ); + static double parseDouble( const QString& token, const QString& propertyName, int lineNumber, const QString& filePath ); + static int parseInt( const QString& token, const QString& propertyName, int lineNumber, const QString& filePath ); + + static bool isEmptyLine( const QString& line ); + static bool isCommentLine( const QString& line ); +}; diff --git a/ApplicationCode/UnitTests/CMakeLists_files.cmake b/ApplicationCode/UnitTests/CMakeLists_files.cmake index e75e795f68..b645857343 100644 --- a/ApplicationCode/UnitTests/CMakeLists_files.cmake +++ b/ApplicationCode/UnitTests/CMakeLists_files.cmake @@ -61,6 +61,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifCsvDataTableFormatter-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveAnalyzer-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaStdStringTools-Test.cpp +${CMAKE_CURRENT_LIST_DIR}/RifWellMeasurementReader-Test.cpp ) if (RESINSIGHT_ENABLE_GRPC) diff --git a/ApplicationCode/UnitTests/RifWellMeasurementReader-Test.cpp b/ApplicationCode/UnitTests/RifWellMeasurementReader-Test.cpp new file mode 100644 index 0000000000..5a4bfd9a1c --- /dev/null +++ b/ApplicationCode/UnitTests/RifWellMeasurementReader-Test.cpp @@ -0,0 +1,257 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "gtest/gtest.h" + +#include "RifFileParseTools.h" +#include "RifWellMeasurementReader.h" + +#include +#include +#include + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifWellMeasurementReaderTest, ReadCorrectInputFile ) +{ + QTemporaryFile file; + EXPECT_TRUE( file.open() ); + + { + QTextStream out( &file ); + out << "NO 1234/5-6, 1234.56, 2019-11-13, 99.9, XLOT, 3, Good test\n" + << "NO 4321/7-8, 4321.79, 2024-12-24, 88.8, DP, 1, Poor test\n"; + } + + QStringList filePaths; + filePaths.append( file.fileName() ); + + std::vector wellMeasurements; + RifWellMeasurementReader::readWellMeasurements( wellMeasurements, filePaths ); + + ASSERT_EQ( 2u, wellMeasurements.size() ); + + ASSERT_EQ( "NO 1234/5-6", wellMeasurements[0].wellName.toStdString() ); + ASSERT_EQ( "NO 4321/7-8", wellMeasurements[1].wellName.toStdString() ); + + ASSERT_DOUBLE_EQ( 1234.56, wellMeasurements[0].MD ); + ASSERT_DOUBLE_EQ( 4321.79, wellMeasurements[1].MD ); + + QDate date0( 2019, 11, 13 ); + ASSERT_EQ( date0.year(), wellMeasurements[0].date.year() ); + ASSERT_EQ( date0.month(), wellMeasurements[0].date.month() ); + ASSERT_EQ( date0.day(), wellMeasurements[0].date.day() ); + + QDate date1( 2024, 12, 24 ); + ASSERT_EQ( date1.year(), wellMeasurements[1].date.year() ); + ASSERT_EQ( date1.month(), wellMeasurements[1].date.month() ); + ASSERT_EQ( date1.day(), wellMeasurements[1].date.day() ); + + ASSERT_DOUBLE_EQ( 99.9, wellMeasurements[0].value ); + ASSERT_DOUBLE_EQ( 88.8, wellMeasurements[1].value ); + + ASSERT_EQ( "XLOT", wellMeasurements[0].kind.toStdString() ); + ASSERT_EQ( "DP", wellMeasurements[1].kind.toStdString() ); + + ASSERT_EQ( 3, wellMeasurements[0].quality ); + ASSERT_EQ( 1, wellMeasurements[1].quality ); + + ASSERT_EQ( "Good test", wellMeasurements[0].remark.toStdString() ); + ASSERT_EQ( "Poor test", wellMeasurements[1].remark.toStdString() ); +} + +//-------------------------------------------------------------------------------------------------- +/// Helper to check exception messages when reading invalid files +//-------------------------------------------------------------------------------------------------- +::testing::AssertionResult readingThrowsException( const QStringList& filePaths, const QString& expectedMessage ) +{ + std::vector wellMeasurements; + try + { + RifWellMeasurementReader::readWellMeasurements( wellMeasurements, filePaths ); + // No exception thrown: fail! + return ::testing::AssertionFailure() << "readWellMeasurements did not throw exception"; + } + catch ( FileParseException& error ) + { + // Should always have cleaned up the well measurements on failure + EXPECT_EQ( 0u, wellMeasurements.size() ); + // Check that we get the expected message + EXPECT_EQ( expectedMessage.toStdString(), error.message.toStdString() ); + return ::testing::AssertionSuccess(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifWellMeasurementReaderTest, ReadMissingFileThrows ) +{ + QStringList filePaths; + QString nonExistingFile( "this/is/a/file/which/does/not/exist.csv" ); + filePaths.append( nonExistingFile ); + ASSERT_TRUE( readingThrowsException( filePaths, QString( "Unable to open file: %1" ).arg( nonExistingFile ) ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifWellMeasurementReaderTest, ReadShortLinesFileThrows ) +{ + QTemporaryFile file; + EXPECT_TRUE( file.open() ); + + { + QTextStream out( &file ); + out << "NO 1234/5-6, 1234.56\n" + << "NO 4321/7-8, 4321.79, 2024-12-24\n"; + } + + QStringList filePaths; + filePaths.append( file.fileName() ); + ASSERT_TRUE( readingThrowsException( filePaths, QString( "Incomplete data on line 1: %1" ).arg( file.fileName() ) ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifWellMeasurementReaderTest, ReadEmptyWellNameThrows ) +{ + QTemporaryFile file; + EXPECT_TRUE( file.open() ); + + { + QTextStream out( &file ); + out << "NO 1234/5-6, 1234.56, 2019-11-13, 99.9, XLOT, 3, Good test\n"; + out << ", 1234.56, 2019-11-13, 99.9, XLOT, 3, Good test\n"; + } + + QStringList filePaths; + filePaths.append( file.fileName() ); + ASSERT_TRUE( + readingThrowsException( filePaths, + QString( "Unexpected empty 'Well Name' on line 2: %1" ).arg( file.fileName() ) ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifWellMeasurementReaderTest, ReadInvalidMeasureDepthThrows ) +{ + QTemporaryFile file; + EXPECT_TRUE( file.open() ); + + { + QTextStream out( &file ); + out << "well 1, 1234.56, 2019-11-13, 99.9, XLOT, 3, Good test\n"; + out << "well 2, this is should be a number, 2019-11-13, 99.9, XLOT, 3, Good test\n"; + } + + QStringList filePaths; + filePaths.append( file.fileName() ); + ASSERT_TRUE( + readingThrowsException( filePaths, + QString( "Invalid number for 'Measured Depth' on line 2: %1" ).arg( file.fileName() ) ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifWellMeasurementReaderTest, ReadInvalidQualityThrows ) +{ + QTemporaryFile file; + EXPECT_TRUE( file.open() ); + + { + QTextStream out( &file ); + out << "well 1, 1234.56, 2019-11-13, 99.9, XLOT, this is not an int, Good test\n"; + out << "well 2, 1234.56, 2019-11-13, 99.9, XLOT, 3, Good test\n"; + } + + QStringList filePaths; + filePaths.append( file.fileName() ); + ASSERT_TRUE( + readingThrowsException( filePaths, + QString( "Invalid number for 'Quality' on line 1: %1" ).arg( file.fileName() ) ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifWellMeasurementReaderTest, ReadInvalidDateFormateThrows ) +{ + QTemporaryFile file; + EXPECT_TRUE( file.open() ); + + { + QTextStream out( &file ); + out << "well 1, 1234.56, 17th May 1814, 99.9, XLOT, 1, Good test\n"; + out << "well 2, 1234.56, 2019-11-13, 99.9, XLOT, 3, Good test\n"; + } + + QStringList filePaths; + filePaths.append( file.fileName() ); + ASSERT_TRUE( readingThrowsException( filePaths, + QString( "Invalid date format (must be ISO 8601) for 'Date' on line 1: %1" ) + .arg( file.fileName() ) ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifWellMeasurementReaderTest, CommentsAndEmptyLinesAreIgnored ) +{ + QTemporaryFile file; + EXPECT_TRUE( file.open() ); + + { + QTextStream out( &file ); + // Comment should be ignored + out << "# This is a comment.\n"; + out << "#This is also a comment.\n"; + // Should skip empty lines + out << "\n"; + out << "\t\n"; + out << " \n"; + // Then some data + out << "well 1, 1234.56, 2019-11-11, 199.9, XLOT, 1, Good test\n"; + // Comment in-between data should be ignored + out << "# One more comment in-between the data\n"; + out << "well 2, 2234.56, 2019-11-12, 299.9, XLOT, 2, Good test\n"; + // Empty line in-between data should be ignored + out << "\n"; + // Data with comment sign inside it is not ignored + out << "well #3, 3234.56, 2019-11-13, 399.9, XLOT, 3, Good test\n"; + // Trailing empty lines should be ignored + out << "\n\n\n"; + } + + QStringList filePaths; + filePaths.append( file.fileName() ); + std::vector wellMeasurements; + RifWellMeasurementReader::readWellMeasurements( wellMeasurements, filePaths ); + + ASSERT_EQ( 3u, wellMeasurements.size() ); + + ASSERT_EQ( "well 1", wellMeasurements[0].wellName.toStdString() ); + ASSERT_EQ( "well 2", wellMeasurements[1].wellName.toStdString() ); + ASSERT_EQ( "well #3", wellMeasurements[2].wellName.toStdString() ); +} From d266e44f1f29bbf1a3431cb8c82e814a522074db Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Mon, 11 Nov 2019 23:09:22 +0100 Subject: [PATCH 04/12] #5001 Add RicImportWellMeasurementsFeature. --- .../WellPathCommands/CMakeLists_files.cmake | 2 + .../RicImportWellMeasurementsFeature.cpp | 142 ++++++++++++++++++ .../RicImportWellMeasurementsFeature.h | 40 +++++ .../RimContextCommandBuilder.cpp | 1 + 4 files changed, 185 insertions(+) create mode 100644 ApplicationCode/Commands/WellPathCommands/RicImportWellMeasurementsFeature.cpp create mode 100644 ApplicationCode/Commands/WellPathCommands/RicImportWellMeasurementsFeature.h diff --git a/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake index d1f45fe324..2ed251eb7d 100644 --- a/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake @@ -17,6 +17,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicWellPathFormationsImportFileFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicPolylineTargetsPickEventHandler.h ${CMAKE_CURRENT_LIST_DIR}/RicNewPolylineTargetFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicDeletePolylineTargetFeature.h +${CMAKE_CURRENT_LIST_DIR}/RicImportWellMeasurementsFeature.h ${CMAKE_CURRENT_LIST_DIR}/PointTangentManipulator/Ric3dObjectEditorHandle.h ${CMAKE_CURRENT_LIST_DIR}/PointTangentManipulator/RicPointTangentManipulator.h ${CMAKE_CURRENT_LIST_DIR}/PointTangentManipulator/RicWellTarget3dEditor.h @@ -44,6 +45,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicWellPathFormationsImportFileFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicPolylineTargetsPickEventHandler.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewPolylineTargetFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicDeletePolylineTargetFeature.cpp +${CMAKE_CURRENT_LIST_DIR}/RicImportWellMeasurementsFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/PointTangentManipulator/Ric3dObjectEditorHandle.cpp ${CMAKE_CURRENT_LIST_DIR}/PointTangentManipulator/RicPointTangentManipulator.cpp ${CMAKE_CURRENT_LIST_DIR}/PointTangentManipulator/RicWellTarget3dEditor.cpp diff --git a/ApplicationCode/Commands/WellPathCommands/RicImportWellMeasurementsFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicImportWellMeasurementsFeature.cpp new file mode 100644 index 0000000000..9f7c5e6ec5 --- /dev/null +++ b/ApplicationCode/Commands/WellPathCommands/RicImportWellMeasurementsFeature.cpp @@ -0,0 +1,142 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RicImportWellMeasurementsFeature.h" + +#include "RiaApplication.h" +#include "RiaLogging.h" + +#include "RimPerforationCollection.h" +#include "RimPerforationInterval.h" +#include "RimProject.h" +#include "RimWellMeasurement.h" +#include "RimWellMeasurementCollection.h" +#include "RimWellPath.h" +#include "RimWellPathCollection.h" + +#include "RifFileParseTools.h" +#include "RifWellMeasurementReader.h" + +#include "Riu3DMainWindowTools.h" + +#include "cafSelectionManager.h" + +#include +#include + +CAF_CMD_SOURCE_INIT( RicImportWellMeasurementsFeature, "RicImportWellMeasurementsFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicImportWellMeasurementsFeature::isCommandEnabled() +{ + return ( RicImportWellMeasurementsFeature::selectedWellPathCollection() != nullptr ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicImportWellMeasurementsFeature::onActionTriggered( bool isChecked ) +{ + RimWellPathCollection* wellPathCollection = RicImportWellMeasurementsFeature::selectedWellPathCollection(); + CVF_ASSERT( wellPathCollection ); + + // Open dialog box to select well path files + RiaApplication* app = RiaApplication::instance(); + QString defaultDir = app->lastUsedDialogDirectory( "WELLPATH_DIR" ); + QStringList wellPathFilePaths = QFileDialog::getOpenFileNames( Riu3DMainWindowTools::mainWindowWidget(), + "Import Well Measurements", + defaultDir, + "Well Measurements (*.csv);;All Files (*.*)" ); + + if ( wellPathFilePaths.size() < 1 ) return; + + // Remember the path to next time + app->setLastUsedDialogDirectory( "WELLPATH_DIR", QFileInfo( wellPathFilePaths.last() ).absolutePath() ); + + std::vector wellMeasurements; + try + { + RifWellMeasurementReader::readWellMeasurements( wellMeasurements, wellPathFilePaths ); + } + catch ( FileParseException& exception ) + { + RiaLogging::warning( QString( "Well measurement import failed: '%1'." ).arg( exception.message ) ); + return; + } + + RimWellMeasurement* lastWellMeasurement = nullptr; + for ( auto& measurement : wellMeasurements ) + { + RimWellPath* wellPath = wellPathCollection->tryFindMatchingWellPath( measurement.wellName ); + if ( wellPath == nullptr ) + { + RiaLogging::warning( QString( "Import Well Measurements : Imported file contains unknown well path '%1'." ) + .arg( measurement.wellName ) ); + } + else + { + RimWellMeasurement* wellMeasurement = new RimWellMeasurement; + wellMeasurement->setWellName( measurement.wellName ); + wellMeasurement->setMD( measurement.MD ); + wellMeasurement->setValue( measurement.value ); + wellMeasurement->setDate( measurement.date ); + wellMeasurement->setQuality( measurement.quality ); + wellMeasurement->setKind( measurement.kind ); + wellMeasurement->setRemark( measurement.remark ); + wellPath->measurementCollection()->appendMeasurement( wellMeasurement ); + lastWellMeasurement = wellMeasurement; + } + } + wellPathCollection->uiCapability()->updateConnectedEditors(); + + if ( app->project() ) + { + app->project()->scheduleCreateDisplayModelAndRedrawAllViews(); + } + + if ( lastWellMeasurement ) + { + Riu3DMainWindowTools::selectAsCurrentItem( lastWellMeasurement ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicImportWellMeasurementsFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Import Measurements" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPathCollection* RicImportWellMeasurementsFeature::selectedWellPathCollection() +{ + std::vector objects; + caf::SelectionManager::instance()->objectsByType( &objects ); + + if ( objects.size() == 1 ) + { + return objects[0]; + } + + return nullptr; +} diff --git a/ApplicationCode/Commands/WellPathCommands/RicImportWellMeasurementsFeature.h b/ApplicationCode/Commands/WellPathCommands/RicImportWellMeasurementsFeature.h new file mode 100644 index 0000000000..d4776c1ac4 --- /dev/null +++ b/ApplicationCode/Commands/WellPathCommands/RicImportWellMeasurementsFeature.h @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 + +#include "cafCmdFeature.h" + +class RimWellPathCollection; + +//================================================================================================== +/// +//================================================================================================== +class RicImportWellMeasurementsFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + // Overrides + bool isCommandEnabled() override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; + +private: + static RimWellPathCollection* selectedWellPathCollection(); +}; diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 7dc7192cb3..5dccc998db 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -310,6 +310,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder.addSeparator(); menuBuilder << "RicWellPathImportPerforationIntervalsFeature"; menuBuilder << "RicWellPathImportCompletionsFileFeature"; + menuBuilder << "RicImportWellMeasurementsFeature"; menuBuilder.subMenuEnd(); menuBuilder.addSeparator(); menuBuilder.subMenuStart( "Export Well Paths", QIcon( ":/Save.png" ) ); From 37ab75bc2a12f22a4e81bfbef8abbb06c595846a Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Wed, 13 Nov 2019 15:29:09 +0100 Subject: [PATCH 05/12] #5001 Add visualization for RimWellMeasurement. --- .../ModelVisualization/RivWellPathPartMgr.cpp | 81 ++++++++++++++++++- .../ModelVisualization/RivWellPathPartMgr.h | 6 ++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 6e83b1856d..972b1afb48 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -20,6 +20,7 @@ #include "RivWellPathPartMgr.h" +#include "RiaColorTables.h" #include "RiaGuiApplication.h" #include "RigEclipseCaseData.h" @@ -36,6 +37,8 @@ #include "RimFishbonesMultipleSubs.h" #include "RimPerforationCollection.h" #include "RimPerforationInterval.h" +#include "RimWellMeasurement.h" +#include "RimWellMeasurementCollection.h" #include "RimWellPath.h" #include "RimWellPathAttribute.h" #include "RimWellPathAttributeCollection.h" @@ -66,7 +69,7 @@ #include "cvfFont.h" #include "cvfModelBasicList.h" #include "cvfPart.h" -#include "cvfScalarMapperDiscreteLinear.h" +#include "cvfScalarMapperContinuousLinear.h" #include "cvfTransform.h" #include "cvfqtUtils.h" @@ -249,6 +252,81 @@ void RivWellPathPartMgr::appendWellPathAttributesToModel( cvf::ModelBasicList* } } +cvf::Color3f RivWellPathPartMgr::mapWellMeasurementToColor( const QString& measurementKind, double value ) +{ + if ( measurementKind == "TH" ) return cvf::Color3f::RED; + if ( measurementKind == "LE" ) return cvf::Color3f::BLUE; + if ( measurementKind == "BA" ) return cvf::Color3f::GREEN; + if ( measurementKind == "CORE" ) return cvf::Color3f::BLACK; + + QStringList rangeBasedMeasurements; + rangeBasedMeasurements << "XLOT" + << "LOT" + << "FIT" + << "MCF" + << "MNF" + << "PPG"; + if ( rangeBasedMeasurements.contains( measurementKind ) ) + { + cvf::ScalarMapperContinuousLinear mapper; + mapper.setColors( RiaColorTables::normalPaletteColors().color3ubArray() ); + mapper.setRange( 1.0, 3.0 ); + cvf::Color3ub color = mapper.mapToColor( value ); + return cvf::Color3f( color ); + } + + return cvf::Color3f::RED; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivWellPathPartMgr::appendWellMeasurementsToModel( cvf::ModelBasicList* model, + const caf::DisplayCoordTransform* displayCoordTransform, + double characteristicCellSize ) +{ + if ( !m_rimWellPath ) return; + + if ( !m_rimWellPath->measurementCollection()->isChecked() ) return; + + RivPipeGeometryGenerator geoGenerator; + std::vector wellMeasurements = m_rimWellPath->measurementCollection()->measurements(); + + for ( RimWellMeasurement* wellMeasurement : wellMeasurements ) + { + double wellPathRadius = this->wellPathRadius( characteristicCellSize, this->wellPathCollection() ); + double startMD = wellMeasurement->MD() - wellPathRadius * 0.5; + double endMD = wellMeasurement->MD() + wellPathRadius * 0.5; + + std::vector displayCoords; + displayCoords.push_back( displayCoordTransform->transformToDisplayCoord( + m_rimWellPath->wellPathGeometry()->interpolatedPointAlongWellPath( startMD ) ) ); + displayCoords.push_back( displayCoordTransform->transformToDisplayCoord( + m_rimWellPath->wellPathGeometry()->interpolatedPointAlongWellPath( startMD ) ) ); + displayCoords.push_back( displayCoordTransform->transformToDisplayCoord( + m_rimWellPath->wellPathGeometry()->interpolatedPointAlongWellPath( endMD ) ) ); + displayCoords.push_back( displayCoordTransform->transformToDisplayCoord( + m_rimWellPath->wellPathGeometry()->interpolatedPointAlongWellPath( endMD ) ) ); + + std::vector radii; + radii.push_back( wellPathRadius ); + radii.push_back( wellPathRadius * 2.5 ); + radii.push_back( wellPathRadius * 2.5 ); + radii.push_back( wellPathRadius ); + + cvf::ref objectSourceInfo = new RivObjectSourceInfo( wellMeasurement ); + + cvf::Collection parts; + cvf::Color3f color = mapWellMeasurementToColor( wellMeasurement->kind(), wellMeasurement->value() ); + geoGenerator.tubeWithCenterLinePartsAndVariableWidth( &parts, displayCoords, radii, color ); + for ( auto part : parts ) + { + part->setSourceInfo( objectSourceInfo.p() ); + model->addPart( part.p() ); + } + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -711,6 +789,7 @@ void RivWellPathPartMgr::appendStaticGeometryPartsToModel( cvf::ModelBasicList* appendFishboneSubsPartsToModel( model, displayCoordTransform, characteristicCellSize ); appendImportedFishbonesToModel( model, displayCoordTransform, characteristicCellSize ); appendWellPathAttributesToModel( model, displayCoordTransform, characteristicCellSize ); + appendWellMeasurementsToModel( model, displayCoordTransform, characteristicCellSize ); RimGridView* gridView = dynamic_cast( m_rimView.p() ); if ( !gridView ) return; diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h index fd2bc04cbc..d77f207b20 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h @@ -93,6 +93,10 @@ private: const caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize ); + void appendWellMeasurementsToModel( cvf::ModelBasicList* model, + const caf::DisplayCoordTransform* displayCoordTransform, + double characteristicCellSize ); + void appendImportedFishbonesToModel( cvf::ModelBasicList* model, const caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize ); @@ -125,6 +129,8 @@ private: bool isWellPathWithinBoundingBox( const cvf::BoundingBox& wellPathClipBoundingBox ) const; + static cvf::Color3f mapWellMeasurementToColor( const QString& measurementKind, double value ); + private: caf::PdmPointer m_rimWellPath; caf::PdmPointer m_rimView; From e380168f13f99b3041d3dbcf295ef5010915f013 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Wed, 13 Nov 2019 16:29:18 +0100 Subject: [PATCH 06/12] #5001 Show result info when picking RimWellMeasurement in 3d view. --- .../RicWellPathPickEventHandler.cpp | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathPickEventHandler.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathPickEventHandler.cpp index b2b5cda46c..64929f8126 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathPickEventHandler.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathPickEventHandler.cpp @@ -24,6 +24,8 @@ #include "Rim2dIntersectionView.h" #include "Rim3dView.h" #include "RimPerforationInterval.h" +#include "RimWellMeasurement.h" +#include "RimWellMeasurementCollection.h" #include "RimWellPath.h" #include "RimWellPathAttribute.h" #include "RimWellPathAttributeCollection.h" @@ -130,6 +132,35 @@ bool RicWellPathPickEventHandler::handle3dPickEvent( const Ric3dPickEvent& event RiuMainWindow::instance()->setResultInfo( attrText ); RiuMainWindow::instance()->selectAsCurrentItem( collection ); } + else if ( dynamic_cast( sourceInfo->object() ) ) + { + RimWellMeasurement* measurement = dynamic_cast( sourceInfo->object() ); + RimWellMeasurementCollection* collection = nullptr; + measurement->firstAncestorOrThisOfTypeAsserted( collection ); + + QString measurementText = QString( "Well path name: %1\n" ).arg( measurement->wellName() ); + measurementText += QString( "Measured Depth: %1\n" ).arg( measurement->MD() ); + measurementText += QString( "Value: %1\n" ).arg( measurement->value() ); + measurementText += QString( "Date: %1\n" ).arg( measurement->date().toString() ); + + if ( !measurement->kind().isEmpty() ) + { + measurementText += QString( "Kind: %1\n" ).arg( measurement->kind() ); + } + + if ( measurement->quality() > 0 ) + { + measurementText += QString( "Quality: %1\n" ).arg( measurement->quality() ); + } + + if ( !measurement->remark().isEmpty() ) + { + measurementText += QString( "Remark: %1\n" ).arg( measurement->remark() ); + } + + RiuMainWindow::instance()->setResultInfo( measurementText ); + RiuMainWindow::instance()->selectAsCurrentItem( collection ); + } } if ( dynamic_cast( firstPickedPart->sourceInfo() ) ) From 18c2350bdf157e39d321b0b0d666cae690ce4a3a Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Tue, 19 Nov 2019 11:07:51 +0100 Subject: [PATCH 07/12] #5001 Add measurements to WBS plot. --- ApplicationCode/Commands/RicWellLogTools.cpp | 31 ++ ApplicationCode/Commands/RicWellLogTools.h | 5 + .../RicNewWellBoreStabilityPlotFeature.cpp | 8 + .../ProjectDataModel/CMakeLists_files.cmake | 2 + .../RimWellMeasurementCurve.cpp | 381 ++++++++++++++++++ .../RimWellMeasurementCurve.h | 76 ++++ 6 files changed, 503 insertions(+) create mode 100644 ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.h diff --git a/ApplicationCode/Commands/RicWellLogTools.cpp b/ApplicationCode/Commands/RicWellLogTools.cpp index e53773e8e0..8dfa71eedc 100644 --- a/ApplicationCode/Commands/RicWellLogTools.cpp +++ b/ApplicationCode/Commands/RicWellLogTools.cpp @@ -33,6 +33,7 @@ #include "RimWellLogRftCurve.h" #include "RimWellLogTrack.h" #include "RimWellLogWbsCurve.h" +#include "RimWellMeasurementCurve.h" #include "RimWellPath.h" #include "RifReaderEclipseRft.h" @@ -410,3 +411,33 @@ RimWellLogWbsCurve* RicWellLogTools::addWellLogWbsCurve( RimWellLogTrack* plotTr useBranchDetection, showPlotWindow ); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellMeasurementCurve* RicWellLogTools::addWellMeasurementCurve( RimWellLogTrack* plotTrack, + RimWellPath* wellPath, + const QString& measurementKind, + bool showPlotWindow ) +{ + CVF_ASSERT( plotTrack ); + + RimWellMeasurementCurve* curve = new RimWellMeasurementCurve; + curve->setWellPath( wellPath ); + curve->setMeasurementKind( measurementKind ); + + plotTrack->addCurve( curve ); + plotTrack->updateConnectedEditors(); + + RiaApplication::instance()->project()->updateConnectedEditors(); + RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); + RiuPlotMainWindowTools::selectAsCurrentItem( curve ); + + if ( showPlotWindow ) + { + // Make sure the summary plot window is visible + RiuPlotMainWindowTools::showPlotMainWindow(); + } + + return curve; +} diff --git a/ApplicationCode/Commands/RicWellLogTools.h b/ApplicationCode/Commands/RicWellLogTools.h index a848bdfcb5..791d423be5 100644 --- a/ApplicationCode/Commands/RicWellLogTools.h +++ b/ApplicationCode/Commands/RicWellLogTools.h @@ -33,6 +33,7 @@ class RimWellLogRftCurve; class RimWellLogTrack; class RimWellLogWbsCurve; class RimWellPath; +class RimWellMeasurementCurve; //-------------------------------------------------------------------------------------------------- /// @@ -66,6 +67,10 @@ public: int branchIndex, bool useBranchDetection, bool showPlotWindow = true ); + static RimWellMeasurementCurve* addWellMeasurementCurve( RimWellLogTrack* plotTrack, + RimWellPath* wellPath, + const QString& measurementName, + bool showPlotWindow = true ); private: template diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewWellBoreStabilityPlotFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicNewWellBoreStabilityPlotFeature.cpp index 85eb22ba16..ba6d0125e6 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicNewWellBoreStabilityPlotFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicNewWellBoreStabilityPlotFeature.cpp @@ -321,6 +321,14 @@ void RicNewWellBoreStabilityPlotFeature::createStabilityCurvesTrack( RimWellBore curve->setSmoothCurve( true ); curve->setSmoothingThreshold( 0.002 ); } + + std::vector measurementNames; + measurementNames.push_back( "XLOT" ); + for ( size_t i = 0; i < measurementNames.size(); i++ ) + { + RicWellLogTools::addWellMeasurementCurve( stabilityCurvesTrack, wellPath, measurementNames[i] ); + } + stabilityCurvesTrack->setAutoScaleXEnabled( true ); } diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 6c419ff965..585a281f38 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -143,6 +143,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimPlotAxisAnnotation.h ${CMAKE_CURRENT_LIST_DIR}/RimObservedDataCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimObservedFmuRftData.h ${CMAKE_CURRENT_LIST_DIR}/RimMultiPlotCollection.h +${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementCurve.h ) @@ -290,6 +291,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimPlotAxisAnnotation.cpp ${CMAKE_CURRENT_LIST_DIR}/RimObservedDataCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimObservedFmuRftData.cpp ${CMAKE_CURRENT_LIST_DIR}/RimMultiPlotCollection.cpp +${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementCurve.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp new file mode 100644 index 0000000000..bac3ca89b9 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp @@ -0,0 +1,381 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// 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 "RimWellMeasurementCurve.h" + +#include "RigWellLogCurveData.h" +#include "RigWellPath.h" + +#include "RimProject.h" +#include "RimTools.h" +#include "RimWellLogFile.h" +#include "RimWellLogPlot.h" +#include "RimWellLogTrack.h" +#include "RimWellMeasurement.h" +#include "RimWellMeasurementCollection.h" +#include "RimWellPath.h" +#include "RimWellPathCollection.h" +#include "RimWellPlotTools.h" +#include "RimWellRftPlot.h" + +#include "RiuQwtPlotCurve.h" +#include "RiuQwtPlotWidget.h" + +#include "RiaApplication.h" +#include "RiaPreferences.h" + +#include "cafPdmUiTreeOrdering.h" + +#include +#include + +CAF_PDM_SOURCE_INIT( RimWellMeasurementCurve, "WellMeasurementCurve" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellMeasurementCurve::RimWellMeasurementCurve() +{ + CAF_PDM_InitObject( "Well Measurement Curve", "", "", "" ); + + CAF_PDM_InitFieldNoDefault( &m_wellPath, "CurveWellPath", "Well Path", "", "", "" ); + m_wellPath.uiCapability()->setUiTreeChildrenHidden( true ); + + CAF_PDM_InitFieldNoDefault( &m_measurementKind, "CurveMeasurementKind", "Measurement Kind", "", "", "" ); + m_measurementKind.uiCapability()->setUiTreeChildrenHidden( true ); + + m_wellPath = nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellMeasurementCurve::~RimWellMeasurementCurve() {} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCurve::onLoadDataAndUpdate( bool updateParentPlot ) +{ + this->RimPlotCurve::updateCurvePresentation( updateParentPlot ); + + if ( isCurveVisible() ) + { + RimWellLogPlot* wellLogPlot; + firstAncestorOrThisOfType( wellLogPlot ); + CVF_ASSERT( wellLogPlot ); + + if ( m_wellPath && !m_measurementKind().isEmpty() && m_wellPath->measurementCollection() ) + { + const RimWellMeasurementCollection* measurementCollection = m_wellPath->measurementCollection(); + + // Extract the values for this measurement kind + std::vector values; + std::vector measuredDepthValues; + for ( auto& measurement : measurementCollection->measurements() ) + { + if ( measurement->kind() == measurementKind() ) + { + values.push_back( measurement->value() ); + measuredDepthValues.push_back( measurement->MD() ); + } + } + + if ( values.size() == measuredDepthValues.size() ) + { + this->setValuesAndDepths( values, + measuredDepthValues, + RiaDefines::MEASURED_DEPTH, + RiaDefines::UNIT_METER, + false ); + + RigWellPath* rigWellPath = m_wellPath->wellPathGeometry(); + if ( rigWellPath ) + { + std::vector trueVerticalDepthValues; + + for ( double measuredDepthValue : measuredDepthValues ) + { + trueVerticalDepthValues.push_back( + -rigWellPath->interpolatedPointAlongWellPath( measuredDepthValue ).z() ); + } + this->setValuesAndDepths( values, + measuredDepthValues, + RiaDefines::TRUE_VERTICAL_DEPTH, + RiaDefines::UNIT_METER, + false ); + } + } + + if ( m_isUsingAutoName ) + { + m_qwtPlotCurve->setTitle( createCurveAutoName() ); + } + + setSymbol( getSymbolForMeasurementKind( m_measurementKind() ) ); + setColor( getColorForMeasurementKind( measurementKind() ) ); + setLineStyle( RiuQwtPlotCurve::STYLE_NONE ); + + RiaDefines::DepthUnitType displayUnit = RiaDefines::UNIT_METER; + if ( wellLogPlot ) + { + displayUnit = wellLogPlot->depthUnit(); + } + if ( wellLogPlot && wellLogPlot->depthType() == RiaDefines::TRUE_VERTICAL_DEPTH && + this->curveData()->availableDepthTypes().count( RiaDefines::TRUE_VERTICAL_DEPTH ) ) + { + m_qwtPlotCurve->setSamples( this->curveData()->xPlotValues().data(), + this->curveData() + ->depthPlotValues( RiaDefines::TRUE_VERTICAL_DEPTH, displayUnit ) + .data(), + static_cast( this->curveData()->xPlotValues().size() ) ); + } + else + { + m_qwtPlotCurve + ->setSamples( this->curveData()->xPlotValues().data(), + this->curveData()->depthPlotValues( RiaDefines::MEASURED_DEPTH, displayUnit ).data(), + static_cast( this->curveData()->xPlotValues().size() ) ); + } + m_qwtPlotCurve->setLineSegmentStartStopIndices( this->curveData()->polylineStartStopIndices() ); + } + + if ( updateParentPlot ) + { + updateZoomInParentPlot(); + } + + if ( m_parentQwtPlot ) + { + m_parentQwtPlot->replot(); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCurve::setWellPath( RimWellPath* wellPath ) +{ + m_wellPath = wellPath; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPath* RimWellMeasurementCurve::wellPath() const +{ + return m_wellPath; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) +{ + RimWellLogCurve::fieldChangedByUi( changedField, oldValue, newValue ); + + if ( changedField == &m_wellPath || changedField == &m_measurementKind ) + { + this->loadDataAndUpdate( true ); + } + if ( m_parentQwtPlot ) m_parentQwtPlot->replot(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + RimPlotCurve::updateOptionSensitivity(); + + caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Curve Data" ); + curveDataGroup->add( &m_wellPath ); + curveDataGroup->add( &m_measurementKind ); + + caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup( "Appearance" ); + RimPlotCurve::appearanceUiOrdering( *appearanceGroup ); + + caf::PdmUiGroup* nameGroup = uiOrdering.addNewGroup( "Curve Name" ); + nameGroup->add( &m_showLegend ); + RimPlotCurve::curveNameUiOrdering( *nameGroup ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCurve::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/ ) +{ + uiTreeOrdering.skipRemainingChildren( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList + RimWellMeasurementCurve::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly ) +{ + QList options; + + options = RimWellLogCurve::calculateValueOptions( fieldNeedingOptions, useOptionsOnly ); + if ( options.size() > 0 ) return options; + + if ( fieldNeedingOptions == &m_wellPath ) + { + auto wellPathColl = RimTools::wellPathCollection(); + if ( wellPathColl ) + { + caf::PdmChildArrayField& wellPaths = wellPathColl->wellPaths; + + for ( size_t i = 0; i < wellPaths.size(); i++ ) + { + options.push_back( caf::PdmOptionItemInfo( wellPaths[i]->name(), wellPaths[i] ) ); + } + + if ( options.size() > 0 ) + { + options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) ); + } + } + } + + if ( fieldNeedingOptions == &m_measurementKind ) + { + if ( m_wellPath() ) + { + // TODO: take all options from somewhere and filter based on + // what the current well path has set. + options.push_back( caf::PdmOptionItemInfo( "XLOT", "XLOT" ) ); + options.push_back( caf::PdmOptionItemInfo( "LOT", "LOT" ) ); + options.push_back( caf::PdmOptionItemInfo( "FIT", "FIT" ) ); + options.push_back( caf::PdmOptionItemInfo( "DP", "DP" ) ); + } + } + + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCurve::initAfterRead() +{ + if ( !m_wellPath ) return; + + // TODO: do something here? +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimWellMeasurementCurve::createCurveAutoName() +{ + if ( m_wellPath ) + { + QStringList name; + name.push_back( wellName() ); + name.push_back( measurementKind() ); + + return name.join( ", " ); + } + + return "Empty curve"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimWellMeasurementCurve::wellLogChannelName() const +{ + // Does not really make sense for measurement curve. + return QString( "" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimWellMeasurementCurve::wellName() const +{ + if ( m_wellPath ) + { + return m_wellPath->name(); + } + + return QString( "" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimWellMeasurementCurve::measurementKind() const +{ + if ( !m_measurementKind().isEmpty() ) + { + return m_measurementKind(); + } + + return QString( "None" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementCurve::setMeasurementKind( const QString& measurementKind ) +{ + m_measurementKind = measurementKind; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuQwtSymbol::PointSymbolEnum RimWellMeasurementCurve::getSymbolForMeasurementKind( const QString& measurementKind ) +{ + std::map symbolTable; + symbolTable["XLOT"] = RiuQwtSymbol::SYMBOL_RECT; + symbolTable["LOT"] = RiuQwtSymbol::SYMBOL_TRIANGLE; + symbolTable["FIT"] = RiuQwtSymbol::SYMBOL_DIAMOND; + symbolTable["MCF"] = RiuQwtSymbol::SYMBOL_ELLIPSE; + symbolTable["MNF"] = RiuQwtSymbol::SYMBOL_ELLIPSE; + symbolTable["TH"] = RiuQwtSymbol::SYMBOL_STAR1; + symbolTable["LE"] = RiuQwtSymbol::SYMBOL_STAR2; + symbolTable["BA"] = RiuQwtSymbol::SYMBOL_STAR1; + symbolTable["CORE"] = RiuQwtSymbol::SYMBOL_RECT; + symbolTable["PPG"] = RiuQwtSymbol::SYMBOL_RECT; + + auto it = symbolTable.find( measurementKind ); + if ( it != symbolTable.end() ) + return it->second; + else + return RiuQwtSymbol::SYMBOL_CROSS; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Color3f RimWellMeasurementCurve::getColorForMeasurementKind( const QString& measurementKind ) +{ + if ( measurementKind == "TH" ) return cvf::Color3f::RED; + if ( measurementKind == "LE" ) return cvf::Color3f::BLUE; + if ( measurementKind == "BA" ) return cvf::Color3f::GREEN; + if ( measurementKind == "CORE" ) return cvf::Color3f::BLACK; + + return cvf::Color3f::CRIMSON; +} diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.h b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.h new file mode 100644 index 0000000000..02f9a8c173 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.h @@ -0,0 +1,76 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// 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 + +#include "RimWellLogCurve.h" + +#include "RiuQwtSymbol.h" + +#include "cafPdmField.h" +#include "cafPdmPtrField.h" + +#include + +class RimWellPath; +class RimWellMeasurement; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimWellMeasurementCurve : public RimWellLogCurve +{ + CAF_PDM_HEADER_INIT; + +public: + RimWellMeasurementCurve(); + ~RimWellMeasurementCurve() override; + + void setWellPath( RimWellPath* wellPath ); + RimWellPath* wellPath() const; + void setMeasurementKind( const QString& measurementKind ); + QString measurementKind() const; + + // Overrides from RimWellLogPlotCurve + QString wellName() const override; + QString wellLogChannelName() const override; + +protected: + // Overrides from RimWellLogCurve + QString createCurveAutoName() override; + void onLoadDataAndUpdate( bool updateParentPlot ) override; + + // Pdm overrrides + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) override; + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly ) override; + void initAfterRead() override; + + RiuQwtSymbol::PointSymbolEnum getSymbolForMeasurementKind( const QString& measurementKind ); + cvf::Color3f getColorForMeasurementKind( const QString& measurementKind ); + +protected: + caf::PdmPtrField m_wellPath; + caf::PdmField m_measurementKind; +}; From ea534cace63c47ffad464c2e9329e435fe8f1897 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Tue, 19 Nov 2019 20:38:17 +0100 Subject: [PATCH 08/12] #5001 Update plots on changes in RimWellMeasurement. --- ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp index ce7b70f191..36b5cee2db 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp @@ -17,6 +17,8 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimWellMeasurement.h" +#include "RimProject.h" +#include "RimWellMeasurementCollection.h" #include "RimWellPath.h" CAF_PDM_SOURCE_INIT( RimWellMeasurement, "WellMeasurement" ); @@ -161,6 +163,13 @@ void RimWellMeasurement::fieldChangedByUi( const caf::PdmFieldHandle* changedFie const QVariant& oldValue, const QVariant& newValue ) { + RimProject* proj; + this->firstAncestorOrThisOfTypeAsserted( proj ); + proj->scheduleCreateDisplayModelAndRedrawAllViews(); + + RimWellMeasurementCollection* wellMeasurementCollection; + this->firstAncestorOrThisOfTypeAsserted( wellMeasurementCollection ); + wellMeasurementCollection->updateAllReferringTracks(); } //-------------------------------------------------------------------------------------------------- From b4fea5f00a595cfa57a6db38390fba51c530b618 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Mon, 25 Nov 2019 12:18:39 +0100 Subject: [PATCH 09/12] #5001 Move RimWellMeasurementCollection from RimWellPath to RimWellPathCollection. Also add filtering of measurements by well path. --- .../RicImportWellMeasurementsFeature.cpp | 29 +++++------- .../ModelVisualization/RivWellPathPartMgr.cpp | 16 +++++-- .../ProjectDataModel/CMakeLists_files.cmake | 2 + .../RimWellMeasurementCurve.cpp | 13 ++++-- .../RimWellMeasurementFilter.cpp | 45 +++++++++++++++++++ .../RimWellMeasurementFilter.h | 35 +++++++++++++++ .../ProjectDataModel/RimWellPath.cpp | 28 ------------ .../ProjectDataModel/RimWellPath.h | 4 -- .../RimWellPathCollection.cpp | 27 ++++++++++- .../ProjectDataModel/RimWellPathCollection.h | 11 +++-- 10 files changed, 147 insertions(+), 63 deletions(-) create mode 100644 ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h diff --git a/ApplicationCode/Commands/WellPathCommands/RicImportWellMeasurementsFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicImportWellMeasurementsFeature.cpp index 9f7c5e6ec5..b3b84d5c4a 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicImportWellMeasurementsFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicImportWellMeasurementsFeature.cpp @@ -84,25 +84,16 @@ void RicImportWellMeasurementsFeature::onActionTriggered( bool isChecked ) RimWellMeasurement* lastWellMeasurement = nullptr; for ( auto& measurement : wellMeasurements ) { - RimWellPath* wellPath = wellPathCollection->tryFindMatchingWellPath( measurement.wellName ); - if ( wellPath == nullptr ) - { - RiaLogging::warning( QString( "Import Well Measurements : Imported file contains unknown well path '%1'." ) - .arg( measurement.wellName ) ); - } - else - { - RimWellMeasurement* wellMeasurement = new RimWellMeasurement; - wellMeasurement->setWellName( measurement.wellName ); - wellMeasurement->setMD( measurement.MD ); - wellMeasurement->setValue( measurement.value ); - wellMeasurement->setDate( measurement.date ); - wellMeasurement->setQuality( measurement.quality ); - wellMeasurement->setKind( measurement.kind ); - wellMeasurement->setRemark( measurement.remark ); - wellPath->measurementCollection()->appendMeasurement( wellMeasurement ); - lastWellMeasurement = wellMeasurement; - } + RimWellMeasurement* wellMeasurement = new RimWellMeasurement; + wellMeasurement->setWellName( measurement.wellName ); + wellMeasurement->setMD( measurement.MD ); + wellMeasurement->setValue( measurement.value ); + wellMeasurement->setDate( measurement.date ); + wellMeasurement->setQuality( measurement.quality ); + wellMeasurement->setKind( measurement.kind ); + wellMeasurement->setRemark( measurement.remark ); + wellPathCollection->measurementCollection()->appendMeasurement( wellMeasurement ); + lastWellMeasurement = wellMeasurement; } wellPathCollection->uiCapability()->updateConnectedEditors(); diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 972b1afb48..1a6e0d587d 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -37,16 +37,17 @@ #include "RimFishbonesMultipleSubs.h" #include "RimPerforationCollection.h" #include "RimPerforationInterval.h" +#include "RimTools.h" #include "RimWellMeasurement.h" #include "RimWellMeasurementCollection.h" +#include "RimWellMeasurementFilter.h" #include "RimWellPath.h" #include "RimWellPathAttribute.h" #include "RimWellPathAttributeCollection.h" #include "RimWellPathCollection.h" -#include "RimWellPathValve.h" - #include "RimWellPathFracture.h" #include "RimWellPathFractureCollection.h" +#include "RimWellPathValve.h" #include "Riv3dWellLogPlanePartMgr.h" #include "RivFishbonesSubsPartMgr.h" @@ -287,10 +288,17 @@ void RivWellPathPartMgr::appendWellMeasurementsToModel( cvf::ModelBasicList* { if ( !m_rimWellPath ) return; - if ( !m_rimWellPath->measurementCollection()->isChecked() ) return; + RimWellPathCollection* wellPathCollection = RimTools::wellPathCollection(); + if ( !wellPathCollection ) return; + + RimWellMeasurementCollection* wellMeasurementCollection = wellPathCollection->measurementCollection(); + if ( !wellMeasurementCollection ) return; RivPipeGeometryGenerator geoGenerator; - std::vector wellMeasurements = m_rimWellPath->measurementCollection()->measurements(); + std::vector wellMeasurements = + RimWellMeasurementFilter::filterMeasurements( wellMeasurementCollection->measurements(), + *wellPathCollection, + *m_rimWellPath ); for ( RimWellMeasurement* wellMeasurement : wellMeasurements ) { diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 585a281f38..80bcc15e5a 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -144,6 +144,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimObservedDataCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimObservedFmuRftData.h ${CMAKE_CURRENT_LIST_DIR}/RimMultiPlotCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementCurve.h +${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementFilter.h ) @@ -292,6 +293,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimObservedDataCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimObservedFmuRftData.cpp ${CMAKE_CURRENT_LIST_DIR}/RimMultiPlotCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementCurve.cpp +${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementFilter.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp index bac3ca89b9..4bab043af1 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp @@ -29,6 +29,7 @@ #include "RimWellLogTrack.h" #include "RimWellMeasurement.h" #include "RimWellMeasurementCollection.h" +#include "RimWellMeasurementFilter.h" #include "RimWellPath.h" #include "RimWellPathCollection.h" #include "RimWellPlotTools.h" @@ -81,14 +82,20 @@ void RimWellMeasurementCurve::onLoadDataAndUpdate( bool updateParentPlot ) firstAncestorOrThisOfType( wellLogPlot ); CVF_ASSERT( wellLogPlot ); - if ( m_wellPath && !m_measurementKind().isEmpty() && m_wellPath->measurementCollection() ) + RimWellPathCollection* wellPathCollection = RimTools::wellPathCollection(); + if ( m_wellPath && !m_measurementKind().isEmpty() && wellPathCollection ) { - const RimWellMeasurementCollection* measurementCollection = m_wellPath->measurementCollection(); + const RimWellMeasurementCollection* measurementCollection = wellPathCollection->measurementCollection(); + + std::vector measurements = + RimWellMeasurementFilter::filterMeasurements( measurementCollection->measurements(), + *wellPathCollection, + *m_wellPath ); // Extract the values for this measurement kind std::vector values; std::vector measuredDepthValues; - for ( auto& measurement : measurementCollection->measurements() ) + for ( auto& measurement : measurements ) { if ( measurement->kind() == measurementKind() ) { diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp new file mode 100644 index 0000000000..451cbbb437 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp @@ -0,0 +1,45 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RimWellMeasurementFilter.h" + +#include "RimWellMeasurement.h" +#include "RimWellMeasurementCollection.h" +#include "RimWellPath.h" +#include "RimWellPathCollection.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector + RimWellMeasurementFilter::filterMeasurements( const std::vector& measurements, + const RimWellPathCollection& wellPathCollection, + const RimWellPath& wellPath ) +{ + std::vector filteredMeasurements; + + for ( auto& measurement : measurements ) + { + RimWellPath* matchedWellPath = wellPathCollection.tryFindMatchingWellPath( measurement->wellName() ); + if ( matchedWellPath && matchedWellPath == &wellPath ) + { + filteredMeasurements.push_back( measurement ); + } + } + + return filteredMeasurements; +} diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h new file mode 100644 index 0000000000..3289f651b7 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h @@ -0,0 +1,35 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 + +#include + +class RimWellPath; +class RimWellMeasurement; +class RimWellPathCollection; + +class RimWellMeasurementFilter +{ +public: + static std::vector filterMeasurements( const std::vector& measurements, + const RimWellPathCollection& wellPathCollection, + const RimWellPath& rimWellPath ); + +private: + RimWellMeasurementFilter(); +}; diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index 446e75ff36..ec658990f9 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -42,7 +42,6 @@ #include "RimWellLogFile.h" #include "RimWellLogFileChannel.h" #include "RimWellLogPlotCollection.h" -#include "RimWellMeasurementCollection.h" #include "RimWellPathAttributeCollection.h" #include "RimWellPathCollection.h" #include "RimWellPathCompletions.h" @@ -129,10 +128,6 @@ RimWellPath::RimWellPath() m_wellPathAttributes = new RimWellPathAttributeCollection; m_wellPathAttributes->uiCapability()->setUiTreeHidden( true ); - CAF_PDM_InitFieldNoDefault( &m_wellMeasurements, "WellMeasurements", "Measurements", "", "", "" ); - m_wellMeasurements = new RimWellMeasurementCollection; - m_wellMeasurements->uiCapability()->setUiTreeHidden( true ); - m_wellPath = nullptr; } @@ -496,24 +491,6 @@ const RimWellPathAttributeCollection* RimWellPath::attributeCollection() const return m_wellPathAttributes; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- - -RimWellMeasurementCollection* RimWellPath::measurementCollection() -{ - return m_wellMeasurements; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- - -const RimWellMeasurementCollection* RimWellPath::measurementCollection() const -{ - return m_wellMeasurements; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -630,11 +607,6 @@ void RimWellPath::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, uiTreeOrdering.add( m_wellPathAttributes() ); } - if ( !m_wellMeasurements->measurements().empty() ) - { - uiTreeOrdering.add( m_wellMeasurements() ); - } - uiTreeOrdering.skipRemainingChildren( true ); } diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.h b/ApplicationCode/ProjectDataModel/RimWellPath.h index 33e48d4676..1a978ce839 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.h +++ b/ApplicationCode/ProjectDataModel/RimWellPath.h @@ -49,7 +49,6 @@ class RimFishboneWellPathCollection; class RimFishbonesCollection; class RimPerforationCollection; class RimWellPathAttributeCollection; -class RimWellMeasurementCollection; class RimWellPathCompletions; class RigWellPathFormations; @@ -111,8 +110,6 @@ public: const RimWellPathFractureCollection* fractureCollection() const; RimWellPathAttributeCollection* attributeCollection(); const RimWellPathAttributeCollection* attributeCollection() const; - RimWellMeasurementCollection* measurementCollection(); - const RimWellMeasurementCollection* measurementCollection() const; bool showWellPathLabel() const; bool showWellPath() const; @@ -174,7 +171,6 @@ private: caf::PdmChildField m_3dWellLogCurves; caf::PdmChildField m_completions; caf::PdmChildField m_wellPathAttributes; - caf::PdmChildField m_wellMeasurements; private: static size_t simulationWellBranchCount( const QString& simWellName ); diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp index cb845f1790..be165e56b8 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp @@ -38,6 +38,7 @@ #include "RimPerforationCollection.h" #include "RimProject.h" #include "RimWellLogFile.h" +#include "RimWellMeasurementCollection.h" #include "RimWellPath.h" #include "Riu3DMainWindowTools.h" @@ -103,9 +104,12 @@ RimWellPathCollection::RimWellPathCollection() CAF_PDM_InitField( &wellPathClipZDistance, "WellPathClipZDistance", 100, "Well Path Clipping Depth Distance", "", "", "" ); CAF_PDM_InitFieldNoDefault( &wellPaths, "WellPaths", "Well Paths", "", "", "" ); - wellPaths.uiCapability()->setUiHidden( true ); + CAF_PDM_InitFieldNoDefault( &m_wellMeasurements, "WellMeasurements", "Measurements", "", "", "" ); + m_wellMeasurements = new RimWellMeasurementCollection; + m_wellMeasurements->uiCapability()->setUiTreeHidden( true ); + m_wellPathImporter = new RifWellPathImporter; m_wellPathFormationsImporter = new RifWellPathFormationsImporter; m_mostRecentlyUpdatedWellPath = nullptr; @@ -221,7 +225,8 @@ std::vector RimWellPathCollection::addWellPaths( QStringList f QString s2 = f2.fileName(); if ( s1 == s2 ) { - // printf("Attempting to open well path JSON file that is already open:\n %s\n", (const char*) filePath.toLocal8Bit()); + // printf("Attempting to open well path JSON file that is already open:\n %s\n", (const char*) + // filePath.toLocal8Bit()); alreadyOpen = true; errorMessages->push_back( QString( "%1 is already loaded" ).arg( filePath ) ); break; @@ -654,3 +659,21 @@ RiaEclipseUnitTools::UnitSystemType RimWellPathCollection::findUnitSystemForWell } return RiaEclipseUnitTools::UNITS_UNKNOWN; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- + +RimWellMeasurementCollection* RimWellPathCollection::measurementCollection() +{ + return m_wellMeasurements; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- + +const RimWellMeasurementCollection* RimWellPathCollection::measurementCollection() const +{ + return m_wellMeasurements; +} diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.h b/ApplicationCode/ProjectDataModel/RimWellPathCollection.h index 4d406638a5..37e61ceb42 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.h +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.h @@ -42,6 +42,7 @@ class RimProject; class RimWellLogFile; class RimWellPath; class RifWellPathFormationsImporter; +class RimWellMeasurementCollection; class QString; namespace cvf @@ -111,6 +112,9 @@ public: bool anyWellsContainingPerforationIntervals() const; size_t modelledWellPathCount() const; + RimWellMeasurementCollection* measurementCollection(); + const RimWellMeasurementCollection* measurementCollection() const; + protected: void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, @@ -125,7 +129,8 @@ private: RiaEclipseUnitTools::UnitSystemType findUnitSystemForWellPath( const RimWellPath* wellPath ); - RifWellPathImporter* m_wellPathImporter; - RifWellPathFormationsImporter* m_wellPathFormationsImporter; - caf::PdmPointer m_mostRecentlyUpdatedWellPath; + RifWellPathImporter* m_wellPathImporter; + RifWellPathFormationsImporter* m_wellPathFormationsImporter; + caf::PdmPointer m_mostRecentlyUpdatedWellPath; + caf::PdmChildField m_wellMeasurements; }; From ea7df9464942aab4bb658c543ce3db07955ef5b9 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Mon, 25 Nov 2019 19:48:11 +0100 Subject: [PATCH 10/12] #5001 Improve filtering of measurement collection. --- .../ModelVisualization/RivWellPathPartMgr.cpp | 7 +++- .../RimWellMeasurementCollection.cpp | 40 ++++++++++++++++++- .../RimWellMeasurementCollection.h | 5 +++ .../RimWellMeasurementCurve.cpp | 5 ++- .../RimWellMeasurementFilter.cpp | 12 ++++-- .../RimWellMeasurementFilter.h | 5 ++- 6 files changed, 66 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 1a6e0d587d..7a7c07bbfb 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -294,11 +294,16 @@ void RivWellPathPartMgr::appendWellMeasurementsToModel( cvf::ModelBasicList* RimWellMeasurementCollection* wellMeasurementCollection = wellPathCollection->measurementCollection(); if ( !wellMeasurementCollection ) return; + if ( !wellMeasurementCollection->isChecked() ) return; + + std::vector measurementKinds = wellMeasurementCollection->measurementKinds(); + RivPipeGeometryGenerator geoGenerator; std::vector wellMeasurements = RimWellMeasurementFilter::filterMeasurements( wellMeasurementCollection->measurements(), *wellPathCollection, - *m_rimWellPath ); + *m_rimWellPath, + measurementKinds ); for ( RimWellMeasurement* wellMeasurement : wellMeasurements ) { diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.cpp index c862c2cc4a..608b3c7700 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.cpp @@ -24,6 +24,7 @@ #include "cafCmdFeatureMenuBuilder.h" #include "cafPdmUiTableViewEditor.h" #include "cafPdmUiTreeOrdering.h" +#include "cafPdmUiTreeSelectionEditor.h" CAF_PDM_SOURCE_INIT( RimWellMeasurementCollection, "WellMeasurements" ); @@ -38,6 +39,13 @@ RimWellMeasurementCollection::RimWellMeasurementCollection() m_measurements.uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() ); m_measurements.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); m_measurements.uiCapability()->setCustomContextMenuEnabled( true ); + + CAF_PDM_InitFieldNoDefault( &m_measurementKinds, "MeasurementKinds", "Measurent Kinds", "", "", "" ); + m_measurementKinds.uiCapability()->setAutoAddingOptionFromValue( false ); + m_measurementKinds.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); + m_measurementKinds.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN ); + m_measurementKinds.xmlCapability()->disableIO(); + this->setName( "Well Measurements" ); } @@ -177,7 +185,7 @@ void RimWellMeasurementCollection::fieldChangedByUi( const caf::PdmFieldHandle* const QVariant& oldValue, const QVariant& newValue ) { - if ( changedField == &m_isChecked ) + if ( changedField == &m_isChecked || changedField == &m_measurementKinds ) { RimProject* proj; this->firstAncestorOrThisOfTypeAsserted( proj ); @@ -185,3 +193,33 @@ void RimWellMeasurementCollection::fieldChangedByUi( const caf::PdmFieldHandle* this->updateAllReferringTracks(); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList + RimWellMeasurementCollection::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly ) +{ + QList options; + if ( fieldNeedingOptions == &m_measurementKinds ) + { + std::set measurementKindsInData; + for ( auto measurement : measurements() ) + { + measurementKindsInData.insert( measurement->kind() ); + } + + for ( auto measurementKind : measurementKindsInData ) + { + options.push_back( caf::PdmOptionItemInfo( measurementKind, measurementKind ) ); + } + } + + return options; +} + +std::vector RimWellMeasurementCollection::measurementKinds() const +{ + return m_measurementKinds; +} diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h index 42a3466356..f97d3b9c4f 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h @@ -22,6 +22,7 @@ #include "cafPdmChildArrayField.h" #include "cafPdmField.h" #include "cafPdmObject.h" +#include "cafPdmProxyValueField.h" class RimWellMeasurement; @@ -34,6 +35,7 @@ public: ~RimWellMeasurementCollection() override; std::vector measurements() const; + std::vector measurementKinds() const; void updateAllReferringTracks(); void insertMeasurement( RimWellMeasurement* insertBefore, RimWellMeasurement* measurement ); @@ -53,7 +55,10 @@ protected: void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly ); private: caf::PdmChildArrayField m_measurements; + caf::PdmField> m_measurementKinds; }; diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp index 4bab043af1..b2095a1b99 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp @@ -87,10 +87,13 @@ void RimWellMeasurementCurve::onLoadDataAndUpdate( bool updateParentPlot ) { const RimWellMeasurementCollection* measurementCollection = wellPathCollection->measurementCollection(); + std::vector measurementKinds = measurementCollection->measurementKinds(); + std::vector measurements = RimWellMeasurementFilter::filterMeasurements( measurementCollection->measurements(), *wellPathCollection, - *m_wellPath ); + *m_wellPath, + measurementKinds ); // Extract the values for this measurement kind std::vector values; diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp index 451cbbb437..440718d17b 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp @@ -28,16 +28,20 @@ std::vector RimWellMeasurementFilter::filterMeasurements( const std::vector& measurements, const RimWellPathCollection& wellPathCollection, - const RimWellPath& wellPath ) + const RimWellPath& wellPath, + const std::vector& measurementKinds ) { std::vector filteredMeasurements; for ( auto& measurement : measurements ) { - RimWellPath* matchedWellPath = wellPathCollection.tryFindMatchingWellPath( measurement->wellName() ); - if ( matchedWellPath && matchedWellPath == &wellPath ) + if ( std::find( measurementKinds.begin(), measurementKinds.end(), measurement->kind() ) != measurementKinds.end() ) { - filteredMeasurements.push_back( measurement ); + RimWellPath* matchedWellPath = wellPathCollection.tryFindMatchingWellPath( measurement->wellName() ); + if ( matchedWellPath && matchedWellPath == &wellPath ) + { + filteredMeasurements.push_back( measurement ); + } } } diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h index 3289f651b7..f409f42860 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h @@ -23,12 +23,15 @@ class RimWellPath; class RimWellMeasurement; class RimWellPathCollection; +class QString; + class RimWellMeasurementFilter { public: static std::vector filterMeasurements( const std::vector& measurements, const RimWellPathCollection& wellPathCollection, - const RimWellPath& rimWellPath ); + const RimWellPath& rimWellPath, + const std::vector& measurementKinds ); private: RimWellMeasurementFilter(); From 6bec758d15204788dd22a7d908c41803f15b0cdd Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Wed, 27 Nov 2019 12:05:01 +0100 Subject: [PATCH 11/12] #5001 Add RimWellMeasurementInViewCollection and legends. --- .../ModelVisualization/RivWellPathPartMgr.cpp | 17 +- .../ProjectDataModel/CMakeLists_files.cmake | 2 + .../ProjectDataModel/RimEclipseView.cpp | 12 ++ .../ProjectDataModel/RimGeoMechView.cpp | 10 + .../ProjectDataModel/RimGridView.cpp | 14 ++ .../ProjectDataModel/RimGridView.h | 13 +- .../RimWellMeasurementCollection.cpp | 56 +---- .../RimWellMeasurementCollection.h | 7 - .../RimWellMeasurementCurve.cpp | 3 +- .../RimWellMeasurementFilter.cpp | 17 ++ .../RimWellMeasurementFilter.h | 2 + .../RimWellMeasurementInViewCollection.cpp | 197 ++++++++++++++++++ .../RimWellMeasurementInViewCollection.h | 60 ++++++ 13 files changed, 341 insertions(+), 69 deletions(-) create mode 100644 ApplicationCode/ProjectDataModel/RimWellMeasurementInViewCollection.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimWellMeasurementInViewCollection.h diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 7a7c07bbfb..c48e8426d4 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -37,10 +37,12 @@ #include "RimFishbonesMultipleSubs.h" #include "RimPerforationCollection.h" #include "RimPerforationInterval.h" +#include "RimRegularLegendConfig.h" #include "RimTools.h" #include "RimWellMeasurement.h" #include "RimWellMeasurementCollection.h" #include "RimWellMeasurementFilter.h" +#include "RimWellMeasurementInViewCollection.h" #include "RimWellPath.h" #include "RimWellPathAttribute.h" #include "RimWellPathAttributeCollection.h" @@ -288,15 +290,18 @@ void RivWellPathPartMgr::appendWellMeasurementsToModel( cvf::ModelBasicList* { if ( !m_rimWellPath ) return; + RimGridView* gridView = dynamic_cast( m_rimView.p() ); + if ( !gridView ) return; + RimWellPathCollection* wellPathCollection = RimTools::wellPathCollection(); if ( !wellPathCollection ) return; RimWellMeasurementCollection* wellMeasurementCollection = wellPathCollection->measurementCollection(); if ( !wellMeasurementCollection ) return; - if ( !wellMeasurementCollection->isChecked() ) return; + if ( !gridView->measurementCollection()->isChecked() ) return; - std::vector measurementKinds = wellMeasurementCollection->measurementKinds(); + std::vector measurementKinds = gridView->measurementCollection()->measurementKinds(); RivPipeGeometryGenerator geoGenerator; std::vector wellMeasurements = @@ -331,6 +336,14 @@ void RivWellPathPartMgr::appendWellMeasurementsToModel( cvf::ModelBasicList* cvf::Collection parts; cvf::Color3f color = mapWellMeasurementToColor( wellMeasurement->kind(), wellMeasurement->value() ); + + // Use the view legend config to find color, if only one type of measurement is selected. + if ( measurementKinds.size() == 1 ) + { + color = cvf::Color3f( gridView->measurementCollection()->legendConfig()->scalarMapper()->mapToColor( + wellMeasurement->value() ) ); + } + geoGenerator.tubeWithCenterLinePartsAndVariableWidth( &parts, displayCoords, radii, color ); for ( auto part : parts ) { diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 80bcc15e5a..e413b23947 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -145,6 +145,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimObservedFmuRftData.h ${CMAKE_CURRENT_LIST_DIR}/RimMultiPlotCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementCurve.h ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementFilter.h +${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementInViewCollection.h ) @@ -294,6 +295,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimObservedFmuRftData.cpp ${CMAKE_CURRENT_LIST_DIR}/RimMultiPlotCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementCurve.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementFilter.cpp +${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementInViewCollection.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationCode/ProjectDataModel/RimEclipseView.cpp index 9227ec38ca..24e9d10a7d 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseView.cpp @@ -76,6 +76,7 @@ #include "RimViewLinker.h" #include "RimViewNameConfig.h" #include "RimVirtualPerforationResults.h" +#include "RimWellMeasurementInViewCollection.h" #include "RimWellPathCollection.h" #include "Riu3dSelectionManager.h" @@ -1311,6 +1312,12 @@ void RimEclipseView::onUpdateLegends() nativeOrOverrideViewer()->addColorLegendToBottomLeftCorner( virtLegend->titledOverlayFrame(), isUsingOverrideViewer() ); } + + if ( m_wellMeasurementCollection->isChecked() && m_wellMeasurementCollection->legendConfig()->showLegend() ) + { + m_wellMeasurementCollection->updateLegendRangesTextAndVisibility( nativeOrOverrideViewer(), + isUsingOverrideViewer() ); + } } //-------------------------------------------------------------------------------------------------- @@ -1719,6 +1726,7 @@ void RimEclipseView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin uiTreeOrdering.add( faultResultSettings() ); uiTreeOrdering.add( &m_intersectionResultDefCollection ); uiTreeOrdering.add( wellCollection() ); + uiTreeOrdering.add( &m_wellMeasurementCollection ); { bool showFractureColors = false; @@ -1856,6 +1864,8 @@ void RimEclipseView::onResetLegendsInViewer() sepInterResDef->ternaryLegendConfig()->recreateLegend(); } + m_wellMeasurementCollection->legendConfig()->recreateLegend(); + nativeOrOverrideViewer()->removeAllColorLegends(); } @@ -2014,6 +2024,8 @@ std::vector RimEclipseView::legendConfigs() const absLegends.push_back( sepInterResDef->ternaryLegendConfig() ); } + absLegends.push_back( m_wellMeasurementCollection->legendConfig() ); + return absLegends; } diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp b/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp index 846a7879d1..78e270c1db 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp +++ b/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp @@ -46,6 +46,7 @@ #include "RimTernaryLegendConfig.h" #include "RimViewLinker.h" #include "RimViewNameConfig.h" +#include "RimWellMeasurementInViewCollection.h" #include "Riu3DMainWindowTools.h" #include "Riu3dSelectionManager.h" @@ -433,6 +434,8 @@ void RimGeoMechView::onResetLegendsInViewer() sepInterResDef->ternaryLegendConfig()->recreateLegend(); } + m_wellMeasurementCollection->legendConfig()->recreateLegend(); + nativeOrOverrideViewer()->removeAllColorLegends(); } @@ -483,6 +486,12 @@ void RimGeoMechView::onUpdateLegends() isUsingOverrideViewer() ); } } + + if ( m_wellMeasurementCollection->isChecked() && m_wellMeasurementCollection->legendConfig()->showLegend() ) + { + m_wellMeasurementCollection->updateLegendRangesTextAndVisibility( nativeOrOverrideViewer(), + isUsingOverrideViewer() ); + } } } @@ -907,6 +916,7 @@ void RimGeoMechView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin uiTreeOrdering.add( cellResult() ); uiTreeOrdering.add( m_tensorResults() ); uiTreeOrdering.add( &m_intersectionResultDefCollection ); + uiTreeOrdering.add( &m_wellMeasurementCollection ); uiTreeOrdering.add( m_intersectionCollection() ); diff --git a/ApplicationCode/ProjectDataModel/RimGridView.cpp b/ApplicationCode/ProjectDataModel/RimGridView.cpp index 09931d0a61..6947ee2b13 100644 --- a/ApplicationCode/ProjectDataModel/RimGridView.cpp +++ b/ApplicationCode/ProjectDataModel/RimGridView.cpp @@ -33,6 +33,7 @@ #include "RimViewLinker.h" #include "RimViewLinkerCollection.h" #include "RimViewNameConfig.h" +#include "RimWellMeasurementInViewCollection.h" #include "Riu3DMainWindowTools.h" #include "RiuMainWindow.h" @@ -85,6 +86,10 @@ RimGridView::RimGridView() m_overlayInfoConfig = new Rim3dOverlayInfoConfig(); m_overlayInfoConfig->setReservoirView( this ); m_overlayInfoConfig.uiCapability()->setUiHidden( true ); + + CAF_PDM_InitFieldNoDefault( &m_wellMeasurementCollection, "WellMeasurements", "Well Measurements", "", "", "" ); + m_wellMeasurementCollection = new RimWellMeasurementInViewCollection; + m_wellMeasurementCollection.uiCapability()->setUiHidden( true ); } //-------------------------------------------------------------------------------------------------- @@ -117,6 +122,7 @@ RimGridView::~RimGridView( void ) delete this->m_overlayInfoConfig(); + delete m_wellMeasurementCollection; delete m_rangeFilterCollection; delete m_overrideRangeFilterCollection; delete m_intersectionCollection; @@ -161,6 +167,14 @@ RimIntersectionCollection* RimGridView::intersectionCollection() const return m_intersectionCollection(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellMeasurementInViewCollection* RimGridView::measurementCollection() const +{ + return m_wellMeasurementCollection; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimGridView.h b/ApplicationCode/ProjectDataModel/RimGridView.h index d0d33e27e3..d28621eb5a 100644 --- a/ApplicationCode/ProjectDataModel/RimGridView.h +++ b/ApplicationCode/ProjectDataModel/RimGridView.h @@ -30,6 +30,7 @@ class RimIntersectionResultsDefinitionCollection; class RimPropertyFilterCollection; class RimGridCollection; class RimCellRangeFilterCollection; +class RimWellMeasurementInViewCollection; class RimGridView : public Rim3dView { @@ -48,6 +49,7 @@ public: RimIntersectionCollection* intersectionCollection() const; RimIntersectionResultsDefinitionCollection* separateIntersectionResultsCollection() const; RimAnnotationInViewCollection* annotationCollection() const; + RimWellMeasurementInViewCollection* measurementCollection() const; virtual const RimPropertyFilterCollection* propertyFilterCollection() const = 0; void rangeFiltersUpdated(); @@ -87,11 +89,12 @@ protected: // Fields caf::PdmChildField m_intersectionResultDefCollection; - caf::PdmChildField m_overlayInfoConfig; - caf::PdmChildField m_rangeFilterCollection; - caf::PdmChildField m_overrideRangeFilterCollection; - caf::PdmChildField m_gridCollection; - caf::PdmChildField m_annotationCollection; + caf::PdmChildField m_overlayInfoConfig; + caf::PdmChildField m_rangeFilterCollection; + caf::PdmChildField m_overrideRangeFilterCollection; + caf::PdmChildField m_gridCollection; + caf::PdmChildField m_annotationCollection; + caf::PdmChildField m_wellMeasurementCollection; private: cvf::ref m_currentReservoirCellVisibility; diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.cpp index 608b3c7700..09316f06d4 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.cpp @@ -38,13 +38,7 @@ RimWellMeasurementCollection::RimWellMeasurementCollection() CAF_PDM_InitFieldNoDefault( &m_measurements, "Measurements", "Well Measurements", "", "", "" ); m_measurements.uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() ); m_measurements.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); - m_measurements.uiCapability()->setCustomContextMenuEnabled( true ); - - CAF_PDM_InitFieldNoDefault( &m_measurementKinds, "MeasurementKinds", "Measurent Kinds", "", "", "" ); - m_measurementKinds.uiCapability()->setAutoAddingOptionFromValue( false ); - m_measurementKinds.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); - m_measurementKinds.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN ); - m_measurementKinds.xmlCapability()->disableIO(); + m_measurements.uiCapability()->setUiTreeHidden( true ); this->setName( "Well Measurements" ); } @@ -126,22 +120,6 @@ void RimWellMeasurementCollection::deleteAllMeasurements() this->updateAllReferringTracks(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellMeasurementCollection::defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, - QMenu* menu, - QWidget* fieldEditorWidget ) -{ - caf::CmdFeatureMenuBuilder menuBuilder; - - // menuBuilder << "RicNewWellMeasurementFeature"; - // menuBuilder << "Separator"; - // menuBuilder << "RicDeleteWellMeasurementFeature"; - - menuBuilder.appendToMenu( menu ); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -185,7 +163,7 @@ void RimWellMeasurementCollection::fieldChangedByUi( const caf::PdmFieldHandle* const QVariant& oldValue, const QVariant& newValue ) { - if ( changedField == &m_isChecked || changedField == &m_measurementKinds ) + if ( changedField == &m_isChecked ) { RimProject* proj; this->firstAncestorOrThisOfTypeAsserted( proj ); @@ -193,33 +171,3 @@ void RimWellMeasurementCollection::fieldChangedByUi( const caf::PdmFieldHandle* this->updateAllReferringTracks(); } } - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QList - RimWellMeasurementCollection::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, - bool* useOptionsOnly ) -{ - QList options; - if ( fieldNeedingOptions == &m_measurementKinds ) - { - std::set measurementKindsInData; - for ( auto measurement : measurements() ) - { - measurementKindsInData.insert( measurement->kind() ); - } - - for ( auto measurementKind : measurementKindsInData ) - { - options.push_back( caf::PdmOptionItemInfo( measurementKind, measurementKind ) ); - } - } - - return options; -} - -std::vector RimWellMeasurementCollection::measurementKinds() const -{ - return m_measurementKinds; -} diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h index f97d3b9c4f..e83172e48f 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h @@ -35,7 +35,6 @@ public: ~RimWellMeasurementCollection() override; std::vector measurements() const; - std::vector measurementKinds() const; void updateAllReferringTracks(); void insertMeasurement( RimWellMeasurement* insertBefore, RimWellMeasurement* measurement ); @@ -44,9 +43,6 @@ public: void deleteAllMeasurements(); protected: - void defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, - QMenu* menu, - QWidget* fieldEditorWidget ) override; void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; @@ -55,10 +51,7 @@ protected: void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; - QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, - bool* useOptionsOnly ); private: caf::PdmChildArrayField m_measurements; - caf::PdmField> m_measurementKinds; }; diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp index b2095a1b99..134f2ff70c 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp @@ -87,7 +87,8 @@ void RimWellMeasurementCurve::onLoadDataAndUpdate( bool updateParentPlot ) { const RimWellMeasurementCollection* measurementCollection = wellPathCollection->measurementCollection(); - std::vector measurementKinds = measurementCollection->measurementKinds(); + std::vector measurementKinds; + measurementKinds.push_back( measurementKind() ); std::vector measurements = RimWellMeasurementFilter::filterMeasurements( measurementCollection->measurements(), diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp index 440718d17b..ab75f3ad56 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.cpp @@ -47,3 +47,20 @@ std::vector return filteredMeasurements; } + +std::vector + RimWellMeasurementFilter::filterMeasurements( const std::vector& measurements, + const std::vector& measurementKinds ) +{ + std::vector filteredMeasurements; + + for ( auto& measurement : measurements ) + { + if ( std::find( measurementKinds.begin(), measurementKinds.end(), measurement->kind() ) != measurementKinds.end() ) + { + filteredMeasurements.push_back( measurement ); + } + } + + return filteredMeasurements; +} diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h index f409f42860..1ccdf3f57f 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementFilter.h @@ -32,6 +32,8 @@ public: const RimWellPathCollection& wellPathCollection, const RimWellPath& rimWellPath, const std::vector& measurementKinds ); + static std::vector filterMeasurements( const std::vector& measurements, + const std::vector& measurementKinds ); private: RimWellMeasurementFilter(); diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementInViewCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementInViewCollection.cpp new file mode 100644 index 0000000000..ed27b6352f --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementInViewCollection.cpp @@ -0,0 +1,197 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RimWellMeasurementInViewCollection.h" + +#include "Rim3dView.h" +#include "RimProject.h" +#include "RimRegularLegendConfig.h" +#include "RimTools.h" +#include "RimWellLogTrack.h" +#include "RimWellMeasurement.h" +#include "RimWellMeasurementCollection.h" +#include "RimWellMeasurementFilter.h" +#include "RimWellPathCollection.h" + +#include "RiuViewer.h" + +#include "cafCmdFeatureMenuBuilder.h" +#include "cafPdmUiTableViewEditor.h" +#include "cafPdmUiTreeOrdering.h" +#include "cafPdmUiTreeSelectionEditor.h" + +#include + +CAF_PDM_SOURCE_INIT( RimWellMeasurementInViewCollection, "WellMeasurementsInView" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellMeasurementInViewCollection::RimWellMeasurementInViewCollection() +{ + CAF_PDM_InitObject( "Well Measurement", "", "", "" ); + + CAF_PDM_InitFieldNoDefault( &m_legendConfig, "LegendDefinition", "Color Legend", "", "", "" ); + m_legendConfig = new RimRegularLegendConfig(); + m_legendConfig.uiCapability()->setUiHidden( true ); + + CAF_PDM_InitFieldNoDefault( &m_measurementKinds, "MeasurementKinds", "Measurent Kinds", "", "", "" ); + m_measurementKinds.uiCapability()->setAutoAddingOptionFromValue( false ); + m_measurementKinds.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); + m_measurementKinds.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN ); + m_measurementKinds.xmlCapability()->disableIO(); + + this->setName( "Well Measurements" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellMeasurementInViewCollection::~RimWellMeasurementInViewCollection() +{ + delete m_legendConfig; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementInViewCollection::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, + QString uiConfigName /*= ""*/ ) +{ + uiTreeOrdering.add( &m_legendConfig ); + uiTreeOrdering.skipRemainingChildren( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementInViewCollection::fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) +{ + if ( changedField == &m_isChecked || changedField == &m_measurementKinds || changedField == &m_legendConfig ) + { + updateLegendData(); + RimProject* proj; + this->firstAncestorOrThisOfTypeAsserted( proj ); + proj->scheduleCreateDisplayModelAndRedrawAllViews(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimRegularLegendConfig* RimWellMeasurementInViewCollection::legendConfig() +{ + return m_legendConfig; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellMeasurementInViewCollection::updateLegendData() +{ + RimWellPathCollection* wellPathCollection = RimTools::wellPathCollection(); + if ( !wellPathCollection ) return false; + + RimWellMeasurementCollection* wellMeasurementCollection = wellPathCollection->measurementCollection(); + if ( !wellMeasurementCollection ) return false; + + std::vector selectedMeasurementKinds = measurementKinds(); + + // Only show legend when only one measurement is selected + if ( selectedMeasurementKinds.size() == 1 ) + { + std::vector wellMeasurements = + RimWellMeasurementFilter::filterMeasurements( wellMeasurementCollection->measurements(), + selectedMeasurementKinds ); + + double minValue = HUGE_VAL; + double maxValue = -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 ); + } + + if ( minValue != HUGE_VAL ) + { + m_legendConfig->setTitle( QString( "Well Measurement: \n" ) + selectedMeasurementKinds[0] ); + m_legendConfig->setAutomaticRanges( minValue, maxValue, minValue, maxValue ); + m_legendConfig->setClosestToZeroValues( posClosestToZero, negClosestToZero, posClosestToZero, negClosestToZero ); + return true; + } + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellMeasurementInViewCollection::updateLegendRangesTextAndVisibility( RiuViewer* nativeOrOverrideViewer, + bool isUsingOverrideViewer ) +{ + bool addToViewer = updateLegendData(); + if ( addToViewer ) + { + nativeOrOverrideViewer->addColorLegendToBottomLeftCorner( m_legendConfig->titledOverlayFrame(), + isUsingOverrideViewer ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList + RimWellMeasurementInViewCollection::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly ) +{ + QList options; + if ( fieldNeedingOptions == &m_measurementKinds ) + { + RimWellPathCollection* wellPathCollection = RimTools::wellPathCollection(); + if ( wellPathCollection ) + { + std::vector measurements = wellPathCollection->measurementCollection()->measurements(); + + std::set measurementKindsInData; + for ( auto measurement : measurements ) + { + measurementKindsInData.insert( measurement->kind() ); + } + + for ( auto measurementKind : measurementKindsInData ) + { + options.push_back( caf::PdmOptionItemInfo( measurementKind, measurementKind ) ); + } + } + } + + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimWellMeasurementInViewCollection::measurementKinds() const +{ + return m_measurementKinds; +} diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementInViewCollection.h b/ApplicationCode/ProjectDataModel/RimWellMeasurementInViewCollection.h new file mode 100644 index 0000000000..6468d5f6f0 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementInViewCollection.h @@ -0,0 +1,60 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 + +#include "RimCheckableNamedObject.h" + +#include "cafPdmChildArrayField.h" +#include "cafPdmChildField.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmProxyValueField.h" + +#include + +class RimWellMeasurement; +class RimRegularLegendConfig; +class RiuViewer; + +class RimWellMeasurementInViewCollection : public RimCheckableNamedObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimWellMeasurementInViewCollection(); + ~RimWellMeasurementInViewCollection() override; + + RimRegularLegendConfig* legendConfig(); + std::vector measurementKinds() const; + + void updateLegendRangesTextAndVisibility( RiuViewer* nativeOrOverrideViewer, bool isUsingOverrideViewer ); + +protected: + void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) override; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly ); + + bool updateLegendData(); + +private: + caf::PdmChildField m_legendConfig; + caf::PdmField> m_measurementKinds; +}; From 4aac43c1676137a3d07321b57285f722f3eceabb Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 27 Nov 2019 13:54:58 +0100 Subject: [PATCH 12/12] Fix headers and whitespace --- ApplicationCode/FileInterface/RifWellMeasurementReader.h | 2 +- ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp | 1 + ApplicationCode/ProjectDataModel/RimWellMeasurement.h | 6 +++++- .../ProjectDataModel/RimWellMeasurementCollection.h | 3 +++ .../ProjectDataModel/RimWellMeasurementCurve.cpp | 6 +++--- ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.h | 4 +--- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/FileInterface/RifWellMeasurementReader.h b/ApplicationCode/FileInterface/RifWellMeasurementReader.h index 4743d6b208..f93241524d 100644 --- a/ApplicationCode/FileInterface/RifWellMeasurementReader.h +++ b/ApplicationCode/FileInterface/RifWellMeasurementReader.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017- Statoil ASA +// Copyright (C) 2019- 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 diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp index 36b5cee2db..c5fc290898 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurement.cpp @@ -15,6 +15,7 @@ // for more details. // ///////////////////////////////////////////////////////////////////////////////// + #include "RimWellMeasurement.h" #include "RimProject.h" diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurement.h b/ApplicationCode/ProjectDataModel/RimWellMeasurement.h index be264d0003..c9f15ebc84 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurement.h +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurement.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2018- Equinor ASA +// Copyright (C) 2019- 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 @@ -15,6 +15,7 @@ // for more details. // ///////////////////////////////////////////////////////////////////////////////// + #pragma once #include "cafPdmObject.h" @@ -26,6 +27,9 @@ class RimWellPath; +//================================================================================================== +/// +//================================================================================================== class RimWellMeasurement : public caf::PdmObject { CAF_PDM_HEADER_INIT; diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h index e83172e48f..2ea86124b6 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCollection.h @@ -26,6 +26,9 @@ class RimWellMeasurement; +//================================================================================================== +/// +//================================================================================================== class RimWellMeasurementCollection : public RimCheckableNamedObject { CAF_PDM_HEADER_INIT; diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp index 134f2ff70c..b01edc4b77 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.cpp @@ -1,7 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS +// Copyright (C) 2019- 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 @@ -233,7 +232,8 @@ void RimWellMeasurementCurve::defineUiOrdering( QString uiConfigName, caf::PdmUi //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellMeasurementCurve::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/ ) +void RimWellMeasurementCurve::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, + QString uiConfigName /*= ""*/ ) { uiTreeOrdering.skipRemainingChildren( true ); } diff --git a/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.h b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.h index 02f9a8c173..d80122f4c0 100644 --- a/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.h +++ b/ApplicationCode/ProjectDataModel/RimWellMeasurementCurve.h @@ -1,7 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS +// Copyright (C) 2019- 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 @@ -33,7 +32,6 @@ class RimWellMeasurement; //================================================================================================== /// -/// //================================================================================================== class RimWellMeasurementCurve : public RimWellLogCurve {