Refactor: simplify VTK surface parsing using pugixml

This commit is contained in:
Kristian Bendiksen committed 2025-03-07 10:34:48 +01:00
1 parent c66f4f8158
commit 7908c8186f
18 files changed
+282 -330

No files matched your search

@@ -18,7 +18,7 @@
#include "RifSurfaceImporter.h"
#include "RiaStdStringTools.h"
#include "RigGocadData.h"
#include "RigTriangleMeshData.h"
#include "cafProgressInfo.h"
@@ -43,9 +43,9 @@
/// Returns vertices with z-value as depth, z is increasing downwards
///
//--------------------------------------------------------------------------------------------------
void RifSurfaceImporter::readGocadFile( const QString& filename, RigGocadData* gocadData )
void RifSurfaceImporter::readGocadFile( const QString& filename, RigTriangleMeshData* triangleMeshData )
{
CVF_ASSERT( gocadData );
CVF_ASSERT( triangleMeshData );
enum class GocadZPositive
{
@@ -204,10 +204,10 @@ void RifSurfaceImporter::readGocadFile( const QString& filename, RigGocadData* g
}
}
if ( gocadData )
if ( triangleMeshData )
{
gocadData->setGeometryData( vertices, triangleIndices );
gocadData->setPropertyData( propertyNames, propertyValues );
triangleMeshData->setGeometryData( vertices, triangleIndices );
triangleMeshData->setPropertyData( propertyNames, propertyValues );
}
}
@@ -26,12 +26,12 @@
#include <QString>
class RigGocadData;
class RigTriangleMeshData;
class RifSurfaceImporter
{
public:
static void readGocadFile( const QString& filename, RigGocadData* gocadData );
static void readGocadFile( const QString& filename, RigTriangleMeshData* triangleMeshData );
static std::pair<std::vector<cvf::Vec3d>, std::vector<unsigned>> readPetrelFile( const QString& filename );
static std::pair<std::vector<cvf::Vec3d>, std::vector<unsigned>> readOpenWorksXyzFile( const QString& filename,
double preferredPointDistance );
@@ -18,8 +18,7 @@
#include "RifVtkSurfaceImporter.h"
#include "../../Fwk/VizFwk/LibIo/cvfTinyXmlFused.hpp"
#include "RigGocadData.h"
#include "RigTriangleMeshData.h"
#include <filesystem>
#include <memory>
@@ -27,60 +26,39 @@
#include <string>
#include <vector>
namespace RifVtkSurfaceImporter
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::unique_ptr<RigTriangleMeshData> RifVtkSurfaceImporter::importFromFile( const std::filesystem::path& filepath )
{
using namespace cvf_tinyXML;
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file( filepath.string().c_str() );
if ( !result ) return nullptr;
bool importFromFile( std::string filename, RigGocadData* gocadData )
{
TiXmlDocument doc;
if ( !doc.LoadFile( filename.c_str() ) )
{
return false;
}
return importFromXmlDoc( doc, gocadData );
return importFromXmlDoc( doc );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool importFromPvdFile( const std::string& filename, RigGocadData* gocadData )
std::unique_ptr<RigTriangleMeshData> RifVtkSurfaceImporter::importFromXmlDoc( const pugi::xml_document& doc )
{
auto datasets = parsePvdDatasets( filename );
auto root = doc.child( "VTKFile" );
if ( !root ) return nullptr;
if ( datasets.empty() ) return false;
auto grid = root.child( "UnstructuredGrid" );
if ( !grid ) return nullptr;
// Sort and import the most recent dataset
std::sort( datasets.begin(), datasets.end(), []( const PvdDataset& a, const PvdDataset& b ) { return a.timestep < b.timestep; } );
return importDataset( datasets.back(), gocadData );
}
bool importFromXmlDoc( const TiXmlDocument& doc, RigGocadData* gocadData )
{
auto* root = doc.FirstChildElement( "VTKFile" );
if ( !root ) return false;
auto* grid = root->FirstChildElement( "UnstructuredGrid" );
if ( !grid ) return false;
auto* piece = grid->FirstChildElement( "Piece" );
if ( !piece ) return false;
auto piece = grid.child( "Piece" );
if ( !piece ) return nullptr;
// Read points
std::vector<cvf::Vec3d> vertices;
if ( !readPoints( piece, vertices ) )
{
return false;
}
std::vector<cvf::Vec3d> vertices = readPoints( piece );
if ( vertices.empty() ) return nullptr;
// Read connectivity
std::vector<unsigned> connectivity;
if ( !readConnectivity( piece, connectivity ) )
{
return false;
}
std::vector<unsigned> connectivity = readConnectivity( piece );
if ( connectivity.empty() ) return nullptr;
// Avoid shared nodes
std::vector<cvf::Vec3d> nonSharedVertices;
@@ -99,69 +77,70 @@ bool importFromXmlDoc( const TiXmlDocument& doc, RigGocadData* gocadData )
}
// Set geometry data
gocadData->setGeometryData( nonSharedVertices, nonSharedConnectivity );
auto triangleMeshData = std::make_unique<RigTriangleMeshData>();
triangleMeshData->setGeometryData( nonSharedVertices, nonSharedConnectivity );
// Read properties
std::vector<std::string> propertyNamesOnFile;
std::vector<std::vector<float>> propertyValuesOnFile;
readProperties( piece, propertyNamesOnFile, propertyValuesOnFile );
if ( propertyNamesOnFile.size() == propertyValuesOnFile.size() )
const std::map<std::string, std::vector<float>> properties = readProperties( piece );
for ( const auto& [name, values] : properties )
{
for ( size_t i = 0; i < propertyValuesOnFile.size(); i++ )
// These values are per element, so we need to duplicate them for each node
if ( values.size() * 3 == nonSharedVertices.size() )
{
// These values are per element, so we need to duplicate them for each node
auto values = propertyValuesOnFile[i];
if ( values.size() * 3 == nonSharedVertices.size() )
std::vector<float> valuesForEachNode;
for ( auto value : values )
{
std::vector<float> valuesForEachNode;
for ( auto value : values )
{
valuesForEachNode.push_back( value );
valuesForEachNode.push_back( value );
valuesForEachNode.push_back( value );
}
gocadData->addPropertyData( QString::fromStdString( propertyNamesOnFile[i] ), valuesForEachNode );
valuesForEachNode.push_back( value );
valuesForEachNode.push_back( value );
valuesForEachNode.push_back( value );
}
triangleMeshData->addPropertyData( QString::fromStdString( name ), valuesForEachNode );
}
}
return true;
return triangleMeshData;
}
bool readPoints( const TiXmlElement* piece, std::vector<cvf::Vec3d>& vertices )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<cvf::Vec3d> RifVtkSurfaceImporter::readPoints( const pugi::xml_node& piece )
{
auto* points = piece->FirstChildElement( "Points" );
if ( !points ) return false;
auto points = piece.child( "Points" );
if ( !points ) return {};
auto* coords = points->FirstChildElement( "DataArray" );
if ( !coords || strcmp( coords->Attribute( "Name" ), "Coordinates" ) != 0 ) return false;
auto coords = points.child( "DataArray" );
if ( !coords || std::string( coords.attribute( "Name" ).value() ) != "Coordinates" ) return {};
std::string coordsText = coords->GetText();
std::istringstream iss( coordsText );
std::vector<cvf::Vec3d> vertices;
std::istringstream iss( coords.text().get() );
double x, y, z;
while ( iss >> x >> y >> z )
{
vertices.push_back( cvf::Vec3d( x, y, -z ) );
vertices.emplace_back( x, y, -z );
}
return !vertices.empty();
return vertices;
}
bool readConnectivity( const TiXmlElement* piece, std::vector<unsigned>& connectivity )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<unsigned> RifVtkSurfaceImporter::readConnectivity( const pugi::xml_node& piece )
{
auto* cells = piece->FirstChildElement( "Cells" );
if ( !cells ) return false;
auto cells = piece.child( "Cells" );
if ( !cells ) return {};
std::vector<unsigned> connectivity;
auto connectivityArray = cells.child( "DataArray" );
auto* connectivityArray = cells->FirstChildElement( "DataArray" );
while ( connectivityArray )
{
if ( strcmp( connectivityArray->Attribute( "Name" ), "connectivity" ) == 0 )
if ( std::string( connectivityArray.attribute( "Name" ).value() ) == "connectivity" )
{
std::string connectivityText = connectivityArray->GetText();
std::string connectivityText = connectivityArray.text().get();
std::istringstream iss( connectivityText );
unsigned index;
@@ -171,26 +150,29 @@ bool readConnectivity( const TiXmlElement* piece, std::vector<unsigned>& connect
}
break;
}
connectivityArray = connectivityArray->NextSiblingElement( "DataArray" );
connectivityArray = connectivityArray.next_sibling( "DataArray" );
}
return !connectivity.empty();
return connectivity;
}
void readProperties( const TiXmlElement* piece, std::vector<std::string>& propertyNames, std::vector<std::vector<float>>& propertyValues )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::map<std::string, std::vector<float>> RifVtkSurfaceImporter::readProperties( const pugi::xml_node& piece )
{
auto* cellData = piece->FirstChildElement( "CellData" );
if ( !cellData ) return;
auto cellData = piece.child( "CellData" );
if ( !cellData ) return {};
auto* dataArray = cellData->FirstChildElement( "DataArray" );
while ( dataArray )
std::map<std::string, std::vector<float>> properties;
for ( const auto& dataArray : cellData.children( "DataArray" ) )
{
const char* name = dataArray->Attribute( "Name" );
if ( name )
const char* name = dataArray.attribute( "Name" ).value();
if ( name && *name )
{
std::vector<float> values;
std::string valuesText = dataArray->GetText();
std::istringstream iss( valuesText );
std::istringstream iss( dataArray.text().get() );
float value;
while ( iss >> value )
@@ -200,64 +182,46 @@ void readProperties( const TiXmlElement* piece, std::vector<std::string>& proper
if ( !values.empty() )
{
propertyNames.push_back( name );
propertyValues.push_back( values );
properties[name] = std::move( values );
}
}
dataArray = dataArray->NextSiblingElement( "DataArray" );
}
return properties;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RifVtkSurfaceImporter::PvdDataset> parsePvdDatasets( const std::string& filename )
std::vector<RifVtkSurfaceImporter::PvdDataset> RifVtkSurfaceImporter::parsePvdDatasets( const std::filesystem::path& filepath )
{
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file( filepath.string().c_str() );
if ( !result ) return {};
auto root = doc.child( "VTKFile" );
if ( !root ) return {};
auto collection = root.child( "Collection" );
if ( !collection ) return {};
std::filesystem::path baseDir = filepath.parent_path();
std::vector<PvdDataset> datasets;
TiXmlDocument doc;
if ( !doc.LoadFile( filename.c_str() ) ) return datasets;
auto* root = doc.FirstChildElement( "VTKFile" );
if ( !root ) return datasets;
auto* collection = root->FirstChildElement( "Collection" );
if ( !collection ) return datasets;
std::string baseDir = std::filesystem::path( filename ).parent_path().string();
auto* datasetElem = collection->FirstChildElement( "DataSet" );
while ( datasetElem )
for ( const auto& datasetElem : collection.children( "DataSet" ) )
{
const char* file = datasetElem->Attribute( "file" );
const char* timestepStr = datasetElem->Attribute( "timestep" );
const char* file = datasetElem.attribute( "file" ).value();
const char* timestepStr = datasetElem.attribute( "timestep" ).value();
if ( file && timestepStr )
{
double timestep = std::stod( timestepStr );
std::string fullPath = std::filesystem::absolute( std::filesystem::path( baseDir ) / file ).string();
double timestep = std::stod( timestepStr );
std::filesystem::path fullPath = std::filesystem::absolute( baseDir / file );
datasets.push_back( { timestep, fullPath } );
}
datasetElem = datasetElem->NextSiblingElement( "DataSet" );
}
return datasets;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool importDataset( const PvdDataset& dataset, RigGocadData* gocadData )
{
TiXmlDocument doc;
if ( !doc.LoadFile( dataset.filename.c_str() ) )
{
return false;
}
return importFromXmlDoc( doc, gocadData );
}
}; // namespace RifVtkSurfaceImporter
@@ -18,6 +18,7 @@
#pragma once
#include <filesystem>
#include <map>
#include <memory>
#include <string>
@@ -25,38 +26,29 @@
#include "cvfVector3.h"
class RigGocadData;
#include "pugixml.hpp"
namespace cvf_tinyXML
{
class TiXmlDocument;
class TiXmlElement;
} // namespace cvf_tinyXML
class RigTriangleMeshData;
//==================================================================================================
///
//==================================================================================================
namespace RifVtkSurfaceImporter
class RifVtkSurfaceImporter
{
public:
struct PvdDataset
{
double timestep;
std::filesystem::path filepath;
};
struct PvdDataset
{
double timestep;
std::string filename;
static std::unique_ptr<RigTriangleMeshData> importFromFile( const std::filesystem::path& filepath );
static std::vector<PvdDataset> parsePvdDatasets( const std::filesystem::path& filepath );
private:
static std::unique_ptr<RigTriangleMeshData> importFromXmlDoc( const pugi::xml_document& doc );
static std::vector<cvf::Vec3d> readPoints( const pugi::xml_node& piece );
static std::vector<unsigned> readConnectivity( const pugi::xml_node& piece );
static std::map<std::string, std::vector<float>> readProperties( const pugi::xml_node& piece );
};
bool importFromFile( std::string filename, RigGocadData* gocadData );
bool importFromPvdFile( const std::string& filename, RigGocadData* gocadData );
bool importFromXmlDoc( const cvf_tinyXML::TiXmlDocument& doc, RigGocadData* gocadData );
bool readPoints( const cvf_tinyXML::TiXmlElement* piece, std::vector<cvf::Vec3d>& vertices );
bool readConnectivity( const cvf_tinyXML::TiXmlElement* piece, std::vector<unsigned>& connectivity );
void readProperties( const cvf_tinyXML::TiXmlElement* piece,
std::vector<std::string>& propertyNames,
std::vector<std::vector<float>>& propertyValues );
std::vector<PvdDataset> parsePvdDatasets( const std::string& filename );
bool importDataset( const PvdDataset& dataset, RigGocadData* gocadData );
}; // namespace RifVtkSurfaceImporter
@@ -25,8 +25,8 @@
#include "RifSurfaceImporter.h"
#include "RifVtkSurfaceImporter.h"
#include "RigGocadData.h"
#include "RigSurface.h"
#include "RigTriangleMeshData.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
@@ -135,12 +135,12 @@ bool RimFileSurface::updateSurfaceData()
surface->setTriangleData( tringleIndices, vertices );
}
if ( m_gocadData )
if ( m_triangleMeshData )
{
auto propertyNames = m_gocadData->propertyNames();
auto propertyNames = m_triangleMeshData->propertyNames();
for ( const auto& name : propertyNames )
{
auto values = m_gocadData->propertyValues( name );
auto values = m_triangleMeshData->propertyValues( name );
surface->addVerticeResult( name, values );
}
}
@@ -173,18 +173,17 @@ bool RimFileSurface::loadDataFromFile()
}
else if ( filePath.endsWith( "ts", Qt::CaseInsensitive ) )
{
m_gocadData = std::make_unique<RigGocadData>();
m_triangleMeshData = std::make_unique<RigTriangleMeshData>();
RifSurfaceImporter::readGocadFile( filePath, m_gocadData.get() );
RifSurfaceImporter::readGocadFile( filePath, m_triangleMeshData.get() );
surface = m_gocadData->gocadGeometry();
surface = m_triangleMeshData->geometry();
}
else if ( filePath.endsWith( "vtu", Qt::CaseInsensitive ) )
{
m_gocadData = std::make_unique<RigGocadData>();
RifVtkSurfaceImporter::importFromFile( filePath.toStdString(), m_gocadData.get() );
m_triangleMeshData = RifVtkSurfaceImporter::importFromFile( filePath.toStdString() );
surface = m_gocadData->gocadGeometry();
surface = m_triangleMeshData->geometry();
}
else if ( filePath.endsWith( "dat", Qt::CaseInsensitive ) || filePath.endsWith( "xyz", Qt::CaseInsensitive ) )
{
@@ -22,7 +22,7 @@
#include <memory>
class RigGocadData;
class RigTriangleMeshData;
class RimFileSurface : public RimSurface
{
@@ -53,5 +53,5 @@ private:
std::vector<unsigned> m_tringleIndices;
std::vector<cvf::Vec3d> m_vertices;
std::unique_ptr<RigGocadData> m_gocadData;
std::unique_ptr<RigTriangleMeshData> m_triangleMeshData;
};
@@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020- Equinor ASA
// Copyright (C) 2025- 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
@@ -18,22 +18,18 @@
#include "RimFractureSurface.h"
#include "RiaPreferences.h"
#include "RigStatisticsMath.h"
#include "RigSurface.h"
#include "RigTriangleMeshData.h"
#include "RimRegularLegendConfig.h"
#include "RimSurfaceCollection.h"
#include "RifSurfaceImporter.h"
#include "RifVtkSurfaceImporter.h"
#include "RigGocadData.h"
#include "RigSurface.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
#include <QFileInfo>
#include <memory>
CAF_PDM_SOURCE_INIT( RimFractureSurface, "RimFractureSurface" );
//--------------------------------------------------------------------------------------------------
@@ -108,14 +104,14 @@ void RimFractureSurface::loadSurfaceDataForTimeStep( int timeStep )
auto surface = new RigSurface;
auto gocadData = m_surfacePerTimeStep[timeStep];
const auto& [coordinates, indices] = gocadData.gocadGeometry();
auto triangleMeshData = m_surfacePerTimeStep[timeStep].get();
const auto& [coordinates, indices] = triangleMeshData->geometry();
surface->setTriangleData( indices, coordinates );
auto propertyNames = gocadData.propertyNames();
auto propertyNames = triangleMeshData->propertyNames();
for ( const auto& name : propertyNames )
{
auto values = gocadData.propertyValues( name );
auto values = triangleMeshData->propertyValues( name );
surface->addVerticeResult( name, values );
}
setSurfaceData( surface );
@@ -127,11 +123,11 @@ void RimFractureSurface::loadSurfaceDataForTimeStep( int timeStep )
std::vector<std::vector<double>> RimFractureSurface::valuesForProperty( const QString& propertyName ) const
{
std::vector<std::vector<double>> values;
for ( auto allTimeStepValues : m_surfacePerTimeStep )
for ( const auto& allTimeStepValues : m_surfacePerTimeStep )
{
const auto& [coordinates, indices] = allTimeStepValues.gocadGeometry();
const auto& [coordinates, indices] = allTimeStepValues->geometry();
auto valuesOneTimeStep = allTimeStepValues.propertyValues( propertyName );
auto valuesOneTimeStep = allTimeStepValues->propertyValues( propertyName );
// convert to double vector
std::vector<double> valuesOneTimeStepDouble( valuesOneTimeStep.begin(), valuesOneTimeStep.end() );
@@ -178,11 +174,6 @@ void RimFractureSurface::clearCachedNativeData()
{
m_secondsSinceSimulationStart.clear();
m_surfacePerTimeStep.clear();
/*
m_vertices.clear();
m_tringleIndices.clear();
*/
}
//--------------------------------------------------------------------------------------------------
@@ -190,17 +181,61 @@ void RimFractureSurface::clearCachedNativeData()
//--------------------------------------------------------------------------------------------------
bool RimFractureSurface::loadDataFromFile()
{
auto surfaceInfo = RifVtkSurfaceImporter::parsePvdDatasets( m_surfaceDefinitionFilePath().path().toStdString() );
std::filesystem::path filepath = m_surfaceDefinitionFilePath().path().toLocal8Bit().constData();
auto surfaceInfo = RifVtkSurfaceImporter::parsePvdDatasets( filepath );
for ( const auto& s : surfaceInfo )
{
RigGocadData gocadData;
if ( RifVtkSurfaceImporter::importFromFile( s.filename, &gocadData ) )
if ( auto triangleMeshData = RifVtkSurfaceImporter::importFromFile( s.filepath ) )
{
m_secondsSinceSimulationStart.push_back( s.timestep );
m_surfacePerTimeStep.push_back( gocadData );
m_surfacePerTimeStep.push_back( std::move( triangleMeshData ) );
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFractureSurface::updateMinMaxValues( RimRegularLegendConfig* legendConfig, const QString& propertyName, int currentTimeStep ) const
{
double localMin = 0.0;
double localMax = 0.0;
double localPosClosestToZero = 0.0;
double localNegClosestToZero = 0.0;
auto valuesForTimeSteps = valuesForProperty( propertyName );
MinMaxAccumulator minMaxAccumulator;
PosNegAccumulator posNegAccumulator;
for ( size_t timeIndex = 0; timeIndex < valuesForTimeSteps.size(); timeIndex++ )
{
auto values = valuesForTimeSteps[timeIndex];
minMaxAccumulator.addData( values );
posNegAccumulator.addData( values );
if ( static_cast<int>( timeIndex ) == currentTimeStep )
{
MinMaxAccumulator localMinMaxAccumulator;
PosNegAccumulator localPosNegAccumulator;
localMinMaxAccumulator.addData( values );
localPosNegAccumulator.addData( values );
localPosClosestToZero = localPosNegAccumulator.pos;
localNegClosestToZero = localPosNegAccumulator.neg;
localMin = localMinMaxAccumulator.min;
localMax = localMinMaxAccumulator.max;
}
}
double globalPosClosestToZero = posNegAccumulator.pos;
double globalNegClosestToZero = posNegAccumulator.neg;
double globalMin = minMaxAccumulator.min;
double globalMax = minMaxAccumulator.max;
legendConfig->setClosestToZeroValues( globalPosClosestToZero, globalNegClosestToZero, localPosClosestToZero, localNegClosestToZero );
legendConfig->setAutomaticRanges( globalMin, globalMax, localMin, localMax );
}
@@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020- Equinor ASA
// Copyright (C) 2025- 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
@@ -20,10 +20,7 @@
#include "RimSurface.h"
#include "cafPdmChildArrayField.h"
class RimFileSurface;
class RigGocadData;
class RigTriangleMeshData;
class RimFractureSurface : public RimSurface
{
@@ -43,6 +40,8 @@ public:
std::vector<std::vector<double>> valuesForProperty( const QString& propertyName ) const;
void updateMinMaxValues( RimRegularLegendConfig* legend, const QString& propertyName, int currentTimeStep ) const override;
protected:
bool updateSurfaceData() override;
void clearCachedNativeData() override;
@@ -55,6 +54,6 @@ private:
caf::PdmField<caf::FilePath> m_surfaceDefinitionFilePath;
std::vector<size_t> m_secondsSinceSimulationStart;
std::vector<RigGocadData> m_surfacePerTimeStep;
std::vector<size_t> m_secondsSinceSimulationStart;
std::vector<std::unique_ptr<RigTriangleMeshData>> m_surfacePerTimeStep;
};
@@ -19,14 +19,15 @@
#include "RimSurface.h"
#include "RiaApplication.h"
#include "RimCase.h"
#include "RimProject.h"
#include "RimRegularLegendConfig.h"
#include "RimSurfaceCollection.h"
#include "RigStatisticsMath.h"
#include "RigSurface.h"
#include "RifSurfaceImporter.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
#include "cafPdmUiDoubleSliderEditor.h"
@@ -322,3 +323,27 @@ void RimSurface::defineEditorAttribute( const caf::PdmFieldHandle* field, QStrin
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurface::updateMinMaxValues( RimRegularLegendConfig* legend, const QString& propertyName, int currentTimeStep ) const
{
if ( !m_surfaceData.isNull() )
{
MinMaxAccumulator minMaxAccumulator;
PosNegAccumulator posNegAccumulator;
auto values = m_surfaceData->propertyValues( propertyName );
minMaxAccumulator.addData( values );
posNegAccumulator.addData( values );
double globalPosClosestToZero = posNegAccumulator.pos;
double globalNegClosestToZero = posNegAccumulator.neg;
double globalMin = minMaxAccumulator.min;
double globalMax = minMaxAccumulator.max;
legend->setClosestToZeroValues( globalPosClosestToZero, globalNegClosestToZero, globalPosClosestToZero, globalNegClosestToZero );
legend->setAutomaticRanges( globalMin, globalMax, globalMin, globalMax );
}
}
@@ -28,6 +28,7 @@
#include <vector>
class RimRegularLegendConfig;
class RigSurface;
class RimSurface : public caf::PdmObject
@@ -68,6 +69,8 @@ public:
void loadDataIfRequired();
void reloadData();
virtual void updateMinMaxValues( RimRegularLegendConfig* legend, const QString& propertyName, int currentTimeStep ) const;
protected:
void setSurfaceData( RigSurface* surface );
@@ -18,14 +18,11 @@
#include "RimSurfaceResultDefinition.h"
#include "RiaDefines.h"
#include "RiaResultNames.h"
#include "RigStatisticsMath.h"
#include "RigSurface.h"
#include "Rim3dView.h"
#include "RimFractureSurface.h"
#include "RimRegularLegendConfig.h"
#include "RimSurface.h"
#include "RimSurfaceInView.h"
@@ -90,82 +87,11 @@ RimRegularLegendConfig* RimSurfaceResultDefinition::legendConfig()
//--------------------------------------------------------------------------------------------------
void RimSurfaceResultDefinition::updateMinMaxValues( int currentTimeStep )
{
if ( !m_surfaceInView ) return;
if ( currentTimeStep < 0 ) currentTimeStep = 0;
// TODO: This is a hack, we need to find a better way to handle time dependent data for a surface
if ( auto fractureSurface = dynamic_cast<RimFractureSurface*>( m_surfaceInView->surface() ) )
{
double localMin = 0.0;
double localMax = 0.0;
double localPosClosestToZero = 0.0;
double localNegClosestToZero = 0.0;
double globalMin = 0.0;
double globalMax = 0.0;
double globalPosClosestToZero = 0.0;
double globalNegClosestToZero = 0.0;
auto valuesForTimeSteps = fractureSurface->valuesForProperty( m_propertyName );
MinMaxAccumulator minMaxAccumulator;
PosNegAccumulator posNegAccumulator;
for ( size_t timeIndex = 0; timeIndex < valuesForTimeSteps.size(); timeIndex++ )
{
auto values = valuesForTimeSteps[timeIndex];
minMaxAccumulator.addData( values );
posNegAccumulator.addData( values );
if ( static_cast<int>( timeIndex ) == currentTimeStep )
{
MinMaxAccumulator localMinMaxAccumulator;
PosNegAccumulator localPosNegAccumulator;
localMinMaxAccumulator.addData( values );
localPosNegAccumulator.addData( values );
localPosClosestToZero = localPosNegAccumulator.pos;
localNegClosestToZero = localPosNegAccumulator.neg;
localMin = localMinMaxAccumulator.min;
localMax = localMinMaxAccumulator.max;
}
}
globalPosClosestToZero = posNegAccumulator.pos;
globalNegClosestToZero = posNegAccumulator.neg;
globalMin = minMaxAccumulator.min;
globalMax = minMaxAccumulator.max;
m_legendConfig->setClosestToZeroValues( globalPosClosestToZero, globalNegClosestToZero, localPosClosestToZero, localNegClosestToZero );
m_legendConfig->setAutomaticRanges( globalMin, globalMax, localMin, localMax );
return;
}
RigSurface* surfData = surfaceData();
if ( surfData )
{
double globalMin = 0.0;
double globalMax = 0.0;
double globalPosClosestToZero = 0.0;
double globalNegClosestToZero = 0.0;
{
MinMaxAccumulator minMaxAccumulator;
PosNegAccumulator posNegAccumulator;
auto values = surfData->propertyValues( m_propertyName );
minMaxAccumulator.addData( values );
posNegAccumulator.addData( values );
globalPosClosestToZero = posNegAccumulator.pos;
globalNegClosestToZero = posNegAccumulator.neg;
globalMin = minMaxAccumulator.min;
globalMax = minMaxAccumulator.max;
}
m_legendConfig->setClosestToZeroValues( globalPosClosestToZero, globalNegClosestToZero, globalPosClosestToZero, globalNegClosestToZero );
m_legendConfig->setAutomaticRanges( globalMin, globalMax, globalMin, globalMax );
}
if ( auto surface = m_surfaceInView->surface() ) surface->updateMinMaxValues( m_legendConfig, m_propertyName, currentTimeStep );
}
//--------------------------------------------------------------------------------------------------
@@ -173,12 +99,12 @@ void RimSurfaceResultDefinition::updateMinMaxValues( int currentTimeStep )
//--------------------------------------------------------------------------------------------------
void RimSurfaceResultDefinition::assignDefaultProperty()
{
if ( m_surfaceInView->surface() && m_surfaceInView->surface()->surfaceData() )
if ( auto surface = surfaceData() )
{
auto propNames = m_surfaceInView->surface()->surfaceData()->propertyNames();
auto propNames = surface->propertyNames();
if ( !propNames.empty() )
{
m_propertyName = m_surfaceInView->surface()->surfaceData()->propertyNames().front();
m_propertyName = propNames.front();
}
}
}
@@ -24,8 +24,6 @@
#include "cafPdmObject.h"
#include "cafPdmPtrField.h"
#include "cvfObject.h"
class RimRegularLegendConfig;
class RimSurfaceInView;
class RigSurface;
@@ -41,7 +41,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RigFractureCell.h
${CMAKE_CURRENT_LIST_DIR}/RigFractureGrid.h
${CMAKE_CURRENT_LIST_DIR}/RigGeoMechBoreHoleStressCalculator.h
${CMAKE_CURRENT_LIST_DIR}/RigGocadData.h
${CMAKE_CURRENT_LIST_DIR}/RigTriangleMeshData.h
${CMAKE_CURRENT_LIST_DIR}/RigGridBase.h
${CMAKE_CURRENT_LIST_DIR}/RigGridCrossPlotCurveGrouping.h
${CMAKE_CURRENT_LIST_DIR}/RigGriddedPart3d.h
@@ -124,7 +124,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RigFractureCell.cpp
${CMAKE_CURRENT_LIST_DIR}/RigFractureGrid.cpp
${CMAKE_CURRENT_LIST_DIR}/RigGeoMechBoreHoleStressCalculator.cpp
${CMAKE_CURRENT_LIST_DIR}/RigGocadData.cpp
${CMAKE_CURRENT_LIST_DIR}/RigTriangleMeshData.cpp
${CMAKE_CURRENT_LIST_DIR}/RigGridBase.cpp
${CMAKE_CURRENT_LIST_DIR}/RigGriddedPart3d.cpp
${CMAKE_CURRENT_LIST_DIR}/RigGridManager.cpp
@@ -16,26 +16,26 @@
//
/////////////////////////////////////////////////////////////////////////////////
#include "RigGocadData.h"
#include "RigTriangleMeshData.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigGocadData::RigGocadData()
RigTriangleMeshData::RigTriangleMeshData()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigGocadData::~RigGocadData()
RigTriangleMeshData::~RigTriangleMeshData()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QString> RigGocadData::propertyNames()
std::vector<QString> RigTriangleMeshData::propertyNames()
{
return m_propertyNames;
}
@@ -43,7 +43,7 @@ std::vector<QString> RigGocadData::propertyNames()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<std::vector<cvf::Vec3d>, std::vector<unsigned>> RigGocadData::gocadGeometry()
std::pair<std::vector<cvf::Vec3d>, std::vector<unsigned>> RigTriangleMeshData::geometry()
{
return std::make_pair( m_vertices, m_tringleIndices );
}
@@ -51,7 +51,7 @@ std::pair<std::vector<cvf::Vec3d>, std::vector<unsigned>> RigGocadData::gocadGeo
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<float> RigGocadData::propertyValues( const QString& property )
std::vector<float> RigTriangleMeshData::propertyValues( const QString& property )
{
for ( size_t propertyIdx = 0; propertyIdx < m_propertyNames.size(); propertyIdx++ )
{
@@ -67,7 +67,7 @@ std::vector<float> RigGocadData::propertyValues( const QString& property )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigGocadData::setGeometryData( const std::vector<cvf::Vec3d>& nodeCoord, const std::vector<unsigned>& connectivities )
void RigTriangleMeshData::setGeometryData( const std::vector<cvf::Vec3d>& nodeCoord, const std::vector<unsigned>& connectivities )
{
m_vertices = nodeCoord;
m_tringleIndices = connectivities;
@@ -76,7 +76,7 @@ void RigGocadData::setGeometryData( const std::vector<cvf::Vec3d>& nodeCoord, co
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigGocadData::setPropertyData( const std::vector<QString>& propertyNames, std::vector<std::vector<float>>& propertyValues )
void RigTriangleMeshData::setPropertyData( const std::vector<QString>& propertyNames, std::vector<std::vector<float>>& propertyValues )
{
m_propertyNames = propertyNames;
m_propertyValues = propertyValues;
@@ -85,7 +85,7 @@ void RigGocadData::setPropertyData( const std::vector<QString>& propertyNames, s
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigGocadData::addPropertyData( const QString& propertyName, std::vector<float>& propertyValues )
void RigTriangleMeshData::addPropertyData( const QString& propertyName, std::vector<float>& propertyValues )
{
m_propertyNames.push_back( propertyName );
m_propertyValues.push_back( propertyValues );
@@ -23,14 +23,14 @@
#include "cvfVector3.h"
class RigGocadData
class RigTriangleMeshData
{
public:
RigGocadData();
~RigGocadData();
RigTriangleMeshData();
~RigTriangleMeshData();
std::vector<QString> propertyNames();
std::pair<std::vector<cvf::Vec3d>, std::vector<unsigned>> gocadGeometry();
std::pair<std::vector<cvf::Vec3d>, std::vector<unsigned>> geometry();
std::vector<float> propertyValues( const QString& property );
void setGeometryData( const std::vector<cvf::Vec3d>& nodeCoord, const std::vector<unsigned>& connectivities );
@@ -3,7 +3,7 @@
#include "RifSurfaceImporter.h"
#include "RiaTestDataDirectory.h"
#include "RigGocadData.h"
#include "RigTriangleMeshData.h"
#include "QDir"
#include <QString>
@@ -17,10 +17,10 @@ TEST( RifSurfaceImporter, GocadReadValidFile )
QString filePath = baseFolder.absoluteFilePath( filename );
EXPECT_TRUE( QFile::exists( filePath ) );
RigGocadData gocadData;
RifSurfaceImporter::readGocadFile( filePath, &gocadData );
RigTriangleMeshData triangleMeshData;
RifSurfaceImporter::readGocadFile( filePath, &triangleMeshData );
auto surface = gocadData.gocadGeometry();
auto surface = triangleMeshData.geometry();
auto vertices = surface.first;
auto indices = surface.second;
@@ -39,10 +39,10 @@ TEST( RifSurfaceImporter, GocadReadWrongIndices )
QString filePath = baseFolder.absoluteFilePath( filename );
EXPECT_TRUE( QFile::exists( filePath ) );
RigGocadData gocadData;
RifSurfaceImporter::readGocadFile( filePath, &gocadData );
RigTriangleMeshData triangleMeshData;
RifSurfaceImporter::readGocadFile( filePath, &triangleMeshData );
auto surface = gocadData.gocadGeometry();
auto surface = triangleMeshData.geometry();
auto vertices = surface.first;
auto indices = surface.second;
@@ -58,19 +58,19 @@ TEST( RifSurfaceImporter, GocadReadProperties )
QString filePath = baseFolder.absoluteFilePath( filename );
EXPECT_TRUE( QFile::exists( filePath ) );
RigGocadData gocadData;
RifSurfaceImporter::readGocadFile( filePath, &gocadData );
RigTriangleMeshData triangleMeshData;
RifSurfaceImporter::readGocadFile( filePath, &triangleMeshData );
auto surface = gocadData.gocadGeometry();
auto surface = triangleMeshData.geometry();
auto vertices = surface.first;
auto indices = surface.second;
std::vector<QString> propNames = gocadData.propertyNames();
std::vector<QString> propNames = triangleMeshData.propertyNames();
EXPECT_TRUE( propNames.size() == 3 );
EXPECT_TRUE( propNames[0] == "SX" );
std::vector<float> propValues_SX = gocadData.propertyValues( propNames[0] );
std::vector<float> propValues_SX = triangleMeshData.propertyValues( propNames[0] );
float SX_first = propValues_SX[0];
float SX_second = propValues_SX[1];
@@ -80,7 +80,7 @@ TEST( RifSurfaceImporter, GocadReadProperties )
EXPECT_NEAR( 0.000972, SX_second, 1e-4 );
EXPECT_NEAR( 0.004293, SX_last, 1e-4 );
std::vector<float> propValues_SY = gocadData.propertyValues( "SY" );
std::vector<float> propValues_SY = triangleMeshData.propertyValues( "SY" );
float SY_first = propValues_SY[0];
float SY_second = propValues_SY[1];
@@ -99,11 +99,11 @@ TEST( RifSurfaceImporter, GocadReadNoProperty )
QString filePath = baseFolder.absoluteFilePath( filename );
EXPECT_TRUE( QFile::exists( filePath ) );
RigGocadData gocadData;
RifSurfaceImporter::readGocadFile( filePath, &gocadData );
RigTriangleMeshData triangleMeshData;
RifSurfaceImporter::readGocadFile( filePath, &triangleMeshData );
std::vector<QString> propNames = gocadData.propertyNames();
std::vector<float> propValues = gocadData.propertyValues( "" );
std::vector<QString> propNames = triangleMeshData.propertyNames();
std::vector<float> propValues = triangleMeshData.propertyValues( "" );
EXPECT_TRUE( propNames.empty() );
EXPECT_TRUE( propValues.empty() );
@@ -117,10 +117,10 @@ TEST( RifSurfaceImporter, GocadReadNonExistingProperty )
QString filePath = baseFolder.absoluteFilePath( filename );
EXPECT_TRUE( QFile::exists( filePath ) );
RigGocadData gocadData;
RifSurfaceImporter::readGocadFile( filePath, &gocadData );
RigTriangleMeshData triangleMeshData;
RifSurfaceImporter::readGocadFile( filePath, &triangleMeshData );
std::vector<float> propValues = gocadData.propertyValues( "NonExistingProperty" );
std::vector<float> propValues = triangleMeshData.propertyValues( "NonExistingProperty" );
EXPECT_TRUE( propValues.empty() );
}
@@ -134,10 +134,10 @@ TEST( RifSurfaceImporter, ReadWrongFileType )
QString filePath = baseFolder.absoluteFilePath( filename );
EXPECT_TRUE( QFile::exists( filePath ) );
RigGocadData gocadData;
RifSurfaceImporter::readGocadFile( filePath, &gocadData );
RigTriangleMeshData triangleMeshData;
RifSurfaceImporter::readGocadFile( filePath, &triangleMeshData );
auto surface = gocadData.gocadGeometry();
auto surface = triangleMeshData.geometry();
auto vertices = surface.first;
auto indices = surface.second;
+10
View File
@@ -717,6 +717,16 @@ else()
list(APPEND THIRD_PARTY_LIBRARIES Parquet::parquet_static)
endif()
# ##############################################################################
# pugixml
# ##############################################################################
find_package(pugixml CONFIG REQUIRED)
if(MSVC)
list(APPEND THIRD_PARTY_LIBRARIES pugixml::pugixml)
else()
list(APPEND THIRD_PARTY_LIBRARIES pugixml::static)
endif()
# ##############################################################################
# nonstd::type-lite
# ##############################################################################
+2 -1
View File
@@ -8,7 +8,8 @@
"grpc",
"type-lite",
"fast-float",
"spdlog"
"spdlog",
"pugixml"
],
"overrides": [
{