Add polygon file readers and make sure UI items are in sync

* Add polygon reader for POL file format
* Add CSV import
* Add helper function to create tag with color and text
* Show polygon color as tag, allow color edit by clicking on tag
* Support optional header in csv file
* Add Reload on polygon file
* Show warning icon if no polygons
* Improve logging text
* Do not show file polygon in view if no polygons are imported
* Use appendMenuItems
* Set default polygon color to orange
* Enter edit state when creating a new polygon
* Fix missing UI text in menu builder
This commit is contained in:
Magne Sjaastad
2024-03-01 14:59:14 +01:00
committed by GitHub
parent 04b14cf52a
commit 818c5c0f9c
37 changed files with 1117 additions and 159 deletions

View File

@@ -286,6 +286,7 @@
<file>decline-curve.svg</file>
<file>regression-curve.svg</file>
<file>padlock.svg</file>
<file>warning.svg</file>
</qresource>
<qresource prefix="/Shader">
<file>fs_CellFace.glsl</file>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><title>ionicons-v5-r</title><path d="M85.57,446.25H426.43a32,32,0,0,0,28.17-47.17L284.18,82.58c-12.09-22.44-44.27-22.44-56.36,0L57.4,399.08A32,32,0,0,0,85.57,446.25Z" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><path d="M250.26,195.39l5.74,122,5.73-121.95a5.74,5.74,0,0,0-5.79-6h0A5.74,5.74,0,0,0,250.26,195.39Z" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><path d="M256,397.25a20,20,0,1,1,20-20A20,20,0,0,1,256,397.25Z"/></svg>

After

Width:  |  Height:  |  Size: 740 B

View File

@@ -1,11 +1,13 @@
set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RicNewPolygonFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewPolygonFileFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicCreatePolygonFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicImportPolygonFileFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicReloadPolygonFileFeature.h
)
set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RicNewPolygonFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewPolygonFileFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicCreatePolygonFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicImportPolygonFileFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicReloadPolygonFileFeature.cpp
)
list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})

View File

