Improved UI for surface band and curves (#8026)

* Add surface intersection bands and curves
* #8024 Ensemble Surface : Fix mix of files for a ensemble layer surface
This commit is contained in:
Magne Sjaastad 2021-09-23 09:59:29 +02:00 committed by GitHub
parent 3d0fa2e7c7
commit 515168600f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 1367 additions and 76 deletions

View File

@ -557,6 +557,22 @@ RiaColorTables::WellPathComponentColors RiaColorTables::wellPathComponentColors(
{ RiaDefines::WellPathComponentType::UNDEFINED_COMPONENT, cvf::Color3::MAGENTA } };
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const caf::ColorTable& RiaColorTables::structuralUncertaintyColors()
{
static std::vector<cvf::Color3ub> colors{
cvf::Color3ub( 255, 183, 198 ), // Large band
cvf::Color3ub( 255, 113, 142 ), // Narrow band
cvf::Color3ub( 255, 18, 67 ), // Mean curve
};
static caf::ColorTable colorTable = caf::ColorTable( colors );
return colorTable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -67,6 +67,9 @@ public:
static WellPathComponentColors wellPathComponentColors();
// Colors used in WebViz
static const caf::ColorTable& structuralUncertaintyColors();
// Default 3d View colors
static cvf::Color3f defaultGridLineColor();
static cvf::Color3f defaultFaultLineColor();

View File

@ -77,6 +77,8 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleSurfaceUi.h
${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleWellLogFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleWellLogUi.h
${CMAKE_CURRENT_LIST_DIR}/RicCreateSurfaceIntersectionBandFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicCreateSurfaceIntersectionCurveFeature.h
)
set(SOURCE_GROUP_SOURCE_FILES
@ -157,6 +159,8 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleSurfaceUi.cpp
${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleWellLogFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleWellLogUi.cpp
${CMAKE_CURRENT_LIST_DIR}/RicCreateSurfaceIntersectionBandFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicCreateSurfaceIntersectionCurveFeature.cpp
)
if(Qt5Charts_FOUND)

View File

@ -0,0 +1,142 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 "RicCreateSurfaceIntersectionBandFeature.h"
#include "RiaColorTables.h"
#include "RimAnnotationLineAppearance.h"
#include "RimEnsembleSurface.h"
#include "RimExtrudedCurveIntersection.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSurface.h"
#include "RimSurfaceCollection.h"
#include "RimSurfaceIntersectionBand.h"
#include "Riu3DMainWindowTools.h"
#include "cafSelectionManager.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicCreateSurfaceIntersectionBandFeature, "RicCreateSurfaceIntersectionBandFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurfaceCollection* RicCreateSurfaceIntersectionBandFeature::surfaceCollection()
{
RimProject* proj = RimProject::current();
return proj->activeOilField()->surfaceCollection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicCreateSurfaceIntersectionBandFeature::isCommandEnabled()
{
auto* surfColl = RicCreateSurfaceIntersectionBandFeature::surfaceCollection();
auto surfaces = surfColl->ensembleSurfaces();
return !surfaces.empty();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateSurfaceIntersectionBandFeature::onActionTriggered( bool isChecked )
{
auto* intersection = caf::SelectionManager::instance()->selectedItemAncestorOfType<RimExtrudedCurveIntersection>();
if ( intersection )
{
RimEnsembleSurface* firstEnsembleSurface = nullptr;
{
auto surfColl = RicCreateSurfaceIntersectionBandFeature::surfaceCollection();
auto surfaces = surfColl->ensembleSurfaces();
if ( !surfaces.empty() ) firstEnsembleSurface = surfaces.front();
}
RimSurfaceIntersectionBand* objectToSelect = nullptr;
if ( firstEnsembleSurface )
{
const double defaultOpacity = 0.6;
auto colors = RiaColorTables::structuralUncertaintyColors();
// Create min/max band
{
auto surf1 =
firstEnsembleSurface->findStatisticsSurface( RigSurfaceStatisticsCalculator::StatisticsType::MIN );
auto surf2 =
firstEnsembleSurface->findStatisticsSurface( RigSurfaceStatisticsCalculator::StatisticsType::MAX );
if ( surf2 && surf1 )
{
auto band = intersection->addIntersectionBand();
band->setSurfaces( surf1, surf2 );
auto color = colors.cycledColor3f( 0 );
band->setBandColor( color );
band->setBandOpacity( defaultOpacity );
band->setPolygonOffsetUnit( 0.08 );
band->lineAppearance()->setColor( color );
objectToSelect = band;
}
}
// Create p10/p90 band
{
auto surf1 =
firstEnsembleSurface->findStatisticsSurface( RigSurfaceStatisticsCalculator::StatisticsType::P10 );
auto surf2 =
firstEnsembleSurface->findStatisticsSurface( RigSurfaceStatisticsCalculator::StatisticsType::P90 );
if ( surf2 && surf1 )
{
auto band = intersection->addIntersectionBand();
band->setSurfaces( surf1, surf2 );
auto color = colors.cycledColor3f( 1 );
band->setBandColor( color );
band->setBandOpacity( defaultOpacity );
band->setPolygonOffsetUnit( 0.1 );
band->lineAppearance()->setColor( color );
}
}
}
intersection->rebuildGeometryAndScheduleCreateDisplayModel();
intersection->updateAllRequiredEditors();
Riu3DMainWindowTools::selectAsCurrentItem( objectToSelect );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateSurfaceIntersectionBandFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setText( "Create Surface Intersection Band" );
actionToSetup->setIcon( QIcon( ":/ReservoirSurface16x16.png" ) );
}

View File

@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 RimSurfaceCollection;
//==================================================================================================
///
//==================================================================================================
class RicCreateSurfaceIntersectionBandFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
public:
static RimSurfaceCollection* surfaceCollection();
protected:
bool isCommandEnabled() override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
};

View File

@ -0,0 +1,62 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 "RicCreateSurfaceIntersectionCurveFeature.h"
#include "RimExtrudedCurveIntersection.h"
#include "RimSurfaceIntersectionCurve.h"
#include "Riu3DMainWindowTools.h"
#include "cafSelectionManager.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicCreateSurfaceIntersectionCurveFeature, "RicCreateSurfaceIntersectionCurveFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicCreateSurfaceIntersectionCurveFeature::isCommandEnabled()
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateSurfaceIntersectionCurveFeature::onActionTriggered( bool isChecked )
{
auto* intersection = caf::SelectionManager::instance()->selectedItemAncestorOfType<RimExtrudedCurveIntersection>();
if ( intersection )
{
auto curve = intersection->addIntersectionCurve();
intersection->updateAllRequiredEditors();
Riu3DMainWindowTools::selectAsCurrentItem( curve );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateSurfaceIntersectionCurveFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setText( "Create Surface Intersection Curve" );
actionToSetup->setIcon( QIcon( ":/ReservoirSurface16x16.png" ) );
}

View File

@ -0,0 +1,34 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 RicCreateSurfaceIntersectionCurveFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
bool isCommandEnabled() override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
};

View File

@ -93,21 +93,22 @@ void RicImportEnsembleSurfaceFeature::importSingleEnsembleSurfaceFromFiles( cons
{
// Create a list of file names for each layer
std::map<QString, QStringList> fileNamesForEachLayer;
for ( const auto& name : fileNames )
for ( const auto& fileName : fileNames )
{
QFileInfo fi( name );
QFileInfo fi( fileName );
auto layerName = fi.baseName();
fileNamesForEachLayer[layerName].push_back( name );
fileNamesForEachLayer[layerName].push_back( fileName );
}
RimEnsembleSurface* ensembleToSelect = nullptr;
for ( const auto& fileNamesForLayer : fileNamesForEachLayer )
{
auto filenames = fileNamesForLayer.second;
QString ensembleName = RiaEnsembleNameTools::findSuitableEnsembleName( fileNames );
// NB! This must be a const reference to avoid threading issues
const QStringList& layerFileNames = fileNamesForLayer.second;
QString layerName = fileNamesForLayer.first;
QString ensembleName = RiaEnsembleNameTools::findSuitableEnsembleName( layerFileNames );
QString layerName = fileNamesForLayer.first;
if ( !layerName.isEmpty() )
{
ensembleName += QString( " : %1" ).arg( layerName );
@ -116,19 +117,19 @@ void RicImportEnsembleSurfaceFeature::importSingleEnsembleSurfaceFromFiles( cons
if ( ensembleName.isEmpty() ) ensembleName = "Ensemble Surface";
std::map<QString, QStringList> keyFileComponentsForAllFiles =
RiaFilePathTools::keyPathComponentsForEachFilePath( fileNames );
RiaFilePathTools::keyPathComponentsForEachFilePath( layerFileNames );
std::vector<RimFileSurface*> surfaces;
for ( int i = 0; i < fileNames.size(); i++ )
for ( int i = 0; i < layerFileNames.size(); i++ )
{
surfaces.push_back( new RimFileSurface );
}
auto fileCount = static_cast<int>( fileNames.size() );
auto fileCount = static_cast<int>( layerFileNames.size() );
#pragma omp parallel for
for ( int i = 0; i < fileCount; i++ )
{
auto fileName = fileNames[i];
auto fileName = layerFileNames[i];
auto fileSurface = surfaces[i];
fileSurface->setSurfaceFilePath( fileName );

View File

@ -30,6 +30,8 @@
#include "RimExtrudedCurveIntersection.h"
#include "RimGridView.h"
#include "RimSurface.h"
#include "RimSurfaceIntersectionBand.h"
#include "RimSurfaceIntersectionCurve.h"
#include "RivExtrudedCurveIntersectionPartMgr.h"
#include "RivHexGridIntersectionTools.h"
@ -167,7 +169,19 @@ void RivExtrudedCurveIntersectionGeometryGenerator::calculateSurfaceIntersection
if ( !m_polylines.empty() )
{
auto firstPolyLine = m_polylines.front();
for ( auto rimSurface : m_intersection->annotatedSurfaces() )
std::vector<RimSurface*> surfaces;
for ( auto curve : m_intersection->surfaceIntersectionCurves() )
{
if ( curve->surface() ) surfaces.push_back( curve->surface() );
}
for ( auto band : m_intersection->surfaceIntersectionBands() )
{
if ( band->surface1() ) surfaces.push_back( band->surface1() );
if ( band->surface2() ) surfaces.push_back( band->surface2() );
}
for ( auto rimSurface : surfaces )
{
if ( !rimSurface ) return;

View File

@ -31,6 +31,7 @@
#include "RigResultAccessorFactory.h"
#include "Rim2dIntersectionView.h"
#include "RimAnnotationLineAppearance.h"
#include "RimEclipseCase.h"
#include "RimEclipseCellColors.h"
#include "RimEclipseView.h"
@ -43,6 +44,8 @@
#include "RimSimWellInView.h"
#include "RimSimWellInViewCollection.h"
#include "RimSurface.h"
#include "RimSurfaceIntersectionBand.h"
#include "RimSurfaceIntersectionCurve.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
@ -601,47 +604,62 @@ void RivExtrudedCurveIntersectionPartMgr::createAnnotationSurfaceParts( bool use
m_annotationParts.clear();
auto surfPolys = m_intersectionGenerator->transformedSurfaceIntersectionPolylines();
for ( auto [surface, polylines] : surfPolys )
for ( auto curve : m_rimIntersection->surfaceIntersectionCurves() )
{
if ( !curve->isChecked() ) continue;
auto surface = curve->surface();
if ( !surface ) continue;
auto polylineGeo = RivPolylineGenerator::createLineAlongPolylineDrawable( polylines );
if ( polylineGeo.notNull() )
{
if ( useBufferObjects )
{
polylineGeo->setRenderMode( cvf::DrawableGeo::BUFFER_OBJECT );
}
if ( surfPolys.count( surface ) == 0 ) continue;
auto polylines = surfPolys[surface];
cvf::ref<cvf::Part> part = new cvf::Part;
part->setName( "Intersection " + surface->userDescription().toStdString() );
part->setDrawable( polylineGeo.p() );
auto part = createCurvePart( polylines,
useBufferObjects,
surface->userDescription(),
curve->lineAppearance()->color(),
curve->lineAppearance()->thickness() );
part->updateBoundingBox();
part->setPriority( RivPartPriority::PartType::Highlight );
cvf::ref<cvf::Effect> eff;
caf::MeshEffectGenerator lineEffGen( surface->color() );
lineEffGen.setLineWidth( 5.0f );
eff = lineEffGen.generateUnCachedEffect();
part->setEffect( eff.p() );
m_annotationParts.push_back( part.p() );
}
if ( part.notNull() ) m_annotationParts.push_back( part.p() );
}
if ( surfPolys.size() > 1 )
for ( auto band : m_rimIntersection->surfaceIntersectionBands() )
{
// Create a quad strip between the two first polylines
if ( !band->isChecked() ) continue;
auto firstSurfaceItem = surfPolys.begin();
auto secondSurfaceItem = firstSurfaceItem++;
auto surface1 = band->surface1();
auto surface2 = band->surface2();
auto polylineA = firstSurfaceItem->second;
auto polylineB = secondSurfaceItem->second;
if ( !surface1 || !surface2 ) continue;
if ( surfPolys.count( surface1 ) == 0 ) continue;
if ( surfPolys.count( surface2 ) == 0 ) continue;
auto polylineA = surfPolys[surface1];
auto polylineB = surfPolys[surface2];
// Create curve parts
{
auto part = createCurvePart( polylineA,
useBufferObjects,
surface1->userDescription(),
band->lineAppearance()->color(),
band->lineAppearance()->thickness() );
if ( part.notNull() ) m_annotationParts.push_back( part.p() );
}
{
auto part = createCurvePart( polylineB,
useBufferObjects,
surface2->userDescription(),
band->lineAppearance()->color(),
band->lineAppearance()->thickness() );
if ( part.notNull() ) m_annotationParts.push_back( part.p() );
}
// Create a quad strip between the two polylines
size_t pointCount = std::min( polylineA.size(), polylineB.size() );
if ( pointCount > 1 )
{
@ -674,10 +692,27 @@ void RivExtrudedCurveIntersectionPartMgr::createAnnotationSurfaceParts( bool use
part->setEnableMask( intersectionCellFaceBit );
part->setPriority( RivPartPriority::PartType::Transparent );
auto color = cvf::Color4f( cvf::Color3f::OLIVE, 0.5f );
auto color = cvf::Color4f( band->bandColor(), band->bandOpacity() );
caf::SurfaceEffectGenerator geometryEffgen( color, caf::PO_NEG_LARGE );
cvf::ref<cvf::Effect> geometryOnlyEffect = geometryEffgen.generateCachedEffect();
cvf::ref<cvf::Effect> geometryOnlyEffect = geometryEffgen.generateUnCachedEffect();
{
cvf::ref<cvf::RenderStatePolygonOffset> polyOffset = new cvf::RenderStatePolygonOffset;
polyOffset->enableFillMode( true );
// The factor value is defined by enums in
// EffectGenerator::createAndConfigurePolygonOffsetRenderState() Use a factor that is more negative
// than the existing enums
const double offsetFactor = -5;
polyOffset->setFactor( offsetFactor );
polyOffset->setUnits( band->polygonOffsetUnit() );
geometryOnlyEffect->setRenderState( polyOffset.p() );
}
part->setEffect( geometryOnlyEffect.p() );
m_annotationParts.push_back( part.p() );
@ -686,6 +721,50 @@ void RivExtrudedCurveIntersectionPartMgr::createAnnotationSurfaceParts( bool use
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Part> RivExtrudedCurveIntersectionPartMgr::createCurvePart( const std::vector<cvf::Vec3d>& polylines,
bool useBufferObjects,
const QString& description,
const cvf::Color3f& color,
float lineWidth )
{
auto polylineGeo = RivPolylineGenerator::createLineAlongPolylineDrawable( polylines );
if ( polylineGeo.notNull() )
{
if ( useBufferObjects )
{
polylineGeo->setRenderMode( cvf::DrawableGeo::BUFFER_OBJECT );
}
cvf::ref<cvf::Part> part = new cvf::Part;
part->setName( "Intersection " + description.toStdString() );
part->setDrawable( polylineGeo.p() );
part->updateBoundingBox();
part->setPriority( RivPartPriority::PartType::FaultMeshLines );
caf::MeshEffectGenerator lineEffGen( color );
lineEffGen.setLineWidth( lineWidth );
cvf::ref<cvf::Effect> eff = lineEffGen.generateUnCachedEffect();
cvf::ref<cvf::RenderStatePolygonOffset> polyOffset = new cvf::RenderStatePolygonOffset;
polyOffset->enableFillMode( true );
polyOffset->setFactor( -5 );
const double maxOffsetFactor = -1000;
polyOffset->setUnits( maxOffsetFactor );
eff->setRenderState( polyOffset.p() );
part->setEffect( eff.p() );
return part;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -88,6 +88,12 @@ private:
void createExtrusionDirParts( bool useBufferObjects );
void createAnnotationSurfaceParts( bool useBufferObjects );
cvf::ref<cvf::Part> createCurvePart( const std::vector<cvf::Vec3d>& polylines,
bool useBufferObjects,
const QString& description,
const cvf::Color3f& color,
float lineWidth );
private:
caf::PdmPointer<RimExtrudedCurveIntersection> m_rimIntersection;

View File

@ -61,6 +61,7 @@ CAF_PDM_SOURCE_INIT( RimAnnotationLineAppearance, "RimAnnotationLineAppearance"
///
//--------------------------------------------------------------------------------------------------
RimAnnotationLineAppearance::RimAnnotationLineAppearance()
: objectChanged( this )
{
CAF_PDM_InitObject( "AnnotationLineAppearance", ":/WellCollection.png", "", "" );
@ -139,8 +140,10 @@ void RimAnnotationLineAppearance::fieldChangedByUi( const caf::PdmFieldHandle* c
const QVariant& newValue )
{
RimAnnotationCollection* annColl = nullptr;
this->firstAncestorOrThisOfTypeAsserted( annColl );
annColl->scheduleRedrawOfRelevantViews();
this->firstAncestorOrThisOfType( annColl );
if ( annColl ) annColl->scheduleRedrawOfRelevantViews();
objectChanged.send();
}
//--------------------------------------------------------------------------------------------------

View File

@ -33,6 +33,9 @@ class RimAnnotationLineAppearance : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
caf::Signal<> objectChanged;
public:
enum LineStyleEnum
{

View File

@ -119,6 +119,9 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveSetInterface.h
${CMAKE_CURRENT_LIST_DIR}/cafTreeNode.h
${CMAKE_CURRENT_LIST_DIR}/RimMultipleLocations.h
${CMAKE_CURRENT_LIST_DIR}/RimSurfaceIntersectionBand.h
${CMAKE_CURRENT_LIST_DIR}/RimSurfaceIntersectionCurve.h
${CMAKE_CURRENT_LIST_DIR}/RimSurfaceIntersectionCollection.h
)
set(SOURCE_GROUP_SOURCE_FILES
@ -237,6 +240,9 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimTimeAxisAnnotation.cpp
${CMAKE_CURRENT_LIST_DIR}/cafTreeNode.cpp
${CMAKE_CURRENT_LIST_DIR}/RimMultipleLocations.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSurfaceIntersectionBand.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSurfaceIntersectionCurve.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSurfaceIntersectionCollection.cpp
)
if(Qt5Charts_FOUND)

View File

@ -810,6 +810,9 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
}
else if ( dynamic_cast<RimExtrudedCurveIntersection*>( firstUiItem ) )
{
menuBuilder << "RicCreateSurfaceIntersectionBandFeature";
menuBuilder << "RicCreateSurfaceIntersectionCurveFeature";
menuBuilder.addSeparator();
menuBuilder << "RicPasteIntersectionsFeature";
menuBuilder.addSeparator();
menuBuilder << "RicAppendIntersectionFeature";

View File

@ -37,6 +37,9 @@
#include "RimSimWellInViewCollection.h"
#include "RimSurface.h"
#include "RimSurfaceCollection.h"
#include "RimSurfaceIntersectionBand.h"
#include "RimSurfaceIntersectionCollection.h"
#include "RimSurfaceIntersectionCurve.h"
#include "RimTools.h"
#include "RimWellPath.h"
@ -49,6 +52,7 @@
#include "cafPdmUiListEditor.h"
#include "cafPdmUiPushButtonEditor.h"
#include "cafPdmUiTreeOrdering.h"
#include "cafPdmUiTreeSelectionEditor.h"
#include "cvfBoundingBox.h"
#include "cvfGeometryTools.h"
@ -236,10 +240,9 @@ RimExtrudedCurveIntersection::RimExtrudedCurveIntersection()
caf::PdmUiPushButtonEditor::configureEditorForField( &m_inputTwoAzimuthPointsFromViewerEnabled );
m_inputTwoAzimuthPointsFromViewerEnabled = false;
CAF_PDM_InitFieldNoDefault( &m_annotationSurfaces, "annotationSurfaces", "", "", "", "" );
m_annotationSurfaces.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
uiCapability()->setUiTreeChildrenHidden( true );
CAF_PDM_InitFieldNoDefault( &m_surfaceIntersections, "SurfaceIntersections", "Surface Intersections", "", "", "" );
m_surfaceIntersections = new RimSurfaceIntersectionCollection;
m_surfaceIntersections->objectChanged.connect( this, &RimExtrudedCurveIntersection::onSurfaceIntersectionsChanged );
setDeletable( true );
}
@ -354,12 +357,6 @@ void RimExtrudedCurveIntersection::fieldChangedByUi( const caf::PdmFieldHandle*
{
rebuildGeometryAndScheduleCreateDisplayModel();
}
if ( changedField == &m_annotationSurfaces )
{
rebuildGeometryAndScheduleCreateDisplayModel();
}
}
//--------------------------------------------------------------------------------------------------
@ -427,9 +424,6 @@ void RimExtrudedCurveIntersection::defineUiOrdering( QString uiConfigName, caf::
m_extentLength.uiCapability()->setUiReadOnly( false );
}
caf::PdmUiGroup* surfaceGroup = uiOrdering.addNewGroup( "Surfaces" );
surfaceGroup->add( &m_annotationSurfaces );
this->defineSeparateDataSourceUi( uiConfigName, uiOrdering );
uiOrdering.skipRemainingFields( true );
@ -485,12 +479,6 @@ QList<caf::PdmOptionItemInfo>
options.push_back( caf::PdmOptionItemInfo( QString::number( bIdx + 1 ), QVariant::fromValue( bIdx ) ) );
}
}
else if ( fieldNeedingOptions == &m_annotationSurfaces )
{
RimSurfaceCollection* surfColl = RimProject::current()->activeOilField()->surfaceCollection();
appendOptionItemsForSources( 0, surfColl, options );
}
else
{
options = RimIntersection::calculateValueOptions( fieldNeedingOptions, useOptionsOnly );
@ -499,6 +487,23 @@ QList<caf::PdmOptionItemInfo>
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimExtrudedCurveIntersection::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
{
for ( auto c : m_surfaceIntersections->surfaceIntersectionCurves() )
{
uiTreeOrdering.add( c );
}
for ( auto c : m_surfaceIntersections->surfaceIntersectionBands() )
{
uiTreeOrdering.add( c );
}
uiTreeOrdering.skipRemainingChildren( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -1031,9 +1036,33 @@ bool RimExtrudedCurveIntersection::hasDefiningPoints() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSurface*> RimExtrudedCurveIntersection::annotatedSurfaces() const
std::vector<RimSurfaceIntersectionCurve*> RimExtrudedCurveIntersection::surfaceIntersectionCurves() const
{
return m_annotationSurfaces.ptrReferencedObjects();
return m_surfaceIntersections->surfaceIntersectionCurves();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSurfaceIntersectionBand*> RimExtrudedCurveIntersection::surfaceIntersectionBands() const
{
return m_surfaceIntersections->surfaceIntersectionBands();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurfaceIntersectionCurve* RimExtrudedCurveIntersection::addIntersectionCurve()
{
return m_surfaceIntersections->addIntersectionCurve();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurfaceIntersectionBand* RimExtrudedCurveIntersection::addIntersectionBand()
{
return m_surfaceIntersections->addIntersectionBand();
}
//--------------------------------------------------------------------------------------------------
@ -1097,3 +1126,12 @@ void RimExtrudedCurveIntersection::appendOptionItemsForSources( int
appendOptionItemsForSources( currentLevel, subColl, options );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimExtrudedCurveIntersection::onSurfaceIntersectionsChanged( const caf::SignalEmitter* emitter )
{
updateAllRequiredEditors();
rebuildGeometryAndScheduleCreateDisplayModel();
}

View File

@ -21,6 +21,7 @@
#include "RimIntersection.h"
#include "cafPdmChildField.h"
#include "cafPdmPtrArrayField.h"
class RimWellPath;
@ -31,6 +32,9 @@ class RimSimWellInViewCollection;
class Rim2dIntersectionView;
class RimSurface;
class RimSurfaceCollection;
class RimSurfaceIntersectionCollection;
class RimSurfaceIntersectionCurve;
class RimSurfaceIntersectionBand;
namespace caf
{
@ -106,7 +110,10 @@ public:
void recomputeSimulationWellBranchData();
bool hasDefiningPoints() const;
std::vector<RimSurface*> annotatedSurfaces() const;
std::vector<RimSurfaceIntersectionCurve*> surfaceIntersectionCurves() const;
std::vector<RimSurfaceIntersectionBand*> surfaceIntersectionBands() const;
RimSurfaceIntersectionCurve* addIntersectionCurve();
RimSurfaceIntersectionBand* addIntersectionBand();
int branchIndex() const;
void rebuildGeometryAndScheduleCreateDisplayModel();
@ -121,6 +128,8 @@ protected:
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
private:
static void setPushButtonText( bool buttonEnable, caf::PdmUiPushButtonEditorAttribute* attribute );
static void setBaseColor( bool enable, caf::PdmUiListEditorAttribute* attribute );
@ -136,6 +145,8 @@ private:
RimSurfaceCollection* currentCollection,
QList<caf::PdmOptionItemInfo>& options ) const;
void onSurfaceIntersectionsChanged( const caf::SignalEmitter* emitter );
private:
caf::PdmField<QString> m_name;
@ -160,8 +171,7 @@ private:
caf::PdmField<std::vector<cvf::Vec3d>> m_customExtrusionPoints;
caf::PdmField<std::vector<cvf::Vec3d>> m_twoAzimuthPoints;
// Surface intersection annotations
caf::PdmPtrArrayField<RimSurface*> m_annotationSurfaces;
caf::PdmChildField<RimSurfaceIntersectionCollection*> m_surfaceIntersections;
cvf::ref<RivExtrudedCurveIntersectionPartMgr> m_crossSectionPartMgr;

View File

@ -0,0 +1,290 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 "RimSurfaceIntersectionBand.h"
#include "RimAnnotationLineAppearance.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSurface.h"
#include "RimSurfaceCollection.h"
#include "RimSurfaceIntersectionCurve.h"
#include "cafPdmUiDoubleSliderEditor.h"
#include "cafPdmUiTreeSelectionEditor.h"
CAF_PDM_SOURCE_INIT( RimSurfaceIntersectionBand, "RimSurfaceIntersectionBand" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimSurfaceIntersectionBand::userDescriptionField()
{
return &m_nameProxy;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurfaceIntersectionBand::RimSurfaceIntersectionBand()
: objectChanged( this )
{
CAF_PDM_InitObject( "SurfaceIntersectionBand", ":/ReservoirSurface16x16.png", "", "" );
CAF_PDM_InitFieldNoDefault( &m_lineAppearance, "LineAppearance", "Line Appearance", "", "", "" );
m_lineAppearance = new RimAnnotationLineAppearance;
m_lineAppearance->objectChanged.connect( this, &RimSurfaceIntersectionBand::onObjectChanged );
uiCapability()->setUiTreeChildrenHidden( true );
CAF_PDM_InitField( &m_bandColor, "BandColor", cvf::Color3f( cvf::Color3f::BLACK ), "Band Color", "", "", "" );
CAF_PDM_InitField( &m_bandOpacity, "BandOpacity", 0.8, "Band Opacity", "", "", "" );
m_bandOpacity.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_bandPolygonOffsetUnit,
"BandPolygonOffsetUnit",
-5.0,
"Depth Offset",
"",
"Larger Value Closer to Camera",
"" );
m_bandPolygonOffsetUnit.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() );
CAF_PDM_InitFieldNoDefault( &m_surfaces, "Surfaces", "Band Surfaces", "", "", "" );
m_surfaces.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
CAF_PDM_InitFieldNoDefault( &m_nameProxy, "NameProxy", "Name", "", "", "" );
m_nameProxy.registerGetMethod( this, &RimSurfaceIntersectionBand::objectName );
m_nameProxy.uiCapability()->setUiHidden( true );
setDeletable( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionBand::setSurfaces( RimSurface* surface1, RimSurface* surface2 )
{
m_surfaces.clear();
m_surfaces.push_back( surface1 );
m_surfaces.push_back( surface2 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionBand::setBandColor( const cvf::Color3f& color )
{
m_bandColor = color;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionBand::setBandOpacity( double opacity )
{
m_bandOpacity = opacity;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionBand::setPolygonOffsetUnit( double offset )
{
m_bandPolygonOffsetUnit = offset;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimAnnotationLineAppearance* RimSurfaceIntersectionBand::lineAppearance() const
{
return m_lineAppearance();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimSurfaceIntersectionBand::bandColor() const
{
return m_bandColor();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RimSurfaceIntersectionBand::bandOpacity() const
{
return m_bandOpacity();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimSurfaceIntersectionBand::polygonOffsetUnit() const
{
// The value in user interface is [0..1]
// An offsetUnitValue in the range -5..-1000 seems to give good visual results
const double minimumValue = 5.0;
auto value = minimumValue + m_bandPolygonOffsetUnit * 1000.0;
return -value;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurface* RimSurfaceIntersectionBand::surface1() const
{
auto surfaces = m_surfaces.ptrReferencedObjects();
if ( !surfaces.empty() ) return surfaces[0];
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurface* RimSurfaceIntersectionBand::surface2() const
{
auto surfaces = m_surfaces.ptrReferencedObjects();
if ( surfaces.size() > 1 ) return surfaces[1];
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionBand::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
if ( changedField == &m_surfaces )
{
auto surfaces = m_surfaces.ptrReferencedObjects();
if ( surfaces.size() > 2 )
{
// Keep first and last surface to make it possible to select a new surface by using a single click
auto firstAndLast = { surfaces.front(), surfaces.back() };
surfaces = firstAndLast;
}
m_surfaces.setValue( surfaces );
}
onObjectChanged( this );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo>
RimSurfaceIntersectionBand::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly )
{
QList<caf::PdmOptionItemInfo> options;
if ( fieldNeedingOptions == &m_surfaces )
{
RimSurfaceCollection* surfColl = RimProject::current()->activeOilField()->surfaceCollection();
RimSurfaceIntersectionCurve::appendOptionItemsForSources( 0, surfColl, false, options );
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionBand::defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute )
{
if ( field == &m_bandPolygonOffsetUnit )
{
auto* myAttr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>( attribute );
if ( myAttr )
{
myAttr->m_minimum = 0;
myAttr->m_maximum = 1.0;
}
}
else if ( field == &m_bandOpacity )
{
auto* myAttr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>( attribute );
if ( myAttr )
{
myAttr->m_minimum = 0.0;
myAttr->m_maximum = 1.0;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionBand::onObjectChanged( const caf::SignalEmitter* emitter )
{
objectChanged.send();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSurfaceIntersectionBand::objectName() const
{
auto surfaces = m_surfaces.ptrReferencedObjects();
if ( surfaces.size() == 2 )
{
QString text;
auto firstSurface = surfaces[0];
RimSurfaceCollection* surfColl = nullptr;
firstSurface->firstAncestorOfType( surfColl );
if ( surfColl )
{
text += surfColl->collectionName();
}
if ( surfaces[0] )
text += "( " + surfaces[0]->userDescription() + " - " + surfaces[1]->userDescription() + " )";
return text;
}
return "Surface Band";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionBand::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
{
caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Band Appearance" );
group->add( &m_bandColor );
group->add( &m_bandOpacity );
}
{
caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Line Appearance" );
m_lineAppearance->uiOrdering( uiConfigName, *group );
}
}

View File

@ -0,0 +1,83 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 "RimCheckableObject.h"
#include "cafPdmChildField.h"
#include "cafPdmFieldCvfColor.h" // Include to make Pdm work for cvf::Color
#include "cafPdmProxyValueField.h"
#include "cafPdmPtrArrayField.h"
class RimSurface;
class RimAnnotationLineAppearance;
//==================================================================================================
//
//
//
//==================================================================================================
class RimSurfaceIntersectionBand : public RimCheckableObject
{
CAF_PDM_HEADER_INIT;
public:
caf::Signal<> objectChanged;
public:
RimSurfaceIntersectionBand();
void setSurfaces( RimSurface* surface1, RimSurface* surface2 );
void setBandColor( const cvf::Color3f& color );
void setBandOpacity( double opacity );
void setPolygonOffsetUnit( double offset );
RimAnnotationLineAppearance* lineAppearance() const;
cvf::Color3f bandColor() const;
float bandOpacity() const;
double polygonOffsetUnit() const;
RimSurface* surface1() const;
RimSurface* surface2() const;
private:
caf::PdmFieldHandle* userDescriptionField() override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;
void defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute ) override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void onObjectChanged( const caf::SignalEmitter* emitter );
QString objectName() const;
private:
caf::PdmChildField<RimAnnotationLineAppearance*> m_lineAppearance;
caf::PdmField<cvf::Color3f> m_bandColor;
caf::PdmField<double> m_bandOpacity;
caf::PdmField<double> m_bandPolygonOffsetUnit;
caf::PdmPtrArrayField<RimSurface*> m_surfaces;
caf::PdmProxyValueField<QString> m_nameProxy;
};

View File

@ -0,0 +1,109 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 "RimSurfaceIntersectionCollection.h"
#include "RimSurfaceIntersectionBand.h"
#include "RimSurfaceIntersectionCurve.h"
CAF_PDM_SOURCE_INIT( RimSurfaceIntersectionCollection, "RimSurfaceIntersectionCollection" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurfaceIntersectionCollection::RimSurfaceIntersectionCollection()
: objectChanged( this )
{
CAF_PDM_InitObject( "SurfaceIntersectionCollection_msj", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_intersectionBands, "IntersectionBands", "Intersection Bands", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_intersectionCurves, "IntersectionCurves", "Intersection Curves", "", "", "" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurfaceIntersectionCurve* RimSurfaceIntersectionCollection::addIntersectionCurve()
{
auto curve = new RimSurfaceIntersectionCurve;
curve->objectChanged.connect( this, &RimSurfaceIntersectionCollection::onObjectChanged );
m_intersectionCurves.push_back( curve );
return curve;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurfaceIntersectionBand* RimSurfaceIntersectionCollection::addIntersectionBand()
{
auto band = new RimSurfaceIntersectionBand;
band->objectChanged.connect( this, &RimSurfaceIntersectionCollection::onObjectChanged );
m_intersectionBands.push_back( band );
return band;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSurfaceIntersectionCurve*> RimSurfaceIntersectionCollection::surfaceIntersectionCurves() const
{
return m_intersectionCurves.childObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSurfaceIntersectionBand*> RimSurfaceIntersectionCollection::surfaceIntersectionBands() const
{
return m_intersectionBands.childObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionCollection::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray,
std::vector<caf::PdmObjectHandle*>& referringObjects )
{
onObjectChanged( this );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionCollection::onObjectChanged( const caf::SignalEmitter* emitter )
{
objectChanged.send();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionCollection::initAfterRead()
{
for ( const auto& band : m_intersectionBands )
{
band->objectChanged.connect( this, &RimSurfaceIntersectionCollection::onObjectChanged );
}
for ( const auto& curve : m_intersectionCurves )
{
curve->objectChanged.connect( this, &RimSurfaceIntersectionCollection::onObjectChanged );
}
}

View File

@ -0,0 +1,59 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 "RimCheckableObject.h"
#include "cafPdmChildArrayField.h"
class RimSurfaceIntersectionBand;
class RimSurfaceIntersectionCurve;
//==================================================================================================
//
//
//
//==================================================================================================
class RimSurfaceIntersectionCollection : public RimCheckableObject
{
CAF_PDM_HEADER_INIT;
public:
caf::Signal<> objectChanged;
public:
RimSurfaceIntersectionCollection();
RimSurfaceIntersectionCurve* addIntersectionCurve();
RimSurfaceIntersectionBand* addIntersectionBand();
std::vector<RimSurfaceIntersectionCurve*> surfaceIntersectionCurves() const;
std::vector<RimSurfaceIntersectionBand*> surfaceIntersectionBands() const;
private:
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray,
std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
void onObjectChanged( const caf::SignalEmitter* emitter );
void initAfterRead() override;
private:
caf::PdmChildArrayField<RimSurfaceIntersectionBand*> m_intersectionBands;
caf::PdmChildArrayField<RimSurfaceIntersectionCurve*> m_intersectionCurves;
};

View File

@ -0,0 +1,176 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 "RimSurfaceIntersectionCurve.h"
#include "RimAnnotationLineAppearance.h"
#include "RimEnsembleSurface.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSurface.h"
#include "RimSurfaceCollection.h"
#include "cafPdmUiTreeSelectionEditor.h"
CAF_PDM_SOURCE_INIT( RimSurfaceIntersectionCurve, "RimSurfaceIntersectionCurve" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurfaceIntersectionCurve::RimSurfaceIntersectionCurve()
: objectChanged( this )
{
CAF_PDM_InitObject( "SurfaceIntersectionCurve", ":/SummaryCurve16x16.png", "", "" );
CAF_PDM_InitFieldNoDefault( &m_lineAppearance, "LineAppearance", "Line Appearance", "", "", "" );
m_lineAppearance = new RimAnnotationLineAppearance;
m_lineAppearance->objectChanged.connect( this, &RimSurfaceIntersectionCurve::onObjectChanged );
uiCapability()->setUiTreeChildrenHidden( true );
CAF_PDM_InitFieldNoDefault( &m_surface1, "Surface1", "Surface 1", "", "", "" );
m_surface1.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
CAF_PDM_InitFieldNoDefault( &m_nameProxy, "NameProxy", "Name", "", "", "" );
m_nameProxy.registerGetMethod( this, &RimSurfaceIntersectionCurve::objectName );
m_nameProxy.uiCapability()->setUiHidden( true );
setDeletable( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurface* RimSurfaceIntersectionCurve::surface() const
{
return m_surface1();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimAnnotationLineAppearance* RimSurfaceIntersectionCurve::lineAppearance() const
{
return m_lineAppearance();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimSurfaceIntersectionCurve::userDescriptionField()
{
return &m_nameProxy;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
onObjectChanged( this );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo>
RimSurfaceIntersectionCurve::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly )
{
QList<caf::PdmOptionItemInfo> options;
if ( fieldNeedingOptions == &m_surface1 )
{
RimSurfaceCollection* surfColl = RimProject::current()->activeOilField()->surfaceCollection();
appendOptionItemsForSources( 0, surfColl, true, options );
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Line Appearance" );
m_lineAppearance->uiOrdering( uiConfigName, *group );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionCurve::onObjectChanged( const caf::SignalEmitter* emitter )
{
objectChanged.send();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSurfaceIntersectionCurve::objectName() const
{
if ( m_surface1() )
{
QString text;
RimSurfaceCollection* surfColl = nullptr;
m_surface1()->firstAncestorOfType( surfColl );
if ( surfColl )
{
text += surfColl->collectionName();
}
if ( m_surface1() ) text += "( " + m_surface1()->userDescription() + " )";
return text;
}
return "Surface Curve";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceIntersectionCurve::appendOptionItemsForSources( int currentLevel,
RimSurfaceCollection* currentCollection,
bool showEnsembleSurfaces,
QList<caf::PdmOptionItemInfo>& options )
{
if ( !currentCollection ) return;
caf::IconProvider surfaceIcon( ":/ReservoirSurface16x16.png" );
options.push_back( caf::PdmOptionItemInfo::createHeader( currentCollection->collectionName(), true ) );
for ( auto surf : currentCollection->surfaces() )
{
auto itemInfo = caf::PdmOptionItemInfo( surf->userDescription(), surf, false, surfaceIcon );
itemInfo.setLevel( currentLevel + 1 );
options.push_back( itemInfo );
}
auto ensembleSurface = dynamic_cast<RimEnsembleSurface*>( currentCollection );
if ( !ensembleSurface || ( showEnsembleSurfaces && ensembleSurface ) )
{
for ( auto subColl : currentCollection->subCollections() )
{
appendOptionItemsForSources( currentLevel, subColl, showEnsembleSurfaces, options );
}
}
}

View File

@ -0,0 +1,69 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 "RimCheckableObject.h"
#include "cafPdmChildField.h"
#include "cafPdmProxyValueField.h"
#include "cafPdmPtrField.h"
class RimSurface;
class RimAnnotationLineAppearance;
class RimSurfaceCollection;
//==================================================================================================
//
//
//
//==================================================================================================
class RimSurfaceIntersectionCurve : public RimCheckableObject
{
CAF_PDM_HEADER_INIT;
public:
caf::Signal<> objectChanged;
public:
RimSurfaceIntersectionCurve();
RimSurface* surface() const;
RimAnnotationLineAppearance* lineAppearance() const;
static void appendOptionItemsForSources( int currentLevel,
RimSurfaceCollection* currentCollection,
bool showEnsembleSurfaces,
QList<caf::PdmOptionItemInfo>& options );
private:
caf::PdmFieldHandle* userDescriptionField() override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void onObjectChanged( const caf::SignalEmitter* emitter );
QString objectName() const;
private:
caf::PdmPtrField<RimSurface*> m_surface1;
caf::PdmChildField<RimAnnotationLineAppearance*> m_lineAppearance;
caf::PdmProxyValueField<QString> m_nameProxy;
};

View File

@ -60,6 +60,14 @@ void RimEnsembleStatisticsSurface::setStatisticsType( RigSurfaceStatisticsCalcul
setUserDescription( fullName() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigSurfaceStatisticsCalculator::StatisticsType RimEnsembleStatisticsSurface::statisticsType() const
{
return m_statisticsType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -37,6 +37,7 @@ public:
RimSurface* createCopy() override;
void setStatisticsType( RigSurfaceStatisticsCalculator::StatisticsType statisticsType );
RigSurfaceStatisticsCalculator::StatisticsType statisticsType() const;
QString fullName() const override;

View File

@ -124,9 +124,11 @@ void RimEnsembleSurface::loadDataAndUpdate()
{
cvf::ref<RigSurface> firstSurface = sourceSurfaceForStatistics[0]->surfaceData();
// The search tree must be created before the multi threading loop is initiated to avoid crash
firstSurface->ensureIntersectionSearchTreeIsBuilt();
auto surfaceCount = static_cast<int>( sourceSurfaceForStatistics.size() );
std::vector<cvf::ref<RigSurface>> sourceSurfaces( surfaceCount );
#pragma omp parallel for
for ( int i = 0; i < surfaceCount; i++ )
{
@ -282,6 +284,21 @@ void RimEnsembleSurface::loadData()
loadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurface* RimEnsembleSurface::findStatisticsSurface( RigSurfaceStatisticsCalculator::StatisticsType statisticsType )
{
for ( auto s : surfaces() )
{
auto ensembleSurface = dynamic_cast<RimEnsembleStatisticsSurface*>( s );
if ( ensembleSurface && ensembleSurface->statisticsType() == statisticsType ) return s;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -20,6 +20,8 @@
#include "RimSurfaceCollection.h"
#include "RigSurfaceStatisticsCalculator.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmPtrField.h"
@ -50,6 +52,8 @@ public:
void loadData() override;
RimSurface* findStatisticsSurface( RigSurfaceStatisticsCalculator::StatisticsType statisticsType );
protected:
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;

View File

@ -59,10 +59,6 @@ RimFileSurface::~RimFileSurface()
void RimFileSurface::setSurfaceFilePath( const QString& filePath )
{
m_surfaceDefinitionFilePath = filePath;
if ( userDescription().isEmpty() )
{
setUserDescription( QFileInfo( filePath ).fileName() );
}
clearCachedNativeData();
}

View File

@ -36,7 +36,8 @@
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
#include "QFile"
#include <QFile>
#include <QFileInfo>
CAF_PDM_SOURCE_INIT( RimSurfaceCollection, "SurfaceCollection" );
@ -117,6 +118,18 @@ void RimSurfaceCollection::addEnsembleSurface( RimEnsembleSurface* ensembleSurfa
addSubCollection( ensembleSurface );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimEnsembleSurface*> RimSurfaceCollection::ensembleSurfaces() const
{
std::vector<RimEnsembleSurface*> ensSurfaces;
this->descendantsIncludingThisOfType( ensSurfaces );
return ensSurfaces;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -135,6 +148,8 @@ RimSurface* RimSurfaceCollection::importSurfacesFromFiles( const QStringList& fi
auto newColor = RiaColorTables::categoryPaletteColors().cycledColor3f( existingSurfCount + newSurfCount );
newSurface->setSurfaceFilePath( newFileName );
newSurface->setUserDescription( QFileInfo( newFileName ).fileName() );
newSurface->setColor( newColor );
if ( !newSurface->onLoadData() )

View File

@ -37,7 +37,8 @@ public:
void addSurface( RimSurface* surface );
void setAsTopmostFolder();
void addEnsembleSurface( RimEnsembleSurface* ensembleSurface );
void addEnsembleSurface( RimEnsembleSurface* ensembleSurface );
std::vector<RimEnsembleSurface*> ensembleSurfaces() const;
RimSurface* importSurfacesFromFiles( const QStringList& fileNames, bool showLegend = true );
RimSurface* addGridCaseSurface( RimCase* sourceCase, int oneBasedSliceIndex = 1 );