From 32326bfa9b8b2a8f6498ef78663da22d86eebe69 Mon Sep 17 00:00:00 2001 From: jonjenssen Date: Wed, 3 May 2023 02:20:05 +0200 Subject: [PATCH] Add fault reactivation modeling --- .../Application/RiaPreferencesGeoMech.cpp | 37 +- .../Application/RiaPreferencesGeoMech.h | 12 +- ApplicationLibCode/CMakeLists.txt | 2 + .../RicEclipseHideFaultFeature.cpp | 8 - .../RicEclipseShowOnlyFaultFeature.cpp | 7 - .../GeoMechCommands/CMakeLists_files.cmake | 2 + .../RicNewFaultReactModelingFeature.cpp | 123 +++++ .../RicNewFaultReactModelingFeature.h | 34 ++ .../RicRunWellIntegrityAnalysisFeature.cpp | 2 +- .../ModelVisualization/CMakeLists_files.cmake | 6 - .../Faults/CMakeLists_files.cmake | 23 + .../RivFaultGeometryGenerator.cpp | 0 .../{ => Faults}/RivFaultGeometryGenerator.h | 0 .../{ => Faults}/RivFaultPartMgr.cpp | 0 .../{ => Faults}/RivFaultPartMgr.h | 0 .../RivFaultReactivationModelPartMgr.cpp | 147 ++++++ .../Faults/RivFaultReactivationModelPartMgr.h | 67 +++ .../RivReservoirFaultsPartMgr.cpp | 0 .../{ => Faults}/RivReservoirFaultsPartMgr.h | 0 .../RivPolylineGenerator.cpp | 42 ++ .../ModelVisualization/RivPolylineGenerator.h | 2 + .../Seismic/CMakeLists_files.cmake | 2 + .../Seismic/RivSeismicSectionPartMgr.cpp | 90 +--- .../Seismic/RivSeismicSectionPartMgr.h | 13 +- .../Seismic/RivTexturePartMgr.cpp | 137 ++++++ .../Seismic/RivTexturePartMgr.h | 63 +++ .../Faults/CMakeLists_files.cmake | 4 + .../Faults/RimFaultReactivationModel.cpp | 450 ++++++++++++++++++ .../Faults/RimFaultReactivationModel.h | 130 +++++ .../RimFaultReactivationModelCollection.cpp | 186 ++++++++ .../RimFaultReactivationModelCollection.h | 81 ++++ .../ProjectDataModel/RimEclipseView.cpp | 32 +- .../ProjectDataModel/RimEclipseView.h | 30 +- .../ProjectDataModel/RimTools.cpp | 16 + .../ProjectDataModel/RimTools.h | 3 + .../ReservoirDataModel/CMakeLists_files.cmake | 6 + .../ReservoirDataModel/RigBasicPlane.cpp | 167 +++++++ .../ReservoirDataModel/RigBasicPlane.h | 75 +++ .../RigFaultReactivationModel.cpp | 308 ++++++++++++ .../RigFaultReactivationModel.h | 124 +++++ .../ReservoirDataModel/RigGriddedPart3d.cpp | 275 +++++++++++ .../ReservoirDataModel/RigGriddedPart3d.h | 65 +++ .../UserInterface/RiuViewerCommands.cpp | 12 +- 43 files changed, 2626 insertions(+), 157 deletions(-) create mode 100644 ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.cpp create mode 100644 ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.h create mode 100644 ApplicationLibCode/ModelVisualization/Faults/CMakeLists_files.cmake rename ApplicationLibCode/ModelVisualization/{ => Faults}/RivFaultGeometryGenerator.cpp (100%) rename ApplicationLibCode/ModelVisualization/{ => Faults}/RivFaultGeometryGenerator.h (100%) rename ApplicationLibCode/ModelVisualization/{ => Faults}/RivFaultPartMgr.cpp (100%) rename ApplicationLibCode/ModelVisualization/{ => Faults}/RivFaultPartMgr.h (100%) create mode 100644 ApplicationLibCode/ModelVisualization/Faults/RivFaultReactivationModelPartMgr.cpp create mode 100644 ApplicationLibCode/ModelVisualization/Faults/RivFaultReactivationModelPartMgr.h rename ApplicationLibCode/ModelVisualization/{ => Faults}/RivReservoirFaultsPartMgr.cpp (100%) rename ApplicationLibCode/ModelVisualization/{ => Faults}/RivReservoirFaultsPartMgr.h (100%) create mode 100644 ApplicationLibCode/ModelVisualization/Seismic/RivTexturePartMgr.cpp create mode 100644 ApplicationLibCode/ModelVisualization/Seismic/RivTexturePartMgr.h create mode 100644 ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h create mode 100644 ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.h create mode 100644 ApplicationLibCode/ReservoirDataModel/RigBasicPlane.cpp create mode 100644 ApplicationLibCode/ReservoirDataModel/RigBasicPlane.h create mode 100644 ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.cpp create mode 100644 ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.h create mode 100644 ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.cpp create mode 100644 ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.h diff --git a/ApplicationLibCode/Application/RiaPreferencesGeoMech.cpp b/ApplicationLibCode/Application/RiaPreferencesGeoMech.cpp index 6dada5822d..b046f7ec32 100644 --- a/ApplicationLibCode/Application/RiaPreferencesGeoMech.cpp +++ b/ApplicationLibCode/Application/RiaPreferencesGeoMech.cpp @@ -42,6 +42,10 @@ RiaPreferencesGeoMech::RiaPreferencesGeoMech() m_geomechWIACommand.uiCapability()->setUiEditorTypeName( caf::PdmUiFilePathEditor::uiEditorTypeName() ); m_geomechWIACommand.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); + CAF_PDM_InitFieldNoDefault( &m_geomechFRMCommand, "geomechFRMCommand", "Command to run" ); + m_geomechFRMCommand.uiCapability()->setUiEditorTypeName( caf::PdmUiFilePathEditor::uiEditorTypeName() ); + m_geomechFRMCommand.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); + CAF_PDM_InitField( &m_keepTemporaryFiles, "keepTemporaryFile", false, "Keep temporary parameter files (for debugging)" ); caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_keepTemporaryFiles ); @@ -65,17 +69,13 @@ void RiaPreferencesGeoMech::appendItems( caf::PdmUiOrdering& uiOrdering ) const caf::PdmUiGroup* wellIAGroup = uiOrdering.addNewGroup( "Well Integrity Analysis" ); wellIAGroup->add( &m_geomechWIACommand ); wellIAGroup->add( &m_geomechWIADefaultXML ); - wellIAGroup->add( &m_waitForInputFileEdit ); + + caf::PdmUiGroup* faultRMGroup = uiOrdering.addNewGroup( "Fault Re-activation Modeling" ); + faultRMGroup->add( &m_geomechFRMCommand ); caf::PdmUiGroup* commonGroup = uiOrdering.addNewGroup( "Common Settings" ); commonGroup->add( &m_keepTemporaryFiles ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaPreferencesGeoMech::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) -{ + commonGroup->add( &m_waitForInputFileEdit ); } //-------------------------------------------------------------------------------------------------- @@ -94,6 +94,14 @@ QString RiaPreferencesGeoMech::geomechWIADefaultXML() const return m_geomechWIADefaultXML; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaPreferencesGeoMech::geomechFRMCommand() const +{ + return m_geomechFRMCommand; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -105,7 +113,7 @@ bool RiaPreferencesGeoMech::keepTemporaryFiles() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RiaPreferencesGeoMech::waitBeforeRunWIA() const +bool RiaPreferencesGeoMech::waitBeforeRun() const { return m_waitForInputFileEdit; } @@ -122,6 +130,17 @@ bool RiaPreferencesGeoMech::validateWIASettings() const return filesExists( files ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaPreferencesGeoMech::validateFRMSettings() const +{ + QStringList files; + files << geomechFRMCommand(); + + return filesExists( files ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/Application/RiaPreferencesGeoMech.h b/ApplicationLibCode/Application/RiaPreferencesGeoMech.h index 2308220570..e040e0a64a 100644 --- a/ApplicationLibCode/Application/RiaPreferencesGeoMech.h +++ b/ApplicationLibCode/Application/RiaPreferencesGeoMech.h @@ -37,23 +37,25 @@ public: void appendItems( caf::PdmUiOrdering& uiOrdering ) const; bool validateWIASettings() const; + bool validateFRMSettings() const; // geomech settings QString geomechWIADefaultXML() const; QString geomechWIACommand() const; - bool waitBeforeRunWIA() const; + QString geomechFRMCommand() const; + + bool waitBeforeRun() const; bool keepTemporaryFiles() const; -protected: - void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; - private: bool filesExists( QStringList& filelist ) const; caf::PdmField m_geomechWIADefaultXML; caf::PdmField m_geomechWIACommand; - caf::PdmField m_waitForInputFileEdit; + caf::PdmField m_geomechFRMCommand; + + caf::PdmField m_waitForInputFileEdit; caf::PdmField m_keepTemporaryFiles; }; diff --git a/ApplicationLibCode/CMakeLists.txt b/ApplicationLibCode/CMakeLists.txt index aeb44e7c1c..d7b7f31b23 100644 --- a/ApplicationLibCode/CMakeLists.txt +++ b/ApplicationLibCode/CMakeLists.txt @@ -148,6 +148,7 @@ list( ProjectDataModelCommands/CommandRouter/CMakeLists_files.cmake GeoMech/GeoMechVisualization/CMakeLists_files.cmake ModelVisualization/CMakeLists_files.cmake + ModelVisualization/Faults/CMakeLists_files.cmake ModelVisualization/GridBox/CMakeLists_files.cmake ModelVisualization/Intersections/CMakeLists_files.cmake ModelVisualization/Seismic/CMakeLists_files.cmake @@ -395,6 +396,7 @@ target_include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/FileInterface ${CMAKE_CURRENT_SOURCE_DIR}/GeoMech ${CMAKE_CURRENT_SOURCE_DIR}/ModelVisualization + ${CMAKE_CURRENT_SOURCE_DIR}/ModelVisualization/Faults ${CMAKE_CURRENT_SOURCE_DIR}/ModelVisualization/GridBox ${CMAKE_CURRENT_SOURCE_DIR}/ModelVisualization/Intersections ${CMAKE_CURRENT_SOURCE_DIR}/ModelVisualization/Seismic diff --git a/ApplicationLibCode/Commands/EclipseCommands/RicEclipseHideFaultFeature.cpp b/ApplicationLibCode/Commands/EclipseCommands/RicEclipseHideFaultFeature.cpp index 75043349ea..803fe86df6 100644 --- a/ApplicationLibCode/Commands/EclipseCommands/RicEclipseHideFaultFeature.cpp +++ b/ApplicationLibCode/Commands/EclipseCommands/RicEclipseHideFaultFeature.cpp @@ -18,14 +18,9 @@ #include "RicEclipseHideFaultFeature.h" -#include "RicEclipsePropertyFilterFeatureImpl.h" -#include "RicEclipsePropertyFilterNewExec.h" - #include "RiaApplication.h" #include "Rim3dView.h" -#include "RimEclipseCellColors.h" -#include "RimEclipsePropertyFilterCollection.h" #include "RimEclipseView.h" #include "RimFaultInView.h" #include "RimFaultInViewCollection.h" @@ -33,9 +28,6 @@ #include "RigFault.h" #include "RigMainGrid.h" -#include "cafCmdExecCommandManager.h" -#include "cvfStructGrid.h" - #include CAF_CMD_SOURCE_INIT( RicEclipseHideFaultFeature, "RicEclipseHideFaultFeature" ); diff --git a/ApplicationLibCode/Commands/EclipseCommands/RicEclipseShowOnlyFaultFeature.cpp b/ApplicationLibCode/Commands/EclipseCommands/RicEclipseShowOnlyFaultFeature.cpp index fada5b5464..6bb8460e37 100644 --- a/ApplicationLibCode/Commands/EclipseCommands/RicEclipseShowOnlyFaultFeature.cpp +++ b/ApplicationLibCode/Commands/EclipseCommands/RicEclipseShowOnlyFaultFeature.cpp @@ -18,14 +18,9 @@ #include "RicEclipseShowOnlyFaultFeature.h" -#include "RicEclipsePropertyFilterFeatureImpl.h" -#include "RicEclipsePropertyFilterNewExec.h" - #include "RiaApplication.h" #include "Rim3dView.h" -#include "RimEclipseCellColors.h" -#include "RimEclipsePropertyFilterCollection.h" #include "RimEclipseView.h" #include "RimFaultInView.h" #include "RimFaultInViewCollection.h" @@ -33,9 +28,7 @@ #include "RigFault.h" #include "RigMainGrid.h" -#include "cafCmdExecCommandManager.h" #include "cafPdmUiObjectHandle.h" -#include "cvfStructGrid.h" #include diff --git a/ApplicationLibCode/Commands/GeoMechCommands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/GeoMechCommands/CMakeLists_files.cmake index 723c2db1dd..540177f86a 100644 --- a/ApplicationLibCode/Commands/GeoMechCommands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/GeoMechCommands/CMakeLists_files.cmake @@ -10,6 +10,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicImportGeoMechCaseTimeStepFilterFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewWellIntegrityAnalysisFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicRunWellIntegrityAnalysisFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicNewFaultReactModelingFeature.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -24,6 +25,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicImportGeoMechCaseTimeStepFilterFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewWellIntegrityAnalysisFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicRunWellIntegrityAnalysisFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicNewFaultReactModelingFeature.cpp ) list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.cpp b/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.cpp new file mode 100644 index 0000000000..07a12f3683 --- /dev/null +++ b/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.cpp @@ -0,0 +1,123 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicNewFaultReactModelingFeature.h" + +#include "RiaApplication.h" +#include "RiaPreferencesGeoMech.h" + +#include "Riu3DMainWindowTools.h" +#include "RiuViewer.h" + +#include "Rim3dView.h" +#include "RimCase.h" +#include "RimEclipseView.h" +#include "RimFaultInView.h" +#include "RimFaultInViewCollection.h" +#include "RimFaultReactivationModel.h" +#include "RimFaultReactivationModelCollection.h" + +#include "RigFault.h" +#include "RigMainGrid.h" + +#include "cafCmdExecCommandManager.h" +#include "cafDisplayCoordTransform.h" + +#include "cvfCamera.h" +#include "cvfStructGrid.h" + +#include + +CAF_CMD_SOURCE_INIT( RicNewFaultReactModelingFeature, "RicNewFaultReactModelingFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicNewFaultReactModelingFeature::isCommandEnabled() const +{ + return RiaPreferencesGeoMech::current()->validateFRMSettings(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewFaultReactModelingFeature::onActionTriggered( bool isChecked ) +{ + QVariant userData = this->userData(); + + if ( !userData.isNull() && userData.type() == QVariant::List ) + { + Rim3dView* view = RiaApplication::instance()->activeMainOrComparisonGridView(); + if ( !view ) return; + RimEclipseView* eclView = dynamic_cast( view ); + if ( !eclView ) return; + + QVariantList list = userData.toList(); + CAF_ASSERT( list.size() == 2 ); + + size_t currentCellIndex = static_cast( list[0].toULongLong() ); + int currentFaceIndex = list[1].toInt(); + + auto face = cvf::StructGridInterface::FaceType( currentFaceIndex ); + + const RigFault* fault = eclView->mainGrid()->findFaultFromCellIndexAndCellFace( currentCellIndex, face ); + if ( fault ) + { + QString faultName = fault->name(); + + RimFaultInView* rimFault = eclView->faultCollection()->findFaultByName( faultName ); + if ( rimFault ) + { + RigCell cell = eclView->mainGrid()->cell( currentCellIndex ); + + auto normal = cell.faceNormalWithAreaLength( face ); + normal.z() = normal.z() / eclView->scaleZ() / eclView->scaleZ(); + normal.normalize(); + normal *= eclView->ownerCase()->characteristicCellSize(); + normal *= 3; + + auto antiNormal = -1.0 * normal; + + auto camPos = eclView->viewer()->mainCamera()->position(); + + auto target1 = cell.faceCenter( face ); + auto candidate1 = target1 + normal; + auto candidate2 = target1 + antiNormal; + auto target2 = candidate1; + + if ( camPos.pointDistance( candidate2 ) < camPos.pointDistance( candidate1 ) ) target2 = candidate2; + + RimFaultReactivationModel* model = eclView->faultReactivationModelCollection()->addNewModel( rimFault, target1, target2 ); + + if ( model != nullptr ) + { + view->updateAllRequiredEditors(); + Riu3DMainWindowTools::selectAsCurrentItem( model ); + } + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewFaultReactModelingFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setIcon( QIcon( ":/fault_react_24x24.png" ) ); +} diff --git a/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.h b/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.h new file mode 100644 index 0000000000..76aeb91772 --- /dev/null +++ b/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicNewFaultReactModelingFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + bool isCommandEnabled() const override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/Commands/GeoMechCommands/RicRunWellIntegrityAnalysisFeature.cpp b/ApplicationLibCode/Commands/GeoMechCommands/RicRunWellIntegrityAnalysisFeature.cpp index 1cbb3ac887..7f97e2ea08 100644 --- a/ApplicationLibCode/Commands/GeoMechCommands/RicRunWellIntegrityAnalysisFeature.cpp +++ b/ApplicationLibCode/Commands/GeoMechCommands/RicRunWellIntegrityAnalysisFeature.cpp @@ -86,7 +86,7 @@ void RicRunWellIntegrityAnalysisFeature::onActionTriggered( bool isChecked ) return; } - if ( RiaPreferencesGeoMech::current()->waitBeforeRunWIA() ) + if ( RiaPreferencesGeoMech::current()->waitBeforeRun() ) { runProgress.setProgressDescription( "Waiting for input file modifications." ); diff --git a/ApplicationLibCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationLibCode/ModelVisualization/CMakeLists_files.cmake index d57c872507..0be91f9ee0 100644 --- a/ApplicationLibCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationLibCode/ModelVisualization/CMakeLists_files.cmake @@ -1,14 +1,11 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RivCellEdgeEffectGenerator.h - ${CMAKE_CURRENT_LIST_DIR}/RivFaultPartMgr.h - ${CMAKE_CURRENT_LIST_DIR}/RivFaultGeometryGenerator.h ${CMAKE_CURRENT_LIST_DIR}/RivNNCGeometryGenerator.h ${CMAKE_CURRENT_LIST_DIR}/RivGridPartMgr.h ${CMAKE_CURRENT_LIST_DIR}/RivTernarySaturationOverlayItem.h ${CMAKE_CURRENT_LIST_DIR}/RivReservoirPartMgr.h ${CMAKE_CURRENT_LIST_DIR}/RivReservoirViewPartMgr.h ${CMAKE_CURRENT_LIST_DIR}/RivPipeGeometryGenerator.h - ${CMAKE_CURRENT_LIST_DIR}/RivReservoirFaultsPartMgr.h ${CMAKE_CURRENT_LIST_DIR}/RivReservoirSimWellsPartMgr.h ${CMAKE_CURRENT_LIST_DIR}/RivSourceInfo.h ${CMAKE_CURRENT_LIST_DIR}/RivWellPathSourceInfo.h @@ -64,12 +61,9 @@ set(SOURCE_GROUP_HEADER_FILES set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RivCellEdgeEffectGenerator.cpp - ${CMAKE_CURRENT_LIST_DIR}/RivFaultPartMgr.cpp ${CMAKE_CURRENT_LIST_DIR}/RivNNCGeometryGenerator.cpp - ${CMAKE_CURRENT_LIST_DIR}/RivFaultGeometryGenerator.cpp ${CMAKE_CURRENT_LIST_DIR}/RivGridPartMgr.cpp ${CMAKE_CURRENT_LIST_DIR}/RivTernarySaturationOverlayItem.cpp - ${CMAKE_CURRENT_LIST_DIR}/RivReservoirFaultsPartMgr.cpp ${CMAKE_CURRENT_LIST_DIR}/RivReservoirPartMgr.cpp ${CMAKE_CURRENT_LIST_DIR}/RivReservoirViewPartMgr.cpp ${CMAKE_CURRENT_LIST_DIR}/RivPipeGeometryGenerator.cpp diff --git a/ApplicationLibCode/ModelVisualization/Faults/CMakeLists_files.cmake b/ApplicationLibCode/ModelVisualization/Faults/CMakeLists_files.cmake new file mode 100644 index 0000000000..64541ad6fb --- /dev/null +++ b/ApplicationLibCode/ModelVisualization/Faults/CMakeLists_files.cmake @@ -0,0 +1,23 @@ +set(SOURCE_GROUP_HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/RivFaultGeometryGenerator.h + ${CMAKE_CURRENT_LIST_DIR}/RivFaultPartMgr.h + ${CMAKE_CURRENT_LIST_DIR}/RivReservoirFaultsPartMgr.h + ${CMAKE_CURRENT_LIST_DIR}/RivFaultReactivationModelPartMgr.h +) + +set(SOURCE_GROUP_SOURCE_FILES + ${CMAKE_CURRENT_LIST_DIR}/RivFaultGeometryGenerator.cpp + ${CMAKE_CURRENT_LIST_DIR}/RivFaultPartMgr.cpp + ${CMAKE_CURRENT_LIST_DIR}/RivReservoirFaultsPartMgr.cpp + ${CMAKE_CURRENT_LIST_DIR}/RivFaultReactivationModelPartMgr.cpp +) + +list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) + +list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES}) + +source_group( + "ModelVisualization\\Faults" + FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} + ${CMAKE_CURRENT_LIST_DIR}/CMakeLists_files.cmake +) diff --git a/ApplicationLibCode/ModelVisualization/RivFaultGeometryGenerator.cpp b/ApplicationLibCode/ModelVisualization/Faults/RivFaultGeometryGenerator.cpp similarity index 100% rename from ApplicationLibCode/ModelVisualization/RivFaultGeometryGenerator.cpp rename to ApplicationLibCode/ModelVisualization/Faults/RivFaultGeometryGenerator.cpp diff --git a/ApplicationLibCode/ModelVisualization/RivFaultGeometryGenerator.h b/ApplicationLibCode/ModelVisualization/Faults/RivFaultGeometryGenerator.h similarity index 100% rename from ApplicationLibCode/ModelVisualization/RivFaultGeometryGenerator.h rename to ApplicationLibCode/ModelVisualization/Faults/RivFaultGeometryGenerator.h diff --git a/ApplicationLibCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationLibCode/ModelVisualization/Faults/RivFaultPartMgr.cpp similarity index 100% rename from ApplicationLibCode/ModelVisualization/RivFaultPartMgr.cpp rename to ApplicationLibCode/ModelVisualization/Faults/RivFaultPartMgr.cpp diff --git a/ApplicationLibCode/ModelVisualization/RivFaultPartMgr.h b/ApplicationLibCode/ModelVisualization/Faults/RivFaultPartMgr.h similarity index 100% rename from ApplicationLibCode/ModelVisualization/RivFaultPartMgr.h rename to ApplicationLibCode/ModelVisualization/Faults/RivFaultPartMgr.h diff --git a/ApplicationLibCode/ModelVisualization/Faults/RivFaultReactivationModelPartMgr.cpp b/ApplicationLibCode/ModelVisualization/Faults/RivFaultReactivationModelPartMgr.cpp new file mode 100644 index 0000000000..82e42b1cca --- /dev/null +++ b/ApplicationLibCode/ModelVisualization/Faults/RivFaultReactivationModelPartMgr.cpp @@ -0,0 +1,147 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivFaultReactivationModelPartMgr.h" + +#include "RiaGuiApplication.h" + +#include "RigBasicPlane.h" +#include "RigFaultReactivationModel.h" + +#include "RivPartPriority.h" +#include "RivPolylineGenerator.h" +#include "RivPolylinePartMgr.h" + +#include "Rim3dView.h" +#include "RimFaultReactivationModel.h" + +#include "cafDisplayCoordTransform.h" +#include "cafEffectGenerator.h" +#include "cafPdmObject.h" + +#include "cvfLibCore.h" +#include "cvfLibGeometry.h" +#include "cvfLibRender.h" +#include "cvfModelBasicList.h" +#include "cvfPart.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivFaultReactivationModelPartMgr::RivFaultReactivationModelPartMgr( RimFaultReactivationModel* frm ) + : m_frm( frm ) +{ + CVF_ASSERT( frm ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivFaultReactivationModelPartMgr::appendPolylinePartsToModel( Rim3dView* view, + cvf::ModelBasicList* vizModel, + const caf::DisplayCoordTransform* transform, + const cvf::BoundingBox& boundingBox ) +{ + if ( m_polylinePartMgr.isNull() ) m_polylinePartMgr = new RivPolylinePartMgr( view, m_frm.p(), m_frm.p() ); + + m_polylinePartMgr->appendDynamicGeometryPartsToModel( vizModel, transform, boundingBox ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivFaultReactivationModelPartMgr::appendMeshPartsToModel( Rim3dView* view, + cvf::ModelBasicList* vizModel, + const caf::DisplayCoordTransform* transform, + const cvf::BoundingBox& boundingBox ) +{ + auto model2d = m_frm->model(); + if ( model2d.notNull() && model2d->isValid() && m_frm->isChecked() && m_frm->showModel() ) + { + for ( auto gridPart : m_frm->model()->allGridParts() ) + { + auto& lines = m_frm->model()->meshLines( gridPart ); + + std::vector> displayPoints; + for ( const auto& pts : lines ) + { + displayPoints.push_back( transform->transformToDisplayCoords( pts ) ); + } + + cvf::ref drawableGeo = RivPolylineGenerator::createSetOfLines( displayPoints ); + cvf::ref part = new cvf::Part; + part->setName( "FaultReactMeshLines" ); + part->setDrawable( drawableGeo.p() ); + + caf::MeshEffectGenerator effgen( cvf::Color3::LIGHT_GRAY ); + effgen.setLineWidth( 1.5 ); + effgen.setLineStipple( false ); + cvf::ref eff = effgen.generateCachedEffect(); + + part->setEffect( eff.p() ); + part->setPriority( RivPartPriority::PartType::MeshLines ); + + vizModel->addPart( part.p() ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivFaultReactivationModelPartMgr::appendGeometryPartsToModel( cvf::ModelBasicList* vizModel, + const caf::DisplayCoordTransform* displayCoordTransform, + const cvf::BoundingBox& boundingBox ) +{ + if ( !m_canUseShaders ) return; + + auto plane = m_frm->faultPlane(); + if ( plane->isValid() && m_frm->showFaultPlane() ) + { + cvf::Vec3dArray displayPoints; + displayPoints.reserve( plane->rect().size() ); + + for ( auto& vOrg : plane->rect() ) + { + displayPoints.add( displayCoordTransform->transformToDisplayCoord( vOrg ) ); + } + + cvf::ref quadPart = createSingleTexturedQuadPart( displayPoints, plane->texture(), false ); + + vizModel->addPart( quadPart.p() ); + } + + auto theModel = m_frm->model(); + if ( theModel->isValid() && m_frm->showModel() ) + { + for ( auto part : theModel->allModelParts() ) + { + cvf::Vec3dArray displayPoints; + displayPoints.reserve( theModel->rect( part ).size() ); + + for ( auto& vOrg : theModel->rect( part ) ) + { + displayPoints.add( displayCoordTransform->transformToDisplayCoord( vOrg ) ); + } + + cvf::ref quadPart = createSingleTexturedQuadPart( displayPoints, theModel->texture( part ), false ); + + vizModel->addPart( quadPart.p() ); + } + } +} diff --git a/ApplicationLibCode/ModelVisualization/Faults/RivFaultReactivationModelPartMgr.h b/ApplicationLibCode/ModelVisualization/Faults/RivFaultReactivationModelPartMgr.h new file mode 100644 index 0000000000..4a2a23e184 --- /dev/null +++ b/ApplicationLibCode/ModelVisualization/Faults/RivFaultReactivationModelPartMgr.h @@ -0,0 +1,67 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include "RivTexturePartMgr.h" + +#include "cafPdmPointer.h" +#include "cvfArray.h" +#include "cvfObject.h" + +namespace cvf +{ +class ModelBasicList; +class Part; +class DrawableGeo; +class BoundingBox; +class TextureImage; +} // namespace cvf + +namespace caf +{ +class DisplayCoordTransform; +} + +class RimFaultReactivationModel; +class Rim3dView; +class RivPolylinePartMgr; + +class RivFaultReactivationModelPartMgr : public RivTexturePartMgr +{ +public: + explicit RivFaultReactivationModelPartMgr( RimFaultReactivationModel* frm ); + + void appendGeometryPartsToModel( cvf::ModelBasicList* vizModel, + const caf::DisplayCoordTransform* displayCoordTransform, + const cvf::BoundingBox& boundingBox ); + + void appendPolylinePartsToModel( Rim3dView* view, + cvf::ModelBasicList* vizModel, + const caf::DisplayCoordTransform* displayCoordTransform, + const cvf::BoundingBox& boundingBox ); + + void appendMeshPartsToModel( Rim3dView* view, + cvf::ModelBasicList* vizModel, + const caf::DisplayCoordTransform* displayCoordTransform, + const cvf::BoundingBox& boundingBox ); + +private: + caf::PdmPointer m_frm; + + cvf::ref m_polylinePartMgr; +}; diff --git a/ApplicationLibCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationLibCode/ModelVisualization/Faults/RivReservoirFaultsPartMgr.cpp similarity index 100% rename from ApplicationLibCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp rename to ApplicationLibCode/ModelVisualization/Faults/RivReservoirFaultsPartMgr.cpp diff --git a/ApplicationLibCode/ModelVisualization/RivReservoirFaultsPartMgr.h b/ApplicationLibCode/ModelVisualization/Faults/RivReservoirFaultsPartMgr.h similarity index 100% rename from ApplicationLibCode/ModelVisualization/RivReservoirFaultsPartMgr.h rename to ApplicationLibCode/ModelVisualization/Faults/RivReservoirFaultsPartMgr.h diff --git a/ApplicationLibCode/ModelVisualization/RivPolylineGenerator.cpp b/ApplicationLibCode/ModelVisualization/RivPolylineGenerator.cpp index 507b0a23dc..de681cf68a 100644 --- a/ApplicationLibCode/ModelVisualization/RivPolylineGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/RivPolylineGenerator.cpp @@ -120,3 +120,45 @@ cvf::ref RivPolylineGenerator::createPointsFromPolylineDrawabl return geo; } + +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivPolylineGenerator::createSetOfLines( const std::vector>& lines ) +{ + std::vector lineIndices; + std::vector vertices; + + for ( const std::vector& polyLine : lines ) + { + if ( polyLine.size() < 2 ) continue; + + size_t verticesCount = vertices.size(); + + for ( size_t i = 0; i < polyLine.size(); i += 2 ) + { + vertices.emplace_back( polyLine[i] ); + vertices.emplace_back( polyLine[i + 1] ); + if ( i < polyLine.size() - 1 ) + { + lineIndices.push_back( static_cast( verticesCount + i ) ); + lineIndices.push_back( static_cast( verticesCount + i + 1 ) ); + } + } + } + + if ( vertices.empty() ) return nullptr; + + cvf::ref vx = new cvf::Vec3fArray; + vx->assign( vertices ); + cvf::ref idxes = new cvf::UIntArray; + idxes->assign( lineIndices ); + + cvf::ref prim = new cvf::PrimitiveSetIndexedUInt( cvf::PT_LINES ); + prim->setIndices( idxes.p() ); + + cvf::ref polylineGeo = new cvf::DrawableGeo; + polylineGeo->setVertexArray( vx.p() ); + polylineGeo->addPrimitiveSet( prim.p() ); + + return polylineGeo; +} diff --git a/ApplicationLibCode/ModelVisualization/RivPolylineGenerator.h b/ApplicationLibCode/ModelVisualization/RivPolylineGenerator.h index 246f5bc961..a27216c569 100644 --- a/ApplicationLibCode/ModelVisualization/RivPolylineGenerator.h +++ b/ApplicationLibCode/ModelVisualization/RivPolylineGenerator.h @@ -40,4 +40,6 @@ public: static cvf::ref createPointsFromPolylineDrawable( const std::vector& polyLine ); static cvf::ref createPointsFromPolylineDrawable( const std::vector>& polyLines ); + + static cvf::ref createSetOfLines( const std::vector>& lines ); }; diff --git a/ApplicationLibCode/ModelVisualization/Seismic/CMakeLists_files.cmake b/ApplicationLibCode/ModelVisualization/Seismic/CMakeLists_files.cmake index a7ab72a8ee..b72ed9d24f 100644 --- a/ApplicationLibCode/ModelVisualization/Seismic/CMakeLists_files.cmake +++ b/ApplicationLibCode/ModelVisualization/Seismic/CMakeLists_files.cmake @@ -1,11 +1,13 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RivSeismicSectionPartMgr.h ${CMAKE_CURRENT_LIST_DIR}/RivSeismicSectionSourceInfo.h + ${CMAKE_CURRENT_LIST_DIR}/RivTexturePartMgr.h ) set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RivSeismicSectionPartMgr.cpp ${CMAKE_CURRENT_LIST_DIR}/RivSeismicSectionSourceInfo.cpp + ${CMAKE_CURRENT_LIST_DIR}/RivTexturePartMgr.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.cpp b/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.cpp index 689dc543bd..7a55987761 100644 --- a/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.cpp @@ -55,17 +55,8 @@ //-------------------------------------------------------------------------------------------------- RivSeismicSectionPartMgr::RivSeismicSectionPartMgr( RimSeismicSection* section ) : m_section( section ) - , m_canUseShaders( true ) { CVF_ASSERT( section ); - - m_canUseShaders = RiaGuiApplication::instance()->useShaders(); - - cvf::ShaderProgramGenerator gen( "Texturing", cvf::ShaderSourceProvider::instance() ); - gen.addVertexCode( cvf::ShaderSourceRepository::vs_Standard ); - gen.addFragmentCode( cvf::ShaderSourceRepository::src_Texture ); - gen.addFragmentCode( cvf::ShaderSourceRepository::fs_Unlit ); - m_textureShaderProg = gen.generate(); } //-------------------------------------------------------------------------------------------------- @@ -111,7 +102,7 @@ void RivSeismicSectionPartMgr::appendGeometryPartsToModel( cvf::ModelBasicList* part.texture = createImageFromData( part.sliceData.get() ); } - cvf::ref quadPart = createSingleTexturedQuadPart( displayPoints, part.texture ); + cvf::ref quadPart = createSingleTexturedQuadPart( displayPoints, part.texture, m_section->isTransparent() ); cvf::ref si = new RivSeismicSectionSourceInfo( m_section, i ); quadPart->setSourceInfo( si.p() ); @@ -120,85 +111,6 @@ void RivSeismicSectionPartMgr::appendGeometryPartsToModel( cvf::ModelBasicList* } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RivSeismicSectionPartMgr::createSingleTexturedQuadPart( const cvf::Vec3dArray& cornerPoints, - cvf::ref image ) -{ - cvf::ref part = new cvf::Part; - - cvf::ref geo = createXYPlaneQuadGeoWithTexCoords( cornerPoints ); - - cvf::ref texture = new cvf::Texture( image.p() ); - cvf::ref sampler = new cvf::Sampler; - sampler->setMinFilter( cvf::Sampler::LINEAR ); - sampler->setMagFilter( cvf::Sampler::NEAREST ); - sampler->setWrapModeS( cvf::Sampler::CLAMP_TO_EDGE ); - sampler->setWrapModeT( cvf::Sampler::CLAMP_TO_EDGE ); - - cvf::ref textureBindings = new cvf::RenderStateTextureBindings; - textureBindings->addBinding( texture.p(), sampler.p(), "u_texture2D" ); - - cvf::ref eff = new cvf::Effect; - eff->setRenderState( textureBindings.p() ); - eff->setShaderProgram( m_textureShaderProg.p() ); - - if ( m_section->isTransparent() ) - { - part->setPriority( RivPartPriority::PartType::TransparentSeismic ); - cvf::ref blending = new cvf::RenderStateBlending; - blending->configureTransparencyBlending(); - eff->setRenderState( blending.p() ); - } - - part->setDrawable( geo.p() ); - part->setEffect( eff.p() ); - - return part; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RivSeismicSectionPartMgr::createXYPlaneQuadGeoWithTexCoords( const cvf::Vec3dArray& cornerPoints ) -{ - cvf::ref vertices = new cvf::Vec3fArray; - vertices->reserve( 4 ); - - for ( const auto& v : cornerPoints ) - { - vertices->add( cvf::Vec3f( v ) ); - } - - cvf::ref texCoords = new cvf::Vec2fArray; - texCoords->reserve( 4 ); - texCoords->add( cvf::Vec2f( 0, 0 ) ); - texCoords->add( cvf::Vec2f( 1, 0 ) ); - texCoords->add( cvf::Vec2f( 1, 1 ) ); - texCoords->add( cvf::Vec2f( 0, 1 ) ); - - cvf::ref geo = new cvf::DrawableGeo; - geo->setVertexArray( vertices.p() ); - geo->setTextureCoordArray( texCoords.p() ); - - cvf::ref indices = new cvf::UIntArray; - indices->reserve( 6 ); - - for ( uint i : { 0, 1, 2, 0, 2, 3 } ) - { - indices->add( i ); - } - - cvf::ref primSet = new cvf::PrimitiveSetIndexedUInt( cvf::PT_TRIANGLES ); - primSet->setIndices( indices.p() ); - geo->addPrimitiveSet( primSet.p() ); - - geo->computeNormals(); - - return geo; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.h b/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.h index 6a70d2efa7..d95ceb7f8f 100644 --- a/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.h +++ b/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.h @@ -17,17 +17,15 @@ ///////////////////////////////////////////////////////////////////////////////// #pragma once +#include "RivTexturePartMgr.h" + #include "cafPdmPointer.h" #include "cvfArray.h" -#include "cvfObject.h" -#include "cvfVector3.h" namespace cvf { class ModelBasicList; -class Transform; class Part; -class ScalarMapper; class DrawableGeo; class BoundingBox; class ShaderProgram; @@ -44,13 +42,12 @@ namespace ZGYAccess class SeismicSliceData; } -class RimSeismicSectionCollection; class RimSeismicSection; class RimSurface; class Rim3dView; class RivPolylinePartMgr; -class RivSeismicSectionPartMgr : public cvf::Object +class RivSeismicSectionPartMgr : public RivTexturePartMgr { public: explicit RivSeismicSectionPartMgr( RimSeismicSection* section ); @@ -73,6 +70,7 @@ private: cvf::ref createXYPlaneQuadGeoWithTexCoords( const cvf::Vec3dArray& cornerPoints ); cvf::ref createSingleTexturedQuadPart( const cvf::Vec3dArray& cornerPoints, cvf::ref image ); +protected: cvf::TextureImage* createImageFromData( ZGYAccess::SeismicSliceData* data ); static std::vector> projectPolyLineOntoSurface( std::vector polyLine, @@ -82,7 +80,4 @@ private: private: caf::PdmPointer m_section; cvf::ref m_polylinePartMgr; - cvf::ref m_textureShaderProg; - - bool m_canUseShaders; }; diff --git a/ApplicationLibCode/ModelVisualization/Seismic/RivTexturePartMgr.cpp b/ApplicationLibCode/ModelVisualization/Seismic/RivTexturePartMgr.cpp new file mode 100644 index 0000000000..6026121ab7 --- /dev/null +++ b/ApplicationLibCode/ModelVisualization/Seismic/RivTexturePartMgr.cpp @@ -0,0 +1,137 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivTexturePartMgr.h" + +#include "RiaGuiApplication.h" + +#include "RivPartPriority.h" + +#include "RigTexturedSection.h" + +#include "cafDisplayCoordTransform.h" +#include "cafEffectGenerator.h" +#include "cafPdmObject.h" + +#include "cvfLibCore.h" +#include "cvfLibGeometry.h" +#include "cvfLibRender.h" +#include "cvfModelBasicList.h" +#include "cvfPart.h" +#include "cvfScalarMapper.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivTexturePartMgr::RivTexturePartMgr() + : m_canUseShaders( true ) +{ + m_canUseShaders = RiaGuiApplication::instance()->useShaders(); + + cvf::ShaderProgramGenerator gen( "Texturing", cvf::ShaderSourceProvider::instance() ); + gen.addVertexCode( cvf::ShaderSourceRepository::vs_Standard ); + gen.addFragmentCode( cvf::ShaderSourceRepository::src_Texture ); + gen.addFragmentCode( cvf::ShaderSourceRepository::fs_Unlit ); + m_textureShaderProg = gen.generate(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivTexturePartMgr::~RivTexturePartMgr() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref + RivTexturePartMgr::createSingleTexturedQuadPart( const cvf::Vec3dArray& cornerPoints, cvf::ref image, bool transparent ) +{ + cvf::ref part = new cvf::Part; + + cvf::ref geo = createXYPlaneQuadGeoWithTexCoords( cornerPoints ); + + cvf::ref texture = new cvf::Texture( image.p() ); + cvf::ref sampler = new cvf::Sampler; + sampler->setMinFilter( cvf::Sampler::LINEAR ); + sampler->setMagFilter( cvf::Sampler::NEAREST ); + sampler->setWrapModeS( cvf::Sampler::CLAMP_TO_EDGE ); + sampler->setWrapModeT( cvf::Sampler::CLAMP_TO_EDGE ); + + cvf::ref textureBindings = new cvf::RenderStateTextureBindings; + textureBindings->addBinding( texture.p(), sampler.p(), "u_texture2D" ); + + cvf::ref eff = new cvf::Effect; + eff->setRenderState( textureBindings.p() ); + eff->setShaderProgram( m_textureShaderProg.p() ); + + if ( transparent ) + { + part->setPriority( RivPartPriority::PartType::TransparentSeismic ); + cvf::ref blending = new cvf::RenderStateBlending; + blending->configureTransparencyBlending(); + eff->setRenderState( blending.p() ); + } + + part->setDrawable( geo.p() ); + part->setEffect( eff.p() ); + + return part; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivTexturePartMgr::createXYPlaneQuadGeoWithTexCoords( const cvf::Vec3dArray& cornerPoints ) +{ + cvf::ref vertices = new cvf::Vec3fArray; + vertices->reserve( 4 ); + + for ( const auto& v : cornerPoints ) + { + vertices->add( cvf::Vec3f( v ) ); + } + + cvf::ref texCoords = new cvf::Vec2fArray; + texCoords->reserve( 4 ); + texCoords->add( cvf::Vec2f( 0, 0 ) ); + texCoords->add( cvf::Vec2f( 1, 0 ) ); + texCoords->add( cvf::Vec2f( 1, 1 ) ); + texCoords->add( cvf::Vec2f( 0, 1 ) ); + + cvf::ref geo = new cvf::DrawableGeo; + geo->setVertexArray( vertices.p() ); + geo->setTextureCoordArray( texCoords.p() ); + + cvf::ref indices = new cvf::UIntArray; + indices->reserve( 6 ); + + for ( uint i : { 0, 1, 2, 0, 2, 3 } ) + { + indices->add( i ); + } + + cvf::ref primSet = new cvf::PrimitiveSetIndexedUInt( cvf::PT_TRIANGLES ); + primSet->setIndices( indices.p() ); + geo->addPrimitiveSet( primSet.p() ); + + geo->computeNormals(); + + return geo; +} diff --git a/ApplicationLibCode/ModelVisualization/Seismic/RivTexturePartMgr.h b/ApplicationLibCode/ModelVisualization/Seismic/RivTexturePartMgr.h new file mode 100644 index 0000000000..afb64405da --- /dev/null +++ b/ApplicationLibCode/ModelVisualization/Seismic/RivTexturePartMgr.h @@ -0,0 +1,63 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include "cafPdmPointer.h" +#include "cvfArray.h" +#include "cvfObject.h" + +namespace cvf +{ +class ModelBasicList; +class Part; +class DrawableGeo; +class BoundingBox; +class ShaderProgram; +class TextureImage; +} // namespace cvf + +namespace caf +{ +class DisplayCoordTransform; +} + +class Rim3dView; + +class RivTexturePartMgr : public cvf::Object +{ +public: + RivTexturePartMgr(); + virtual ~RivTexturePartMgr(); + + virtual void appendGeometryPartsToModel( cvf::ModelBasicList* model, + const caf::DisplayCoordTransform* displayCoordTransform, + const cvf::BoundingBox& boundingBox ) = 0; + + virtual void appendPolylinePartsToModel( Rim3dView* view, + cvf::ModelBasicList* model, + const caf::DisplayCoordTransform* displayCoordTransform, + const cvf::BoundingBox& boundingBox ) = 0; + +protected: + cvf::ref createXYPlaneQuadGeoWithTexCoords( const cvf::Vec3dArray& cornerPoints ); + cvf::ref createSingleTexturedQuadPart( const cvf::Vec3dArray& cornerPoints, cvf::ref image, bool transparent ); + + cvf::ref m_textureShaderProg; + + bool m_canUseShaders; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake index 4bf68e1964..f45b12175d 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake @@ -1,11 +1,15 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RimFaultInView.h ${CMAKE_CURRENT_LIST_DIR}/RimFaultInViewCollection.h + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModel.h + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModelCollection.h ) set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimFaultInView.cpp ${CMAKE_CURRENT_LIST_DIR}/RimFaultInViewCollection.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModel.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModelCollection.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp new file mode 100644 index 0000000000..8f1a8a9afa --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp @@ -0,0 +1,450 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimFaultReactivationModel.h" + +#include "RiaApplication.h" +#include "RiaPreferencesGeoMech.h" + +#include "RigBasicPlane.h" +#include "RigFaultReactivationModel.h" +#include "RigPolyLinesData.h" + +#include "WellPathCommands/PointTangentManipulator/RicPolyline3dEditor.h" +#include "WellPathCommands/RicPolylineTargetsPickEventHandler.h" + +#include "RiuViewer.h" + +#include "RivFaultReactivationModelPartMgr.h" + +#include "Rim3dView.h" +#include "RimEclipseCase.h" +#include "RimEclipseView.h" +#include "RimFaultInView.h" +#include "RimFaultInViewCollection.h" +#include "RimPolylineTarget.h" +#include "RimTools.h" + +#include "cafPdmUiDoubleSliderEditor.h" +#include "cafPdmUiTableViewEditor.h" + +#include "cvfPlane.h" +#include "cvfTextureImage.h" + +CAF_PDM_SOURCE_INIT( RimFaultReactivationModel, "FaultReactivationModel" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationModel::RimFaultReactivationModel() + : m_pickTargetsEventHandler( new RicPolylineTargetsPickEventHandler( this ) ) +{ + CAF_PDM_InitObject( "Fault Reactivation Model", ":/fault_react_24x24.png" ); + + CAF_PDM_InitField( &m_userDescription, "UserDescription", QString( "Model" ), "Name" ); + + CAF_PDM_InitField( &m_extentHorizontal, "HorizontalExtent", 1000.0, "Horizontal Extent" ); + CAF_PDM_InitField( &m_extentVerticalAbove, "VerticalExtentAbove", 200.0, "Vertical Extent Above Anchor" ); + m_extentVerticalAbove.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() ); + m_extentVerticalAbove.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosType::TOP ); + + CAF_PDM_InitField( &m_extentVerticalBelow, "VerticalExtentBelow", 200.0, "Vertical Extent Below Anchor" ); + m_extentVerticalBelow.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() ); + m_extentVerticalBelow.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosType::TOP ); + + CAF_PDM_InitField( &m_modelExtentFromAnchor, "ModelExtentFromAnchor", 1000.0, "Horz. Extent from Anchor" ); + CAF_PDM_InitField( &m_modelMinZ, "ModelMinZ", 0.0, "Start Depth" ); + CAF_PDM_InitField( &m_modelBelowSize, "ModelBelowSize", 500.0, "Depth Below Fault" ); + + CAF_PDM_InitField( &m_showFaultPlane, "ShowFaultPlane", true, "Show Fault Plane" ); + CAF_PDM_InitField( &m_showModelPlane, "ShowModelPlane", false, "Show 2D Model" ); + + CAF_PDM_InitFieldNoDefault( &m_fault, "Fault", "Fault" ); + m_fault.uiCapability()->setUiReadOnly( true ); + + CAF_PDM_InitField( &m_faultPlaneColor, "FaultPlaneColor", cvf::Color3f( cvf::Color3f::GRAY ), "Plane Color" ); + CAF_PDM_InitField( &m_modelPart1Color, "ModelPart1Color", cvf::Color3f( cvf::Color3f::GREEN ), "Part 1 Color" ); + CAF_PDM_InitField( &m_modelPart2Color, "ModelPart2Color", cvf::Color3f( cvf::Color3f::BLUE ), "Part 2 Color" ); + + CAF_PDM_InitField( &m_numberOfCellsHorzPart1, "NumberOfCellsHorzPart1", 20, "Horizontal Number of Cells, Part 1" ); + CAF_PDM_InitField( &m_numberOfCellsHorzPart2, "NumberOfCellsHorzPart2", 20, "Horizontal Number of Cells, Part 2" ); + CAF_PDM_InitField( &m_numberOfCellsVertUp, "NumberOfCellsVertUp", 20, "Vertical Number of Cells, Upper Part" ); + CAF_PDM_InitField( &m_numberOfCellsVertMid, "NumberOfCellsVertMid", 20, "Vertical Number of Cells, Middle Part" ); + CAF_PDM_InitField( &m_numberOfCellsVertLow, "NumberOfCellsVertLow", 20, "Vertical Number of Cells, Lower Part" ); + + CAF_PDM_InitFieldNoDefault( &m_targets, "Targets", "Targets" ); + m_targets.uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() ); + m_targets.uiCapability()->setUiTreeChildrenHidden( true ); + m_targets.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); + m_targets.uiCapability()->setCustomContextMenuEnabled( false ); + + this->setUi3dEditorTypeName( RicPolyline3dEditor::uiEditorTypeName() ); + this->uiCapability()->setUiTreeChildrenHidden( true ); + + setDeletable( true ); + + m_faultPlane = new RigBasicPlane(); + m_modelPlane = new RigFaultReactivationModel(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationModel::~RimFaultReactivationModel() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModel::initAfterRead() +{ + updateVisualization(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimFaultReactivationModel::userDescription() +{ + return m_userDescription; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModel::setUserDescription( QString description ) +{ + m_userDescription = description; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimFaultReactivationModel::userDescriptionField() +{ + return &m_userDescription; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModel::setFault( RimFaultInView* fault ) +{ + m_fault = fault; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultInView* RimFaultReactivationModel::fault() const +{ + return m_fault(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModel::setTargets( cvf::Vec3d target1, cvf::Vec3d target2 ) +{ + m_targets.deleteChildren(); + + RimPolylineTarget* planeCenter = new RimPolylineTarget(); + planeCenter->setAsPointXYZ( target1 ); + + m_targets.push_back( planeCenter ); + + RimPolylineTarget* steeringTarget = new RimPolylineTarget(); + steeringTarget->setAsPointXYZ( target2 ); + + m_targets.push_back( steeringTarget ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimFaultReactivationModel::activeTargets() const +{ + return m_targets.childrenByType(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModel::insertTarget( const RimPolylineTarget* targetToInsertBefore, RimPolylineTarget* targetToInsert ) +{ + // do nothing, we should only have 2 predefined targets +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModel::deleteTarget( RimPolylineTarget* targetToDelete ) +{ + // do nothing, we should always have 2 predefined targets +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationModel::pickingEnabled() const +{ + // never pick, we only have our 2 predefined targets + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PickEventHandler* RimFaultReactivationModel::pickEventHandler() const +{ + return m_pickTargetsEventHandler.get(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModel::updateVisualization() +{ + auto view = firstAncestorOrThisOfType(); + if ( !view ) return; + + auto normal = m_targets[1]->targetPointXYZ() - m_targets[0]->targetPointXYZ(); + normal.z() = normal.z() * view->scaleZ() * view->scaleZ(); + normal.normalize(); + + m_faultPlane->setPlane( m_targets[0]->targetPointXYZ(), normal ); + m_faultPlane->setMaxExtentFromAnchor( m_extentHorizontal, m_extentVerticalAbove, m_extentVerticalBelow ); + m_faultPlane->setColor( m_faultPlaneColor ); + m_faultPlane->updateRect(); + + double maxZ = m_faultPlane->maxDepth(); + auto [topInt, bottomInt] = m_faultPlane->intersectTopBottomLine(); + + cvf::Vec3d zdir( 0, 0, 1 ); + auto modelNormal = normal ^ zdir; + modelNormal.normalize(); + + m_modelPlane->setPlane( m_targets[0]->targetPointXYZ(), modelNormal ); + m_modelPlane->setFaultPlaneIntersect( topInt, bottomInt ); + m_modelPlane->setMaxExtentFromAnchor( m_modelExtentFromAnchor, m_modelMinZ, maxZ + m_modelBelowSize ); + m_modelPlane->setPartColors( m_modelPart1Color, m_modelPart2Color ); + m_modelPlane->setCellCounts( m_numberOfCellsHorzPart1, + m_numberOfCellsHorzPart2, + m_numberOfCellsVertUp, + m_numberOfCellsVertMid, + m_numberOfCellsVertLow ); + m_modelPlane->updateRects(); + + view->scheduleCreateDisplayModelAndRedraw(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModel::updateEditorsAndVisualization() +{ + updateConnectedEditors(); + updateVisualization(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RimFaultReactivationModel::polyLinesData() const +{ + cvf::ref pld = new RigPolyLinesData; + + std::vector line; + for ( const RimPolylineTarget* target : m_targets ) + { + line.push_back( target->targetPointXYZ() ); + } + pld->setPolyLine( line ); + + return pld; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimFaultReactivationModel::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) +{ + QList options; + + if ( fieldNeedingOptions == &m_fault ) + { + if ( m_fault() != nullptr ) + { + auto coll = m_fault->firstAncestorOrThisOfType(); + if ( coll != nullptr ) RimTools::faultOptionItems( &options, coll ); + } + } + + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivFaultReactivationModelPartMgr* RimFaultReactivationModel::partMgr() +{ + if ( m_partMgr.isNull() ) m_partMgr = new RivFaultReactivationModelPartMgr( this ); + + return m_partMgr.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RimFaultReactivationModel::faultPlane() const +{ + return m_faultPlane; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RimFaultReactivationModel::model() const +{ + return m_modelPlane; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationModel::showFaultPlane() const +{ + return m_showFaultPlane; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationModel::showModel() const +{ + return m_showModelPlane; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModel::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + auto genGrp = uiOrdering.addNewGroup( "General" ); + genGrp->add( &m_userDescription ); + genGrp->add( &m_fault ); + + auto faultGrp = uiOrdering.addNewGroup( "Fault Plane" ); + + faultGrp->add( &m_showFaultPlane ); + faultGrp->add( &m_faultPlaneColor ); + faultGrp->add( &m_extentHorizontal ); + faultGrp->add( &m_extentVerticalAbove ); + faultGrp->add( &m_extentVerticalBelow ); + + auto modelGrp = uiOrdering.addNewGroup( "2D Model" ); + modelGrp->add( &m_showModelPlane ); + + auto sizeModelGrp = modelGrp->addNewGroup( "Size" ); + sizeModelGrp->add( &m_modelExtentFromAnchor ); + sizeModelGrp->add( &m_modelMinZ ); + sizeModelGrp->add( &m_modelBelowSize ); + + auto gridModelGrp = modelGrp->addNewGroup( "Grid" ); + + gridModelGrp->add( &m_numberOfCellsHorzPart1 ); + gridModelGrp->add( &m_numberOfCellsHorzPart2 ); + gridModelGrp->add( &m_numberOfCellsVertUp ); + gridModelGrp->add( &m_numberOfCellsVertMid ); + gridModelGrp->add( &m_numberOfCellsVertLow ); + + auto appModelGrp = modelGrp->addNewGroup( "Appearance" ); + appModelGrp->add( &m_modelPart1Color ); + appModelGrp->add( &m_modelPart2Color ); + + auto trgGroup = uiOrdering.addNewGroup( "Debug" ); + trgGroup->setCollapsedByDefault(); + trgGroup->add( &m_targets ); + + uiOrdering.skipRemainingFields(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModel::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) +{ + if ( changedField == &m_userDescription ) + { + updateConnectedEditors(); + } + else + { + updateVisualization(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModel::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) +{ + if ( field == &m_targets ) + { + auto tvAttribute = dynamic_cast( attribute ); + if ( tvAttribute ) + { + tvAttribute->resizePolicy = caf::PdmUiTableViewEditorAttribute::RESIZE_TO_FIT_CONTENT; + } + } + else if ( ( field == &m_extentVerticalAbove ) || ( field == &m_extentVerticalBelow ) ) + { + auto* attr = dynamic_cast( attribute ); + + if ( attr ) + { + auto eclCase = eclipseCase(); + if ( eclCase ) + { + auto bb = eclCase->allCellsBoundingBox(); + double diff = bb.max().z() - bb.min().z(); + attr->m_minimum = 0; + attr->m_maximum = diff; + } + else + { + attr->m_minimum = 0; + attr->m_maximum = 1000; + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEclipseCase* RimFaultReactivationModel::eclipseCase() +{ + auto activeView = dynamic_cast( RiaApplication::instance()->activeGridView() ); + if ( activeView ) + { + return activeView->eclipseCase(); + } + return nullptr; +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h new file mode 100644 index 0000000000..498a6f2795 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h @@ -0,0 +1,130 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include "RimCheckableNamedObject.h" +#include "RimPolylinePickerInterface.h" +#include "RimPolylinesDataInterface.h" + +#include "cafFilePath.h" +#include "cafPdmChildArrayField.h" +#include "cafPdmChildField.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmPtrField.h" + +#include "cvfColor3.h" +#include "cvfVector3.h" + +#include + +#include +#include + +class RicPolylineTargetsPickEventHandler; +class RimEclipseCase; +class RimFaultInView; +class RimPolylineTarget; +class RivFaultReactivationModelPartMgr; +class RigBasicPlane; +class RigFaultReactivationModel; + +namespace cvf +{ +class BoundingBox; +class Plane; +} // namespace cvf + +class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPolylinePickerInterface, public RimPolylinesDataInterface +{ + CAF_PDM_HEADER_INIT; + +public: + RimFaultReactivationModel(); + ~RimFaultReactivationModel() override; + + QString userDescription(); + void setUserDescription( QString description ); + + void setFault( RimFaultInView* fault ); + RimFaultInView* fault() const; + + void setTargets( cvf::Vec3d target1, cvf::Vec3d target2 ); + + RivFaultReactivationModelPartMgr* partMgr(); + + // polyline picker interface + void insertTarget( const RimPolylineTarget* targetToInsertBefore, RimPolylineTarget* targetToInsert ) override; + void deleteTarget( RimPolylineTarget* targetToDelete ) override; + void updateEditorsAndVisualization() override; + void updateVisualization() override; + std::vector activeTargets() const override; + bool pickingEnabled() const override; + caf::PickEventHandler* pickEventHandler() const override; + + // polyline data interface + cvf::ref polyLinesData() const override; + + cvf::ref faultPlane() const; + bool showFaultPlane() const; + + cvf::ref model() const; + bool showModel() const; + +protected: + caf::PdmFieldHandle* userDescriptionField() override; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; + + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; + + RimEclipseCase* eclipseCase(); + + void initAfterRead() override; + +private: + std::shared_ptr m_pickTargetsEventHandler; + + cvf::ref m_partMgr; + + caf::PdmField m_userDescription; + caf::PdmPtrField m_fault; + caf::PdmChildArrayField m_targets; + caf::PdmField m_faultPlaneColor; + caf::PdmField m_modelPart1Color; + caf::PdmField m_modelPart2Color; + + caf::PdmField m_showFaultPlane; + caf::PdmField m_showModelPlane; + + caf::PdmField m_extentVerticalAbove; + caf::PdmField m_extentVerticalBelow; + caf::PdmField m_extentHorizontal; + caf::PdmField m_modelExtentFromAnchor; + caf::PdmField m_modelMinZ; + caf::PdmField m_modelBelowSize; + caf::PdmField m_numberOfCellsHorzPart1; + caf::PdmField m_numberOfCellsHorzPart2; + caf::PdmField m_numberOfCellsVertUp; + caf::PdmField m_numberOfCellsVertMid; + caf::PdmField m_numberOfCellsVertLow; + + cvf::ref m_faultPlane; + cvf::ref m_modelPlane; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.cpp new file mode 100644 index 0000000000..bd929403bb --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.cpp @@ -0,0 +1,186 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimFaultReactivationModelCollection.h" + +#include "RiaPreferencesGeoMech.h" + +#include "RiuViewer.h" + +#include "Rim3dView.h" +#include "RimFaultInView.h" +#include "RimFaultReactivationModel.h" + +#include "RivFaultReactivationModelPartMgr.h" + +#include "cvfBoundingBox.h" +#include "cvfModelBasicList.h" + +#include "cafDisplayCoordTransform.h" + +CAF_PDM_SOURCE_INIT( RimFaultReactivationModelCollection, "FaultReactivationModelCollection" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationModelCollection::RimFaultReactivationModelCollection() +{ + CAF_PDM_InitObject( "Fault Reactivation Models", ":/fault_react_24x24.png" ); + + CAF_PDM_InitField( &m_userDescription, "UserDescription", QString( "Fault Reactivation Models" ), "Name" ); + + CAF_PDM_InitFieldNoDefault( &m_models, "FaultReactivationModels", "Models" ); + m_models.uiCapability()->setUiTreeHidden( true ); + + setName( "Fault Reactivation Models" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationModelCollection::~RimFaultReactivationModelCollection() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationModel* RimFaultReactivationModelCollection::addNewModel( RimFaultInView* fault, cvf::Vec3d target1, cvf::Vec3d target2 ) +{ + auto newModel = new RimFaultReactivationModel(); + newModel->setFault( fault ); + newModel->setUserDescription( fault->name() ); + newModel->setTargets( target1, target2 ); + + m_models.push_back( newModel ); + + newModel->updateVisualization(); + + // updateView(); + return newModel; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationModelCollection::empty() +{ + return m_models.empty(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RimFaultReactivationModelCollection::size() +{ + return static_cast( m_models.size() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimFaultReactivationModelCollection::userDescription() +{ + return m_userDescription; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModelCollection::setUserDescription( QString description ) +{ + m_userDescription = description; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimFaultReactivationModelCollection::userDescriptionField() +{ + return &m_userDescription; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModelCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + uiOrdering.skipRemainingFields( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModelCollection::fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) +{ + if ( changedField == objectToggleField() ) + { + updateView(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModelCollection::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, + std::vector& referringObjects ) +{ + updateView(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModelCollection::updateView() +{ + auto view = firstAncestorOrThisOfType(); + if ( view ) view->scheduleCreateDisplayModelAndRedraw(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationModelCollection::shouldBeVisibleInTree() const +{ + return RiaPreferencesGeoMech::current()->validateFRMSettings(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModelCollection::appendPartsToModel( Rim3dView* view, + cvf::ModelBasicList* model, + caf::DisplayCoordTransform* transform, + const cvf::BoundingBox& boundingBox ) +{ + if ( !isChecked() ) return; + + for ( auto& frm : m_models ) + { + if ( frm->isChecked() ) + { + frm->partMgr()->appendPolylinePartsToModel( view, model, transform, boundingBox ); + frm->partMgr()->appendGeometryPartsToModel( model, transform, boundingBox ); + frm->partMgr()->appendMeshPartsToModel( view, model, transform, boundingBox ); + } + } + + model->updateBoundingBoxesRecursive(); +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.h new file mode 100644 index 0000000000..ca9a5ab0de --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.h @@ -0,0 +1,81 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include "RimCheckableNamedObject.h" + +#include "cafPdmChildArrayField.h" +#include "cafPdmField.h" + +#include "cvfVector3.h" + +#include + +class RimFaultReactivationModel; +class RimFaultInView; +class Rim3dView; + +namespace cvf +{ +class ModelBasicList; +class Transform; +class BoundingBox; +} // namespace cvf + +namespace caf +{ +class DisplayCoordTransform; +} + +class RimFaultReactivationModelCollection : public RimCheckableNamedObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimFaultReactivationModelCollection(); + ~RimFaultReactivationModelCollection() override; + + RimFaultReactivationModel* addNewModel( RimFaultInView* fault, cvf::Vec3d target1, cvf::Vec3d target2 ); + + bool empty(); + int size(); + + bool shouldBeVisibleInTree() const; + + QString userDescription(); + void setUserDescription( QString description ); + + void appendPartsToModel( Rim3dView* view, + cvf::ModelBasicList* model, + caf::DisplayCoordTransform* transform, + const cvf::BoundingBox& boundingBox ); + +protected: + caf::PdmFieldHandle* userDescriptionField() override; + + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + + void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector& referringObjects ) override; + + void updateView(); + +private: + caf::PdmField m_userDescription; + caf::PdmChildArrayField m_models; +}; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp index e008ae6365..3f114746d7 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp @@ -56,6 +56,7 @@ #include "RimElementVectorResult.h" #include "RimExtrudedCurveIntersection.h" #include "RimFaultInViewCollection.h" +#include "RimFaultReactivationModelCollection.h" #include "RimFlowCharacteristicsPlot.h" #include "RimFlowDiagSolution.h" #include "RimFracture.h" @@ -172,6 +173,10 @@ RimEclipseView::RimEclipseView() m_faultCollection = new RimFaultInViewCollection; m_faultCollection.uiCapability()->setUiTreeHidden( true ); + CAF_PDM_InitFieldNoDefault( &m_faultReactivationModelCollection, "FaultReactivationModelCollection", "Fault Reactivation Models" ); + m_faultReactivationModelCollection = new RimFaultReactivationModelCollection; + m_faultReactivationModelCollection.uiCapability()->setUiTreeHidden( true ); + CAF_PDM_InitFieldNoDefault( &m_annotationCollection, "AnnotationCollection", "Annotations" ); m_annotationCollection = new RimAnnotationInViewCollection; m_annotationCollection.uiCapability()->setUiTreeHidden( true ); @@ -220,6 +225,9 @@ RimEclipseView::RimEclipseView() setDeletable( true ); updateAnimations.connect( this, &RimEclipseView::onAnimationsUpdate ); + + m_faultReactVizModel = new cvf::ModelBasicList; + m_faultReactVizModel->setName( "FaultReactModel" ); } //-------------------------------------------------------------------------------------------------- @@ -306,6 +314,14 @@ RimFaultInViewCollection* RimEclipseView::faultCollection() const return m_faultCollection; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationModelCollection* RimEclipseView::faultReactivationModelCollection() const +{ + return m_faultReactivationModelCollection; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -598,6 +614,12 @@ void RimEclipseView::onCreateDisplayModel() m_seismicSectionCollection->appendPartsToModel( this, m_seismicVizModel.p(), transform.p(), ownerCase()->allCellsBoundingBox() ); nativeOrOverrideViewer()->addStaticModelOnce( m_seismicVizModel.p(), isUsingOverrideViewer() ); + // Fault reactivation models + + m_faultReactVizModel->removeAllParts(); + m_faultReactivationModelCollection->appendPartsToModel( this, m_faultReactVizModel.p(), transform.p(), ownerCase()->allCellsBoundingBox() ); + nativeOrOverrideViewer()->addStaticModelOnce( m_faultReactVizModel.p(), isUsingOverrideViewer() ); + // Surfaces m_surfaceVizModel->removeAllParts(); if ( surfaceInViewCollection() ) @@ -1879,25 +1901,21 @@ void RimEclipseView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin uiTreeOrdering.add( wellCollection() ); { - bool showFractureColors = false; - std::vector fractures = m_wellCollection->descendantsIncludingThisOfType(); auto otherFractures = wellPathCollection()->descendantsIncludingThisOfType(); fractures.insert( fractures.end(), otherFractures.begin(), otherFractures.end() ); if ( !fractures.empty() ) - { - showFractureColors = true; - } - - if ( showFractureColors ) { uiTreeOrdering.add( fractureColors() ); } } uiTreeOrdering.add( faultCollection() ); + + if ( faultReactivationModelCollection()->shouldBeVisibleInTree() ) uiTreeOrdering.add( faultReactivationModelCollection() ); + uiTreeOrdering.add( annotationCollection() ); uiTreeOrdering.add( intersectionCollection() ); diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.h b/ApplicationLibCode/ProjectDataModel/RimEclipseView.h index a7d5218d05..847122b191 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.h +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.h @@ -68,6 +68,7 @@ class RimElementVectorResult; class RimStreamlineInViewCollection; class RimMultipleEclipseResults; class RigEclipseResultAddress; +class RimFaultReactivationModelCollection; namespace cvf { @@ -91,15 +92,16 @@ public: RiaDefines::View3dContent viewContent() const override; - RimEclipseCellColors* cellResult() const; - RimCellEdgeColors* cellEdgeResult() const; - RimElementVectorResult* elementVectorResult() const; - RimEclipseFaultColors* faultResultSettings() const; - RimStimPlanColors* fractureColors() const; - RimSimWellInViewCollection* wellCollection() const; - RimFaultInViewCollection* faultCollection() const; - RimVirtualPerforationResults* virtualPerforationResult() const; - RimStreamlineInViewCollection* streamlineCollection() const; + RimEclipseCellColors* cellResult() const; + RimCellEdgeColors* cellEdgeResult() const; + RimElementVectorResult* elementVectorResult() const; + RimEclipseFaultColors* faultResultSettings() const; + RimStimPlanColors* fractureColors() const; + RimSimWellInViewCollection* wellCollection() const; + RimFaultInViewCollection* faultCollection() const; + RimVirtualPerforationResults* virtualPerforationResult() const; + RimStreamlineInViewCollection* streamlineCollection() const; + RimFaultReactivationModelCollection* faultReactivationModelCollection() const; bool showInvalidCells() const; bool showInactiveCells() const; @@ -215,6 +217,9 @@ private: void setVisibleGridParts( const std::vector& cellSets ); void setVisibleGridPartsWatertight(); +protected: + cvf::ref m_faultReactVizModel; + private: caf::PdmField m_showInvalidCells; caf::PdmField m_showInactiveCells; @@ -228,9 +233,10 @@ private: caf::PdmProxyValueField> m_cellResultData; - caf::PdmChildField m_wellCollection; - caf::PdmChildField m_faultCollection; - caf::PdmChildField m_streamlineCollection; + caf::PdmChildField m_wellCollection; + caf::PdmChildField m_faultCollection; + caf::PdmChildField m_faultReactivationModelCollection; + caf::PdmChildField m_streamlineCollection; caf::PdmChildField m_propertyFilterCollection; caf::PdmPointer m_overridePropertyFilterCollection; diff --git a/ApplicationLibCode/ProjectDataModel/RimTools.cpp b/ApplicationLibCode/ProjectDataModel/RimTools.cpp index 3605bfded8..fcb48b37e1 100644 --- a/ApplicationLibCode/ProjectDataModel/RimTools.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimTools.cpp @@ -29,6 +29,8 @@ #include "RimColorLegend.h" #include "RimColorLegendCollection.h" #include "RimEclipseCase.h" +#include "RimFaultInView.h" +#include "RimFaultInViewCollection.h" #include "RimGeoMechCase.h" #include "RimOilField.h" #include "RimProject.h" @@ -581,3 +583,17 @@ void RimTools::optionItemsForSpecifiedWellPaths( const std::vector options->push_back( caf::PdmOptionItemInfo( wellPath->name(), wellPath, false, wellIcon ) ); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTools::faultOptionItems( QList* options, RimFaultInViewCollection* coll ) +{ + if ( !options ) return; + if ( !coll ) return; + + for ( auto& f : coll->faults() ) + { + options->push_back( caf::PdmOptionItemInfo( f->name(), f, false, f->uiIconProvider() ) ); + } +} diff --git a/ApplicationLibCode/ProjectDataModel/RimTools.h b/ApplicationLibCode/ProjectDataModel/RimTools.h index 4ae40e3656..187e5d684f 100644 --- a/ApplicationLibCode/ProjectDataModel/RimTools.h +++ b/ApplicationLibCode/ProjectDataModel/RimTools.h @@ -40,6 +40,7 @@ class RimWellPathCollection; class RimCase; class RimWellPath; class RimSurfaceCollection; +class RimFaultInViewCollection; //-------------------------------------------------------------------------------------------------- /// @@ -69,6 +70,8 @@ public: static void seismicDataOptionItems( QList* options, cvf::BoundingBox worldBBox, bool basicDataOnly = false ); static void seismicDataOptionItems( QList* options ); + static void faultOptionItems( QList* options, RimFaultInViewCollection* coll ); + static RimWellPathCollection* wellPathCollection(); static RimWellPath* firstWellPath(); diff --git a/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake index 5454e285fe..8b0a2d36e5 100644 --- a/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake @@ -89,6 +89,9 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RigTexturedSection.h ${CMAKE_CURRENT_LIST_DIR}/RigPressureDepthData.h ${CMAKE_CURRENT_LIST_DIR}/RigMswCenterLineCalculator.h + ${CMAKE_CURRENT_LIST_DIR}/RigBasicPlane.h + ${CMAKE_CURRENT_LIST_DIR}/RigGriddedPart3d.h + ${CMAKE_CURRENT_LIST_DIR}/RigFaultReactivationModel.h ${CMAKE_CURRENT_LIST_DIR}/RigWellAllocationOverTime.h ${CMAKE_CURRENT_LIST_DIR}/RigWellResultBranch.h ${CMAKE_CURRENT_LIST_DIR}/RigWellResultFrame.h @@ -178,6 +181,9 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RigTexturedSection.cpp ${CMAKE_CURRENT_LIST_DIR}/RigPressureDepthData.cpp ${CMAKE_CURRENT_LIST_DIR}/RigMswCenterLineCalculator.cpp + ${CMAKE_CURRENT_LIST_DIR}/RigBasicPlane.cpp + ${CMAKE_CURRENT_LIST_DIR}/RigGriddedPart3d.cpp + ${CMAKE_CURRENT_LIST_DIR}/RigFaultReactivationModel.cpp ${CMAKE_CURRENT_LIST_DIR}/RigWellAllocationOverTime.cpp ${CMAKE_CURRENT_LIST_DIR}/RigWellResultBranch.cpp ${CMAKE_CURRENT_LIST_DIR}/RigWellResultFrame.cpp diff --git a/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.cpp b/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.cpp new file mode 100644 index 0000000000..e87b5b553e --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.cpp @@ -0,0 +1,167 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigBasicPlane.h" + +#include "cvfTextureImage.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigBasicPlane::RigBasicPlane() + : m_isRectValid( false ) + , m_maxHorzExtent( 0.0 ) + , m_maxVertExtentAbove( 0.0 ) + , m_maxVertExtentBelow( 0.0 ) +{ + m_texture = new cvf::TextureImage(); + m_texture->allocate( 1, 1 ); + m_texture->fill( cvf::Color4ub( 0, 0, 0, 0 ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigBasicPlane::~RigBasicPlane() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigBasicPlane::reset() +{ + m_isRectValid = false; + m_rect.clear(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigBasicPlane::isValid() const +{ + return m_isRectValid; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigBasicPlane::setPlane( cvf::Vec3d anchorPoint, cvf::Vec3d normal ) +{ + m_planeAnchor = anchorPoint; + m_planeNormal = normal; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigBasicPlane::setColor( cvf::Color3f color ) +{ + m_color = color; + m_texture->fill( cvf::Color4ub( color.rByte(), color.gByte(), color.bByte(), 255 ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigBasicPlane::setMaxExtentFromAnchor( double maxExtentHorz, double maxExtentVertAbove, double maxExtentVertBelow ) +{ + m_maxHorzExtent = maxExtentHorz; + m_maxVertExtentAbove = maxExtentVertAbove; + m_maxVertExtentBelow = maxExtentVertBelow; +} + +//-------------------------------------------------------------------------------------------------- +/// ti +/// 1 ----------- 2 +/// | | +/// ml | | mr +/// | | +/// 0 ----------- 3 +/// bi +//-------------------------------------------------------------------------------------------------- +void RigBasicPlane::updateRect() +{ + if ( ( m_maxHorzExtent <= 0.0 ) || ( m_maxVertExtentAbove <= 0.0 ) || ( m_maxVertExtentBelow <= 0.0 ) ) + { + m_isRectValid = false; + return; + } + + cvf::Vec3d zDirection( 0, 0, 1 ); + + auto alongPlane = m_planeNormal ^ zDirection; + auto upwards = m_planeNormal ^ alongPlane; + + upwards.normalize(); + alongPlane.normalize(); + + const double extHorz = m_maxHorzExtent / 2.0; + auto ml = m_planeAnchor + alongPlane * extHorz; + auto mr = m_planeAnchor - alongPlane * extHorz; + + m_rect.resize( 4 ); + m_rect[0] = ml - upwards * m_maxVertExtentAbove; + m_rect[1] = ml + upwards * m_maxVertExtentBelow; + m_rect[2] = mr + upwards * m_maxVertExtentBelow; + m_rect[3] = mr - upwards * m_maxVertExtentAbove; + + m_isRectValid = true; + + m_topIntersect = m_planeAnchor - upwards * m_maxVertExtentAbove; + m_bottomIntersect = m_planeAnchor + upwards * m_maxVertExtentBelow; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3dArray RigBasicPlane::rect() const +{ + return m_rect; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigBasicPlane::texture() const +{ + return m_texture; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigBasicPlane::maxDepth() +{ + if ( !m_isRectValid ) return 0.0; + + double maxdepth = 0.0; + for ( auto p : m_rect ) + { + maxdepth = std::max( maxdepth, std::abs( p.z() ) ); + } + return maxdepth; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RigBasicPlane::intersectTopBottomLine() +{ + return std::make_pair( m_topIntersect, m_bottomIntersect ); +} diff --git a/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.h b/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.h new file mode 100644 index 0000000000..28e31d639a --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.h @@ -0,0 +1,75 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfArray.h" +#include "cvfColor3.h" +#include "cvfObject.h" +#include "cvfPlane.h" +#include "cvfVector3.h" + +#include +#include + +namespace cvf +{ +class TextureImage; +} + +//================================================================================================== +/// +/// +//================================================================================================== +class RigBasicPlane : public cvf::Object +{ +public: + RigBasicPlane(); + ~RigBasicPlane() override; + + bool isValid() const; + void reset(); + + void updateRect(); + + void setPlane( cvf::Vec3d anchorPoint, cvf::Vec3d normal ); + void setMaxExtentFromAnchor( double maxExtentHorz, double maxExtentVertAbove, double maxExtentVertBelow ); + void setColor( cvf::Color3f color ); + + double maxDepth(); + std::pair intersectTopBottomLine(); + + cvf::Vec3dArray rect() const; + cvf::ref texture() const; + +private: + cvf::Vec3d m_planeNormal; + cvf::Vec3d m_planeAnchor; + + double m_maxHorzExtent; + double m_maxVertExtentAbove; + double m_maxVertExtentBelow; + + cvf::Vec3d m_topIntersect; + cvf::Vec3d m_bottomIntersect; + + cvf::Vec3dArray m_rect; + bool m_isRectValid; + cvf::Color3f m_color; + cvf::ref m_texture; +}; diff --git a/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.cpp b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.cpp new file mode 100644 index 0000000000..25a15b7808 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.cpp @@ -0,0 +1,308 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigFaultReactivationModel.h" + +#include "RigGriddedPart3d.h" +#include "RigPolyLinesData.h" + +#include "cvfTextureImage.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigFaultReactivationModel::RigFaultReactivationModel() + : m_maxZ( 0 ) + , m_minZ( 0 ) + , m_maxHorzExtent( 0 ) + , m_isValid( false ) + , m_cellCountHorzPart1( 1 ) + , m_cellCountHorzPart2( 1 ) + , m_cellCountVertUpper( 1 ) + , m_cellCountVertMiddle( 1 ) + , m_cellCountVertLower( 1 ) + +{ + for ( auto part : allModelParts() ) + { + m_parts[part] = RigFRModelPart(); + m_parts[part].texture = new cvf::TextureImage(); + m_parts[part].texture->allocate( 1, 1 ); + m_parts[part].texture->fill( cvf::Color4ub( 0, 0, 0, 0 ) ); + m_parts[part].rect.reserve( 4 ); + } + + m_cornerIndexes[ModelParts::HiPart1] = { 2, 3, 7, 6 }; + m_cornerIndexes[ModelParts::MidPart1] = { 1, 2, 6, 5 }; + m_cornerIndexes[ModelParts::LowPart1] = { 0, 1, 5, 4 }; + + m_cornerIndexes[ModelParts::HiPart2] = { 6, 7, 11, 10 }; + m_cornerIndexes[ModelParts::MidPart2] = { 5, 6, 10, 9 }; + m_cornerIndexes[ModelParts::LowPart2] = { 4, 5, 9, 8 }; + + for ( auto part : allGridParts() ) + { + m_3dparts[part] = std::make_shared(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigFaultReactivationModel::~RigFaultReactivationModel() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigFaultReactivationModel::allModelParts() const +{ + return { ModelParts::HiPart1, ModelParts::MidPart1, ModelParts::LowPart1, ModelParts::HiPart2, ModelParts::MidPart2, ModelParts::LowPart2 }; +} + +std::vector RigFaultReactivationModel::allGridParts() const +{ + return { GridPart::PART1, GridPart::PART2 }; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModel::reset() +{ + m_isValid = false; + for ( auto part : allModelParts() ) + { + m_parts[part].rect.clear(); + m_parts[part].rect.reserve( 4 ); + } + + for ( auto part : allGridParts() ) + { + m_3dparts[part]->reset(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigFaultReactivationModel::isValid() const +{ + return m_isValid; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModel::setPlane( cvf::Vec3d anchorPoint, cvf::Vec3d normal ) +{ + m_planeAnchor = anchorPoint; + m_planeNormal = normal; + reset(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModel::setPartColors( cvf::Color3f part1Color, cvf::Color3f part2Color ) +{ + for ( auto part : { ModelParts::HiPart1, ModelParts::MidPart1, ModelParts::LowPart1 } ) + { + m_parts[part].texture->fill( cvf::Color4ub( part1Color.rByte(), part1Color.gByte(), part1Color.bByte(), 255 ) ); + } + + for ( auto part : { ModelParts::HiPart2, ModelParts::MidPart2, ModelParts::LowPart2 } ) + { + m_parts[part].texture->fill( cvf::Color4ub( part2Color.rByte(), part2Color.gByte(), part2Color.bByte(), 255 ) ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModel::setMaxExtentFromAnchor( double maxExtentHorz, double minZ, double maxZ ) +{ + m_maxHorzExtent = maxExtentHorz; + m_minZ = minZ; + m_maxZ = maxZ; + reset(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModel::setFaultPlaneIntersect( cvf::Vec3d faultPlaneTop, cvf::Vec3d faultPlaneBottom ) +{ + m_faultPlaneIntersectBottom = faultPlaneBottom; + m_faultPlaneIntersectTop = faultPlaneTop; + + reset(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModel::setCellCounts( int horzPart1, int horzPart2, int vertUpper, int vertMiddle, int vertLower ) +{ + m_cellCountHorzPart1 = horzPart1; + m_cellCountHorzPart2 = horzPart2; + m_cellCountVertUpper = vertUpper; + m_cellCountVertMiddle = vertMiddle; + m_cellCountVertLower = vertLower; + + reset(); +} + +//-------------------------------------------------------------------------------------------------- +/// 7 +/// 3----------|----------- 11 +/// | | | +/// | | | +/// | | | +/// 2|---------|----------| 10 +/// | \6 | +/// | X Anchor | +/// | \ | +/// 1-------------|------- 9 +/// | 5| | +/// | | | +/// | | | +/// | | | +/// 0-------------|-------- 8 +/// 4 +/// +/// +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModel::updateRects() +{ + reset(); + + if ( ( m_maxHorzExtent <= 0.0 ) || ( m_minZ == m_maxZ ) ) + { + return; + } + + cvf::Vec3d zDir( 0, 0, 1 ); + + auto alongPlane = m_planeNormal ^ zDir; + alongPlane.normalize(); + + // how far from anchor point we should stop + const double extHorz = m_maxHorzExtent / 2.0; + auto mr = m_planeAnchor + alongPlane * extHorz; + auto ml = m_planeAnchor - alongPlane * extHorz; + + cvf::Vec3dArray points; + points.resize( 12 ); + + points[0] = ml; + points[0].z() = -m_maxZ; + + points[1] = ml; + points[1].z() = m_faultPlaneIntersectBottom.z(); + + points[2] = ml; + points[2].z() = m_faultPlaneIntersectTop.z(); + + points[3] = ml; + points[3].z() = -m_minZ; + + points[4] = m_faultPlaneIntersectBottom; + points[4].z() = -m_maxZ; + + points[5] = m_faultPlaneIntersectBottom; + points[6] = m_faultPlaneIntersectTop; + + points[7] = m_faultPlaneIntersectTop; + points[7].z() = -m_minZ; + + points[8] = mr; + points[8].z() = -m_maxZ; + + points[9] = mr; + points[9].z() = m_faultPlaneIntersectBottom.z(); + + points[10] = mr; + points[10].z() = m_faultPlaneIntersectTop.z(); + + points[11] = mr; + points[11].z() = -m_minZ; + + for ( auto part : allModelParts() ) + { + for ( auto i : m_cornerIndexes[part] ) + { + m_parts[part].rect.push_back( points[i] ); + } + } + + m_isValid = true; + + generateGrids( points ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigFaultReactivationModel::rect( ModelParts part ) const +{ + return m_parts.at( part ).rect; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigFaultReactivationModel::texture( ModelParts part ) const +{ + return m_parts.at( part ).texture; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector>& RigFaultReactivationModel::meshLines( GridPart part ) const +{ + return m_3dparts.at( part )->meshLines(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModel::generateGrids( cvf::Vec3dArray points ) +{ + m_3dparts[GridPart::PART1]->generateGeometry( { points[0], points[1], points[2], points[3], points[4], points[5], points[6], points[7] }, + m_cellCountHorzPart1, + m_cellCountVertLower, + m_cellCountVertMiddle, + m_cellCountVertUpper ); + m_3dparts[GridPart::PART2]->generateGeometry( { points[8], points[9], points[10], points[11], points[4], points[5], points[6], points[7] }, + m_cellCountHorzPart2, + m_cellCountVertLower, + m_cellCountVertMiddle, + m_cellCountVertUpper ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::shared_ptr RigFaultReactivationModel::grid( GridPart part ) const +{ + return m_3dparts.at( part ); +} diff --git a/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.h b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.h new file mode 100644 index 0000000000..e8ef619fbb --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.h @@ -0,0 +1,124 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfArray.h" +#include "cvfColor3.h" +#include "cvfObject.h" +#include "cvfPlane.h" +#include "cvfVector3.h" + +#include +#include +#include + +namespace cvf +{ +class TextureImage; +} + +class RigGriddedPart3d; + +class RigFRModelPart +{ +public: + RigFRModelPart(){}; + ~RigFRModelPart(){}; + + std::vector rect; + cvf::ref texture; +}; + +//================================================================================================== +/// +/// +//================================================================================================== +class RigFaultReactivationModel : public cvf::Object + +{ +public: + enum class ModelParts + { + HiPart1 = 0, + MidPart1, + LowPart1, + HiPart2, + MidPart2, + LowPart2 + }; + + enum class GridPart + { + PART1, + PART2 + }; + +public: + RigFaultReactivationModel(); + ~RigFaultReactivationModel() override; + + std::vector allModelParts() const; + std::vector allGridParts() const; + + bool isValid() const; + void reset(); + + void setPlane( cvf::Vec3d anchorPoint, cvf::Vec3d normal ); + void setFaultPlaneIntersect( cvf::Vec3d faultPlaneTop, cvf::Vec3d faultPlaneBottom ); + void setMaxExtentFromAnchor( double maxExtentHorz, double minZ, double maxZ ); + + void setCellCounts( int horzPart1, int horzPart2, int vertUpper, int vertMiddle, int vertLower ); + + void updateRects(); + + void setPartColors( cvf::Color3f part1Color, cvf::Color3f part2Color ); + std::vector rect( ModelParts part ) const; + cvf::ref texture( ModelParts part ) const; + + const std::vector>& meshLines( GridPart part ) const; + + std::shared_ptr grid( GridPart part ) const; + +protected: + void generateGrids( cvf::Vec3dArray points ); + +private: + cvf::Vec3d m_planeNormal; + cvf::Vec3d m_planeAnchor; + + cvf::Vec3d m_faultPlaneIntersectTop; + cvf::Vec3d m_faultPlaneIntersectBottom; + + double m_maxHorzExtent; + double m_minZ; + double m_maxZ; + + int m_cellCountHorzPart1; + int m_cellCountHorzPart2; + int m_cellCountVertUpper; + int m_cellCountVertMiddle; + int m_cellCountVertLower; + + std::map> m_cornerIndexes; + + std::map m_parts; + bool m_isValid; + + std::map> m_3dparts; +}; diff --git a/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.cpp b/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.cpp new file mode 100644 index 0000000000..876582b4b8 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.cpp @@ -0,0 +1,275 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigGriddedPart3d.h" + +#include "cvfTextureImage.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigGriddedPart3d::RigGriddedPart3d() + : m_thickness( 10.0 ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigGriddedPart3d::~RigGriddedPart3d() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigGriddedPart3d::reset() +{ + m_borderSurfaceElements.clear(); + m_vertices.clear(); + m_elementIndices.clear(); + m_meshLines.clear(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RigGriddedPart3d::stepVector( cvf::Vec3d start, cvf::Vec3d stop, int nSteps ) +{ + cvf::Vec3d vec = stop - start; + return vec.getNormalized() * ( vec.length() / nSteps ); +} + +//-------------------------------------------------------------------------------------------------- +/// Point index in input +/// +/// +/// 3 ----------- 7 * +/// | | * +/// | | * +/// | | * +/// 2 |---------| 6 * +/// | \ * +/// | \ * +/// | \ * +/// 1 -------------| 5 * +/// | | * +/// | | * +/// | | * +/// | | * +/// 0 -------------- 4 * +/// +/// Assumes 0->4, 1->5, 2->6 and 3->7 is parallel +/// +/// +//-------------------------------------------------------------------------------------------------- +void RigGriddedPart3d::generateGeometry( std::vector inputPoints, int nHorzCells, int nVertCellsLower, int nVertCellsMiddle, int nVertCellsUpper ) +{ + reset(); + + cvf::Vec3d step0to1 = stepVector( inputPoints[0], inputPoints[1], nVertCellsLower ); + cvf::Vec3d step1to2 = stepVector( inputPoints[1], inputPoints[2], nVertCellsMiddle ); + cvf::Vec3d step2to3 = stepVector( inputPoints[2], inputPoints[3], nVertCellsUpper ); + + cvf::Vec3d step4to5 = stepVector( inputPoints[4], inputPoints[5], nVertCellsLower ); + cvf::Vec3d step5to6 = stepVector( inputPoints[5], inputPoints[6], nVertCellsMiddle ); + cvf::Vec3d step6to7 = stepVector( inputPoints[6], inputPoints[7], nVertCellsUpper ); + + cvf::Vec3d step0to4 = stepVector( inputPoints[0], inputPoints[4], nHorzCells ); + + cvf::Vec3d tVec = step0to4 ^ step0to1; + tVec.normalize(); + tVec *= m_thickness; + const std::vector m_thicknessFactors = { -1.0, 0.0, 1.0 }; + const int nThicknessCells = 2; + const int nVertCells = nVertCellsLower + nVertCellsMiddle + nVertCellsUpper; + + const std::vector vertCells = { nVertCellsLower, nVertCellsMiddle, nVertCellsUpper + 1 }; + const std::vector firstSteps = { step0to1, step1to2, step2to3 }; + const std::vector lastSteps = { step4to5, step5to6, step6to7 }; + + // ** generate vertices + + m_vertices.reserve( (size_t)( ( nVertCells + 1 ) * ( nHorzCells + 1 ) ) ); + + cvf::Vec3d p = inputPoints[0]; + cvf::Vec3d pLast = inputPoints[4]; + + for ( int i = 0; i < (int)vertCells.size(); i++ ) + { + for ( int v = 0; v < vertCells[i]; v++ ) + { + cvf::Vec3d stepHorz = stepVector( p, pLast, nHorzCells ); + cvf::Vec3d p2 = p; + for ( int h = 0; h <= nHorzCells; h++ ) + { + for ( int t = 0; t < (int)m_thicknessFactors.size(); t++ ) + { + m_vertices.push_back( p2 + m_thicknessFactors[t] * tVec ); + } + + p2 += stepHorz; + pLast = p2; + } + p += firstSteps[i]; + pLast += lastSteps[i]; + } + } + + // ** generate elements of type hex8 + + m_elementIndices.resize( (size_t)( nVertCells * nHorzCells * nThicknessCells ) ); + + m_borderSurfaceElements[BorderSurface::UpperSurface] = {}; + m_borderSurfaceElements[BorderSurface::FaultSurface] = {}; + m_borderSurfaceElements[BorderSurface::LowerSurface] = {}; + + int layerIndex = 0; + int elementIdx = 0; + + BorderSurface currentRegion = BorderSurface::LowerSurface; + + const int nextLayerIdxOff = ( nHorzCells + 1 ) * ( nThicknessCells + 1 ); + const int nThicknessOff = nThicknessCells + 1; + + for ( int v = 0; v < nVertCells; v++ ) + { + if ( v >= nVertCellsLower ) currentRegion = BorderSurface::FaultSurface; + if ( v >= nVertCellsLower + nVertCellsMiddle ) currentRegion = BorderSurface::UpperSurface; + + int i = layerIndex; + + for ( int h = 0; h < nHorzCells; h++ ) + { + for ( int t = 0; t < nThicknessCells; t++ ) + { + m_elementIndices[elementIdx].push_back( t + i ); + m_elementIndices[elementIdx].push_back( t + i + nThicknessOff ); + m_elementIndices[elementIdx].push_back( t + i + nThicknessOff + 1 ); + m_elementIndices[elementIdx].push_back( t + i + 1 ); + + m_elementIndices[elementIdx].push_back( t + nextLayerIdxOff + i ); + m_elementIndices[elementIdx].push_back( t + nextLayerIdxOff + i + nThicknessOff ); + m_elementIndices[elementIdx].push_back( t + nextLayerIdxOff + i + nThicknessOff + 1 ); + m_elementIndices[elementIdx].push_back( t + nextLayerIdxOff + i + 1 ); + + elementIdx++; + } + i += nThicknessOff; + } + + // add elements to border surface in current region + m_borderSurfaceElements[currentRegion].push_back( elementIdx - 2 ); + m_borderSurfaceElements[currentRegion].push_back( elementIdx - 1 ); + + layerIndex += nextLayerIdxOff; + } + + // generate meshlines for 2d viz + + generateMeshlines( { inputPoints[0], inputPoints[1], inputPoints[5], inputPoints[4] }, nHorzCells, nVertCellsLower ); + generateMeshlines( { inputPoints[1], inputPoints[2], inputPoints[6], inputPoints[5] }, nHorzCells, nVertCellsMiddle ); + generateMeshlines( { inputPoints[2], inputPoints[3], inputPoints[7], inputPoints[6] }, nHorzCells, nVertCellsUpper ); +} + +//-------------------------------------------------------------------------------------------------- +/// Point index in input +/// +/// 1 ____________ 2 +/// | / +/// | / +/// | / +/// | / +/// |_______/ +/// 0 3 +/// +/// Assumes 0->3 and 1->2 is parallel +//-------------------------------------------------------------------------------------------------- +void RigGriddedPart3d::generateMeshlines( std::vector cornerPoints, int numHorzCells, int numVertCells ) +{ + cvf::Vec3d step0to1 = stepVector( cornerPoints[0], cornerPoints[1], numVertCells ); + cvf::Vec3d step0to3 = stepVector( cornerPoints[0], cornerPoints[3], numHorzCells ); + cvf::Vec3d step1to2 = stepVector( cornerPoints[1], cornerPoints[2], numHorzCells ); + cvf::Vec3d step3to2 = stepVector( cornerPoints[3], cornerPoints[2], numVertCells ); + + // horizontal lines + + cvf::Vec3d startP = cornerPoints[0]; + cvf::Vec3d endP = cornerPoints[3]; + + for ( int v = 0; v <= numVertCells; v++ ) + { + m_meshLines.push_back( { startP, endP } ); + startP += step0to1; + endP += step3to2; + } + + // vertical lines + + startP = cornerPoints[0]; + endP = cornerPoints[1]; + + for ( int h = 0; h <= numHorzCells; h++ ) + { + m_meshLines.push_back( { startP, endP } ); + startP += step0to3; + endP += step1to2; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector& RigGriddedPart3d::vertices() const +{ + return m_vertices; +} + +//-------------------------------------------------------------------------------------------------- +/// Output elements will be of type HEX8 +/// +/// 7---------6 +/// /| /| +/// / | / | +/// 4---------5 | z +/// | 3------|--2 | y +/// | / | / | / +/// |/ |/ |/ +/// 0---------1 ----- x +/// +//-------------------------------------------------------------------------------------------------- +const std::vector>& RigGriddedPart3d::elementIndices() const +{ + return m_elementIndices; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::map>& RigGriddedPart3d::borderSurfaceElements() const +{ + return m_borderSurfaceElements; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector>& RigGriddedPart3d::meshLines() const +{ + return m_meshLines; +} diff --git a/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.h b/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.h new file mode 100644 index 0000000000..f6ad4daf49 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.h @@ -0,0 +1,65 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfObject.h" +#include "cvfVector3.h" + +#include +#include + +//================================================================================================== +/// +/// +//================================================================================================== +class RigGriddedPart3d : public cvf::Object +{ +public: + enum class BorderSurface + { + UpperSurface = 0, + FaultSurface, + LowerSurface + }; + +public: + RigGriddedPart3d(); + ~RigGriddedPart3d() override; + + void reset(); + + void generateGeometry( std::vector inputPoints, int nHorzCells, int nVertCellsLower, int nVertCellsMiddle, int nVertCellsUpper ); + + const std::vector& vertices() const; + const std::vector>& elementIndices() const; + const std::map>& borderSurfaceElements() const; + const std::vector>& meshLines() const; + +protected: + cvf::Vec3d stepVector( cvf::Vec3d start, cvf::Vec3d stop, int nSteps ); + void generateMeshlines( std::vector cornerPoints, int numHorzCells, int numVertCells ); + +private: + std::vector m_vertices; + std::vector> m_elementIndices; + std::map> m_borderSurfaceElements; + std::vector> m_meshLines; + + double m_thickness; +}; diff --git a/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp b/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp index 8c37f592d3..aa1659bb75 100644 --- a/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp +++ b/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp @@ -437,17 +437,21 @@ void RiuViewerCommands::displayContextMenu( QMouseEvent* event ) menuBuilder.addSeparator(); QString faultName = fault->name(); - QVariantList hideFaultList; + QVariantList faultDataList; qulonglong currentCellIndex = m_currentCellIndex; - hideFaultList.push_back( currentCellIndex ); - hideFaultList.push_back( m_currentFaceIndex ); + faultDataList.push_back( currentCellIndex ); + faultDataList.push_back( m_currentFaceIndex ); - menuBuilder.addCmdFeatureWithUserData( "RicEclipseHideFaultFeature", QString( "Hide " ) + faultName, hideFaultList ); + menuBuilder.addCmdFeatureWithUserData( "RicEclipseHideFaultFeature", QString( "Hide " ) + faultName, faultDataList ); menuBuilder.addCmdFeatureWithUserData( "RicEclipseShowOnlyFaultFeature", QString( "Show " ) + faultName + QString( " - Others Off" ), QVariant( fault->name() ) ); + menuBuilder.addCmdFeatureWithUserData( "RicNewFaultReactModelingFeature", + QString( "New Fault Re-activation Model" ), + faultDataList ); + menuBuilder.addSeparator(); } }