diff --git a/ApplicationLibCode/Application/RiaPreferencesSummary.cpp b/ApplicationLibCode/Application/RiaPreferencesSummary.cpp index fffa156995..bd65bed688 100644 --- a/ApplicationLibCode/Application/RiaPreferencesSummary.cpp +++ b/ApplicationLibCode/Application/RiaPreferencesSummary.cpp @@ -111,6 +111,15 @@ RiaPreferencesSummary::RiaPreferencesSummary() "" ); CAF_PDM_InitFieldNoDefault( &m_defaultSummaryPlot, "defaultSummaryPlot", "Create Plot On Summary Data Import" ); + CAF_PDM_InitField( &m_crossPlotAddressCombinations, + "CrossPlotAddressCombinations", + QString( "FWIR FOPT;FGOR FOPT;FWCT FOPT;FGLIR FOPR" ), + "Cross Plot Addresses [Y-adr X-adr]", + "", + "Semicolon separated list used to create cross plot curves. Based on selection, the names will be changed to " + "corresponing well or group vector names", + "" ); + CAF_PDM_InitField( &m_selectDefaultTemplates, "selectDefaultTemplate", false, "", "", "Select Default Templates" ); m_selectDefaultTemplates.xmlCapability()->disableIO(); m_selectDefaultTemplates.uiCapability()->setUiEditorTypeName( caf::PdmUiPushButtonEditor::uiEditorTypeName() ); @@ -282,6 +291,8 @@ void RiaPreferencesSummary::appendItemsToPlottingGroup( caf::PdmUiOrdering& uiOr break; } + uiOrdering.add( &m_crossPlotAddressCombinations ); + auto historyCurveGroup = uiOrdering.addNewGroup( "History Vectors" ); historyCurveGroup->add( &m_defaultSummaryHistoryCurveStyle ); @@ -369,6 +380,14 @@ bool RiaPreferencesSummary::appendHistoryVectors() const return m_appendHistoryVectors(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaPreferencesSummary::crossPlotAddressCombinations() const +{ + return m_crossPlotAddressCombinations; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/Application/RiaPreferencesSummary.h b/ApplicationLibCode/Application/RiaPreferencesSummary.h index 8076863418..7effa71a5f 100644 --- a/ApplicationLibCode/Application/RiaPreferencesSummary.h +++ b/ApplicationLibCode/Application/RiaPreferencesSummary.h @@ -107,6 +107,8 @@ public: bool colorCurvesByPhase() const; bool appendHistoryVectors() const; + QString crossPlotAddressCombinations() const; + SummaryHistoryCurveStyleMode defaultSummaryHistoryCurveStyle() const; RiaDefines::ColumnCount defaultMultiPlotColumnCount() const; @@ -132,6 +134,7 @@ private: caf::PdmField m_summaryEnsembleImportMode; caf::PdmField m_defaultSummaryCurvesTextFilter; + caf::PdmField m_crossPlotAddressCombinations; caf::PdmField m_defaultSummaryHistoryCurveStyle; caf::PdmField m_curveColorByPhase; caf::PdmField m_appendHistoryVectors; diff --git a/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.cpp b/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.cpp index 9881a6ffa5..d527fa154d 100644 --- a/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.cpp +++ b/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.cpp @@ -22,6 +22,7 @@ #include "SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.h" #include "SummaryPlotCommands/RicSummaryPlotFeatureImpl.h" +#include "RiaPreferencesSummary.h" #include "RiaSummaryAddressAnalyzer.h" #include "RiaSummaryTools.h" @@ -29,7 +30,6 @@ #include "RifReaderEclipseSummary.h" #include "RifSummaryReaderInterface.h" -#include "RiaPreferencesSummary.h" #include "RimEnsembleCurveSet.h" #include "RimEnsembleCurveSetCollection.h" #include "RimMainPlotCollection.h" @@ -40,6 +40,7 @@ #include "RimSummaryCase.h" #include "RimSummaryCaseCollection.h" #include "RimSummaryCurve.h" +#include "RimSummaryCurveAppearanceCalculator.h" #include "RimSummaryMultiPlot.h" #include "RimSummaryMultiPlotCollection.h" #include "RimSummaryPlot.h" @@ -619,6 +620,41 @@ RimSummaryPlot* RicSummaryPlotBuilder::createPlot( const std::set& addresses, + const std::vector& summaryCases, + const std::vector& ensembles ) +{ + auto* summaryPlot = new RimSummaryPlot(); + summaryPlot->enableAutoPlotTitle( true ); + + for ( const auto& addr : addresses ) + { + for ( const auto ensemble : ensembles ) + { + if ( !ensemble ) continue; + + auto curveSet = addNewEnsembleCurve( summaryPlot, addr, ensemble ); + curveSet->findOrAssignBottomAxisX( RiuPlotAxis::defaultBottomForSummaryVectors() ); + } + + for ( const auto summaryCase : summaryCases ) + { + if ( !summaryCase ) continue; + + addNewSummaryCurve( summaryPlot, addr, summaryCase ); + } + } + + summaryPlot->applyDefaultCurveAppearances(); + summaryPlot->loadDataAndUpdate(); + summaryPlot->zoomAll(); + + return summaryPlot; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -633,6 +669,7 @@ void RicSummaryPlotBuilder::appendCurvesToPlot( RimSummaryPlot* { auto curveSet = createCurveSet( ensemble, addr ); summaryPlot->ensembleCurveSetCollection()->addCurveSet( curveSet ); + curveSet->setLeftOrRightAxisY( RiuPlotAxis::defaultLeft() ); } for ( const auto summaryCase : summaryCases ) @@ -642,3 +679,64 @@ void RicSummaryPlotBuilder::appendCurvesToPlot( RimSummaryPlot* } } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEnsembleCurveSet* RicSummaryPlotBuilder::addNewEnsembleCurve( RimSummaryPlot* summaryPlot, + const RiaSummaryCurveAddress& curveAddress, + RimSummaryCaseCollection* ensemble ) +{ + auto* curveSet = new RimEnsembleCurveSet(); + + curveSet->setSummaryCaseCollection( ensemble ); + curveSet->setCurveAddress( curveAddress ); + + cvf::Color3f curveColor = + RimSummaryCurveAppearanceCalculator::computeTintedCurveColorForAddress( curveSet->summaryAddressY(), + static_cast( + summaryPlot->ensembleCurveSetCollection()->curveSetCount() ) ); + + auto adr = curveSet->summaryAddressY(); + if ( adr.isHistoryVector() ) curveColor = RiaPreferencesSummary::current()->historyCurveContrastColor(); + + curveSet->setColor( curveColor ); + + summaryPlot->ensembleCurveSetCollection()->addCurveSet( curveSet ); + + curveSet->setLeftOrRightAxisY( RiuPlotAxis::defaultLeft() ); + curveSet->setBottomOrTopAxisX( RiuPlotAxis::defaultBottomForSummaryVectors() ); + + summaryPlot->curvesChanged.send(); + + return curveSet; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimSummaryCurve* RicSummaryPlotBuilder::addNewSummaryCurve( RimSummaryPlot* summaryPlot, + const RiaSummaryCurveAddress& curveAddress, + RimSummaryCase* summaryCase ) +{ + auto curve = new RimSummaryCurve(); + + curve->setSummaryCaseY( summaryCase ); + curve->setSummaryAddressY( curveAddress.summaryAddressY() ); + + curve->setSummaryCaseX( summaryCase ); + curve->setSummaryAddressX( curveAddress.summaryAddressX() ); + if ( curveAddress.summaryAddressX().category() != SummaryCategory::SUMMARY_TIME ) + { + curve->setAxisTypeX( RiaDefines::HorizontalAxisType::SUMMARY_VECTOR ); + } + + summaryPlot->addCurveNoUpdate( curve ); + + if ( curveAddress.summaryAddressX().category() != SummaryCategory::SUMMARY_TIME ) + { + summaryPlot->findOrAssignPlotAxisX( curve ); + } + + return curve; +} diff --git a/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.h b/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.h index ac6be6a69f..bc57c3ba29 100644 --- a/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.h +++ b/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.h @@ -27,6 +27,7 @@ class RimSummaryPlot; class RimEnsembleCurveSet; class RimSummaryCurve; class RimSummaryMultiPlot; +class RiaSummaryCurveAddress; namespace caf { @@ -90,11 +91,21 @@ public: const std::vector& summaryCases, const std::vector& ensembles ); + static RimSummaryPlot* createCrossPlot( const std::vector& addresses, + const std::vector& summaryCases, + const std::vector& ensembles ); + static void appendCurvesToPlot( RimSummaryPlot* summaryPlot, const std::set& addresses, const std::vector& summaryCases, const std::vector& ensembles ); + static RimEnsembleCurveSet* + addNewEnsembleCurve( RimSummaryPlot* summaryPlot, const RiaSummaryCurveAddress& curveAddress, RimSummaryCaseCollection* ensemble ); + + static RimSummaryCurve* + addNewSummaryCurve( RimSummaryPlot* summaryPlot, const RiaSummaryCurveAddress& curveAddress, RimSummaryCase* summaryCase ); + private: std::set m_addresses; std::vector m_summaryCases; diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/SummaryPlotCommands/CMakeLists_files.cmake index 8accb9f93b..e5cd1750b7 100644 --- a/ApplicationLibCode/Commands/SummaryPlotCommands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/CMakeLists_files.cmake @@ -47,6 +47,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicDuplicateSummaryTableFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicCreateDeclineCurvesFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicCreateRegressionAnalysisCurveFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicCreateCrossPlotFeature.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -98,6 +99,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicDuplicateSummaryTableFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicCreateDeclineCurvesFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicCreateRegressionAnalysisCurveFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicCreateCrossPlotFeature.cpp ) list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/RicCreateCrossPlotFeature.cpp b/ApplicationLibCode/Commands/SummaryPlotCommands/RicCreateCrossPlotFeature.cpp new file mode 100644 index 0000000000..02b59481cb --- /dev/null +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/RicCreateCrossPlotFeature.cpp @@ -0,0 +1,209 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023- 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 "RicCreateCrossPlotFeature.h" + +#include "PlotBuilderCommands/RicSummaryPlotBuilder.h" + +#include "RiaPreferencesSummary.h" +#include "RiaSummaryCurveAddress.h" + +#include "RifEclipseSummaryAddress.h" + +#include "RimSummaryAddress.h" +#include "RimSummaryAddressCollection.h" +#include "RimSummaryCase.h" +#include "RimSummaryCaseCollection.h" + +#include "cafSelectionManagerTools.h" + +#include +#include + +CAF_CMD_SOURCE_INIT( RicCreateCrossPlotFeature, "RicCreateCrossPlotFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicCreateCrossPlotFeature::isCommandEnabled() const +{ + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicCreateCrossPlotFeature::onActionTriggered( bool isChecked ) +{ + // Nothing to do here, the sub menus are handled by the onSubMenuActionTriggered +} + +auto newCrossPlotText = []() -> QString { return "New Cross Plot"; }; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicCreateCrossPlotFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Summary Cross Plot" ); + actionToSetup->setIcon( QIcon( ":/SummaryXPlotLight16x16.png" ) ); + + auto subMenu = new QMenu( "Create Cross Plot" ); + + auto menuTexts = crossPlotAddressesBasedOnSelection(); + menuTexts.append( newCrossPlotText() ); + + for ( const auto& crossPlotAddresses : menuTexts ) + { + auto action = subMenu->addAction( crossPlotAddresses ); + action->setIcon( QIcon( ":/SummaryXPlotLight16x16.png" ) ); + + connect( action, &QAction::triggered, this, &RicCreateCrossPlotFeature::onSubMenuActionTriggered ); + } + + actionToSetup->setMenu( subMenu ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicCreateCrossPlotFeature::onSubMenuActionTriggered( bool isChecked ) +{ + QString addressX; + QString addressY; + + if ( auto* action = qobject_cast( sender() ) ) + { + auto text = action->text(); + if ( text != newCrossPlotText() ) + { + auto words = action->text().split( " " ); + + if ( !words.empty() ) addressY = words[0]; + if ( words.size() > 1 ) addressX = words[1]; + } + } + + RifEclipseSummaryAddress adrX = RifEclipseSummaryAddress::fromEclipseTextAddress( addressX.toStdString() ); + RifEclipseSummaryAddress adrY = RifEclipseSummaryAddress::fromEclipseTextAddress( addressY.toStdString() ); + + RiaSummaryCurveAddress curveAddress( adrX, adrY ); + + auto selectedCases = caf::firstAncestorOfTypeFromSelectedObject(); + auto selectedEnsembles = caf::firstAncestorOfTypeFromSelectedObject(); + + auto newPlot = RicSummaryPlotBuilder::createCrossPlot( { curveAddress }, { selectedCases }, { selectedEnsembles } ); + + RicSummaryPlotBuilder::createAndAppendSingleSummaryMultiPlot( newPlot ); +} + +//-------------------------------------------------------------------------------------------------- +// Returns a list of cross plot address combinations based on the current selection +// The vectors defined in preferences is given in field vectors +// If the selection is a field address, use the list from preferences +// If the selection is a well address, F is replaced with W and well name is appended +// If the selection is a group address, F is replaced with G and group name is appended +//-------------------------------------------------------------------------------------------------- +QStringList RicCreateCrossPlotFeature::crossPlotAddressesBasedOnSelection() +{ + auto text = RiaPreferencesSummary::current()->crossPlotAddressCombinations(); + + auto collectionContentType = RimSummaryAddressCollection::CollectionContentType::NOT_DEFINED; + + std::string wellName; + std::string groupName; + + if ( auto addr = dynamic_cast( caf::SelectionManager::instance()->selectedItem() ) ) + { + wellName = addr->address().wellName(); + groupName = addr->address().groupName(); + } + + if ( auto addrCollection = dynamic_cast( caf::SelectionManager::instance()->selectedItem() ) ) + { + collectionContentType = addrCollection->contentType(); + + if ( ( collectionContentType == RimSummaryAddressCollection::CollectionContentType::WELL ) && wellName.empty() ) + { + auto addresses = addrCollection->descendantsOfType(); + if ( !addresses.empty() ) + { + wellName = addresses.front()->address().wellName(); + } + } + + if ( ( collectionContentType == RimSummaryAddressCollection::CollectionContentType::GROUP ) && groupName.empty() ) + { + auto addresses = addrCollection->descendantsOfType(); + if ( !addresses.empty() ) + { + groupName = addresses.front()->address().groupName(); + } + } + } + + bool isWell = ( ( collectionContentType == RimSummaryAddressCollection::CollectionContentType::WELL ) || !wellName.empty() ); + bool isGroup = ( ( collectionContentType == RimSummaryAddressCollection::CollectionContentType::GROUP ) || !groupName.empty() ); + + QStringList crossPlotAddressCombinations; + + auto textList = text.split( ";" ); + for ( const auto& inputText : textList ) + { + auto modifiedString = inputText.toStdString(); + + if ( isWell ) + { + std::string wellAddress; + + auto words = inputText.split( " " ); + for ( const auto& w : words ) + { + auto tmp = w.toStdString().substr( 1 ); + + tmp = "W" + tmp + ":" + wellName; + + if ( !wellAddress.empty() ) wellAddress += " "; + wellAddress += tmp; + } + + modifiedString = wellAddress; + } + else if ( isGroup ) + { + std::string groupAddress; + + auto words = inputText.split( " " ); + for ( const auto& w : words ) + { + auto tmp = w.toStdString().substr( 1 ); + + tmp = "G" + tmp + ":" + groupName; + + if ( !groupAddress.empty() ) groupAddress += " "; + groupAddress += tmp; + } + + modifiedString = groupAddress; + } + + crossPlotAddressCombinations.append( QString::fromStdString( modifiedString ) ); + } + + return crossPlotAddressCombinations; +} diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/RicCreateCrossPlotFeature.h b/ApplicationLibCode/Commands/SummaryPlotCommands/RicCreateCrossPlotFeature.h new file mode 100644 index 0000000000..801e22163b --- /dev/null +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/RicCreateCrossPlotFeature.h @@ -0,0 +1,38 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023- 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 RicCreateCrossPlotFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + bool isCommandEnabled() const override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; + +private: + void onSubMenuActionTriggered( bool isChecked ); + static QStringList crossPlotAddressesBasedOnSelection(); +}; diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/RicNewSummaryCrossPlotCurveFeature.cpp b/ApplicationLibCode/Commands/SummaryPlotCommands/RicNewSummaryCrossPlotCurveFeature.cpp index dd16106175..d65be85ead 100644 --- a/ApplicationLibCode/Commands/SummaryPlotCommands/RicNewSummaryCrossPlotCurveFeature.cpp +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/RicNewSummaryCrossPlotCurveFeature.cpp @@ -32,6 +32,7 @@ #include "RiuPlotMainWindow.h" #include "RiuPlotMainWindowTools.h" +#include "PlotBuilderCommands/RicSummaryPlotBuilder.h" #include "WellLogCommands/RicWellLogPlotCurveFeatureImpl.h" #include "cafSelectionManager.h" @@ -58,26 +59,21 @@ void RicNewSummaryCrossPlotCurveFeature::onActionTriggered( bool isChecked ) auto plot = selectedSummaryPlot(); if ( plot ) { - RimSummaryCurve* newCurve = new RimSummaryCurve(); - cvf::Color3f curveColor = RicWellLogPlotCurveFeatureImpl::curveColorFromTable( plot->curveCount() ); - newCurve->setColor( curveColor ); + cvf::Color3f curveColor = RicWellLogPlotCurveFeatureImpl::curveColorFromTable( plot->curveCount() ); RimSummaryCase* defaultCase = nullptr; if ( project->activeOilField()->summaryCaseMainCollection()->summaryCaseCount() > 0 ) { defaultCase = project->activeOilField()->summaryCaseMainCollection()->summaryCase( 0 ); - newCurve->setSummaryCaseY( defaultCase ); - newCurve->setSummaryAddressY( RifEclipseSummaryAddress::fieldAddress( "FOPT" ) ); - - newCurve->setAxisTypeX( RiaDefines::HorizontalAxisType::SUMMARY_VECTOR ); - newCurve->setSummaryCaseX( defaultCase ); - newCurve->setSummaryAddressX( RifEclipseSummaryAddress::fieldAddress( "FGOR" ) ); } - plot->addCurveAndUpdate( newCurve ); + RiaSummaryCurveAddress addr( RifEclipseSummaryAddress::fieldAddress( "FOPT" ), RifEclipseSummaryAddress::fieldAddress( "FGOR" ) ); + auto newCurve = RicSummaryPlotBuilder::addNewSummaryCurve( plot, addr, defaultCase ); + newCurve->setColor( curveColor ); newCurve->loadDataAndUpdate( true ); + plot->zoomAll(); plot->updateConnectedEditors(); RiuPlotMainWindowTools::onObjectAppended( newCurve ); @@ -90,7 +86,7 @@ void RicNewSummaryCrossPlotCurveFeature::onActionTriggered( bool isChecked ) void RicNewSummaryCrossPlotCurveFeature::setupActionLook( QAction* actionToSetup ) { actionToSetup->setText( "New Summary Cross Plot Curve" ); - actionToSetup->setIcon( QIcon( ":/SummaryCurve16x16.png" ) ); + actionToSetup->setIcon( QIcon( ":/SummaryXPlotLight16x16.png" ) ); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp index 662d752f9e..18e1b3bf52 100644 --- a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -699,10 +699,10 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "RicDuplicateSummaryPlotFeature"; menuBuilder << "RicSplitMultiPlotFeature"; menuBuilder << "RicNewSummaryEnsembleCurveSetFeature"; - menuBuilder << "RicNewSummaryCrossPlotCurveFeature"; menuBuilder << "Separator"; menuBuilder << "RicNewPlotAxisPropertiesFeature"; menuBuilder << "RicNewSummaryCurveFeature"; + menuBuilder << "RicNewSummaryCrossPlotCurveFeature"; menuBuilder << "Separator"; menuBuilder << "RicAsciiExportSummaryPlotFeature"; menuBuilder << "RicShowSummaryCurveCalculatorFeature"; @@ -1101,6 +1101,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() { menuBuilder << "RicCreateMultiPlotFromSelectionFeature"; menuBuilder << "RicCreatePlotFromTemplateByShortcutFeature"; + menuBuilder << "RicCreateCrossPlotFeature"; } else if ( dynamic_cast( firstUiItem ) ) { @@ -1288,6 +1289,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "RicAppendSummaryPlotsForSummaryAddressesFeature"; menuBuilder << "Separator"; menuBuilder << "RicNewSummaryTableFeature"; + menuBuilder << "RicCreateCrossPlotFeature"; } #ifdef USE_ODB_API else if ( dynamic_cast( firstUiItem ) ) diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp index db67fced3d..6a9748661c 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp @@ -156,6 +156,7 @@ RimEnsembleCurveSet::RimEnsembleCurveSet() CAF_PDM_InitFieldNoDefault( &m_xAddressSelector, "XAddressSelector", "" ); m_xAddressSelector = new RimSummaryAddressSelector; m_xAddressSelector->setAxisOrientation( RimPlotAxisProperties::Orientation::HORIZONTAL ); + m_xAddressSelector->setShowResampling( false ); m_xAddressSelector.uiCapability()->setUiTreeHidden( true ); m_xAddressSelector.uiCapability()->setUiTreeChildrenHidden( true ); @@ -481,6 +482,27 @@ RiaDefines::HorizontalAxisType RimEnsembleCurveSet::xAxisType() const return m_xAxisType(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleCurveSet::findOrAssignBottomAxisX( RiuPlotAxis plotAxis ) +{ + auto plot = firstAncestorOrThisOfType(); + if ( !plot ) return; + + if ( auto axis = plot->axisPropertiesForPlotAxis( plotAxis ) ) + { + m_xAddressSelector->setPlotAxisProperties( axis ); + } + else + { + RimPlotAxisProperties* newPlotAxisProperties = plot->addNewAxisProperties( plotAxis, "Bottom Axis" ); + plot->updateConnectedEditors(); + + m_xAddressSelector->setPlotAxisProperties( newPlotAxisProperties ); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -771,25 +793,14 @@ void RimEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedFi if ( !m_xAddressSelector->ensemble() ) { m_xAddressSelector->setEnsemble( summaryCaseCollection() ); + } + + if ( !m_xAddressSelector->summaryAddress().isValid() ) + { m_xAddressSelector->setAddress( summaryAddressY() ); } - if ( !m_xAddressSelector->plotAxisProperties() ) - { - RiuPlotAxis plotAxis = RiuPlotAxis::defaultBottomForSummaryVectors(); - if ( auto axis = plot->axisPropertiesForPlotAxis( plotAxis ) ) - { - m_xAddressSelector->setPlotAxisProperties( axis ); - } - else - { - RimPlotAxisProperties* newPlotAxisProperties = - plot->addNewAxisProperties( RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM, "Bottom Axis" ); - plot->updateConnectedEditors(); - - m_xAddressSelector->setPlotAxisProperties( newPlotAxisProperties ); - } - } + findOrAssignBottomAxisX( RiuPlotAxis::defaultBottomForSummaryVectors() ); } plot->updateAxes(); plot->updatePlotTitle(); @@ -1053,6 +1064,9 @@ void RimEnsembleCurveSet::childFieldChangedByUi( const caf::PdmFieldHandle* chan { multiPlot->updatePlotTitles(); } + + // Trigger update, as the axis object name might have changed. Will update the axis object of the curve set. + updateConnectedEditors(); } } @@ -1068,7 +1082,13 @@ void RimEnsembleCurveSet::defineUiOrdering( QString uiConfigName, caf::PdmUiOrde curveDataGroup->add( &m_yValuesSummaryCaseCollection ); curveDataGroup->add( &m_yValuesSummaryAddressUiField ); curveDataGroup->add( &m_yPushButtonSelectSummaryAddress, { false, 1, 0 } ); - curveDataGroup->add( &m_resampling ); + + if ( !isXAxisSummaryVector() ) + { + // Resampling is automatic for cross plot curves + curveDataGroup->add( &m_resampling ); + } + curveDataGroup->add( &m_yPlotAxisProperties ); } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h index 7843672dd1..07ac38f20e 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h @@ -195,6 +195,7 @@ public: void setBottomOrTopAxisX( RiuPlotAxis plotAxis ); bool isXAxisSummaryVector() const; RiaDefines::HorizontalAxisType xAxisType() const; + void findOrAssignBottomAxisX( RiuPlotAxis plotAxis ); protected: void initAfterRead() override; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressSelector.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressSelector.cpp index c6af1b2ede..9d184eeb4c 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressSelector.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressSelector.cpp @@ -43,6 +43,9 @@ CAF_PDM_SOURCE_INIT( RimSummaryAddressSelector, "RimSummaryAddressSelector" ); //-------------------------------------------------------------------------------------------------- RimSummaryAddressSelector::RimSummaryAddressSelector() : addressChanged( this ) + , m_showDataSource( true ) + , m_showResampling( true ) + , m_plotAxisOrientation( RimPlotAxisProperties::Orientation::ANY ) { CAF_PDM_InitFieldNoDefault( &m_summaryCase, "SummaryCase", "Case" ); @@ -71,9 +74,6 @@ RimSummaryAddressSelector::RimSummaryAddressSelector() m_summaryAddress = new RimSummaryAddress; CAF_PDM_InitFieldNoDefault( &m_resamplingPeriod, "Resampling", "Resampling" ); - - m_showDataSource = true; - m_plotAxisOrientation = RimPlotAxisProperties::Orientation::ANY; } //-------------------------------------------------------------------------------------------------- @@ -124,6 +124,14 @@ void RimSummaryAddressSelector::setShowDataSource( bool enable ) m_showDataSource = enable; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryAddressSelector::setShowResampling( bool enable ) +{ + m_showResampling = enable; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -344,7 +352,12 @@ void RimSummaryAddressSelector::defineUiOrdering( QString uiConfigName, caf::Pdm uiOrdering.add( &m_summaryAddressUiField, { true, 2, 1 } ); uiOrdering.add( &m_pushButtonSelectSummaryAddress, { false, 1, 0 } ); - uiOrdering.add( &m_resamplingPeriod, { true, 3, 1 } ); + + if ( m_showResampling ) + { + uiOrdering.add( &m_resamplingPeriod, { true, 3, 1 } ); + } + uiOrdering.add( &m_plotAxisProperties, { true, 3, 1 } ); uiOrdering.skipRemainingFields( true ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressSelector.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressSelector.h index ca5cb25392..1e383db564 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressSelector.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressSelector.h @@ -50,9 +50,11 @@ public: void setAddress( const RifEclipseSummaryAddress& address ); void setResamplingPeriod( RiaDefines::DateTimePeriodEnum resampling ); void setPlotAxisProperties( RimPlotAxisPropertiesInterface* plotAxisProperties ); - void setShowDataSource( bool enable ); void setAxisOrientation( RimPlotAxisProperties::Orientation orientation ); + void setShowDataSource( bool enable ); + void setShowResampling( bool enable ); + RimSummaryCase* summaryCase() const; RimSummaryCaseCollection* ensemble() const; RifEclipseSummaryAddress summaryAddress() const; @@ -77,6 +79,7 @@ private: caf::PdmField m_resamplingPeriod; bool m_showDataSource; + bool m_showResampling; RimPlotAxisProperties::Orientation m_plotAxisOrientation; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp index c3ba79b6f5..e1cd35dd3c 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp @@ -1021,15 +1021,17 @@ QString RimSummaryCurve::curveExportDescription( const RifEclipseSummaryAddress& auto group = curveSet ? curveSet->summaryCaseCollection() : nullptr; auto addressUiText = addr.uiText(); + if ( !m_yValuesSummaryCase() ) + { + return QString::fromStdString( addressUiText ); + } if ( group && group->isEnsemble() ) { return QString( "%1.%2.%3" ).arg( QString::fromStdString( addressUiText ) ).arg( m_yValuesSummaryCase->nativeCaseName() ).arg( group->name() ); } - else - { - return QString( "%1.%2" ).arg( QString::fromStdString( addressUiText ) ).arg( m_yValuesSummaryCase->nativeCaseName() ); - } + + return QString( "%1.%2" ).arg( QString::fromStdString( addressUiText ) ).arg( m_yValuesSummaryCase->nativeCaseName() ); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index 0a38dff05a..22d7adf2f5 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -39,6 +39,7 @@ #include "RicfCommandObject.h" +#include "PlotBuilderCommands/RicSummaryPlotBuilder.h" #include "SummaryPlotCommands/RicSummaryPlotEditorUi.h" #include "PlotTemplates/RimPlotTemplateFileItem.h" @@ -2379,7 +2380,7 @@ RimSummaryPlot::CurveInfo RimSummaryPlot::handleEnsembleDrop( RimSummaryCaseColl { if ( ensembles.count( ensemble ) > 0 ) continue; - auto curveSet = addNewEnsembleCurve( addr, ensemble ); + auto curveSet = RicSummaryPlotBuilder::addNewEnsembleCurve( this, addr, ensemble ); curveSetsToUpdate.push_back( curveSet ); newCurves++; } @@ -2481,7 +2482,8 @@ RimSummaryPlot::CurveInfo RimSummaryPlot::handleAddressCollectionDrop( RimSummar auto addresses = curveDef.ensemble()->ensembleSummaryAddresses(); if ( addresses.find( curveDef.summaryAddressY() ) != addresses.end() ) { - curveSetsToUpdate.push_back( addNewEnsembleCurve( curveDef.summaryCurveAddress(), curveDef.ensemble() ) ); + auto curveSet = RicSummaryPlotBuilder::addNewEnsembleCurve( this, curveDef.summaryCurveAddress(), curveDef.ensemble() ); + curveSetsToUpdate.push_back( curveSet ); newCurves++; } } @@ -2551,8 +2553,13 @@ RimSummaryPlot::CurveInfo RimSummaryPlot::handleSummaryAddressDrop( RimSummaryAd if ( !skipAddress ) { - curveSetsToUpdate.push_back( - addNewEnsembleCurve( RiaSummaryCurveAddress( RifEclipseSummaryAddress::timeAddress(), droppedAddress ), ensemble ) ); + auto curveSet = + RicSummaryPlotBuilder::addNewEnsembleCurve( this, + RiaSummaryCurveAddress( RifEclipseSummaryAddress::timeAddress(), + droppedAddress ), + ensemble ); + + curveSetsToUpdate.push_back( curveSet ); newCurves++; } } @@ -2671,35 +2678,6 @@ RimSummaryCurve* RimSummaryPlot::addNewCurve( const RifEclipseSummaryAddress& ad return newCurve; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimEnsembleCurveSet* RimSummaryPlot::addNewEnsembleCurve( const RiaSummaryCurveAddress& address, RimSummaryCaseCollection* ensemble ) -{ - auto* curveSet = new RimEnsembleCurveSet(); - - curveSet->setSummaryCaseCollection( ensemble ); - curveSet->setSummaryAddressYAndStatisticsFlag( address.summaryAddressY() ); - curveSet->setCurveAddress( address ); - - cvf::Color3f curveColor = - RimSummaryCurveAppearanceCalculator::computeTintedCurveColorForAddress( curveSet->summaryAddressY(), - static_cast( - ensembleCurveSetCollection()->curveSetCount() ) ); - - auto adr = curveSet->summaryAddressY(); - if ( adr.isHistoryVector() ) curveColor = RiaPreferencesSummary::current()->historyCurveContrastColor(); - - curveSet->setColor( curveColor ); - - ensembleCurveSetCollection()->addCurveSet( curveSet ); - - curveSet->setLeftOrRightAxisY( RiuPlotAxis::defaultLeft() ); - curveSet->setBottomOrTopAxisX( RiuPlotAxis::defaultBottomForSummaryVectors() ); - - return curveSet; -} - //-------------------------------------------------------------------------------------------------- /// //--------------------------------------------------------------------------------------------------