Well Path Groups

This commit is contained in:
Gaute Lindkvist
2020-10-14 18:55:17 +02:00
parent 5ec3e2a7d7
commit 7684596829
10 changed files with 381 additions and 137 deletions

View File

@@ -62,24 +62,27 @@ QString RiaTextStringTools::trimAndRemoveDoubleSpaces( const QString& s )
//--------------------------------------------------------------------------------------------------
QString RiaTextStringTools::commonRoot( const QStringList& stringList )
{
QString root = stringList.front();
for ( const auto& item : stringList )
QString root;
if ( !stringList.isEmpty() )
{
if ( root.length() > item.length() )
root = stringList.front();
for ( const auto& item : stringList )
{
root.truncate( item.length() );
}
for ( int i = 0; i < root.length(); ++i )
{
if ( root[i] != item[i] )
if ( root.length() > item.length() )
{
root.truncate( i );
break;
root.truncate( item.length() );
}
for ( int i = 0; i < root.length(); ++i )
{
if ( root[i] != item[i] )
{
root.truncate( i );
break;
}
}
}
}
return root;
}

View File

@@ -25,6 +25,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimSimWellInView.h
${CMAKE_CURRENT_LIST_DIR}/RimSimWellInViewCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimSimWellInViewTools.h
${CMAKE_CURRENT_LIST_DIR}/RimWellPath.h
${CMAKE_CURRENT_LIST_DIR}/RimWellPathGroup.h
${CMAKE_CURRENT_LIST_DIR}/RimFileWellPath.h
${CMAKE_CURRENT_LIST_DIR}/RimModeledWellPath.h
${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurement.h
@@ -205,6 +206,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimSimWellInView.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSimWellInViewCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSimWellInViewTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellPath.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellPathGroup.cpp
${CMAKE_CURRENT_LIST_DIR}/RimFileWellPath.cpp
${CMAKE_CURRENT_LIST_DIR}/RimModeledWellPath.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurement.cpp

View File

@@ -127,8 +127,6 @@ RimWellPath::RimWellPath()
m_wellPathAttributes = new RimWellPathAttributeCollection;
m_wellPathAttributes->uiCapability()->setUiTreeHidden( true );
CAF_PDM_InitFieldNoDefault( &m_childWellPaths, "ChildWellPaths", "Child Well Paths", "", "", "" );
this->setDeletable( true );
}
@@ -363,54 +361,6 @@ double RimWellPath::endMD() const
return std::numeric_limits<double>::infinity();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPath::addChildWellPath( RimWellPath* wellPath )
{
m_childWellPaths.push_back( wellPath );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimWellPath*> RimWellPath::childWellPaths() const
{
return m_childWellPaths.childObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RimWellPath::childWellpathCount() const
{
return m_childWellPaths.size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellPath::hasChildWellPath( RimWellPath* wellPath )
{
return m_childWellPaths.count( wellPath ) != 0u;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPath::removeChildWellPath( RimWellPath* wellPath )
{
m_childWellPaths.removeChildObject( wellPath );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPath::removeAllChildWellPaths()
{
m_childWellPaths.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -681,14 +631,6 @@ void RimWellPath::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering,
uiTreeOrdering.add( m_wellPathAttributes() );
}
for ( auto child : m_childWellPaths() )
{
if ( child )
{
uiTreeOrdering.add( child );
}
}
uiTreeOrdering.skipRemainingChildren( true );
}

View File

@@ -97,13 +97,6 @@ public:
double startMD() const override;
double endMD() const override;
void addChildWellPath( RimWellPath* wellPath );
std::vector<RimWellPath*> childWellPaths() const;
size_t childWellpathCount() const;
bool hasChildWellPath( RimWellPath* wellPath );
void removeChildWellPath( RimWellPath* wellPath );
void removeAllChildWellPaths();
void addWellLogFile( RimWellLogFile* logFileInfo );
void deleteWellLogFile( RimWellLogFile* logFileInfo );
void detachWellLogFile( RimWellLogFile* logFileInfo );
@@ -190,8 +183,6 @@ private:
caf::PdmChildField<RimWellPathCompletions*> m_completions;
caf::PdmChildField<RimWellPathAttributeCollection*> m_wellPathAttributes;
caf::PdmChildArrayField<RimWellPath*> m_childWellPaths;
private:
static size_t simulationWellBranchCount( const QString& simWellName );

View File

@@ -43,6 +43,7 @@
#include "RimWellLogFile.h"
#include "RimWellMeasurementCollection.h"
#include "RimWellPath.h"
#include "RimWellPathGroup.h"
#include "Riu3DMainWindowTools.h"
#include "RifWellPathFormationsImporter.h"
@@ -52,6 +53,7 @@
#include "cafPdmUiTreeOrdering.h"
#include "cafProgressInfo.h"
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QString>
@@ -190,6 +192,7 @@ void RimWellPathCollection::loadDataAndUpdate()
progress.incrementProgress();
}
this->checkAndFixBranchNames();
this->sortWellsByName();
}
@@ -267,18 +270,13 @@ std::vector<RimWellPath*>
//--------------------------------------------------------------------------------------------------
void RimWellPathCollection::addWellPath( gsl::not_null<RimWellPath*> wellPath, bool importGrouped )
{
RimWellPath* mainWellPath = nullptr;
RimWellPathGroup* wellPathGroup = nullptr;
if ( importGrouped )
{
mainWellPath = findSuitableParentWellPath( wellPath );
wellPathGroup = findOrCreateWellPathGroup( wellPath );
}
if ( mainWellPath )
{
mainWellPath->addChildWellPath( wellPath );
createWellPathBranchFromExistingWellPath( mainWellPath );
}
else
if ( !wellPathGroup )
{
m_wellPaths.push_back( wellPath );
}
@@ -341,9 +339,24 @@ void RimWellPathCollection::readAndAddWellPaths( std::vector<RimFileWellPath*>&
progress.incrementProgress();
}
wellPathArray.clear(); // This should not be used again. We may have deleted items
this->checkAndFixBranchNames();
this->sortWellsByName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathCollection::checkAndFixBranchNames()
{
for ( auto wellPath : m_wellPaths )
{
if ( auto group = dynamic_cast<RimWellPathGroup*>( wellPath.p() ); group )
{
group->fixBranchNames();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -353,6 +366,7 @@ void RimWellPathCollection::addWellPaths( const std::vector<RimWellPath*> incomi
{
addWellPath( wellPath, importGrouped );
}
this->checkAndFixBranchNames();
this->sortWellsByName();
updateAllRequiredEditors();
@@ -389,6 +403,7 @@ std::vector<RimWellLogFile*> RimWellPathCollection::addWellLogs( const QStringLi
}
}
this->checkAndFixBranchNames();
this->sortWellsByName();
updateAllRequiredEditors();
@@ -441,6 +456,7 @@ void RimWellPathCollection::addWellPathFormations( const QStringList& filePaths
RiaLogging::errorInMessageBox( Riu3DMainWindowTools::mainWindowWidget(), "Well Picks Import", outputMessage );
}
this->checkAndFixBranchNames();
this->sortWellsByName();
updateAllRequiredEditors();
}
@@ -653,9 +669,10 @@ void RimWellPathCollection::removeWellPath( RimWellPath* wellPath )
{
for ( auto possibleParentWellPath : allWellPaths() )
{
if ( possibleParentWellPath->hasChildWellPath( wellPath ) )
auto wellPathGroup = dynamic_cast<RimWellPathGroup*>( possibleParentWellPath );
if ( wellPathGroup->hasChildWellPath( wellPath ) )
{
possibleParentWellPath->removeChildWellPath( wellPath );
wellPathGroup->removeChildWellPath( wellPath );
removed = true;
break;
}
@@ -712,58 +729,57 @@ void RimWellPathCollection::sortWellsByName()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathCollection::createWellPathBranchFromExistingWellPath( RimWellPath* wellPath )
{
if ( wellPath->childWellpathCount() > 0u )
{
auto childCopy = static_cast<RimWellPath*>(
wellPath->xmlCapability()->copyByXmlSerialization( caf::PdmDefaultObjectFactory::instance() ) );
childCopy->setWellPathGeometry( wellPath->wellPathGeometry() );
wellPath->setWellPathGeometry( nullptr );
childCopy->removeAllChildWellPaths();
wellPath->addChildWellPath( childCopy );
std::vector<const RigWellPath*> allGeometries;
QStringList allNames;
for ( const auto& childWellPath : wellPath->childWellPaths() )
{
allGeometries.push_back( childWellPath->wellPathGeometry() );
allNames.push_back( childWellPath->name() );
}
cvf::ref<RigWellPath> commonGeometry = new RigWellPath( RigWellPath::commonGeometry( allGeometries ) );
QString commonName = RiaTextStringTools::commonRoot( allNames );
QString trimmedCommonName = RiaTextStringTools::trimNonAlphaNumericCharacters( commonName );
wellPath->setWellPathGeometry( commonGeometry.p() );
wellPath->setName( trimmedCommonName );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPath* RimWellPathCollection::findSuitableParentWellPath( gsl::not_null<const RimWellPath*> wellPath ) const
RimWellPathGroup* RimWellPathCollection::findOrCreateWellPathGroup( gsl::not_null<RimWellPath*> wellPath )
{
auto wellPathGeometry = wellPath->wellPathGeometry();
if ( !wellPathGeometry ) return nullptr;
const double eps = 1.0e-4;
double maxIdenticalTubeLength = 0.0;
RimWellPath* maxIdenticalWellPath = nullptr;
qDebug() << wellPath->name();
const double eps = 1.0e-4;
std::map<RimWellPath*, double> wellPathsWithCommonGeometry;
for ( auto existingWellPath : allWellPaths() )
{
double identicalTubeLength = existingWellPath->wellPathGeometry()->identicalTubeLength( *wellPathGeometry );
if ( identicalTubeLength > maxIdenticalTubeLength && identicalTubeLength > eps )
if ( identicalTubeLength > eps )
{
maxIdenticalTubeLength = identicalTubeLength;
maxIdenticalWellPath = existingWellPath;
wellPathsWithCommonGeometry[existingWellPath] = identicalTubeLength;
}
}
return maxIdenticalWellPath;
// See if we have a well path group
RimWellPathGroup* mostSimilarWellPathGroup = nullptr;
double longestIdenticalTubeLength = 0.0;
for ( auto [existingWellPath, identicalTubeLength] : wellPathsWithCommonGeometry )
{
auto wellPathGroup = dynamic_cast<RimWellPathGroup*>( existingWellPath );
if ( wellPathGroup && identicalTubeLength > longestIdenticalTubeLength )
{
mostSimilarWellPathGroup = wellPathGroup;
longestIdenticalTubeLength = identicalTubeLength;
}
}
if ( mostSimilarWellPathGroup )
{
mostSimilarWellPathGroup->addChildWellPath( wellPath.get() );
}
else if ( !wellPathsWithCommonGeometry.empty() )
{
RimWellPathGroup* group = new RimWellPathGroup;
m_wellPaths.push_back( group );
for ( auto [existingWellPath, identicalTubeLength] : wellPathsWithCommonGeometry )
{
removeWellPath( existingWellPath );
group->addChildWellPath( existingWellPath );
}
group->addChildWellPath( wellPath );
mostSimilarWellPathGroup = group;
}
return mostSimilarWellPathGroup;
}
//--------------------------------------------------------------------------------------------------

View File

@@ -45,6 +45,7 @@ class RimEclipseView;
class RimProject;
class RimWellLogFile;
class RimWellPath;
class RimWellPathGroup;
class RifWellPathFormationsImporter;
class RimWellMeasurementCollection;
class QString;
@@ -134,11 +135,11 @@ private:
caf::PdmFieldHandle* objectToggleField() override;
void checkAndFixBranchNames();
void readAndAddWellPaths( std::vector<RimFileWellPath*>& wellPathArray, bool importGrouped );
void sortWellsByName();
void createWellPathBranchFromExistingWellPath( RimWellPath* wellPath );
RimWellPath* findSuitableParentWellPath( gsl::not_null<const RimWellPath*> wellPath ) const;
RimWellPathGroup* findOrCreateWellPathGroup( gsl::not_null<RimWellPath*> wellPath );
RiaEclipseUnitTools::UnitSystemType findUnitSystemForWellPath( const RimWellPath* wellPath );

View File

@@ -0,0 +1,239 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020- 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimWellPathGroup.h"
#include "RiaTextStringTools.h"
#include "RigWellPath.h"
#include "cafPdmUiTreeOrdering.h"
#include <QStringList>
CAF_PDM_SOURCE_INIT( RimWellPathGroup, "WellPathGroup" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPathGroup::RimWellPathGroup()
{
CAF_PDM_InitScriptableObjectWithNameAndComment( "Well Path Group", ":/Well.png", "", "", "WellPathGroup", "A Group of Well Paths" );
CAF_PDM_InitFieldNoDefault( &m_childWellPaths, "ChildWellPaths", "Child Well Paths", "", "", "" );
setWellPathGeometry( new RigWellPath );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathGroup::addChildWellPath( RimWellPath* wellPath )
{
if ( !this->wellPathGeometry()->wellPathPoints().empty() )
{
auto commonGeometry = RigWellPath::commonGeometry( {this->wellPathGeometry(), wellPath->wellPathGeometry()} );
setWellPathGeometry( commonGeometry.p() );
m_childWellPaths.push_back( wellPath );
makeMoreLevelsIfNecessary();
}
else
{
cvf::ref<RigWellPath> geometryCopy( new RigWellPath( *( wellPath->wellPathGeometry() ) ) );
setWellPathGeometry( geometryCopy.p() );
m_childWellPaths.push_back( wellPath );
}
updateWellPathName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimWellPath*> RimWellPathGroup::childWellPaths() const
{
return m_childWellPaths.childObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RimWellPathGroup::childWellpathCount() const
{
return m_childWellPaths.size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellPathGroup::hasChildWellPath( RimWellPath* wellPath )
{
return m_childWellPaths.count( wellPath ) != 0u;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathGroup::removeChildWellPath( RimWellPath* wellPath )
{
m_childWellPaths.removeChildObject( wellPath );
auto commonGeometry = RigWellPath::commonGeometry( wellPathGeometries() );
setWellPathGeometry( commonGeometry.p() );
updateWellPathName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathGroup::removeAllChildWellPaths()
{
m_childWellPaths.clear();
auto commonGeometry = RigWellPath::commonGeometry( wellPathGeometries() );
setWellPathGeometry( commonGeometry.p() );
updateWellPathName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathGroup::fixBranchNames()
{
const auto& measuredDepths = this->wellPathGeometry()->measuredDepths();
int index = 1;
for ( auto wellPath : m_childWellPaths )
{
auto group = dynamic_cast<RimWellPathGroup*>( wellPath.p() );
if ( group )
{
group->fixBranchNames();
if ( group->name() == this->name() )
{
QString groupName = QString( "%1 branch #%2" ).arg( this->name() ).arg( index++ );
if ( !measuredDepths.empty() )
{
groupName += QString( " at md=%1" ).arg( measuredDepths.back() );
}
group->setName( groupName );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathGroup::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
{
for ( auto child : m_childWellPaths() )
{
if ( child )
{
uiTreeOrdering.add( child );
}
}
uiTreeOrdering.skipRemainingChildren( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<const RigWellPath*> RimWellPathGroup::wellPathGeometries() const
{
std::vector<const RigWellPath*> allGeometries;
for ( const auto child : m_childWellPaths() )
{
allGeometries.push_back( child->wellPathGeometry() );
}
return allGeometries;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathGroup::updateWellPathName()
{
auto autoName = createWellPathName();
setName( autoName );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellPathGroup::createWellPathName() const
{
QStringList allNames;
for ( auto wellPath : m_childWellPaths )
{
allNames.push_back( wellPath->name() );
}
QString commonName = RiaTextStringTools::commonRoot( allNames );
QString trimmedCommonName = RiaTextStringTools::trimNonAlphaNumericCharacters( commonName );
return trimmedCommonName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathGroup::makeMoreLevelsIfNecessary()
{
if ( m_childWellPaths.size() <= 1u ) return;
auto wellPathPoints = this->wellPathGeometry()->wellPathPoints();
auto comp = []( const cvf::Vec3d& lhs, const cvf::Vec3d& rhs ) {
auto diff = rhs - lhs;
if ( diff.length() < 1.0e-8 ) return false;
if ( diff.z() == 0.0 )
{
if ( diff.y() == 0.0 )
{
return diff.x() > 0.0;
}
return diff.y() > 0.0;
}
return diff.z() > 0.0;
};
auto branches = std::map<cvf::Vec3d, std::vector<RimWellPath*>, decltype( comp )>( comp );
for ( auto wellPath : m_childWellPaths )
{
auto childWellPathPoints = wellPath->wellPathGeometry()->wellPathPoints();
if ( childWellPathPoints.size() > wellPathPoints.size() )
{
cvf::Vec3d firstDeviation = childWellPathPoints[wellPathPoints.size()];
branches[firstDeviation].push_back( wellPath );
}
}
if ( branches.size() <= 1u ) return;
for ( const auto& [firstDeviation, wellPaths] : branches )
{
if ( wellPaths.size() > 1u )
{
RimWellPathGroup* newGroup = new RimWellPathGroup;
for ( auto wellPath : wellPaths )
{
m_childWellPaths().removeChildObject( wellPath );
newGroup->addChildWellPath( wellPath );
}
m_childWellPaths().push_back( newGroup );
}
}
}

View File

@@ -0,0 +1,50 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020- 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimWellPath.h"
#include <QString>
class RimWellPathGroup : public RimWellPath
{
CAF_PDM_HEADER_INIT;
public:
RimWellPathGroup();
void addChildWellPath( RimWellPath* wellPath );
std::vector<RimWellPath*> childWellPaths() const;
size_t childWellpathCount() const;
bool hasChildWellPath( RimWellPath* wellPath );
void removeChildWellPath( RimWellPath* wellPath );
void removeAllChildWellPaths();
void fixBranchNames();
void makeMoreLevelsIfNecessary();
protected:
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName );
private:
std::vector<const RigWellPath*> wellPathGeometries() const;
void updateWellPathName();
QString createWellPathName() const;
private:
caf::PdmChildArrayField<RimWellPath*> m_childWellPaths;
};

View File

@@ -374,14 +374,14 @@ double RigWellPath::identicalTubeLength( const RigWellPath& other ) const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigWellPath RigWellPath::commonGeometry( const std::vector<const RigWellPath*>& allGeometries )
cvf::ref<RigWellPath> RigWellPath::commonGeometry( const std::vector<const RigWellPath*>& allGeometries )
{
const double eps = 1.0e-8;
if ( allGeometries.empty() )
return RigWellPath();
return nullptr;
else if ( allGeometries.size() == 1u )
return *allGeometries.front();
return cvf::ref<RigWellPath>( new RigWellPath( *allGeometries.front() ) );
const RigWellPath* firstGeometry = allGeometries.front();
@@ -410,7 +410,7 @@ RigWellPath RigWellPath::commonGeometry( const std::vector<const RigWellPath*>&
break;
}
}
return RigWellPath( commonWellPathPoints, commonMDs );
return cvf::ref<RigWellPath>( new RigWellPath( commonWellPathPoints, commonMDs ) );
}
//--------------------------------------------------------------------------------------------------

View File

@@ -70,7 +70,7 @@ public:
void twoClosestPoints( const cvf::Vec3d& position, cvf::Vec3d* p1, cvf::Vec3d* p2 ) const;
double identicalTubeLength( const RigWellPath& otherWellPathGeometry ) const;
static RigWellPath commonGeometry( const std::vector<const RigWellPath*>& allGeometries );
static cvf::ref<RigWellPath> commonGeometry( const std::vector<const RigWellPath*>& allGeometries );
std::pair<std::vector<cvf::Vec3d>, std::vector<double>>
clippedPointSubset( double startMD, double endMD, double* horizontalLengthAlongWellToStartClipPoint = nullptr ) const;