Files
ResInsight/ApplicationLibCode/ProjectDataModel/WellPath/RimFileWellPath.cpp
T
Kristian Bendiksen 74ffc822f2 #14538 Well path: Preserve renamed file well name
The renamed well path name is serialized correctly, but reopening the project reloads the source well path file and overwrites the saved name with the name from that file. The reload flag only protected the completion export name, despite the loader also updating the displayed well path name.

Only initialize the well path and export names from the source file during first import. Subsequent data reloads preserve the names stored in the project while continuing to refresh geometry and metadata.

Add an RMS well round-trip test that renames an imported well, saves and reopens the project, and verifies that the custom name is retained.
2026-08-25 08:25:20 +02:00

241 lines
10 KiB
C++

#include "RimFileWellPath.h"
#include "RicfCommandObject.h"
#include "RifWellPathImporter.h"
#include "RimProject.h"
#include "RimTools.h"
#include "cafUtils.h"
#include <QFileInfo>
CAF_PDM_SOURCE_INIT( RimFileWellPath, "WellPath" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFileWellPath::RimFileWellPath()
{
CAF_PDM_InitScriptableObjectWithNameAndComment( "File Well Path", ":/Well.svg", "", "", "FileWellPath", "Well Paths Loaded From File" );
CAF_PDM_InitFieldNoDefault( &id, "WellPathId", "Id" );
id.uiCapability()->setUiReadOnly( true );
id.xmlCapability()->disableIO();
CAF_PDM_InitFieldNoDefault( &sourceSystem, "SourceSystem", "Source System" );
sourceSystem.uiCapability()->setUiReadOnly( true );
sourceSystem.xmlCapability()->disableIO();
CAF_PDM_InitFieldNoDefault( &utmZone, "UTMZone", "UTM Zone" );
utmZone.uiCapability()->setUiReadOnly( true );
utmZone.xmlCapability()->disableIO();
CAF_PDM_InitFieldNoDefault( &updateDate, "WellPathUpdateDate", "Update Date" );
updateDate.uiCapability()->setUiReadOnly( true );
updateDate.xmlCapability()->disableIO();
CAF_PDM_InitFieldNoDefault( &updateUser, "WellPathUpdateUser", "Update User" );
updateUser.uiCapability()->setUiReadOnly( true );
updateUser.xmlCapability()->disableIO();
CAF_PDM_InitFieldNoDefault( &m_surveyType, "WellPathSurveyType", "Survey Type" );
m_surveyType.uiCapability()->setUiReadOnly( true );
m_surveyType.xmlCapability()->disableIO();
CAF_PDM_InitFieldNoDefault( &m_filePath, "WellPathFilepath", "File Path" );
m_filePath.uiCapability()->setUiReadOnly( true );
// Read-only legacy field used to migrate SSIHUB-cached well paths saved before commit
// bdb46d9df407878f0016ea2c150f44cc07fef698 removed the cache mechanism. See initAfterRead.
CAF_PDM_InitFieldNoDefault( &m_filePathInCache_OBSOLETE, "WellPathFilePathInCache", "File Name" );
m_filePathInCache_OBSOLETE.uiCapability()->setUiHidden( true );
m_filePathInCache_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_wellPathIndexInFile, "WellPathNumberInFile", -1, "Well Number in File" );
m_wellPathIndexInFile.uiCapability()->setUiReadOnly( true );
CAF_PDM_InitField( &m_useAutoGeneratedPointAtSeaLevel, "UseAutoGeneratedPointAtSeaLevel", false, "Generate Point at Sea Level" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFileWellPath::~RimFileWellPath()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimFileWellPath::filePath() const
{
return m_filePath().path();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFileWellPath::setFilepath( const QString& path )
{
m_filePath = path;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimFileWellPath::wellPathIndexInFile() const
{
return m_wellPathIndexInFile();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFileWellPath::setWellPathIndexInFile( int index )
{
m_wellPathIndexInFile = index;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFileWellPath::setSurveyType( QString surveyType )
{
m_surveyType = surveyType;
if ( m_surveyType() == "PLAN" )
setWellPathColor( cvf::Color3f( 0.999f, 0.333f, 0.0f ) );
else if ( m_surveyType() == "PROTOTYPE" )
setWellPathColor( cvf::Color3f( 0.0f, 0.333f, 0.999f ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFileWellPath::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
RimWellPath::defineUiOrdering( uiConfigName, uiOrdering );
uiOrdering.add( &m_useAutoGeneratedPointAtSeaLevel );
caf::PdmUiGroup* fileInfoGroup = uiOrdering.createGroupBeforeGroup( "Simulation Well", "File" );
fileInfoGroup->add( &m_filePath );
fileInfoGroup->add( &m_wellPathIndexInFile );
if ( !id().isEmpty() ) uiOrdering.insertBeforeItem( m_datumElevation.uiCapability(), &id );
if ( !sourceSystem().isEmpty() ) uiOrdering.insertBeforeItem( m_datumElevation.uiCapability(), &sourceSystem );
if ( !utmZone().isEmpty() ) uiOrdering.insertBeforeItem( m_datumElevation.uiCapability(), &utmZone );
if ( !updateDate().isEmpty() ) uiOrdering.insertBeforeItem( m_datumElevation.uiCapability(), &updateDate );
if ( !updateUser().isEmpty() ) uiOrdering.insertBeforeItem( m_datumElevation.uiCapability(), &updateUser );
if ( !m_surveyType().isEmpty() ) uiOrdering.insertBeforeItem( m_datumElevation.uiCapability(), &m_surveyType );
}
//--------------------------------------------------------------------------------------------------
/// Read JSON or ascii file containing well path data
//--------------------------------------------------------------------------------------------------
bool RimFileWellPath::readWellPathFile( QString* errorMessage, RifWellPathImporter* wellPathImporter, bool initializeWellNamesFromFile )
{
if ( caf::Utils::fileExists( filePath() ) )
{
RifWellPathImporter::WellData wellData = wellPathImporter->readWellData( filePath(), m_wellPathIndexInFile() );
RifWellPathImporter::WellMetaData wellMetaData = RifWellPathImporter::readWellMetaData( filePath(), m_wellPathIndexInFile() );
// General well info
if ( initializeWellNamesFromFile )
{
setName( wellData.m_name );
}
id = wellMetaData.m_id;
sourceSystem = wellMetaData.m_sourceSystem;
utmZone = wellMetaData.m_utmZone;
updateUser = wellMetaData.m_updateUser;
setSurveyType( wellMetaData.m_surveyType );
updateDate = wellMetaData.m_updateDate.toString( "d MMMM yyyy" );
if ( m_useAutoGeneratedPointAtSeaLevel )
{
ensureWellPathStartAtSeaLevel( wellData.m_wellPathGeometry.p() );
}
setWellPathGeometry( wellData.m_wellPathGeometry.p() );
return true;
}
else
{
if ( errorMessage ) ( *errorMessage ) = "Could not find the well path file: " + filePath();
return false;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFileWellPath::ensureWellPathStartAtSeaLevel( RigWellPath* wellPath )
{
std::vector<cvf::Vec3d> wellPathPoints = wellPath->wellPathPoints();
std::vector<double> measuredDepths = wellPath->measuredDepths();
if ( wellPathPoints.empty() || measuredDepths.empty() || wellPathPoints.size() != measuredDepths.size() ) return;
cvf::Vec3d firstPoint = wellPathPoints[0];
const double epsilon = 1e-3;
bool firstPointAtSeaLevel = std::abs( firstPoint.z() ) < epsilon;
if ( !firstPointAtSeaLevel )
{
// Insert a new point on sea level straight above the
// first point in the read well path.
std::vector<cvf::Vec3d> newPoints = { cvf::Vec3d( firstPoint.x(), firstPoint.y(), 0.0 ) };
newPoints.insert( newPoints.end(), wellPathPoints.begin(), wellPathPoints.end() );
// Use rkbDiff as MD for the point at sea level
double mdAtSeaLevel = 0.0;
if ( wellPath->datumElevation() > 0.0 )
{
mdAtSeaLevel = wellPath->datumElevation();
}
else if ( airGap() != std::numeric_limits<double>::infinity() && airGap() > 0.0 )
{
mdAtSeaLevel = airGap();
}
std::vector<double> newMeasuredDepths = { mdAtSeaLevel };
newMeasuredDepths.insert( newMeasuredDepths.end(), measuredDepths.begin(), measuredDepths.end() );
wellPath->setWellPathPoints( newPoints, newMeasuredDepths );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFileWellPath::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
{
RimWellPath::fieldChangedByUi( changedField, oldValue, newValue );
if ( changedField == &m_useAutoGeneratedPointAtSeaLevel )
{
RifWellPathImporter wellPathImporter;
QString errorMessage;
if ( readWellPathFile( &errorMessage, &wellPathImporter, false ) )
{
RimProject::current()->scheduleCreateDisplayModelAndRedrawAllViews();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFileWellPath::initAfterRead()
{
RimWellPath::initAfterRead();
QString cachedPath = m_filePathInCache_OBSOLETE().path();
if ( cachedPath.isEmpty() ) return;
QString newCacheFileName = RimTools::getCacheRootDirectoryPathFromProject() + "_wellpaths/" + QFileInfo( cachedPath ).fileName();
if ( caf::Utils::fileExists( newCacheFileName ) )
{
m_filePath = newCacheFileName;
}
}