diff --git a/ApplicationLibCode/Application/RiaApplication.cpp b/ApplicationLibCode/Application/RiaApplication.cpp index 8211705f7d..cc047d06e0 100644 --- a/ApplicationLibCode/Application/RiaApplication.cpp +++ b/ApplicationLibCode/Application/RiaApplication.cpp @@ -40,6 +40,8 @@ #include "RicfCommandObject.h" #include "PlotTemplates/RimPlotTemplateFolderItem.h" +#include "Polygons/RimPolygonCollection.h" + #include "Rim2dIntersectionViewCollection.h" #include "RimAnnotationCollection.h" #include "RimAnnotationInViewCollection.h" @@ -548,6 +550,8 @@ bool RiaApplication::loadProject( const QString& projectFileName, ProjectLoadAct { seismicData->ensureFileReaderIsInitialized(); } + + oilField->polygonCollection()->loadData(); } { diff --git a/ApplicationLibCode/Application/RiaDefines.h b/ApplicationLibCode/Application/RiaDefines.h index 27afa6fd2b..4eaee4a384 100644 --- a/ApplicationLibCode/Application/RiaDefines.h +++ b/ApplicationLibCode/Application/RiaDefines.h @@ -243,8 +243,17 @@ enum class View3dContent ALL = 0b00011111 }; +enum class ItemIn3dView +{ + NONE = 0b00000000, + SURFACE = 0b00000001, + POLYGON = 0b00000010, + ALL = 0b00000011 +}; + }; // namespace RiaDefines // Activate bit mask operators at global scope ENABLE_BITMASK_OPERATORS( RiaDefines::MultiPlotPageUpdateType ) ENABLE_BITMASK_OPERATORS( RiaDefines::View3dContent ) +ENABLE_BITMASK_OPERATORS( RiaDefines::ItemIn3dView ) diff --git a/ApplicationLibCode/CMakeLists.txt b/ApplicationLibCode/CMakeLists.txt index ff62c7ff1c..614b65bcc8 100644 --- a/ApplicationLibCode/CMakeLists.txt +++ b/ApplicationLibCode/CMakeLists.txt @@ -140,6 +140,7 @@ list( ProjectDataModel/Intersections/CMakeLists_files.cmake ProjectDataModel/CellFilters/CMakeLists_files.cmake ProjectDataModel/ProcessControl/CMakeLists_files.cmake + ProjectDataModel/Polygons/CMakeLists_files.cmake ProjectDataModel/WellLog/CMakeLists_files.cmake ProjectDataModel/WellMeasurement/CMakeLists_files.cmake ProjectDataModel/WellPath/CMakeLists_files.cmake diff --git a/ApplicationLibCode/Commands/CMakeLists.txt b/ApplicationLibCode/Commands/CMakeLists.txt index 931eb11e82..740ee78f12 100644 --- a/ApplicationLibCode/Commands/CMakeLists.txt +++ b/ApplicationLibCode/Commands/CMakeLists.txt @@ -41,6 +41,7 @@ set(COMMAND_REFERENCED_CMAKE_FILES PlotTemplateCommands/CMakeLists_files.cmake FractureCommands/CMakeLists_files.cmake PlotBuilderCommands/CMakeLists_files.cmake + PolygonCommands/CMakeLists_files.cmake ) # Include source file lists from *.cmake files diff --git a/ApplicationLibCode/Commands/PolygonCommands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/PolygonCommands/CMakeLists_files.cmake new file mode 100644 index 0000000000..8cd3631c22 --- /dev/null +++ b/ApplicationLibCode/Commands/PolygonCommands/CMakeLists_files.cmake @@ -0,0 +1,19 @@ +set(SOURCE_GROUP_HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/RicAppendPolygonFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicAppendPolygonFileFeature.h +) + +set(SOURCE_GROUP_SOURCE_FILES + ${CMAKE_CURRENT_LIST_DIR}/RicAppendPolygonFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicAppendPolygonFileFeature.cpp +) + +list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) + +list(APPEND COMMAND_CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES}) + +source_group( + "CommandFeature\\Polygons" + FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} + ${CMAKE_CURRENT_LIST_DIR}/CMakeLists_files.cmake +) diff --git a/ApplicationLibCode/Commands/PolygonCommands/RicAppendPolygonFeature.cpp b/ApplicationLibCode/Commands/PolygonCommands/RicAppendPolygonFeature.cpp new file mode 100644 index 0000000000..5c4bc3dfbc --- /dev/null +++ b/ApplicationLibCode/Commands/PolygonCommands/RicAppendPolygonFeature.cpp @@ -0,0 +1,54 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2022 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicAppendPolygonFeature.h" + +#include "Polygons/RimPolygon.h" +#include "Polygons/RimPolygonCollection.h" +#include "RimOilField.h" +#include "RimProject.h" + +#include "RiuPlotMainWindowTools.h" + +#include + +CAF_CMD_SOURCE_INIT( RicAppendPolygonFeature, "RicAppendPolygonFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicAppendPolygonFeature::onActionTriggered( bool isChecked ) +{ + auto proj = RimProject::current(); + auto polygonCollection = proj->activeOilField()->polygonCollection(); + + auto newPolygon = polygonCollection->appendUserDefinedPolygon(); + polygonCollection->uiCapability()->updateAllRequiredEditors(); + + RiuPlotMainWindowTools::setExpanded( newPolygon ); + RiuPlotMainWindowTools::selectAsCurrentItem( newPolygon ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicAppendPolygonFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Append Polygon" ); + actionToSetup->setIcon( QIcon( ":/PolylinesFromFile16x16.png" ) ); +} diff --git a/ApplicationLibCode/Commands/PolygonCommands/RicAppendPolygonFeature.h b/ApplicationLibCode/Commands/PolygonCommands/RicAppendPolygonFeature.h new file mode 100644 index 0000000000..6773df5e44 --- /dev/null +++ b/ApplicationLibCode/Commands/PolygonCommands/RicAppendPolygonFeature.h @@ -0,0 +1,33 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2022 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicAppendPolygonFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/Commands/PolygonCommands/RicAppendPolygonFileFeature.cpp b/ApplicationLibCode/Commands/PolygonCommands/RicAppendPolygonFileFeature.cpp new file mode 100644 index 0000000000..f459516c08 --- /dev/null +++ b/ApplicationLibCode/Commands/PolygonCommands/RicAppendPolygonFileFeature.cpp @@ -0,0 +1,57 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2022 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicAppendPolygonFileFeature.h" + +#include "Polygons/RimPolygon.h" +#include "Polygons/RimPolygonCollection.h" +#include "Polygons/RimPolygonFile.h" +#include "RimOilField.h" +#include "RimProject.h" + +#include "RiuPlotMainWindowTools.h" + +#include + +CAF_CMD_SOURCE_INIT( RicAppendPolygonFileFeature, "RicAppendPolygonFileFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicAppendPolygonFileFeature::onActionTriggered( bool isChecked ) +{ + auto proj = RimProject::current(); + auto polygonCollection = proj->activeOilField()->polygonCollection(); + + auto newPolygonFile = new RimPolygonFile(); + newPolygonFile->setName( "File Polygon " + QString::number( polygonCollection->polygonFiles().size() + 1 ) ); + polygonCollection->addPolygonFile( newPolygonFile ); + polygonCollection->uiCapability()->updateAllRequiredEditors(); + + RiuPlotMainWindowTools::setExpanded( newPolygonFile ); + RiuPlotMainWindowTools::selectAsCurrentItem( newPolygonFile ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicAppendPolygonFileFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Append File Polygon" ); + actionToSetup->setIcon( QIcon( ":/PolylinesFromFile16x16.png" ) ); +} diff --git a/ApplicationLibCode/Commands/PolygonCommands/RicAppendPolygonFileFeature.h b/ApplicationLibCode/Commands/PolygonCommands/RicAppendPolygonFileFeature.h new file mode 100644 index 0000000000..2a5333cb76 --- /dev/null +++ b/ApplicationLibCode/Commands/PolygonCommands/RicAppendPolygonFileFeature.h @@ -0,0 +1,33 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2022 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicAppendPolygonFileFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechView.cpp b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechView.cpp index 7ff399e36a..db9ae62cdb 100644 --- a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechView.cpp +++ b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechView.cpp @@ -31,6 +31,7 @@ #include "RigFormationNames.h" #include "RigGeoMechCaseData.h" +#include "Polygons/RimPolygonInViewCollection.h" #include "Rim3dOverlayInfoConfig.h" #include "RimCellFilterCollection.h" #include "RimEclipseResultDefinition.h" @@ -153,7 +154,7 @@ void RimGeoMechView::onLoadDataAndUpdate() onUpdateScaleTransform(); - updateSurfacesInViewTreeItems(); + updateViewTreeItems( RiaDefines::ItemIn3dView::ALL ); if ( m_geomechCase ) { @@ -319,6 +320,12 @@ void RimGeoMechView::onCreateDisplayModel() m_seismicSectionCollection->appendPartsToModel( this, m_seismicVizModel.p(), transform.p(), femBBox ); nativeOrOverrideViewer()->addStaticModelOnce( m_seismicVizModel.p(), isUsingOverrideViewer() ); + // Polygons + + m_polygonVizModel->removeAllParts(); + m_polygonCollection->appendPartsToModel( m_polygonVizModel.p(), transform.p(), femBBox ); + nativeOrOverrideViewer()->addStaticModelOnce( m_polygonVizModel.p(), isUsingOverrideViewer() ); + // Surfaces m_surfaceVizModel->removeAllParts(); @@ -1043,6 +1050,8 @@ void RimGeoMechView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin if ( surfaceInViewCollection() ) uiTreeOrdering.add( surfaceInViewCollection() ); if ( seismicSectionCollection()->shouldBeVisibleInTree() ) uiTreeOrdering.add( seismicSectionCollection() ); + uiTreeOrdering.add( m_polygonCollection ); + uiTreeOrdering.skipRemainingChildren( true ); } diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/Polygons/CMakeLists_files.cmake new file mode 100644 index 0000000000..af99df45c7 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Polygons/CMakeLists_files.cmake @@ -0,0 +1,27 @@ +set(SOURCE_GROUP_HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/RimPolygon.h + ${CMAKE_CURRENT_LIST_DIR}/RimPolygonFile.h + ${CMAKE_CURRENT_LIST_DIR}/RimPolygonCollection.h + ${CMAKE_CURRENT_LIST_DIR}/RimPolygonInView.h + ${CMAKE_CURRENT_LIST_DIR}/RimPolygonInViewCollection.h + ${CMAKE_CURRENT_LIST_DIR}/RimPolygonAppearance.h +) + +set(SOURCE_GROUP_SOURCE_FILES + ${CMAKE_CURRENT_LIST_DIR}/RimPolygon.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimPolygonFile.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimPolygonCollection.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimPolygonInView.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimPolygonInViewCollection.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimPolygonAppearance.cpp +) + +list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) + +list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES}) + +source_group( + "ProjectDataModel\\Polygons" + FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} + ${CMAKE_CURRENT_LIST_DIR}/CMakeLists_files.cmake +) diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygon.cpp b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygon.cpp new file mode 100644 index 0000000000..c505ac9345 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygon.cpp @@ -0,0 +1,115 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 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 "RimPolygon.h" + +#include "RigPolyLinesData.h" +#include "RimPolygonAppearance.h" + +CAF_PDM_SOURCE_INIT( RimPolygon, "RimPolygon" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPolygon::RimPolygon() + : objectChanged( this ) +{ + CAF_PDM_InitObject( "Polygon", ":/PolylinesFromFile16x16.png" ); + + CAF_PDM_InitField( &m_isReadOnly, "IsReadOnly", false, "Read Only" ); + CAF_PDM_InitFieldNoDefault( &m_pointsInDomainCoords, "PointsInDomainCoords", "Points" ); + CAF_PDM_InitFieldNoDefault( &m_appearance, "Appearance", "Appearance" ); + m_appearance = new RimPolygonAppearance; + m_appearance.uiCapability()->setUiTreeChildrenHidden( true ); + + setDeletable( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RimPolygon::polyLinesData() const +{ + cvf::ref pld = new RigPolyLinesData; + + pld->setPolyLine( m_pointsInDomainCoords() ); + m_appearance->applyAppearanceSettings( pld.p() ); + + return pld; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygon::setPointsInDomainCoords( const std::vector& points ) +{ + m_pointsInDomainCoords = points; + + objectChanged.send(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimPolygon::pointsInDomainCoords() const +{ + return m_pointsInDomainCoords(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimPolygon::isClosed() const +{ + return m_appearance->isClosed(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygon::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + uiOrdering.add( nameField() ); + uiOrdering.add( &m_isReadOnly ); + + auto groupPoints = uiOrdering.addNewGroup( "Points" ); + groupPoints->setCollapsedByDefault(); + groupPoints->add( &m_pointsInDomainCoords ); + + auto group = uiOrdering.addNewGroup( "Appearance" ); + m_appearance->uiOrdering( uiConfigName, *group ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygon::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) +{ + if ( changedField == &m_pointsInDomainCoords ) + { + objectChanged.send(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygon::childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField ) +{ + objectChanged.send(); +} diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygon.h b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygon.h new file mode 100644 index 0000000000..b559d11c9a --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygon.h @@ -0,0 +1,55 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 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 "RimNamedObject.h" + +#include "RimPolylinesDataInterface.h" + +#include "cafPdmFieldCvfVec3d.h" + +#include "cvfVector3.h" + +class RimPolygonAppearance; + +class RimPolygon : public RimNamedObject, public RimPolylinesDataInterface +{ + CAF_PDM_HEADER_INIT; + +public: + caf::Signal<> objectChanged; + +public: + RimPolygon(); + + void setPointsInDomainCoords( const std::vector& points ); + std::vector pointsInDomainCoords() const; + bool isClosed() const; + + cvf::ref polyLinesData() const override; + +protected: + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + void childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField ) override; + +private: + caf::PdmField m_isReadOnly; + caf::PdmField> m_pointsInDomainCoords; + caf::PdmChildField m_appearance; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonAppearance.cpp b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonAppearance.cpp new file mode 100644 index 0000000000..22c4191bad --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonAppearance.cpp @@ -0,0 +1,207 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 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 "RimPolygonAppearance.h" + +#include "RimCase.h" +#include "RimProject.h" + +#include "RigPolyLinesData.h" + +#include "RiaNumericalTools.h" +#include "RiaStdStringTools.h" + +#include "cafPdmUiDoubleSliderEditor.h" +#include "cafPdmUiLineEditor.h" + +#include "cvfBoundingBox.h" + +#include + +CAF_PDM_SOURCE_INIT( RimPolygonAppearance, "RimPolygonAppearance" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class ThicknessValidator : public QValidator +{ +public: + State validate( QString& input, int& pos ) const override + { + if ( input.isEmpty() ) return State::Intermediate; + + int val = RiaStdStringTools::toInt( input.toStdString() ); + if ( val > 0 && val < 8 ) + return State::Acceptable; + else + return State::Invalid; + } +}; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class RadiusValidator : public QValidator +{ +public: + State validate( QString& input, int& pos ) const override + { + if ( input.isEmpty() ) return State::Intermediate; + + double val = RiaStdStringTools::toDouble( input.toStdString() ); + if ( val > 0.001 && val <= 2.0 ) + return State::Acceptable; + else + return State::Invalid; + } +}; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPolygonAppearance::RimPolygonAppearance() + : objectChanged( this ) + +{ + CAF_PDM_InitObject( "Polygon", ":/PolylinesFromFile16x16.png" ); + + CAF_PDM_InitField( &m_isClosed, "IsClosed", false, "Closed Polygon" ); + CAF_PDM_InitField( &m_showLines, "ShowLines", true, "Show Lines" ); + CAF_PDM_InitField( &m_showSpheres, "ShowSpheres", false, "Show Spheres" ); + + CAF_PDM_InitField( &m_lineThickness, "LineThickness", 3, "Line Thickness" ); + CAF_PDM_InitField( &m_sphereRadiusFactor, "SphereRadiusFactor", 0.15, "Sphere Radius Factor" ); + + CAF_PDM_InitField( &m_lineColor, "LineColor", cvf::Color3f( cvf::Color3f::WHITE ), "Line Color" ); + CAF_PDM_InitField( &m_sphereColor, "SphereColor", cvf::Color3f( cvf::Color3f::WHITE ), "Sphere Color" ); + + CAF_PDM_InitField( &m_polygonPlaneDepth, "PolygonPlaneDepth", 0.0, "Polygon Plane Depth" ); + CAF_PDM_InitField( &m_lockPolygonToPlane, "LockPolygon", false, "Lock Polygon to Plane" ); + + m_polygonPlaneDepth.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() ); + m_polygonPlaneDepth.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosType::TOP ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonAppearance::applyAppearanceSettings( RigPolyLinesData* polyLinesData ) +{ + polyLinesData->setLineAppearance( m_lineThickness, m_lineColor, m_isClosed ); + polyLinesData->setSphereAppearance( m_sphereRadiusFactor, m_sphereColor ); + polyLinesData->setZPlaneLock( m_lockPolygonToPlane, -m_polygonPlaneDepth ); + polyLinesData->setVisibility( m_showLines, m_showSpheres ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimPolygonAppearance::isClosed() const +{ + return m_isClosed(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonAppearance::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + uiOrdering.add( &m_showLines ); + if ( m_showLines ) + { + uiOrdering.add( &m_lineThickness ); + uiOrdering.add( &m_lineColor ); + } + + uiOrdering.add( &m_showSpheres ); + if ( m_showSpheres ) + { + uiOrdering.add( &m_sphereRadiusFactor ); + uiOrdering.add( &m_sphereColor ); + } + + uiOrdering.add( &m_lockPolygonToPlane ); + if ( m_lockPolygonToPlane ) + { + uiOrdering.add( &m_polygonPlaneDepth ); + } + + uiOrdering.add( &m_isClosed ); + + uiOrdering.skipRemainingFields(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonAppearance::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) +{ + objectChanged.send(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonAppearance::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) +{ + if ( field == &m_lineThickness ) + { + if ( auto myAttr = dynamic_cast( attribute ) ) + { + myAttr->validator = new ThicknessValidator(); + } + } + else if ( field == &m_lineThickness ) + { + if ( auto myAttr = dynamic_cast( attribute ) ) + { + myAttr->validator = new RadiusValidator(); + } + } + else if ( field == &m_polygonPlaneDepth ) + { + if ( auto attr = dynamic_cast( attribute ) ) + { + auto allCases = RimProject::current()->allGridCases(); + if ( allCases.empty() ) + { + attr->m_minimum = 0; + attr->m_maximum = 10000.0; + } + else + { + double min = std::numeric_limits::max(); + double max = -std::numeric_limits::max(); + + for ( auto gridCase : allCases ) + { + auto bb = gridCase->allCellsBoundingBox(); + + min = std::min( min, bb.min().z() ); + max = std::max( max, bb.max().z() ); + } + + auto adjustedMin = RiaNumericalTools::roundToNumSignificantDigitsFloor( -min, 2 ); + auto adjustedMax = RiaNumericalTools::roundToNumSignificantDigitsCeil( -max, 2 ); + + attr->m_minimum = adjustedMax; + attr->m_maximum = adjustedMin; + } + } + } +} diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonAppearance.h b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonAppearance.h new file mode 100644 index 0000000000..7a2bdd866e --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonAppearance.h @@ -0,0 +1,56 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 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 "cafPdmObject.h" +#include "cvfVector3.h" + +class RigPolyLinesData; + +class RimPolygonAppearance : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + caf::Signal<> objectChanged; + + void applyAppearanceSettings( RigPolyLinesData* polyLinesData ); + + bool isClosed() const; + +public: + RimPolygonAppearance(); + +protected: + 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; + +private: + caf::PdmField m_isClosed; + caf::PdmField m_showLines; + caf::PdmField m_lineThickness; + caf::PdmField m_lineColor; + + caf::PdmField m_showSpheres; + caf::PdmField m_sphereRadiusFactor; + caf::PdmField m_sphereColor; + + caf::PdmField m_lockPolygonToPlane; + caf::PdmField m_polygonPlaneDepth; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonCollection.cpp b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonCollection.cpp new file mode 100644 index 0000000000..7ddf232599 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonCollection.cpp @@ -0,0 +1,205 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 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 "RimPolygonCollection.h" + +#include "Rim3dView.h" +#include "RimPolygon.h" +#include "RimPolygonFile.h" +#include "RimProject.h" + +CAF_PDM_SOURCE_INIT( RimPolygonCollection, "RimPolygonCollection" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPolygonCollection::RimPolygonCollection() +{ + CAF_PDM_InitObject( "Polygons", ":/PolylinesFromFile16x16.png" ); + + CAF_PDM_InitFieldNoDefault( &m_polygons, "Polygons", "Polygons" ); + CAF_PDM_InitFieldNoDefault( &m_polygonFiles, "PolygonFiles", "Polygon Files" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonCollection::loadData() +{ + for ( auto& p : m_polygonFiles() ) + { + p->loadData(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPolygon* RimPolygonCollection::appendUserDefinedPolygon() +{ + auto newPolygon = new RimPolygon(); + newPolygon->setName( "Polygon " + QString::number( userDefinedPolygons().size() + 1 ) ); + addUserDefinedPolygon( newPolygon ); + + return newPolygon; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonCollection::addUserDefinedPolygon( RimPolygon* polygon ) +{ + m_polygons().push_back( polygon ); + + connectSignals( polygon ); + + updateViewTreeItems(); + scheduleRedrawViews(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonCollection::deleteUserDefinedPolygons() +{ + m_polygons().deleteChildren(); + + updateViewTreeItems(); + scheduleRedrawViews(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonCollection::addPolygonFile( RimPolygonFile* polygonFile ) +{ + m_polygonFiles().push_back( polygonFile ); + + updateViewTreeItems(); + scheduleRedrawViews(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimPolygonCollection::userDefinedPolygons() const +{ + return m_polygons.childrenByType(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimPolygonCollection::polygonFiles() const +{ + return m_polygonFiles.childrenByType(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimPolygonCollection::allPolygons() const +{ + std::vector allPolygons; + + for ( auto& p : m_polygonFiles() ) + { + for ( auto& polygon : p->polygons() ) + { + allPolygons.push_back( polygon ); + } + } + + for ( auto& polygon : m_polygons.childrenByType() ) + { + allPolygons.push_back( polygon ); + } + + return allPolygons; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonCollection::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector& referringObjects ) +{ + updateViewTreeItems(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonCollection::childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField ) +{ + scheduleRedrawViews(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonCollection::updateViewTreeItems() +{ + RimProject* proj = RimProject::current(); + + // Make sure the tree items are synchronized + std::vector views; + proj->allViews( views ); + for ( auto view : views ) + { + view->updateViewTreeItems( RiaDefines::ItemIn3dView::POLYGON ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonCollection::scheduleRedrawViews() +{ + RimProject* proj = RimProject::current(); + proj->scheduleCreateDisplayModelAndRedrawAllViews(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonCollection::connectSignals( RimPolygon* polygon ) +{ + if ( polygon ) + { + polygon->objectChanged.connect( this, &RimPolygonCollection::onObjectChanged ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonCollection::onObjectChanged( const caf::SignalEmitter* emitter ) +{ + scheduleRedrawViews(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonCollection::initAfterRead() +{ + for ( auto& p : m_polygons() ) + { + connectSignals( p ); + } +} diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonCollection.h b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonCollection.h new file mode 100644 index 0000000000..4246dae416 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonCollection.h @@ -0,0 +1,65 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 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 "cafPdmChildArrayField.h" +#include "cafPdmObject.h" + +class RimPolygon; +class RimPolygonFile; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimPolygonCollection : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimPolygonCollection(); + + void loadData(); + RimPolygon* appendUserDefinedPolygon(); + void addUserDefinedPolygon( RimPolygon* polygon ); + void deleteUserDefinedPolygons(); + + void addPolygonFile( RimPolygonFile* polygonFile ); + + std::vector userDefinedPolygons() const; + std::vector polygonFiles() const; + std::vector allPolygons() const; + + void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector& referringObjects ) override; + + void childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField ) override; + +private: + void updateViewTreeItems(); + void scheduleRedrawViews(); + void connectSignals( RimPolygon* polygon ); + void onObjectChanged( const caf::SignalEmitter* emitter ); + +private: + caf::PdmChildArrayField m_polygons; + caf::PdmChildArrayField m_polygonFiles; + +protected: + void initAfterRead() override; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonFile.cpp b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonFile.cpp new file mode 100644 index 0000000000..cec7ec8160 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonFile.cpp @@ -0,0 +1,82 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 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 "RimPolygonFile.h" +#include "RimPolygon.h" + +CAF_PDM_SOURCE_INIT( RimPolygonFile, "RimPolygonFileFile" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPolygonFile::RimPolygonFile() +{ + CAF_PDM_InitObject( "PolygonFile", ":/PolylinesFromFile16x16.png" ); + + CAF_PDM_InitFieldNoDefault( &m_fileName, "StimPlanFileName", "File Name" ); + CAF_PDM_InitFieldNoDefault( &m_polygons, "Polygons", "Polygons" ); + + setDeletable( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonFile::loadData() +{ + loadPolygonsFromFile(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimPolygonFile::polygons() const +{ + return m_polygons.childrenByType(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonFile::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonFile::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) +{ + loadPolygonsFromFile(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonFile::loadPolygonsFromFile() +{ + // m_polygons()->deletePolygons(); + + auto polygon = new RimPolygon(); + polygon->setName( "Polygon 1" ); + m_polygons.push_back( polygon ); + + polygon = new RimPolygon(); + polygon->setName( "Polygon 2" ); + m_polygons.push_back( polygon ); +} diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonFile.h b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonFile.h new file mode 100644 index 0000000000..540f9ce32c --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonFile.h @@ -0,0 +1,49 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 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 "RimNamedObject.h" + +#include "cafFilePath.h" +#include "cafPdmChildArrayField.h" + +class RimPolygon; + +class RimPolygonFile : public RimNamedObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimPolygonFile(); + + void loadData(); + + std::vector polygons() const; + +protected: + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + +private: + void loadPolygonsFromFile(); + +private: + caf::PdmField m_fileName; + + caf::PdmChildArrayField m_polygons; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonInView.cpp b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonInView.cpp new file mode 100644 index 0000000000..c4b1c44534 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonInView.cpp @@ -0,0 +1,362 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 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 "RimPolygonInView.h" + +#include "RigPolyLinesData.h" + +#include "Rim3dView.h" +#include "RimPolygon.h" +#include "RimTools.h" + +#include "WellPathCommands/PointTangentManipulator/RicPolyline3dEditor.h" +#include "WellPathCommands/RicPolylineTargetsPickEventHandler.h" + +#include "RiuGuiTheme.h" + +#include "RivPolylinePartMgr.h" + +#include "cafCmdFeatureMenuBuilder.h" +#include "cafDisplayCoordTransform.h" +#include "cafPdmUiPushButtonEditor.h" +#include "cafPdmUiTableViewEditor.h" + +#include "cvfModelBasicList.h" + +CAF_PDM_SOURCE_INIT( RimPolygonInView, "RimPolygonInView" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPolygonInView::RimPolygonInView() + : m_pickTargetsEventHandler( new RicPolylineTargetsPickEventHandler( this ) ) +{ + CAF_PDM_InitObject( "Polygon", ":/PolylinesFromFile16x16.png" ); + + CAF_PDM_InitFieldNoDefault( &m_polygon, "Polygon", "Polygon" ); + m_polygon.uiCapability()->setUiReadOnly( true ); + + nameField()->uiCapability()->setUiReadOnly( true ); + + CAF_PDM_InitField( &m_enablePicking, "EnablePicking", false, "" ); + caf::PdmUiPushButtonEditor::configureEditorForField( &m_enablePicking ); + m_enablePicking.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosType::HIDDEN ); + + CAF_PDM_InitFieldNoDefault( &m_targets, "Targets", "Targets" ); + m_targets.uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() ); + // m_targets.uiCapability()->setUiTreeHidden(true); + m_targets.uiCapability()->setUiTreeChildrenHidden( true ); + m_targets.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); + m_targets.uiCapability()->setCustomContextMenuEnabled( true ); + + setUi3dEditorTypeName( RicPolyline3dEditor::uiEditorTypeName() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPolygon* RimPolygonInView::polygon() const +{ + return m_polygon(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::setPolygon( RimPolygon* polygon ) +{ + m_polygon = polygon; + + updateTargetsFromPolygon(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::appendPartsToModel( cvf::ModelBasicList* model, + const caf::DisplayCoordTransform* scaleTransform, + const cvf::BoundingBox& boundingBox ) +{ + auto view = firstAncestorOfType(); + + if ( m_polylinePartMgr.isNull() ) m_polylinePartMgr = new RivPolylinePartMgr( view, this, this ); + + m_polylinePartMgr->appendDynamicGeometryPartsToModel( model, scaleTransform, boundingBox ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::enablePicking( bool enable ) +{ + m_enablePicking = enable; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::insertTarget( const RimPolylineTarget* targetToInsertBefore, RimPolylineTarget* targetToInsert ) +{ + size_t index = m_targets.indexOf( targetToInsertBefore ); + if ( index < m_targets.size() ) + m_targets.insert( index, targetToInsert ); + else + m_targets.push_back( targetToInsert ); + + updatePolygonFromTargets(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::deleteTarget( RimPolylineTarget* targetToDelete ) +{ + m_targets.removeChild( targetToDelete ); + delete targetToDelete; + + updatePolygonFromTargets(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::updateEditorsAndVisualization() +{ + updateConnectedEditors(); + updateVisualization(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::updateVisualization() +{ + auto view = firstAncestorOfType(); + if ( view ) + { + view->scheduleCreateDisplayModelAndRedraw(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimPolygonInView::activeTargets() const +{ + return m_targets.childrenByType(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimPolygonInView::pickingEnabled() const +{ + return m_enablePicking(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PickEventHandler* RimPolygonInView::pickEventHandler() const +{ + return m_pickTargetsEventHandler.get(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::onChildrenUpdated( caf::PdmChildArrayFieldHandle* childArray, std::vector& updatedObjects ) +{ + if ( childArray == &m_targets ) + { + updatePolygonFromTargets(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RimPolygonInView::polyLinesData() const +{ + if ( m_polygon ) + { + return m_polygon->polyLinesData(); + } + + return nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::updatePolygonFromTargets() +{ + if ( m_polygon ) + { + std::vector points; + for ( const RimPolylineTarget* target : m_targets ) + { + points.push_back( target->targetPointXYZ() ); + } + m_polygon->setPointsInDomainCoords( points ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::updateTargetsFromPolygon() +{ + if ( m_polygon ) + { + m_targets.deleteChildren(); + + for ( const auto& p : m_polygon->pointsInDomainCoords() ) + { + auto target = new RimPolylineTarget(); + target->setAsPointXYZ( p ); + + m_targets.push_back( target ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + updateNameField(); + + if ( m_polygon() ) uiOrdering.add( m_polygon ); + uiOrdering.add( &m_enablePicking ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) +{ + if ( changedField == &m_enablePicking ) + { + updateConnectedEditors(); + } + + updateVisualization(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimPolygonInView::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) +{ + QList options; + if ( fieldNeedingOptions == &m_polygon ) + { + options.push_back( caf::PdmOptionItemInfo( "None", nullptr ) ); + + RimTools::polygonOptionItems( &options ); + } + + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) +{ + if ( auto attrib = dynamic_cast( attribute ) ) + { + attrib->pickEventHandler = m_pickTargetsEventHandler; + attrib->enablePicking = m_enablePicking; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) +{ + if ( field == &m_enablePicking ) + { + auto* pbAttribute = dynamic_cast( attribute ); + if ( pbAttribute ) + { + if ( !m_enablePicking ) + { + pbAttribute->m_buttonText = "Start Picking Points"; + } + else + { + pbAttribute->m_buttonText = "Stop Picking Points"; + } + } + } + + if ( field == &m_targets ) + { + if ( auto tvAttribute = dynamic_cast( attribute ) ) + { + tvAttribute->resizePolicy = caf::PdmUiTableViewEditorAttribute::RESIZE_TO_FIT_CONTENT; + + if ( m_enablePicking ) + { + tvAttribute->baseColor = RiuGuiTheme::getColorByVariableName( "externalInputColor" ); + } + tvAttribute->alwaysEnforceResizePolicy = true; + tvAttribute->heightHint = 1000; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, QMenu* menu, QWidget* fieldEditorWidget ) +{ + caf::CmdFeatureMenuBuilder menuBuilder; + + menuBuilder << "RicNewPolylineTargetFeature"; + menuBuilder << "Separator"; + menuBuilder << "RicDeletePolylineTargetFeature"; + + menuBuilder.appendToMenu( menu ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::updateNameField() +{ + QString name = "Undefined"; + if ( m_polygon() ) + { + name = m_polygon->name(); + } + + setName( name ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= "" */ ) +{ + updateNameField(); +} diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonInView.h b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonInView.h new file mode 100644 index 0000000000..5a2a56d826 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonInView.h @@ -0,0 +1,92 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 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 "cafPdmChildArrayField.h" +#include "cafPdmPtrField.h" + +class RimPolygon; +class RivPolylinePartMgr; +class RicPolylineTargetsPickEventHandler; +class RimPolylineTarget; + +namespace cvf +{ +class ModelBasicList; +class BoundingBox; +} // namespace cvf + +namespace caf +{ +class DisplayCoordTransform; +} // namespace caf + +class RimPolygonInView : public RimCheckableNamedObject, public RimPolylinesDataInterface, public RimPolylinePickerInterface +{ + CAF_PDM_HEADER_INIT; + +public: + RimPolygonInView(); + + RimPolygon* polygon() const; + void setPolygon( RimPolygon* polygon ); + + void appendPartsToModel( cvf::ModelBasicList* model, const caf::DisplayCoordTransform* scaleTransform, const cvf::BoundingBox& boundingBox ); + void enablePicking( bool enable ); + + // RimPolylinesDataInterface + 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; + + cvf::ref polyLinesData() const override; + + void onChildrenUpdated( caf::PdmChildArrayFieldHandle* childArray, std::vector& updatedObjects ) override; + void defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; + +protected: + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; + void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; + void defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, QMenu* menu, QWidget* fieldEditorWidget ) override; + +private: + void updateNameField(); + + void updatePolygonFromTargets(); + void updateTargetsFromPolygon(); + +private: + caf::PdmPtrField m_polygon; + + caf::PdmField m_enablePicking; + caf::PdmChildArrayField m_targets; + + cvf::ref m_polylinePartMgr; + std::shared_ptr m_pickTargetsEventHandler; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonInViewCollection.cpp b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonInViewCollection.cpp new file mode 100644 index 0000000000..9b3ed927d0 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonInViewCollection.cpp @@ -0,0 +1,97 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 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 "RimPolygonInViewCollection.h" + +#include "RimPolygon.h" +#include "RimPolygonCollection.h" +#include "RimPolygonInView.h" +#include "RimTools.h" + +#include "cafDisplayCoordTransform.h" + +#include "cvfModelBasicList.h" + +CAF_PDM_SOURCE_INIT( RimPolygonInViewCollection, "RimPolygonInViewCollection" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPolygonInViewCollection::RimPolygonInViewCollection() +{ + CAF_PDM_InitObject( "Polygons", ":/PolylinesFromFile16x16.png" ); + + CAF_PDM_InitFieldNoDefault( &m_polygons, "Polygons", "Polygons" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInViewCollection::syncPolygonsInView() +{ + std::vector existingPolygonsInView = m_polygons.childrenByType(); + m_polygons.clearWithoutDelete(); + + auto polygonCollection = RimTools::polygonCollection(); + if ( polygonCollection ) + { + std::vector newPolygonsInView; + + for ( auto polygon : polygonCollection->allPolygons() ) + { + auto it = std::find_if( existingPolygonsInView.begin(), + existingPolygonsInView.end(), + [polygon]( auto* polygonInView ) { return polygonInView->polygon() == polygon; } ); + + if ( it != existingPolygonsInView.end() ) + { + newPolygonsInView.push_back( *it ); + existingPolygonsInView.erase( it ); + } + else + { + auto polygonInView = new RimPolygonInView(); + polygonInView->setPolygon( polygon ); + newPolygonsInView.push_back( polygonInView ); + } + } + + m_polygons.setValue( newPolygonsInView ); + } + + for ( auto polyInView : existingPolygonsInView ) + { + delete polyInView; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonInViewCollection::appendPartsToModel( cvf::ModelBasicList* model, + caf::DisplayCoordTransform* scaleTransform, + const cvf::BoundingBox& boundingBox ) +{ + for ( auto polygon : m_polygons ) + { + if ( polygon && polygon->isChecked() ) + { + polygon->appendPartsToModel( model, scaleTransform, boundingBox ); + } + } +} diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonInViewCollection.h b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonInViewCollection.h new file mode 100644 index 0000000000..7d79a1b853 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonInViewCollection.h @@ -0,0 +1,54 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 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 "cafPdmChildArrayField.h" +#include "cafPdmObject.h" + +class RimPolygonInView; + +namespace cvf +{ +class ModelBasicList; +class BoundingBox; +} // namespace cvf + +namespace caf +{ +class DisplayCoordTransform; +} // namespace caf + +//================================================================================================== +/// +/// +//================================================================================================== +class RimPolygonInViewCollection : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimPolygonInViewCollection(); + + void syncPolygonsInView(); + + void appendPartsToModel( cvf::ModelBasicList* model, caf::DisplayCoordTransform* scaleTransform, const cvf::BoundingBox& boundingBox ); + +private: + caf::PdmChildArrayField m_polygons; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp b/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp index 2805312a19..eaba599751 100644 --- a/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp +++ b/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp @@ -1860,7 +1860,7 @@ void Rim3dView::onUpdateScaleTransform() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void Rim3dView::updateSurfacesInViewTreeItems() +void Rim3dView::updateViewTreeItems( RiaDefines::ItemIn3dView itemType ) { // default is to do nothing } diff --git a/ApplicationLibCode/ProjectDataModel/Rim3dView.h b/ApplicationLibCode/ProjectDataModel/Rim3dView.h index c58b5daedd..e25459dacd 100644 --- a/ApplicationLibCode/ProjectDataModel/Rim3dView.h +++ b/ApplicationLibCode/ProjectDataModel/Rim3dView.h @@ -193,7 +193,7 @@ class Rim3dView : public RimViewWindow, public RiuViewerToViewInterface, public RimViewLinker* assosiatedViewLinker() const override; RimViewController* viewController() const override; - virtual void updateSurfacesInViewTreeItems(); + virtual void updateViewTreeItems( RiaDefines::ItemIn3dView itemType ); RimAnnotationInViewCollection* annotationCollection() const; void syncronizeLocalAnnotationsFromGlobal(); diff --git a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp index d036783239..870316d8ce 100644 --- a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -23,6 +23,7 @@ #include "PlotTemplates/RimPlotTemplateFileItem.h" #include "PlotTemplates/RimPlotTemplateFolderItem.h" +#include "Polygons/RimPolygonCollection.h" #include "Rim3dOverlayInfoConfig.h" #include "Rim3dWellLogCurveCollection.h" #include "Rim3dWellLogExtractionCurve.h" @@ -1138,6 +1139,11 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() { menuBuilder << "RicAddGridCalculationFeature"; } + else if ( dynamic_cast( firstUiItem ) ) + { + menuBuilder << "RicAppendPolygonFeature"; + menuBuilder << "RicAppendPolygonFileFeature"; + } if ( dynamic_cast( firstUiItem ) ) { diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp index 00483713dd..b30d82fd6b 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp @@ -41,6 +41,7 @@ #include "RigWellResultFrame.h" #include "RigWellResultPoint.h" +#include "Polygons/RimPolygonInViewCollection.h" #include "Rim2dIntersectionView.h" #include "Rim3dOverlayInfoConfig.h" #include "RimAnnotationCollection.h" @@ -647,6 +648,11 @@ void RimEclipseView::onCreateDisplayModel() nativeOrOverrideViewer()->addStaticModelOnce( m_surfaceVizModel.p(), isUsingOverrideViewer() ); } + // Polygons + m_polygonVizModel->removeAllParts(); + m_polygonCollection->appendPartsToModel( m_polygonVizModel.p(), transform.p(), ownerCase()->allCellsBoundingBox() ); + nativeOrOverrideViewer()->addStaticModelOnce( m_polygonVizModel.p(), isUsingOverrideViewer() ); + // Well path model m_wellPathPipeVizModel->removeAllParts(); @@ -1077,7 +1083,7 @@ void RimEclipseView::appendStreamlinesToModel() //-------------------------------------------------------------------------------------------------- void RimEclipseView::onLoadDataAndUpdate() { - updateSurfacesInViewTreeItems(); + updateViewTreeItems( RiaDefines::ItemIn3dView::ALL ); onUpdateScaleTransform(); @@ -1947,6 +1953,8 @@ void RimEclipseView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin if ( surfaceInViewCollection() ) uiTreeOrdering.add( surfaceInViewCollection() ); if ( seismicSectionCollection()->shouldBeVisibleInTree() ) uiTreeOrdering.add( seismicSectionCollection() ); + uiTreeOrdering.add( m_polygonCollection ); + uiTreeOrdering.skipRemainingChildren( true ); } diff --git a/ApplicationLibCode/ProjectDataModel/RimGridView.cpp b/ApplicationLibCode/ProjectDataModel/RimGridView.cpp index 81006c365b..98a57cd0d3 100644 --- a/ApplicationLibCode/ProjectDataModel/RimGridView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimGridView.cpp @@ -18,6 +18,7 @@ #include "RimGridView.h" +#include "Polygons/RimPolygonInViewCollection.h" #include "Rim3dOverlayInfoConfig.h" #include "RimCellFilterCollection.h" #include "RimEclipseCase.h" @@ -96,6 +97,9 @@ RimGridView::RimGridView() CAF_PDM_InitFieldNoDefault( &m_seismicSectionCollection, "SeismicSectionCollection", "Seismic Collection Field" ); m_seismicSectionCollection = new RimSeismicSectionCollection(); + CAF_PDM_InitFieldNoDefault( &m_polygonCollection, "PolygonCollection", "Polygon Collection Field" ); + m_polygonCollection = new RimPolygonInViewCollection(); + CAF_PDM_InitFieldNoDefault( &m_cellFilterCollection, "RangeFilters", "Cell Filter Collection Field" ); m_cellFilterCollection = new RimCellFilterCollection(); @@ -104,6 +108,9 @@ RimGridView::RimGridView() m_intersectionVizModel = new cvf::ModelBasicList; m_intersectionVizModel->setName( "CrossSectionModel" ); + + m_polygonVizModel = new cvf::ModelBasicList; + m_polygonVizModel->setName( "PolygonModel" ); } //-------------------------------------------------------------------------------------------------- @@ -161,6 +168,14 @@ RimSeismicSectionCollection* RimGridView::seismicSectionCollection() const return m_seismicSectionCollection(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPolygonInViewCollection* RimGridView::polygonCollection() const +{ + return m_polygonCollection(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -455,23 +470,32 @@ void RimGridView::updateWellMeasurements() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimGridView::updateSurfacesInViewTreeItems() +void RimGridView::updateViewTreeItems( RiaDefines::ItemIn3dView itemType ) { - RimSurfaceCollection* surfColl = RimTools::surfaceCollection(); + auto bitmaskEnum = BitmaskEnum( itemType ); - if ( surfColl && surfColl->containsSurface() ) + if ( bitmaskEnum.AnyOf( RiaDefines::ItemIn3dView::SURFACE ) ) { - if ( !m_surfaceCollection() ) + RimSurfaceCollection* surfColl = RimTools::surfaceCollection(); + if ( surfColl && surfColl->containsSurface() ) { - m_surfaceCollection = new RimSurfaceInViewCollection(); - } + if ( !m_surfaceCollection() ) + { + m_surfaceCollection = new RimSurfaceInViewCollection(); + } - m_surfaceCollection->setSurfaceCollection( surfColl ); - m_surfaceCollection->updateFromSurfaceCollection(); + m_surfaceCollection->setSurfaceCollection( surfColl ); + m_surfaceCollection->updateFromSurfaceCollection(); + } + else + { + delete m_surfaceCollection; + } } - else + + if ( bitmaskEnum.AnyOf( RiaDefines::ItemIn3dView::POLYGON ) ) { - delete m_surfaceCollection; + m_polygonCollection->syncPolygonsInView(); } updateConnectedEditors(); diff --git a/ApplicationLibCode/ProjectDataModel/RimGridView.h b/ApplicationLibCode/ProjectDataModel/RimGridView.h index f3115e2f34..203f7e9100 100644 --- a/ApplicationLibCode/ProjectDataModel/RimGridView.h +++ b/ApplicationLibCode/ProjectDataModel/RimGridView.h @@ -32,6 +32,7 @@ class RimCellFilterCollection; class RimWellMeasurementInViewCollection; class RimSurfaceInViewCollection; class RimSeismicSectionCollection; +class RimPolygonInViewCollection; class RimGridView : public Rim3dView { @@ -54,6 +55,7 @@ class RimGridView : public Rim3dView RimIntersectionResultsDefinitionCollection* separateSurfaceResultsCollection() const; RimWellMeasurementInViewCollection* measurementCollection() const; RimSeismicSectionCollection* seismicSectionCollection() const; + RimPolygonInViewCollection* polygonCollection() const; virtual const RimPropertyFilterCollection* propertyFilterCollection() const = 0; @@ -68,7 +70,7 @@ class RimGridView : public Rim3dView bool isGridVisualizationMode() const override; void updateWellMeasurements(); - void updateSurfacesInViewTreeItems() override; + void updateViewTreeItems( RiaDefines::ItemIn3dView itemType ) override; protected: virtual void updateViewFollowingCellFilterUpdates(); @@ -90,6 +92,7 @@ class RimGridView : public Rim3dView protected: cvf::ref m_surfaceVizModel; cvf::ref m_intersectionVizModel; + cvf::ref m_polygonVizModel; // Fields caf::PdmChildField m_intersectionCollection; @@ -104,6 +107,7 @@ class RimGridView : public Rim3dView caf::PdmChildField m_cellFilterCollection; caf::PdmChildField m_overrideCellFilterCollection; caf::PdmChildField m_seismicSectionCollection; + caf::PdmChildField m_polygonCollection; private: void onCreatePartCollectionFromSelection( cvf::Collection* parts ) override; diff --git a/ApplicationLibCode/ProjectDataModel/RimOilField.cpp b/ApplicationLibCode/ProjectDataModel/RimOilField.cpp index f0f421c609..ac36308e79 100644 --- a/ApplicationLibCode/ProjectDataModel/RimOilField.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimOilField.cpp @@ -35,6 +35,8 @@ #include "RimSurfaceCollection.h" #include "RimWellPathCollection.h" +#include "Polygons/RimPolygonCollection.h" + CAF_PDM_SOURCE_INIT( RimOilField, "ResInsightOilField" ); //-------------------------------------------------------------------------------------------------- /// @@ -55,6 +57,7 @@ RimOilField::RimOilField() CAF_PDM_InitFieldNoDefault( &annotationCollection, "AnnotationCollection", "Annotations" ); CAF_PDM_InitFieldNoDefault( &ensembleWellLogsCollection, "EnsembleWellLogsCollection", "Ensemble Well Logs" ); + CAF_PDM_InitFieldNoDefault( &polygonCollection, "PolygonCollection", "Polygons" ); CAF_PDM_InitFieldNoDefault( &m_fractureTemplateCollection_OBSOLETE, "FractureDefinitionCollection", "Defenition of Fractures" ); @@ -80,6 +83,7 @@ RimOilField::RimOilField() formationNamesCollection = new RimFormationNamesCollection(); annotationCollection = new RimAnnotationCollection(); ensembleWellLogsCollection = new RimEnsembleWellLogsCollection(); + polygonCollection = new RimPolygonCollection(); m_fractureTemplateCollection_OBSOLETE = new RimFractureTemplateCollection; m_fractureTemplateCollection_OBSOLETE.xmlCapability()->setIOWritable( false ); diff --git a/ApplicationLibCode/ProjectDataModel/RimOilField.h b/ApplicationLibCode/ProjectDataModel/RimOilField.h index a45ed80936..60b17c698b 100644 --- a/ApplicationLibCode/ProjectDataModel/RimOilField.h +++ b/ApplicationLibCode/ProjectDataModel/RimOilField.h @@ -41,6 +41,7 @@ class RimSeismicDataCollection; class RimSeismicViewCollection; class RimSurfaceCollection; class RimEnsembleWellLogsCollection; +class RimPolygonCollection; //================================================================================================== /// @@ -73,6 +74,7 @@ class RimOilField : public caf::PdmObject caf::PdmChildField seismicDataCollection; caf::PdmChildField seismicViewCollection; caf::PdmChildField ensembleWellLogsCollection; + caf::PdmChildField polygonCollection; protected: void initAfterRead() override; diff --git a/ApplicationLibCode/ProjectDataModel/RimPolylinePickerInterface.cpp b/ApplicationLibCode/ProjectDataModel/RimPolylinePickerInterface.cpp index 9ca78cfffd..cf5c9dcff8 100644 --- a/ApplicationLibCode/ProjectDataModel/RimPolylinePickerInterface.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimPolylinePickerInterface.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2020 Equinor ASA +// Copyright (C) 2024 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 diff --git a/ApplicationLibCode/ProjectDataModel/RimProject.cpp b/ApplicationLibCode/ProjectDataModel/RimProject.cpp index 2aec13c3fd..a83a566f5b 100644 --- a/ApplicationLibCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimProject.cpp @@ -33,6 +33,7 @@ #include "RigGridBase.h" #include "PlotTemplates/RimPlotTemplateFolderItem.h" +#include "Polygons/RimPolygonCollection.h" #include "RimAdvancedSnapshotExportDefinition.h" #include "RimAnalysisPlotCollection.h" #include "RimAnnotationCollection.h" @@ -1533,6 +1534,7 @@ void RimProject::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, Q if ( oilField->formationNamesCollection() ) uiTreeOrdering.add( oilField->formationNamesCollection() ); if ( oilField->completionTemplateCollection() ) uiTreeOrdering.add( oilField->completionTemplateCollection() ); if ( oilField->annotationCollection() ) uiTreeOrdering.add( oilField->annotationCollection() ); + if ( oilField->polygonCollection() ) uiTreeOrdering.add( oilField->polygonCollection() ); } uiTreeOrdering.add( colorLegendCollection() ); diff --git a/ApplicationLibCode/ProjectDataModel/RimTools.cpp b/ApplicationLibCode/ProjectDataModel/RimTools.cpp index 5e3bad0eb7..47c6e8d9a3 100644 --- a/ApplicationLibCode/ProjectDataModel/RimTools.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimTools.cpp @@ -25,6 +25,8 @@ #include "RigGeoMechCaseData.h" #include "RigReservoirGridTools.h" +#include "Polygons/RimPolygon.h" +#include "Polygons/RimPolygonCollection.h" #include "RimCase.h" #include "RimColorLegend.h" #include "RimColorLegendCollection.h" @@ -493,6 +495,20 @@ void RimTools::seismicDataOptionItems( QList* options, c } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTools::polygonOptionItems( QList* options ) +{ + auto project = RimProject::current(); + auto coll = project->activeOilField()->polygonCollection(); + + for ( auto* p : coll->allPolygons() ) + { + options->push_back( caf::PdmOptionItemInfo( p->name(), p, false, p->uiIconProvider() ) ); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -546,6 +562,15 @@ RimSurfaceCollection* RimTools::surfaceCollection() return proj->activeOilField()->surfaceCollection(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPolygonCollection* RimTools::polygonCollection() +{ + RimProject* proj = RimProject::current(); + return proj->activeOilField()->polygonCollection(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimTools.h b/ApplicationLibCode/ProjectDataModel/RimTools.h index 187e5d684f..5146a59cc7 100644 --- a/ApplicationLibCode/ProjectDataModel/RimTools.h +++ b/ApplicationLibCode/ProjectDataModel/RimTools.h @@ -41,6 +41,7 @@ class RimCase; class RimWellPath; class RimSurfaceCollection; class RimFaultInViewCollection; +class RimPolygonCollection; //-------------------------------------------------------------------------------------------------- /// @@ -69,6 +70,7 @@ class RimTools static void colorLegendOptionItems( QList* options ); static void seismicDataOptionItems( QList* options, cvf::BoundingBox worldBBox, bool basicDataOnly = false ); static void seismicDataOptionItems( QList* options ); + static void polygonOptionItems( QList* options ); static void faultOptionItems( QList* options, RimFaultInViewCollection* coll ); @@ -76,6 +78,7 @@ class RimTools static RimWellPath* firstWellPath(); static RimSurfaceCollection* surfaceCollection(); + static RimPolygonCollection* polygonCollection(); static void timeStepsForCase( RimCase* gridCase, QList* options ); diff --git a/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicView.cpp b/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicView.cpp index 2d66d04664..800bc01985 100644 --- a/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicView.cpp +++ b/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicView.cpp @@ -407,7 +407,7 @@ void RimSeismicView::onUpdateLegends() //-------------------------------------------------------------------------------------------------- void RimSeismicView::onLoadDataAndUpdate() { - updateSurfacesInViewTreeItems(); + updateViewTreeItems( RiaDefines::ItemIn3dView::ALL ); syncronizeLocalAnnotationsFromGlobal(); onUpdateScaleTransform(); @@ -461,23 +461,28 @@ void RimSeismicView::updateGridBoxData() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimSeismicView::updateSurfacesInViewTreeItems() +void RimSeismicView::updateViewTreeItems( RiaDefines::ItemIn3dView itemType ) { - RimSurfaceCollection* surfColl = RimTools::surfaceCollection(); + auto bitmaskEnum = BitmaskEnum( itemType ); - if ( surfColl && surfColl->containsSurface() ) + if ( bitmaskEnum.AnyOf( RiaDefines::ItemIn3dView::SURFACE ) ) { - if ( !m_surfaceCollection() ) + RimSurfaceCollection* surfColl = RimTools::surfaceCollection(); + + if ( surfColl && surfColl->containsSurface() ) { - m_surfaceCollection = new RimSurfaceInViewCollection(); - } + if ( !m_surfaceCollection() ) + { + m_surfaceCollection = new RimSurfaceInViewCollection(); + } - m_surfaceCollection->setSurfaceCollection( surfColl ); - m_surfaceCollection->updateFromSurfaceCollection(); - } - else - { - delete m_surfaceCollection; + m_surfaceCollection->setSurfaceCollection( surfColl ); + m_surfaceCollection->updateFromSurfaceCollection(); + } + else + { + delete m_surfaceCollection; + } } updateConnectedEditors(); diff --git a/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicView.h b/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicView.h index dbfb1a6db5..b18d60a1e2 100644 --- a/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicView.h +++ b/ApplicationLibCode/ProjectDataModel/Seismic/RimSeismicView.h @@ -90,7 +90,7 @@ class RimSeismicView : public Rim3dView, public RimPolylinesDataInterface void setDefaultView() override; - void updateSurfacesInViewTreeItems() override; + void updateViewTreeItems( RiaDefines::ItemIn3dView itemType ) override; private: caf::PdmChildField m_surfaceCollection; diff --git a/ApplicationLibCode/ProjectDataModel/Surfaces/RimSurfaceCollection.cpp b/ApplicationLibCode/ProjectDataModel/Surfaces/RimSurfaceCollection.cpp index be7f01c1ac..6332511ee5 100644 --- a/ApplicationLibCode/ProjectDataModel/Surfaces/RimSurfaceCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Surfaces/RimSurfaceCollection.cpp @@ -302,7 +302,7 @@ void RimSurfaceCollection::updateViews( const std::vector& surfsToR proj->allViews( views ); for ( auto view : views ) { - view->updateSurfacesInViewTreeItems(); + view->updateViewTreeItems( RiaDefines::ItemIn3dView::SURFACE ); if ( auto gridView = dynamic_cast( view ) ) { @@ -355,7 +355,7 @@ void RimSurfaceCollection::updateViews() for ( auto view : views ) { - view->updateSurfacesInViewTreeItems(); + view->updateViewTreeItems( RiaDefines::ItemIn3dView::SURFACE ); } for ( auto view : views )