mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Improve well path modeling
* Improve handling of MD at first target * When sea level well target is disabled, update MD of first target * Show well target spheres by default, allow toggling of spheres * Activate well target modifiers when clicking on well targets * Remove selection update causing an unstable 3D view * Improve display and handling of multiple locations * Add special 3D target for tie in well target * Add slider to tie in MD input field * Show MD in well path target table * Delete all well path laterals when deleting a well path * Python : Add lateral to parent well * Python : Add perforation interval
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
#include "RimWellPathTarget.h"
|
||||
#include "RimWellPathTieIn.h"
|
||||
|
||||
#include "RigWellPathGeometryTools.h"
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmUiDoubleValueEditor.h"
|
||||
#include "cafPdmUiTreeOrdering.h"
|
||||
@@ -87,7 +88,7 @@ void RimModeledWellPath::createWellPathGeometry()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimModeledWellPath::updateWellPathVisualization()
|
||||
{
|
||||
this->setWellPathGeometry( m_geometryDefinition->createWellPathGeometry().p() );
|
||||
createWellPathGeometry();
|
||||
|
||||
std::vector<RimPlotCurve*> refferingCurves;
|
||||
this->objectsWithReferringPtrFieldsOfType( refferingCurves );
|
||||
@@ -288,7 +289,10 @@ void RimModeledWellPath::updateTieInLocationFromParentWell()
|
||||
cvf::Vec3d relativePointXYZ = lastPointXYZ - referencePointXYZ;
|
||||
|
||||
auto firstTarget = targets.front();
|
||||
firstTarget->setPointXYZ( relativePointXYZ );
|
||||
const auto [azimuth, inclination] =
|
||||
RigWellPathGeometryTools::calculateAzimuthAndInclinationAtMd( tieIn->tieInMeasuredDepth(),
|
||||
parentWellPath->wellPathGeometry() );
|
||||
firstTarget->setAsPointXYZAndTangentTarget( relativePointXYZ, azimuth, inclination );
|
||||
|
||||
updateGeometry( true );
|
||||
}
|
||||
|
||||
@@ -137,8 +137,6 @@ RimWellPath::RimWellPath()
|
||||
CAF_PDM_InitFieldNoDefault( &m_wellPathTieIn, "WellPathTieIn", "well Path Tie-In", "", "", "" );
|
||||
m_wellPathTieIn = new RimWellPathTieIn;
|
||||
m_wellPathTieIn->connectWellPaths( nullptr, this, 0.0 );
|
||||
|
||||
this->setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -1170,6 +1168,31 @@ std::vector<RimWellPath*> RimWellPath::allWellPathLaterals() const
|
||||
return laterals;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimWellPath*> RimWellPath::wellPathLaterals() const
|
||||
{
|
||||
std::vector<RimWellPath*> laterals;
|
||||
|
||||
std::vector<caf::PdmObjectHandle*> referringObjects;
|
||||
this->objectsWithReferringPtrFields( referringObjects );
|
||||
for ( auto obj : referringObjects )
|
||||
{
|
||||
if ( auto tieIn = dynamic_cast<RimWellPathTieIn*>( obj ) )
|
||||
{
|
||||
auto tieInWellPath = tieIn->childWell();
|
||||
if ( tieInWellPath == this ) continue;
|
||||
if ( tieInWellPath )
|
||||
{
|
||||
laterals.push_back( tieInWellPath );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return laterals;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -163,6 +163,7 @@ public:
|
||||
RimWellPath* topLevelWellPath();
|
||||
const RimWellPath* topLevelWellPath() const;
|
||||
std::vector<RimWellPath*> allWellPathLaterals() const;
|
||||
std::vector<RimWellPath*> wellPathLaterals() const;
|
||||
|
||||
RimWellPathTieIn* wellPathTieIn() const;
|
||||
void connectWellPaths( RimWellPath* childWell, double tieInMeasuredDepth );
|
||||
|
||||
@@ -583,6 +583,15 @@ void RimWellPathCollection::deleteAllWellPaths()
|
||||
updateAllRequiredEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellPathCollection::deleteWell( RimWellPath* wellPath )
|
||||
{
|
||||
m_wellPaths.removeChildObject( wellPath );
|
||||
delete wellPath;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -98,6 +98,7 @@ public:
|
||||
void removeWellPath( gsl::not_null<RimWellPath*> wellPath );
|
||||
|
||||
void deleteAllWellPaths();
|
||||
void deleteWell( RimWellPath* wellPath );
|
||||
|
||||
void groupWellPaths( const std::vector<RimWellPath*>& wellPaths );
|
||||
void rebuildWellPathNodes();
|
||||
|
||||
@@ -105,7 +105,7 @@ RimWellPathGeometryDef::RimWellPathGeometryDef()
|
||||
CAF_PDM_InitScriptableField( &m_linkReferencePointUpdates,
|
||||
"LinkReferencePointUpdates",
|
||||
false,
|
||||
"Link Reference Point Updates",
|
||||
"Link Reference Point",
|
||||
"",
|
||||
"",
|
||||
"" );
|
||||
@@ -121,7 +121,7 @@ RimWellPathGeometryDef::RimWellPathGeometryDef()
|
||||
CAF_PDM_InitField( &m_pickPointsEnabled, "m_pickPointsEnabled", false, "", "", "", "" );
|
||||
caf::PdmUiPushButtonEditor::configureEditorForField( &m_pickPointsEnabled );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_showSpheres, "ShowSpheres", false, "Spheres", "", "", "" );
|
||||
CAF_PDM_InitScriptableField( &m_showSpheres, "ShowSpheres", true, "Spheres", "", "", "" );
|
||||
CAF_PDM_InitField( &m_sphereColor, "SphereColor", cvf::Color3f( cvf::Color3f::CEETRON ), "Sphere Color", "", "", "" );
|
||||
CAF_PDM_InitField( &m_sphereRadiusFactor, "SphereRadiusFactor", 0.15, "Sphere Radius Factor", "", "", "" );
|
||||
}
|
||||
@@ -289,7 +289,17 @@ cvf::ref<RigWellPath> RimWellPathGeometryDef::createWellPathGeometry()
|
||||
RiaPolyArcLineSampler arcLineSampler( wellPathCalculator.startTangent(), wellPathCalculator.lineArcEndpoints() );
|
||||
auto [sampledWellPathPoints, sampledMeasuredDepths] = arcLineSampler.sampledPointsAndMDs( 30, false );
|
||||
wellPathPoints.insert( wellPathPoints.end(), sampledWellPathPoints.begin(), sampledWellPathPoints.end() );
|
||||
double startMD = measuredDepths.empty() ? 0.0 : measuredDepths.back();
|
||||
|
||||
double startMD = 0.0;
|
||||
if ( !measuredDepths.empty() )
|
||||
{
|
||||
startMD = measuredDepths.back();
|
||||
}
|
||||
else if ( !m_useAutoGeneratedTargetAtSeaLevel )
|
||||
{
|
||||
startMD = m_mdAtFirstTarget;
|
||||
}
|
||||
|
||||
for ( auto md : sampledMeasuredDepths )
|
||||
{
|
||||
measuredDepths.push_back( md + startMD );
|
||||
@@ -523,6 +533,23 @@ void RimWellPathGeometryDef::fieldChangedByUi( const caf::PdmFieldHandle* change
|
||||
RimWellPathGeometryDefTools::updateLinkedGeometryDefinitions( linkedDefs, delta );
|
||||
}
|
||||
}
|
||||
else if ( changedField == &m_useAutoGeneratedTargetAtSeaLevel && !m_useAutoGeneratedTargetAtSeaLevel )
|
||||
{
|
||||
auto firstTarget = firstActiveTarget();
|
||||
if ( firstTarget != nullptr )
|
||||
{
|
||||
auto firstLocationXYZ = firstTarget->targetPointXYZ() + anchorPointXyz();
|
||||
|
||||
// Temporarily enable target at sea level to be able to create a complete geometry to find MD of first
|
||||
// target of the complete geometry
|
||||
m_useAutoGeneratedTargetAtSeaLevel = true;
|
||||
auto wellPathGeo = createWellPathGeometry();
|
||||
m_useAutoGeneratedTargetAtSeaLevel = false;
|
||||
|
||||
double mdAtFirstTarget = wellPathGeo->closestMeasuredDepth( firstLocationXYZ );
|
||||
m_mdAtFirstTarget = mdAtFirstTarget;
|
||||
}
|
||||
}
|
||||
|
||||
changed.send( false );
|
||||
}
|
||||
@@ -759,6 +786,14 @@ void RimWellPathGeometryDef::defineObjectEditorAttribute( QString uiConfigName,
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
caf::PdmFieldHandle* RimWellPathGeometryDef::objectToggleField()
|
||||
{
|
||||
return &m_showSpheres;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -102,6 +102,7 @@ protected:
|
||||
caf::PdmUiEditorAttribute* attribute ) override;
|
||||
|
||||
void defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
|
||||
caf::PdmFieldHandle* objectToggleField() override;
|
||||
|
||||
void onTargetMoved( const caf::SignalEmitter* emitter, bool fullUpdate );
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ void caf::AppEnum<RimWellPathTarget::TargetTypeEnum>::setUp()
|
||||
{
|
||||
addItem( RimWellPathTarget::TargetTypeEnum::POINT_AND_TANGENT, "POINT_AND_TANGENT", "Point and Tangent" );
|
||||
addItem( RimWellPathTarget::TargetTypeEnum::POINT, "POINT", "Point" );
|
||||
setDefault( RimWellPathTarget::TargetTypeEnum::POINT_AND_TANGENT );
|
||||
setDefault( RimWellPathTarget::TargetTypeEnum::POINT );
|
||||
}
|
||||
} // namespace caf
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -51,7 +51,7 @@ void caf::AppEnum<RimWellPathTarget::TargetTypeEnum>::setUp()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellPathTarget::RimWellPathTarget()
|
||||
: moved( this )
|
||||
, m_targetType( TargetTypeEnum::POINT_AND_TANGENT )
|
||||
, m_targetType( TargetTypeEnum::POINT )
|
||||
, m_targetPointXYD( cvf::Vec3d::ZERO )
|
||||
, m_azimuth( 0.0 )
|
||||
, m_inclination( 0.0 )
|
||||
@@ -69,10 +69,13 @@ RimWellPathTarget::RimWellPathTarget()
|
||||
m_isLocked.uiCapability()->setUiHidden( true );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_targetPointXYD, "TargetPoint", "Relative Coord", "", "", "" );
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_targetPointForDisplay, "TargetPointForDisplay", "UTM Coord", "", "", "" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_targetPointForDisplay, "TargetPointForDisplay", "UTM Coord", "", "", "" );
|
||||
m_targetPointForDisplay.registerGetMethod( this, &RimWellPathTarget::targetPointForDisplayXYD );
|
||||
m_targetPointForDisplay.registerSetMethod( this, &RimWellPathTarget::setTargetPointFromDisplayCoord );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_targetMeasuredDepth, "TargetMeasuredDepth", "MD", "", "", "" );
|
||||
m_targetMeasuredDepth.registerGetMethod( this, &RimWellPathTarget::measuredDepth );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_dogleg1, "Dogleg1", 3.0, "DL in", "", "[deg/30m]", "" );
|
||||
CAF_PDM_InitScriptableField( &m_dogleg2, "Dogleg2", 3.0, "DL out", "", "[deg/30m]", "" );
|
||||
|
||||
@@ -224,10 +227,8 @@ double RimWellPathTarget::azimuth() const
|
||||
{
|
||||
return cvf::Math::toRadians( m_azimuth );
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -239,10 +240,8 @@ double RimWellPathTarget::inclination() const
|
||||
{
|
||||
return cvf::Math::toRadians( m_inclination );
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -441,6 +440,28 @@ void RimWellPathTarget::setTargetPointFromDisplayCoord( const cvf::Vec3d& coordI
|
||||
m_targetPointXYD = newCoordInXYD;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellPathTarget::measuredDepth() const
|
||||
{
|
||||
RimWellPath* wellPath = nullptr;
|
||||
this->firstAncestorOfType( wellPath );
|
||||
|
||||
auto geoDef = geometryDefinition();
|
||||
|
||||
if ( geoDef && wellPath && wellPath->wellPathGeometry() )
|
||||
{
|
||||
auto offsetXYZ = geoDef->anchorPointXyz();
|
||||
auto coordXYZ = targetPointXYZ() + offsetXYZ;
|
||||
|
||||
auto wellPathGeo = wellPath->wellPathGeometry();
|
||||
return wellPathGeo->closestMeasuredDepth( coordXYZ );
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -85,6 +85,7 @@ private:
|
||||
|
||||
cvf::Vec3d targetPointForDisplayXYD() const;
|
||||
void setTargetPointFromDisplayCoord( const cvf::Vec3d& coordInXYZ );
|
||||
double measuredDepth() const;
|
||||
|
||||
RimWellPathGeometryDef* geometryDefinition() const;
|
||||
|
||||
@@ -96,9 +97,11 @@ private:
|
||||
caf::PdmField<caf::AppEnum<TargetTypeEnum>> m_targetType;
|
||||
caf::PdmField<cvf::Vec3d> m_targetPointXYD;
|
||||
caf::PdmProxyValueField<cvf::Vec3d> m_targetPointForDisplay;
|
||||
caf::PdmField<double> m_azimuth;
|
||||
caf::PdmField<double> m_inclination;
|
||||
caf::PdmField<double> m_dogleg1;
|
||||
caf::PdmField<double> m_dogleg2;
|
||||
caf::PdmField<bool> m_hasTangentConstraintUiField;
|
||||
caf::PdmProxyValueField<double> m_targetMeasuredDepth;
|
||||
|
||||
caf::PdmField<double> m_azimuth;
|
||||
caf::PdmField<double> m_inclination;
|
||||
caf::PdmField<double> m_dogleg1;
|
||||
caf::PdmField<double> m_dogleg2;
|
||||
caf::PdmField<bool> m_hasTangentConstraintUiField;
|
||||
};
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
|
||||
#include "RiuMainWindow.h"
|
||||
|
||||
#include "cafPdmUiDoubleValueEditor.h"
|
||||
#include "RigWellPathGeometryTools.h"
|
||||
#include "cafPdmUiDoubleSliderEditor.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimWellPathTieIn, "RimWellPathTieIn" );
|
||||
|
||||
@@ -44,7 +45,7 @@ RimWellPathTieIn::RimWellPathTieIn()
|
||||
CAF_PDM_InitFieldNoDefault( &m_parentWell, "ParentWellPath", "Parent Well Path", "", "", "" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_childWell, "ChildWellPath", "ChildWellPath", "", "", "" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_tieInMeasuredDepth, "TieInMeasuredDepth", "Tie In Measured Depth", "", "", "" );
|
||||
m_tieInMeasuredDepth.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
|
||||
m_tieInMeasuredDepth.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() );
|
||||
|
||||
CAF_PDM_InitField( &m_addValveAtConnection, "AddValveAtConnection", false, "Add Outlet Valve for Branches", "", "", "" );
|
||||
|
||||
@@ -227,3 +228,32 @@ QList<caf::PdmOptionItemInfo> RimWellPathTieIn::calculateValueOptions( const caf
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellPathTieIn::defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute )
|
||||
{
|
||||
if ( field == &m_tieInMeasuredDepth )
|
||||
{
|
||||
caf::PdmUiDoubleSliderEditorAttribute* myAttr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>( attribute );
|
||||
|
||||
if ( myAttr && parentWell() )
|
||||
{
|
||||
double minimumValue = 0.0, maximumValue = 0.0;
|
||||
|
||||
auto wellPathGeo = parentWell()->wellPathGeometry();
|
||||
|
||||
if ( wellPathGeo )
|
||||
{
|
||||
minimumValue = wellPathGeo->measuredDepths().front();
|
||||
maximumValue = wellPathGeo->measuredDepths().back();
|
||||
|
||||
myAttr->m_minimum = minimumValue;
|
||||
myAttr->m_maximum = maximumValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,10 @@ private:
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
|
||||
bool* useOptionsOnly ) override;
|
||||
|
||||
void defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute ) override;
|
||||
|
||||
private:
|
||||
caf::PdmPtrField<RimWellPath*> m_parentWell;
|
||||
caf::PdmPtrField<RimWellPath*> m_childWell;
|
||||
|
||||
Reference in New Issue
Block a user