Basic seismic support (#10010)

Add basic seismic section support to eclipse and geomech views.
This commit is contained in:
jonjenssen
2023-03-24 15:36:10 +01:00
committed by GitHub
parent 71a418dc78
commit 2e01f4a31d
73 changed files with 4594 additions and 76 deletions

View File

@@ -45,6 +45,8 @@
#include "RimIntersectionResultDefinition.h"
#include "RimIntersectionResultsDefinitionCollection.h"
#include "RimRegularLegendConfig.h"
#include "RimSeismicSection.h"
#include "RimSeismicSectionCollection.h"
#include "RimSurfaceInViewCollection.h"
#include "RimTensorResults.h"
#include "RimTernaryLegendConfig.h"
@@ -319,6 +321,13 @@ void RimGeoMechView::onCreateDisplayModel()
m_intersectionCollection->appendPartsToModel( *this, m_intersectionVizModel.p(), scaleTransform() );
nativeOrOverrideViewer()->addStaticModelOnce( m_intersectionVizModel.p(), isUsingOverrideViewer() );
// Seismic sections
cvf::ref<caf::DisplayCoordTransform> transform = displayCoordTransform();
m_seismicVizModel->removeAllParts();
m_seismicSectionCollection->appendPartsToModel( this, m_seismicVizModel.p(), transform.p(), femBBox );
nativeOrOverrideViewer()->addStaticModelOnce( m_seismicVizModel.p(), isUsingOverrideViewer() );
// Surfaces
m_surfaceVizModel->removeAllParts();
@@ -591,6 +600,11 @@ void RimGeoMechView::onUpdateLegends()
{
m_surfaceCollection->updateLegendRangesTextAndVisibility( nativeOrOverrideViewer(), isUsingOverrideViewer() );
}
if ( m_seismicSectionCollection->isChecked() )
{
m_seismicSectionCollection->updateLegendRangesTextAndVisibility( nativeOrOverrideViewer(), isUsingOverrideViewer() );
}
}
}
@@ -704,6 +718,11 @@ std::vector<RimLegendConfig*> RimGeoMechView::legendConfigs() const
}
}
for ( auto section : seismicSectionCollection()->seismicSections() )
{
absLegendConfigs.push_back( section->legendConfig() );
}
absLegendConfigs.erase( std::remove( absLegendConfigs.begin(), absLegendConfigs.end(), nullptr ), absLegendConfigs.end() );
return absLegendConfigs;
@@ -1037,6 +1056,7 @@ void RimGeoMechView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin
uiTreeOrdering.add( m_intersectionCollection() );
if ( surfaceInViewCollection() ) uiTreeOrdering.add( surfaceInViewCollection() );
uiTreeOrdering.add( seismicSectionCollection() );
uiTreeOrdering.skipRemainingChildren( true );
}

View File

@@ -153,6 +153,9 @@ Rim3dView::Rim3dView()
m_intersectionVizModel = new cvf::ModelBasicList;
m_intersectionVizModel->setName( "CrossSectionModel" );
m_seismicVizModel = new cvf::ModelBasicList;
m_seismicVizModel->setName( "SeismicSectionModel" );
m_highlightVizModel = new cvf::ModelBasicList;
m_highlightVizModel->setName( "HighlightModel" );
@@ -1142,14 +1145,15 @@ bool Rim3dView::isMasterView() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rim3dView::updateGridBoxData()
cvf::BoundingBox Rim3dView::domainBoundingBox()
{
cvf::BoundingBox combinedDomainBBox;
if ( viewer() && ownerCase() )
{
using BBox = cvf::BoundingBox;
BBox masterDomainBBox = isShowingActiveCellsOnly() ? ownerCase()->activeCellsBoundingBox() : ownerCase()->allCellsBoundingBox();
BBox combinedDomainBBox = masterDomainBBox;
cvf::BoundingBox masterDomainBBox = isShowingActiveCellsOnly() ? ownerCase()->activeCellsBoundingBox()
: ownerCase()->allCellsBoundingBox();
combinedDomainBBox.add( masterDomainBBox );
if ( Rim3dView* depView = activeComparisonView() )
{
@@ -1159,17 +1163,25 @@ void Rim3dView::updateGridBoxData()
if ( destinationOwnerCase )
{
BBox depDomainBBox = depView->isShowingActiveCellsOnly() ? destinationOwnerCase->activeCellsBoundingBox()
: destinationOwnerCase->allCellsBoundingBox();
if ( depDomainBBox.isValid() )
{
combinedDomainBBox.add( depDomainBBox.min() );
combinedDomainBBox.add( depDomainBBox.max() );
}
cvf::BoundingBox depDomainBBox = depView->isShowingActiveCellsOnly() ? destinationOwnerCase->activeCellsBoundingBox()
: destinationOwnerCase->allCellsBoundingBox();
combinedDomainBBox.add( depDomainBBox );
}
}
}
viewer()->updateGridBoxData( m_scaleZ(), ownerCase()->displayModelOffset(), backgroundColor(), combinedDomainBBox, fontSize() );
return combinedDomainBBox;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rim3dView::updateGridBoxData()
{
if ( viewer() && ownerCase() )
{
viewer()->updateGridBoxData( m_scaleZ(), ownerCase()->displayModelOffset(), backgroundColor(), domainBoundingBox(), fontSize() );
}
}

View File

@@ -169,6 +169,8 @@ public:
void updateAnnotationItems();
void resetLegends();
cvf::BoundingBox domainBoundingBox();
void setScaleZ( double scaleZ );
void setScaleZAndUpdate( double scaleZ );
void updateScaling();
@@ -256,6 +258,7 @@ protected:
// 3D display model data
cvf::ref<cvf::ModelBasicList> m_wellPathPipeVizModel;
cvf::ref<cvf::ModelBasicList> m_intersectionVizModel;
cvf::ref<cvf::ModelBasicList> m_seismicVizModel;
cvf::ref<RivWellPathsPartMgr> m_wellPathsPartManager;
caf::PdmField<double> m_scaleZ;

View File

@@ -112,6 +112,8 @@
#include "RimRftPlotCollection.h"
#include "RimSaturationPressurePlotCollection.h"
#include "RimScriptCollection.h"
#include "RimSeismicDataCollection.h"
#include "RimSeismicSectionCollection.h"
#include "RimSimWellFracture.h"
#include "RimSimWellInView.h"
#include "RimSimWellInViewCollection.h"
@@ -1032,6 +1034,17 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicNewRangeFilterSliceKFeature";
menuBuilder.subMenuEnd();
}
else if ( dynamic_cast<RimSeismicSectionCollection*>( firstUiItem ) )
{
menuBuilder << "RicNewInlineSeismicSectionFeature";
menuBuilder << "RicNewXlineSeismicSectionFeature";
menuBuilder << "RicNewZSliceSeismicSectionFeature";
menuBuilder << "RicNewPolylineSeismicSectionFeature";
}
else if ( dynamic_cast<RimSeismicDataCollection*>( firstUiItem ) )
{
menuBuilder << "RicImportSeismicFeature";
}
else if ( dynamic_cast<RimAnnotationCollection*>( firstUiItem ) || dynamic_cast<RimAnnotationGroupCollection*>( firstUiItem ) )
{
menuBuilder << "RicCreateTextAnnotationFeature";

View File

@@ -71,6 +71,8 @@
#include "RimProject.h"
#include "RimRegularLegendConfig.h"
#include "RimReservoirCellResultsStorage.h"
#include "RimSeismicSection.h"
#include "RimSeismicSectionCollection.h"
#include "RimSimWellFracture.h"
#include "RimSimWellInView.h"
#include "RimSimWellInViewCollection.h"
@@ -591,6 +593,13 @@ void RimEclipseView::onCreateDisplayModel()
m_intersectionCollection->appendPartsToModel( *this, m_intersectionVizModel.p(), m_reservoirGridPartManager->scaleTransform() );
nativeOrOverrideViewer()->addStaticModelOnce( m_intersectionVizModel.p(), isUsingOverrideViewer() );
// Seismic sections
cvf::ref<caf::DisplayCoordTransform> transform = displayCoordTransform();
m_seismicVizModel->removeAllParts();
m_seismicSectionCollection->appendPartsToModel( this, m_seismicVizModel.p(), transform.p(), ownerCase()->allCellsBoundingBox() );
nativeOrOverrideViewer()->addStaticModelOnce( m_seismicVizModel.p(), isUsingOverrideViewer() );
// Surfaces
m_surfaceVizModel->removeAllParts();
@@ -1468,6 +1477,11 @@ void RimEclipseView::onUpdateLegends()
m_surfaceCollection->updateLegendRangesTextAndVisibility( nativeOrOverrideViewer(), isUsingOverrideViewer() );
}
if ( m_seismicSectionCollection->isChecked() )
{
m_seismicSectionCollection->updateLegendRangesTextAndVisibility( nativeOrOverrideViewer(), isUsingOverrideViewer() );
}
if ( m_streamlineCollection )
{
m_streamlineCollection->updateLegendRangesTextAndVisibility( nativeOrOverrideViewer(), isUsingOverrideViewer() );
@@ -1918,6 +1932,8 @@ void RimEclipseView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin
if ( surfaceInViewCollection() ) uiTreeOrdering.add( surfaceInViewCollection() );
uiTreeOrdering.add( seismicSectionCollection() );
uiTreeOrdering.skipRemainingChildren( true );
}
@@ -2243,6 +2259,11 @@ std::vector<RimLegendConfig*> RimEclipseView::legendConfigs() const
}
}
for ( auto section : seismicSectionCollection()->seismicSections() )
{
absLegends.push_back( section->legendConfig() );
}
absLegends.erase( std::remove( absLegends.begin(), absLegends.end(), nullptr ), absLegends.end() );
return absLegends;

