Seismic support improvments (#10086)

Adds support for creating seismic sections from well paths and existing intersections.
Adds more stability and user improvements
This commit is contained in:
jonjenssen 2023-04-13 13:18:34 +02:00 committed by GitHub
parent 952e766c2f
commit 2e955f2875
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 576 additions and 103 deletions

View File

@ -26,9 +26,10 @@ template <>
void caf::AppEnum<RiaDefines::SeismicSectionType>::setUp()
{
addItem( RiaDefines::SeismicSectionType::SS_INLINE, "SS_INLINE", "Inline" );
addItem( RiaDefines::SeismicSectionType::SS_XLINE, "SS_XLINE", "Crossline" );
addItem( RiaDefines::SeismicSectionType::SS_XLINE, "SS_XLINE", "Xline" );
addItem( RiaDefines::SeismicSectionType::SS_DEPTHSLICE, "SS_DEPTHSLICE", "Depth Slice" );
addItem( RiaDefines::SeismicSectionType::SS_POLYLINE, "SS_POLYLINE", "Polyline" );
addItem( RiaDefines::SeismicSectionType::SS_WELLPATH, "SS_WELLPATH", "Well Path" );
setDefault( RiaDefines::SeismicSectionType::SS_INLINE );
}
} // namespace caf

View File

@ -32,7 +32,8 @@ enum class SeismicSectionType
SS_INLINE,
SS_XLINE,
SS_DEPTHSLICE,
SS_POLYLINE
SS_POLYLINE,
SS_WELLPATH
};
}; // namespace RiaDefines

View File

@ -5,6 +5,8 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RicNewZSliceSeismicSectionFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicSeismicSectionFeatureImpl.h
${CMAKE_CURRENT_LIST_DIR}/RicNewPolylineSeismicSectionFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewWellpathSeismicSectionFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicSeismicSectionFromIntersectionFeature.h
)
set(SOURCE_GROUP_SOURCE_FILES
@ -14,6 +16,8 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RicNewZSliceSeismicSectionFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicSeismicSectionFeatureImpl.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewPolylineSeismicSectionFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewWellpathSeismicSectionFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicSeismicSectionFromIntersectionFeature.cpp
)
list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})

View File

@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020- Equinor ASA
// Copyright (C) 2023 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
@ -17,16 +17,9 @@
/////////////////////////////////////////////////////////////////////////////////
#include "RicNewInlineSeismicSectionFeature.h"
#include "RicSeismicSectionFeatureImpl.h"
#include "RimGridView.h"
#include "RimSeismicSection.h"
#include "RimSeismicSectionCollection.h"
#include "Riu3DMainWindowTools.h"
#include "cafSelectionManagerTools.h"
#include "cafUtils.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicNewInlineSeismicSectionFeature, "RicNewInlineSeismicSectionFeature" );
@ -44,7 +37,7 @@ bool RicNewInlineSeismicSectionFeature::isCommandEnabled()
//--------------------------------------------------------------------------------------------------
void RicNewInlineSeismicSectionFeature::onActionTriggered( bool isChecked )
{
RicSeismicSectionFeatureImpl::createSeismicSection( "Inline", RiaDefines::SeismicSectionType::SS_INLINE );
RicSeismicSectionFeatureImpl::createSeismicSection( RiaDefines::SeismicSectionType::SS_INLINE );
}
//--------------------------------------------------------------------------------------------------

View File

@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020- Equinor ASA
// Copyright (C) 2023 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
@ -17,16 +17,9 @@
/////////////////////////////////////////////////////////////////////////////////
#include "RicNewPolylineSeismicSectionFeature.h"
#include "RicSeismicSectionFeatureImpl.h"
#include "RimGridView.h"
#include "RimSeismicSection.h"
#include "RimSeismicSectionCollection.h"
#include "Riu3DMainWindowTools.h"
#include "cafSelectionManagerTools.h"
#include "cafUtils.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicNewPolylineSeismicSectionFeature, "RicNewPolylineSeismicSectionFeature" );
@ -44,7 +37,7 @@ bool RicNewPolylineSeismicSectionFeature::isCommandEnabled()
//--------------------------------------------------------------------------------------------------
void RicNewPolylineSeismicSectionFeature::onActionTriggered( bool isChecked )
{
RicSeismicSectionFeatureImpl::createSeismicSection( "Polyline Section", RiaDefines::SeismicSectionType::SS_POLYLINE );
RicSeismicSectionFeatureImpl::createSeismicSection( RiaDefines::SeismicSectionType::SS_POLYLINE );
}
//--------------------------------------------------------------------------------------------------

View File

