Files
ResInsight/ApplicationLibCode/ReservoirDataModel/Well/RigWellPathFormations.cpp
T
Magne Sjaastad 93bd0b9c9d Refactor well log track settings into modular classes
* Refactor well log track settings into modular classes

Major refactoring of RimWellLogTrack to delegate property axis, formation, region annotation, and well path attribute settings to dedicated settings classes. Introduces RimWellLogPropertyAxisSettings, RimWellLogFormationSettings, RimWellLogRegionAnnotationSettings, and RimWellLogWellPathAttributeSettings, each encapsulating related fields, UI logic, and option handling. Old fields are retained for migration and backward compatibility. Updates enums and signatures for consistency.
2026-02-09 15:33:18 +01:00

404 lines
15 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017- Statoil 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.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RigWellPathFormations.h"
#include "QStringList"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigWellPathFormations::RigWellPathFormations( const std::vector<RigWellPathFormation>& formations, const QString& filePath, const QString& key )
{
m_filePath = filePath;
m_keyInFile = key;
for ( const RigWellPathFormation& formation : formations )
{
if ( isFluid( formation.formationName ) )
{
m_fluids.push_back( formation );
}
else
{
FormationLevel level = detectLevel( formation.formationName );
m_formationsLevelsPresent[level] = true;
m_formations.push_back( std::pair<RigWellPathFormation, FormationLevel>( formation, level ) );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellPathFormations::depthAndFormationNamesWithoutDuplicatesOnDepth( std::vector<QString>* names,
std::vector<double>* measuredDepths,
RiaDefines::DepthType depthType ) const
{
std::map<double, bool, DepthComp> tempMakeVectorUniqueOnMeasuredDepth;
if ( depthType == RiaDefines::DepthType::MEASURED_DEPTH )
{
for ( const std::pair<RigWellPathFormation, FormationLevel>& formation : m_formations )
{
if ( !tempMakeVectorUniqueOnMeasuredDepth.count( formation.first.mdTop ) )
{
measuredDepths->push_back( formation.first.mdTop );
names->push_back( formation.first.formationName + " Top" );
tempMakeVectorUniqueOnMeasuredDepth[formation.first.mdTop] = true;
}
}
for ( const std::pair<RigWellPathFormation, FormationLevel>& formation : m_formations )
{
if ( !tempMakeVectorUniqueOnMeasuredDepth.count( formation.first.mdBase ) )
{
measuredDepths->push_back( formation.first.mdBase );
names->push_back( formation.first.formationName + " Base" );
tempMakeVectorUniqueOnMeasuredDepth[formation.first.mdBase] = true;
}
}
}
else if ( depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH )
{
for ( const std::pair<RigWellPathFormation, FormationLevel>& formation : m_formations )
{
if ( !tempMakeVectorUniqueOnMeasuredDepth.count( formation.first.tvdTop ) )
{
measuredDepths->push_back( formation.first.tvdTop );
names->push_back( formation.first.formationName + " Top" );
tempMakeVectorUniqueOnMeasuredDepth[formation.first.tvdTop] = true;
}
}
for ( const std::pair<RigWellPathFormation, FormationLevel>& formation : m_formations )
{
if ( !tempMakeVectorUniqueOnMeasuredDepth.count( formation.first.tvdBase ) )
{
measuredDepths->push_back( formation.first.tvdBase );
names->push_back( formation.first.formationName + " Base" );
tempMakeVectorUniqueOnMeasuredDepth[formation.first.tvdBase] = true;
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellPathFormations::evaluateFormationsForOnePosition( const std::vector<std::pair<RigWellPathFormation, FormationLevel>>& formations,
const FormationLevel& maxLevel,
const PickPosition& position,
std::map<double, LevelAndName, DepthComp>* uniqueListMaker,
RiaDefines::DepthType depthType ) const
{
QString postFix;
if ( position == TOP )
{
postFix = " Top";
}
else
{
postFix = " Base";
}
for ( const std::pair<RigWellPathFormation, FormationLevel>& formation : formations )
{
double depth;
if ( depthType == RiaDefines::DepthType::MEASURED_DEPTH )
{
if ( position == TOP )
{
depth = formation.first.mdTop;
}
else
{
depth = formation.first.mdBase;
}
}
else if ( depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH )
{
if ( position == TOP )
{
depth = formation.first.tvdTop;
}
else
{
depth = formation.first.tvdBase;
}
}
else
return;
if ( formation.second > maxLevel ) continue;
if ( !uniqueListMaker->count( depth ) || uniqueListMaker->at( depth ).level < formation.second )
{
( *uniqueListMaker )[depth] = LevelAndName( formation.second, formation.first.formationName + postFix );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellPathFormations::evaluateFormations( const std::vector<std::pair<RigWellPathFormation, FormationLevel>>& formations,
const FormationLevel& maxLevel,
std::vector<QString>* names,
std::vector<double>* depths,
RiaDefines::DepthType depthType ) const
{
std::map<double, LevelAndName, DepthComp> tempMakeVectorUniqueOnDepth;
evaluateFormationsForOnePosition( formations, maxLevel, PickPosition::TOP, &tempMakeVectorUniqueOnDepth, depthType );
evaluateFormationsForOnePosition( formations, maxLevel, PickPosition::BASE, &tempMakeVectorUniqueOnDepth, depthType );
for ( const std::pair<const double, LevelAndName>& uniqueDepth : tempMakeVectorUniqueOnDepth )
{
depths->push_back( uniqueDepth.first );
names->push_back( uniqueDepth.second.name );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellPathFormations::evaluateFluids( const std::vector<RigWellPathFormation>& fluidFormations,
std::vector<QString>* names,
std::vector<double>* depths,
RiaDefines::DepthType depthType ) const
{
std::map<double, QString, DepthComp> uniqueListMaker;
for ( const RigWellPathFormation& formation : fluidFormations )
{
double depthBase;
if ( depthType == RiaDefines::DepthType::MEASURED_DEPTH )
{
depthBase = formation.mdBase;
}
else if ( depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH )
{
depthBase = formation.tvdBase;
}
else
return;
uniqueListMaker[depthBase] = formation.formationName + " Base";
}
for ( const RigWellPathFormation& formation : fluidFormations )
{
double depthTop;
if ( depthType == RiaDefines::DepthType::MEASURED_DEPTH )
{
depthTop = formation.mdTop;
}
else if ( depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH )
{
depthTop = formation.tvdTop;
}
else
return;
uniqueListMaker[depthTop] = formation.formationName + " Top";
}
for ( const std::pair<const double, QString>& depthAndFormation : uniqueListMaker )
{
depths->push_back( depthAndFormation.first );
names->push_back( depthAndFormation.second );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellPathFormations::depthAndFormationNamesUpToLevel( FormationLevel level,
std::vector<QString>* names,
std::vector<double>* depths,
bool includeFluids,
RiaDefines::DepthType depthType ) const
{
names->clear();
depths->clear();
if ( includeFluids )
{
evaluateFluids( m_fluids, names, depths, depthType );
}
if ( level == FormationLevel::NONE )
{
return;
}
else if ( level == FormationLevel::ALL )
{
depthAndFormationNamesWithoutDuplicatesOnDepth( names, depths, depthType );
}
else
{
evaluateFormations( m_formations, level, names, depths, depthType );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigWellPathFormations::FormationLevel> RigWellPathFormations::formationsLevelsPresent() const
{
std::vector<RigWellPathFormations::FormationLevel> formationLevels;
for ( const std::pair<const RigWellPathFormations::FormationLevel, bool>& formationLevel : m_formationsLevelsPresent )
{
formationLevels.push_back( formationLevel.first );
}
return formationLevels;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RigWellPathFormations::filePath() const
{
return m_filePath;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RigWellPathFormations::keyInFile() const
{
return m_keyInFile;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RigWellPathFormations::formationNamesCount() const
{
return m_formations.size() + m_fluids.size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigWellPathFormations::isFluid( QString formationName )
{
formationName = formationName.trimmed();
return formationName == "OIL" || formationName == "GAS" || formationName == "WATER";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigWellPathFormations::FormationLevel RigWellPathFormations::detectLevel( QString formationName )
{
formationName = formationName.trimmed();
bool isGroupName = true;
for ( QChar c : formationName )
{
if ( c.isLower() )
{
isGroupName = false;
break;
}
}
if ( isGroupName )
{
return FormationLevel::GROUP;
}
QStringList formationNameSplitted = formationName.split( " " );
std::vector<QString> levelDesctiptorCandidates;
for ( QString word : formationNameSplitted )
{
for ( const QChar& c : word )
{
if ( c.isDigit() )
{
levelDesctiptorCandidates.push_back( word );
break;
}
}
}
if ( levelDesctiptorCandidates.empty() )
{
return FormationLevel::LEVEL0;
}
if ( levelDesctiptorCandidates.size() > 1 )
{
for ( auto it = levelDesctiptorCandidates.begin(); it != levelDesctiptorCandidates.end(); it++ )
{
for ( const QChar& c : *it )
{
if ( c.isLetter() )
{
levelDesctiptorCandidates.erase( it );
}
}
}
}
if ( levelDesctiptorCandidates.size() != 1 ) return FormationLevel::UNKNOWN;
QString levelDescriptor = levelDesctiptorCandidates[0];
QStringList joinedLevel = levelDescriptor.split( '+' );
if ( joinedLevel.size() > 1 )
{
levelDescriptor = joinedLevel[0];
}
int dotCount = levelDescriptor.count( '.' );
switch ( dotCount )
{
case 0:
return FormationLevel::LEVEL1;
case 1:
return FormationLevel::LEVEL2;
case 2:
return FormationLevel::LEVEL3;
case 3:
return FormationLevel::LEVEL4;
case 4:
return FormationLevel::LEVEL5;
case 5:
return FormationLevel::LEVEL6;
case 6:
return FormationLevel::LEVEL7;
case 7:
return FormationLevel::LEVEL8;
case 8:
return FormationLevel::LEVEL9;
case 9:
return FormationLevel::LEVEL10;
default:
break;
}
return FormationLevel::UNKNOWN;
}