2020-05-03 04:29:33 -05:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Copyright (C) 2020- 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 "RimGridCaseSurface.h"
|
|
|
|
|
|
|
|
#include "RigSurface.h"
|
|
|
|
|
|
|
|
#include "RigMainGrid.h"
|
|
|
|
#include "RimCase.h"
|
|
|
|
#include "RimEclipseCase.h"
|
|
|
|
#include "RimSurfaceCollection.h"
|
|
|
|
#include "RimTools.h"
|
|
|
|
|
|
|
|
#include "cafPdmUiSliderEditor.h"
|
|
|
|
|
|
|
|
#include "RigReservoirGridTools.h"
|
|
|
|
#include "cvfVector3.h"
|
|
|
|
|
|
|
|
CAF_PDM_SOURCE_INIT( RimGridCaseSurface, "GridCaseSurface" );
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
RimGridCaseSurface::RimGridCaseSurface()
|
|
|
|
{
|
|
|
|
CAF_PDM_InitObject( "Surface", ":/ReservoirSurface16x16.png", "", "" );
|
|
|
|
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_case, "SourceCase", "Source Case", "", "", "" );
|
|
|
|
|
|
|
|
CAF_PDM_InitField( &m_sliceDirection,
|
|
|
|
"SnapShotDirection",
|
|
|
|
caf::AppEnum<RiaDefines::GridCaseAxis>( RiaDefines::GridCaseAxis::UNDEFINED_AXIS ),
|
|
|
|
"Range Filter Slice",
|
|
|
|
"",
|
|
|
|
"",
|
|
|
|
"" );
|
|
|
|
|
2020-04-30 13:51:25 -05:00
|
|
|
CAF_PDM_InitField( &m_oneBasedSliceIndex, "SliceIndex", 1, "Slice Index", "", "", "" );
|
|
|
|
m_oneBasedSliceIndex.uiCapability()->setUiEditorTypeName( caf::PdmUiSliderEditor::uiEditorTypeName() );
|
2020-05-03 04:29:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
RimGridCaseSurface::~RimGridCaseSurface()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void RimGridCaseSurface::setCase( RimCase* sourceCase )
|
|
|
|
{
|
|
|
|
m_case = sourceCase;
|
|
|
|
}
|
|
|
|
|
2020-04-30 13:51:25 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void RimGridCaseSurface::setSliceTypeAndOneBasedIndex( RiaDefines::GridCaseAxis sliceType, int oneBasedSliceIndex )
|
|
|
|
{
|
|
|
|
m_sliceDirection = sliceType;
|
|
|
|
m_oneBasedSliceIndex = oneBasedSliceIndex;
|
|
|
|
}
|
|
|
|
|
2020-05-03 04:29:33 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2020-05-03 04:35:06 -05:00
|
|
|
bool RimGridCaseSurface::onLoadData()
|
2020-05-03 04:29:33 -05:00
|
|
|
{
|
|
|
|
return updateSurfaceDataFromGridCase();
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
QList<caf::PdmOptionItemInfo> RimGridCaseSurface::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
|
|
|
|
bool* useOptionsOnly )
|
|
|
|
{
|
|
|
|
QList<caf::PdmOptionItemInfo> options;
|
|
|
|
|
|
|
|
if ( fieldNeedingOptions == &m_case )
|
|
|
|
{
|
|
|
|
RimTools::caseOptionItems( &options );
|
|
|
|
}
|
|
|
|
|
|
|
|
return options;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void RimGridCaseSurface::defineEditorAttribute( const caf::PdmFieldHandle* field,
|
|
|
|
QString uiConfigName,
|
|
|
|
caf::PdmUiEditorAttribute* attribute )
|
|
|
|
{
|
|
|
|
caf::PdmUiSliderEditorAttribute* myAttr = dynamic_cast<caf::PdmUiSliderEditorAttribute*>( attribute );
|
|
|
|
if ( myAttr && m_case )
|
|
|
|
{
|
|
|
|
const cvf::StructGridInterface* grid = RigReservoirGridTools::mainGrid( m_case );
|
|
|
|
if ( !grid ) return;
|
|
|
|
|
|
|
|
myAttr->m_minimum = 1;
|
|
|
|
|
|
|
|
if ( m_sliceDirection() == RiaDefines::GridCaseAxis::AXIS_I )
|
|
|
|
{
|
|
|
|
myAttr->m_maximum = static_cast<int>( grid->cellCountI() );
|
|
|
|
}
|
|
|
|
else if ( m_sliceDirection() == RiaDefines::GridCaseAxis::AXIS_J )
|
|
|
|
{
|
|
|
|
myAttr->m_maximum = static_cast<int>( grid->cellCountJ() );
|
|
|
|
}
|
|
|
|
else if ( m_sliceDirection() == RiaDefines::GridCaseAxis::AXIS_K )
|
|
|
|
{
|
|
|
|
myAttr->m_maximum = static_cast<int>( grid->cellCountK() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void RimGridCaseSurface::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
|
|
|
const QVariant& oldValue,
|
|
|
|
const QVariant& newValue )
|
|
|
|
{
|
2020-05-03 04:35:06 -05:00
|
|
|
RimSurface::fieldChangedByUi( changedField, oldValue, newValue );
|
|
|
|
|
2020-04-30 13:51:25 -05:00
|
|
|
if ( changedField == &m_case || changedField == &m_sliceDirection || changedField == &m_oneBasedSliceIndex )
|
2020-05-03 04:29:33 -05:00
|
|
|
{
|
2020-05-03 04:35:06 -05:00
|
|
|
clearNativeGridData();
|
2020-05-03 04:29:33 -05:00
|
|
|
updateSurfaceDataFromGridCase();
|
2020-04-30 13:51:25 -05:00
|
|
|
updateUserDescription();
|
2020-05-03 04:29:33 -05:00
|
|
|
|
|
|
|
RimSurfaceCollection* surfColl;
|
|
|
|
this->firstAncestorOrThisOfTypeAsserted( surfColl );
|
|
|
|
surfColl->updateViews( {this} );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2020-05-03 04:35:06 -05:00
|
|
|
///
|
2020-05-03 04:29:33 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2020-05-03 04:35:06 -05:00
|
|
|
void RimGridCaseSurface::extractDataFromGrid()
|
2020-05-03 04:29:33 -05:00
|
|
|
{
|
2020-05-02 02:41:08 -05:00
|
|
|
clearNativeGridData();
|
2020-05-03 04:29:33 -05:00
|
|
|
|
2020-05-02 02:41:08 -05:00
|
|
|
if ( m_sliceDirection() == RiaDefines::GridCaseAxis::UNDEFINED_AXIS ) return;
|
2020-05-03 04:29:33 -05:00
|
|
|
|
2020-05-02 02:41:08 -05:00
|
|
|
if ( m_case )
|
2020-05-03 04:29:33 -05:00
|
|
|
{
|
|
|
|
RimEclipseCase* eclCase = dynamic_cast<RimEclipseCase*>( m_case() );
|
|
|
|
if ( eclCase && eclCase->mainGrid() )
|
|
|
|
{
|
2020-05-03 04:35:06 -05:00
|
|
|
const RigMainGrid* grid = eclCase->mainGrid();
|
2020-05-03 04:29:33 -05:00
|
|
|
|
2020-05-02 02:41:08 -05:00
|
|
|
size_t minI = 0;
|
|
|
|
size_t minJ = 0;
|
|
|
|
size_t minK = 0;
|
|
|
|
size_t maxI = grid->cellCountI();
|
|
|
|
size_t maxJ = grid->cellCountJ();
|
|
|
|
size_t maxK = grid->cellCountK();
|
|
|
|
|
2020-04-30 13:51:25 -05:00
|
|
|
size_t zeroBasedLayerIndex = static_cast<size_t>( m_oneBasedSliceIndex - 1 );
|
2020-05-02 02:41:08 -05:00
|
|
|
|
|
|
|
cvf::StructGridInterface::FaceType faceType = cvf::StructGridInterface::NO_FACE;
|
2020-05-03 04:35:06 -05:00
|
|
|
{
|
2020-05-02 02:41:08 -05:00
|
|
|
if ( m_sliceDirection() == RiaDefines::GridCaseAxis::AXIS_K )
|
2020-05-03 04:29:33 -05:00
|
|
|
{
|
2020-05-02 02:41:08 -05:00
|
|
|
faceType = cvf::StructGridInterface::NEG_K;
|
2020-05-03 04:29:33 -05:00
|
|
|
|
2020-05-02 02:41:08 -05:00
|
|
|
minK = zeroBasedLayerIndex;
|
|
|
|
maxK = zeroBasedLayerIndex + 1;
|
|
|
|
}
|
|
|
|
else if ( m_sliceDirection() == RiaDefines::GridCaseAxis::AXIS_J )
|
|
|
|
{
|
|
|
|
faceType = cvf::StructGridInterface::NEG_J;
|
|
|
|
minJ = zeroBasedLayerIndex;
|
|
|
|
maxJ = zeroBasedLayerIndex + 1;
|
|
|
|
}
|
|
|
|
else if ( m_sliceDirection() == RiaDefines::GridCaseAxis::AXIS_I )
|
|
|
|
{
|
|
|
|
faceType = cvf::StructGridInterface::NEG_I;
|
|
|
|
minI = zeroBasedLayerIndex;
|
|
|
|
maxI = zeroBasedLayerIndex + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<unsigned> tringleIndices;
|
|
|
|
std::vector<cvf::Vec3d> vertices;
|
|
|
|
|
|
|
|
for ( size_t i = minI; i < maxI; i++ )
|
|
|
|
{
|
|
|
|
for ( size_t j = minJ; j < maxJ; j++ )
|
|
|
|
{
|
|
|
|
for ( size_t k = minK; k < maxK; k++ )
|
|
|
|
{
|
|
|
|
size_t cellIndex = grid->cellIndexFromIJK( i, j, k );
|
2020-05-03 04:29:33 -05:00
|
|
|
|
2020-05-02 02:41:08 -05:00
|
|
|
if ( grid->cell( cellIndex ).isInvalid() ) continue;
|
2020-05-03 04:29:33 -05:00
|
|
|
|
2020-05-02 02:41:08 -05:00
|
|
|
cvf::Vec3d cornerVerts[8];
|
|
|
|
grid->cellCornerVertices( cellIndex, cornerVerts );
|
2020-05-03 04:29:33 -05:00
|
|
|
|
2020-05-02 02:41:08 -05:00
|
|
|
cvf::ubyte faceConn[4];
|
|
|
|
grid->cellFaceVertexIndices( faceType, faceConn );
|
2020-05-03 04:29:33 -05:00
|
|
|
|
2020-05-02 02:41:08 -05:00
|
|
|
cvf::uint triangleIndex = static_cast<cvf::uint>( vertices.size() );
|
2020-05-03 04:29:33 -05:00
|
|
|
|
2020-05-02 02:41:08 -05:00
|
|
|
for ( int n = 0; n < 4; n++ )
|
|
|
|
{
|
|
|
|
vertices.push_back( cornerVerts[faceConn[n]] );
|
|
|
|
}
|
2020-05-03 04:29:33 -05:00
|
|
|
|
2020-05-02 02:41:08 -05:00
|
|
|
tringleIndices.push_back( triangleIndex + 0 );
|
|
|
|
tringleIndices.push_back( triangleIndex + 1 );
|
|
|
|
tringleIndices.push_back( triangleIndex + 2 );
|
|
|
|
|
|
|
|
tringleIndices.push_back( triangleIndex + 0 );
|
|
|
|
tringleIndices.push_back( triangleIndex + 2 );
|
|
|
|
tringleIndices.push_back( triangleIndex + 3 );
|
|
|
|
}
|
2020-05-03 04:29:33 -05:00
|
|
|
}
|
|
|
|
}
|
2020-05-02 02:41:08 -05:00
|
|
|
|
|
|
|
m_vertices = vertices;
|
|
|
|
m_tringleIndices = tringleIndices;
|
2020-05-03 04:29:33 -05:00
|
|
|
}
|
|
|
|
}
|
2020-05-03 04:35:06 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void RimGridCaseSurface::clearNativeGridData()
|
|
|
|
{
|
|
|
|
m_vertices.clear();
|
|
|
|
m_tringleIndices.clear();
|
|
|
|
}
|
|
|
|
|
2020-04-30 13:51:25 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void RimGridCaseSurface::updateUserDescription()
|
|
|
|
{
|
|
|
|
QString name;
|
|
|
|
|
|
|
|
auto dirValue = m_sliceDirection().value();
|
|
|
|
switch ( dirValue )
|
|
|
|
{
|
|
|
|
case RiaDefines::GridCaseAxis::AXIS_I:
|
2020-05-02 02:41:08 -05:00
|
|
|
name = "Surface I : ";
|
2020-04-30 13:51:25 -05:00
|
|
|
break;
|
|
|
|
case RiaDefines::GridCaseAxis::AXIS_J:
|
|
|
|
name = "Surface J : ";
|
|
|
|
break;
|
|
|
|
case RiaDefines::GridCaseAxis::AXIS_K:
|
|
|
|
name = "Surface K : ";
|
|
|
|
break;
|
|
|
|
case RiaDefines::GridCaseAxis::UNDEFINED_AXIS:
|
|
|
|
default:
|
|
|
|
name = "Surface ";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
name += QString::number( m_oneBasedSliceIndex );
|
|
|
|
|
2020-05-02 02:41:08 -05:00
|
|
|
const double epsilon = 1.0e-3;
|
|
|
|
if ( std::fabs( depthOffset() ) > epsilon )
|
|
|
|
{
|
|
|
|
name += ", Offset : " + QString::number( depthOffset() );
|
|
|
|
}
|
|
|
|
|
2020-04-30 13:51:25 -05:00
|
|
|
setUserDescription( name );
|
|
|
|
}
|
|
|
|
|
2020-05-03 04:35:06 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
/// Returns false for fatal failure
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
bool RimGridCaseSurface::updateSurfaceDataFromGridCase()
|
|
|
|
{
|
|
|
|
if ( m_vertices.empty() || m_tringleIndices.empty() )
|
2020-05-03 04:29:33 -05:00
|
|
|
{
|
2020-05-03 04:35:06 -05:00
|
|
|
extractDataFromGrid();
|
|
|
|
}
|
2020-04-28 07:02:07 -05:00
|
|
|
|
2020-05-03 04:35:06 -05:00
|
|
|
RigSurface* surfaceData = nullptr;
|
|
|
|
|
|
|
|
std::vector<unsigned> tringleIndices{m_tringleIndices};
|
|
|
|
std::vector<cvf::Vec3d> vertices{m_vertices};
|
|
|
|
|
|
|
|
if ( !tringleIndices.empty() )
|
|
|
|
{
|
2020-04-28 07:02:07 -05:00
|
|
|
{
|
2020-05-02 02:41:08 -05:00
|
|
|
// Modify the z-value slightly to avoid geometrical numerical issues when the surface intersects
|
|
|
|
// exactly at the cell face
|
2020-04-28 07:02:07 -05:00
|
|
|
|
|
|
|
double delta = 1.0e-5;
|
|
|
|
|
|
|
|
cvf::Vec3d offset = cvf::Vec3d::ZERO;
|
|
|
|
|
|
|
|
if ( m_sliceDirection == RiaDefines::GridCaseAxis::AXIS_I )
|
|
|
|
{
|
|
|
|
offset.x() += delta;
|
|
|
|
}
|
|
|
|
else if ( m_sliceDirection == RiaDefines::GridCaseAxis::AXIS_J )
|
|
|
|
{
|
|
|
|
offset.y() += delta;
|
|
|
|
}
|
|
|
|
if ( m_sliceDirection == RiaDefines::GridCaseAxis::AXIS_K )
|
|
|
|
{
|
|
|
|
offset.z() += delta;
|
|
|
|
}
|
|
|
|
|
2020-05-03 04:35:06 -05:00
|
|
|
// Include the potential depth offset in the base class
|
|
|
|
offset.z() += depthOffset();
|
|
|
|
|
|
|
|
RimSurface::applyDepthOffset( offset, &vertices );
|
2020-04-28 07:02:07 -05:00
|
|
|
}
|
|
|
|
|
2020-05-03 04:35:06 -05:00
|
|
|
surfaceData = new RigSurface;
|
2020-05-03 04:29:33 -05:00
|
|
|
surfaceData->setTriangleData( tringleIndices, vertices );
|
|
|
|
}
|
|
|
|
|
|
|
|
setSurfaceData( surfaceData );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|