ResInsight/ApplicationLibCode/SocketInterface/RiaGeometryCommands.cpp
jonjenssen a7775214c8
Rewrite of cell filters. Added new polyline filter and user defined filter types. (#7191)
Make 3d view picker more generic to enable picking cell filter polygon

Give cell filters a new, generic interface for updating included/excluded cells from collection

Remove old range filter collection and replace with new filter collection that supports both range filters, polyline filters and user defined filters.

Update existing range filter code for the new collection and interface

Add user defined cell filter type

Add polyline cell filter type

Implement both Z and K index depth for polyline filters
Allow interactive editing of polyline filter node positions.
Support both geomech and eclipse views
Support view linking with both eclipse and geomech views and the new filter types

Support loading old project files with range filter collections into the new collection type

Adjust to new world order.
2021-01-11 18:47:09 +01:00

411 lines
16 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011- Statoil ASA
// Copyright (C) 2013- Ceetron Solutions AS
// Copyright (C) 2011-2012 Ceetron AS
//
// 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 "RiaSocketCommand.h"
#include "RiaPreferences.h"
#include "RiaSocketServer.h"
#include "RiaSocketTools.h"
#include "RigActiveCellInfo.h"
#include "RigCaseCellResultsData.h"
#include "RigEclipseCaseData.h"
#include "RigMainGrid.h"
#include "Rim3dOverlayInfoConfig.h"
#include "RimCellEdgeColors.h"
#include "RimEclipseCase.h"
#include "RimEclipseCellColors.h"
#include "RimEclipsePropertyFilterCollection.h"
#include "RimEclipseView.h"
#include "RimReservoirCellResultsStorage.h"
#include "RimSimWellInViewCollection.h"
#include <QTcpSocket>
//--------------------------------------------------------------------------------------------------
/// Convert internal ResInsight representation of cells with negative depth to positive depth.
//--------------------------------------------------------------------------------------------------
static inline void convertVec3dToPositiveDepth( cvf::Vec3d* vec )
{
double& z = vec->z();
z *= -1;
}
//--------------------------------------------------------------------------------------------------
/// Retrieve a cell corner where the depth is represented as negative converted to positive depth.
//--------------------------------------------------------------------------------------------------
static inline double getCellCornerWithPositiveDepth( const cvf::Vec3d* cornerVerts, size_t cornerIndexMapping, int coordIdx )
{
if ( coordIdx == 2 )
{
// Z-value aka depth
return -1 * cornerVerts[cornerIndexMapping][coordIdx];
}
else
{
return cornerVerts[cornerIndexMapping][coordIdx];
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetCellCenters : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetCellCenters" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
size_t argGridIndex = args[2].toUInt();
if ( !rimCase || !rimCase->eclipseCaseData() || ( argGridIndex >= rimCase->eclipseCaseData()->gridCount() ) )
{
// No data available
socketStream << (quint64)0 << (quint64)0 << (quint64)0 << (quint64)0 << (quint64)0;
return true;
}
RigGridBase* rigGrid = rimCase->eclipseCaseData()->grid( argGridIndex );
quint64 cellCount = (quint64)rigGrid->cellCount();
quint64 cellCountI = (quint64)rigGrid->cellCountI();
quint64 cellCountJ = (quint64)rigGrid->cellCountJ();
quint64 cellCountK = (quint64)rigGrid->cellCountK();
socketStream << cellCount;
socketStream << cellCountI;
socketStream << cellCountJ;
socketStream << cellCountK;
size_t doubleValueCount = cellCount * 3;
quint64 byteCount = doubleValueCount * sizeof( double );
socketStream << byteCount;
// This structure is supposed to be received by Octave using a NDArray. The ordering of this loop is
// defined by the ordering of the receiving NDArray
//
// See riGetCellCenters
//
// dim_vector dv;
// dv.resize(4);
// dv(0) = cellCountI;
// dv(1) = cellCountJ;
// dv(2) = cellCountK;
// dv(3) = 3;
size_t blockByteCount = cellCount * sizeof( double );
std::vector<double> doubleValues( blockByteCount );
for ( int coordIdx = 0; coordIdx < 3; coordIdx++ )
{
quint64 valueIndex = 0;
for ( size_t k = 0; k < cellCountK; k++ )
{
for ( size_t j = 0; j < cellCountJ; j++ )
{
for ( size_t i = 0; i < cellCountI; i++ )
{
size_t gridLocalCellIndex = rigGrid->cellIndexFromIJK( i, j, k );
cvf::Vec3d center = rigGrid->cell( gridLocalCellIndex ).center();
convertVec3dToPositiveDepth( &center );
doubleValues[valueIndex++] = center[coordIdx];
}
}
}
CVF_ASSERT( valueIndex == cellCount );
RiaSocketTools::writeBlockData( server, server->currentClient(), (const char*)doubleValues.data(), blockByteCount );
}
return true;
}
};
static bool RiaGetCellCenters_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetCellCenters>( RiaGetCellCenters::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetActiveCellCenters : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetActiveCellCenters" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
QString porosityModelName;
porosityModelName = args[2];
RiaDefines::PorosityModelType porosityModelEnum = RiaDefines::PorosityModelType::MATRIX_MODEL;
if ( porosityModelName.toUpper() == "FRACTURE" )
{
porosityModelEnum = RiaDefines::PorosityModelType::FRACTURE_MODEL;
}
if ( !rimCase || !rimCase->eclipseCaseData() )
{
// No data available
socketStream << (quint64)0 << (quint64)0;
return true;
}
RigActiveCellInfo* actCellInfo = rimCase->eclipseCaseData()->activeCellInfo( porosityModelEnum );
RigMainGrid* mainGrid = rimCase->eclipseCaseData()->mainGrid();
size_t activeCellCount = actCellInfo->reservoirActiveCellCount();
size_t doubleValueCount = activeCellCount * 3;
socketStream << (quint64)activeCellCount;
quint64 byteCount = doubleValueCount * sizeof( double );
socketStream << byteCount;
// This structure is supposed to be received by Octave using a NDArray. The ordering of this loop is
// defined by the ordering of the receiving NDArray
//
// See riGetActiveCellCenters
//
// dim_vector dv;
// dv.resize(2);
// dv(0) = coordCount;
// dv(1) = 3;
size_t blockByteCount = activeCellCount * sizeof( double );
std::vector<double> doubleValues( blockByteCount );
for ( int coordIdx = 0; coordIdx < 3; coordIdx++ )
{
quint64 valueIndex = 0;
for ( size_t reservoirCellIndex = 0; reservoirCellIndex < mainGrid->globalCellArray().size();
reservoirCellIndex++ )
{
if ( !actCellInfo->isActive( reservoirCellIndex ) ) continue;
cvf::Vec3d center = mainGrid->globalCellArray()[reservoirCellIndex].center();
convertVec3dToPositiveDepth( &center );
doubleValues[valueIndex++] = center[coordIdx];
}
CVF_ASSERT( valueIndex == activeCellCount );
RiaSocketTools::writeBlockData( server, server->currentClient(), (const char*)doubleValues.data(), blockByteCount );
}
return true;
}
};
static bool RiaGetActiveCellCenters_init = RiaSocketCommandFactory::instance()->registerCreator<RiaGetActiveCellCenters>(
RiaGetActiveCellCenters::commandName() );
// NB: Match this mapping with the mapping in RifReaderEclipseOutput.cpp
static const size_t cellCornerMappingEclipse[8] = { 0, 1, 3, 2, 4, 5, 7, 6 };
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetCellCorners : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetCellCorners" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
size_t argGridIndex = args[2].toUInt();
if ( !rimCase || !rimCase->eclipseCaseData() || ( argGridIndex >= rimCase->eclipseCaseData()->gridCount() ) )
{
// No data available
socketStream << (quint64)0 << (quint64)0 << (quint64)0 << (quint64)0 << (quint64)0;
return true;
}
RigGridBase* rigGrid = rimCase->eclipseCaseData()->grid( argGridIndex );
quint64 cellCount = (quint64)rigGrid->cellCount();
quint64 cellCountI = (quint64)rigGrid->cellCountI();
quint64 cellCountJ = (quint64)rigGrid->cellCountJ();
quint64 cellCountK = (quint64)rigGrid->cellCountK();
size_t doubleValueCount = cellCount * 3 * 8;
quint64 byteCount = doubleValueCount * sizeof( double );
socketStream << cellCount;
socketStream << cellCountI;
socketStream << cellCountJ;
socketStream << cellCountK;
socketStream << byteCount;
// This structure is supposed to be received by Octave using a NDArray. The ordering of this loop is
// defined by the ordering of the receiving NDArray
//
// See riGetCellCorners
//
// dim_vector dv;
// dv.resize(5);
// dv(0) = cellCountI;
// dv(1) = cellCountJ;
// dv(2) = cellCountK;
// dv(3) = 8;
// dv(4) = 3;
cvf::Vec3d cornerVerts[8];
size_t blockByteCount = cellCount * sizeof( double );
std::vector<double> doubleValues( blockByteCount );
for ( int coordIdx = 0; coordIdx < 3; coordIdx++ )
{
for ( size_t cornerIdx = 0; cornerIdx < 8; cornerIdx++ )
{
size_t cornerIndexMapping = cellCornerMappingEclipse[cornerIdx];
quint64 valueIndex = 0;
for ( size_t k = 0; k < cellCountK; k++ )
{
for ( size_t j = 0; j < cellCountJ; j++ )
{
for ( size_t i = 0; i < cellCountI; i++ )
{
size_t gridLocalCellIndex = rigGrid->cellIndexFromIJK( i, j, k );
rigGrid->cellCornerVertices( gridLocalCellIndex, cornerVerts );
doubleValues[valueIndex++] =
getCellCornerWithPositiveDepth( cornerVerts, cornerIndexMapping, coordIdx );
}
}
}
CVF_ASSERT( valueIndex == cellCount );
RiaSocketTools::writeBlockData( server,
server->currentClient(),
(const char*)doubleValues.data(),
blockByteCount );
}
}
return true;
}
};
static bool RiaGetCellCorners_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetCellCorners>( RiaGetCellCorners::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetActiveCellCorners : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetActiveCellCorners" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
QString porosityModelName;
porosityModelName = args[2];
RiaDefines::PorosityModelType porosityModelEnum = RiaDefines::PorosityModelType::MATRIX_MODEL;
if ( porosityModelName.toUpper() == "FRACTURE" )
{
porosityModelEnum = RiaDefines::PorosityModelType::FRACTURE_MODEL;
}
if ( !rimCase || !rimCase->eclipseCaseData() )
{
// No data available
socketStream << (quint64)0 << (quint64)0;
return true;
}
RigActiveCellInfo* actCellInfo = rimCase->eclipseCaseData()->activeCellInfo( porosityModelEnum );
RigMainGrid* mainGrid = rimCase->eclipseCaseData()->mainGrid();
size_t activeCellCount = actCellInfo->reservoirActiveCellCount();
size_t doubleValueCount = activeCellCount * 3 * 8;
socketStream << (quint64)activeCellCount;
quint64 byteCount = doubleValueCount * sizeof( double );
socketStream << byteCount;
// This structure is supposed to be received by Octave using a NDArray. The ordering of this loop is
// defined by the ordering of the receiving NDArray
//
// See riGetCellCorners
//
// dim_vector dv;
// dv.resize(3);
// dv(0) = coordCount;
// dv(1) = 8;
// dv(2) = 3;
cvf::Vec3d cornerVerts[8];
size_t blockByteCount = activeCellCount * sizeof( double );
std::vector<double> doubleValues( blockByteCount );
for ( int coordIdx = 0; coordIdx < 3; coordIdx++ )
{
for ( size_t cornerIdx = 0; cornerIdx < 8; cornerIdx++ )
{
size_t cornerIndexMapping = cellCornerMappingEclipse[cornerIdx];
quint64 valueIndex = 0;
for ( size_t reservoirCellIndex = 0; reservoirCellIndex < mainGrid->globalCellArray().size();
reservoirCellIndex++ )
{
if ( !actCellInfo->isActive( reservoirCellIndex ) ) continue;
mainGrid->cellCornerVertices( reservoirCellIndex, cornerVerts );
doubleValues[valueIndex++] =
getCellCornerWithPositiveDepth( cornerVerts, cornerIndexMapping, coordIdx );
}
CVF_ASSERT( valueIndex == activeCellCount );
RiaSocketTools::writeBlockData( server,
server->currentClient(),
(const char*)doubleValues.data(),
blockByteCount );
}
}
return true;
}
};
static bool RiaGetActiveCellCorners_init = RiaSocketCommandFactory::instance()->registerCreator<RiaGetActiveCellCorners>(
RiaGetActiveCellCorners::commandName() );