@ -0,0 +1,50 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023 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 "RicNewWellpathSeismicSectionFeature.h"
#include "RicSeismicSectionFeatureImpl.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicNewWellpathSeismicSectionFeature, "RicNewWellpathSeismicSectionFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicNewWellpathSeismicSectionFeature::isCommandEnabled()
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewWellpathSeismicSectionFeature::onActionTriggered( bool isChecked )
{
RicSeismicSectionFeatureImpl::createSeismicSection( RiaDefines::SeismicSectionType::SS_WELLPATH );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewWellpathSeismicSectionFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setIcon( QIcon( ":/Seismic16x16.png" ) );
actionToSetup->setText( "New Well Path Section" );
}

View File

@ -0,0 +1,34 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023 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 "cafCmdFeature.h"
//==================================================================================================
///
//==================================================================================================
class RicNewWellpathSeismicSectionFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
bool isCommandEnabled() override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
};

View File

@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020- Equinor ASA
// Copyright (C) 2023 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
@ -17,6 +17,7 @@
/////////////////////////////////////////////////////////////////////////////////
#include "RicNewXlineSeismicSectionFeature.h"
#include "RicSeismicSectionFeatureImpl.h"
#include <QAction>
@ -36,7 +37,7 @@ bool RicNewXlineSeismicSectionFeature::isCommandEnabled()
//--------------------------------------------------------------------------------------------------
void RicNewXlineSeismicSectionFeature::onActionTriggered( bool isChecked )
{
RicSeismicSectionFeatureImpl::createSeismicSection( "Xline", RiaDefines::SeismicSectionType::SS_XLINE );
RicSeismicSectionFeatureImpl::createSeismicSection( RiaDefines::SeismicSectionType::SS_XLINE );
}
//--------------------------------------------------------------------------------------------------

View File

@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020- Equinor ASA
// Copyright (C) 2023 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
@ -17,16 +17,9 @@
/////////////////////////////////////////////////////////////////////////////////
#include "RicNewZSliceSeismicSectionFeature.h"
#include "RicSeismicSectionFeatureImpl.h"
#include "RimGridView.h"
#include "RimSeismicSection.h"
#include "RimSeismicSectionCollection.h"
#include "Riu3DMainWindowTools.h"
#include "cafSelectionManagerTools.h"
#include "cafUtils.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicNewZSliceSeismicSectionFeature, "RicNewZSliceSeismicSectionFeature" );
@ -44,7 +37,7 @@ bool RicNewZSliceSeismicSectionFeature::isCommandEnabled()
//--------------------------------------------------------------------------------------------------
void RicNewZSliceSeismicSectionFeature::onActionTriggered( bool isChecked )
{
RicSeismicSectionFeatureImpl::createSeismicSection( "Depth Slice", RiaDefines::SeismicSectionType::SS_DEPTHSLICE );
RicSeismicSectionFeatureImpl::createSeismicSection( RiaDefines::SeismicSectionType::SS_DEPTHSLICE );
}
//--------------------------------------------------------------------------------------------------

View File