View File

@@ -31,6 +31,7 @@
#include "RimOilField.h"
#include "RimProject.h"
#include "RimPropertyFilterCollection.h"
#include "RimSeismicSectionCollection.h"
#include "RimSurfaceCollection.h"
#include "RimSurfaceInView.h"
#include "RimSurfaceInViewCollection.h"
@@ -100,6 +101,10 @@ RimGridView::RimGridView()
CAF_PDM_InitFieldNoDefault( &m_surfaceCollection, "SurfaceInViewCollection", "Surface Collection Field" );
m_surfaceCollection.uiCapability()->setUiTreeHidden( true );
CAF_PDM_InitFieldNoDefault( &m_seismicSectionCollection, "SeismicSectionCollection", "Seismic Collection Field" );
m_seismicSectionCollection.uiCapability()->setUiTreeHidden( true );
m_seismicSectionCollection = new RimSeismicSectionCollection();
CAF_PDM_InitFieldNoDefault( &m_cellFilterCollection, "RangeFilters", "Cell Filter Collection Field" );
m_cellFilterCollection = new RimCellFilterCollection();
m_cellFilterCollection.uiCapability()->setUiTreeHidden( true );
@@ -154,6 +159,14 @@ RimSurfaceInViewCollection* RimGridView::surfaceInViewCollection() const
return m_surfaceCollection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicSectionCollection* RimGridView::seismicSectionCollection() const
{
return m_seismicSectionCollection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -32,6 +32,7 @@ class RimGridCollection;
class RimCellFilterCollection;
class RimWellMeasurementInViewCollection;
class RimSurfaceInViewCollection;
class RimSeismicSectionCollection;
class RimGridView : public Rim3dView
{
@@ -52,6 +53,7 @@ public:
RimIntersectionResultsDefinitionCollection* separateSurfaceResultsCollection() const;
RimAnnotationInViewCollection* annotationCollection() const;
RimWellMeasurementInViewCollection* measurementCollection() const;
RimSeismicSectionCollection* seismicSectionCollection() const;
virtual const RimPropertyFilterCollection* propertyFilterCollection() const = 0;
@@ -96,6 +98,7 @@ protected:
caf::PdmChildField<RimSurfaceInViewCollection*> m_surfaceCollection;
caf::PdmChildField<RimCellFilterCollection*> m_cellFilterCollection;
caf::PdmChildField<RimCellFilterCollection*> m_overrideCellFilterCollection;
caf::PdmChildField<RimSeismicSectionCollection*> m_seismicSectionCollection;
private:
void onCreatePartCollectionFromSelection( cvf::Collection<cvf::Part>* parts ) override;

View File

@@ -29,6 +29,7 @@
#include "RimGeoMechModels.h"
#include "RimMeasurement.h"
#include "RimObservedDataCollection.h"
#include "RimSeismicDataCollection.h"
#include "RimSummaryCaseMainCollection.h"
#include "RimSurfaceCollection.h"
#include "RimWellPathCollection.h"
@@ -64,6 +65,9 @@ RimOilField::RimOilField( void )
surfaceCollection = new RimSurfaceCollection();
surfaceCollection->setAsTopmostFolder();
CAF_PDM_InitFieldNoDefault( &seismicCollection, "SeismicCollection", "Seismic Data" );
seismicCollection = new RimSeismicDataCollection();
completionTemplateCollection = new RimCompletionTemplateCollection;
analysisModels = new RimEclipseCaseCollection();
wellPathCollection = new RimWellPathCollection();

View File

@@ -37,6 +37,7 @@ class RimSummaryCaseMainCollection;
class RimWellPathCollection;
class RimAnnotationCollection;
class RimMeasurement;
class RimSeismicDataCollection;
class RimSurfaceCollection;
class RimEnsembleWellLogsCollection;
@@ -68,6 +69,7 @@ public:
caf::PdmChildField<RimAnnotationCollection*> annotationCollection;
caf::PdmChildField<RimMeasurement*> measurement;
caf::PdmChildField<RimSurfaceCollection*> surfaceCollection;
caf::PdmChildField<RimSeismicDataCollection*> seismicCollection;
caf::PdmChildField<RimEnsembleWellLogsCollection*> ensembleWellLogsCollection;
protected:

View File

@@ -72,6 +72,7 @@
#include "RimRftPlotCollection.h"
#include "RimSaturationPressurePlotCollection.h"
#include "RimScriptCollection.h"
#include "RimSeismicDataCollection.h"
#include "RimStimPlanModelPlotCollection.h"
#include "RimSummaryCalculation.h"
#include "RimSummaryCalculationCollection.h"
@@ -1517,6 +1518,7 @@ void RimProject::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, Q
if ( oilField->geoMechModels() ) uiTreeOrdering.add( oilField->geoMechModels() );
if ( oilField->wellPathCollection() ) uiTreeOrdering.add( oilField->wellPathCollection() );
if ( oilField->surfaceCollection() ) uiTreeOrdering.add( oilField->surfaceCollection() );
if ( oilField->seismicCollection() ) uiTreeOrdering.add( oilField->seismicCollection() );
if ( oilField->formationNamesCollection() ) uiTreeOrdering.add( oilField->formationNamesCollection() );
if ( oilField->completionTemplateCollection() ) uiTreeOrdering.add( oilField->completionTemplateCollection() );
if ( oilField->annotationCollection() ) uiTreeOrdering.add( oilField->annotationCollection() );

View File

@@ -586,6 +586,17 @@ void RimRegularLegendConfig::setTickNumberFormat( RiaNumberFormat::NumberFormatT
m_tickNumberFormat = numberFormat;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularLegendConfig::setUserDefinedRange( double minVal, double maxVal )
{
m_userDefinedMinValue = minVal;
m_userDefinedMaxValue = maxVal;
updateLegend();
sendChangedSignal( &m_userDefinedMaxValue );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -1265,6 +1276,15 @@ void RimRegularLegendConfig::defineUiOrdering( QString uiConfigName, caf::PdmUiO
updateFieldVisibility();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularLegendConfig::defineUiOrderingColorOnly( caf::PdmUiOrdering* colorGroup )
{
colorGroup->add( &m_colorLegend, { true, 2, 1 } );
colorGroup->add( &m_selectColorLegendButton, { false, 1, 0 } );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -130,6 +130,7 @@ public:
void setTickNumberFormat( RiaNumberFormat::NumberFormatType numberFormat );
void resetUserDefinedValues();
void setCenterLegendAroundZero( bool enable );
void setUserDefinedRange( double minVal, double maxVal );
void disableAllTimeStepsRange( bool doDisable );
@@ -171,6 +172,8 @@ public:
void setDefaultConfigForResultName( const QString& resultName, bool useDiscreteLogLevels, bool isCategoryResult );
void defineUiOrderingColorOnly( caf::PdmUiOrdering* colorGroup );
private:
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
void sendChangedSignal( const caf::PdmFieldHandle* changedField );

View File

@@ -27,6 +27,8 @@
#include "RimGeoMechCase.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSeismicData.h"
#include "RimSeismicDataCollection.h"
#include "RimWellLogFile.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
@@ -371,6 +373,26 @@ void RimTools::geoMechCaseOptionItems( QList<caf::PdmOptionItemInfo>* options )
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimTools::seismicDataOptionItems( QList<caf::PdmOptionItemInfo>* options, cvf::BoundingBox worldBBox )
{
if ( !options ) return;
RimProject* proj = RimProject::current();
if ( proj )
{
const auto& coll = proj->activeOilField()->seismicCollection().p();
for ( auto* c : coll->seismicData() )
{
if ( c->boundingBox()->intersects( worldBBox ) )
options->push_back( caf::PdmOptionItemInfo( c->userDescription(), c, false, c->uiIconProvider() ) );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -20,6 +20,8 @@
#pragma once
#include "cvfBoundingBox.h"
#include <QList>
#include <QString>
@@ -58,6 +60,8 @@ public:
static void eclipseCaseOptionItems( QList<caf::PdmOptionItemInfo>* options );
static void geoMechCaseOptionItems( QList<caf::PdmOptionItemInfo>* options );
static void colorLegendOptionItems( QList<caf::PdmOptionItemInfo>* options );
static void seismicDataOptionItems( QList<caf::PdmOptionItemInfo>* options, cvf::BoundingBox worldBBox );
static RimWellPathCollection* wellPathCollection();
static void timeStepsForCase( RimCase* gridCase, QList<caf::PdmOptionItemInfo>* options );

View File

@@ -0,0 +1,25 @@
set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimSeismicDataCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimSeismicData.h
${CMAKE_CURRENT_LIST_DIR}/RimSeismicSectionCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimSeismicSection.h
${CMAKE_CURRENT_LIST_DIR}/RimSeismicAlphaMapper.h
)
set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimSeismicDataCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSeismicData.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSeismicSectionCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSeismicSection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSeismicAlphaMapper.cpp
)
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES})
source_group(
"ProjectDataModel\\Seismic"
FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES}
${CMAKE_CURRENT_LIST_DIR}/CMakeLists_files.cmake
)

View File

@@ -0,0 +1,65 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSeismicAlphaMapper.h"
#include <algorithm>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicAlphaMapper::RimSeismicAlphaMapper()
: m_maxValue( 0.0 )
, m_minValue( 0.0 )
, m_dataRange( 0.0 )
, m_scaleFactor( 0.0 )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicAlphaMapper::~RimSeismicAlphaMapper()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicAlphaMapper::setDataRangeAndAlphas( double minVal, double maxVal, std::vector<double> alphas )
{
m_minValue = minVal;
m_maxValue = maxVal;
m_dataRange = maxVal - minVal;
m_alphavalues = alphas;
if ( m_dataRange != 0.0 )
m_scaleFactor = 1.0 * alphas.size() / m_dataRange;
else
m_scaleFactor = 0.0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ubyte RimSeismicAlphaMapper::alphaValue( double dataValue ) const
{
int index = (int)( m_scaleFactor * ( dataValue - m_minValue ) );
return ( cvf::ubyte )( m_alphavalues[index] * 255 );
}

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 "cvfBase.h"
#include <vector>
class RimSeismicAlphaMapper
{
public:
RimSeismicAlphaMapper();
~RimSeismicAlphaMapper();
void setDataRangeAndAlphas( double minVal, double maxVal, std::vector<double> alphas );
cvf::ubyte alphaValue( double dataValue ) const;
private:
std::vector<double> m_alphavalues;
double m_maxValue;
double m_minValue;
double m_dataRange;
double m_scaleFactor;
};

View File

@@ -0,0 +1,683 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2022 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 "RimSeismicData.h"
#include "RiaLogging.h"
#include "RifSeismicZGYReader.h"
#include "RimRegularLegendConfig.h"
#include "RimSeismicAlphaMapper.h"
#include "RimStringParameter.h"
#include "RiuMainWindow.h"
#include "RiuSeismicHistogramPanel.h"
#include <zgyaccess/seismicslice.h>
#include "cafPdmUiLineEditor.h"
#include "cafPdmUiTableViewEditor.h"
#include "cafPdmUiTreeOrdering.h"
#include "cvfBoundingBox.h"
#include <QValidator>
#include <algorithm>
#include <cmath>
#include <limits>
#include <tuple>
CAF_PDM_SOURCE_INIT( RimSeismicData, "SeismicData" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicData::RimSeismicData()
: m_zStep( 0 )
, m_filereader( nullptr )
, m_nErrorsLogged( 0 )
, m_fileDataRange( 0, 0 )
, m_activeDataRange( 0, 0 )
{
CAF_PDM_InitObject( "SeismicData", ":/Seismic16x16.png" );
CAF_PDM_InitFieldNoDefault( &m_userDescription, "SeismicUserDecription", "Name" );
CAF_PDM_InitFieldNoDefault( &m_filename, "SeismicFilePath", "File" );
m_filename.uiCapability()->setUiReadOnly( true );
CAF_PDM_InitFieldNoDefault( &m_legendConfig, "LegendDefinition", "Color Legend" );
m_legendConfig = new RimRegularLegendConfig();
m_legendConfig.uiCapability()->setUiTreeHidden( true );
CAF_PDM_InitFieldNoDefault( &m_metadata, "Metadata", "Metadata" );
m_metadata.uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() );
m_metadata.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
m_metadata.uiCapability()->setUiTreeChildrenHidden( true );
m_metadata.uiCapability()->setUiTreeHidden( true );
m_metadata.uiCapability()->setUiReadOnly( true );
m_metadata.xmlCapability()->disableIO();
CAF_PDM_InitField( &m_overrideDataRange, "overrideDataRange", false, "Override Data Range" );
CAF_PDM_InitField( &m_userClipValue, "userClipValue", 0.0, "Clip Value" );
setDeletable( true );
m_boundingBox = std::make_shared<cvf::BoundingBox>();
m_alphaValueMapper = std::make_shared<RimSeismicAlphaMapper>();
initColorLegend();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicData::~RimSeismicData()
{
if ( m_filereader != nullptr ) m_filereader->close();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSeismicData::openFileIfNotOpen()
{
if ( m_filereader == nullptr )
{
m_filereader = std::make_shared<RifSeismicZGYReader>();
}
if ( m_filereader->isOpen() ) return true;
QString filename = m_filename().path();
if ( filename.isEmpty() ) return false;
if ( QFile::exists( filename ) )
{
if ( !m_filereader->open( filename ) )
{
logError( "Unable to open seismic file : " + filename );
m_filereader.reset();
return false;
}
if ( !m_filereader->isValid() )
{
logError( "Seismic file has invalid header values. Cannot import file: " + filename );
m_filereader->close();
m_filereader.reset();
return false;
}
}
else
{
logError( "Seismic file not found: " + filename );
return false;
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicData::logError( QString msg )
{
if ( m_nErrorsLogged < 4 ) RiaLogging::error( msg );
m_nErrorsLogged++;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicData::initAfterRead()
{
updateMetaData();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicData::setFileName( QString filename )
{
if ( filename != m_filename().path() )
{
if ( m_filereader != nullptr ) m_filereader->close();
m_nErrorsLogged = 0;
m_filename = filename;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSeismicData::fileName() const
{
return m_filename().path();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSeismicData::userDescription()
{
return m_userDescription;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicData::setUserDescription( QString description )
{
m_userDescription = description;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimSeismicData::userDescriptionField()
{
return &m_userDescription;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicData::updateMetaData()
{
m_metadata.deleteChildren();
m_boundingBox->reset();
m_worldOutline.clear();
if ( !openFileIfNotOpen() ) return;
auto metadata = m_filereader->metaData();
for ( auto& [name, value] : metadata )
{
auto param = new RimStringParameter();
param->setLabel( name );
param->setValue( value );
m_metadata.push_back( param );
}
m_boundingBox->add( m_filereader->boundingBox() );
m_zStep = m_filereader->zStep();
auto [minDataValue, maxDataValue] = m_filereader->dataRange();
double maxAbsDataValue = std::max( std::abs( minDataValue ), std::abs( maxDataValue ) );
if ( m_userClipValue <= 0.0 ) m_userClipValue = maxAbsDataValue;
m_userClipValue = std::clamp( m_userClipValue(), 0.0, maxAbsDataValue );
m_filereader->histogramData( m_histogramXvalues, m_histogramYvalues );
for ( auto& p : m_filereader->worldCorners() )
{
m_worldOutline.push_back( p );
}
m_inlineInfo = m_filereader->inlineMinMaxStep();
m_xlineInfo = m_filereader->xlineMinMaxStep();
m_fileDataRange = m_filereader->dataRange();
updateDataRange( false );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<cvf::Vec3d> RimSeismicData::worldOutline() const
{
return m_worldOutline;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicData::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
if ( m_metadata.empty() )
{
updateMetaData();
}
auto genGroup = uiOrdering.addNewGroup( "General" );
genGroup->add( &m_userDescription );
genGroup->add( &m_filename );
auto cmGroup = uiOrdering.addNewGroup( "Color Mapping" );
m_legendConfig->defineUiOrderingColorOnly( cmGroup );
cmGroup->add( &m_overrideDataRange );
if ( m_overrideDataRange() )
{
cmGroup->add( &m_userClipValue );
}
auto metaGroup = uiOrdering.addNewGroup( "File Information" );
metaGroup->add( &m_metadata );
metaGroup->setCollapsedByDefault();
uiOrdering.skipRemainingFields();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicData::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= "" */ )
{
uiTreeOrdering.skipRemainingChildren();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicData::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute )
{
if ( field == &m_metadata )
{
auto tvAttribute = dynamic_cast<caf::PdmUiTableViewEditorAttribute*>( attribute );
if ( tvAttribute )
{
tvAttribute->resizePolicy = caf::PdmUiTableViewEditorAttribute::RESIZE_TO_FILL_CONTAINER;
tvAttribute->alwaysEnforceResizePolicy = true;
tvAttribute->minimumHeight = 400;
}
}
else if ( field == &m_userClipValue )
{
auto myAttr = dynamic_cast<caf::PdmUiLineEditorAttribute*>( attribute );
if ( myAttr )
{
myAttr->validator = new QDoubleValidator( 0.00001, std::numeric_limits<double>::infinity(), 6 );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::BoundingBox* RimSeismicData::boundingBox() const
{
return m_boundingBox.get();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimSeismicData::zMin() const
{
return std::abs( m_boundingBox->max().z() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimSeismicData::zMax() const
{
return std::abs( m_boundingBox->min().z() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimSeismicData::zStep() const
{
return m_zStep;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSeismicData::inlineMin() const
{
return m_inlineInfo[0];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSeismicData::inlineMax() const
{
return m_inlineInfo[1];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSeismicData::inlineStep() const
{
return m_inlineInfo[2];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSeismicData::xlineMin() const
{
return m_xlineInfo[0];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSeismicData::xlineMax() const
{
return m_xlineInfo[1];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSeismicData::xlineStep() const
{
return m_xlineInfo[2];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSeismicData::toInlineIndex( int inLine ) const
{
int iIndex = inLine - inlineMin();
iIndex /= inlineStep();
return iIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSeismicData::toXlineIndex( int xLine ) const
{
int xIndex = xLine - xlineMin();
xIndex /= xlineStep();
return xIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSeismicData::toZIndex( double z ) const
{
int zIndex = (int)( ( z - zMin() ) / zStep() );
return zIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimSeismicData::histogramXvalues() const
{
return m_clippedHistogramXvalues;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimSeismicData::histogramYvalues() const
{
return m_clippedHistogramYvalues;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimSeismicData::alphaValues() const
{
return m_clippedAlphaValues;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicData::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
{
if ( ( changedField == &m_overrideDataRange ) || ( changedField == &m_userClipValue ) )
{
updateDataRange( true );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicData::updateDataRange( bool updatePlot )
{
m_clippedHistogramXvalues.clear();
m_clippedHistogramYvalues.clear();
m_clippedAlphaValues.clear();
double clipValue = m_userClipValue;
if ( m_overrideDataRange() )
{
m_activeDataRange = std::make_pair( -m_userClipValue, m_userClipValue );
}
else
{
m_activeDataRange = std::make_pair( m_fileDataRange.first, m_fileDataRange.second );
clipValue = m_fileDataRange.second;
}
const int nVals = (int)m_histogramXvalues.size();
for ( int i = 0; i < nVals; i++ )
{
double tmp = std::abs( m_histogramXvalues[i] );
if ( tmp > clipValue ) continue;
m_clippedHistogramXvalues.push_back( m_histogramXvalues[i] );
m_clippedHistogramYvalues.push_back( m_histogramYvalues[i] );
}
double maxRawValue = *std::max_element( m_clippedHistogramYvalues.begin(), m_clippedHistogramYvalues.end() );
for ( auto val : m_clippedHistogramYvalues )
{
m_clippedAlphaValues.push_back( 1.0 - std::clamp( val / maxRawValue, 0.0, 1.0 ) );
}
m_alphaValueMapper->setDataRangeAndAlphas( m_activeDataRange.first, m_activeDataRange.second, m_clippedAlphaValues );
m_legendConfig->setUserDefinedRange( m_activeDataRange.first, m_activeDataRange.second );
if ( updatePlot ) RiuMainWindow::instance()->seismicHistogramPanel()->showHistogram( this );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec3d RimSeismicData::convertToWorldCoords( int iLine, int xLine, double depth )
{
if ( !openFileIfNotOpen() ) return { 0, 0, 0 };
return m_filereader->convertToWorldCoords( iLine, xLine, depth );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<double, double> RimSeismicData::dataRangeMinMax() const
{
return m_activeDataRange;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::shared_ptr<ZGYAccess::SeismicSliceData>
RimSeismicData::sliceData( RiaDefines::SeismicSliceDirection direction, int sliceNumber, double zMin, double zMax )
{
if ( !openFileIfNotOpen() ) return nullptr;
int sliceIndex = 0;
int zMinIndex = toZIndex( zMin );
int zMaxIndex = toZIndex( zMax );
switch ( direction )
{
case RiaDefines::SeismicSliceDirection::INLINE:
sliceIndex = ( sliceNumber - m_inlineInfo[0] ) / m_inlineInfo[2];
break;
case RiaDefines::SeismicSliceDirection::XLINE:
sliceIndex = ( sliceNumber - m_xlineInfo[0] ) / m_xlineInfo[2];
break;
case RiaDefines::SeismicSliceDirection::DEPTH:
sliceIndex = (int)( 1.0 * ( sliceNumber - this->zMin() ) / m_zStep );
break;
default:
return nullptr;
}
auto data = m_filereader->slice( direction, sliceIndex, zMinIndex, zMaxIndex - zMinIndex );
double tmp = 0.0;
float* pValue = data->values();
const auto [minVal, maxVal] = dataRangeMinMax();
const int nSize = data->size();
for ( int i = 0; i < nSize; i++, pValue++ )
{
tmp = *pValue;
if ( tmp < minVal )
*pValue = minVal;
else if ( tmp > maxVal )
*pValue = maxVal;
}
return data;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimRegularLegendConfig* RimSeismicData::legendConfig() const
{
return m_legendConfig();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicAlphaMapper* RimSeismicData::alphaValueMapper() const
{
return m_alphaValueMapper.get();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicData::initColorLegend()
{
m_legendConfig->setColorLegend( RimRegularLegendConfig::mapToColorLegend( RimRegularLegendConfig::ColorRangesType::BLUE_WHITE_RED ) );
m_legendConfig->setMappingMode( RimRegularLegendConfig::MappingType::LINEAR_CONTINUOUS );
m_legendConfig->setRangeMode( RimLegendConfig::RangeModeType::USER_DEFINED );
m_legendConfig->setCenterLegendAroundZero( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::shared_ptr<ZGYAccess::SeismicSliceData>
RimSeismicData::sliceData( double worldX1, double worldY1, double worldX2, double worldY2, double zMin, double zMax )
{
if ( !openFileIfNotOpen() ) return nullptr;
auto [startInline, startXline] = m_filereader->convertToInlineXline( worldX1, worldY1 );
auto [stopInline, stopXline] = m_filereader->convertToInlineXline( worldX2, worldY2 );
int startInlineIndex = toInlineIndex( startInline );
int startXlineIndex = toXlineIndex( startXline );
int stopInlineIndex = toInlineIndex( stopInline );
int stopXlineIndex = toXlineIndex( stopXline );
int zMinIndex = toZIndex( zMin );
int zMaxIndex = toZIndex( zMax );
int diffI = std::abs( startInlineIndex - stopInlineIndex );
int diffX = std::abs( startXlineIndex - stopXlineIndex );
int dirI = 1;
if ( startInlineIndex > stopInlineIndex ) dirI = -1;
int dirX = 1;
if ( startXlineIndex > stopXlineIndex ) dirX = -1;
const int zSize = zMaxIndex - zMinIndex;
std::shared_ptr<ZGYAccess::SeismicSliceData> retdata;
if ( diffI > diffX )
{
double dstepX = 1.0 * dirX * diffX / diffI;
double xlined = 1.0 * startXlineIndex;
retdata = std::make_shared<ZGYAccess::SeismicSliceData>( diffI, zSize );
float* pOut = retdata->values();
for ( int iline = startInlineIndex; iline != stopInlineIndex; iline += dirI, xlined += dstepX )
{
int xline = (int)std::round( xlined );
auto trace = m_filereader->trace( iline, xline, zMinIndex, zSize );
if ( trace->size() != zSize )
{
memset( pOut, 0, zSize * sizeof( float ) );
}
else
{
memcpy( pOut, trace->values(), zSize * sizeof( float ) );
}
pOut += zSize;
}
}
else
{
if ( diffX == 0 ) return nullptr;
double dstepI = 1.0 * dirI * diffI / diffX;
double ilined = 1.0 * startInlineIndex;
retdata = std::make_shared<ZGYAccess::SeismicSliceData>( diffX, zSize );
float* pOut = retdata->values();
for ( int xline = startXlineIndex; xline != stopXlineIndex; xline += dirX, ilined += dstepI )
{
int iline = (int)std::round( ilined );
auto trace = m_filereader->trace( iline, xline, zMinIndex, zSize );
if ( trace->size() != zSize )
{
memset( pOut, 0, zSize * sizeof( float ) );
}
else
{
memcpy( pOut, trace->values(), zSize * sizeof( float ) );
}
pOut += zSize;
}
}
return retdata;
}

View File

@@ -0,0 +1,142 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2022 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 "RiaSeismicDefines.h"
#include "cafFilePath.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cvfVector3.h"
#include <QString>
#include <memory>
#include <utility>
class RimGenericParameter;
class RimSeismicAlphaMapper;
class RimRegularLegendConfig;
class RifSeismicZGYReader;
namespace cvf
{
class BoundingBox;
} // namespace cvf
namespace ZGYAccess
{
class SeismicSliceData;
}
class RimSeismicData : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimSeismicData();
~RimSeismicData() override;
void setFileName( QString filename );
QString fileName() const;
QString userDescription();
void setUserDescription( QString description );
void updateMetaData();
double zMin() const;
double zMax() const;
double zStep() const;
int inlineMin() const;
int inlineMax() const;
int inlineStep() const;
int xlineMin() const;
int xlineMax() const;
int xlineStep() const;
std::vector<double> histogramXvalues() const;
std::vector<double> histogramYvalues() const;
std::vector<double> alphaValues() const;
std::vector<cvf::Vec3d> worldOutline() const;
cvf::Vec3d convertToWorldCoords( int iLine, int xLine, double depth );
std::shared_ptr<ZGYAccess::SeismicSliceData>
sliceData( RiaDefines::SeismicSliceDirection direction, int sliceNumber, double zMin, double zMax );
std::shared_ptr<ZGYAccess::SeismicSliceData>
sliceData( double worldX1, double worldY1, double worldX2, double worldY2, double zMin, double zMax );
std::pair<double, double> dataRangeMinMax() const;
RimRegularLegendConfig* legendConfig() const;
RimSeismicAlphaMapper* alphaValueMapper() const;
cvf::BoundingBox* boundingBox() const;
protected:
void initAfterRead() override;
caf::PdmFieldHandle* userDescriptionField() override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
private:
void updateDataRange( bool updatePlot );
bool openFileIfNotOpen();
void logError( QString msg );
void initColorLegend();
int toInlineIndex( int inLine ) const;
int toXlineIndex( int xLine ) const;
int toZIndex( double z ) const;
private:
caf::PdmField<caf::FilePath> m_filename;
caf::PdmField<QString> m_userDescription;
caf::PdmChildArrayField<RimGenericParameter*> m_metadata;
caf::PdmChildField<RimRegularLegendConfig*> m_legendConfig;
caf::PdmField<bool> m_overrideDataRange;
caf::PdmField<double> m_userClipValue;
double m_zStep;
cvf::Vec3i m_inlineInfo;
cvf::Vec3i m_xlineInfo;
std::shared_ptr<cvf::BoundingBox> m_boundingBox;
std::vector<double> m_histogramXvalues;
std::vector<double> m_histogramYvalues;
std::vector<double> m_clippedHistogramXvalues;
std::vector<double> m_clippedHistogramYvalues;
std::vector<double> m_clippedAlphaValues;
std::vector<cvf::Vec3d> m_worldOutline;
std::pair<double, double> m_activeDataRange;
std::pair<double, double> m_fileDataRange;
std::shared_ptr<RimSeismicAlphaMapper> m_alphaValueMapper;
std::shared_ptr<RifSeismicZGYReader> m_filereader;
int m_nErrorsLogged;
};

View File

@@ -0,0 +1,106 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2022 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 "RimSeismicDataCollection.h"
#include "RiaLogging.h"
#include "Rim3dView.h"
#include "RimGridView.h"
#include "RimProject.h"
#include "RimSeismicData.h"
#include <QFile>
#include <QFileInfo>
CAF_PDM_SOURCE_INIT( RimSeismicDataCollection, "SeismicDataCollection", "SeismicCollection" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicDataCollection::RimSeismicDataCollection()
{
CAF_PDM_InitObject( "Seismic", ":/Seismic16x16.png" );
CAF_PDM_InitFieldNoDefault( &m_seismicData, "SeismicData", "Seismic Data" );
m_seismicData.uiCapability()->setUiTreeHidden( true );
setDeletable( false );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicDataCollection::~RimSeismicDataCollection()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicData* RimSeismicDataCollection::importSeismicFromFile( const QString fileName )
{
RimSeismicData* seisData = new RimSeismicData();
seisData->setFileName( fileName );
QFileInfo fi( fileName );
seisData->setUserDescription( fi.baseName() );
m_seismicData.push_back( seisData );
updateAllRequiredEditors();
return seisData;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSeismicData*> RimSeismicDataCollection::seismicData() const
{
return m_seismicData.children();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSeismicDataCollection::isEmpty()
{
return !m_seismicData.hasChildren();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicDataCollection::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& referringObjects )
{
updateViews();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicDataCollection::updateViews()
{
RimProject* proj = RimProject::current();
std::vector<RimGridView*> views;
proj->allVisibleGridViews( views );
for ( auto view : views )
{
view->scheduleCreateDisplayModelAndRedraw();
}
}

View File

@@ -0,0 +1,49 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2022 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 "cafPdmField.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmObject.h"
#include <QString>
class RimSeismicData;
class RimSeismicDataCollection : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimSeismicDataCollection();
~RimSeismicDataCollection() override;
RimSeismicData* importSeismicFromFile( const QString file );
bool isEmpty();
std::vector<RimSeismicData*> seismicData() const;
protected:
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
void updateViews();
private:
caf::PdmChildArrayField<RimSeismicData*> m_seismicData;
};

View File

@@ -0,0 +1,900 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSeismicSection.h"
#include "RiuMainWindow.h"
#include "RiuSeismicHistogramPanel.h"
#include "Rim3dView.h"
#include "RimRegularLegendConfig.h"
#include "RimSeismicAlphaMapper.h"
#include "RimSeismicData.h"
#include "RimTools.h"
#include "WellPathCommands/PointTangentManipulator/RicPolyline3dEditor.h"
#include "WellPathCommands/RicPolylineTargetsPickEventHandler.h"
#include "RigPolyLinesData.h"
#include "RigTexturedSection.h"
#include "RivSeismicSectionPartMgr.h"
#include "cafPdmUiDoubleSliderEditor.h"
#include "cafPdmUiPushButtonEditor.h"
#include "cafPdmUiSliderEditor.h"
#include "cafPdmUiTableViewEditor.h"
#include "cafPdmUiTreeOrdering.h"
#include "cvfBoundingBox.h"
#include "cvfScalarMapper.h"
#include "cvfTextureImage.h"
#include "cvfVector3.h"
#include <zgyaccess/seismicslice.h>
#include <QDialog>
#include <QImage>
#include <QLayout>
#include <QPixmap>
#include <algorithm>
CAF_PDM_SOURCE_INIT( RimSeismicSection, "SeismicSection" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicSection::RimSeismicSection()
: m_pickTargetsEventHandler( new RicPolylineTargetsPickEventHandler( this ) )
{
CAF_PDM_InitObject( "Seismic Section", ":/Seismic16x16.png" );
CAF_PDM_InitField( &m_userDescription, "UserDecription", QString( "Seismic Section" ), "Name" );
CAF_PDM_InitFieldNoDefault( &m_type, "Type", "Type" );
CAF_PDM_InitFieldNoDefault( &m_seismicData, "SeismicData", "Seismic Data" );
CAF_PDM_InitField( &m_enablePicking, "EnablePicking", false, "" );
caf::PdmUiPushButtonEditor::configureEditorForField( &m_enablePicking );
m_enablePicking.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosType::HIDDEN );
CAF_PDM_InitField( &m_showImage, "ShowImage", false, "" );
caf::PdmUiPushButtonEditor::configureEditorForField( &m_showImage );
m_showImage.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosType::HIDDEN );
CAF_PDM_InitFieldNoDefault( &m_targets, "Targets", "Targets" );
m_targets.uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() );
m_targets.uiCapability()->setUiTreeChildrenHidden( true );
m_targets.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP );
m_targets.uiCapability()->setCustomContextMenuEnabled( true );
CAF_PDM_InitField( &m_inlineIndex, "InlineIndex", -1, "Inline" );
m_inlineIndex.uiCapability()->setUiEditorTypeName( caf::PdmUiSliderEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_xlineIndex, "CrosslineIndex", -1, "Crossline" );
m_xlineIndex.uiCapability()->setUiEditorTypeName( caf::PdmUiSliderEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_depthIndex, "DepthIndex", -1, "Depth Slice" );
m_depthIndex.uiCapability()->setUiEditorTypeName( caf::PdmUiSliderEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_lineThickness, "LineThickness", 1, "Line Thickness" );
CAF_PDM_InitField( &m_lineColor, "LineColor", cvf::Color3f( cvf::Color3f::WHITE ), "Line Color" );
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_InitFieldNoDefault( &m_zFilterType, "DepthFilter", "Depth Filter" );
CAF_PDM_InitField( &m_zUpperThreshold, "UpperThreshold", -1, "Upper Threshold" );
m_zUpperThreshold.uiCapability()->setUiEditorTypeName( caf::PdmUiSliderEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_zLowerThreshold, "LowerThreshold", -1, "Lower Threshold" );
m_zLowerThreshold.uiCapability()->setUiEditorTypeName( caf::PdmUiSliderEditor::uiEditorTypeName() );
this->setUi3dEditorTypeName( RicPolyline3dEditor::uiEditorTypeName() );
setDeletable( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicSection::~RimSeismicSection()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSeismicSection::userDescription()
{
return m_userDescription;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::setUserDescription( QString description )
{
m_userDescription = description;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimSeismicSection::userDescriptionField()
{
return &m_userDescription;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
initSliceRanges();
auto genGrp = uiOrdering.addNewGroup( "General" );
genGrp->add( &m_userDescription );
genGrp->add( &m_seismicData );
if ( m_seismicData() != nullptr )
{
genGrp->add( &m_type );
if ( m_type() == RiaDefines::SeismicSectionType::SS_POLYLINE )
{
auto polyGrp = uiOrdering.addNewGroup( "Polyline Definition" );
polyGrp->add( &m_targets );
polyGrp->add( &m_enablePicking );
}
else if ( m_type() == RiaDefines::SeismicSectionType::SS_INLINE )
{
genGrp->add( &m_inlineIndex );
}
else if ( m_type() == RiaDefines::SeismicSectionType::SS_XLINE )
{
genGrp->add( &m_xlineIndex );
}
else if ( m_type() == RiaDefines::SeismicSectionType::SS_DEPTHSLICE )
{
genGrp->add( &m_depthIndex );
}
auto filterGroup = uiOrdering.addNewGroup( "Depth Filter" );
filterGroup->add( &m_zFilterType );
switch ( zFilterType() )
{
case RimIntersectionFilterEnum::INTERSECT_FILTER_BELOW:
m_zUpperThreshold.uiCapability()->setUiName( "Depth" );
filterGroup->add( &m_zUpperThreshold );
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" );
expGrp->setCollapsedByDefault();
expGrp->add( &m_transparent );
auto outlGrp = uiOrdering.addNewGroup( "Outline" );
outlGrp->add( &m_lineThickness );
outlGrp->add( &m_lineColor );
outlGrp->add( &m_showSeismicOutline );
if ( m_type() == RiaDefines::SeismicSectionType::SS_POLYLINE ) outlGrp->add( &m_showSectionLine );
outlGrp->setCollapsedByDefault();
}
if ( m_type() != RiaDefines::SeismicSectionType::SS_POLYLINE ) uiOrdering.add( &m_showImage );
uiOrdering.skipRemainingFields();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= "" */ )
{
uiTreeOrdering.skipRemainingChildren();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute )
{
if ( field == &m_enablePicking )
{
auto* pbAttribute = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>( attribute );
if ( pbAttribute )
{
if ( !m_enablePicking )
{
pbAttribute->m_buttonText = "Start Picking Points";
}
else
{
pbAttribute->m_buttonText = "Stop Picking Points";
}
}
}
else if ( field == &m_showImage )
{
auto* pbAttribute = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>( attribute );
if ( pbAttribute )
{
pbAttribute->m_buttonText = "Show Image";
}
}
else if ( field == &m_targets )
{
auto tvAttribute = dynamic_cast<caf::PdmUiTableViewEditorAttribute*>( attribute );
if ( tvAttribute )
{
tvAttribute->resizePolicy = caf::PdmUiTableViewEditorAttribute::RESIZE_TO_FIT_CONTENT;
if ( m_enablePicking )
{
tvAttribute->baseColor.setRgb( 255, 220, 255 );
tvAttribute->alwaysEnforceResizePolicy = true;
}
}
}
else if ( ( field == &m_depthIndex ) || ( field == &m_inlineIndex ) || ( field == &m_xlineIndex ) )
{
if ( m_seismicData() != nullptr )
{
auto* sliderAttrib = dynamic_cast<caf::PdmUiSliderEditorAttribute*>( attribute );
if ( sliderAttrib != nullptr )
{
sliderAttrib->m_showSpinBox = true;
int minVal = m_seismicData()->inlineMin();
int maxVal = m_seismicData()->inlineMax();
int stepVal = m_seismicData()->inlineStep();
if ( field == &m_xlineIndex )
{
minVal = m_seismicData()->xlineMin();
maxVal = m_seismicData()->xlineMax();
stepVal = m_seismicData()->xlineStep();
}
else if ( field == &m_depthIndex )
{
minVal = m_seismicData()->zMin();
maxVal = m_seismicData()->zMax();
stepVal = m_seismicData()->zStep();
}
sliderAttrib->m_maximum = maxVal;
sliderAttrib->m_minimum = minVal;
sliderAttrib->m_step = stepVal;
}
}
}
else if ( ( field == &m_zUpperThreshold ) || ( field == &m_zLowerThreshold ) )
{
auto* sliderAttrib = dynamic_cast<caf::PdmUiSliderEditorAttribute*>( attribute );
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();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::setSectionType( RiaDefines::SeismicSectionType sectionType )
{
m_type = sectionType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::enablePicking( bool enable )
{
m_enablePicking = enable;
updateConnectedEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSeismicSection::pickingEnabled() const
{
return m_enablePicking();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PickEventHandler* RimSeismicSection::pickEventHandler() const
{
return m_pickTargetsEventHandler.get();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimPolylineTarget*> RimSeismicSection::activeTargets() const
{
return m_targets.children();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::insertTarget( const RimPolylineTarget* targetToInsertBefore, RimPolylineTarget* targetToInsert )
{
size_t index = m_targets.indexOf( targetToInsertBefore );
if ( index < m_targets.size() )
m_targets.insert( index, targetToInsert );
else
m_targets.push_back( targetToInsert );
updateVisualization();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::deleteTarget( RimPolylineTarget* targetToDelete )
{
m_targets.removeChild( targetToDelete );
delete targetToDelete;
updateVisualization();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::updateVisualization()
{
if ( texturedSection().notNull() ) texturedSection()->setWhatToUpdate( RigTexturedSection::WhatToUpdateEnum::UPDATE_GEOMETRY );
scheduleViewUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::initAfterRead()
{
resolveReferencesRecursively();
if ( m_seismicData != nullptr )
{
m_seismicData->legendConfig()->changed.connect( this, &RimSeismicSection::onLegendConfigChanged );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::updateEditorsAndVisualization()
{
updateConnectedEditors();
updateVisualization();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::scheduleViewUpdate()
{
Rim3dView* view = nullptr;
firstAncestorOrThisOfType( view );
if ( view ) view->scheduleCreateDisplayModelAndRedraw();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<RigPolyLinesData> RimSeismicSection::polyLinesData() const
{
cvf::ref<RigPolyLinesData> pld = new RigPolyLinesData;
if ( ( m_type() == RiaDefines::SeismicSectionType::SS_POLYLINE ) && m_showSectionLine() )
{
std::vector<cvf::Vec3d> line;
for ( const RimPolylineTarget* target : m_targets )
{
line.push_back( target->targetPointXYZ() );
}
pld->setPolyLine( line );
}
if ( m_showSeismicOutline() && m_seismicData() != nullptr )
{
std::vector<cvf::Vec3d> outline = m_seismicData()->worldOutline();
if ( outline.size() == 8 )
{
std::vector<cvf::Vec3d> box;
for ( auto i : { 4, 0, 1, 3, 2, 0 } )
box.push_back( outline[i] );
pld->addPolyLine( box );
box.clear();
for ( auto i : { 1, 5, 4, 6, 7, 5 } )
box.push_back( outline[i] );
pld->addPolyLine( box );
box.clear();
box.push_back( outline[2] );
box.push_back( outline[6] );
pld->addPolyLine( box );
box.clear();
box.push_back( outline[3] );
box.push_back( outline[7] );
pld->addPolyLine( box );
}
}
pld->setLineAppearance( m_lineThickness, m_lineColor, false );
pld->setZPlaneLock( false, 0.0 );
if ( isChecked() )
{
pld->setVisibility( true, false );
}
else
{
pld->setVisibility( false, false );
}
return pld;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivSeismicSectionPartMgr* RimSeismicSection::partMgr()
{
if ( m_sectionPartMgr.isNull() ) m_sectionPartMgr = new RivSeismicSectionPartMgr( this );
return m_sectionPartMgr.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimSeismicSection::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
{
QList<caf::PdmOptionItemInfo> options;
if ( fieldNeedingOptions == &m_seismicData )
{
Rim3dView* view = nullptr;
firstAncestorOrThisOfType( view );
if ( view != nullptr ) RimTools::seismicDataOptionItems( &options, view->domainBoundingBox() );
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<RigTexturedSection> RimSeismicSection::texturedSection()
{
if ( m_texturedSection.isNull() ) m_texturedSection = new RigTexturedSection();
if ( m_texturedSection->isValid() || ( m_seismicData == nullptr ) ) return m_texturedSection;
std::vector<cvf::Vec3dArray> rects;
std::vector<int> widths;
double zmin = upperFilterZ( m_seismicData->zMin() );
double zmax = lowerFilterZ( m_seismicData->zMax() );
if ( zmax <= zmin ) return m_texturedSection;
if ( m_type() == RiaDefines::SeismicSectionType::SS_POLYLINE )
{
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 );
for ( int i = 1; 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 ) );
}
}
}
else if ( m_type() == RiaDefines::SeismicSectionType::SS_INLINE )
{
bool valid = m_texturedSection->partsCount() == 1;
if ( valid )
valid = m_texturedSection->part( 0 ).isRectValid;
else
m_texturedSection->resize( 1 );
int ilStart = m_inlineIndex();
if ( !valid )
{
int xlStart = m_seismicData->xlineMin();
int xlStop = m_seismicData->xlineMax();
cvf::Vec3dArray points;
points.resize( 4 );
points[0] = m_seismicData->convertToWorldCoords( ilStart, xlStart, -zmax );
points[1] = m_seismicData->convertToWorldCoords( ilStart, xlStop, -zmax );
points[2] = m_seismicData->convertToWorldCoords( ilStart, xlStop, -zmin );
points[3] = m_seismicData->convertToWorldCoords( ilStart, xlStart, -zmin );
m_texturedSection->setSectionPartRect( 0, points );
}
if ( m_texturedSection->part( 0 ).sliceData == nullptr )
{
m_texturedSection->setSectionPartData( 0, m_seismicData->sliceData( RiaDefines::SeismicSliceDirection::INLINE, ilStart, zmin, zmax ) );
}
}
else if ( m_type() == RiaDefines::SeismicSectionType::SS_XLINE )
{
bool valid = m_texturedSection->partsCount() == 1;
if ( valid )
valid = m_texturedSection->part( 0 ).isRectValid;
else
m_texturedSection->resize( 1 );
int xlStart = m_xlineIndex();
if ( !valid )
{
int ilStart = m_seismicData->inlineMin();
int ilStop = m_seismicData->inlineMax();
cvf::Vec3dArray points;
points.resize( 4 );
points[0] = m_seismicData->convertToWorldCoords( ilStart, xlStart, -zmax );
points[1] = m_seismicData->convertToWorldCoords( ilStop, xlStart, -zmax );
points[2] = m_seismicData->convertToWorldCoords( ilStop, xlStart, -zmin );
points[3] = m_seismicData->convertToWorldCoords( ilStart, xlStart, -zmin );
m_texturedSection->setSectionPartRect( 0, points );
}
if ( m_texturedSection->part( 0 ).sliceData == nullptr )
{
m_texturedSection->setSectionPartData( 0, m_seismicData->sliceData( RiaDefines::SeismicSliceDirection::XLINE, xlStart, zmin, zmax ) );
}
}
else if ( m_type() == RiaDefines::SeismicSectionType::SS_DEPTHSLICE )
{
bool valid = m_texturedSection->partsCount() == 1;
if ( valid )
valid = m_texturedSection->part( 0 ).isRectValid;
else
m_texturedSection->resize( 1 );
int zIndex = m_depthIndex();
if ( !valid )
{
int ilStart = m_seismicData->inlineMin();
int ilStop = m_seismicData->inlineMax();
int xlStart = m_seismicData->xlineMin();
int xlStop = m_seismicData->xlineMax();
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();
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 ) );
}
}
return m_texturedSection;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
{
if ( changedField == &m_enablePicking )
{
this->updateConnectedEditors();
}
else if ( changedField == &m_showImage )
{
QDialog w;
QLabel l;
QHBoxLayout layout;
layout.addWidget( &l );
w.setLayout( &layout );
QPixmap i = getImage();
l.setPixmap( i );
w.exec();
m_showImage = false;
}
else if ( changedField != &m_userDescription )
{
RigTexturedSection::WhatToUpdateEnum updateType = RigTexturedSection::WhatToUpdateEnum::UPDATE_NONE;
if ( changedField == &m_seismicData )
{
RiuMainWindow::instance()->seismicHistogramPanel()->showHistogram( m_seismicData() );
initSliceRanges();
PdmObjectHandle* prevValue = oldValue.value<caf::PdmPointer<PdmObjectHandle>>().rawPtr();
auto prevSeisData = dynamic_cast<RimSeismicData*>( prevValue );
if ( prevSeisData != nullptr )
{
prevSeisData->legendConfig()->changed.disconnect( this );
}
m_seismicData->legendConfig()->changed.connect( this, &RimSeismicSection::onLegendConfigChanged );
updateType = RigTexturedSection::WhatToUpdateEnum::UPDATE_ALL;
}
else if ( ( changedField == &m_type ) || ( changedField == &m_targets ) || ( changedField == &m_depthIndex ) ||
( changedField == &m_inlineIndex ) || ( changedField == &m_xlineIndex ) || changedField == &m_zFilterType ||
changedField == &m_zLowerThreshold || changedField == &m_zUpperThreshold )
{
updateType = RigTexturedSection::WhatToUpdateEnum::UPDATE_GEOMETRY;
}
else if ( changedField == &m_transparent )
{
updateType = RigTexturedSection::WhatToUpdateEnum::UPDATE_TEXTURE;
}
texturedSection()->setWhatToUpdate( updateType );
scheduleViewUpdate();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicData* RimSeismicSection::seismicData() const
{
return m_seismicData();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::setSeismicData( RimSeismicData* seisData )
{
if ( m_seismicData != nullptr ) m_seismicData->legendConfig()->changed.disconnect( this );
m_seismicData = seisData;
if ( seisData != nullptr ) m_seismicData->legendConfig()->changed.connect( this, &RimSeismicSection::onLegendConfigChanged );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimRegularLegendConfig* RimSeismicSection::legendConfig() const
{
if ( seismicData() != nullptr ) return seismicData()->legendConfig();
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicAlphaMapper* RimSeismicSection::alphaValueMapper() const
{
if ( seismicData() != nullptr ) return seismicData()->alphaValueMapper();
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSeismicSection::isTransparent() const
{
return m_transparent;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::initSliceRanges()
{
if ( m_seismicData() == nullptr ) return;
if ( m_zLowerThreshold < 0 ) m_zLowerThreshold = m_seismicData->zMax();
if ( m_zUpperThreshold < 0 ) m_zUpperThreshold = m_seismicData->zMin();
m_inlineIndex = std::clamp( m_inlineIndex(), m_seismicData->inlineMin(), m_seismicData->inlineMax() );
m_xlineIndex = std::clamp( m_xlineIndex(), m_seismicData->xlineMin(), m_seismicData->xlineMax() );
m_depthIndex = std::clamp( m_depthIndex(), (int)m_seismicData->zMin(), (int)m_seismicData->zMax() );
m_zLowerThreshold = std::clamp( m_zLowerThreshold(), (int)m_seismicData->zMin(), (int)m_seismicData->zMax() );
m_zUpperThreshold = std::clamp( m_zUpperThreshold(), (int)m_seismicData->zMin(), (int)m_seismicData->zMax() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QPixmap RimSeismicSection::getImage()
{
RiaDefines::SeismicSliceDirection sliceDir = RiaDefines::SeismicSliceDirection::INLINE;
int iStart = m_inlineIndex();
if ( m_type() == RiaDefines::SeismicSectionType::SS_XLINE )
{
sliceDir = RiaDefines::SeismicSliceDirection::XLINE;
iStart = m_xlineIndex();
}
else if ( m_type() == RiaDefines::SeismicSectionType::SS_DEPTHSLICE )
{
sliceDir = RiaDefines::SeismicSliceDirection::DEPTH;
iStart = m_depthIndex();
}
double zmin = upperFilterZ( m_seismicData->zMin() );
double zmax = lowerFilterZ( m_seismicData->zMax() );
auto data = m_seismicData->sliceData( sliceDir, iStart, zmin, zmax );
auto mapper = legendConfig()->scalarMapper();
float* pData = data->values();
QImage img( data->width(), data->depth(), QImage::Format_RGB888 );
for ( int i = 0; i < data->width(); i++ )
{
for ( int j = 0; j < data->depth(); j++ )
{
auto rgb = mapper->mapToColor( *pData );
QColor color( rgb.r(), rgb.g(), rgb.b() );
img.setPixel( i, j, color.rgb() );
pData++;
}
}
return QPixmap::fromImage( img );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSection::onLegendConfigChanged( const caf::SignalEmitter* emitter, RimLegendConfigChangeType changeType )
{
RigTexturedSection::WhatToUpdateEnum updateType = RigTexturedSection::WhatToUpdateEnum::UPDATE_GEOMETRY;
switch ( changeType )
{
case RimLegendConfigChangeType::COLORS:
case RimLegendConfigChangeType::COLOR_MODE:
updateType = RigTexturedSection::WhatToUpdateEnum::UPDATE_TEXTURE;
break;
case RimLegendConfigChangeType::ALL:
case RimLegendConfigChangeType::RANGE:
updateType = RigTexturedSection::WhatToUpdateEnum::UPDATE_DATA;
break;
case RimLegendConfigChangeType::LEVELS:
case RimLegendConfigChangeType::NUMBER_FORMAT:
case RimLegendConfigChangeType::VISIBILITY:
updateType = RigTexturedSection::WhatToUpdateEnum::UPDATE_NONE;
break;
default:
break;
}
texturedSection()->setWhatToUpdate( updateType );
if ( m_isChecked() ) scheduleViewUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimIntersectionFilterEnum RimSeismicSection::zFilterType() const
{
return m_zFilterType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSeismicSection::upperFilterZ( int upperGridLimit ) const
{
switch ( zFilterType() )
{
case RimIntersectionFilterEnum::INTERSECT_FILTER_BELOW:
case RimIntersectionFilterEnum::INTERSECT_FILTER_BETWEEN:
return m_zUpperThreshold;
case RimIntersectionFilterEnum::INTERSECT_FILTER_ABOVE:
case RimIntersectionFilterEnum::INTERSECT_FILTER_NONE:
default:
return upperGridLimit;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSeismicSection::lowerFilterZ( int lowerGridLimit ) const
{
switch ( zFilterType() )
{
case RimIntersectionFilterEnum::INTERSECT_FILTER_ABOVE:
case RimIntersectionFilterEnum::INTERSECT_FILTER_BETWEEN:
return m_zLowerThreshold;
case RimIntersectionFilterEnum::INTERSECT_FILTER_BELOW:
case RimIntersectionFilterEnum::INTERSECT_FILTER_NONE:
default:
return lowerGridLimit;
}
}

View File

@@ -0,0 +1,137 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaSeismicDefines.h"
#include "RimCheckableNamedObject.h"
#include "RimIntersectionEnums.h"
#include "RimLegendConfigChangeType.h"
#include "RimPolylinePickerInterface.h"
#include "RimPolylinesDataInterface.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmField.h"
#include "cafPdmFieldCvfColor.h"
#include "cafPdmFieldCvfVec3d.h"
#include "cafPdmPtrField.h"
#include "cvfArray.h"
#include "cvfColor3.h"
#include "cvfObject.h"
#include <QList>
#include <QString>
class RicPolylineTargetsPickEventHandler;
class RimPolylineTarget;
class RigPolylinesData;
class RigTexturedSection;
class RivSeismicSectionPartMgr;
class Rim3dView;
class RimSeismicData;
class RimRegularLegendConfig;
class RimSeismicAlphaMapper;
class RimSeismicSection : public RimCheckableNamedObject, public RimPolylinePickerInterface, public RimPolylinesDataInterface
{
CAF_PDM_HEADER_INIT;
public:
RimSeismicSection();
~RimSeismicSection() override;
QString userDescription();
void setUserDescription( QString description );
void updateVisualization() override;
void updateEditorsAndVisualization() override;
void insertTarget( const RimPolylineTarget* targetToInsertBefore, RimPolylineTarget* targetToInsert ) override;
void deleteTarget( RimPolylineTarget* targetToDelete ) override;
void enablePicking( bool enable );
void setSectionType( RiaDefines::SeismicSectionType sectionType );
std::vector<RimPolylineTarget*> activeTargets() const override;
bool pickingEnabled() const override;
caf::PickEventHandler* pickEventHandler() const override;
cvf::ref<RigPolyLinesData> polyLinesData() const override;
cvf::ref<RigTexturedSection> texturedSection();
RivSeismicSectionPartMgr* partMgr();
RimSeismicData* seismicData() const;
void setSeismicData( RimSeismicData* seisData );
RimRegularLegendConfig* legendConfig() const;
RimSeismicAlphaMapper* alphaValueMapper() const;
bool isTransparent() const;
int upperFilterZ( int upperGridLimit ) const;
int lowerFilterZ( int lowerGridLimit ) const;
RimIntersectionFilterEnum zFilterType() const;
protected:
void initAfterRead() override;
caf::PdmFieldHandle* userDescriptionField() override;
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
private:
void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
void onLegendConfigChanged( const caf::SignalEmitter* emitter, RimLegendConfigChangeType changeType );
void initSliceRanges();
void scheduleViewUpdate();
QPixmap getImage();
caf::PdmField<QString> m_userDescription;
caf::PdmPtrField<RimSeismicData*> m_seismicData;
caf::PdmField<caf::AppEnum<RiaDefines::SeismicSectionType>> m_type;
caf::PdmChildArrayField<RimPolylineTarget*> m_targets;
caf::PdmField<bool> m_showSeismicOutline;
caf::PdmField<bool> m_enablePicking;
caf::PdmField<bool> m_showSectionLine;
caf::PdmField<int> m_lineThickness;
caf::PdmField<cvf::Color3f> m_lineColor;
caf::PdmField<bool> m_transparent;
caf::PdmField<bool> m_showImage;
caf::PdmField<int> m_inlineIndex;
caf::PdmField<int> m_xlineIndex;
caf::PdmField<int> m_depthIndex;
caf::PdmField<caf::AppEnum<RimIntersectionFilterEnum>> m_zFilterType;
caf::PdmField<int> m_zUpperThreshold;
caf::PdmField<int> m_zLowerThreshold;
std::shared_ptr<RicPolylineTargetsPickEventHandler> m_pickTargetsEventHandler;
cvf::ref<RivSeismicSectionPartMgr> m_sectionPartMgr;
cvf::ref<RigTexturedSection> m_texturedSection;
};

View File

@@ -0,0 +1,260 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSeismicSectionCollection.h"
#include "RiuViewer.h"
#include "Rim3dView.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimRegularLegendConfig.h"
#include "RimSeismicData.h"
#include "RimSeismicDataCollection.h"
#include "RimSeismicSection.h"
#include "RivSeismicSectionPartMgr.h"
#include "cvfBoundingBox.h"
#include "cvfModelBasicList.h"
#include "cafDisplayCoordTransform.h"
CAF_PDM_SOURCE_INIT( RimSeismicSectionCollection, "SeismicSectionCollection" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicSectionCollection::RimSeismicSectionCollection()
{
CAF_PDM_InitObject( "Seismic Sections", ":/Seismic16x16.png" );
CAF_PDM_InitField( &m_userDescription, "UserDecription", QString( "Seismic Sections" ), "Name" );
CAF_PDM_InitFieldNoDefault( &m_seismicSections, "SeismicSections", "SeismicSections" );
m_seismicSections.uiCapability()->setUiTreeHidden( true );
setName( "Seismic Sections" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicSectionCollection::~RimSeismicSectionCollection()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSeismicSection* RimSeismicSectionCollection::addNewSection( RiaDefines::SeismicSectionType sectionType )
{
Rim3dView* view = nullptr;
firstAncestorOrThisOfType( view );
if ( view == nullptr ) return nullptr;
RimSeismicData* defaultSeis = nullptr;
RimProject* proj = RimProject::current();
if ( proj )
{
const auto& coll = proj->activeOilField()->seismicCollection().p();
for ( auto* c : coll->seismicData() )
{
if ( c->boundingBox()->intersects( view->domainBoundingBox() ) )
{
defaultSeis = c;
break;
}
}
}
RimSeismicSection* newSection = new RimSeismicSection();
if ( defaultSeis != nullptr ) newSection->setSeismicData( defaultSeis );
newSection->setSectionType( sectionType );
m_seismicSections.push_back( newSection );
updateAllRequiredEditors();
updateView();
return newSection;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSeismicSectionCollection::empty()
{
return m_seismicSections.empty();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSeismicSectionCollection::size()
{
return static_cast<int>( m_seismicSections.size() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSeismicSectionCollection::userDescription()
{
return m_userDescription;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSectionCollection::setUserDescription( QString description )
{
m_userDescription = description;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimSeismicSectionCollection::userDescriptionField()
{
return &m_userDescription;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSectionCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.skipRemainingFields( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSeismicSection*> RimSeismicSectionCollection::seismicSections() const
{
return m_seismicSections.children();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSectionCollection::appendPartsToModel( Rim3dView* view,
cvf::ModelBasicList* model,
caf::DisplayCoordTransform* transform,
const cvf::BoundingBox& boundingBox )
{
if ( !isChecked() ) return;
for ( auto& section : m_seismicSections )
{
if ( section->isChecked() )
{
if ( section->seismicData() != nullptr )
{
section->partMgr()->appendGeometryPartsToModel( model, transform, boundingBox );
}
section->partMgr()->appendPolylinePartsToModel( view, model, transform, boundingBox );
}
}
model->updateBoundingBoxesRecursive();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSectionCollection::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
{
if ( changedField == objectToggleField() )
{
updateView();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimRegularLegendConfig*> RimSeismicSectionCollection::legendConfigs()
{
std::vector<RimRegularLegendConfig*> retVals;
std::set<RimSeismicData*> usedSeisData;
for ( auto& section : m_seismicSections )
{
auto seisData = section->seismicData();
if ( usedSeisData.contains( seisData ) ) continue;
retVals.push_back( seisData->legendConfig() );
usedSeisData.insert( seisData );
}
return retVals;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSectionCollection::updateLegendRangesTextAndVisibility( RiuViewer* nativeOrOverrideViewer, bool isUsingOverrideViewer )
{
for ( auto& section : m_seismicSections )
{
if ( section->legendConfig() )
{
auto legendConfig = section->legendConfig();
QString subtitle;
if ( section->seismicData() )
{
subtitle = section->seismicData()->userDescription();
const int maxChar = 20;
if ( subtitle.size() > maxChar )
{
subtitle = subtitle.left( maxChar - 2 );
subtitle += "..";
}
}
legendConfig->setTitle( QString( "Seismic: \n" ) + subtitle );
if ( section->isChecked() && legendConfig->showLegend() )
{
nativeOrOverrideViewer->addColorLegendToBottomLeftCorner( legendConfig->titledOverlayFrame(), isUsingOverrideViewer );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSectionCollection::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray,
std::vector<caf::PdmObjectHandle*>& referringObjects )
{
updateView();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSectionCollection::updateView()
{
Rim3dView* view = nullptr;
firstAncestorOrThisOfType( view );
if ( view ) view->scheduleCreateDisplayModelAndRedraw();
}

View File

@@ -0,0 +1,84 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaSeismicDefines.h"
#include "RimCheckableNamedObject.h"
#include "cafPdmChildArrayField.h"
#include <vector>
class RimRegularLegendConfig;
class RimSeismicSection;
class Rim3dView;
class RiuViewer;
namespace cvf
{
class ModelBasicList;
class Transform;
class BoundingBox;
} // namespace cvf
namespace caf
{
class DisplayCoordTransform;
}
class RimSeismicSectionCollection : public RimCheckableNamedObject
{
CAF_PDM_HEADER_INIT;
public:
RimSeismicSectionCollection();
~RimSeismicSectionCollection() override;
RimSeismicSection* addNewSection( RiaDefines::SeismicSectionType sectionType = RiaDefines::SeismicSectionType::SS_INLINE );
std::vector<RimSeismicSection*> seismicSections() const;
bool empty();
int size();
QString userDescription();
void setUserDescription( QString description );
void appendPartsToModel( Rim3dView* view,
cvf::ModelBasicList* model,
caf::DisplayCoordTransform* scaleTransform,
const cvf::BoundingBox& boundingBox );
std::vector<RimRegularLegendConfig*> legendConfigs();
void updateLegendRangesTextAndVisibility( RiuViewer* nativeOrOverrideViewer, bool isUsingOverrideViewer );
protected:
caf::PdmFieldHandle* userDescriptionField() override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
void updateView();
private:
caf::PdmField<QString> m_userDescription;
caf::PdmChildArrayField<RimSeismicSection*> m_seismicSections;
};