@@ -16,23 +16,27 @@
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicNewPolygonFeature.h"
#include "RicCreatePolygonFeature.h"
#include "RiaApplication.h"
#include "Polygons/RimPolygon.h"
#include "Polygons/RimPolygonCollection.h"
#include "Polygons/RimPolygonTools.h"
#include "Rim3dView.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RiuPlotMainWindowTools.h"
#include "Riu3DMainWindowTools.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicNewPolygonFeature, "RicNewPolygonFeature" );
CAF_CMD_SOURCE_INIT( RicCreatePolygonFeature, "RicCreatePolygonFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewPolygonFeature::onActionTriggered( bool isChecked )
void RicCreatePolygonFeature::onActionTriggered( bool isChecked )
{
auto proj = RimProject::current();
auto polygonCollection = proj->activeOilField()->polygonCollection();
@@ -40,15 +44,17 @@ void RicNewPolygonFeature::onActionTriggered( bool isChecked )
auto newPolygon = polygonCollection->appendUserDefinedPolygon();
polygonCollection->uiCapability()->updateAllRequiredEditors();
RiuPlotMainWindowTools::setExpanded( newPolygon );
RiuPlotMainWindowTools::selectAsCurrentItem( newPolygon );
Riu3DMainWindowTools::setExpanded( newPolygon );
auto activeView = RiaApplication::instance()->activeReservoirView();
RimPolygonTools::selectAndActivatePolygonInView( newPolygon, activeView );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewPolygonFeature::setupActionLook( QAction* actionToSetup )
void RicCreatePolygonFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setText( "New Polygon" );
actionToSetup->setText( "Create Polygon" );
actionToSetup->setIcon( QIcon( ":/PolylinesFromFile16x16.png" ) );
}

View File

@@ -23,7 +23,7 @@
//==================================================================================================
///
//==================================================================================================
class RicNewPolygonFeature : public caf::CmdFeature
class RicCreatePolygonFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;

View File

@@ -0,0 +1,83 @@
////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicImportPolygonFileFeature.h"
#include "RiaApplication.h"
#include "Polygons/RimPolygon.h"
#include "Polygons/RimPolygonCollection.h"
#include "Polygons/RimPolygonFile.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "Riu3DMainWindowTools.h"
#include "RiuFileDialogTools.h"
#include <QAction>
#include <QFileInfo>
CAF_CMD_SOURCE_INIT( RicImportPolygonFileFeature, "RicImportPolygonFileFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicImportPolygonFileFeature::onActionTriggered( bool isChecked )
{
RiaApplication* app = RiaApplication::instance();
QString defaultDir = app->lastUsedDialogDirectory( "BINARY_GRID" );
QStringList fileNames = RiuFileDialogTools::getOpenFileNames( Riu3DMainWindowTools::mainWindowWidget(),
"Import Polygons",
defaultDir,
"Polylines (*.csv *.dat *.pol);;Text Files (*.txt);;Polylines "
"(*.dat);;Polylines (*.pol);;Polylines (*.csv);;All Files (*.*)" );
if ( fileNames.isEmpty() ) return;
// Remember the path to next time
app->setLastUsedDialogDirectory( "BINARY_GRID", QFileInfo( fileNames.last() ).absolutePath() );
auto proj = RimProject::current();
auto polygonCollection = proj->activeOilField()->polygonCollection();
RimPolygon* objectToSelect = nullptr;
for ( const auto& filename : fileNames )
{
auto newPolygonFile = new RimPolygonFile();
newPolygonFile->setFileName( filename );
newPolygonFile->loadData();
polygonCollection->addPolygonFile( newPolygonFile );
if ( !newPolygonFile->polygons().empty() ) objectToSelect = newPolygonFile->polygons().front();
}
polygonCollection->uiCapability()->updateAllRequiredEditors();
Riu3DMainWindowTools::setExpanded( objectToSelect );
Riu3DMainWindowTools::selectAsCurrentItem( objectToSelect );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicImportPolygonFileFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setText( "Import Polygon" );
actionToSetup->setIcon( QIcon( ":/PolylinesFromFile16x16.png" ) );
}

View File

@@ -23,7 +23,7 @@
//==================================================================================================
///
//==================================================================================================
class RicNewPolygonFileFeature : public caf::CmdFeature
class RicImportPolygonFileFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;

View File

@@ -16,42 +16,36 @@
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicNewPolygonFileFeature.h"
#include "RicReloadPolygonFileFeature.h"
#include "Polygons/RimPolygon.h"
#include "Polygons/RimPolygonCollection.h"
#include "Polygons/RimPolygonFile.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RiuPlotMainWindowTools.h"
#include "cafSelectionManager.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicNewPolygonFileFeature, "RicNewPolygonFileFeature" );
CAF_CMD_SOURCE_INIT( RicReloadPolygonFileFeature, "RicReloadPolygonFileFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewPolygonFileFeature::onActionTriggered( bool isChecked )
void RicReloadPolygonFileFeature::onActionTriggered( bool isChecked )
{
auto proj = RimProject::current();
auto polygonCollection = proj->activeOilField()->polygonCollection();
auto polygonFile = caf::SelectionManager::instance()->selectedItemOfType<RimPolygonFile>();
if ( polygonFile )
{
polygonFile->loadData();
polygonFile->objectChanged.send();
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 );
polygonFile->updateConnectedEditors();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewPolygonFileFeature::setupActionLook( QAction* actionToSetup )
void RicReloadPolygonFileFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setText( "New File Polygon" );
actionToSetup->setIcon( QIcon( ":/PolylinesFromFile16x16.png" ) );
actionToSetup->setText( "Reload" );
actionToSetup->setIcon( QIcon( ":/Refresh.svg" ) );
}

View File

@@ -0,0 +1,33 @@
////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
//==================================================================================================
///
//==================================================================================================
class RicReloadPolygonFileFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
};

View File

@@ -95,6 +95,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculation.h
${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationImporter.h
${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationExporter.h
${CMAKE_CURRENT_LIST_DIR}/RifPolygonReader.h
)
set(SOURCE_GROUP_SOURCE_FILES
@@ -189,6 +190,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RifGridCalculationExporter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationImporter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationExporter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifPolygonReader.cpp
)
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})

View File

@@ -0,0 +1,209 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RifPolygonReader.h"
#include "RiaTextStringTools.h"
#include "SummaryPlotCommands/RicPasteAsciiDataToSummaryPlotFeatureUi.h"
#include "RifCsvUserDataParser.h"
#include <QFileInfo>
#include <QTextStream>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::pair<int, std::vector<cvf::Vec3d>>> RifPolygonReader::parsePolygonFile( const QString& fileName, QString* errorMessage )
{
QFileInfo fi( fileName );
QFile dataFile( fileName );
if ( !dataFile.open( QFile::ReadOnly ) )
{
if ( errorMessage ) ( *errorMessage ) += "Could not open file: " + fileName + "\n";
return {};
}
QTextStream stream( &dataFile );
auto fileContent = stream.readAll();
if ( fi.suffix().trimmed().toLower() == "csv" )
{
return parseTextCsv( fileContent, errorMessage );
}
else
{
auto polygons = parseText( fileContent, errorMessage );
std::vector<std::pair<int, std::vector<cvf::Vec3d>>> polygonsWithIds;
for ( auto& polygon : polygons )
{
polygonsWithIds.push_back( std::make_pair( -1, polygon ) );
}
return polygonsWithIds;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::vector<cvf::Vec3d>> RifPolygonReader::parseText( const QString& content, QString* errorMessage )
{
std::vector<std::vector<cvf::Vec3d>> polylines( 1 );
QString myString = content;
QTextStream stream( &myString );
int lineNumber = 1;
while ( !stream.atEnd() )
{
QString line = stream.readLine();
QStringList commentLineSegs = line.split( "#" );
if ( commentLineSegs.empty() ) continue; // Empty line
QStringList lineSegs = RiaTextStringTools::splitSkipEmptyParts( commentLineSegs[0], QRegExp( "\\s+" ) );
if ( lineSegs.empty() ) continue; // No data
if ( lineSegs.size() != 3 )
{
if ( errorMessage ) ( *errorMessage ) += "Unexpected number of words on line: " + QString::number( lineNumber ) + "\n";
continue;
}
{
bool isNumberParsingOk = true;
bool isOk = true;
double x = lineSegs[0].toDouble( &isOk );
isNumberParsingOk &= isOk;
double y = lineSegs[1].toDouble( &isOk );
isNumberParsingOk &= isOk;
double z = lineSegs[2].toDouble( &isOk );
isNumberParsingOk &= isOk;
if ( !isNumberParsingOk )
{
if ( errorMessage ) ( *errorMessage ) += "Could not read the point at line: " + QString::number( lineNumber ) + "\n";
continue;
}
if ( x == 999.0 && y == 999.0 && z == 999.0 ) // New PolyLine
{
polylines.push_back( std::vector<cvf::Vec3d>() );
continue;
}
cvf::Vec3d point( x, y, -z );
polylines.back().push_back( point );
}
++lineNumber;
}
if ( polylines.back().empty() )
{
polylines.pop_back();
}
return polylines;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::pair<int, std::vector<cvf::Vec3d>>> RifPolygonReader::parseTextCsv( const QString& content, QString* errorMessage )
{
RifCsvUserDataPastedTextParser parser( content, errorMessage );
AsciiDataParseOptions parseOptions;
parseOptions.cellSeparator = ",";
parseOptions.decimalSeparator = ".";
std::vector<std::pair<QString, std::vector<double>>> readValues;
if ( parser.parse( parseOptions ) )
{
for ( auto s : parser.tableData().columnInfos() )
{
if ( s.dataType != Column::NUMERIC ) continue;
QString columnName = QString::fromStdString( s.columnName() );
bool isNumber = false;
auto value = columnName.toDouble( &isNumber );
std::vector<double> values = s.values;
if ( isNumber )
{
values.insert( values.begin(), value );
}
readValues.push_back( { columnName, values } );
}
}
if ( readValues.size() == 4 )
{
// Three first columns represent XYZ, last column polygon ID
const auto firstSize = readValues[0].second.size();
if ( ( firstSize == readValues[1].second.size() ) && ( firstSize == readValues[2].second.size() ) &&
( firstSize == readValues[3].second.size() ) )
{
std::vector<std::pair<int, std::vector<cvf::Vec3d>>> polylines;
std::vector<cvf::Vec3d> polygon;
int polygonId = -1;
for ( size_t i = 0; i < firstSize; i++ )
{
int currentPolygonId = static_cast<int>( readValues[3].second[i] );
if ( polygonId != currentPolygonId )
{
if ( !polygon.empty() ) polylines.push_back( std::make_pair( polygonId, polygon ) );
polygon.clear();
polygonId = currentPolygonId;
}
cvf::Vec3d point( readValues[0].second[i], readValues[1].second[i], -readValues[2].second[i] );
polygon.push_back( point );
}
if ( !polygon.empty() ) polylines.push_back( std::make_pair( polygonId, polygon ) );
return polylines;
}
}
if ( readValues.size() == 3 )
{
std::vector<cvf::Vec3d> points;
for ( size_t i = 0; i < readValues[0].second.size(); i++ )
{
cvf::Vec3d point( readValues[0].second[i], readValues[1].second[i], -readValues[2].second[i] );
points.push_back( point );
}
int polygonId = -1;
return { std::make_pair( polygonId, points ) };
}
return {};
}

View File

@@ -0,0 +1,40 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cvfVector3.h"
#include <QString>
#include <vector>
//==================================================================================================
//
//
//==================================================================================================
class RifPolygonReader
{
public:
static std::vector<std::pair<int, std::vector<cvf::Vec3d>>> parsePolygonFile( const QString& fileName, QString* errorMessage );
// Defined public for testing purposes
public:
static std::vector<std::vector<cvf::Vec3d>> parseText( const QString& content, QString* errorMessage );
static std::vector<std::pair<int, std::vector<cvf::Vec3d>>> parseTextCsv( const QString& content, QString* errorMessage );
};

View File

@@ -1048,10 +1048,7 @@ void RimGeoMechView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin
if ( surfaceInViewCollection() ) uiTreeOrdering.add( surfaceInViewCollection() );
if ( seismicSectionCollection()->shouldBeVisibleInTree() ) uiTreeOrdering.add( seismicSectionCollection() );
if ( RiaApplication::enableDevelopmentFeatures() )
{
uiTreeOrdering.add( m_polygonInViewCollection );
}
uiTreeOrdering.add( m_polygonInViewCollection );
uiTreeOrdering.skipRemainingChildren( true );
}

View File

@@ -18,14 +18,19 @@
#include "RimPolygon.h"
#include "RiaApplication.h"
#include "RiaColorTools.h"
#include "RigPolyLinesData.h"
#include "RiaApplication.h"
#include "Rim3dView.h"
#include "RimPolygonAppearance.h"
#include "RimPolygonTools.h"
#include "RiuGuiTheme.h"
#include "cafCmdFeatureMenuBuilder.h"
#include "cafPdmUiColorEditor.h"
#include "cafPdmUiPushButtonEditor.h"
#include "cafPdmUiTreeAttributes.h"
@@ -132,6 +137,30 @@ bool RimPolygon::isReadOnly() const
return m_isReadOnly();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygon::disableStorageOfPolygonPoints()
{
m_pointsInDomainCoords.xmlCapability()->setIOWritable( false );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimPolygon::color() const
{
return m_appearance->lineColor();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygon::setColor( const cvf::Color3f& color )
{
m_appearance->setLineColor( color );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -189,18 +218,51 @@ void RimPolygon::defineEditorAttribute( const caf::PdmFieldHandle* field, QStrin
{
if ( auto attrib = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>( attribute ) )
{
attrib->m_buttonText = "Edit in Active View";
if ( m_isReadOnly() )
{
attrib->m_buttonText = "Select in Active View";
}
else
{
attrib->m_buttonText = "Edit in Active View";
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygon::onColorTagClicked( const SignalEmitter* emitter, size_t index )
{
QColor sourceColor = RiaColorTools::toQColor( color() );
QColor newColor = caf::PdmUiColorEditor::getColor( sourceColor );
if ( newColor.isValid() && newColor != sourceColor )
{
setColor( RiaColorTools::fromQColorTo3f( newColor ) );
objectChanged.send();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygon::defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute )
{
if ( auto* treeItemAttribute = dynamic_cast<caf::PdmUiTreeViewItemAttribute*>( attribute ) )
{
auto tag = caf::PdmUiTreeViewItemAttribute::createTag( RiaColorTools::toQColor( color() ),
RiuGuiTheme::getColorByVariableName( "backgroundColor1" ),
"---" );
tag->clicked.connect( this, &RimPolygon::onColorTagClicked );
treeItemAttribute->tags.push_back( std::move( tag ) );
}
if ( m_isReadOnly )
{
caf::PdmUiTreeViewItemAttribute::createTagIfTreeViewItemAttribute( attribute, ":/padlock.svg" );
caf::PdmUiTreeViewItemAttribute::appendTagToTreeViewItemAttribute( attribute, ":/padlock.svg" );
}
}

View File

@@ -24,6 +24,7 @@
#include "cafPdmChildField.h"
#include "cafPdmFieldCvfVec3d.h"
#include "cvfColor3.h"
#include "cvfVector3.h"
class RimPolygonAppearance;
@@ -51,13 +52,19 @@ public:
void setReadOnly( bool isReadOnly );
bool isReadOnly() const;
void disableStorageOfPolygonPoints();
cvf::Color3f color() const;
void setColor( const cvf::Color3f& color );
cvf::ref<RigPolyLinesData> polyLinesData() const override;
void uiOrderingForLocalPolygon( QString uiConfigName, caf::PdmUiOrdering& uiOrdering );
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
void defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
void onColorTagClicked( const SignalEmitter* emitter, size_t index );
protected:
private:
void defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
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;

View File

@@ -85,8 +85,8 @@ RimPolygonAppearance::RimPolygonAppearance()
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_lineColor, "LineColor", cvf::Color3f( cvf::Color3f::ORANGE ), "Line Color" );
CAF_PDM_InitField( &m_sphereColor, "SphereColor", cvf::Color3f( cvf::Color3f::ORANGE ), "Sphere Color" );
CAF_PDM_InitField( &m_polygonPlaneDepth, "PolygonPlaneDepth", 0.0, "Polygon Plane Depth" );
CAF_PDM_InitField( &m_lockPolygonToPlane, "LockPolygon", false, "Lock Polygon to Plane" );
@@ -123,6 +123,22 @@ bool RimPolygonAppearance::isClosed() const
return m_isClosed();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimPolygonAppearance::lineColor() const
{
return m_lineColor();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonAppearance::setLineColor( const cvf::Color3f& color )
{
m_lineColor = color;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -37,6 +37,9 @@ public:
void setIsClosed( bool isClosed );
bool isClosed() const;
cvf::Color3f lineColor() const;
void setLineColor( const cvf::Color3f& color );
public:
RimPolygonAppearance();

View File

@@ -23,6 +23,8 @@
#include "RimPolygonFile.h"
#include "RimProject.h"
#include "cafCmdFeatureMenuBuilder.h"
CAF_PDM_SOURCE_INIT( RimPolygonCollection, "RimPolygonCollection" );
//--------------------------------------------------------------------------------------------------
@@ -30,7 +32,7 @@ CAF_PDM_SOURCE_INIT( RimPolygonCollection, "RimPolygonCollection" );
//--------------------------------------------------------------------------------------------------
RimPolygonCollection::RimPolygonCollection()
{
CAF_PDM_InitObject( "Polygons (Under construction)", ":/PolylinesFromFile16x16.png" );
CAF_PDM_InitObject( "Polygons", ":/PolylinesFromFile16x16.png" );
CAF_PDM_InitFieldNoDefault( &m_polygons, "Polygons", "Polygons" );
CAF_PDM_InitFieldNoDefault( &m_polygonFiles, "PolygonFiles", "Polygon Files" );
@@ -66,7 +68,7 @@ void RimPolygonCollection::addUserDefinedPolygon( RimPolygon* polygon )
{
m_polygons().push_back( polygon );
connectSignals( polygon );
connectPolygonSignals( polygon );
updateViewTreeItems();
scheduleRedrawViews();
@@ -90,6 +92,8 @@ void RimPolygonCollection::addPolygonFile( RimPolygonFile* polygonFile )
{
m_polygonFiles().push_back( polygonFile );
connectPolygonFileSignals( polygonFile );
updateViewTreeItems();
scheduleRedrawViews();
}
@@ -150,6 +154,15 @@ void RimPolygonCollection::childFieldChangedByUi( const caf::PdmFieldHandle* cha
scheduleRedrawViews();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const
{
menuBuilder << "RicCreatePolygonFeature";
menuBuilder << "RicImportPolygonFileFeature";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -178,19 +191,39 @@ void RimPolygonCollection::scheduleRedrawViews()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::connectSignals( RimPolygon* polygon )
void RimPolygonCollection::connectPolygonSignals( RimPolygon* polygon )
{
if ( polygon )
{
polygon->objectChanged.connect( this, &RimPolygonCollection::onObjectChanged );
polygon->objectChanged.connect( this, &RimPolygonCollection::onPolygonChanged );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::onObjectChanged( const caf::SignalEmitter* emitter )
void RimPolygonCollection::connectPolygonFileSignals( RimPolygonFile* polygonFile )
{
if ( polygonFile )
{
polygonFile->objectChanged.connect( this, &RimPolygonCollection::onPolygonFileChanged );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::onPolygonChanged( const caf::SignalEmitter* emitter )
{
scheduleRedrawViews();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::onPolygonFileChanged( const caf::SignalEmitter* emitter )
{
updateViewTreeItems();
scheduleRedrawViews();
}
@@ -201,6 +234,11 @@ void RimPolygonCollection::initAfterRead()
{
for ( auto& p : m_polygons() )
{
connectSignals( p );
connectPolygonSignals( p );
}
for ( auto& pf : m_polygonFiles() )
{
connectPolygonFileSignals( pf );
}
}

View File

@@ -46,15 +46,18 @@ public:
std::vector<RimPolygonFile*> polygonFiles() const;
std::vector<RimPolygon*> allPolygons() const;
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
void childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField ) override;
private:
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
void childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField ) override;
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
void updateViewTreeItems();
void scheduleRedrawViews();
void connectSignals( RimPolygon* polygon );
void onObjectChanged( const caf::SignalEmitter* emitter );
void connectPolygonSignals( RimPolygon* polygon );
void connectPolygonFileSignals( RimPolygonFile* polygonFile );
void onPolygonChanged( const caf::SignalEmitter* emitter );
void onPolygonFileChanged( const caf::SignalEmitter* emitter );
private:
caf::PdmChildArrayField<RimPolygon*> m_polygons;

View File

@@ -17,14 +17,25 @@
/////////////////////////////////////////////////////////////////////////////////
#include "RimPolygonFile.h"
#include "RiaLogging.h"
#include "RifPolygonReader.h"
#include "RimPolygon.h"
#include "cafCmdFeatureMenuBuilder.h"
#include "cafPdmUiTreeAttributes.h"
#include <QFileInfo>
CAF_PDM_SOURCE_INIT( RimPolygonFile, "RimPolygonFileFile" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimPolygonFile::RimPolygonFile()
: objectChanged( this )
{
CAF_PDM_InitObject( "PolygonFile", ":/PolylinesFromFile16x16.png" );
@@ -34,12 +45,48 @@ RimPolygonFile::RimPolygonFile()
setDeletable( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonFile::setFileName( const QString& fileName )
{
m_fileName = fileName;
updateName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonFile::loadData()
{
loadPolygonsFromFile();
auto polygonsFromFile = importDataFromFile( m_fileName().path() );
if ( m_polygons.size() == polygonsFromFile.size() )
{
for ( size_t i = 0; i < m_polygons.size(); i++ )
{
auto projectPoly = m_polygons()[i];
auto filePoly = polygonsFromFile[i];
projectPoly->setPointsInDomainCoords( filePoly->pointsInDomainCoords() );
delete filePoly;
}
}
else
{
m_polygons.deleteChildren();
m_polygons.setValue( polygonsFromFile );
}
if ( polygonsFromFile.empty() )
{
RiaLogging::warning( "No polygons found in file: " + m_fileName().path() );
}
else
{
RiaLogging::info( QString( "Imported %1 polygons from file: " ).arg( polygonsFromFile.size() ) + m_fileName().path() );
}
}
//--------------------------------------------------------------------------------------------------
@@ -50,11 +97,36 @@ std::vector<RimPolygon*> RimPolygonFile::polygons() const
return m_polygons.childrenByType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimPolygonFile::name() const
{
QString nameCandidate = RimNamedObject::name();
if ( !nameCandidate.isEmpty() )
{
return nameCandidate;
}
auto fileName = m_fileName().path();
if ( fileName.isEmpty() )
{
return "Polygon File";
}
QFileInfo fileInfo( fileName );
return fileInfo.fileName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonFile::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( nameField() );
uiOrdering.add( &m_fileName );
uiOrdering.skipRemainingFields();
}
//--------------------------------------------------------------------------------------------------
@@ -62,21 +134,71 @@ void RimPolygonFile::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering&
//--------------------------------------------------------------------------------------------------
void RimPolygonFile::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
{
loadPolygonsFromFile();
if ( changedField == &m_fileName )
{
updateName();
m_polygons.deleteChildren();
loadData();
}
objectChanged.send();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonFile::loadPolygonsFromFile()
std::vector<RimPolygon*> RimPolygonFile::importDataFromFile( const QString& fileName )
{
// m_polygons()->deletePolygons();
QString errorMessages;
auto filePolygons = RifPolygonReader::parsePolygonFile( fileName, &errorMessages );
auto polygon = new RimPolygon();
polygon->setName( "Polygon 1" );
m_polygons.push_back( polygon );
std::vector<RimPolygon*> polygons;
polygon = new RimPolygon();
polygon->setName( "Polygon 2" );
m_polygons.push_back( polygon );
for ( const auto& [polygonId, filePolygon] : filePolygons )
{
auto polygon = new RimPolygon();
polygon->disableStorageOfPolygonPoints();
polygon->setReadOnly( true );
int id = ( polygonId != -1 ) ? polygonId : static_cast<int>( polygons.size() + 1 );
polygon->setName( QString( "Polygon %1" ).arg( id ) );
polygon->setPointsInDomainCoords( filePolygon );
polygons.push_back( polygon );
}
if ( !errorMessages.isEmpty() )
{
RiaLogging::error( errorMessages );
}
return polygons;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonFile::updateName()
{
QFileInfo fileInfo( m_fileName().path() );
setName( fileInfo.fileName() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonFile::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const
{
menuBuilder << "RicReloadPolygonFileFeature";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonFile::defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute )
{
if ( m_polygons.empty() )
{
caf::PdmUiTreeViewItemAttribute::appendTagToTreeViewItemAttribute( attribute, ":/warning.svg" );
}
}

View File

@@ -28,19 +28,29 @@ class RimPolygonFile : public RimNamedObject
{
CAF_PDM_HEADER_INIT;
public:
caf::Signal<> objectChanged;
public:
RimPolygonFile();
void setFileName( const QString& fileName );
void loadData();
std::vector<RimPolygon*> polygons() const;
QString name() 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 appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
void defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
private:
void loadPolygonsFromFile();
static std::vector<RimPolygon*> importDataFromFile( const QString& fileName );
void updateName();
private:
caf::PdmField<caf::FilePath> m_fileName;

View File

@@ -18,6 +18,8 @@
#include "RimPolygonInView.h"
#include "RiaColorTools.h"
#include "RigPolyLinesData.h"
#include "Rim3dView.h"
@@ -70,6 +72,7 @@ RimPolygonInView::RimPolygonInView()
m_targets.uiCapability()->setUiTreeChildrenHidden( true );
m_targets.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP );
m_targets.uiCapability()->setCustomContextMenuEnabled( true );
m_targets.xmlCapability()->disableIO();
setUi3dEditorTypeName( RicPolyline3dEditor::uiEditorTypeName() );
}
@@ -87,6 +90,16 @@ RimPolygon* RimPolygonInView::polygon() const
//--------------------------------------------------------------------------------------------------
void RimPolygonInView::setPolygon( RimPolygon* polygon )
{
if ( m_polygon )
{
m_polygon->objectChanged.disconnect( this );
}
if ( polygon )
{
polygon->objectChanged.connect( this, &RimPolygonInView::onObjectChanged );
}
m_polygon = polygon;
updateTargetsFromPolygon();
@@ -322,9 +335,23 @@ void RimPolygonInView::defineObjectEditorAttribute( QString uiConfigName, caf::P
attrib->enablePicking = m_enablePicking;
}
if ( m_polygon() && m_polygon->isReadOnly() )
if ( m_polygon() )
{
caf::PdmUiTreeViewItemAttribute::createTagIfTreeViewItemAttribute( attribute, ":/padlock.svg" );
if ( auto* treeItemAttribute = dynamic_cast<caf::PdmUiTreeViewItemAttribute*>( attribute ) )
{
auto tag = caf::PdmUiTreeViewItemAttribute::createTag( RiaColorTools::toQColor( m_polygon->color() ),
RiuGuiTheme::getColorByVariableName( "backgroundColor1" ),
"---" );
tag->clicked.connect( m_polygon(), &RimPolygon::onColorTagClicked );
treeItemAttribute->tags.push_back( std::move( tag ) );
}
if ( m_polygon->isReadOnly() )
{
caf::PdmUiTreeViewItemAttribute::appendTagToTreeViewItemAttribute( attribute, ":/padlock.svg" );
}
}
}
@@ -346,6 +373,25 @@ void RimPolygonInView::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder
if ( m_polygon() ) m_polygon->appendMenuItems( menuBuilder );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonInView::onObjectChanged( const caf::SignalEmitter* emitter )
{
updateVisualization();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonInView::initAfterRead()
{
if ( m_polygon )
{
m_polygon->objectChanged.connect( this, &RimPolygonInView::onObjectChanged );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -79,6 +79,8 @@ protected:
void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
void defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, QMenu* menu, QWidget* fieldEditorWidget ) override;
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
void onObjectChanged( const caf::SignalEmitter* emitter );
void initAfterRead() override;
private:
void updateNameField();

View File

@@ -21,6 +21,7 @@
#include "Rim3dView.h"
#include "RimPolygon.h"
#include "RimPolygonCollection.h"
#include "RimPolygonFile.h"
#include "RimPolygonInView.h"
#include "RimTools.h"
@@ -31,58 +32,74 @@ CAF_PDM_SOURCE_INIT( RimPolygonInViewCollection, "RimPolygonInViewCollection" );
//--------------------------------------------------------------------------------------------------
RimPolygonInViewCollection::RimPolygonInViewCollection()
{
CAF_PDM_InitObject( "Polygons (Under construction)", ":/PolylinesFromFile16x16.png" );
CAF_PDM_InitObject( "Polygons", ":/PolylinesFromFile16x16.png" );
CAF_PDM_InitFieldNoDefault( &m_polygons, "Polygons", "Polygons" );
CAF_PDM_InitFieldNoDefault( &m_polygonsInView, "Polygons", "Polygons" );
CAF_PDM_InitFieldNoDefault( &m_collectionsInView, "Collections", "Collections" );
nameField()->uiCapability()->setUiHidden( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonInViewCollection::syncPolygonsInView()
void RimPolygonInViewCollection::updateFromPolygonCollection()
{
std::vector<RimPolygonInView*> existingPolygonsInView = m_polygons.childrenByType();
m_polygons.clearWithoutDelete();
auto polygonCollection = RimTools::polygonCollection();
if ( polygonCollection )
{
std::vector<RimPolygonInView*> 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;
}
updateAllViewItems();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimPolygonInView*> RimPolygonInViewCollection::polygonsInView() const
std::vector<RimPolygonInView*> RimPolygonInViewCollection::visiblePolygonsInView() const
{
return m_polygons.childrenByType();
if ( !m_isChecked ) return {};
std::vector<RimPolygonInView*> polys = m_polygonsInView.childrenByType();
for ( auto coll : m_collectionsInView )
{
if ( coll->isChecked() == false ) continue;
auto other = coll->visiblePolygonsInView();
polys.insert( polys.end(), other.begin(), other.end() );
}
return polys;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimPolygonInView*> RimPolygonInViewCollection::allPolygonsInView() const
{
std::vector<RimPolygonInView*> polys = m_polygonsInView.childrenByType();
for ( auto coll : m_collectionsInView )
{
auto other = coll->visiblePolygonsInView();
polys.insert( polys.end(), other.begin(), other.end() );
}
return polys;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonInViewCollection::setPolygonFile( RimPolygonFile* polygonFile )
{
m_polygonFile = polygonFile;
updateName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimPolygonFile* RimPolygonInViewCollection::polygonFile() const
{
return m_polygonFile;
}
//--------------------------------------------------------------------------------------------------
@@ -90,11 +107,11 @@ std::vector<RimPolygonInView*> RimPolygonInViewCollection::polygonsInView() cons
//--------------------------------------------------------------------------------------------------
void RimPolygonInViewCollection::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
{
RimCheckableObject::fieldChangedByUi( changedField, oldValue, newValue );
RimCheckableNamedObject::fieldChangedByUi( changedField, oldValue, newValue );
if ( changedField == &m_isChecked )
{
for ( auto poly : polygonsInView() )
for ( auto poly : visiblePolygonsInView() )
{
poly->updateConnectedEditors();
}
@@ -105,3 +122,151 @@ void RimPolygonInViewCollection::fieldChangedByUi( const caf::PdmFieldHandle* ch
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonInViewCollection::updateAllViewItems()
{
// Based on the same concept as RimSurfaceInViewCollection
syncCollectionsWithView();
syncPolygonsWithView();
updateConnectedEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonInViewCollection::syncCollectionsWithView()
{
// Based on the same concept as RimSurfaceInViewCollection
auto colls = m_collectionsInView.childrenByType();
for ( auto coll : colls )
{
if ( !coll->polygonFile() )
{
m_collectionsInView.removeChild( coll );
delete coll;
}
}
if ( !m_polygonFile )
{
std::vector<RimPolygonInViewCollection*> orderedColls;
if ( auto polygonCollection = RimTools::polygonCollection() )
{
std::vector<RimPolygonInView*> newPolygonsInView;
for ( auto polygonFile : polygonCollection->polygonFiles() )
{
if ( polygonFile->polygons().empty() ) continue;
auto viewPolygonFile = getCollectionInViewForPolygonFile( polygonFile );
if ( viewPolygonFile == nullptr )
{
auto newColl = new RimPolygonInViewCollection();
newColl->setPolygonFile( polygonFile );
orderedColls.push_back( newColl );
}
else
{
viewPolygonFile->updateName();
orderedColls.push_back( viewPolygonFile );
}
}
}
m_collectionsInView.clearWithoutDelete();
for ( auto viewColl : orderedColls )
{
m_collectionsInView.push_back( viewColl );
viewColl->updateAllViewItems();
}
}
updateName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonInViewCollection::syncPolygonsWithView()
{
std::vector<RimPolygonInView*> existingPolygonsInView = m_polygonsInView.childrenByType();
m_polygonsInView.clearWithoutDelete();
std::vector<RimPolygon*> polygons;
if ( m_polygonFile )
{
polygons = m_polygonFile->polygons();
}
else
{
auto polygonCollection = RimTools::polygonCollection();
polygons = polygonCollection->userDefinedPolygons();
}
std::vector<RimPolygonInView*> newPolygonsInView;
for ( auto polygon : polygons )
{
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_polygonsInView.setValue( newPolygonsInView );
for ( auto polyInView : existingPolygonsInView )
{
delete polyInView;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonInViewCollection::updateName()
{
QString name = "Polygons";
if ( m_polygonFile )
{
name = m_polygonFile->name();
}
setName( name );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimPolygonInViewCollection* RimPolygonInViewCollection::getCollectionInViewForPolygonFile( const RimPolygonFile* polygonFile ) const
{
for ( auto collInView : m_collectionsInView )
{
if ( collInView->polygonFile() == polygonFile )
{
return collInView;
}
}
return nullptr;
}

View File

@@ -18,29 +18,47 @@
#pragma once
#include "RimCheckableObject.h"
#include "RimCheckableNamedObject.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmPointer.h"
class RimPolygonInView;
class RimPolygonFile;
class RimPolygon;
//==================================================================================================
///
///
//==================================================================================================
class RimPolygonInViewCollection : public RimCheckableObject
class RimPolygonInViewCollection : public RimCheckableNamedObject
{
CAF_PDM_HEADER_INIT;
public:
RimPolygonInViewCollection();
void syncPolygonsInView();
void updateFromPolygonCollection();
std::vector<RimPolygonInView*> polygonsInView() const;
std::vector<RimPolygonInView*> visiblePolygonsInView() const;
std::vector<RimPolygonInView*> allPolygonsInView() const;
private:
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
void setPolygonFile( RimPolygonFile* polygonFile );
RimPolygonFile* polygonFile() const;
void updateAllViewItems();
void syncCollectionsWithView();
void syncPolygonsWithView();
void updateName();
RimPolygonInViewCollection* getCollectionInViewForPolygonFile( const RimPolygonFile* polygonFile ) const;
private:
caf::PdmChildArrayField<RimPolygonInView*> m_polygons;
caf::PdmChildArrayField<RimPolygonInView*> m_polygonsInView;
caf::PdmChildArrayField<RimPolygonInViewCollection*> m_collectionsInView;
caf::PdmPointer<RimPolygonFile> m_polygonFile;
};

View File

@@ -55,7 +55,7 @@ RimPolygonInView* RimPolygonTools::findPolygonInView( RimPolygon* polygon, caf::
{
auto polyCollection = gridView->polygonInViewCollection();
for ( auto polygonInView : polyCollection->polygonsInView() )
for ( auto polygonInView : polyCollection->allPolygonsInView() )
{
if ( polygonInView && polygonInView->polygon() == polygon )
{

View File

@@ -23,7 +23,6 @@
#include "PlotTemplates/RimPlotTemplateFileItem.h"
#include "PlotTemplates/RimPlotTemplateFolderItem.h"
#include "Polygons/RimPolygonCollection.h"
#include "Rim3dOverlayInfoConfig.h"
#include "Rim3dWellLogCurveCollection.h"
#include "Rim3dWellLogExtractionCurve.h"
@@ -1139,11 +1138,6 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
{
menuBuilder << "RicAddGridCalculationFeature";
}
else if ( dynamic_cast<RimPolygonCollection*>( firstUiItem ) )
{
menuBuilder << "RicNewPolygonFeature";
menuBuilder << "RicNewPolygonFileFeature";
}
if ( dynamic_cast<Rim3dView*>( firstUiItem ) )
{

View File

@@ -1946,16 +1946,13 @@ void RimEclipseView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin
if ( faultReactivationModelCollection()->shouldBeVisibleInTree() ) uiTreeOrdering.add( faultReactivationModelCollection() );
uiTreeOrdering.add( annotationCollection() );
uiTreeOrdering.add( intersectionCollection() );
uiTreeOrdering.add( m_polygonInViewCollection );
if ( surfaceInViewCollection() ) uiTreeOrdering.add( surfaceInViewCollection() );
if ( seismicSectionCollection()->shouldBeVisibleInTree() ) uiTreeOrdering.add( seismicSectionCollection() );
if ( RiaApplication::enableDevelopmentFeatures() )
{
uiTreeOrdering.add( m_polygonInViewCollection );
}
uiTreeOrdering.add( annotationCollection() );
uiTreeOrdering.skipRemainingChildren( true );
}

View File

@@ -405,16 +405,9 @@ void RimGridView::appendPolygonPartsToModel( caf::DisplayCoordTransform* scaleTr
m_polygonVizModel->removeAllParts();
std::vector<RimPolygonInView*> polygonsInView;
if ( m_polygonInViewCollection && m_polygonInViewCollection->isChecked() )
if ( m_polygonInViewCollection )
{
auto candidates = m_polygonInViewCollection->polygonsInView();
for ( auto polygonInView : candidates )
{
if ( polygonInView->isChecked() )
{
polygonsInView.push_back( polygonInView );
}
}
polygonsInView = m_polygonInViewCollection->visiblePolygonsInView();
}
if ( cellFilterCollection() && cellFilterCollection()->isActive() )
@@ -534,7 +527,7 @@ void RimGridView::updateViewTreeItems( RiaDefines::ItemIn3dView itemType )
if ( bitmaskEnum.AnyOf( RiaDefines::ItemIn3dView::POLYGON ) )
{
m_polygonInViewCollection->syncPolygonsInView();
m_polygonInViewCollection->updateFromPolygonCollection();
}
updateConnectedEditors();

View File

@@ -1262,19 +1262,10 @@ void RimPlotCurve::defineObjectEditorAttribute( QString uiConfigName, caf::PdmUi
if ( auto* treeItemAttribute = dynamic_cast<caf::PdmUiTreeViewItemAttribute*>( attribute ) )
{
treeItemAttribute->tags.clear();
auto tag = caf::PdmUiTreeViewItemAttribute::createTag();
// Blend with background for a nice look
auto backgroundColor = RiuGuiTheme::getColorByVariableName( "backgroundColor1" );
auto color = RiaColorTools::toQColor( m_curveAppearance->color() );
auto sourceWeight = 100;
double transparency = 0.3;
int backgroundWeight = std::max( 1, static_cast<int>( sourceWeight * 10 * transparency ) );
auto blendedColor = RiaColorTools::blendQColors( backgroundColor, color, backgroundWeight, sourceWeight );
tag->bgColor = blendedColor;
tag->fgColor = RiaColorTools::toQColor( m_curveAppearance->color() );
tag->text = "---";
auto tag = caf::PdmUiTreeViewItemAttribute::createTag( RiaColorTools::toQColor( m_curveAppearance->color() ),
RiuGuiTheme::getColorByVariableName( "backgroundColor1" ),
"---" );
tag->clicked.connect( this, &RimPlotCurve::onColorTagClicked );

View File

@@ -1524,6 +1524,7 @@ void RimProject::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, Q
if ( oilField->analysisModels() ) uiTreeOrdering.add( oilField->analysisModels() );
if ( oilField->geoMechModels() ) uiTreeOrdering.add( oilField->geoMechModels() );
if ( oilField->wellPathCollection() ) uiTreeOrdering.add( oilField->wellPathCollection() );
if ( oilField->polygonCollection() ) uiTreeOrdering.add( oilField->polygonCollection() );
if ( oilField->surfaceCollection() ) uiTreeOrdering.add( oilField->surfaceCollection() );
if ( oilField->seismicDataCollection() )
{
@@ -1534,11 +1535,6 @@ 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 ( RiaApplication::enableDevelopmentFeatures() )
{
if ( oilField->polygonCollection() ) uiTreeOrdering.add( oilField->polygonCollection() );
}
}
uiTreeOrdering.add( colorLegendCollection() );

View File

@@ -101,6 +101,7 @@ set(SOURCE_UNITTEST_FILES
${CMAKE_CURRENT_LIST_DIR}/RifGridCalculationIO-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationIO-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RimEmReader-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifPolygonReader-Test.cpp
)
if(RESINSIGHT_ENABLE_GRPC)

View File

@@ -0,0 +1,99 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "gtest/gtest.h"
#include "RifPolygonReader.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RifPolygonReader, MultiplePolygonsInSameFile )
{
std::string fileContent = R"(
# This is a comment
# This is a comment
58177.76 732.7 1643.6
58260.83 732.8 1596.6
57985.66 732.7 1542.0
59601.45 732.4 3639.0
59422.01 732.2 3639.0
59793.41 732.2 3639.0
999 999 999
# starting polyline 2
58260.83 732.8 1596.6
57985.66 732.7 1542.0
59601.45 732.4 3639.0 )";
QString fileContentAsQString = QString::fromStdString( fileContent );
QString errorMessage;
auto polygons = RifPolygonReader::parseText( fileContentAsQString, &errorMessage );
EXPECT_TRUE( polygons.size() == 2 );
auto firstPolygon = polygons.front();
EXPECT_TRUE( firstPolygon.size() == 6 );
EXPECT_DOUBLE_EQ( firstPolygon.front().x(), 58177.76 );
auto secondPolygon = polygons.back();
EXPECT_TRUE( secondPolygon.size() == 3 );
EXPECT_DOUBLE_EQ( secondPolygon.back().x(), 59601.45 );
}
TEST( RifPolygonReader, CsvImport )
{
std::string fileContent = R"(
X_UTME,Y_UTMN,Z_TVDSS,POLY_ID
460536.5500488281,5934613.072753906,1652.97265625,0
460535.4345703125,5934678.220581055,1652.8203125,0
460534.3497314453,5934741.589111328,1652.672119140625,0
460534.5389404297,5934747.926269531,1652.6595458984375,0
460530.44287109375,5934829.321044922,1652.448974609375,0
460530.20642089844,5934842.320922852,1652.6920166015625,0
460535.5516357422,5934890.617675781,1653.71240234375,0
460548.05139160156,5935007.113769531,1656.166259765625,0
460550.3292236328,5935027.826538086,1656.641845703125,0
)";
QString fileContentAsQString = QString::fromStdString( fileContent );
QString errorMessage;
auto polygons = RifPolygonReader::parseTextCsv( fileContentAsQString, &errorMessage );
EXPECT_TRUE( polygons.size() == 1 );
auto firstPolygon = polygons.front();
EXPECT_TRUE( firstPolygon.second.size() == 9 );
EXPECT_DOUBLE_EQ( firstPolygon.second.back().z(), -1656.641845703125 );
}
TEST( RifPolygonReader, CsvImportNoHeader )
{
std::string fileContent = R"(
460536.5500488281,5934613.072753906,1652.97265625,0
460535.4345703125,5934678.220581055,1652.8203125,0
)";
QString fileContentAsQString = QString::fromStdString( fileContent );
QString errorMessage;
auto polygons = RifPolygonReader::parseTextCsv( fileContentAsQString, &errorMessage );
EXPECT_TRUE( polygons.size() == 1 );
auto firstPolygon = polygons.front();
EXPECT_TRUE( firstPolygon.second.size() == 2 );
}

View File

@@ -393,6 +393,7 @@ void RiuViewerCommands::displayContextMenu( QMouseEvent* event )
}
menuBuilder << "RicNewPolygonFilter3dviewFeature";
menuBuilder.addCmdFeature( "RicCreatePolygonFeature", "Polygon" );
menuBuilder << "RicEclipsePropertyFilterNewInViewFeature";
menuBuilder << "RicGeoMechPropertyFilterNewInViewFeature";

View File

@@ -204,7 +204,7 @@ void CmdFeatureMenuBuilder::appendToMenu( QMenu* menu )
}
else
{
act = commandManager->action( m_items[i].itemName );
act = commandManager->action( m_items[i].itemName, m_items[i].uiText );
}
CAF_ASSERT( act );

View File

@@ -47,12 +47,36 @@ std::unique_ptr<caf::PdmUiTreeViewItemAttribute::Tag> caf::PdmUiTreeViewItemAttr
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void caf::PdmUiTreeViewItemAttribute::createTagIfTreeViewItemAttribute( caf::PdmUiEditorAttribute* attribute,
std::unique_ptr<caf::PdmUiTreeViewItemAttribute::Tag>
caf::PdmUiTreeViewItemAttribute::createTag( const QColor& color, const QColor& backgroundColor, const QString& text )
{
auto tag = createTag();
auto weight1 = 100;
double transparency = 0.3;
int weight2 = std::max( 1, static_cast<int>( weight1 * 10 * transparency ) );
int weightsum = weight1 + weight2;
auto blendedColor = QColor( ( color.red() * weight1 + backgroundColor.red() * weight2 ) / weightsum,
( color.green() * weight1 + backgroundColor.green() * weight2 ) / weightsum,
( color.blue() * weight1 + backgroundColor.blue() * weight2 ) / weightsum );
tag->bgColor = blendedColor;
tag->fgColor = color;
tag->text = text;
return tag;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void caf::PdmUiTreeViewItemAttribute::appendTagToTreeViewItemAttribute( caf::PdmUiEditorAttribute* attribute,
const QString& iconResourceString )
{
if ( auto* treeItemAttribute = dynamic_cast<caf::PdmUiTreeViewItemAttribute*>( attribute ) )
{
treeItemAttribute->tags.clear();
auto tag = caf::PdmUiTreeViewItemAttribute::createTag();
tag->icon = caf::IconProvider( iconResourceString );

View File

@@ -76,7 +76,8 @@ public:
};
static std::unique_ptr<Tag> createTag();
static void createTagIfTreeViewItemAttribute( caf::PdmUiEditorAttribute* attribute, const QString& iconString );
static std::unique_ptr<Tag> createTag( const QColor& color, const QColor& backgroundColor, const QString& text );
static void appendTagToTreeViewItemAttribute( caf::PdmUiEditorAttribute* attribute, const QString& iconString );
std::vector<std::unique_ptr<Tag>> tags;
};