diff --git a/ApplicationLibCode/Commands/WellPathCommands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/WellPathCommands/CMakeLists_files.cmake index 8eb2c80473..cb8c3b62c6 100644 --- a/ApplicationLibCode/Commands/WellPathCommands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/WellPathCommands/CMakeLists_files.cmake @@ -22,6 +22,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicNewWellPathLateralFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicPasteModeledWellPathFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicCreateMultipleWellPathLaterals.h ${CMAKE_CURRENT_LIST_DIR}/RicCreateMultipleWellPathLateralsUi.h +${CMAKE_CURRENT_LIST_DIR}/RicLinkWellPathFeature.h ${CMAKE_CURRENT_LIST_DIR}/PointTangentManipulator/Ric3dObjectEditorHandle.h ${CMAKE_CURRENT_LIST_DIR}/PointTangentManipulator/RicPointTangentManipulator.h ${CMAKE_CURRENT_LIST_DIR}/PointTangentManipulator/RicWellTarget3dEditor.h @@ -54,6 +55,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicNewWellPathLateralFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicPasteModeledWellPathFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicCreateMultipleWellPathLaterals.cpp ${CMAKE_CURRENT_LIST_DIR}/RicCreateMultipleWellPathLateralsUi.cpp +${CMAKE_CURRENT_LIST_DIR}/RicLinkWellPathFeature.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/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicWellTarget3dEditor.cpp b/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicWellTarget3dEditor.cpp index 46cb304d21..972b9997aa 100644 --- a/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicWellTarget3dEditor.cpp +++ b/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicWellTarget3dEditor.cpp @@ -24,6 +24,7 @@ #include "RimCase.h" #include "RimModeledWellPath.h" #include "RimWellPathGeometryDef.h" +#include "RimWellPathGeometryDefTools.h" #include "RimWellPathTarget.h" #include "RiuViewer.h" @@ -166,15 +167,19 @@ void RicWellTarget3dEditor::slotUpdated( const cvf::Vec3d& origin, const cvf::Ve auto relativePositionXYZ = domainCoordXYZ - geomDef->anchorPointXyz(); auto delta = target->targetPointXYZ() - relativePositionXYZ; - auto currentRefPointXyz = geomDef->anchorPointXyz(); - auto newRefPointXyz = currentRefPointXyz - delta; - geomDef->setReferencePointXyz( newRefPointXyz ); - geomDef->changed.send( false ); - geomDef->updateWellPathVisualization( true ); - for ( auto wt : geomDef->activeWellTargets() ) + // Find all linked wells and update with delta change + + std::vector linkedWellPathGeoDefs; + if ( geomDef->isReferencePointUpdatesLinked() ) { - wt->updateConnectedEditors(); + linkedWellPathGeoDefs = RimWellPathGeometryDefTools::linkedDefinitions(); } + else + { + linkedWellPathGeoDefs.push_back( geomDef ); + } + + RimWellPathGeometryDefTools::updateLinkedGeometryDefinitions( linkedWellPathGeoDefs, delta ); } else { diff --git a/ApplicationLibCode/Commands/WellPathCommands/RicLinkWellPathFeature.cpp b/ApplicationLibCode/Commands/WellPathCommands/RicLinkWellPathFeature.cpp new file mode 100644 index 0000000000..4707eb8d5e --- /dev/null +++ b/ApplicationLibCode/Commands/WellPathCommands/RicLinkWellPathFeature.cpp @@ -0,0 +1,87 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2021- 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 "RicLinkWellPathFeature.h" + +#include "RimModeledWellPath.h" +#include "RimWellPathGeometryDef.h" + +#include "Riu3dSelectionManager.h" + +#include "cafSelectionManager.h" + +#include + +CAF_CMD_SOURCE_INIT( RicLinkWellPathFeature, "RicLinkWellPathFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicLinkWellPathFeature::isCommandEnabled() +{ + return ( wellPathGeometryDef() != nullptr ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicLinkWellPathFeature::onActionTriggered( bool isChecked ) +{ + if ( auto geoDef = wellPathGeometryDef() ) + { + geoDef->enableLinkOfReferencePointUpdates( isChecked ); + geoDef->updateConnectedEditors(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicLinkWellPathFeature::setupActionLook( QAction* actionToSetup ) +{ + QString text = "Link Reference Point"; + actionToSetup->setText( text ); + actionToSetup->setCheckable( true ); + actionToSetup->setChecked( isCommandChecked() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicLinkWellPathFeature::isCommandChecked() +{ + if ( auto geoDef = wellPathGeometryDef() ) + { + return geoDef->isReferencePointUpdatesLinked(); + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPathGeometryDef* RicLinkWellPathFeature::wellPathGeometryDef() +{ + auto wellPathSelectionItem = RiuWellPathSelectionItem::wellPathSelectionItem(); + if ( wellPathSelectionItem && wellPathSelectionItem->m_wellpath ) + { + auto modeledWellPath = dynamic_cast( wellPathSelectionItem->m_wellpath ); + return modeledWellPath->geometryDefinition(); + } +} diff --git a/ApplicationLibCode/Commands/WellPathCommands/RicLinkWellPathFeature.h b/ApplicationLibCode/Commands/WellPathCommands/RicLinkWellPathFeature.h new file mode 100644 index 0000000000..006f942e84 --- /dev/null +++ b/ApplicationLibCode/Commands/WellPathCommands/RicLinkWellPathFeature.h @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2021- 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 RimWellPathGeometryDef; + +//================================================================================================== +/// +//================================================================================================== +class RicLinkWellPathFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +public: + bool isCommandEnabled() override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; + bool isCommandChecked() override; + +private: + static RimWellPathGeometryDef* wellPathGeometryDef(); +}; diff --git a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake index 567b8c996e..d70bc6d209 100644 --- a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake @@ -27,6 +27,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurement.h ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementFilePath.h ${CMAKE_CURRENT_LIST_DIR}/RimWellPathGeometryDef.h +${CMAKE_CURRENT_LIST_DIR}/RimWellPathGeometryDefTools.h ${CMAKE_CURRENT_LIST_DIR}/RimWellPathAttribute.h ${CMAKE_CURRENT_LIST_DIR}/RimWellPathAttributeCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimWellPathCollection.h @@ -185,6 +186,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurement.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementFilePath.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathGeometryDef.cpp +${CMAKE_CURRENT_LIST_DIR}/RimWellPathGeometryDefTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathAttribute.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathAttributeCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathCollection.cpp diff --git a/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDef.cpp b/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDef.cpp index 7c04009259..6a800647ac 100644 --- a/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDef.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDef.cpp @@ -32,6 +32,7 @@ #include "RimModeledWellPath.h" #include "RimProject.h" +#include "RimWellPathGeometryDefTools.h" #include "RimWellPathTarget.h" #include "RiuViewerCommands.h" @@ -101,6 +102,14 @@ RimWellPathGeometryDef::RimWellPathGeometryDef() "", "" ); + CAF_PDM_InitScriptableField( &m_linkReferencePointUpdates, + "LinkReferencePointUpdates", + false, + "Link Reference Point Updates", + "", + "", + "" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_autoTargetAtSeaLevel, "AutoGeneratedTarget", "Auto Generated Target", "", "", "" ); m_autoTargetAtSeaLevel = new RimWellPathTarget; m_autoTargetAtSeaLevel->setEnabled( false ); @@ -168,6 +177,22 @@ void RimWellPathGeometryDef::enableReferencePointFromTopLevelWell( bool enable ) m_useTopLevelWellReferencePoint = enable; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPathGeometryDef::enableLinkOfReferencePointUpdates( bool enable ) +{ + m_linkReferencePointUpdates = enable; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellPathGeometryDef::isReferencePointUpdatesLinked() const +{ + return m_linkReferencePointUpdates; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -478,6 +503,26 @@ void RimWellPathGeometryDef::fieldChangedByUi( const caf::PdmFieldHandle* change { this->updateConnectedEditors(); } + else if ( changedField == &m_referencePointUtmXyd ) + { + if ( isReferencePointUpdatesLinked() ) + { + auto linkedDefs = RimWellPathGeometryDefTools::linkedDefinitions(); + + // Remove this to avoid duplicate updates + linkedDefs.erase( std::remove_if( linkedDefs.begin(), + linkedDefs.end(), + [this]( auto const& geoDef ) { return geoDef == this; } ), + linkedDefs.end() ); + + cvf::Vec3d oldPos; + caf::PdmValueFieldSpecialization::setFromVariant( oldValue, oldPos ); + + auto delta = m_referencePointUtmXyd() - oldPos; + + RimWellPathGeometryDefTools::updateLinkedGeometryDefinitions( linkedDefs, delta ); + } + } changed.send( false ); } @@ -488,15 +533,19 @@ void RimWellPathGeometryDef::fieldChangedByUi( const caf::PdmFieldHandle* change void RimWellPathGeometryDef::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { uiOrdering.add( &m_referencePointUtmXyd ); - uiOrdering.add( &m_useTopLevelWellReferencePoint ); m_referencePointUtmXyd.uiCapability()->setUiReadOnly( m_useTopLevelWellReferencePoint ); if ( !m_isAttachedToParentWell ) { + uiOrdering.add( &m_linkReferencePointUpdates ); uiOrdering.add( &m_airGap ); uiOrdering.add( &m_mdAtFirstTarget ); uiOrdering.add( &m_useAutoGeneratedTargetAtSeaLevel ); } + else + { + uiOrdering.add( &m_useTopLevelWellReferencePoint ); + } auto group = uiOrdering.addNewGroup( "Well Target Appearance" ); group->add( &m_showSpheres ); diff --git a/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDef.h b/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDef.h index ec819387ef..573a843052 100644 --- a/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDef.h +++ b/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDef.h @@ -54,6 +54,8 @@ public: void setReferencePointXyz( const cvf::Vec3d& refPointXyz ); bool useReferencePointFromTopLevelWell() const; void enableReferencePointFromTopLevelWell( bool enable ); + void enableLinkOfReferencePointUpdates( bool enable ); + bool isReferencePointUpdatesLinked() const; double airGap() const; void setAirGap( double airGap ); @@ -125,6 +127,7 @@ private: caf::PdmChildArrayField m_wellTargets; caf::PdmField m_showAbsolutePosForWellTargets; caf::PdmField m_useTopLevelWellReferencePoint; + caf::PdmField m_linkReferencePointUpdates; caf::PdmField m_useAutoGeneratedTargetAtSeaLevel; caf::PdmChildField m_autoTargetAtSeaLevel; diff --git a/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDefTools.cpp b/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDefTools.cpp new file mode 100644 index 0000000000..7d21740ddf --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDefTools.cpp @@ -0,0 +1,68 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2021 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 "RimWellPathGeometryDefTools.h" + +#include "RimModeledWellPath.h" +#include "RimTools.h" +#include "RimWellPathCollection.h" +#include "RimWellPathGeometryDef.h" +#include "RimWellPathTarget.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPathGeometryDefTools::updateLinkedGeometryDefinitions( std::vector& definitions, + cvf::Vec3d delta ) +{ + for ( auto wellPathGeoDef : definitions ) + { + auto currentRefPointXyz = wellPathGeoDef->anchorPointXyz(); + auto newRefPointXyz = currentRefPointXyz - delta; + + wellPathGeoDef->setReferencePointXyz( newRefPointXyz ); + + wellPathGeoDef->changed.send( false ); + wellPathGeoDef->updateWellPathVisualization( true ); + for ( auto wt : wellPathGeoDef->activeWellTargets() ) + { + wt->updateConnectedEditors(); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimWellPathGeometryDefTools::linkedDefinitions() +{ + std::vector linkedWellPathGeoDefs; + + for ( auto w : RimTools::wellPathCollection()->allWellPaths() ) + { + auto modeledWellPath = dynamic_cast( w ); + if ( !modeledWellPath ) continue; + + if ( modeledWellPath->geometryDefinition()->isReferencePointUpdatesLinked() ) + { + linkedWellPathGeoDefs.push_back( modeledWellPath->geometryDefinition() ); + } + } + + return linkedWellPathGeoDefs; +} diff --git a/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDefTools.h b/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDefTools.h new file mode 100644 index 0000000000..b93e32ef97 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimWellPathGeometryDefTools.h @@ -0,0 +1,26 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2021 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 + +class RimWellPathGeometryDefTools +{ +public: + static void updateLinkedGeometryDefinitions( std::vector& definitions, cvf::Vec3d delta ); + + static std::vector linkedDefinitions(); +}; diff --git a/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp b/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp index 294bca3f14..c8e8c7a797 100644 --- a/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp +++ b/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp @@ -553,6 +553,7 @@ void RiuViewerCommands::displayContextMenu( QMouseEvent* event ) menuBuilder.addSeparator(); menuBuilder << "RicNewWellPathLateralAtDepthFeature"; menuBuilder << "RicNewWellPathIntersectionFeature"; + menuBuilder << "RicLinkWellPathFeature"; } const RivSimWellPipeSourceInfo* eclipseWellSourceInfo =