Files
ResInsight/ApplicationLibCode/ProjectDataModel/Completions/RimCustomSegmentIntervalCollection.cpp
T
Kristian Bendiksen a71fb9ad19 #13398 Python: Add API for custom well path segments
Add Python GRPC interface support for creating and managing custom segment
intervals for multi-segment wells. This provides API parity with the existing
GUI functionality.

Changes:
- Add createInterval() method to RimCustomSegmentIntervalCollection
- Add GRPC method addCustomSegmentInterval to RimcWellPathCompletionSettings
- Add validation to prevent creating intervals with start_md >= end_md
- Add Python test test_custom_segment_intervals.py with validation test
- Add usage example to modeled_well_path.py

Follows the pattern established by diameter roughness intervals.

Fixes #13398.
2026-01-13 10:44:55 +01:00

118 lines
4.7 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2025 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.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimCustomSegmentIntervalCollection.h"
#include "cafCmdFeatureMenuBuilder.h"
CAF_PDM_SOURCE_INIT( RimCustomSegmentIntervalCollection, "CustomSegmentIntervalCollection" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCustomSegmentIntervalCollection::RimCustomSegmentIntervalCollection()
{
CAF_PDM_InitObject( "Custom Segment Intervals", ":/WellPathComponent16x16.png" );
CAF_PDM_InitFieldNoDefault( &m_items, "Intervals", "Intervals" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCustomSegmentIntervalCollection::~RimCustomSegmentIntervalCollection()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCustomSegmentInterval* RimCustomSegmentIntervalCollection::createInterval( double startMD, double endMD )
{
auto* interval = new RimCustomSegmentInterval();
interval->setStartMD( startMD );
interval->setEndMD( endMD );
addInterval( interval );
return interval;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::map<QString, QString> RimCustomSegmentIntervalCollection::validate( const QString& configName ) const
{
// First validate all fields using base implementation
auto errors = PdmObject::validate( configName );
QStringList validationIssues;
// Validate each child interval
for ( const auto* interval : intervals() )
{
if ( interval )
{
// Get validation errors from the interval itself
auto intervalErrors = interval->validate( configName );
for ( const auto& [field, errorMsg] : intervalErrors )
{
validationIssues.append( QString( "Interval (%1): %2." ).arg( interval->generateDisplayLabel() ).arg( errorMsg ) );
}
}
}
// Check for overlaps between intervals
for ( size_t i = 0; i < intervals().size(); ++i )
{
for ( size_t j = i + 1; j < intervals().size(); ++j )
{
RimCustomSegmentInterval* intervalI = intervals()[i];
RimCustomSegmentInterval* intervalJ = intervals()[j];
if ( intervalI && intervalJ && intervalI->overlaps( intervalJ ) )
{
validationIssues.append( QString( "Interval (%1) overlaps with another interval (%2)." )
.arg( intervalI->generateDisplayLabel() )
.arg( intervalJ->generateDisplayLabel() ) );
}
}
}
// If there are any validation issues, combine them into a single error message
if ( !validationIssues.isEmpty() )
{
errors["Intervals"] = validationIssues.join( "\n" );
}
return errors;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCustomSegmentIntervalCollection::defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu,
QMenu* menu,
QWidget* fieldEditorWidget )
{
caf::CmdFeatureMenuBuilder menuBuilder;
menuBuilder << "RicNewCustomSegmentIntervalFeature";
menuBuilder << "Separator";
menuBuilder << "RicDeleteCustomSegmentIntervalFeature";
menuBuilder.appendToMenu( menu );
}