Intersection : Add Python support for triangle and result values (#8505)

#8508 Python : Make sure an empty list will be received as empty list in Python

Co-authored-by: magnesj <magnesj@users.noreply.github.com>
This commit is contained in:
Magne Sjaastad 2022-02-07 18:38:19 +01:00 committed by GitHub
parent 316cb222d9
commit 64bed86f8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 722 additions and 28 deletions

View File

@ -478,6 +478,15 @@ void RivExtrudedCurveIntersectionGeometryGenerator::calculateArrays()
point1 = point1.getTransformedPoint( invSectionCS );
point2 = point2.getTransformedPoint( invSectionCS );
if ( m_isFlattened )
{
// The points are transformed in to the XZ-plane with Y = zero.
// Set all y values to zero to avoid numerical issues
point0.y() = 0.0;
point1.y() = 0.0;
point2.y() = 0.0;
}
triangleVertices.emplace_back( point0 );
triangleVertices.emplace_back( point1 );
triangleVertices.emplace_back( point2 );
@ -765,6 +774,31 @@ const cvf::Vec3fArray* RivExtrudedCurveIntersectionGeometryGenerator::triangleVx
return m_triangleVxes.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const cvf::Vec3fArray* RivExtrudedCurveIntersectionGeometryGenerator::cellMeshVxes() const
{
CVF_ASSERT( m_cellBorderLineVxes->size() );
return m_cellBorderLineVxes.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const cvf::Vec3fArray* RivExtrudedCurveIntersectionGeometryGenerator::faultMeshVxes() const
{
return m_faultCellBorderLineVxes.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivExtrudedCurveIntersectionGeometryGenerator::ensureGeometryIsCalculated()
{
calculateArrays();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -81,6 +81,10 @@ public:
const std::vector<size_t>& triangleToCellIndex() const override;
const std::vector<RivIntersectionVertexWeights>& triangleVxToCellCornerInterpolationWeights() const override;
const cvf::Vec3fArray* triangleVxes() const override;
const cvf::Vec3fArray* cellMeshVxes() const override;
const cvf::Vec3fArray* faultMeshVxes() const override;
void ensureGeometryIsCalculated();
private:
void calculateArrays();

View File

@ -27,8 +27,11 @@
class RivIntersectionGeometryGeneratorInterface
{
public:
virtual bool isAnyGeometryPresent() const = 0;
virtual const std::vector<size_t>& triangleToCellIndex() const = 0;
virtual ~RivIntersectionGeometryGeneratorInterface() = default;
virtual bool isAnyGeometryPresent() const = 0;
virtual const std::vector<size_t>& triangleToCellIndex() const = 0;
virtual const std::vector<RivIntersectionVertexWeights>& triangleVxToCellCornerInterpolationWeights() const = 0;
virtual const cvf::Vec3fArray* triangleVxes() const = 0;
virtual const cvf::Vec3fArray* cellMeshVxes() const { return nullptr; };
virtual const cvf::Vec3fArray* faultMeshVxes() const { return nullptr; };
};

View File

@ -52,12 +52,14 @@
#include "cafCmdFeature.h"
#include "cafCmdFeatureManager.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmFieldScriptingCapabilityCvfVec3d.h"
#include "cafPdmObjectScriptingCapability.h"
#include "cafPdmUiCheckBoxEditor.h"
#include "cafPdmUiDoubleSliderEditor.h"
#include "cafPdmUiListEditor.h"
#include "cafPdmUiPushButtonEditor.h"
#include "cafPdmUiSliderEditor.h"
#include "cafPdmUiTreeOrdering.h"
#include "cafPdmUiTreeSelectionEditor.h"
#include "cvfBoundingBox.h"
@ -73,7 +75,7 @@ void caf::AppEnum<RimExtrudedCurveIntersection::CrossSectionEnum>::setUp()
addItem( RimExtrudedCurveIntersection::CrossSectionEnum::CS_SIMULATION_WELL, "CS_SIMULATION_WELL", "Simulation Well" );
addItem( RimExtrudedCurveIntersection::CrossSectionEnum::CS_POLYLINE, "CS_POLYLINE", "Polyline" );
addItem( RimExtrudedCurveIntersection::CrossSectionEnum::CS_AZIMUTHLINE, "CS_AZIMUTHLINE", "Azimuth and Dip" );
setDefault( RimExtrudedCurveIntersection::CrossSectionEnum::CS_WELL_PATH );
setDefault( RimExtrudedCurveIntersection::CrossSectionEnum::CS_POLYLINE );
}
template <>
@ -87,7 +89,7 @@ void caf::AppEnum<RimExtrudedCurveIntersection::CrossSectionDirEnum>::setUp()
} // namespace caf
CAF_PDM_SOURCE_INIT( RimExtrudedCurveIntersection, "CrossSection" );
CAF_PDM_SOURCE_INIT( RimExtrudedCurveIntersection, "CurveIntersection", "CrossSection" );
//--------------------------------------------------------------------------------------------------
///
@ -196,14 +198,19 @@ void RimExtrudedCurveIntersection::configureForAzimuthLine()
//--------------------------------------------------------------------------------------------------
RimExtrudedCurveIntersection::RimExtrudedCurveIntersection()
{
CAF_PDM_InitObject( "Intersection", ":/CrossSection16x16.png" );
CAF_PDM_InitField( &m_name, "UserDescription", QString( "Intersection Name" ), "Name" );
CAF_PDM_InitScriptableObject( "Intersection", ":/CrossSection16x16.png" );
CAF_PDM_InitScriptableFieldWithScriptKeyword( &m_name, "UserDescription", "Name", QString( "Intersection Name" ), "Name" );
CAF_PDM_InitFieldNoDefault( &m_type, "Type", "Type" );
CAF_PDM_InitScriptableFieldNoDefault( &m_type, "Type", "Type" );
CAF_PDM_InitFieldNoDefault( &m_direction, "Direction", "Direction" );
CAF_PDM_InitFieldNoDefault( &m_wellPath, "WellPath", "Well Path " );
CAF_PDM_InitFieldNoDefault( &m_simulationWell, "SimulationWell", "Simulation Well" );
CAF_PDM_InitFieldNoDefault( &m_userPolylineXyz, "Points", "Points", "", "Use Ctrl-C for copy and Ctrl-V for paste", "" );
CAF_PDM_InitScriptableFieldNoDefault( &m_wellPath, "WellPath", "Well Path " );
CAF_PDM_InitScriptableFieldNoDefault( &m_simulationWell, "SimulationWell", "Simulation Well" );
CAF_PDM_InitScriptableFieldNoDefault( &m_userPolylineXyz,
"Points",
"Points",
"",
"Use Ctrl-C for copy and Ctrl-V for paste",
"" );
CAF_PDM_InitFieldNoDefault( &m_userPolylineXydForUi, "PointsUi", "Points", "", "Use Ctrl-C for copy and Ctrl-V for paste", "" );
m_userPolylineXydForUi.registerSetMethod( this, &RimExtrudedCurveIntersection::setPointsFromXYD );

View File

@ -38,19 +38,20 @@
#include "RivBoxIntersectionPartMgr.h"
#include "RivExtrudedCurveIntersectionPartMgr.h"
#include "cafPdmObjectScriptingCapability.h"
#include "cafPdmUiCheckBoxEditor.h"
#include "cafPdmUiDoubleSliderEditor.h"
#include "cafPdmUiTreeOrdering.h"
#include "cvfModelBasicList.h"
CAF_PDM_SOURCE_INIT( RimIntersectionCollection, "CrossSectionCollection" );
CAF_PDM_SOURCE_INIT( RimIntersectionCollection, "IntersectionCollection", "CrossSectionCollection" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimIntersectionCollection::RimIntersectionCollection()
{
CAF_PDM_InitObject( "Intersections", ":/CrossSections16x16.png" );
CAF_PDM_InitScriptableObject( "Intersections", ":/CrossSections16x16.png" );
CAF_PDM_InitFieldNoDefault( &m_intersections, "CrossSections", "Intersections" );
m_intersections.uiCapability()->setUiTreeHidden( true );
@ -404,6 +405,15 @@ void RimIntersectionCollection::onChildDeleted( caf::PdmChildArrayFieldHandle*
rebuild3dView();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimIntersectionCollection::onChildAdded( caf::PdmFieldHandle* containerForNewObject )
{
syncronize2dIntersectionViews();
rebuild3dView();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -83,6 +83,8 @@ public:
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray,
std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
void onChildAdded( caf::PdmFieldHandle* containerForNewObject ) override;
protected:
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
caf::PdmFieldHandle* objectToggleField() override;

View File

@ -20,6 +20,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimcModeledWellPath.h
${CMAKE_CURRENT_LIST_DIR}/RimcWellPath.h
${CMAKE_CURRENT_LIST_DIR}/RimcFractureTemplateCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimcIntersection.h
)
set(SOURCE_GROUP_SOURCE_FILES
@ -44,6 +45,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimcModeledWellPath.cpp
${CMAKE_CURRENT_LIST_DIR}/RimcWellPath.cpp
${CMAKE_CURRENT_LIST_DIR}/RimcFractureTemplateCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimcIntersection.cpp
)
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})

View File

@ -32,3 +32,14 @@ RimcDataContainerDouble::RimcDataContainerDouble()
CAF_PDM_InitScriptableObject( "Data Container Float" );
CAF_PDM_InitScriptableFieldNoDefault( &m_doubleValues, "values", "Float Values" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcDataContainerDouble* RimcDataContainerDouble::create( const std::vector<double>& values )
{
auto obj = new RimcDataContainerDouble;
obj->m_doubleValues = values;
return obj;
}

View File

@ -31,5 +31,7 @@ class RimcDataContainerDouble : public caf::PdmObject
public:
RimcDataContainerDouble();
static RimcDataContainerDouble* create( const std::vector<double>& values );
caf::PdmField<std::vector<double>> m_doubleValues;
};

View File

@ -37,7 +37,7 @@ RimcElasticProperties_addPropertyScaling::RimcElasticProperties_addPropertyScali
CAF_PDM_InitScriptableFieldNoDefault( &m_formation, "Formation", "", "", "", "Formation" );
CAF_PDM_InitScriptableFieldNoDefault( &m_facies, "Facies", "", "", "", "Facies" );
CAF_PDM_InitScriptableFieldNoDefault( &m_property, "Property", "", "", "", "Property" );
CAF_PDM_InitScriptableFieldNoDefault( &m_scale, "Scale", "", "", "", "Scale" );
CAF_PDM_InitScriptableField( &m_scale, "Scale", 1.0, "", "", "", "Scale" );
}
//--------------------------------------------------------------------------------------------------

View File

@ -0,0 +1,365 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2022- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimcIntersection.h"
#include "RiaLogging.h"
#include "RigResultAccessor.h"
#include "RigResultAccessorFactory.h"
#include "Rim2dIntersectionView.h"
#include "RimEclipseCase.h"
#include "RimEclipseCellColors.h"
#include "RimEclipseResultDefinition.h"
#include "RimEclipseView.h"
#include "RimExtrudedCurveIntersection.h"
#include "RimIntersectionResultDefinition.h"
#include "RimcDataContainerDouble.h"
#include "RivExtrudedCurveIntersectionGeometryGenerator.h"
#include "RivExtrudedCurveIntersectionPartMgr.h"
#include "RivIntersectionGeometryGeneratorInterface.h"
#include "RivIntersectionHexGridInterface.h"
#include "cafPdmAbstractFieldScriptingCapability.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmFieldScriptingCapabilityCvfVec3d.h"
#include "cafPdmObjectScriptingCapability.h"
#include <memory>
namespace caf
{
template <>
void caf::AppEnum<RimcTriangleGeometry::GeometryType>::setUp()
{
addItem( RimcTriangleGeometry::GeometryType::FULL_3D, "FULL_3D", "Full 3DDynamic" );
addItem( RimcTriangleGeometry::GeometryType::PROJECTED_TO_PLANE, "PROJECTED_TO_PLANE", "Projected To Plane" );
setDefault( RimcTriangleGeometry::GeometryType::FULL_3D );
}
}; // namespace caf
CAF_PDM_SOURCE_INIT( RimcTriangleGeometry, "TriangleGeometry" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcTriangleGeometry::RimcTriangleGeometry()
{
CAF_PDM_InitScriptableObject( "Triangle Geometry" );
CAF_PDM_InitScriptableFieldNoDefault( &m_x, "XCoords", "X coords" );
CAF_PDM_InitScriptableFieldNoDefault( &m_y, "YCoords", "Y coords" );
CAF_PDM_InitScriptableFieldNoDefault( &m_z, "ZCoords", "Z coords" );
CAF_PDM_InitScriptableFieldNoDefault( &m_connections, "Connections", "Indices to triangle vertices" );
CAF_PDM_InitScriptableFieldNoDefault( &m_meshX, "MeshXCoords", "Mesh X coords" );
CAF_PDM_InitScriptableFieldNoDefault( &m_meshY, "MeshYCoords", "Mesh Y coords" );
CAF_PDM_InitScriptableFieldNoDefault( &m_meshZ, "MeshZCoords", "Mesh Z coords" );
CAF_PDM_InitScriptableFieldNoDefault( &m_faultMeshX, "FaultMeshXCoords", "Fault Mesh X coords" );
CAF_PDM_InitScriptableFieldNoDefault( &m_faultMeshY, "FaultmeshYCoords", "Fault Mesh Y coords" );
CAF_PDM_InitScriptableFieldNoDefault( &m_faultMeshZ, "FaultmeshZCoords", "Fault Mesh Z coords" );
CAF_PDM_InitScriptableFieldNoDefault( &m_displayModelOffset, "DisplayModelOffset", "Display Model Offset" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcTriangleGeometry* RimcTriangleGeometry::createFromVertices( const std::vector<cvf::Vec3f>& vertices )
{
std::vector<int> conn;
if ( !vertices.empty() )
{
conn.resize( vertices.size() );
std::iota( conn.begin(), conn.end(), 0 );
}
return createFromVerticesAndConnections( vertices, conn );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcTriangleGeometry* RimcTriangleGeometry::createFromVerticesAndConnections( const std::vector<cvf::Vec3f>& vertices,
const std::vector<int>& connections )
{
auto [xVals, yVals, zVals] = assignCoordinatesToSeparateVectors( vertices );
auto obj = new RimcTriangleGeometry;
obj->m_x = xVals;
obj->m_y = yVals;
obj->m_z = zVals;
obj->m_connections = connections;
return obj;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimcTriangleGeometry::setMeshVertices( const std::vector<cvf::Vec3f>& vertices )
{
auto [xVals, yVals, zVals] = assignCoordinatesToSeparateVectors( vertices );
m_meshX = xVals;
m_meshY = yVals;
m_meshZ = zVals;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimcTriangleGeometry::setFaultMeshVertices( const std::vector<cvf::Vec3f>& faultMeshVertices )
{
auto [xVals, yVals, zVals] = assignCoordinatesToSeparateVectors( faultMeshVertices );
m_faultMeshX = xVals;
m_faultMeshY = yVals;
m_faultMeshZ = zVals;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimcTriangleGeometry::setDisplayModelOffset( const cvf::Vec3d& offset )
{
m_displayModelOffset = offset;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::tuple<std::vector<float>, std::vector<float>, std::vector<float>>
RimcTriangleGeometry::assignCoordinatesToSeparateVectors( const std::vector<cvf::Vec3f>& vertices )
{
std::vector<float> xVals;
std::vector<float> yVals;
std::vector<float> zVals;
if ( !vertices.empty() )
{
xVals.reserve( vertices.size() );
yVals.reserve( vertices.size() );
zVals.reserve( vertices.size() );
for ( const auto& v : vertices )
{
xVals.push_back( v.x() );
yVals.push_back( v.y() );
zVals.push_back( v.z() );
}
}
return { xVals, yVals, zVals };
}
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimExtrudedCurveIntersection, RimcExtrudedCurveIntersection_geometry, "geometry" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcExtrudedCurveIntersection_geometry::RimcExtrudedCurveIntersection_geometry( caf::PdmObjectHandle* self )
: caf::PdmObjectMethod( self )
{
CAF_PDM_InitObject( "Intersection Geometry" );
CAF_PDM_InitScriptableFieldNoDefault( &m_geometryType, "GeometryType", "Geometry Type" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmObjectHandle* RimcExtrudedCurveIntersection_geometry::execute()
{
auto intersection = self<RimExtrudedCurveIntersection>();
auto geoGenerator = RimcExtrudedCurveIntersection_geometry::createGeometryGenerator( intersection, m_geometryType() );
if ( geoGenerator && geoGenerator->isAnyGeometryPresent() )
{
std::vector<cvf::Vec3f> coords;
geoGenerator->triangleVxes()->toStdVector( &coords );
auto triangleGeometry = RimcTriangleGeometry::createFromVertices( coords );
{
auto cellMeshVertices = geoGenerator->cellMeshVxes();
if ( cellMeshVertices )
{
std::vector<cvf::Vec3f> meshCoords;
cellMeshVertices->toStdVector( &meshCoords );
triangleGeometry->setMeshVertices( meshCoords );
}
}
{
auto faultMeshVertices = geoGenerator->faultMeshVxes();
if ( faultMeshVertices )
{
std::vector<cvf::Vec3f> meshCoords;
faultMeshVertices->toStdVector( &meshCoords );
triangleGeometry->setFaultMeshVertices( meshCoords );
}
}
{
RimEclipseView* eclView = nullptr;
intersection->firstAncestorOfType( eclView );
if ( eclView && eclView->eclipseCase() )
{
auto offset = eclView->eclipseCase()->displayModelOffset();
triangleGeometry->setDisplayModelOffset( offset );
}
}
return triangleGeometry;
}
return new RimcTriangleGeometry;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimcExtrudedCurveIntersection_geometry::resultIsPersistent() const
{
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::unique_ptr<caf::PdmObjectHandle> RimcExtrudedCurveIntersection_geometry::defaultResult() const
{
return std::unique_ptr<caf::PdmObjectHandle>( new RimcTriangleGeometry );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::unique_ptr<RivIntersectionGeometryGeneratorInterface>
RimcExtrudedCurveIntersection_geometry::createGeometryGenerator( RimExtrudedCurveIntersection* intersection,
RimcTriangleGeometry::GeometryType geometryType )
{
bool isFlat = false;
if ( geometryType == RimcTriangleGeometry::GeometryType::PROJECTED_TO_PLANE ) isFlat = true;
cvf::Vec3d flattenedPolylineStartPoint;
auto polyLines = intersection->polyLines( &flattenedPolylineStartPoint );
if ( !polyLines.empty() )
{
auto direction = intersection->extrusionDirection();
auto hexGrid = intersection->createHexGridInterface();
auto intersectionGeoGenerator =
std::make_unique<RivExtrudedCurveIntersectionGeometryGenerator>( intersection,
polyLines,
direction,
hexGrid.p(),
isFlat,
flattenedPolylineStartPoint );
intersectionGeoGenerator->ensureGeometryIsCalculated();
return intersectionGeoGenerator;
}
return nullptr;
}
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimExtrudedCurveIntersection,
RimcExtrudedCurveIntersection_geometryResult,
"geometryResult" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcExtrudedCurveIntersection_geometryResult::RimcExtrudedCurveIntersection_geometryResult( caf::PdmObjectHandle* self )
: caf::PdmObjectMethod( self )
{
CAF_PDM_InitObject( "Geometry Result" );
CAF_PDM_InitScriptableFieldNoDefault( &m_geometryType, "GeometryType", "Geometry Type" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmObjectHandle* RimcExtrudedCurveIntersection_geometryResult::execute()
{
auto intersection = self<RimExtrudedCurveIntersection>();
auto geoGenerator = RimcExtrudedCurveIntersection_geometry::createGeometryGenerator( intersection, m_geometryType() );
if ( geoGenerator && geoGenerator->isAnyGeometryPresent() )
{
RimEclipseView* eclView = nullptr;
intersection->firstAncestorOfType( eclView );
if ( !eclView )
{
RiaLogging::error( "No Eclipse view found. Extraction of intersection result is only supported for "
"Eclipse view." );
return nullptr;
}
RimEclipseResultDefinition* eclResultDef = nullptr;
auto intersectionResultDef = intersection->activeSeparateResultDefinition();
if ( intersectionResultDef ) eclResultDef = intersectionResultDef->eclipseResultDefinition();
if ( !eclResultDef ) eclResultDef = eclView->cellResult();
RigEclipseCaseData* eclipseCase = eclView->eclipseCase()->eclipseCaseData();
size_t gridIndex = 0;
cvf::ref<RigResultAccessor> resultAccessor =
RigResultAccessorFactory::createFromResultDefinition( eclipseCase,
gridIndex,
eclView->currentTimeStep(),
eclResultDef );
auto triToCellIndex = geoGenerator->triangleToCellIndex();
std::vector<double> values;
values.reserve( triToCellIndex.size() );
for ( const auto& i : triToCellIndex )
{
auto value = resultAccessor->cellScalar( i );
values.push_back( value );
}
return RimcDataContainerDouble::create( values );
}
return new RimcDataContainerDouble();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimcExtrudedCurveIntersection_geometryResult::resultIsPersistent() const
{
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::unique_ptr<caf::PdmObjectHandle> RimcExtrudedCurveIntersection_geometryResult::defaultResult() const
{
return std::unique_ptr<caf::PdmObjectHandle>( new RimcDataContainerDouble );
}

View File

@ -0,0 +1,117 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2022- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafPdmField.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmObjectMethod.h"
#include "cafPdmPtrField.h"
#include <QString>
#include "cvfVector3.h"
class RivIntersectionGeometryGeneratorInterface;
class RimExtrudedCurveIntersection;
//==================================================================================================
///
//==================================================================================================
class RimcTriangleGeometry : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
enum class GeometryType
{
FULL_3D,
PROJECTED_TO_PLANE,
};
public:
RimcTriangleGeometry();
static RimcTriangleGeometry* createFromVertices( const std::vector<cvf::Vec3f>& vertices );
static RimcTriangleGeometry* createFromVerticesAndConnections( const std::vector<cvf::Vec3f>& vertices,
const std::vector<int>& connections );
void setMeshVertices( const std::vector<cvf::Vec3f>& meshVertices );
void setFaultMeshVertices( const std::vector<cvf::Vec3f>& faultMeshVertices );
void setDisplayModelOffset( const cvf::Vec3d& offset );
private:
static std::tuple<std::vector<float>, std::vector<float>, std::vector<float>>
assignCoordinatesToSeparateVectors( const std::vector<cvf::Vec3f>& vertices );
private:
caf::PdmField<std::vector<float>> m_x;
caf::PdmField<std::vector<float>> m_y;
caf::PdmField<std::vector<float>> m_z;
caf::PdmField<std::vector<int>> m_connections;
caf::PdmField<std::vector<float>> m_meshX;
caf::PdmField<std::vector<float>> m_meshY;
caf::PdmField<std::vector<float>> m_meshZ;
caf::PdmField<std::vector<float>> m_faultMeshX;
caf::PdmField<std::vector<float>> m_faultMeshY;
caf::PdmField<std::vector<float>> m_faultMeshZ;
caf::PdmField<cvf::Vec3d> m_displayModelOffset;
};
//==================================================================================================
///
//==================================================================================================
class RimcExtrudedCurveIntersection_geometry : public caf::PdmObjectMethod
{
CAF_PDM_HEADER_INIT;
public:
RimcExtrudedCurveIntersection_geometry( caf::PdmObjectHandle* self );
caf::PdmObjectHandle* execute() override;
bool resultIsPersistent() const override;
std::unique_ptr<PdmObjectHandle> defaultResult() const override;
static std::unique_ptr<RivIntersectionGeometryGeneratorInterface>
createGeometryGenerator( RimExtrudedCurveIntersection* intersection,
RimcTriangleGeometry::GeometryType geometryType );
private:
caf::PdmField<caf::AppEnum<RimcTriangleGeometry::GeometryType>> m_geometryType;
};
//==================================================================================================
///
//==================================================================================================
class RimcExtrudedCurveIntersection_geometryResult : public caf::PdmObjectMethod
{
CAF_PDM_HEADER_INIT;
public:
RimcExtrudedCurveIntersection_geometryResult( caf::PdmObjectHandle* self );
caf::PdmObjectHandle* execute() override;
bool resultIsPersistent() const override;
std::unique_ptr<PdmObjectHandle> defaultResult() const override;
private:
caf::PdmField<caf::AppEnum<RimcTriangleGeometry::GeometryType>> m_geometryType;
};

View File

@ -43,7 +43,7 @@ RimcStimPlanModelTemplateCollection_appendStimPlanModelTemplate::RimcStimPlanMod
{
CAF_PDM_InitObject( "Create StimPlan Model Template", "", "", "Create a new StimPlan Model Template" );
CAF_PDM_InitScriptableFieldNoDefault( &m_eclipseCase, "EclipseCase", "", "", "", "Eclipse Case" );
CAF_PDM_InitScriptableFieldNoDefault( &m_timeStep, "TimeStep", "", "", "", "Time Step" );
CAF_PDM_InitScriptableField( &m_timeStep, "TimeStep", 0, "", "", "", "Time Step" );
CAF_PDM_InitScriptableFieldNoDefault( &m_faciesPropertiesFilePath,
"FaciesPropertiesFilePath",

View File

@ -66,10 +66,7 @@ caf::PdmObjectHandle* RimSummaryCase_summaryVectorValues::execute()
}
}
auto dataObject = new RimcDataContainerDouble();
dataObject->m_doubleValues = values;
return dataObject;
return RimcDataContainerDouble::create( values );
}
//--------------------------------------------------------------------------------------------------

View File

@ -142,7 +142,7 @@ RimcSurfaceCollection_newSurface::RimcSurfaceCollection_newSurface( caf::PdmObje
{
CAF_PDM_InitObject( "New Surface", "", "", "Create a new surface" );
CAF_PDM_InitScriptableFieldNoDefault( &m_case, "Case", "" );
CAF_PDM_InitScriptableFieldNoDefault( &m_kIndex, "KIndex", "" );
CAF_PDM_InitScriptableField( &m_kIndex, "KIndex", 0, "" );
}
//--------------------------------------------------------------------------------------------------

View File

@ -18,6 +18,10 @@
#include "RiuTimeStepChangedHandler.h"
#include "RiaGuiApplication.h"
#include "Rim3dView.h"
#include "RiuMainWindow.h"
#include "RiuMohrsCirclePlot.h"
#include "RiuPvtPlotPanel.h"
@ -25,8 +29,6 @@
#include "RiuRelativePermeabilityPlotPanel.h"
#include "RiuRelativePermeabilityPlotUpdater.h"
#include "Rim3dView.h"
#include "cvfDebugTimer.h"
#include "cvfTrace.h"
@ -59,8 +61,7 @@ RiuTimeStepChangedHandler* RiuTimeStepChangedHandler::instance()
//--------------------------------------------------------------------------------------------------
void RiuTimeStepChangedHandler::handleTimeStepChanged( Rim3dView* changedView ) const
{
// cvf::Trace::show("handleTimeStepChanged() viewName: %s timeStep:%d", changedView->name().toLatin1().data(),
// changedView->currentTimeStep()); cvf::DebugTimer tim("handleTimeStepChanged()");
if ( !RiaGuiApplication::isRunning() ) return;
RiuRelativePermeabilityPlotUpdater* relPermPlotUpdater =
RiuMainWindow::instance()->relativePermeabilityPlotPanel()->plotUpdater();
@ -71,6 +72,4 @@ void RiuTimeStepChangedHandler::handleTimeStepChanged( Rim3dView* changedView )
RiuMohrsCirclePlot* mohrsCirclePlot = RiuMainWindow::instance()->mohrsCirclePlot();
if ( mohrsCirclePlot ) mohrsCirclePlot->updateOnTimeStepChanged( changedView );
// tim.reportTimeMS("done");
}

View File

@ -282,10 +282,20 @@ QString caf::PdmPythonGenerator::generate( PdmObjectFactory* factory, std::vecto
QString defaultValue = getDefaultValue( field );
QString commentOrEnumDescription = field->uiCapability()->uiWhatsThis();
QStringList enumTexts = scriptability->enumScriptTexts();
if ( !enumTexts.empty() )
{
// Replace the comment text with enum values
// The space is limited for the generation of documentation
commentOrEnumDescription = "One of [" + enumTexts.join( ", " ) + "]";
}
inputArgumentStrings.push_back( QString( "%1=%2" ).arg( argumentName ).arg( defaultValue ) );
outputArgumentStrings.push_back( QString( "%1=%1" ).arg( argumentName ) );
argumentComments.push_back(
QString( "%1 (%2): %3" ).arg( argumentName ).arg( dataType ).arg( field->uiCapability()->uiWhatsThis() ) );
QString( "%1 (%2): %3" ).arg( argumentName ).arg( dataType ).arg( commentOrEnumDescription ) );
}
QString fullComment = QString( " \"\"\"\n %1\n\n Arguments:\n "
"%2\n Returns:\n %3\n \"\"\"" )
@ -468,6 +478,9 @@ QString PdmPythonGenerator::dataTypeString( const PdmFieldHandle* field, bool us
{
auto xmlObj = field->capability<PdmXmlFieldHandle>();
auto scriptability = field->capability<PdmAbstractFieldScriptingCapability>();
if ( scriptability && !scriptability->enumScriptTexts().empty() ) return "str";
QString dataType = xmlObj->dataTypeName();
std::map<QString, QString> builtins = { { QString::fromStdString( typeid( double ).name() ), "float" },

View File

@ -0,0 +1,56 @@
# Load ResInsight Processing Server Client Library
import math, time
import rips
resinsight = rips.Instance.find()
# The coordinates in this example is based on the Drogon test case from Equinor
file_path = "e:/models/from_equinor_sftp/drogon-real0-iter3/DROGON-0.EGRID"
case = resinsight.project.load_case(file_path)
view = case.create_view()
view.set_time_step(2)
intersection_coll = resinsight.project.descendants(rips.IntersectionCollection)[0]
# Add a CurveIntersection and set coordinates for the polyline
intersection = intersection_coll.add_new_object(rips.CurveIntersection)
intersection.points = [
[45854, 595757, 1500],
[46493, 534259.1, 1500],
[46598, 590044.1, 1500],
]
intersection.update()
# Add a new modeled well path
well_path_coll = resinsight.project.descendants(rips.WellPathCollection)[0]
well_path = well_path_coll.add_new_object(rips.ModeledWellPath)
well_path.name = "Test Well-1"
well_path.update()
# Set reference coordinate
geometry = well_path.well_path_geometry()
reference_point = geometry.reference_point
reference_point[0] = 458580
reference_point[1] = 5935514
reference_point[2] = 1742
geometry.update() # Commit updates back to ResInsight
# Create the first well target at the reference point
coord = [0, 0, 0]
geometry.append_well_target(coord)
# Append new well targets relative the the reference point
coord = [2229.10, -833.74, -74.70]
target = geometry.append_well_target(coord)
coord = [4577.21, -3043.47, -87.15]
target = geometry.append_well_target(coord)
geometry.update()
# Add a curve intersection based on the modeled well path
well_path_intersection = intersection_coll.add_new_object(rips.CurveIntersection)
well_path_intersection.type = "CS_WELL_PATH"
well_path_intersection.well_path = well_path
well_path_intersection.update()

View File

@ -223,6 +223,9 @@ class PdmObjectBase:
def __makelist(self, list_string):
list_string = list_string.lstrip("[")
list_string = list_string.rstrip("]")
if not list_string:
# Return empty list if empty string. Otherwise, the split function will return ['']
return []
strings = list_string.split(", ")
values = []
for string in strings:

View File

@ -21,3 +21,72 @@ def test_10k(rips_instance, initialize_test):
assert len(wells) == 2
assert wells[0].name == "Well Path A"
assert wells[1].name == "Well Path B"
def test_10k_intersection(rips_instance, initialize_test):
case_root_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC"
case_path = case_root_path + "/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=case_path)
assert len(case.grids()) == 2
well_path_files = [
case_root_path + "/wellpath_a.dev",
]
view = case.create_view()
view.set_time_step(1)
well_path_names = rips_instance.project.import_well_paths(well_path_files)
wells = rips_instance.project.well_paths()
well_path = wells[0]
# Add a curve intersection based on the well path
intersection_coll = rips_instance.project.descendants(rips.IntersectionCollection)[
0
]
well_path_intersection = intersection_coll.add_new_object(rips.CurveIntersection)
well_path_intersection.type = "CS_WELL_PATH"
well_path_intersection.well_path = well_path
well_path_intersection.update()
# Three coords per triangle
geometry = well_path_intersection.geometry()
coord_count = len(geometry.x_coords)
assert coord_count == 13254
# One value per triangle
geometry_result_values = well_path_intersection.geometry_result()
result_count = len(geometry_result_values.values)
assert result_count == 4418
# Three coords per triangle, one result value per triangle
assert (result_count * 3) == coord_count
def test_empty_well_intersection(rips_instance, initialize_test):
case_root_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC"
case_path = case_root_path + "/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=case_path)
view = case.create_view()
view.set_time_step(1)
# Add a curve intersection based on the well path
intersection_coll = rips_instance.project.descendants(rips.IntersectionCollection)[
0
]
well_path_intersection = intersection_coll.add_new_object(rips.CurveIntersection)
well_path_intersection.type = "CS_WELL_PATH"
well_path_intersection.well_path = None
well_path_intersection.update()
# Test with empty geometry. This will also test that an empty list in CAF is converted to an empty list in Python
# See __makelist in pdmobject.py
geometry = well_path_intersection.geometry()
coord_count = len(geometry.x_coords)
assert coord_count == 0
# One value per triangle
geometry_result_values = well_path_intersection.geometry_result()
result_count = len(geometry_result_values.values)
assert result_count == 0

View File

@ -11,7 +11,7 @@ set(RESINSIGHT_VERSION_TEXT "-dev")
# Must be unique and increasing within one combination of major/minor/patch version
# The uniqueness of this text is independent of RESINSIGHT_VERSION_TEXT
# Format of text must be ".xx"
set(RESINSIGHT_DEV_VERSION ".02")
set(RESINSIGHT_DEV_VERSION ".03")
# https://github.com/CRAVA/crava/tree/master/libs/nrlib
set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f")