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:
@@ -315,41 +315,15 @@ cvf::Vec3d RigWellPath::tangentAlongWellPath( double measuredDepth ) const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigWellPath::wellPathAzimuthAngle( const cvf::Vec3d& position ) const
|
||||
{
|
||||
size_t closestIndex = cvf::UNDEFINED_SIZE_T;
|
||||
double closestDistance = cvf::UNDEFINED_DOUBLE;
|
||||
|
||||
for ( size_t i = 1; i < m_wellPathPoints.size(); i++ )
|
||||
{
|
||||
cvf::Vec3d p1 = m_wellPathPoints[i - 1];
|
||||
cvf::Vec3d p2 = m_wellPathPoints[i - 0];
|
||||
|
||||
double candidateDistance = cvf::GeometryTools::linePointSquareDist( p1, p2, position );
|
||||
if ( candidateDistance < closestDistance )
|
||||
{
|
||||
closestDistance = candidateDistance;
|
||||
closestIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
// For vertical well (x-component of direction = 0) returned angle will be 90.
|
||||
double azimuthAngleDegrees = 90.0;
|
||||
|
||||
if ( closestIndex != cvf::UNDEFINED_DOUBLE )
|
||||
cvf::Vec3d p1 = cvf::Vec3d::UNDEFINED;
|
||||
cvf::Vec3d p2 = cvf::Vec3d::UNDEFINED;
|
||||
twoClosestPoints( position, &p1, &p2 );
|
||||
|
||||
if ( !p1.isUndefined() )
|
||||
{
|
||||
cvf::Vec3d p1;
|
||||
cvf::Vec3d p2;
|
||||
|
||||
if ( closestIndex > 0 )
|
||||
{
|
||||
p1 = m_wellPathPoints[closestIndex - 1];
|
||||
p2 = m_wellPathPoints[closestIndex - 0];
|
||||
}
|
||||
else
|
||||
{
|
||||
p1 = m_wellPathPoints[closestIndex + 1];
|
||||
p2 = m_wellPathPoints[closestIndex + 0];
|
||||
}
|
||||
|
||||
cvf::Vec3d direction = p2 - p1;
|
||||
|
||||
if ( fabs( direction.y() ) > 1e-5 )
|
||||
@@ -370,34 +344,11 @@ void RigWellPath::twoClosestPoints( const cvf::Vec3d& position, cvf::Vec3d* p1,
|
||||
{
|
||||
CVF_ASSERT( p1 && p2 );
|
||||
|
||||
size_t closestIndex = cvf::UNDEFINED_SIZE_T;
|
||||
double closestDistance = cvf::UNDEFINED_DOUBLE;
|
||||
|
||||
for ( size_t i = 1; i < m_wellPathPoints.size(); i++ )
|
||||
auto closeIndices = closestIndices( position );
|
||||
if ( closeIndices.first != cvf::UNDEFINED_SIZE_T )
|
||||
{
|
||||
cvf::Vec3d point1 = m_wellPathPoints[i - 1];
|
||||
cvf::Vec3d point2 = m_wellPathPoints[i - 0];
|
||||
|
||||
double candidateDistance = cvf::GeometryTools::linePointSquareDist( point1, point2, position );
|
||||
if ( candidateDistance < closestDistance )
|
||||
{
|
||||
closestDistance = candidateDistance;
|
||||
closestIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if ( closestIndex != cvf::UNDEFINED_SIZE_T )
|
||||
{
|
||||
if ( closestIndex > 0 )
|
||||
{
|
||||
*p1 = m_wellPathPoints[closestIndex - 1];
|
||||
*p2 = m_wellPathPoints[closestIndex - 0];
|
||||
}
|
||||
else
|
||||
{
|
||||
*p1 = m_wellPathPoints[closestIndex + 1];
|
||||
*p2 = m_wellPathPoints[closestIndex + 0];
|
||||
}
|
||||
*p1 = m_wellPathPoints[closeIndices.first];
|
||||
*p2 = m_wellPathPoints[closeIndices.second];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,6 +380,32 @@ double RigWellPath::identicalTubeLength( const RigWellPath& other ) const
|
||||
return identicalLength;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigWellPath::closestMeasuredDepth( const cvf::Vec3d& position ) const
|
||||
{
|
||||
auto [firstIndex, secondIndex] = closestIndices( position );
|
||||
if ( firstIndex != cvf::UNDEFINED_SIZE_T )
|
||||
{
|
||||
cvf::Vec3d p1 = m_wellPathPoints[firstIndex];
|
||||
cvf::Vec3d p2 = m_wellPathPoints[secondIndex];
|
||||
|
||||
double diffP1 = ( p1 - position ).lengthSquared();
|
||||
double diffP2 = ( p2 - position ).lengthSquared();
|
||||
|
||||
double weigth1 = diffP2 / ( diffP1 + diffP2 );
|
||||
|
||||
double measureDepth1 = m_measuredDepths[firstIndex];
|
||||
double measureDepth2 = m_measuredDepths[secondIndex];
|
||||
|
||||
double interpolatedValue = measureDepth1 * weigth1 + measureDepth2 * ( 1.0 - weigth1 );
|
||||
return interpolatedValue;
|
||||
}
|
||||
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -681,3 +658,40 @@ std::vector<cvf::Vec3d> RigWellPath::clipPolylineStartAboveZ( const std::vector<
|
||||
|
||||
return clippedPolyLine;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Returns the closes indices with smallest index first
|
||||
// If not found, cvf::UNDEFINED_SIZE_T is returned for both
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::pair<size_t, size_t> RigWellPath::closestIndices( const cvf::Vec3d& position ) const
|
||||
{
|
||||
size_t closestIndex = cvf::UNDEFINED_SIZE_T;
|
||||
double closestDistance = cvf::UNDEFINED_DOUBLE;
|
||||
|
||||
for ( size_t i = 1; i < m_wellPathPoints.size(); i++ )
|
||||
{
|
||||
cvf::Vec3d point1 = m_wellPathPoints[i - 1];
|
||||
cvf::Vec3d point2 = m_wellPathPoints[i - 0];
|
||||
|
||||
double candidateDistance = cvf::GeometryTools::linePointSquareDist( point1, point2, position );
|
||||
if ( candidateDistance < closestDistance )
|
||||
{
|
||||
closestDistance = candidateDistance;
|
||||
closestIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if ( closestIndex != cvf::UNDEFINED_SIZE_T )
|
||||
{
|
||||
if ( closestIndex > 0 )
|
||||
{
|
||||
return { closestIndex - 1, closestIndex };
|
||||
}
|
||||
else
|
||||
{
|
||||
return { closestIndex, closestIndex + 1 };
|
||||
}
|
||||
}
|
||||
|
||||
return { cvf::UNDEFINED_SIZE_T, cvf::UNDEFINED_SIZE_T };
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
double wellPathAzimuthAngle( const cvf::Vec3d& position ) const;
|
||||
void twoClosestPoints( const cvf::Vec3d& position, cvf::Vec3d* p1, cvf::Vec3d* p2 ) const;
|
||||
double identicalTubeLength( const RigWellPath& otherWellPathGeometry ) const;
|
||||
double closestMeasuredDepth( const cvf::Vec3d& position ) const;
|
||||
|
||||
static cvf::ref<RigWellPath> commonGeometry( const std::vector<const RigWellPath*>& allGeometries );
|
||||
void setUniqueStartAndEndIndex( size_t uniqueStartIndex, size_t uniqueEndIndex );
|
||||
@@ -90,6 +91,9 @@ public:
|
||||
double* horizontalLengthAlongWellToClipPoint,
|
||||
size_t* indexToFirstVisibleSegment );
|
||||
|
||||
private:
|
||||
std::pair<size_t, size_t> closestIndices( const cvf::Vec3d& position ) const;
|
||||
|
||||
private:
|
||||
std::vector<cvf::Vec3d> m_wellPathPoints;
|
||||
std::vector<double> m_measuredDepths;
|
||||
|
||||
@@ -53,10 +53,6 @@ void RigWellPathGeometryExporter::exportWellPathGeometry( gsl::not_null<const Ri
|
||||
{
|
||||
rkbOffset = modeledWellPath->geometryDefinition()->airGap();
|
||||
}
|
||||
else
|
||||
{
|
||||
rkbOffset = modeledWellPath->geometryDefinition()->mdAtFirstTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
exportWellPathGeometry( *wellPathGeom, mdStepSize, rkbOffset, xValues, yValues, tvdValues, mdValues );
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "cvfMath.h"
|
||||
#include "cvfMatrix3.h"
|
||||
|
||||
#include "RiaOffshoreSphericalCoords.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
@@ -133,6 +134,61 @@ std::vector<double> RigWellPathGeometryTools::interpolateMdFromTvd( const std::v
|
||||
return interpolatedMdValues;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::pair<double, double>
|
||||
RigWellPathGeometryTools::calculateAzimuthAndInclinationAtMd( double measuredDepth,
|
||||
gsl::not_null<const RigWellPath*> wellPathGeometry )
|
||||
{
|
||||
int mdIndex = -1;
|
||||
auto mdList = wellPathGeometry->measuredDepths();
|
||||
|
||||
for ( int i = 0; i < (int)mdList.size(); i++ )
|
||||
{
|
||||
if ( mdList[i] > measuredDepth )
|
||||
{
|
||||
mdIndex = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto ptList = wellPathGeometry->wellPathPoints();
|
||||
if ( mdIndex >= 0 && mdIndex < (int)ptList.size() - 1 )
|
||||
{
|
||||
const auto& v2 = cvf::Vec3d( ptList[mdIndex] );
|
||||
const auto& v3 = cvf::Vec3d( ptList[mdIndex + 1] );
|
||||
|
||||
auto v32 = ( v3 - v2 ).getNormalized();
|
||||
|
||||
auto v13mean = v32;
|
||||
|
||||
if ( mdIndex > 0 )
|
||||
{
|
||||
const auto& v1 = cvf::Vec3d( ptList[mdIndex - 1] );
|
||||
auto v21 = ( v2 - v1 ).getNormalized();
|
||||
v13mean = ( v21 + v32 ) / 2;
|
||||
}
|
||||
|
||||
auto v24mean = v32;
|
||||
if ( mdIndex < (int)ptList.size() - 2 )
|
||||
{
|
||||
const auto& v4 = cvf::Vec3d( ptList[mdIndex + 2] );
|
||||
auto v43 = ( v4 - v3 ).getNormalized();
|
||||
v24mean = ( v32 + v43 ) / 2;
|
||||
}
|
||||
|
||||
double weight = ( measuredDepth - mdList[mdIndex] ) / ( mdList[mdIndex + 1] - mdList[mdIndex] );
|
||||
auto vTan = v13mean * ( 1.0 - weight ) + v24mean * ( weight );
|
||||
|
||||
RiaOffshoreSphericalCoords coords( vTan );
|
||||
|
||||
return { coords.azi(), coords.inc() };
|
||||
}
|
||||
|
||||
return { 0.0, 0.0 };
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gsl/gsl>
|
||||
|
||||
class RigWellPath;
|
||||
|
||||
//==================================================================================================
|
||||
@@ -45,6 +47,9 @@ public:
|
||||
const std::vector<double>& originalTvdValues,
|
||||
const std::vector<double>& tvdValuesToInterpolateFrom );
|
||||
|
||||
static std::pair<double, double>
|
||||
calculateAzimuthAndInclinationAtMd( double measuredDepth, gsl::not_null<const RigWellPath*> wellPathGeometry );
|
||||
|
||||
private:
|
||||
static std::vector<cvf::Vec3d> interpolateUndefinedNormals( const cvf::Vec3d& planeNormal,
|
||||
const std::vector<cvf::Vec3d>& normals,
|
||||
|
||||
Reference in New Issue
Block a user