mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 22:27:55 -05:00
#12461 Add support for import of .irap and .gri
* Add surfio as submodule and create importer with tests * Update compile fix when mio.h is included in multiple compile units * Move file tools into RifFileTools
This commit is contained in:
1 parent
d628760339
commit
13a793f16c
25 files changed
+21091
-42
No files matched your search
@@ -22,3 +22,6 @@
|
||||
[submodule "ThirdParty/qtadvanceddocking"]
|
||||
path = ThirdParty/qtadvanceddocking
|
||||
url = https://github.com/CeetronSolutions/qtadvanceddocking.git
|
||||
[submodule "ThirdParty/custom-surfio/surfio"]
|
||||
path = ThirdParty/custom-surfio/surfio
|
||||
url = https://github.com/CeetronSolutions/surfio.git
|
||||
@@ -42,10 +42,19 @@ void RicImportSurfacesFeature::onActionTriggered( bool isChecked )
|
||||
{
|
||||
RiaApplication* app = RiaApplication::instance();
|
||||
QString defaultDir = app->lastUsedDialogDirectory( "BINARY_GRID" );
|
||||
QStringList fileNames = RiuFileDialogTools::getOpenFileNames( Riu3DMainWindowTools::mainWindowWidget(),
|
||||
"Import Surfaces",
|
||||
defaultDir,
|
||||
"Surface files (*.ptl *.ts *.dat *.vtu *.pvd *.xyz);;All Files (*.*)" );
|
||||
|
||||
QString generalExtensions = "*.ptl *.ts *.dat *.xyz";
|
||||
QString irapExtensions = "*.irap *.gri";
|
||||
QString vtkExtensions = "*.vtu *.pvd";
|
||||
QString allExtensions = generalExtensions + " " + irapExtensions + " " + vtkExtensions;
|
||||
|
||||
QString dialogFilter = QString( "Surface files (%1);;VTK files (%2);;IRAP GRI files (%3);;All Files (*.*)" )
|
||||
.arg( allExtensions )
|
||||
.arg( vtkExtensions )
|
||||
.arg( irapExtensions );
|
||||
|
||||
QStringList fileNames =
|
||||
RiuFileDialogTools::getOpenFileNames( Riu3DMainWindowTools::mainWindowWidget(), "Import Surfaces", defaultDir, dialogFilter );
|
||||
|
||||
if ( fileNames.isEmpty() ) return;
|
||||
|
||||
|
||||
@@ -105,6 +105,8 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifArrowTools.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifReaderRegularGridModel.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifVtkSurfaceImporter.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifSurfio.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifFileTools.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@@ -207,6 +209,8 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifArrowTools.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifReaderRegularGridModel.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifVtkSurfaceImporter.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifSurfio.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifFileTools.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RifFileTools.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
|
||||
namespace RifFileTools
|
||||
{
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<bool, std::string> isFileReadable( const std::string& filename )
|
||||
{
|
||||
// Check if file exists and is a regular file
|
||||
if ( !fs::exists( filename ) || !fs::is_regular_file( filename ) )
|
||||
{
|
||||
return std::unexpected( "File does not exist or is not a regular file: " + filename );
|
||||
}
|
||||
|
||||
auto p = fs::status( filename ).permissions();
|
||||
auto isReadable = ( p & fs::perms::owner_read ) != fs::perms::none || ( p & fs::perms::group_read ) != fs::perms::none ||
|
||||
( p & fs::perms::others_read ) != fs::perms::none;
|
||||
|
||||
if ( !isReadable )
|
||||
{
|
||||
return std::unexpected( "File is not readable: " + filename );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string extensionLowerCase( const std::string& filename )
|
||||
{
|
||||
if ( filename.empty() ) return "";
|
||||
|
||||
std::string extension = fs::path( filename ).extension().string();
|
||||
std::transform( extension.begin(), extension.end(), extension.begin(), ::tolower );
|
||||
return extension;
|
||||
}
|
||||
}; // namespace RifFileTools
|
||||
@@ -0,0 +1,34 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <expected>
|
||||
#include <string>
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
namespace RifFileTools
|
||||
{
|
||||
|
||||
std::expected<bool, std::string> isFileReadable( const std::string& filename );
|
||||
std::string extensionLowerCase( const std::string& filename );
|
||||
|
||||
}; // namespace RifFileTools
|
||||
@@ -0,0 +1,96 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RifSurfio.h"
|
||||
#include "RifFileTools.h"
|
||||
|
||||
#include "irap_import.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// https://github.com/equinor/xtgeo/blob/main/src/xtgeo/surface/_regsurf_import.py
|
||||
/// https://xtgeo.readthedocs.io/en/latest/datamodels.html#description
|
||||
/// https://github.com/equinor/surfio
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<std::pair<RigRegularSurfaceData, std::vector<float>>, std::string> RifSurfio::importSurfaceData( const std::string& filename )
|
||||
{
|
||||
auto extension = RifFileTools::extensionLowerCase( filename );
|
||||
if ( extension != ".irap" && extension != ".gri" )
|
||||
{
|
||||
return std::unexpected( "File is not a valid IRAP or GRI file: " + filename );
|
||||
}
|
||||
|
||||
// Check file permissions (best effort, may not be reliable on all platforms)
|
||||
auto isFileReadable = RifFileTools::isFileReadable( filename );
|
||||
if ( !isFileReadable.has_value() )
|
||||
{
|
||||
return std::unexpected( isFileReadable.error() );
|
||||
}
|
||||
|
||||
// Try to open the file to confirm readability
|
||||
std::ifstream file( filename );
|
||||
if ( !file.is_open() )
|
||||
{
|
||||
return std::unexpected( "Could not open file: " + filename );
|
||||
}
|
||||
|
||||
auto convertToRegularSurface =
|
||||
[]( const surfio::irap::irap& fileData ) -> std::expected<std::pair<RigRegularSurfaceData, std::vector<float>>, std::string>
|
||||
{
|
||||
RigRegularSurfaceData surfaceData;
|
||||
surfaceData.nx = fileData.header.ncol;
|
||||
surfaceData.ny = fileData.header.nrow;
|
||||
surfaceData.originX = fileData.header.xori;
|
||||
surfaceData.originY = fileData.header.yori;
|
||||
surfaceData.incrementX = fileData.header.xinc;
|
||||
surfaceData.incrementY = fileData.header.yinc;
|
||||
surfaceData.rotation = fileData.header.rot;
|
||||
|
||||
// transpose the data to match the expected format
|
||||
std::vector<float> transposedValues( fileData.values.size() );
|
||||
for ( int row = 0; row < fileData.header.nrow; ++row )
|
||||
{
|
||||
for ( int col = 0; col < fileData.header.ncol; ++col )
|
||||
{
|
||||
transposedValues[row * fileData.header.ncol + col] = fileData.values[col * fileData.header.nrow + row];
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair( surfaceData, transposedValues );
|
||||
};
|
||||
|
||||
if ( extension == ".gri" )
|
||||
{
|
||||
auto fileData = surfio::irap::from_binary_file( filename );
|
||||
|
||||
return convertToRegularSurface( fileData );
|
||||
}
|
||||
else if ( extension == ".irap" )
|
||||
{
|
||||
auto fileData = surfio::irap::from_ascii_file( filename );
|
||||
|
||||
return convertToRegularSurface( fileData );
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::unexpected( "File is not a valid IRAP or GRI file: " + filename );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <expected>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct RigRegularSurfaceData
|
||||
{
|
||||
int nx;
|
||||
int ny;
|
||||
double originX;
|
||||
double originY;
|
||||
double incrementX;
|
||||
double incrementY;
|
||||
double rotation;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RifSurfio
|
||||
{
|
||||
public:
|
||||
static std::expected<std::pair<RigRegularSurfaceData, std::vector<float>>, std::string> importSurfaceData( const std::string& filename );
|
||||
};
|
||||
@@ -11,6 +11,7 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimDepthSurface.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimFractureSurface.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimRegularSurface.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimRegularFileSurface.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@@ -26,6 +27,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimDepthSurface.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimFractureSurface.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimRegularSurface.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimRegularFileSurface.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
#include <memory>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimFileSurface, "Surface", "FileSurface" );
|
||||
@@ -119,13 +120,12 @@ void RimFileSurface::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
bool RimFileSurface::updateSurfaceData()
|
||||
{
|
||||
bool result = true;
|
||||
if ( m_vertices.empty() )
|
||||
if ( m_triangleMeshData->geometry().first.empty() )
|
||||
{
|
||||
result = loadDataFromFile();
|
||||
}
|
||||
|
||||
std::vector<cvf::Vec3d> vertices{ m_vertices };
|
||||
std::vector<unsigned> tringleIndices{ m_tringleIndices };
|
||||
auto [vertices, tringleIndices] = m_triangleMeshData->geometry();
|
||||
|
||||
auto surface = new RigSurface;
|
||||
if ( !vertices.empty() && !tringleIndices.empty() )
|
||||
@@ -155,8 +155,7 @@ bool RimFileSurface::updateSurfaceData()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFileSurface::clearCachedNativeData()
|
||||
{
|
||||
m_vertices.clear();
|
||||
m_tringleIndices.clear();
|
||||
m_triangleMeshData.reset();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -164,35 +163,28 @@ void RimFileSurface::clearCachedNativeData()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimFileSurface::loadDataFromFile()
|
||||
{
|
||||
std::pair<std::vector<cvf::Vec3d>, std::vector<unsigned>> surface;
|
||||
m_triangleMeshData = std::make_unique<RigTriangleMeshData>();
|
||||
|
||||
QString filePath = surfaceFilePath();
|
||||
if ( filePath.endsWith( "ptl", Qt::CaseInsensitive ) )
|
||||
{
|
||||
surface = RifSurfaceImporter::readPetrelFile( filePath );
|
||||
auto surface = RifSurfaceImporter::readPetrelFile( filePath );
|
||||
m_triangleMeshData->setGeometryData( surface.first, surface.second );
|
||||
}
|
||||
else if ( filePath.endsWith( "ts", Qt::CaseInsensitive ) )
|
||||
{
|
||||
m_triangleMeshData = std::make_unique<RigTriangleMeshData>();
|
||||
|
||||
RifSurfaceImporter::readGocadFile( filePath, m_triangleMeshData.get() );
|
||||
|
||||
surface = m_triangleMeshData->geometry();
|
||||
}
|
||||
else if ( filePath.endsWith( "vtu", Qt::CaseInsensitive ) )
|
||||
{
|
||||
m_triangleMeshData = RifVtkSurfaceImporter::importFromFile( filePath.toStdString() );
|
||||
|
||||
surface = m_triangleMeshData->geometry();
|
||||
}
|
||||
else if ( filePath.endsWith( "dat", Qt::CaseInsensitive ) || filePath.endsWith( "xyz", Qt::CaseInsensitive ) )
|
||||
{
|
||||
double resamplingDistance = RiaPreferences::current()->surfaceImportResamplingDistance();
|
||||
surface = RifSurfaceImporter::readOpenWorksXyzFile( filePath, resamplingDistance );
|
||||
auto surface = RifSurfaceImporter::readOpenWorksXyzFile( filePath, resamplingDistance );
|
||||
m_triangleMeshData->setGeometryData( surface.first, surface.second );
|
||||
}
|
||||
|
||||
m_vertices = surface.first;
|
||||
m_tringleIndices = surface.second;
|
||||
|
||||
return !( m_vertices.empty() || m_tringleIndices.empty() );
|
||||
return !( m_triangleMeshData->geometry().first.empty() );
|
||||
}
|
||||
@@ -50,8 +50,5 @@ private:
|
||||
|
||||
caf::PdmField<caf::FilePath> m_surfaceDefinitionFilePath;
|
||||
|
||||
std::vector<unsigned> m_tringleIndices;
|
||||
std::vector<cvf::Vec3d> m_vertices;
|
||||
|
||||
std::unique_ptr<RigTriangleMeshData> m_triangleMeshData;
|
||||
};
|
||||
@@ -0,0 +1,91 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimRegularFileSurface.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
|
||||
#include "RifSurfio.h"
|
||||
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimRegularFileSurface, "RegularFileSurface" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimRegularFileSurface::RimRegularFileSurface()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "RegularFileSurface", ":/ReservoirSurface16x16.png" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_surfaceFilePath, "SurfaceFilePath", "File" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimRegularFileSurface::setFilePath( const QString& filePath )
|
||||
{
|
||||
m_surfaceFilePath = filePath;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimRegularFileSurface::onLoadData()
|
||||
{
|
||||
auto surfaceData = RifSurfio::importSurfaceData( m_surfaceFilePath().path().toStdString() );
|
||||
if ( surfaceData.has_value() )
|
||||
{
|
||||
const auto [regularSurface, values] = surfaceData.value();
|
||||
|
||||
setNx( regularSurface.nx );
|
||||
setNy( regularSurface.ny );
|
||||
setOriginX( regularSurface.originX );
|
||||
setOriginY( regularSurface.originY );
|
||||
setIncrementX( regularSurface.incrementX );
|
||||
setIncrementY( regularSurface.incrementY );
|
||||
setRotation( regularSurface.rotation );
|
||||
|
||||
if ( !values.empty() )
|
||||
{
|
||||
const QString propertyName = "File Property Values";
|
||||
setProperty( propertyName, values );
|
||||
}
|
||||
|
||||
RimRegularSurface::onLoadData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RiaLogging::error( QString::fromStdString( surfaceData.error() ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimRegularFileSurface::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
auto group = uiOrdering.addNewGroup( "Data Source" );
|
||||
group->add( &m_surfaceFilePath );
|
||||
|
||||
setFieldsReadOnly( true );
|
||||
RimRegularSurface::defineUiOrdering( uiConfigName, uiOrdering );
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimRegularSurface.h"
|
||||
|
||||
class RimRegularFileSurface : public RimRegularSurface
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimRegularFileSurface();
|
||||
void setFilePath( const QString& filePath );
|
||||
|
||||
bool onLoadData() override;
|
||||
|
||||
private:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
|
||||
private:
|
||||
caf::PdmField<caf::FilePath> m_surfaceFilePath;
|
||||
};
|
||||
@@ -32,6 +32,14 @@
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimRegularSurface, "RegularSurface" );
|
||||
|
||||
namespace internal
|
||||
{
|
||||
QString fixedDepth()
|
||||
{
|
||||
return "FIXED_DEPTH";
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -51,7 +59,7 @@ RimRegularSurface::RimRegularSurface()
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_rotation, "Rotation", 0.0, "Rotation" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_depthProperty, "DepthProperty", QString( "" ), "Depth Property" );
|
||||
CAF_PDM_InitScriptableField( &m_depthProperty, "DepthProperty", internal::fixedDepth(), "Depth Property" );
|
||||
m_rotation.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() );
|
||||
}
|
||||
|
||||
@@ -127,7 +135,12 @@ void RimRegularSurface::defineUiOrdering( QString uiConfigName, caf::PdmUiOrderi
|
||||
auto locationGroup = uiOrdering.addNewGroup( "Location" );
|
||||
locationGroup->add( &m_originX );
|
||||
locationGroup->add( &m_originY );
|
||||
locationGroup->add( &m_depth );
|
||||
locationGroup->add( &m_depthProperty );
|
||||
|
||||
if ( m_depthProperty() == internal::fixedDepth() )
|
||||
{
|
||||
locationGroup->add( &m_depth );
|
||||
}
|
||||
|
||||
auto extentGroup = uiOrdering.addNewGroup( "Extent" );
|
||||
extentGroup->add( &m_nx );
|
||||
@@ -149,6 +162,38 @@ void RimRegularSurface::defineUiOrdering( QString uiConfigName, caf::PdmUiOrderi
|
||||
uiOrdering.skipRemainingFields();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimRegularSurface::setFieldsReadOnly( bool enable )
|
||||
{
|
||||
m_nx.uiCapability()->setUiReadOnly( enable );
|
||||
m_ny.uiCapability()->setUiReadOnly( enable );
|
||||
m_originX.uiCapability()->setUiReadOnly( enable );
|
||||
m_originY.uiCapability()->setUiReadOnly( enable );
|
||||
m_incrementX.uiCapability()->setUiReadOnly( enable );
|
||||
m_incrementY.uiCapability()->setUiReadOnly( enable );
|
||||
m_rotation.uiCapability()->setUiReadOnly( enable );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo> RimRegularSurface::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
if ( fieldNeedingOptions == &m_depthProperty )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( "Fixed Depth", internal::fixedDepth() ) );
|
||||
|
||||
for ( const auto& [key, value] : m_properties )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( key, key ) );
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -202,7 +247,7 @@ bool RimRegularSurface::updateSurfaceData()
|
||||
for ( int i = 0; i < m_nx(); i++ )
|
||||
{
|
||||
double depth = m_depth;
|
||||
if ( !m_depthProperty().isEmpty() && m_properties.contains( m_depthProperty ) )
|
||||
if ( !m_depthProperty().isEmpty() && m_properties.contains( m_depthProperty ) && m_depthProperty() != internal::fixedDepth() )
|
||||
{
|
||||
depth = m_properties[m_depthProperty][j * m_nx + i];
|
||||
}
|
||||
|
||||
@@ -45,13 +45,17 @@ public:
|
||||
int nx() const;
|
||||
int ny() const;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void setFieldsReadOnly( bool enable );
|
||||
|
||||
private:
|
||||
bool updateSurfaceData() override;
|
||||
void clearCachedNativeData() override;
|
||||
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
|
||||
|
||||
private:
|
||||
caf::PdmField<int> m_nx;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "RimGridCaseSurface.h"
|
||||
#include "RimGridView.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimRegularFileSurface.h"
|
||||
#include "RimRegularLegendConfig.h"
|
||||
#include "RimSeismicSectionCollection.h"
|
||||
#include "RimSurface.h"
|
||||
@@ -144,13 +145,22 @@ RimSurface* RimSurfaceCollection::importSurfacesFromFiles( const QStringList& fi
|
||||
{
|
||||
RimSurface* newSurface = nullptr;
|
||||
|
||||
if ( newFileName.endsWith( ".pvd" ) )
|
||||
auto extension = QFileInfo( newFileName ).suffix().toLower();
|
||||
|
||||
if ( extension == "pvd" )
|
||||
{
|
||||
RimFractureSurface* fractureSurface = new RimFractureSurface;
|
||||
fractureSurface->setSurfaceFilePath( newFileName );
|
||||
|
||||
newSurface = fractureSurface;
|
||||
}
|
||||
else if ( extension == "irap" || extension == "gri" )
|
||||
{
|
||||
auto regularFileSurface = new RimRegularFileSurface;
|
||||
regularFileSurface->setFilePath( newFileName );
|
||||
|
||||
newSurface = regularFileSurface;
|
||||
}
|
||||
else
|
||||
{
|
||||
RimFileSurface* fileSurface = new RimFileSurface;
|
||||
|
||||
@@ -45,7 +45,7 @@ std::vector<QString> RigTriangleMeshData::propertyNames() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::pair<std::vector<cvf::Vec3d>, std::vector<unsigned>> RigTriangleMeshData::geometry() const
|
||||
{
|
||||
return std::make_pair( m_vertices, m_tringleIndices );
|
||||
return std::make_pair( m_vertices, m_triangleIndices );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -69,8 +69,8 @@ std::vector<float> RigTriangleMeshData::propertyValues( const QString& property
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigTriangleMeshData::setGeometryData( const std::vector<cvf::Vec3d>& nodeCoord, const std::vector<unsigned>& connectivities )
|
||||
{
|
||||
m_vertices = nodeCoord;
|
||||
m_tringleIndices = connectivities;
|
||||
m_vertices = nodeCoord;
|
||||
m_triangleIndices = connectivities;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
|
||||
private:
|
||||
std::vector<cvf::Vec3d> m_vertices;
|
||||
std::vector<unsigned> m_tringleIndices;
|
||||
std::vector<unsigned> m_triangleIndices;
|
||||
std::vector<QString> m_propertyNames;
|
||||
std::vector<std::vector<float>> m_propertyValues;
|
||||
};
|
||||
@@ -111,6 +111,7 @@ set(SOURCE_UNITTEST_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaKeyValueStore-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaEnsembleImportTools-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimTools-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifSurfio-Test.cpp
|
||||
)
|
||||
|
||||
if(RESINSIGHT_ENABLE_GRPC)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "RifSurfio.h"
|
||||
|
||||
#include "RiaTestDataDirectory.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST( RifSurfioTest, ImportFromIrapFile )
|
||||
{
|
||||
std::filesystem::path testDataDir = std::filesystem::path( TEST_DATA_DIR ) / "RifSurfaceImporter";
|
||||
std::filesystem::path irapFilePath = testDataDir / "volantis.irap";
|
||||
|
||||
auto surfaceData = RifSurfio::importSurfaceData( irapFilePath.string() );
|
||||
EXPECT_TRUE( surfaceData.has_value() );
|
||||
|
||||
const auto& [regularSurface, values] = surfaceData.value();
|
||||
EXPECT_EQ( regularSurface.nx, 280 );
|
||||
EXPECT_EQ( regularSurface.ny, 440 );
|
||||
EXPECT_DOUBLE_EQ( regularSurface.incrementX, 25.0 );
|
||||
EXPECT_DOUBLE_EQ( regularSurface.incrementY, 25.0 );
|
||||
EXPECT_DOUBLE_EQ( regularSurface.rotation, 30.0 );
|
||||
EXPECT_EQ( regularSurface.ny * regularSurface.nx, values.size() );
|
||||
}
|
||||
|
||||
TEST( RifSurfioTest, ImportFromGriFile )
|
||||
{
|
||||
std::filesystem::path testDataDir = std::filesystem::path( TEST_DATA_DIR ) / "RifSurfaceImporter";
|
||||
std::filesystem::path irapFilePath = testDataDir / "volantis.gri";
|
||||
|
||||
auto surfaceData = RifSurfio::importSurfaceData( irapFilePath.string() );
|
||||
EXPECT_TRUE( surfaceData.has_value() );
|
||||
|
||||
const auto& [regularSurface, values] = surfaceData.value();
|
||||
EXPECT_EQ( regularSurface.nx, 280 );
|
||||
EXPECT_EQ( regularSurface.ny, 440 );
|
||||
EXPECT_DOUBLE_EQ( regularSurface.incrementX, 25.0 );
|
||||
EXPECT_DOUBLE_EQ( regularSurface.incrementY, 25.0 );
|
||||
EXPECT_DOUBLE_EQ( regularSurface.rotation, 30.0 );
|
||||
EXPECT_EQ( regularSurface.ny * regularSurface.nx, values.size() );
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because it is too large.
Load diff
@@ -684,6 +684,13 @@ set_property(
|
||||
"Thirdparty"
|
||||
)
|
||||
|
||||
# ##############################################################################
|
||||
# surfio
|
||||
# ##############################################################################
|
||||
|
||||
add_subdirectory(ThirdParty/custom-surfio)
|
||||
list(APPEND THIRD_PARTY_LIBRARIES surfio_lib)
|
||||
|
||||
# ##############################################################################
|
||||
# toml++
|
||||
# ##############################################################################
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
cmake_minimum_required(VERSION 3.22.0)
|
||||
project(surfio_lib LANGUAGES CXX)
|
||||
|
||||
# mdspan is part of C++23. kokkos/mdspan is the reference implementation for the standard proposal.
|
||||
# This can be removed when all needed compilers/libs support it.
|
||||
FetchContent_Declare(
|
||||
mdspan
|
||||
GIT_REPOSITORY https://github.com/kokkos/mdspan.git
|
||||
GIT_TAG 9ceface91483775a6c74d06ebf717bbb2768452f # mdspan-0.6.0
|
||||
)
|
||||
FetchContent_MakeAvailable(mdspan)
|
||||
|
||||
# surfio_lib
|
||||
set(SRC_PATH "${CMAKE_CURRENT_LIST_DIR}/surfio/src/lib")
|
||||
add_library(surfio_lib)
|
||||
target_sources(
|
||||
surfio_lib
|
||||
PRIVATE ${SRC_PATH}/irap_import_ascii.cpp
|
||||
${SRC_PATH}/irap_import_binary.cpp ${SRC_PATH}/irap_export_ascii.cpp
|
||||
${SRC_PATH}/irap_export_binary.cpp
|
||||
${SRC_PATH}/mmap_wrapper/mmap_wrapper.cpp
|
||||
)
|
||||
target_include_directories(
|
||||
surfio_lib
|
||||
INTERFACE ${SRC_PATH}/include
|
||||
PRIVATE $<BUILD_INTERFACE:${mdspan_SOURCE_DIR}/include/>
|
||||
PRIVATE ../mio
|
||||
)
|
||||
|
||||
+1
Submodule ThirdParty/custom-surfio/surfio added at 935220b409.
Vendored
+11
-8
@@ -794,14 +794,17 @@ inline DWORD int64_low(int64_t n) noexcept
|
||||
return n & 0xffffffff;
|
||||
}
|
||||
|
||||
std::wstring s_2_ws(const std::string& s)
|
||||
inline std::wstring s_2_ws(const std::string& s)
|
||||
{
|
||||
if (s.empty())
|
||||
return{};
|
||||
const auto s_length = static_cast<int>(s.length());
|
||||
auto buf = std::vector<wchar_t>(s_length);
|
||||
const auto wide_char_count = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), s_length, buf.data(), s_length);
|
||||
return std::wstring(buf.data(), wide_char_count);
|
||||
std::wstring ret;
|
||||
if (!s.empty())
|
||||
{
|
||||
ret.resize(s.size());
|
||||
int wide_char_count = MultiByteToWideChar(CP_UTF8, 0, s.c_str(),
|
||||
static_cast<int>(s.size()), &ret[0], static_cast<int>(s.size()));
|
||||
ret.resize(wide_char_count);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<
|
||||
@@ -1757,4 +1760,4 @@ using shared_ummap_sink = basic_shared_mmap_sink<unsigned char>;
|
||||
|
||||
} // namespace mio
|
||||
|
||||
#endif // MIO_SHARED_MMAP_HEADER
|
||||
#endif // MIO_SHARED_MMAP_HEADER
|
||||
Reference in new issue
Block a user