#12459 Add regular surface domain object.

This commit is contained in:
Kristian Bendiksen authored and Magne Sjaastad committed 2025-05-20 20:39:07 +02:00
1 parent b9ac1bc0c5
commit 1a55fa11c3
23 files changed
+1143 -31

No files matched your search

@@ -1,6 +1,10 @@
set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaKeyValueStore.h)
set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaKeyValueStore.h
${CMAKE_CURRENT_LIST_DIR}/RiaKeyValueStoreUtil.h
)
set(SOURCE_GROUP_SOURCE_FILES)
set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RiaKeyValueStoreUtil.cpp
)
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
@@ -0,0 +1,25 @@
#include "RiaKeyValueStoreUtil.h"
#include <cstring>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<float> RiaKeyValueStoreUtil::convertToFloatVector( const std::optional<std::vector<char>>& inputVector )
{
if ( !inputVector || inputVector->empty() ) return {};
// Ensure the byte vector size is a multiple of sizeof(float)
if ( inputVector->size() % sizeof( float ) != 0 ) return {};
// Calculate how many floats we'll have
size_t numFloats = inputVector->size() / sizeof( float );
// Create a vector of floats with the appropriate size
std::vector<float> floatVector( numFloats );
// Copy the binary data from the byte vector to the float vector
std::memcpy( floatVector.data(), inputVector->data(), inputVector->size() );
return floatVector;
}
@@ -0,0 +1,31 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <optional>
#include <vector>
//==================================================================================================
///
//==================================================================================================
class RiaKeyValueStoreUtil
{
public:
static std::vector<float> convertToFloatVector( const std::optional<std::vector<char>>& input );
};
+1
View File
@@ -338,6 +338,7 @@ target_include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Application
${CMAKE_CURRENT_SOURCE_DIR}/Application/Tools
${CMAKE_CURRENT_SOURCE_DIR}/Application/Tools/WellPathTools
${CMAKE_CURRENT_SOURCE_DIR}/Application/Tools/KeyValueStore
${CMAKE_CURRENT_SOURCE_DIR}/CommandFileInterface
${CMAKE_CURRENT_SOURCE_DIR}/CommandFileInterface/Core
${CMAKE_CURRENT_SOURCE_DIR}/FileInterface
@@ -7,6 +7,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RicExportSurfaceToTsurfFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewSurfaceCollectionFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewDepthSurfaceFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewRegularSurfaceFeature.h
)
set(SOURCE_GROUP_SOURCE_FILES
@@ -18,6 +19,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RicExportSurfaceToTsurfFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewSurfaceCollectionFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewDepthSurfaceFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewRegularSurfaceFeature.cpp
)
list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
@@ -0,0 +1,66 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicNewRegularSurfaceFeature.h"
#include "RimCase.h"
#include "RimProject.h"
#include "RimRegularSurface.h"
#include "RimSurface.h"
#include "RimSurfaceCollection.h"
#include "Riu3DMainWindowTools.h"
#include "cafSelectionManagerTools.h"
#include "cvfBoundingBox.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicNewRegularSurfaceFeature, "RicNewRegularSurfaceFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewRegularSurfaceFeature::onActionTriggered( bool isChecked )
{
auto colls = caf::selectedObjectsByTypeStrict<RimSurfaceCollection*>();
if ( colls.empty() ) return;
auto surface = new RimRegularSurface;
surface->setColor( cvf::Color3f::BLUE );
surface->setOpacity( true, 0.6f );
surface->setUserDescription( "Regular Surface" );
surface->loadDataIfRequired();
auto surfColl = colls.front();
surfColl->addSurfacesAtIndex( -1, { surface } );
surfColl->updateConnectedEditors();
Riu3DMainWindowTools::selectAsCurrentItem( surface );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewRegularSurfaceFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setIcon( QIcon( ":/ReservoirSurfaces16x16.png" ) );
actionToSetup->setText( "Create Regular Surface" );
}
@@ -0,0 +1,33 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafCmdFeature.h"
//==================================================================================================
///
//==================================================================================================
class RicNewRegularSurfaceFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
};
@@ -10,6 +10,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatisticsSurface.h
${CMAKE_CURRENT_LIST_DIR}/RimDepthSurface.h
${CMAKE_CURRENT_LIST_DIR}/RimFractureSurface.h
${CMAKE_CURRENT_LIST_DIR}/RimRegularSurface.h
)
set(SOURCE_GROUP_SOURCE_FILES
@@ -24,6 +25,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatisticsSurface.cpp
${CMAKE_CURRENT_LIST_DIR}/RimDepthSurface.cpp
${CMAKE_CURRENT_LIST_DIR}/RimFractureSurface.cpp
${CMAKE_CURRENT_LIST_DIR}/RimRegularSurface.cpp
)
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
@@ -0,0 +1,370 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimRegularSurface.h"
#include "RigSurface.h"
#include "RimSurfaceCollection.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
#include "cafPdmUiDoubleSliderEditor.h"
#include "cvfVector3.h"
#include <numbers>
CAF_PDM_SOURCE_INIT( RimRegularSurface, "RegularSurface" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimRegularSurface::RimRegularSurface()
{
CAF_PDM_InitScriptableObject( "RegularSurface", ":/ReservoirSurface16x16.png" );
CAF_PDM_InitScriptableField( &m_originX, "OriginX", 0.0, "Origin X" );
CAF_PDM_InitScriptableField( &m_originY, "OriginY", 0.0, "Origin Y" );
CAF_PDM_InitScriptableField( &m_depth, "Depth", 0.0, "Depth" );
m_depth.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() );
CAF_PDM_InitScriptableField( &m_nx, "Nx", 10, "Nx" );
CAF_PDM_InitScriptableField( &m_ny, "Ny", 10, "Ny" );
CAF_PDM_InitScriptableField( &m_incrementX, "IncrementX", 20.0, "Increment X" );
CAF_PDM_InitScriptableField( &m_incrementY, "IncrementY", 20.0, "Increment Y" );
CAF_PDM_InitScriptableField( &m_rotation, "Rotation", 0.0, "Rotation" );
CAF_PDM_InitScriptableField( &m_depthProperty, "DepthProperty", QString( "" ), "Depth Property" );
m_rotation.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimRegularSurface::onLoadData()
{
clearCachedNativeData();
return updateSurfaceData();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurface* RimRegularSurface::createCopy()
{
return copyObject<RimRegularSurface>();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularSurface::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
{
RimSurface::fieldChangedByUi( changedField, oldValue, newValue );
if ( changedField == &m_nx || changedField == &m_ny )
{
// Invalidate all properties when dimensions changes
m_properties.clear();
m_depthProperty = "";
}
clearCachedNativeData();
updateSurfaceData();
auto surfColl = firstAncestorOrThisOfTypeAsserted<RimSurfaceCollection>();
surfColl->updateViews( { this } );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularSurface::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute )
{
RimSurface::defineEditorAttribute( field, uiConfigName, attribute );
if ( field == &m_rotation )
{
if ( auto attr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>( attribute ) )
{
attr->m_minimum = 0.0;
attr->m_maximum = 360.0;
}
}
if ( field == &m_depth )
{
if ( auto attr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>( attribute ) )
{
attr->m_minimum = 0.0;
attr->m_maximum = 10000.0;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularSurface::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
auto locationGroup = uiOrdering.addNewGroup( "Location" );
locationGroup->add( &m_originX );
locationGroup->add( &m_originY );
locationGroup->add( &m_depth );
auto extentGroup = uiOrdering.addNewGroup( "Extent" );
extentGroup->add( &m_nx );
extentGroup->add( &m_ny );
extentGroup->add( &m_incrementX );
extentGroup->add( &m_incrementY );
uiOrdering.add( &m_rotation );
uiOrdering.add( &m_depthOffset );
// Fields from RimSurface
auto appearanceGroup = uiOrdering.addNewGroup( "Appearance" );
appearanceGroup->add( &m_userDescription );
appearanceGroup->add( &m_color );
appearanceGroup->add( &m_enableOpacity );
appearanceGroup->add( &m_opacity );
uiOrdering.skipRemainingFields();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularSurface::clearCachedNativeData()
{
m_vertices.clear();
m_triangleIndices.clear();
}
//--------------------------------------------------------------------------------------------------
/// Returns false for fatal failure
//--------------------------------------------------------------------------------------------------
bool RimRegularSurface::updateSurfaceData()
{
// Adapted from xtgeo surf_xyz_from_ij
auto computeXyzFromIj =
[]( int i, int j, double depth, double xori, double yori, double xinc, double yinc, double rotationDegrees ) -> cvf::Vec3d
{
CAF_ASSERT( i >= 0 );
CAF_ASSERT( j >= 0 );
double z = -depth;
if ( i == 0 && j == 0 ) return cvf::Vec3d( xori, yori, z );
// Surface rotation: this should be the usual angle, anti-clock from x axis,
// radians, positive
const double angle = rotationDegrees * std::numbers::pi / 180.0;
const double xdist = xinc * i;
const double ydist = yinc * j;
// Distance of point from "origo"
const double dist = sqrt( xdist * xdist + ydist * ydist );
const double beta = acos( xdist / dist );
if ( beta < 0 || beta > std::numbers::pi / 2.0 || std::isnan( beta ) ) return cvf::Vec3d::UNDEFINED;
// The difference in rotated coord system
double gamma = angle + beta;
double dxrot = dist * cos( gamma );
double dyrot = dist * sin( gamma );
return cvf::Vec3d( xori + dxrot, yori + dyrot, z );
};
for ( int j = 0; j < m_ny(); j++ )
{
for ( int i = 0; i < m_nx(); i++ )
{
double depth = m_depth;
if ( !m_depthProperty().isEmpty() && m_properties.contains( m_depthProperty ) )
{
depth = m_properties[m_depthProperty][j * m_nx + i];
}
m_vertices.push_back( computeXyzFromIj( i, j, depth, m_originX, m_originY, m_incrementX, m_incrementY, m_rotation ) );
}
}
// Iterate through the entire grid
for ( int j = 0; j < m_ny() - 1; j++ )
{
for ( int i = 0; i < m_nx() - 1; i++ )
{
// Calculate the indices of the four vertices in the current cell
// Top-left vertex
size_t idx00 = j * m_nx() + i;
// Top-right vertex
size_t idx01 = j * m_nx() + ( i + 1 );
// Bottom-left vertex
size_t idx10 = ( j + 1 ) * m_nx() + i;
// Bottom-right vertex
size_t idx11 = ( j + 1 ) * m_nx() + ( i + 1 );
// First triangle (top-left, top-right, bottom-left)
m_triangleIndices.push_back( static_cast<unsigned>( idx00 ) );
m_triangleIndices.push_back( static_cast<unsigned>( idx01 ) );
m_triangleIndices.push_back( static_cast<unsigned>( idx10 ) );
// Second triangle (top-right, bottom-right, bottom-left)
m_triangleIndices.push_back( static_cast<unsigned>( idx01 ) );
m_triangleIndices.push_back( static_cast<unsigned>( idx11 ) );
m_triangleIndices.push_back( static_cast<unsigned>( idx10 ) );
}
}
if ( !m_triangleIndices.empty() )
{
std::vector<unsigned> tringleIndices{ m_triangleIndices };
std::vector<cvf::Vec3d> vertices{ m_vertices };
cvf::Vec3d offset;
offset.z() += depthOffset();
RimSurface::applyDepthOffset( offset, &vertices );
auto surfaceData = new RigSurface;
surfaceData->setTriangleData( tringleIndices, vertices );
for ( auto& [key, vec] : m_properties )
{
surfaceData->addVertexResult( key, vec );
}
setSurfaceData( surfaceData );
}
else
{
setSurfaceData( nullptr );
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularSurface::setOriginX( double originX )
{
m_originX = originX;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularSurface::setOriginY( double originY )
{
m_originY = originY;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularSurface::setNx( int nx )
{
CAF_ASSERT( nx > 0 );
m_nx = nx;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularSurface::setNy( int ny )
{
CAF_ASSERT( ny > 0 );
m_ny = ny;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularSurface::setDepth( double depth )
{
m_depth = depth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularSurface::setIncrementX( double incrementX )
{
CAF_ASSERT( incrementX > 0.0 );
m_incrementX = incrementX;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularSurface::setIncrementY( double incrementY )
{
CAF_ASSERT( incrementY > 0.0 );
m_incrementY = incrementY;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularSurface::setRotation( double rotation )
{
CAF_ASSERT( rotation >= 0.0 && rotation <= 360.0 );
m_rotation = rotation;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRegularSurface::setProperty( const QString& key, const std::vector<float>& values )
{
CAF_ASSERT( values.size() == static_cast<size_t>( m_nx() * m_ny() ) );
m_properties[key] = values;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimRegularSurface::setPropertyAsDepth( const QString& key )
{
if ( !m_properties.contains( key ) ) return false;
m_depthProperty = key;
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimRegularSurface::nx() const
{
return m_nx;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimRegularSurface::ny() const
{
return m_ny;
}
@@ -0,0 +1,72 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSurface.h"
class RimRegularSurface : public RimSurface
{
CAF_PDM_HEADER_INIT;
public:
RimRegularSurface();
bool onLoadData() override;
RimSurface* createCopy() override;
void setOriginX( double originX );
void setOriginY( double originY );
void setNx( int nx );
void setNy( int ny );
void setDepth( double depth );
void setIncrementX( double incrementX );
void setIncrementY( double incrementY );
void setRotation( double rotation );
void setProperty( const QString& key, const std::vector<float>& values );
bool setPropertyAsDepth( const QString& key );
int nx() const;
int ny() const;
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;
private:
caf::PdmField<int> m_nx;
caf::PdmField<int> m_ny;
caf::PdmField<double> m_originX;
caf::PdmField<double> m_originY;
caf::PdmField<double> m_depth;
caf::PdmField<double> m_incrementX;
caf::PdmField<double> m_incrementY;
caf::PdmField<double> m_rotation;
caf::PdmField<QString> m_depthProperty;
std::vector<unsigned> m_triangleIndices;
std::vector<cvf::Vec3d> m_vertices;
std::map<QString, std::vector<float>> m_properties;
};
@@ -99,10 +99,10 @@ protected:
caf::PdmField<bool> m_enableOpacity;
caf::PdmField<bool> m_showMeshLines;
caf::PdmField<double> m_opacity;
caf::PdmField<double> m_depthOffset;
cvf::ref<RigSurface> m_surfaceData;
private:
caf::PdmProxyValueField<QString> m_nameProxy;
caf::PdmField<double> m_depthOffset;
};
@@ -295,6 +295,7 @@ void RimSurfaceCollection::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuil
menuBuilder << "RicImportSurfacesFeature";
menuBuilder << "RicNewGridSurfaceFeature";
menuBuilder << "RicNewDepthSurfaceFeature";
menuBuilder << "RicNewRegularSurfaceFeature";
menuBuilder << "RicImportEnsembleSurfaceFeature";
menuBuilder << "RicCreateEnsembleSurfaceFeature";
menuBuilder.addSeparator();
@@ -29,6 +29,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimcPressureTable.h
${CMAKE_CURRENT_LIST_DIR}/RimcFishbonesCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimcPolygonCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimcRegularSurface.h
)
set(SOURCE_GROUP_SOURCE_FILES
@@ -62,6 +63,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimcPressureTable.cpp
${CMAKE_CURRENT_LIST_DIR}/RimcFishbonesCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimcPolygonCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimcRegularSurface.cpp
)
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
@@ -19,6 +19,7 @@
#include "RimcProject.h"
#include "Ensemble/RiaEnsembleImportTools.h"
#include "KeyValueStore/RiaKeyValueStoreUtil.h"
#include "RiaApplication.h"
#include "RiaGuiApplication.h"
#include "RiaLogging.h"
@@ -271,34 +272,9 @@ std::expected<caf::PdmObjectHandle*, QString> RimProject_createGridFromKeyValues
auto keyValueStore = RiaApplication::instance()->keyValueStore();
auto convertToFloatVector = []( const std::optional<std::vector<char>>& input ) -> std::vector<float>
{
if ( input && !input->empty() )
{
// Ensure the byte vector size is a multiple of sizeof(float)
if ( input->size() % sizeof( float ) != 0 )
{
return {};
}
// Calculate how many floats we'll have
size_t float_count = input->size() / sizeof( float );
// Create a vector of floats with the appropriate size
std::vector<float> float_vec( float_count );
// Copy the binary data from the byte vector to the float vector
std::memcpy( float_vec.data(), input->data(), input->size() );
return float_vec;
}
return {};
};
std::vector<float> coord = convertToFloatVector( keyValueStore->get( m_coordKey().toStdString() ) );
std::vector<float> zcorn = convertToFloatVector( keyValueStore->get( m_zcornKey().toStdString() ) );
std::vector<float> actnum = convertToFloatVector( keyValueStore->get( m_actnumKey().toStdString() ) );
std::vector<float> coord = RiaKeyValueStoreUtil::convertToFloatVector( keyValueStore->get( m_coordKey().toStdString() ) );
std::vector<float> zcorn = RiaKeyValueStoreUtil::convertToFloatVector( keyValueStore->get( m_zcornKey().toStdString() ) );
std::vector<float> actnum = RiaKeyValueStoreUtil::convertToFloatVector( keyValueStore->get( m_actnumKey().toStdString() ) );
if ( coord.empty() || zcorn.empty() || actnum.empty() )
{
return std::unexpected( "Found unexcepted empty coord, zcorn or actnum array." );
@@ -0,0 +1,156 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimcRegularSurface.h"
#include "KeyValueStore/RiaKeyValueStoreUtil.h"
#include "RiaApplication.h"
#include "RimRegularSurface.h"
#include "RimSurfaceCollection.h"
#include "RifSurfaceExporter.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimRegularSurface, RimcRegularSurface_setPropertyFromKey, "SetPropertyFromKey" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcRegularSurface_setPropertyFromKey::RimcRegularSurface_setPropertyFromKey( caf::PdmObjectHandle* self )
: caf::PdmObjectMethod( self )
{
CAF_PDM_InitObject( "Set property from key", "", "", "Set property from key." );
CAF_PDM_InitScriptableFieldNoDefault( &m_name, "Name", "", "", "", "Name" );
CAF_PDM_InitScriptableFieldNoDefault( &m_valueKey, "ValueKey", "", "", "", "Key Value" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimcRegularSurface_setPropertyFromKey::execute()
{
RimRegularSurface* surface = self<RimRegularSurface>();
if ( !surface ) return std::unexpected( "No surface found" );
auto keyValueStore = RiaApplication::instance()->keyValueStore();
std::vector<float> values = RiaKeyValueStoreUtil::convertToFloatVector( keyValueStore->get( m_valueKey().toStdString() ) );
if ( values.empty() ) return std::unexpected( "Found unexcepted empty property." );
if ( values.size() != static_cast<size_t>( surface->nx() * surface->ny() ) )
return std::unexpected( "Failed to set property: incorrect dimensions." );
surface->setProperty( m_name, values );
surface->onLoadData();
if ( auto coll = surface->firstAncestorOrThisOfType<RimSurfaceCollection>() )
{
coll->updateUiIconFromToggleField();
coll->updateViews();
}
keyValueStore->remove( m_valueKey().toStdString() );
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimcRegularSurface_setPropertyFromKey::resultIsPersistent() const
{
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::unique_ptr<caf::PdmObjectHandle> RimcRegularSurface_setPropertyFromKey::defaultResult() const
{
return std::unique_ptr<caf::PdmObjectHandle>( nullptr );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimcRegularSurface_setPropertyFromKey::isNullptrValidResult() const
{
return true;
}
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimRegularSurface, RimcRegularSurface_setPropertyAsDepth, "SetPropertyAsDepth" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcRegularSurface_setPropertyAsDepth::RimcRegularSurface_setPropertyAsDepth( caf::PdmObjectHandle* self )
: caf::PdmObjectMethod( self )
{
CAF_PDM_InitObject( "Set property as depth", "", "", "Set property as depth." );
CAF_PDM_InitScriptableFieldNoDefault( &m_name, "Name", "", "", "", "Name" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimcRegularSurface_setPropertyAsDepth::execute()
{
RimRegularSurface* surface = self<RimRegularSurface>();
if ( !surface ) return std::unexpected( "No surface found" );
if ( !surface->setPropertyAsDepth( m_name ) ) return std::unexpected( "Failed to set depth property." );
surface->onLoadData();
if ( auto coll = surface->firstAncestorOrThisOfType<RimSurfaceCollection>() )
{
coll->updateUiIconFromToggleField();
coll->updateViews();
coll->updateConnectedEditors();
}
surface->updateConnectedEditors();
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimcRegularSurface_setPropertyAsDepth::resultIsPersistent() const
{
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::unique_ptr<caf::PdmObjectHandle> RimcRegularSurface_setPropertyAsDepth::defaultResult() const
{
return std::unique_ptr<caf::PdmObjectHandle>( nullptr );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimcRegularSurface_setPropertyAsDepth::isNullptrValidResult() const
{
return true;
}
@@ -0,0 +1,66 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmField.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmObjectMethod.h"
#include <QString>
#include <memory>
//==================================================================================================
///
//==================================================================================================
class RimcRegularSurface_setPropertyFromKey : public caf::PdmObjectMethod
{
CAF_PDM_HEADER_INIT;
public:
RimcRegularSurface_setPropertyFromKey( caf::PdmObjectHandle* self );
std::expected<caf::PdmObjectHandle*, QString> execute() override;
bool resultIsPersistent() const override;
std::unique_ptr<PdmObjectHandle> defaultResult() const override;
bool isNullptrValidResult() const override;
private:
caf::PdmField<QString> m_name;
caf::PdmField<QString> m_valueKey;
};
//==================================================================================================
///
//==================================================================================================
class RimcRegularSurface_setPropertyAsDepth : public caf::PdmObjectMethod
{
CAF_PDM_HEADER_INIT;
public:
RimcRegularSurface_setPropertyAsDepth( caf::PdmObjectHandle* self );
std::expected<caf::PdmObjectHandle*, QString> execute() override;
bool resultIsPersistent() const override;
std::unique_ptr<PdmObjectHandle> defaultResult() const override;
bool isNullptrValidResult() const override;
private:
caf::PdmField<QString> m_name;
};
@@ -22,6 +22,7 @@
#include "RimCase.h"
#include "RimFileSurface.h"
#include "RimGridCaseSurface.h"
#include "RimRegularSurface.h"
#include "RimSurface.h"
#include "RimSurfaceCollection.h"
@@ -33,6 +34,7 @@
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimSurfaceCollection, RimcSurfaceCollection_importSurface, "ImportSurface" );
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimSurfaceCollection, RimcSurfaceCollection_addFolder, "AddFolder" );
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimSurfaceCollection, RimcSurfaceCollection_newSurface, "NewSurface" );
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimSurfaceCollection, RimcSurfaceCollection_newRegularSurface, "NewRegularSurface" );
//--------------------------------------------------------------------------------------------------
///
@@ -182,3 +184,85 @@ bool RimcSurfaceCollection_newSurface::isNullptrValidResult() const
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcSurfaceCollection_newRegularSurface::RimcSurfaceCollection_newRegularSurface( caf::PdmObjectHandle* self )
: caf::PdmObjectMethod( self )
{
CAF_PDM_InitObject( "New Regular Surface", "", "", "Create a new regular surface" );
CAF_PDM_InitScriptableField( &m_name, "Name", QString( "" ), "Name" );
CAF_PDM_InitScriptableField( &m_originX, "OriginX", 0.0, "Origin X" );
CAF_PDM_InitScriptableField( &m_originY, "OriginY", 0.0, "Origin Y" );
CAF_PDM_InitScriptableField( &m_depth, "Depth", 0.0, "Depth" );
CAF_PDM_InitScriptableField( &m_nx, "Nx", 10, "Nx" );
CAF_PDM_InitScriptableField( &m_ny, "Ny", 10, "Ny" );
CAF_PDM_InitScriptableField( &m_incrementX, "IncrementX", 20.0, "Increment X" );
CAF_PDM_InitScriptableField( &m_incrementY, "IncrementY", 20.0, "Increment Y" );
CAF_PDM_InitScriptableField( &m_rotation, "Rotation", 0.0, "Rotation" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimcSurfaceCollection_newRegularSurface::execute()
{
RimSurfaceCollection* coll = self<RimSurfaceCollection>();
if ( !coll ) return std::unexpected( "No surface collection found" );
if ( m_nx() <= 0 ) return std::unexpected( "Invalid nx. Must be positive." );
if ( m_ny() <= 0 ) return std::unexpected( "Invalid ny. Must be positive." );
if ( m_incrementX() <= 0.0 ) return std::unexpected( "Invalid increment X. Must be positive." );
if ( m_incrementY() <= 0.0 ) return std::unexpected( "Invalid increment Y. Must be positive." );
if ( m_rotation() < 0.0 || m_rotation() > 360.0 ) return std::unexpected( "Invalid rotation. Valid range: [0.0-360.0]" );
RimRegularSurface* surface = new RimRegularSurface;
surface->setUserDescription( m_name() );
surface->setNx( m_nx() );
surface->setNy( m_ny() );
surface->setOriginX( m_originX() );
surface->setOriginY( m_originY() );
surface->setDepth( m_depth() );
surface->setIncrementX( m_incrementX() );
surface->setIncrementY( m_incrementY() );
surface->setRotation( m_rotation() );
surface->setColor( cvf::Color3f::BLUE );
surface->setOpacity( true, 0.6f );
coll->addSurface( surface );
coll->updateViews();
coll->updateConnectedEditors();
return surface;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimcSurfaceCollection_newRegularSurface::resultIsPersistent() const
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::unique_ptr<caf::PdmObjectHandle> RimcSurfaceCollection_newRegularSurface::defaultResult() const
{
return std::unique_ptr<caf::PdmObjectHandle>( new RimRegularSurface );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimcSurfaceCollection_newRegularSurface::isNullptrValidResult() const
{
return true;
}
@@ -90,3 +90,30 @@ private:
caf::PdmPtrField<RimCase*> m_case;
caf::PdmField<int> m_kIndex;
};
//==================================================================================================
///
//==================================================================================================
class RimcSurfaceCollection_newRegularSurface : public caf::PdmObjectMethod
{
CAF_PDM_HEADER_INIT;
public:
RimcSurfaceCollection_newRegularSurface( caf::PdmObjectHandle* self );
std::expected<caf::PdmObjectHandle*, QString> execute() override;
bool resultIsPersistent() const override;
std::unique_ptr<PdmObjectHandle> defaultResult() const override;
bool isNullptrValidResult() const override;
private:
caf::PdmField<QString> m_name;
caf::PdmField<int> m_nx;
caf::PdmField<int> m_ny;
caf::PdmField<double> m_originX;
caf::PdmField<double> m_originY;
caf::PdmField<double> m_depth;
caf::PdmField<double> m_incrementX;
caf::PdmField<double> m_incrementY;
caf::PdmField<double> m_rotation;
};