@ -28,7 +28,7 @@
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicSeismicSectionFeatureImpl::createSeismicSection( const QString& name, RiaDefines::SeismicSectionType sectionType )
void RicSeismicSectionFeatureImpl::createSeismicSection( RiaDefines::SeismicSectionType sectionType )
{
// Find the selected seismic section collection
std::vector<RimSeismicSectionCollection*> colls = caf::selectedObjectsByTypeStrict<RimSeismicSectionCollection*>();
@ -39,7 +39,6 @@ void RicSeismicSectionFeatureImpl::createSeismicSection( const QString& name, Ri
if ( newSection )
{
newSection->setSectionType( sectionType );
newSection->setUserDescription( name );
Riu3DMainWindowTools::selectAsCurrentItem( newSection );
if ( sectionType == RiaDefines::SeismicSectionType::SS_POLYLINE ) newSection->enablePicking( true );
}

View File

@ -25,5 +25,5 @@ class QString;
class RicSeismicSectionFeatureImpl
{
public:
static void createSeismicSection( const QString& name, RiaDefines::SeismicSectionType sectionType );
static void createSeismicSection( RiaDefines::SeismicSectionType sectionType );
};

View File

@ -0,0 +1,135 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023 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 "RicSeismicSectionFromIntersectionFeature.h"
#include "RiaApplication.h"
#include "RiaSeismicDefines.h"
#include "RimExtrudedCurveIntersection.h"
#include "RimGridView.h"
#include "RimPolylineTarget.h"
#include "RimSeismicSection.h"
#include "RimSeismicSectionCollection.h"
#include "Riu3DMainWindowTools.h"
#include "cafSelectionManagerTools.h"
#include "cafUtils.h"
#include "cvfBoundingBox.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicSeismicSectionFromIntersectionFeature, "RicSeismicSectionFromIntersectionFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicSeismicSectionFromIntersectionFeature::isCommandEnabled()
{
RimExtrudedCurveIntersection* intersection = getSelectedIntersection();
if ( intersection != nullptr )
{
return ( ( intersection->type() == RimExtrudedCurveIntersection::CrossSectionEnum::CS_POLYLINE ) ||
( intersection->type() == RimExtrudedCurveIntersection::CrossSectionEnum::CS_WELL_PATH ) );
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicSeismicSectionFromIntersectionFeature::onActionTriggered( bool isChecked )
{
RimExtrudedCurveIntersection* intersection = getSelectedIntersection();
if ( intersection == nullptr ) return;
RimGridView* activeView = RiaApplication::instance()->activeGridView();
if ( activeView == nullptr ) return;
auto bbox = activeView->domainBoundingBox();
RimSeismicSectionCollection* seisColl = activeView->seismicSectionCollection();
RimSeismicSection* newSection = seisColl->addNewSection();
if ( !newSection ) return;
if ( intersection->type() == RimExtrudedCurveIntersection::CrossSectionEnum::CS_POLYLINE )
{
newSection->setSectionType( RiaDefines::SeismicSectionType::SS_POLYLINE );
newSection->setUserDescription( intersection->name() );
auto polyline = intersection->polyLines();
if ( polyline.size() > 0 )
{
for ( auto& p : polyline[0] )
{
RimPolylineTarget* target = new RimPolylineTarget();
target->setAsPointXYZ( p );
newSection->addTargetNoUpdate( target );
}
}
}
else if ( ( intersection->type() == RimExtrudedCurveIntersection::CrossSectionEnum::CS_WELL_PATH ) )
{
newSection->setSectionType( RiaDefines::SeismicSectionType::SS_WELLPATH );
newSection->setWellPath( intersection->wellPath() );
}
if ( intersection->depthFilterType() == RimIntersectionFilterEnum::INTERSECT_FILTER_NONE )
{
newSection->setDepthFilter( RimIntersectionFilterEnum::INTERSECT_FILTER_BETWEEN,
(int)( -1 * bbox.max().z() ),
(int)( -1 * bbox.min().z() ) );
}
else
{
newSection->setDepthFilter( intersection->depthFilterType(),
(int)-1 * intersection->upperFilterDepth( bbox.max().z() ),
(int)-1 * intersection->lowerFilterDepth( ( bbox.min().z() ) ) );
}
Riu3DMainWindowTools::selectAsCurrentItem( newSection );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicSeismicSectionFromIntersectionFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setIcon( QIcon( ":/Seismic16x16.png" ) );
actionToSetup->setText( "Create as Seismic Section" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimExtrudedCurveIntersection* RicSeismicSectionFromIntersectionFeature::getSelectedIntersection()
{
std::vector<caf::PdmUiItem*> selectedUiItems;
caf::SelectionManager::instance()->selectedItems( selectedUiItems );
RimExtrudedCurveIntersection* intersection = nullptr;
if ( !selectedUiItems.empty() )
{
intersection = dynamic_cast<RimExtrudedCurveIntersection*>( selectedUiItems[0] );
}
return intersection;
}

View File

@ -0,0 +1,40 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023 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 "cafCmdFeature.h"
class RimExtrudedCurveIntersection;
//==================================================================================================
///
//==================================================================================================
class RicSeismicSectionFromIntersectionFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
bool isCommandEnabled() override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
private:
RimExtrudedCurveIntersection* getSelectedIntersection();
};

View File

@ -845,6 +845,8 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicAppendIntersectionFeature";
menuBuilder << "RicAppendIntersectionBoxFeature";
menuBuilder.addSeparator();
menuBuilder << "RicSeismicSectionFromIntersectionFeature";
menuBuilder.addSeparator();
menuBuilder << "RicNewIntersectionViewFeature";
menuBuilder.addSeparator();
menuBuilder << "RicCopyIntersectionsToAllViewsInCaseFeature";
@ -1039,7 +1041,9 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicNewInlineSeismicSectionFeature";
menuBuilder << "RicNewXlineSeismicSectionFeature";
menuBuilder << "RicNewZSliceSeismicSectionFeature";
menuBuilder.addSeparator();
menuBuilder << "RicNewPolylineSeismicSectionFeature";
menuBuilder << "RicNewWellpathSeismicSectionFeature";
}
else if ( dynamic_cast<RimSeismicDataCollection*>( firstUiItem ) )
{

View File

@ -1,4 +1,4 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011- Statoil ASA
// Copyright (C) 2013- Ceetron Solutions AS
@ -424,6 +424,19 @@ RimWellPathCollection* RimTools::wellPathCollection()
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPath* RimTools::firstWellPath()
{
auto wellpathcoll = wellPathCollection();
auto wellpaths = wellpathcoll->allWellPaths();
if ( wellpaths.size() > 0 ) return wellpaths[0];
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -63,6 +63,7 @@ public:
static void seismicDataOptionItems( QList<caf::PdmOptionItemInfo>* options, cvf::BoundingBox worldBBox );
static RimWellPathCollection* wellPathCollection();
static RimWellPath* firstWellPath();
static void timeStepsForCase( RimCase* gridCase, QList<caf::PdmOptionItemInfo>* options );

View File

@ -60,6 +60,7 @@ void RimSeismicAlphaMapper::setDataRangeAndAlphas( double minVal, double maxVal,
cvf::ubyte RimSeismicAlphaMapper::alphaValue( double dataValue ) const
{
int index = (int)( m_scaleFactor * ( dataValue - m_minValue ) );
index = std::clamp( index, 0, (int)sizeof( m_alphavalues ) - 1 );
return ( cvf::ubyte )( m_alphavalues[index] * 255 );
}

View File

@ -34,6 +34,7 @@
#include "cafPdmUiLineEditor.h"
#include "cafPdmUiTableViewEditor.h"
#include "cafPdmUiTreeOrdering.h"
#include "cvfBoundingBox.h"
#include <QValidator>

View File

@ -26,15 +26,18 @@
#include "RimSeismicAlphaMapper.h"
#include "RimSeismicData.h"
#include "RimTools.h"
#include "RimWellPath.h"
#include "WellPathCommands/PointTangentManipulator/RicPolyline3dEditor.h"
#include "WellPathCommands/RicPolylineTargetsPickEventHandler.h"
#include "RigPolyLinesData.h"
#include "RigTexturedSection.h"
#include "RigWellPath.h"
#include "RivSeismicSectionPartMgr.h"
#include "cafCmdFeatureMenuBuilder.h"
#include "cafPdmUiDoubleSliderEditor.h"
#include "cafPdmUiPushButtonEditor.h"
#include "cafPdmUiSliderEditor.h"
@ -51,6 +54,7 @@
#include <QDialog>
#include <QImage>
#include <QLayout>
#include <QMenu>
#include <QPixmap>
#include <algorithm>
@ -66,11 +70,18 @@ RimSeismicSection::RimSeismicSection()
{
CAF_PDM_InitObject( "Seismic Section", ":/Seismic16x16.png" );
CAF_PDM_InitField( &m_userDescription, "UserDecription", QString( "Seismic Section" ), "Name" );
CAF_PDM_InitFieldNoDefault( &m_userDescription, "UserDecription", "Description" );
CAF_PDM_InitFieldNoDefault( &m_nameProxy, "NameProxy", "Name Proxy" );
m_nameProxy.registerGetMethod( this, &RimSeismicSection::fullName );
m_nameProxy.uiCapability()->setUiReadOnly( true );
m_nameProxy.uiCapability()->setUiHidden( true );
m_nameProxy.xmlCapability()->disableIO();
CAF_PDM_InitFieldNoDefault( &m_type, "Type", "Type" );
CAF_PDM_InitFieldNoDefault( &m_seismicData, "SeismicData", "Seismic Data" );
CAF_PDM_InitFieldNoDefault( &m_wellPath, "WellPath", "Well Path" );
CAF_PDM_InitField( &m_enablePicking, "EnablePicking", false, "" );
caf::PdmUiPushButtonEditor::configureEditorForField( &m_enablePicking );
@ -88,7 +99,7 @@ RimSeismicSection::RimSeismicSection()
CAF_PDM_InitField( &m_inlineIndex, "InlineIndex", -1, "Inline" );
m_inlineIndex.uiCapability()->setUiEditorTypeName( caf::PdmUiSliderEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_xlineIndex, "CrosslineIndex", -1, "Crossline" );
CAF_PDM_InitField( &m_xlineIndex, "CrosslineIndex", -1, "Xline" );
m_xlineIndex.uiCapability()->setUiEditorTypeName( caf::PdmUiSliderEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_depthIndex, "DepthIndex", -1, "Depth Slice" );
m_depthIndex.uiCapability()->setUiEditorTypeName( caf::PdmUiSliderEditor::uiEditorTypeName() );
@ -98,7 +109,7 @@ RimSeismicSection::RimSeismicSection()
CAF_PDM_InitField( &m_showSeismicOutline, "ShowSeismicOutline", false, "Show Seismic Data Outline" );
CAF_PDM_InitField( &m_showSectionLine, "ShowSectionLine", false, "Show Section Polyline" );
CAF_PDM_InitField( &m_transparent, "TransperentSection", false, "Transparent (Use on only one section at a time!)" );
CAF_PDM_InitField( &m_transparent, "TransparentSection", false, "Transparent (Use on only one section at a time!)" );
CAF_PDM_InitFieldNoDefault( &m_zFilterType, "DepthFilter", "Depth Filter" );
CAF_PDM_InitField( &m_zUpperThreshold, "UpperThreshold", -1, "Upper Threshold" );
@ -139,7 +150,7 @@ void RimSeismicSection::setUserDescription( QString description )
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimSeismicSection::userDescriptionField()
{
return &m_userDescription;
return &m_nameProxy;
}
//--------------------------------------------------------------------------------------------------
@ -176,32 +187,39 @@ void RimSeismicSection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrderi
{
genGrp->add( &m_depthIndex );
}
auto filterGroup = uiOrdering.addNewGroup( "Depth Filter" );
filterGroup->add( &m_zFilterType );
switch ( zFilterType() )
else if ( m_type() == RiaDefines::SeismicSectionType::SS_WELLPATH )
{
case RimIntersectionFilterEnum::INTERSECT_FILTER_BELOW:
m_zUpperThreshold.uiCapability()->setUiName( "Depth" );
filterGroup->add( &m_zUpperThreshold );
break;
genGrp->add( &m_wellPath );
}
case RimIntersectionFilterEnum::INTERSECT_FILTER_BETWEEN:
m_zUpperThreshold.uiCapability()->setUiName( "Upper Depth" );
filterGroup->add( &m_zUpperThreshold );
m_zLowerThreshold.uiCapability()->setUiName( "Lower Depth" );
filterGroup->add( &m_zLowerThreshold );
break;
if ( m_type() != RiaDefines::SeismicSectionType::SS_DEPTHSLICE )
{
auto filterGroup = uiOrdering.addNewGroup( "Depth Filter" );
filterGroup->add( &m_zFilterType );
case RimIntersectionFilterEnum::INTERSECT_FILTER_ABOVE:
m_zLowerThreshold.uiCapability()->setUiName( "Depth" );
filterGroup->add( &m_zLowerThreshold );
break;
switch ( zFilterType() )
{
case RimIntersectionFilterEnum::INTERSECT_FILTER_BELOW:
m_zUpperThreshold.uiCapability()->setUiName( "Depth" );
filterGroup->add( &m_zUpperThreshold );
break;
case RimIntersectionFilterEnum::INTERSECT_FILTER_NONE:
default:
break;
case RimIntersectionFilterEnum::INTERSECT_FILTER_BETWEEN:
m_zUpperThreshold.uiCapability()->setUiName( "Upper Depth" );
filterGroup->add( &m_zUpperThreshold );
m_zLowerThreshold.uiCapability()->setUiName( "Lower Depth" );
filterGroup->add( &m_zLowerThreshold );
break;
case RimIntersectionFilterEnum::INTERSECT_FILTER_ABOVE:
m_zLowerThreshold.uiCapability()->setUiName( "Depth" );
filterGroup->add( &m_zLowerThreshold );
break;
case RimIntersectionFilterEnum::INTERSECT_FILTER_NONE:
default:
break;
}
}
auto expGrp = uiOrdering.addNewGroup( "Experimental" );
@ -217,7 +235,10 @@ void RimSeismicSection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrderi
outlGrp->setCollapsedByDefault();
}
if ( m_type() != RiaDefines::SeismicSectionType::SS_POLYLINE ) uiOrdering.add( &m_showImage );
if ( ( m_type() != RiaDefines::SeismicSectionType::SS_POLYLINE ) && ( m_type() != RiaDefines::SeismicSectionType::SS_WELLPATH ) )
{
uiOrdering.add( &m_showImage );
}
uiOrdering.skipRemainingFields();
}
@ -274,7 +295,7 @@ void RimSeismicSection::defineEditorAttribute( const caf::PdmFieldHandle* field,
}
else if ( ( field == &m_depthIndex ) || ( field == &m_inlineIndex ) || ( field == &m_xlineIndex ) )
{
if ( m_seismicData() != nullptr )
if ( ( m_seismicData() != nullptr ) && m_seismicData->boundingBox()->isValid() )
{
auto* sliderAttrib = dynamic_cast<caf::PdmUiSliderEditorAttribute*>( attribute );
if ( sliderAttrib != nullptr )
@ -308,10 +329,12 @@ void RimSeismicSection::defineEditorAttribute( const caf::PdmFieldHandle* field,
if ( ( sliderAttrib ) && ( m_seismicData() != nullptr ) )
{
auto bb = m_seismicData()->boundingBox();
sliderAttrib->m_minimum = -1 * bb->max().z();
sliderAttrib->m_maximum = -1 * bb->min().z();
sliderAttrib->m_step = (int)m_seismicData->zStep();
if ( bb->isValid() )
{
sliderAttrib->m_minimum = -1 * bb->max().z();
sliderAttrib->m_maximum = -1 * bb->min().z();
sliderAttrib->m_step = (int)m_seismicData->zStep();
}
}
}
}
@ -322,6 +345,11 @@ void RimSeismicSection::defineEditorAttribute( const caf::PdmFieldHandle* field,
void RimSeismicSection::setSectionType( RiaDefines::SeismicSectionType sectionType )
{
m_type = sectionType;
if ( sectionType == RiaDefines::SeismicSectionType::SS_WELLPATH )
{
auto wellpath = RimTools::firstWellPath();
if ( wellpath != nullptr ) m_wellPath = wellpath;
}
}
//--------------------------------------------------------------------------------------------------
@ -354,6 +382,8 @@ caf::PickEventHandler* RimSeismicSection::pickEventHandler() const
//--------------------------------------------------------------------------------------------------
std::vector<RimPolylineTarget*> RimSeismicSection::activeTargets() const
{
if ( m_type() != RiaDefines::SeismicSectionType::SS_POLYLINE ) return {};
return m_targets.children();
}
@ -371,6 +401,14 @@ void RimSeismicSection::insertTarget( const RimPolylineTarget* targetToInsertBef
updateVisualization();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::addTargetNoUpdate( RimPolylineTarget* target )
{
m_targets.push_back( target );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -505,10 +543,53 @@ QList<caf::PdmOptionItemInfo> RimSeismicSection::calculateValueOptions( const ca
if ( view != nullptr ) RimTools::seismicDataOptionItems( &options, view->domainBoundingBox() );
}
else if ( fieldNeedingOptions == &m_wellPath )
{
RimTools::wellPathOptionItems( &options );
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::updateTextureSectionFromPoints( std::vector<cvf::Vec3d> points, double zmin, double zmax )
{
const int pointCount = (int)points.size();
if ( pointCount < 2 )
{
m_texturedSection->resize( 0 );
return;
}
bool valid = m_texturedSection->partsCount() == ( pointCount - 1 );
if ( !valid ) m_texturedSection->resize( pointCount - 1 );
for ( int i = 1, j = 0; i < pointCount; i++, j++ )
{
cvf::Vec3d p1 = points[j];
cvf::Vec3d p2 = points[i];
if ( !m_texturedSection->part( j ).isRectValid )
{
cvf::Vec3dArray rect;
rect.resize( 4 );
rect[0].set( p1.x(), p1.y(), -zmax );
rect[1].set( p2.x(), p2.y(), -zmax );
rect[2].set( p2.x(), p2.y(), -zmin );
rect[3].set( p1.x(), p1.y(), -zmin );
m_texturedSection->setSectionPartRect( j, rect );
}
if ( m_texturedSection->part( j ).sliceData == nullptr )
{
m_texturedSection->setSectionPartData( j, m_seismicData->sliceData( p1.x(), p1.y(), p2.x(), p2.y(), zmin, zmax ) );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -516,7 +597,8 @@ cvf::ref<RigTexturedSection> RimSeismicSection::texturedSection()
{
if ( m_texturedSection.isNull() ) m_texturedSection = new RigTexturedSection();
if ( m_texturedSection->isValid() || ( m_seismicData == nullptr ) ) return m_texturedSection;
if ( m_texturedSection->isValid() || ( m_seismicData == nullptr ) || ( !m_seismicData->boundingBox()->isValid() ) )
return m_texturedSection;
std::vector<cvf::Vec3dArray> rects;
std::vector<int> widths;
@ -530,31 +612,26 @@ cvf::ref<RigTexturedSection> RimSeismicSection::texturedSection()
{
if ( m_targets.size() == 0 ) return m_texturedSection;
bool valid = m_texturedSection->partsCount() == (int)( m_targets.size() - 1 );
if ( !valid ) m_texturedSection->resize( m_targets.size() - 1 );
std::vector<cvf::Vec3d> points;
for ( int i = 1; i < (int)m_targets.size(); i++ )
for ( int i = 0; i < (int)m_targets.size(); i++ )
{
cvf::Vec3d p1 = m_targets[i - 1]->targetPointXYZ();
cvf::Vec3d p2 = m_targets[i]->targetPointXYZ();
if ( !m_texturedSection->part( i - 1 ).isRectValid )
{
cvf::Vec3dArray points;
points.resize( 4 );
points[0].set( p1.x(), p1.y(), -zmax );
points[1].set( p2.x(), p2.y(), -zmax );
points[2].set( p2.x(), p2.y(), -zmin );
points[3].set( p1.x(), p1.y(), -zmin );
m_texturedSection->setSectionPartRect( i - 1, points );
}
if ( m_texturedSection->part( i - 1 ).sliceData == nullptr )
{
m_texturedSection->setSectionPartData( i - 1, m_seismicData->sliceData( p1.x(), p1.y(), p2.x(), p2.y(), zmin, zmax ) );
}
if ( m_targets[i]->isEnabled() ) points.push_back( m_targets[i]->targetPointXYZ() );
}
updateTextureSectionFromPoints( points, zmin, zmax );
}
else if ( m_type() == RiaDefines::SeismicSectionType::SS_WELLPATH )
{
if ( m_wellPath() == nullptr ) return m_texturedSection;
if ( m_wellPathPoints.empty() )
{
m_wellPathPoints = wellPathToSectionPoints( m_wellPath()->wellPathGeometry(), zmin );
}
if ( m_wellPathPoints.empty() ) return m_texturedSection;
updateTextureSectionFromPoints( m_wellPathPoints, zmin, zmax );
}
else if ( m_type() == RiaDefines::SeismicSectionType::SS_INLINE )
{
@ -624,7 +701,7 @@ cvf::ref<RigTexturedSection> RimSeismicSection::texturedSection()
else
m_texturedSection->resize( 1 );
int zIndex = m_depthIndex();
int z = m_depthIndex();
if ( !valid )
{
@ -636,20 +713,17 @@ cvf::ref<RigTexturedSection> RimSeismicSection::texturedSection()
cvf::Vec3dArray points;
points.resize( 4 );
points[3] = m_seismicData->convertToWorldCoords( ilStart, xlStart, zIndex );
points[2] = m_seismicData->convertToWorldCoords( ilStop, xlStart, zIndex );
points[1] = m_seismicData->convertToWorldCoords( ilStop, xlStop, zIndex );
points[0] = m_seismicData->convertToWorldCoords( ilStart, xlStop, zIndex );
for ( int i = 0; i < 4; i++ )
points[i].z() = -points[i].z();
points[3] = m_seismicData->convertToWorldCoords( ilStart, xlStart, -z );
points[2] = m_seismicData->convertToWorldCoords( ilStop, xlStart, -z );
points[1] = m_seismicData->convertToWorldCoords( ilStop, xlStop, -z );
points[0] = m_seismicData->convertToWorldCoords( ilStart, xlStop, -z );
m_texturedSection->setSectionPartRect( 0, points );
}
if ( m_texturedSection->part( 0 ).sliceData == nullptr )
{
m_texturedSection->setSectionPartData( 0, m_seismicData->sliceData( RiaDefines::SeismicSliceDirection::DEPTH, zIndex, zmin, zmax ) );
m_texturedSection->setSectionPartData( 0, m_seismicData->sliceData( RiaDefines::SeismicSliceDirection::DEPTH, z, zmin, zmax ) );
}
}
@ -705,6 +779,11 @@ void RimSeismicSection::fieldChangedByUi( const caf::PdmFieldHandle* changedFiel
{
updateType = RigTexturedSection::WhatToUpdateEnum::UPDATE_GEOMETRY;
}
else if ( changedField == &m_wellPath )
{
updateType = RigTexturedSection::WhatToUpdateEnum::UPDATE_GEOMETRY;
m_wellPathPoints.clear();
}
else if ( changedField == &m_transparent )
{
updateType = RigTexturedSection::WhatToUpdateEnum::UPDATE_TEXTURE;
@ -767,7 +846,7 @@ bool RimSeismicSection::isTransparent() const
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::initSliceRanges()
{
if ( m_seismicData() == nullptr ) return;
if ( ( m_seismicData() == nullptr ) || ( !m_seismicData->boundingBox()->isValid() ) ) return;
if ( m_zLowerThreshold < 0 ) m_zLowerThreshold = m_seismicData->zMax();
if ( m_zUpperThreshold < 0 ) m_zUpperThreshold = m_seismicData->zMin();
@ -864,6 +943,16 @@ RimIntersectionFilterEnum RimSeismicSection::zFilterType() const
return m_zFilterType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::setDepthFilter( RimIntersectionFilterEnum filterType, int upperValue, int lowerValue )
{
m_zFilterType = filterType;
m_zUpperThreshold = upperValue;
m_zLowerThreshold = lowerValue;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -928,3 +1017,102 @@ QString RimSeismicSection::resultInfoText( cvf::Vec3d worldCoord, int partIndex
return retVal;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<cvf::Vec3d> RimSeismicSection::wellPathToSectionPoints( RigWellPath* wellpath, double zmin )
{
if ( wellpath == nullptr ) return {};
int currentInline = 0;
int currentXline = 0;
auto& wellpoints = wellpath->wellPathPoints();
std::vector<cvf::Vec3d> points;
for ( auto& p : wellpoints )
{
auto [iline, xline] = m_seismicData->convertToInlineXline( p );
if ( std::abs( p.z() ) < zmin ) continue;
// first point?
if ( points.empty() )
{
points.push_back( p );
currentInline = iline;
currentXline = xline;
continue;
}
// skip points that give same seismic index
if ( ( currentInline == iline ) && ( currentXline == xline ) ) continue;
points.push_back( p );
currentInline = iline;
currentXline = xline;
}
// make sure we include the last point
if ( points.back() != wellpoints.back() ) points.push_back( wellpoints.back() );
return points;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSeismicSection::fullName() const
{
QString name = m_userDescription();
QString prefix;
if ( m_type() == RiaDefines::SeismicSectionType::SS_WELLPATH )
{
if ( m_wellPath() != nullptr )
prefix = m_wellPath->name();
else
prefix = "Well Path";
}
else if ( m_type() == RiaDefines::SeismicSectionType::SS_POLYLINE )
{
prefix = "Polyline";
}
else if ( m_type() == RiaDefines::SeismicSectionType::SS_INLINE )
{
prefix = QString( "Inline [%1]" ).arg( m_inlineIndex );
}
else if ( m_type() == RiaDefines::SeismicSectionType::SS_XLINE )
{
prefix = QString( "Xline [%1]" ).arg( m_xlineIndex );
}
else if ( m_type() == RiaDefines::SeismicSectionType::SS_DEPTHSLICE )
{
prefix = QString( "Depth Slice [%1]" ).arg( m_depthIndex );
}
if ( !name.isEmpty() ) return QString( "%1 - %2" ).arg( prefix ).arg( name );
return prefix;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::setWellPath( RimWellPath* wellPath )
{
m_wellPath = wellPath;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, QMenu* menu, QWidget* fieldEditorWidget )
{
caf::CmdFeatureMenuBuilder menuBuilder;
menuBuilder << "RicDeletePolylineTargetFeature";
menuBuilder.appendToMenu( menu );
}

View File

@ -29,6 +29,7 @@
#include "cafPdmField.h"
#include "cafPdmFieldCvfColor.h"
#include "cafPdmFieldCvfVec3d.h"
#include "cafPdmProxyValueField.h"
#include "cafPdmPtrField.h"
#include "cvfArray.h"
@ -38,15 +39,21 @@
#include <QList>
#include <QString>
#include <vector>
class RicPolylineTargetsPickEventHandler;
class RimPolylineTarget;
class RigPolylinesData;
class RigWellPath;
class RigTexturedSection;
class RivSeismicSectionPartMgr;
class Rim3dView;
class RimSeismicData;
class RimRegularLegendConfig;
class RimSeismicAlphaMapper;
class RimWellPath;
class QMenu;
class QWidget;
class RimSeismicSection : public RimCheckableNamedObject, public RimPolylinePickerInterface, public RimPolylinesDataInterface
{
@ -58,9 +65,11 @@ public:
QString userDescription();
void setUserDescription( QString description );
QString fullName() const;
void updateVisualization() override;
void updateEditorsAndVisualization() override;
void addTargetNoUpdate( RimPolylineTarget* target );
void insertTarget( const RimPolylineTarget* targetToInsertBefore, RimPolylineTarget* targetToInsert ) override;
void deleteTarget( RimPolylineTarget* targetToDelete ) override;
void enablePicking( bool enable );
@ -89,8 +98,12 @@ public:
int lowerFilterZ( int lowerGridLimit ) const;
RimIntersectionFilterEnum zFilterType() const;
void setDepthFilter( RimIntersectionFilterEnum filterType, int upperValue, int lowerValue );
QString resultInfoText( cvf::Vec3d worldCoord, int partIndex );
void setWellPath( RimWellPath* wellPath );
protected:
void initAfterRead() override;
caf::PdmFieldHandle* userDescriptionField() override;
@ -102,6 +115,7 @@ protected:
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
private:
void defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, QMenu* menu, QWidget* fieldEditorWidget ) override;
void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
void onLegendConfigChanged( const caf::SignalEmitter* emitter, RimLegendConfigChangeType changeType );
@ -112,8 +126,13 @@ private:
QPixmap getImage();
void updateTextureSectionFromPoints( std::vector<cvf::Vec3d> points, double zmin, double zmax );
std::vector<cvf::Vec3d> wellPathToSectionPoints( RigWellPath* wellpath, double zmin );
caf::PdmField<QString> m_userDescription;
caf::PdmPtrField<RimSeismicData*> m_seismicData;
caf::PdmPtrField<RimWellPath*> m_wellPath;
caf::PdmProxyValueField<QString> m_nameProxy;
caf::PdmField<caf::AppEnum<RiaDefines::SeismicSectionType>> m_type;
caf::PdmChildArrayField<RimPolylineTarget*> m_targets;
@ -136,4 +155,6 @@ private:
std::shared_ptr<RicPolylineTargetsPickEventHandler> m_pickTargetsEventHandler;
cvf::ref<RivSeismicSectionPartMgr> m_sectionPartMgr;
cvf::ref<RigTexturedSection> m_texturedSection;
std::vector<cvf::Vec3d> m_wellPathPoints;
};