diff --git a/ApplicationExeCode/CMakeLists.txt b/ApplicationExeCode/CMakeLists.txt index 9ca62df5e1..dd7666c16c 100644 --- a/ApplicationExeCode/CMakeLists.txt +++ b/ApplicationExeCode/CMakeLists.txt @@ -322,6 +322,10 @@ if(MSVC) set(RESINSIGHT_USE_ODB_API 1) endif() + if(NOT ${RESINSIGHT_OPENVDS_API_DIR} EQUAL "") + set(RESINSIGHT_USE_OPENVDS_API 1) + endif() + # Odb Dlls if(RESINSIGHT_USE_ODB_API) # Find all the dlls @@ -338,6 +342,16 @@ if(MSVC) endforeach() endif() + # OpenVDS Dlls + if(RESINSIGHT_USE_OPENVDS_API) + set(OPENVDS_DLL_NAMES openvds segyutils) + foreach(OPENVDS_DLL_NAME ${OPENVDS_DLL_NAMES}) + list(APPEND RI_DLL_FILENAMES + ${RESINSIGHT_OPENVDS_API_DIR}/lib/${OPENVDS_DLL_NAME}.dll + ) + endforeach(OPENVDS_DLL_NAME) + endif() + # HDF5 Dlls if(RESINSIGHT_FOUND_HDF5) set(HDF5_DLL_NAMES hdf5 hdf5_cpp szip zlib) diff --git a/ApplicationLibCode/CMakeLists.txt b/ApplicationLibCode/CMakeLists.txt index 422cdafca2..f0316c3c22 100644 --- a/ApplicationLibCode/CMakeLists.txt +++ b/ApplicationLibCode/CMakeLists.txt @@ -255,6 +255,21 @@ endif() add_subdirectory(GeoMech/GeoMechDataModel) list(APPEND RI_LIBRARIES RigGeoMechDataModel) +# +# OpenVDS +# +if(RESINSIGHT_USE_OPENVDS_API) + set(OPENVDS_FILES FileInterface/RifOpenVDSReader.h + FileInterface/RifOpenVDSReader.cpp + ) + + list(APPEND CPP_SOURCES ${OPENVDS_FILES}) + + add_definitions(-DUSE_OPENVDS) + + include_directories(${RESINSIGHT_OPENVDS_API_DIR}/include) +endif() + # # HDF5 # diff --git a/ApplicationLibCode/Commands/CMakeLists.txt b/ApplicationLibCode/Commands/CMakeLists.txt index 652942ecc4..2145d2c1ef 100644 --- a/ApplicationLibCode/Commands/CMakeLists.txt +++ b/ApplicationLibCode/Commands/CMakeLists.txt @@ -66,7 +66,6 @@ target_include_directories( ${CMAKE_SOURCE_DIR}/ThirdParty/custom-opm-common/generated-opm-common ${CMAKE_SOURCE_DIR}/ThirdParty/custom-opm-common/opm-common ${CMAKE_SOURCE_DIR}/ThirdParty/qtadvanceddocking/src - ${CMAKE_SOURCE_DIR}/ThirdParty/openzgy/include ) if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") diff --git a/ApplicationLibCode/Commands/SeismicCommands/RicImportSeismicFeature.cpp b/ApplicationLibCode/Commands/SeismicCommands/RicImportSeismicFeature.cpp index 490d9c1fb3..0d6d853dee 100644 --- a/ApplicationLibCode/Commands/SeismicCommands/RicImportSeismicFeature.cpp +++ b/ApplicationLibCode/Commands/SeismicCommands/RicImportSeismicFeature.cpp @@ -49,12 +49,15 @@ bool RicImportSeismicFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicImportSeismicFeature::onActionTriggered( bool isChecked ) { +#ifdef USE_OPENVDS + QString filter = "Seismic files (*.zgy *.vds);;All Files (*.*)"; +#else + QString filter = "Seismic files (*.zgy);;All Files (*.*)"; +#endif + RiaApplication* app = RiaApplication::instance(); QString defaultDir = app->lastUsedDialogDirectory( "SEISMIC_GRID" ); - QString fileName = RiuFileDialogTools::getOpenFileName( Riu3DMainWindowTools::mainWindowWidget(), - "Import Seismic", - defaultDir, - "Seismic files (*.zgy);;All Files (*.*)" ); + QString fileName = RiuFileDialogTools::getOpenFileName( Riu3DMainWindowTools::mainWindowWidget(), "Import Seismic", defaultDir, filter ); if ( fileName.isEmpty() ) return; diff --git a/ApplicationLibCode/FileInterface/CMakeLists_files.cmake b/ApplicationLibCode/FileInterface/CMakeLists_files.cmake index 35b816ba1b..e00c47ebd4 100644 --- a/ApplicationLibCode/FileInterface/CMakeLists_files.cmake +++ b/ApplicationLibCode/FileInterface/CMakeLists_files.cmake @@ -77,6 +77,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RifRftSegment.h ${CMAKE_CURRENT_LIST_DIR}/RifPressureDepthTextFileReader.h ${CMAKE_CURRENT_LIST_DIR}/RifReaderPressureDepthData.h + ${CMAKE_CURRENT_LIST_DIR}/RifSeismicReader.h ${CMAKE_CURRENT_LIST_DIR}/RifSeismicZGYReader.h ${CMAKE_CURRENT_LIST_DIR}/RifOpmGridTools.h ${CMAKE_CURRENT_LIST_DIR}/RifCsvSummaryReader.h @@ -161,6 +162,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RifRftSegment.cpp ${CMAKE_CURRENT_LIST_DIR}/RifPressureDepthTextFileReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifReaderPressureDepthData.cpp + ${CMAKE_CURRENT_LIST_DIR}/RifSeismicReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifSeismicZGYReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifOpmGridTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RifCsvSummaryReader.cpp diff --git a/ApplicationLibCode/FileInterface/RifOpenVDSReader.cpp b/ApplicationLibCode/FileInterface/RifOpenVDSReader.cpp new file mode 100644 index 0000000000..e6c414b6eb --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifOpenVDSReader.cpp @@ -0,0 +1,518 @@ + +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RifOpenVDSReader.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include "cvfBoundingBox.h" + +constexpr int VDS_INLINE_DIM = 2; +constexpr int VDS_XLINE_DIM = 1; +constexpr int VDS_Z_DIM = 0; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifOpenVDSReader::RifOpenVDSReader() + : m_filename( "" ) + , m_handle( nullptr ) + , m_dataChannelToUse( 0 ) + , m_layout( nullptr ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifOpenVDSReader::~RifOpenVDSReader() +{ + close(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifOpenVDSReader::open( QString filename ) +{ + close(); + + m_filename = filename; + + try + { + OpenVDS::Error error; + m_handle = OpenVDS::Open( filename.toStdString(), "", error ); + + if ( error.code != 0 ) + { + m_handle = nullptr; + return false; + } + + auto accessManager = OpenVDS::GetAccessManager( m_handle ); + m_layout = accessManager.GetVolumeDataLayout(); + if ( m_layout == nullptr ) + { + close(); + return false; + } + m_coordinateTransform = std::make_unique( m_layout ); + } + catch ( const std::exception& ) + { + m_handle = nullptr; + return false; + } + + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifOpenVDSReader::isOpen() const +{ + return ( m_handle != nullptr ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifOpenVDSReader::isValid() +{ + if ( !isOpen() ) return false; + + auto iAxis = m_layout->GetAxisDescriptor( VDS_INLINE_DIM ); + auto xAxis = m_layout->GetAxisDescriptor( VDS_XLINE_DIM ); + auto zAxis = m_layout->GetAxisDescriptor( VDS_Z_DIM ); + + return ( iAxis.GetCoordinateStep() > 0 ) && ( xAxis.GetCoordinateStep() > 0 ) && ( zAxis.GetCoordinateStep() > 0 ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifOpenVDSReader::close() +{ + if ( !isOpen() ) return; + + try + { + OpenVDS::Close( m_handle ); + } + catch ( const std::exception& ) + { + } + + m_handle = nullptr; + m_layout = nullptr; + + return; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString openvds_dataFormatToString( OpenVDS::VolumeDataFormat format ) +{ + switch ( format ) + { + case OpenVDS::VolumeDataFormat::Format_1Bit: + return "1-bit"; + case OpenVDS::VolumeDataFormat::Format_U8: + return "Unsigned 8-bit"; + case OpenVDS::VolumeDataFormat::Format_U16: + return "Unsigned 16-bit"; + case OpenVDS::VolumeDataFormat::Format_R32: + return "Float (32-bit)"; + case OpenVDS::VolumeDataFormat::Format_U32: + return "Unsigned 32-bit"; + case OpenVDS::VolumeDataFormat::Format_R64: + return "Double (64-bit)"; + case OpenVDS::VolumeDataFormat::Format_U64: + return "Unsigned 64-bit"; + case OpenVDS::VolumeDataFormat::Format_Any: + default: + break; + } + + return "Unknown"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString openvds_axisToString( OpenVDS::VolumeDataAxisDescriptor axis ) +{ + return QString( "%1 - %2, step %3" ).arg( axis.GetCoordinateMin() ).arg( axis.GetCoordinateMax() ).arg( axis.GetCoordinateStep() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector> RifOpenVDSReader::metaData() +{ + std::vector> retValues; + + if ( !isOpen() ) return retValues; + + QString version( OpenVDS::GetOpenVDSVersion() ); + retValues.push_back( std::make_pair( QString( "Open VDS version" ), QString( OpenVDS::GetOpenVDSVersion() ) ) ); + + QString compressed( "No" ); + if ( OpenVDS::GetCompressionMethod( m_handle ) != OpenVDS::CompressionMethod::None ) compressed = "Yes"; + retValues.push_back( std::make_pair( QString( "Compression" ), compressed ) ); + + retValues.push_back( std::make_pair( QString( "Inline" ), openvds_axisToString( m_layout->GetAxisDescriptor( VDS_INLINE_DIM ) ) ) ); + retValues.push_back( std::make_pair( QString( "Xline" ), openvds_axisToString( m_layout->GetAxisDescriptor( VDS_XLINE_DIM ) ) ) ); + retValues.push_back( std::make_pair( QString( "Z" ), openvds_axisToString( m_layout->GetAxisDescriptor( VDS_Z_DIM ) ) ) ); + + const int dimensions = m_layout->GetDimensionality(); + retValues.push_back( std::make_pair( QString( "Dimensions" ), QString::number( dimensions ) ) ); + + const int channels = m_layout->GetChannelCount(); + retValues.push_back( std::make_pair( QString( "Data Channels" ), QString::number( channels ) ) ); + + for ( int i = 0; i < channels; i++ ) + { + QString prefix = QString( "Data Channel %1 " ).arg( i ); + + auto chanDesc = m_layout->GetChannelDescriptor( i ); + + QString chanName( chanDesc.GetName() ); + retValues.push_back( std::make_pair( prefix + "Name", chanName ) ); + retValues.push_back( std::make_pair( prefix + "Format", openvds_dataFormatToString( chanDesc.GetFormat() ) ) ); + QString range = QString( "%1 - %2" ).arg( chanDesc.GetValueRangeMin() ).arg( chanDesc.GetValueRangeMax() ); + retValues.push_back( std::make_pair( prefix + "Range", range ) ); + + if ( chanName.toLower() == "amplitude" ) m_dataChannelToUse = i; + } + + return retValues; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifOpenVDSReader::histogramData( std::vector& xvals, std::vector& yvals ) +{ + if ( !isOpen() ) return; + + auto iMinMaxStep = inlineMinMaxStep(); + auto xMinMaxStep = xlineMinMaxStep(); + + int voxelMin[OpenVDS::Dimensionality_Max] = { 0, 0, 0, 0, 0, 0 }; + int voxelMax[OpenVDS::Dimensionality_Max] = { 1, 1, 1, 1, 1, 1 }; + + const int zMax = zSize(); + + const int iSize = ( iMinMaxStep[1] - iMinMaxStep[0] ) / iMinMaxStep[2]; + const int xSize = ( xMinMaxStep[1] - xMinMaxStep[0] ) / xMinMaxStep[2]; + + voxelMin[VDS_Z_DIM] = zMax / 4; + voxelMax[VDS_Z_DIM] = zMax - zMax / 4; + + voxelMin[VDS_XLINE_DIM] = xSize / 4; + voxelMax[VDS_XLINE_DIM] = xSize - xSize / 4; + + voxelMin[VDS_INLINE_DIM] = iSize / 4; + voxelMax[VDS_INLINE_DIM] = iSize - iSize / 4; + + const int totalSize = ( voxelMax[VDS_Z_DIM] - voxelMin[VDS_Z_DIM] ) * ( voxelMax[VDS_XLINE_DIM] - voxelMin[VDS_XLINE_DIM] ) * + ( voxelMax[VDS_INLINE_DIM] - voxelMin[VDS_INLINE_DIM] ); + + std::vector buffer( totalSize ); + + auto accessManager = OpenVDS::GetAccessManager( m_handle ); + + auto request = accessManager.RequestVolumeSubset( buffer.data(), + buffer.size() * sizeof( float ), + OpenVDS::Dimensions_012, + 0, + m_dataChannelToUse, + voxelMin, + voxelMax ); + + bool success = request->WaitForCompletion(); + if ( success ) + { + auto chanDesc = m_layout->GetChannelDescriptor( m_dataChannelToUse ); + + m_histogram = + ZGYAccess::HistogramGenerator::getHistogram( buffer, 151, (float)chanDesc.GetValueRangeMin(), (float)chanDesc.GetValueRangeMax() ); + + xvals = m_histogram->Xvalues; + yvals = m_histogram->Yvalues; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RifOpenVDSReader::dataRange() +{ + if ( !isOpen() ) return { 0.0, 0.0 }; + + auto chanDesc = m_layout->GetChannelDescriptor( m_dataChannelToUse ); + return { chanDesc.GetValueRangeMin(), chanDesc.GetValueRangeMax() }; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RifOpenVDSReader::worldCorners() +{ + if ( !isOpen() ) return {}; + + auto iAxis = m_layout->GetAxisDescriptor( VDS_INLINE_DIM ); + auto xAxis = m_layout->GetAxisDescriptor( VDS_XLINE_DIM ); + auto zAxis = m_layout->GetAxisDescriptor( VDS_Z_DIM ); + + const float iMin = iAxis.GetCoordinateMin(); + const float iMax = iAxis.GetCoordinateMax(); + const float xMin = xAxis.GetCoordinateMin(); + const float xMax = xAxis.GetCoordinateMax(); + const float zMin = zAxis.GetCoordinateMin(); + const float zMax = zAxis.GetCoordinateMax(); + + cvf::Vec3dArray annotPoints; + annotPoints.resize( 8 ); + annotPoints[0] = cvf::Vec3d( iMin, xMin, zMin ); + annotPoints[1] = cvf::Vec3d( iMax, xMin, zMin ); + annotPoints[2] = cvf::Vec3d( iMin, xMax, zMin ); + annotPoints[3] = cvf::Vec3d( iMax, xMax, zMin ); + annotPoints[4] = cvf::Vec3d( iMin, xMin, zMax ); + annotPoints[5] = cvf::Vec3d( iMax, xMin, zMax ); + annotPoints[6] = cvf::Vec3d( iMin, xMax, zMax ); + annotPoints[7] = cvf::Vec3d( iMax, xMax, zMax ); + + std::vector retval; + + for ( auto p : annotPoints ) + { + auto world = m_coordinateTransform->AnnotationToWorld( OpenVDS::DoubleVector3( p.x(), p.y(), p.z() ) ); + + retval.push_back( cvf::Vec3d( world.X, world.Y, world.Z ) ); + } + + return retval; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RifOpenVDSReader::zStep() +{ + if ( !isOpen() ) return 0.0; + + return m_layout->GetAxisDescriptor( VDS_Z_DIM ).GetCoordinateStep(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RifOpenVDSReader::zSize() +{ + if ( !isOpen() ) return 0; + + return m_layout->GetAxisDescriptor( VDS_Z_DIM ).GetNumSamples(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3i RifOpenVDSReader::minMaxStep( int dimension ) +{ + if ( !isOpen() ) return { 0, 0, 0 }; + + auto axis = m_layout->GetAxisDescriptor( dimension ); + + return { (int)( axis.GetCoordinateMin() + 0.5 ), (int)( axis.GetCoordinateMax() + 0.5 ), (int)( axis.GetCoordinateStep() + 0.5 ) }; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3i RifOpenVDSReader::inlineMinMaxStep() +{ + return minMaxStep( VDS_INLINE_DIM ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3i RifOpenVDSReader::xlineMinMaxStep() +{ + return minMaxStep( VDS_XLINE_DIM ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RifOpenVDSReader::convertToWorldCoords( int iLine, int xLine, double depth ) +{ + if ( !isOpen() ) return { 0, 0, 0 }; + + auto world = m_coordinateTransform->AnnotationToWorld( OpenVDS::DoubleVector3( iLine, xLine, depth ) ); + return { world.X, world.Y, depth }; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RifOpenVDSReader::convertToInlineXline( double worldx, double worldy ) +{ + if ( !isOpen() ) return { 0, 0 }; + + auto annot = m_coordinateTransform->WorldToAnnotation( OpenVDS::DoubleVector3( worldx, worldy, 0 ) ); + return { (int)( annot.X + 0.5 ), (int)( annot.Y + 0.5 ) }; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::shared_ptr + RifOpenVDSReader::slice( RiaDefines::SeismicSliceDirection direction, int sliceIndex, int zStartIndex, int zSize ) +{ + if ( !isOpen() ) return nullptr; + + if ( zStartIndex < 0 ) + { + zStartIndex = 0; + zSize = this->zSize(); + } + + const int xlineSize = m_layout->GetAxisDescriptor( VDS_XLINE_DIM ).GetNumSamples(); + const int inlineSize = m_layout->GetAxisDescriptor( VDS_INLINE_DIM ).GetNumSamples(); + + int voxelMin[OpenVDS::Dimensionality_Max] = { 0, 0, 0, 0, 0, 0 }; + int voxelMax[OpenVDS::Dimensionality_Max] = { 1, 1, 1, 1, 1, 1 }; + + int width = 0; + int height = 0; + + switch ( direction ) + { + case RiaDefines::SeismicSliceDirection::INLINE: + voxelMin[VDS_Z_DIM] = zStartIndex; + voxelMax[VDS_Z_DIM] = zStartIndex + zSize; + voxelMin[VDS_XLINE_DIM] = 0; + voxelMax[VDS_XLINE_DIM] = xlineSize; + voxelMin[VDS_INLINE_DIM] = sliceIndex; + voxelMax[VDS_INLINE_DIM] = sliceIndex + 1; + width = xlineSize; + height = zSize; + break; + + case RiaDefines::SeismicSliceDirection::XLINE: + voxelMin[VDS_Z_DIM] = zStartIndex; + voxelMax[VDS_Z_DIM] = zStartIndex + zSize; + voxelMin[VDS_XLINE_DIM] = sliceIndex; + voxelMax[VDS_XLINE_DIM] = sliceIndex + 1; + voxelMin[VDS_INLINE_DIM] = 0; + voxelMax[VDS_INLINE_DIM] = inlineSize; + width = inlineSize; + height = zSize; + break; + + case RiaDefines::SeismicSliceDirection::DEPTH: + voxelMin[VDS_Z_DIM] = sliceIndex; + voxelMax[VDS_Z_DIM] = sliceIndex + 1; + voxelMin[VDS_XLINE_DIM] = 0; + voxelMax[VDS_XLINE_DIM] = xlineSize; + voxelMin[VDS_INLINE_DIM] = 0; + voxelMax[VDS_INLINE_DIM] = inlineSize; + width = inlineSize; + height = xlineSize; + break; + + default: + return nullptr; + } + + int totalSize = width * height; + + std::shared_ptr retData = std::make_shared( width, height ); + + auto accessManager = OpenVDS::GetAccessManager( m_handle ); + + auto request = accessManager.RequestVolumeSubset( retData->values(), + totalSize * sizeof( float ), + OpenVDS::Dimensions_012, + 0, + m_dataChannelToUse, + voxelMin, + voxelMax ); + + bool success = request->WaitForCompletion(); + if ( !success ) retData.reset(); + + return retData; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::shared_ptr RifOpenVDSReader::trace( int inlineIndex, int xlineIndex, int zStartIndex, int zSize ) +{ + if ( !isOpen() ) return nullptr; + + if ( zStartIndex < 0 ) + { + zStartIndex = 0; + zSize = this->zSize(); + } + + int voxelMin[OpenVDS::Dimensionality_Max] = { 0, 0, 0, 0, 0, 0 }; + int voxelMax[OpenVDS::Dimensionality_Max] = { 1, 1, 1, 1, 1, 1 }; + + voxelMin[VDS_Z_DIM] = zStartIndex; + voxelMax[VDS_Z_DIM] = zStartIndex + zSize; + + voxelMin[VDS_XLINE_DIM] = xlineIndex; + voxelMax[VDS_XLINE_DIM] = xlineIndex + 1; + + voxelMin[VDS_INLINE_DIM] = inlineIndex; + voxelMax[VDS_INLINE_DIM] = inlineIndex + 1; + + std::shared_ptr retData = std::make_shared( 1, zSize ); + + auto accessManager = OpenVDS::GetAccessManager( m_handle ); + + auto request = accessManager.RequestVolumeSubset( retData->values(), + zSize * sizeof( float ), + OpenVDS::Dimensions_012, + 0, + m_dataChannelToUse, + voxelMin, + voxelMax ); + + bool success = request->WaitForCompletion(); + if ( !success ) retData.reset(); + + return retData; +} diff --git a/ApplicationLibCode/FileInterface/RifOpenVDSReader.h b/ApplicationLibCode/FileInterface/RifOpenVDSReader.h new file mode 100644 index 0000000000..d354aa356f --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifOpenVDSReader.h @@ -0,0 +1,79 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RifSeismicReader.h" + +namespace OpenVDS +{ +struct VDS; +struct IJKCoordinateTransformer; +class VolumeDataLayout; +} // namespace OpenVDS + +namespace ZGYAccess +{ +class HistogramData; +} + +class RifOpenVDSReader : public RifSeismicReader +{ +public: + RifOpenVDSReader(); + ~RifOpenVDSReader(); + + bool open( QString filename ) override; + void close() override; + + bool isValid() override; + + bool isOpen() const override; + + std::vector> metaData() override; + + void histogramData( std::vector& xvals, std::vector& yvals ) override; + + std::pair dataRange() override; + + std::vector worldCorners() override; + + cvf::Vec3i inlineMinMaxStep() override; + cvf::Vec3i xlineMinMaxStep() override; + + double zStep() override; + int zSize() override; + + cvf::Vec3d convertToWorldCoords( int iLine, int xLine, double depth ) override; + std::pair convertToInlineXline( double worldx, double worldy ) override; + + std::shared_ptr + slice( RiaDefines::SeismicSliceDirection direction, int sliceIndex, int zStartIndex = -1, int zSize = 0 ) override; + std::shared_ptr trace( int inlineIndex, int xlineIndex, int zStartIndex = -1, int zSize = 0 ) override; + +protected: + cvf::Vec3i minMaxStep( int dimension ); + +private: + QString m_filename; + OpenVDS::VDS* m_handle; + OpenVDS::VolumeDataLayout const* m_layout; + int m_dataChannelToUse; + std::unique_ptr m_coordinateTransform; + std::unique_ptr m_histogram; +}; diff --git a/ApplicationLibCode/FileInterface/RifSeismicReader.cpp b/ApplicationLibCode/FileInterface/RifSeismicReader.cpp new file mode 100644 index 0000000000..2034459c20 --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifSeismicReader.cpp @@ -0,0 +1,50 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RifSeismicReader.h" + +#include "cvfBoundingBox.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifSeismicReader::RifSeismicReader() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifSeismicReader::~RifSeismicReader() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::BoundingBox RifSeismicReader::boundingBox() +{ + cvf::BoundingBox retBox; + + for ( auto& p : worldCorners() ) + { + retBox.add( p ); + } + + return retBox; +} diff --git a/ApplicationLibCode/FileInterface/RifSeismicReader.h b/ApplicationLibCode/FileInterface/RifSeismicReader.h new file mode 100644 index 0000000000..8614967549 --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifSeismicReader.h @@ -0,0 +1,76 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfVector3.h" + +#include "RiaSeismicDefines.h" + +#include + +#include +#include +#include + +namespace ZGYAccess +{ +class SeismicSliceData; +} // namespace ZGYAccess + +namespace cvf +{ +class BoundingBox; +} // namespace cvf + +class RifSeismicReader +{ +public: + RifSeismicReader(); + virtual ~RifSeismicReader(); + + cvf::BoundingBox boundingBox(); + + virtual bool open( QString filename ) = 0; + virtual void close() = 0; + + virtual bool isValid() = 0; + + virtual bool isOpen() const = 0; + + virtual std::vector> metaData() = 0; + + virtual void histogramData( std::vector& xvals, std::vector& yvals ) = 0; + + virtual std::pair dataRange() = 0; + + virtual std::vector worldCorners() = 0; + + virtual cvf::Vec3i inlineMinMaxStep() = 0; + virtual cvf::Vec3i xlineMinMaxStep() = 0; + + virtual double zStep() = 0; + virtual int zSize() = 0; + + virtual cvf::Vec3d convertToWorldCoords( int iLine, int xLine, double depth ) = 0; + virtual std::pair convertToInlineXline( double worldx, double worldy ) = 0; + + virtual std::shared_ptr + slice( RiaDefines::SeismicSliceDirection direction, int sliceIndex, int zStartIndex = -1, int zSize = 0 ) = 0; + virtual std::shared_ptr trace( int inlineIndex, int xlineIndex, int zStartIndex = -1, int zSize = 0 ) = 0; +}; diff --git a/ApplicationLibCode/FileInterface/RifSeismicZGYReader.cpp b/ApplicationLibCode/FileInterface/RifSeismicZGYReader.cpp index 441d139433..7d34eee049 100644 --- a/ApplicationLibCode/FileInterface/RifSeismicZGYReader.cpp +++ b/ApplicationLibCode/FileInterface/RifSeismicZGYReader.cpp @@ -37,6 +37,7 @@ RifSeismicZGYReader::RifSeismicZGYReader() //-------------------------------------------------------------------------------------------------- RifSeismicZGYReader::~RifSeismicZGYReader() { + close(); } //-------------------------------------------------------------------------------------------------- @@ -44,7 +45,7 @@ RifSeismicZGYReader::~RifSeismicZGYReader() //-------------------------------------------------------------------------------------------------- bool RifSeismicZGYReader::open( QString filename ) { - if ( isOpen() ) close(); + close(); m_filename = filename; @@ -124,30 +125,6 @@ std::vector> RifSeismicZGYReader::metaData() return retValues; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::BoundingBox RifSeismicZGYReader::boundingBox() -{ - cvf::BoundingBox retBox; - - if ( isOpen() ) - { - auto [zmin, zmax] = m_reader->zRange(); - - auto outline = m_reader->seismicWorldOutline(); - - auto corners = outline.points(); - for ( auto p : corners ) - { - retBox.add( cvf::Vec3d( p.x(), p.y(), -zmin ) ); - retBox.add( cvf::Vec3d( p.x(), p.y(), -zmax ) ); - } - } - - return retBox; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/FileInterface/RifSeismicZGYReader.h b/ApplicationLibCode/FileInterface/RifSeismicZGYReader.h index 799cdac1bb..d4d8ef5e00 100644 --- a/ApplicationLibCode/FileInterface/RifSeismicZGYReader.h +++ b/ApplicationLibCode/FileInterface/RifSeismicZGYReader.h @@ -18,62 +18,46 @@ #pragma once -#include "cvfVector3.h" - -#include "RiaSeismicDefines.h" - -#include - -#include -#include -#include +#include "RifSeismicReader.h" namespace ZGYAccess { class ZGYReader; -class SeismicSliceData; } // namespace ZGYAccess -namespace cvf -{ -class BoundingBox; -} // namespace cvf - -class RifSeismicZGYReader +class RifSeismicZGYReader : public RifSeismicReader { public: RifSeismicZGYReader(); ~RifSeismicZGYReader(); - bool open( QString filename ); - void close(); + bool open( QString filename ) override; + void close() override; - bool isValid(); + bool isValid() override; - bool isOpen() const; + bool isOpen() const override; - std::vector> metaData(); + std::vector> metaData() override; - cvf::BoundingBox boundingBox(); + void histogramData( std::vector& xvals, std::vector& yvals ) override; - void histogramData( std::vector& xvals, std::vector& yvals ); + std::pair dataRange() override; - std::pair dataRange(); + std::vector worldCorners() override; - std::vector worldCorners(); + cvf::Vec3i inlineMinMaxStep() override; + cvf::Vec3i xlineMinMaxStep() override; - cvf::Vec3i inlineMinMaxStep(); - cvf::Vec3i xlineMinMaxStep(); + double zStep() override; + int zSize() override; - double zStep(); - int zSize(); - - cvf::Vec3d convertToWorldCoords( int iLine, int xLine, double depth ); - std::pair convertToInlineXline( double worldx, double worldy ); + cvf::Vec3d convertToWorldCoords( int iLine, int xLine, double depth ) override; + std::pair convertToInlineXline( double worldx, double worldy ) override; std::shared_ptr - slice( RiaDefines::SeismicSliceDirection direction, int sliceIndex, int zStartIndex = -1, int zSize = 0 ); - std::shared_ptr trace( int inlineIndex, int xlineIndex, int zStartIndex = -1, int zSize = 0 ); + slice( RiaDefines::SeismicSliceDirection direction, int sliceIndex, int zStartIndex = -1, int zSize = 0 ) override; + std::shared_ptr trace( int inlineIndex, int xlineIndex, int zStartIndex = -1, int zSize = 0 ) override; private: QString m_filename; diff --git a/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicAlphaMapper.cpp b/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicAlphaMapper.cpp index ab1017a15a..a261d122a3 100644 --- a/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicAlphaMapper.cpp +++ b/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicAlphaMapper.cpp @@ -60,7 +60,7 @@ void RimSeismicAlphaMapper::setDataRangeAndAlphas( double minVal, double maxVal, cvf::ubyte RimSeismicAlphaMapper::alphaValue( double dataValue ) const { int index = (int)( m_scaleFactor * ( dataValue - m_minValue ) ); - index = std::clamp( index, 0, (int)sizeof( m_alphavalues ) - 1 ); + index = std::clamp( index, 0, (int)( m_alphavalues.size() - 1 ) ); return ( cvf::ubyte )( m_alphavalues[index] * 255 ); } diff --git a/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicData.cpp b/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicData.cpp index 9511dd36dd..51e9c44122 100644 --- a/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicData.cpp +++ b/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicData.cpp @@ -22,6 +22,10 @@ #include "RifSeismicZGYReader.h" +#ifdef USE_OPENVDS +#include "RifOpenVDSReader.h" +#endif + #include "RimRegularLegendConfig.h" #include "RimSeismicAlphaMapper.h" #include "RimStringParameter.h" @@ -37,6 +41,8 @@ #include "cvfBoundingBox.h" +#include +#include #include #include @@ -99,19 +105,32 @@ RimSeismicData::~RimSeismicData() //-------------------------------------------------------------------------------------------------- bool RimSeismicData::openFileIfNotOpen() { - if ( m_filereader == nullptr ) - { - m_filereader = std::make_shared(); - } - - if ( m_filereader->isOpen() ) return true; + if ( ( m_filereader != nullptr ) && m_filereader->isOpen() ) return true; QString filename = m_filename().path(); - if ( filename.isEmpty() ) return false; if ( QFile::exists( filename ) ) { + QFileInfo fi( filename ); + + if ( fi.suffix().toLower() == "zgy" ) + { + m_filereader = std::make_shared(); + } +#ifdef USE_OPENVDS + else if ( fi.suffix().toLower() == "vds" ) + { + m_filereader = std::make_shared(); + } +#endif + else + { + m_filereader.reset(); + logError( "Unknown seismic file type: " + filename ); + return false; + } + if ( !m_filereader->open( filename ) ) { logError( "Unable to open seismic file : " + filename ); diff --git a/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicData.h b/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicData.h index c4ba606f34..f68d70c056 100644 --- a/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicData.h +++ b/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicData.h @@ -35,7 +35,7 @@ class RimGenericParameter; class RimSeismicAlphaMapper; class RimRegularLegendConfig; -class RifSeismicZGYReader; +class RifSeismicReader; namespace cvf { @@ -140,6 +140,6 @@ private: std::shared_ptr m_alphaValueMapper; - std::shared_ptr m_filereader; - int m_nErrorsLogged; + std::shared_ptr m_filereader; + int m_nErrorsLogged; }; diff --git a/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp b/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp index 8318966d43..ca269cd089 100644 --- a/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp +++ b/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp @@ -962,7 +962,7 @@ void RiuViewerCommands::handlePickAction( int winPosX, int winPosY, Qt::Keyboard cvf::Vec3d domainCoord = transForm->transformToDomainCoord( globalIntersectionPoint ); // Set surface resultInfo text - QString resultInfoText = "Seismic Section: \"" + section->userDescription() + "\"\n\n"; + QString resultInfoText = "Seismic Section: \"" + section->fullName() + "\"\n\n"; resultInfoText += section->resultInfoText( domainCoord, seismicSourceInfo->partIndex() ); diff --git a/CMakeLists.txt b/CMakeLists.txt index ddaa0c3efa..000184ec8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -315,6 +315,33 @@ if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") endif() endif() +# ############################################################################## +# OpenVDS seismic file access +# ############################################################################## +set(RESINSIGHT_OPENVDS_API_DIR + "" + CACHE + PATH + "Optional path to the OpenVDS API. Adds support for OpenVDS seismic files" +) +if(NOT ${RESINSIGHT_OPENVDS_API_DIR} EQUAL "") + add_definitions(-DUSE_OPENVDS) + set(RESINSIGHT_USE_OPENVDS_API 1) + message(STATUS "Using OpenVDS api from : ${RESINSIGHT_OPENVDS_API_DIR}") + + if(MSVC) + list(APPEND EXTERNAL_LINK_LIBRARIES + ${RESINSIGHT_OPENVDS_API_DIR}/lib/segyutils.lib + ${RESINSIGHT_OPENVDS_API_DIR}/lib/openvds.lib + ) + else() + list(APPEND EXTERNAL_LINK_LIBRARIES + ${RESINSIGHT_OPENVDS_API_DIR}/lib/libsegyutils.so + ${RESINSIGHT_OPENVDS_API_DIR}/lib/libopenvds.so + ) + endif() +endif() + # ############################################################################## # HDF5 # ############################################################################## diff --git a/ThirdParty/openzgy b/ThirdParty/openzgy index 9c61a2b55d..6ae9fd19a8 160000 --- a/ThirdParty/openzgy +++ b/ThirdParty/openzgy @@ -1 +1 @@ -Subproject commit 9c61a2b55d8c1d086233fb998eb335b9e9db1de5 +Subproject commit 6ae9fd19a8de076715da16c9da415f7a1ca46665