#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:
Magne Sjaastad authored and GitHub committed 2025-05-28 09:50:45 +02:00
1 parent d628760339
commit 13a793f16c
25 files changed
+21091 -42

No files matched your search

+3
View File
@@ -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() );
}
File diff suppressed because it is too large. Load diff
+7
View File
@@ -684,6 +684,13 @@ set_property(
"Thirdparty"
)
# ##############################################################################
# surfio
# ##############################################################################
add_subdirectory(ThirdParty/custom-surfio)
list(APPEND THIRD_PARTY_LIBRARIES surfio_lib)
# ##############################################################################
# toml++
# ##############################################################################
+29
View File
@@ -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
)
+11 -8
View File
@@ -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