Cleanup well path creation and duplication menu and functionality.

Changes:
- Allow duplication of only modeled well paths.
- Allow creating modeled well path from file-backed well paths.
This commit is contained in:
Kristian Bendiksen authored and Magne Sjaastad committed 2025-03-17 18:02:56 +01:00
1 parent 549c07b22d
commit 70fe005d8a
5 files changed
+112 -18

No files matched your search

@@ -28,6 +28,7 @@
#include "RimTools.h"
#include "RimWellPathCollection.h"
#include "RimWellPathGeometryDef.h"
#include "RimWellPathTarget.h"
#include "Riu3DMainWindowTools.h"
@@ -43,8 +44,7 @@ CAF_CMD_SOURCE_INIT( RicDuplicateWellPathFeature, "RicDuplicateWellPathFeature"
//--------------------------------------------------------------------------------------------------
bool RicDuplicateWellPathFeature::isCommandEnabled() const
{
auto wellPath = caf::firstAncestorOfTypeFromSelectedObject<RimWellPath>();
auto wellPath = caf::firstAncestorOfTypeFromSelectedObject<RimModeledWellPath>();
return wellPath != nullptr;
}
@@ -53,7 +53,7 @@ bool RicDuplicateWellPathFeature::isCommandEnabled() const
//--------------------------------------------------------------------------------------------------
void RicDuplicateWellPathFeature::onActionTriggered( bool isChecked )
{
auto sourceWellPath = caf::firstAncestorOfTypeFromSelectedObject<RimWellPath>();
auto sourceWellPath = caf::firstAncestorOfTypeFromSelectedObject<RimModeledWellPath>();
if ( !sourceWellPath ) return;
RimProject* project = RimProject::current();
@@ -78,17 +78,11 @@ void RicDuplicateWellPathFeature::onActionTriggered( bool isChecked )
{
auto destinationGeometryDef = newModeledWellPath->geometryDefinition();
const int targetCount = 8;
const auto sourceMDs = sourceWellPath->wellPathGeometry()->measuredDepths();
const double distanceBetweenTargets = ( sourceMDs.back() - sourceMDs.front() ) / targetCount;
std::vector<cvf::Vec3d> targetCoordinates;
for ( int targetIdx = 0; targetIdx <= targetCount; targetIdx++ )
for ( auto target : sourceWellPath->geometryDefinition()->activeWellTargets( false ) )
{
double measuredDepth = sourceMDs.front() + targetIdx * distanceBetweenTargets;
auto sourceCoord = sourceWellPath->wellPathGeometry()->interpolatedPointAlongWellPath( measuredDepth );
targetCoordinates.push_back( sourceCoord );
targetCoordinates.push_back( target->targetPointXYZ() );
}
destinationGeometryDef->createAndInsertTargets( targetCoordinates );
newModeledWellPath->createWellPathGeometry();
@@ -19,6 +19,11 @@
#include "RiaColorTables.h"
#include "RigEclipseCaseData.h"
#include "Well/RigWellPath.h"
#include "RimEclipseCase.h"
#include "RimFileWellPath.h"
#include "RimModeledWellPath.h"
#include "RimOilField.h"
#include "RimProject.h"
@@ -26,6 +31,7 @@
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
#include "RimWellPathGeometryDef.h"
#include "Riu3DMainWindowTools.h"
#include "cafSelectionManager.h"
@@ -78,6 +84,9 @@ void RicNewEditableWellPathFeature::onActionTriggered( bool isChecked )
newModeledWellPath->setUnitSystem( project->commonUnitSystemForAllCases() );
RimFileWellPath* sourceWellPath = caf::SelectionManager::instance()->selectedItemOfType<RimFileWellPath>();
bool enableTargetPointPicking = !copyWellPathGeometry( sourceWellPath, newModeledWellPath );
size_t modelledWellpathCount = wellPathCollection->modelledWellPathCount();
newWellPaths.back()->setName( "Well-" + QString::number( modelledWellpathCount + 1 ) );
@@ -86,7 +95,7 @@ void RicNewEditableWellPathFeature::onActionTriggered( bool isChecked )
wellPathCollection->addWellPaths( newWellPaths );
wellPathCollection->uiCapability()->updateConnectedEditors();
newModeledWellPath->geometryDefinition()->enableTargetPointPicking( true );
newModeledWellPath->geometryDefinition()->enableTargetPointPicking( enableTargetPointPicking );
project->scheduleCreateDisplayModelAndRedrawAllViews();
@@ -95,11 +104,90 @@ void RicNewEditableWellPathFeature::onActionTriggered( bool isChecked )
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicNewEditableWellPathFeature::copyWellPathGeometry( RimFileWellPath* sourceWellPath, RimModeledWellPath* newModeledWellPath )
{
if ( sourceWellPath && sourceWellPath->wellPathGeometry() && sourceWellPath->wellPathGeometry()->measuredDepths().size() > 2 )
{
auto destinationGeometryDef = newModeledWellPath->geometryDefinition();
const int targetCount = 8;
const auto wellPathPoints = sourceWellPath->wellPathGeometry()->wellPathPoints();
const auto sourceMDs = sourceWellPath->wellPathGeometry()->measuredDepths();
auto findCaseContainingAnyPoint = []( const std::vector<cvf::Vec3d>& points ) -> RimCase*
{
std::vector<RimCase*> cases = RimProject::current()->allGridCases();
for ( RimCase* c : cases )
{
for ( const cvf::Vec3d& p : points )
{
if ( c->activeCellsBoundingBox().contains( p ) )
{
return c;
}
}
}
return nullptr;
};
const RimCase* theCase = findCaseContainingAnyPoint( wellPathPoints );
const double depth = theCase ? theCase->activeCellsBoundingBox().max().z() : 0.0;
auto filterAwayPointsAboveMinimumDepth = []( const std::vector<cvf::Vec3d>& wellPathPoints,
const std::vector<double>& md,
double minimumDepth ) -> std::pair<std::vector<cvf::Vec3d>, std::vector<double>>
{
// Loop from the top and exclude until the minimum depth has been reached
std::vector<cvf::Vec3d> filteredPoints;
std::vector<double> filteredMds;
bool minimumDepthReached = false;
for ( size_t i = 0; i < wellPathPoints.size(); i++ )
{
if ( wellPathPoints[i].z() < minimumDepth || minimumDepthReached )
{
filteredPoints.push_back( wellPathPoints[i] );
filteredMds.push_back( md[i] );
minimumDepthReached = true;
}
}
return { filteredPoints, filteredMds };
};
const auto& [filteredWellPathPoints, filteredMDs] = filterAwayPointsAboveMinimumDepth( wellPathPoints, sourceMDs, depth );
CAF_ASSERT( filteredWellPathPoints.size() == filteredMDs.size() );
if ( filteredWellPathPoints.size() < 2 ) return false;
std::vector<cvf::Vec3d> targetCoordinates;
const double distanceBetweenTargets = ( filteredMDs.back() - filteredMDs.front() ) / targetCount;
RigWellPath wellPath( filteredWellPathPoints, filteredMDs );
for ( int targetIdx = 0; targetIdx <= targetCount; targetIdx++ )
{
double measuredDepth = filteredMDs.front() + targetIdx * distanceBetweenTargets;
auto sourceCoord = wellPath.interpolatedPointAlongWellPath( measuredDepth );
targetCoordinates.push_back( sourceCoord );
}
destinationGeometryDef->createAndInsertTargets( targetCoordinates );
newModeledWellPath->createWellPathGeometry();
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewEditableWellPathFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setText( "Create Well Path" );
actionToSetup->setIcon( QIcon( ":/Well.svg" ) );
actionToSetup->setText( "Create Editable Well Path" );
actionToSetup->setIcon( QIcon( ":/EditableWell.png" ) );
}
@@ -20,6 +20,9 @@
#include "cafCmdFeature.h"
class RimFileWellPath;
class RimModeledWellPath;
//==================================================================================================
///
//==================================================================================================
@@ -31,4 +34,6 @@ protected:
bool isCommandEnabled() const override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
bool copyWellPathGeometry( RimFileWellPath* sourceWellPath, RimModeledWellPath* newModeledWellPath );
};