diff --git a/external/mdal/api/mdal.h b/external/mdal/api/mdal.h index 7e597e6c51e..40242225b20 100644 --- a/external/mdal/api/mdal.h +++ b/external/mdal/api/mdal.h @@ -117,7 +117,7 @@ MDAL_EXPORT MDAL_Status MDAL_LastStatus(); */ MDAL_EXPORT void MDAL_ResetStatus(); -/* +/** * Sets the last status message * \since MDAL 0.9.0 */ @@ -215,6 +215,13 @@ MDAL_EXPORT const char *MDAL_DR_longName( MDAL_DriverH driver ); */ MDAL_EXPORT const char *MDAL_DR_filters( MDAL_DriverH driver ); +/** + * Returns the maximum number of vertices per face supported by the driver + * + * \since MDAL 0.9.0 + */ +MDAL_EXPORT int MDAL_DR_faceVerticesMaximumCount( MDAL_DriverH driver ); + /////////////////////////////////////////////////////////////////////////////////////// /// MESH /////////////////////////////////////////////////////////////////////////////////////// @@ -266,6 +273,16 @@ MDAL_EXPORT MDAL_MeshH MDAL_CreateMesh( MDAL_DriverH driver ); */ MDAL_EXPORT void MDAL_SaveMesh( MDAL_MeshH mesh, const char *meshFile, const char *driver ); +/** + * Saves mesh (only mesh structure) on a file with an uri. On error see MDAL_LastStatus for error type. + * + * uri has form :""[:] + * examples: Ugrid:"mesh.nc":0, Ugrid:"mesh.nc":mesh2d, Ugrid:"mesh.nc" + * + * since MDAL 0.9 + */ +MDAL_EXPORT void MDAL_SaveMeshWithUri( MDAL_MeshH mesh, const char *uri ); + /** * Returns mesh projection * not thread-safe and valid only till next call @@ -331,7 +348,7 @@ MDAL_EXPORT int MDAL_M_edgeCount( MDAL_MeshH mesh ); MDAL_EXPORT int MDAL_M_faceCount( MDAL_MeshH mesh ); /** - * Returns maximum number of vertices face can consist of, e.g. 4 for regular quad mesh + * Returns maximum number of vertices per face for this mesh, can consist of, e.g. 4 for regular quad mesh. */ MDAL_EXPORT int MDAL_M_faceVerticesMaximumCount( MDAL_MeshH mesh ); @@ -343,6 +360,36 @@ MDAL_EXPORT int MDAL_M_faceVerticesMaximumCount( MDAL_MeshH mesh ); */ MDAL_EXPORT void MDAL_M_LoadDatasets( MDAL_MeshH mesh, const char *datasetFile ); +/** + * Returns number of metadata values + * + * \since MDAL 0.9.0 + */ +MDAL_EXPORT int MDAL_M_metadataCount( MDAL_MeshH mesh ); + +/** + * Returns dataset metadata key + * not thread-safe and valid only till next call + * + * \since MDAL 0.9.0 + */ +MDAL_EXPORT const char *MDAL_M_metadataKey( MDAL_MeshH mesh, int index ); + +/** + * Returns dataset metadata value + * not thread-safe and valid only till next call + * + * \since MDAL 0.9.0 + */ +MDAL_EXPORT const char *MDAL_M_metadataValue( MDAL_MeshH mesh, int index ); + +/** + * Adds new metadata to the mesh + * + * \since MDAL 0.9.0 + */ +MDAL_EXPORT void MDAL_M_setMetadata( MDAL_MeshH mesh, const char *key, const char *val ); + /** * Returns dataset groups count */ @@ -580,6 +627,36 @@ MDAL_EXPORT MDAL_DatasetH MDAL_G_addDataset( const int *active ); +/** + * Adds empty (new) 3D dataset to the group + * This increases dataset group count MDAL_G_datasetCount() by 1 + * + * The dataset is opened in edit mode. + * To persist dataset, call MDAL_G_closeEditMode() on parent group + * + * Minimum and maximum dataset values are automatically calculated + * + * Only for 3D datasets + * + * \param group parent group handle + * \param time time for dataset (hours) + * \param values For scalar data, the size must be volume count + * For vector data , the size must be volume count * 2 (x1, y1, x2, y2, ..., xN, yN) + * \param verticalLevelCount Int Array holding the number of vertical levels for each face. + * Size must be the face count + * \param verticalExtrusion Double Array holding the vertical level values for the voxels + * Size must be Face count + Volume count + * \returns empty pointer if not possible to create dataset (e.g. group opened in read mode), otherwise handle to new dataset + */ + +MDAL_EXPORT MDAL_DatasetH MDAL_G_addDataset3D( + MDAL_DatasetGroupH group, + double time, + const double *values, + const int *verticalLevelCount, + const double *verticalExtrusions +); + /** * Returns whether dataset group is in edit mode */ diff --git a/external/mdal/frmts/mdal_2dm.cpp b/external/mdal/frmts/mdal_2dm.cpp index e9cb577ee17..cb1dd882297 100644 --- a/external/mdal/frmts/mdal_2dm.cpp +++ b/external/mdal/frmts/mdal_2dm.cpp @@ -376,15 +376,15 @@ std::unique_ptr MDAL::Driver2dm::load( const std::string &meshFile, return std::unique_ptr( mesh.release() ); } -void MDAL::Driver2dm::save( const std::string &uri, MDAL::Mesh *mesh ) +void MDAL::Driver2dm::save( const std::string &fileName, const std::string &, MDAL::Mesh *mesh ) { MDAL::Log::resetLastStatus(); - std::ofstream file( uri, std::ofstream::out ); + std::ofstream file( fileName, std::ofstream::out ); if ( !file.is_open() ) { - MDAL::Log::error( MDAL_Status::Err_FailToWriteToDisk, name(), "Could not open file " + uri ); + MDAL::Log::error( MDAL_Status::Err_FailToWriteToDisk, name(), "Could not open file " + fileName ); } std::string line = "MESH2D"; diff --git a/external/mdal/frmts/mdal_2dm.hpp b/external/mdal/frmts/mdal_2dm.hpp index 23882397190..838c20aba6f 100644 --- a/external/mdal/frmts/mdal_2dm.hpp +++ b/external/mdal/frmts/mdal_2dm.hpp @@ -87,7 +87,7 @@ namespace MDAL bool canReadMesh( const std::string &uri ) override; std::unique_ptr< Mesh > load( const std::string &meshFile, const std::string &meshName = "" ) override; - void save( const std::string &uri, Mesh *mesh ) override; + void save( const std::string &fileName, const std::string &, Mesh *mesh ) override; std::string saveMeshOnFileSuffix() const override; diff --git a/external/mdal/frmts/mdal_driver.cpp b/external/mdal/frmts/mdal_driver.cpp index 19ffcf6f967..95fd170e354 100644 --- a/external/mdal/frmts/mdal_driver.cpp +++ b/external/mdal/frmts/mdal_driver.cpp @@ -83,7 +83,8 @@ std::unique_ptr< MDAL::Mesh > MDAL::Driver::load( const std::string &, const std void MDAL::Driver::load( const std::string &, Mesh * ) {} -void MDAL::Driver::save( const std::string &, MDAL::Mesh * ) {} +void MDAL::Driver::save( const std::string &, const std::string &, MDAL::Mesh * ) +{} void MDAL::Driver::createDatasetGroup( MDAL::Mesh *mesh, const std::string &groupName, MDAL_DataLocation dataLocation, bool hasScalarData, const std::string &datasetGroupFile ) { @@ -116,4 +117,27 @@ void MDAL::Driver::createDataset( MDAL::DatasetGroup *group, MDAL::RelativeTimes group->datasets.push_back( dataset ); } +void MDAL::Driver::createDataset( MDAL::DatasetGroup *group, MDAL::RelativeTimestamp time, const double *values, const int *verticalLevelCounts, const double *verticalExtrusions ) +{ + size_t count = 0; + size_t facesCount = group->mesh()->facesCount(); + int maxVerticalLevel = 0; + for ( size_t i = 0; i < facesCount; i++ ) + { + count += verticalLevelCounts[i]; + if ( verticalLevelCounts[i] > maxVerticalLevel ) maxVerticalLevel = verticalLevelCounts[i]; + }; + + std::shared_ptr dataset = std::make_shared< MemoryDataset3D >( group, count, maxVerticalLevel, verticalLevelCounts, verticalExtrusions ); + dataset->setTime( time ); + + if ( !group->isScalar() ) + count *= 2; + + memcpy( dataset->values(), values, sizeof( double ) * count ); + + dataset->setStatistics( MDAL::calculateStatistics( dataset ) ); + group->datasets.push_back( dataset ); +} + bool MDAL::Driver::persist( MDAL::DatasetGroup * ) { return true; } // failure diff --git a/external/mdal/frmts/mdal_driver.hpp b/external/mdal/frmts/mdal_driver.hpp index d34db86f8b6..87a60dfd396 100644 --- a/external/mdal/frmts/mdal_driver.hpp +++ b/external/mdal/frmts/mdal_driver.hpp @@ -58,7 +58,7 @@ namespace MDAL // loads datasets virtual void load( const std::string &uri, Mesh *mesh ); // save mesh - virtual void save( const std::string &uri, Mesh *mesh ); + virtual void save( const std::string &fileName, const std::string &meshName, Mesh *mesh ); // create new dataset group virtual void createDatasetGroup( @@ -68,12 +68,19 @@ namespace MDAL bool hasScalarData, const std::string &datasetGroupFile ); - // create new dataset from array + // create new 2D dataset from array virtual void createDataset( DatasetGroup *group, RelativeTimestamp time, const double *values, const int *active ); + // create new 3D dataset from array + virtual void createDataset( DatasetGroup *group, + RelativeTimestamp time, + const double *values, + const int *verticalLevelCount, + const double *verticalExtrusion ); + // persist to the file // returns true on error, false on success virtual bool persist( DatasetGroup *group ); diff --git a/external/mdal/frmts/mdal_selafin.cpp b/external/mdal/frmts/mdal_selafin.cpp index 594207f73c0..5ad83feae09 100644 --- a/external/mdal/frmts/mdal_selafin.cpp +++ b/external/mdal/frmts/mdal_selafin.cpp @@ -728,7 +728,7 @@ bool MDAL::DriverSelafin::saveDatasetGroupOnFile( MDAL::DatasetGroup *datasetGro if ( ! MDAL::fileExists( fileName ) ) { //create a new mesh file - save( fileName, datasetGroup->mesh() ); + save( fileName, "", datasetGroup->mesh() ); if ( ! MDAL::fileExists( fileName ) ) throw MDAL::Error( MDAL_Status::Err_FailToWriteToDisk, "Unable to create new file" ); @@ -983,9 +983,9 @@ static void writeVertices( std::ofstream &file, MDAL::Mesh *mesh ) writeValueArrayRecord( file, yValues ); } -void MDAL::DriverSelafin::save( const std::string &uri, MDAL::Mesh *mesh ) +void MDAL::DriverSelafin::save( const std::string &fileName, const std::string &, MDAL::Mesh *mesh ) { - std::ofstream file( uri.c_str(), std::ofstream::binary ); + std::ofstream file( fileName.c_str(), std::ofstream::binary ); std::string header( "Selafin file created by MDAL library" ); std::string remainingStr( " ", 72 - header.size() ); diff --git a/external/mdal/frmts/mdal_selafin.hpp b/external/mdal/frmts/mdal_selafin.hpp index c4ea807e15c..2ad549400b3 100644 --- a/external/mdal/frmts/mdal_selafin.hpp +++ b/external/mdal/frmts/mdal_selafin.hpp @@ -325,7 +325,7 @@ namespace MDAL bool persist( DatasetGroup *group ) override; int faceVerticesMaximumCount() const override {return 3;} - void save( const std::string &uri, Mesh *mesh ) override; + void save( const std::string &fileName, const std::string &meshName, Mesh *mesh ) override; std::string writeDatasetOnFileSuffix() const override; std::string saveMeshOnFileSuffix() const override; diff --git a/external/mdal/frmts/mdal_ugrid.cpp b/external/mdal/frmts/mdal_ugrid.cpp index f5a6176410b..4eb39e904e5 100644 --- a/external/mdal/frmts/mdal_ugrid.cpp +++ b/external/mdal/frmts/mdal_ugrid.cpp @@ -18,12 +18,10 @@ MDAL::DriverUgrid::DriverUgrid() : DriverCF( "Ugrid", - "UGRID Results", + "UGRID", "*.nc", Capability::ReadMesh | Capability::SaveMesh ) -{ - -} +{} MDAL::DriverUgrid *MDAL::DriverUgrid::create() { @@ -673,9 +671,9 @@ void MDAL::DriverUgrid::parse2VariablesFromAttribute( const std::string &name, c } } -void MDAL::DriverUgrid::save( const std::string &uri, MDAL::Mesh *mesh ) +void MDAL::DriverUgrid::save( const std::string &fileName, const std::string &, MDAL::Mesh *mesh ) { - mFileName = uri; + mFileName = fileName; try { @@ -691,7 +689,7 @@ void MDAL::DriverUgrid::save( const std::string &uri, MDAL::Mesh *mesh ) } catch ( MDAL_Status error ) { - MDAL::Log::error( error, name(), "could not save file " + uri ); + MDAL::Log::error( error, name(), "could not save file " + fileName ); } catch ( MDAL::Error err ) { diff --git a/external/mdal/frmts/mdal_ugrid.hpp b/external/mdal/frmts/mdal_ugrid.hpp index 9144d044124..c12e21f45ba 100644 --- a/external/mdal/frmts/mdal_ugrid.hpp +++ b/external/mdal/frmts/mdal_ugrid.hpp @@ -26,7 +26,8 @@ namespace MDAL DriverUgrid(); ~DriverUgrid() override = default; DriverUgrid *create() override; - void save( const std::string &uri, Mesh *mesh ) override; + void save( const std::string &fileName, const std::string &meshName, Mesh *mesh ) override; + std::string saveMeshOnFileSuffix() const override; private: diff --git a/external/mdal/mdal.cpp b/external/mdal/mdal.cpp index 7e3d8f320e8..b13f7d08019 100644 --- a/external/mdal/mdal.cpp +++ b/external/mdal/mdal.cpp @@ -21,7 +21,7 @@ static const char *EMPTY_STR = ""; const char *MDAL_Version() { - return "0.8.90"; + return "0.8.92"; } MDAL_Status MDAL_LastStatus() @@ -171,6 +171,17 @@ const char *MDAL_DR_filters( MDAL_DriverH driver ) return _return_str( d->filters() ); } +int MDAL_DR_faceVerticesMaximumCount( MDAL_DriverH driver ) +{ + if ( !driver ) + { + MDAL::Log::error( MDAL_Status::Err_MissingDriver, "Driver is not valid (null)" ); + return -1; + } + MDAL::Driver *d = static_cast< MDAL::Driver * >( driver ); + return d->faceVerticesMaximumCount(); +} + /////////////////////////////////////////////////////////////////////////////////////// /// MESH /////////////////////////////////////////////////////////////////////////////////////// @@ -244,10 +255,52 @@ void MDAL_SaveMesh( MDAL_MeshH mesh, const char *meshFile, const char *driver ) } std::string filename( meshFile ); - MDAL::DriverManager::instance().save( static_cast< MDAL::Mesh * >( mesh ), filename, driverName ); + + std::string uri = MDAL::buildMeshUri( filename, "", driverName ); + + MDAL::DriverManager::instance().save( static_cast< MDAL::Mesh * >( mesh ), uri ); } +void MDAL_SaveMeshWithUri( MDAL_MeshH mesh, const char *uri ) +{ + MDAL::Log::resetLastStatus(); + + std::string meshFile; + std::string driverName; + std::string meshName; + + MDAL::parseDriverAndMeshFromUri( uri, driverName, meshFile, meshName ); + + if ( meshFile.empty() ) + { + MDAL::Log::error( MDAL_Status::Err_FileNotFound, "Mesh file is not valid (null)" ); + return; + } + + auto d = MDAL::DriverManager::instance().driver( driverName ); + + if ( !d ) + { + MDAL::Log::error( MDAL_Status::Err_MissingDriver, "No driver with name: " + driverName ); + return; + } + + if ( !d->hasCapability( MDAL::Capability::SaveMesh ) ) + { + MDAL::Log::error( MDAL_Status::Err_MissingDriverCapability, "Driver " + driverName + " does not have SaveMesh capability" ); + return; + } + + if ( d->faceVerticesMaximumCount() < MDAL_M_faceVerticesMaximumCount( mesh ) ) + { + MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, "Mesh is incompatible with driver " + driverName ); + return; + } + + MDAL::DriverManager::instance().save( static_cast< MDAL::Mesh * >( mesh ), uri ); +} + void MDAL_CloseMesh( MDAL_MeshH mesh ) { if ( mesh ) @@ -361,6 +414,80 @@ void MDAL_M_LoadDatasets( MDAL_MeshH mesh, const char *datasetFile ) MDAL::DriverManager::instance().loadDatasets( m, datasetFile ); } +int MDAL_M_metadataCount( MDAL_MeshH mesh ) +{ + if ( !mesh ) + { + MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, "Mesh is not valid (null)" ); + return 0; + } + MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh ); + int len = static_cast( m->metadata.size() ); + return len; +} + +const char *MDAL_M_metadataKey( MDAL_MeshH mesh, int index ) +{ + if ( !mesh ) + { + MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, "Mesh is not valid (null)" ); + return EMPTY_STR; + } + MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh ); + int len = static_cast( m->metadata.size() ); + if ( len <= index ) + { + MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, "Requested index: " + std::to_string( index ) + " is out of scope for metadata" ); + return EMPTY_STR; + } + size_t i = static_cast( index ); + return _return_str( m->metadata[i].first ); +} + +const char *MDAL_M_metadataValue( MDAL_MeshH mesh, int index ) +{ + if ( !mesh ) + { + MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, "Mesh is not valid (null)" ); + return EMPTY_STR; + } + MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh ); + int len = static_cast( m->metadata.size() ); + if ( len <= index ) + { + MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, "Requested index: " + std::to_string( index ) + " is out of scope for metadata" ); + return EMPTY_STR; + } + size_t i = static_cast( index ); + return _return_str( m->metadata[i].second ); +} + +void MDAL_M_setMetadata( MDAL_MeshH mesh, const char *key, const char *val ) +{ + if ( !mesh ) + { + MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, "Mesh is not valid (null)" ); + return; + } + + if ( !key ) + { + MDAL::Log::error( MDAL_Status::Err_InvalidData, "Passed pointer key is not valid (null)" ); + return; + } + + if ( !val ) + { + MDAL::Log::error( MDAL_Status::Err_InvalidData, "Passed pointer val is not valid (null)" ); + return; + } + + const std::string k( key ); + const std::string v( val ); + MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh ); + m->setMetadata( k, v ); +} + int MDAL_M_datasetGroupCount( MDAL_MeshH mesh ) { if ( !mesh ) @@ -812,7 +939,7 @@ MDAL_DatasetH MDAL_G_addDataset( MDAL_DatasetGroupH group, double time, const do if ( g->dataLocation() == MDAL_DataLocation::DataOnVolumes ) { - MDAL::Log::error( MDAL_Status::Err_MissingDriverCapability, "Dataset Group has data on 3D volumes" ); + MDAL::Log::error( MDAL_Status::Err_MissingDriverCapability, "Cannot save 3D dataset as a 2D dataset" ); return nullptr; } @@ -835,6 +962,55 @@ MDAL_DatasetH MDAL_G_addDataset( MDAL_DatasetGroupH group, double time, const do return nullptr; } +MDAL_DatasetH MDAL_G_addDataset3D( MDAL_DatasetGroupH group, double time, const double *values, const int *verticalLevelCount, const double *verticalExtrusions ) +{ + if ( !group ) + { + MDAL::Log::error( MDAL_Status::Err_IncompatibleDataset, "Dataset Group is not valid (null)" ); + return nullptr; + } + + if ( !values || !verticalLevelCount || !verticalExtrusions ) + { + MDAL::Log::error( MDAL_Status::Err_InvalidData, "Passed pointer Values are not valid" ); + return nullptr; + } + + MDAL::DatasetGroup *g = static_cast< MDAL::DatasetGroup * >( group ); + if ( !g->isInEditMode() ) + { + MDAL::Log::error( MDAL_Status::Err_IncompatibleDataset, "Dataset Group is not in edit mode" ); + return nullptr; + } + + const std::string driverName = g->driverName(); + std::shared_ptr dr = MDAL::DriverManager::instance().driver( driverName ); + if ( !dr ) + { + MDAL::Log::error( MDAL_Status::Err_MissingDriver, "Driver name " + driverName + " saved in dataset group could not be found" ); + return nullptr; + } + + if ( g->dataLocation() != MDAL_DataLocation::DataOnVolumes ) + { + MDAL::Log::error( MDAL_Status::Err_MissingDriverCapability, "Cannot write 3D data to a Dataset Group that does not have Data On Volumes" ); + return nullptr; + } + + const size_t index = g->datasets.size(); + MDAL::RelativeTimestamp t( time, MDAL::RelativeTimestamp::hours ); + dr->createDataset( g, + t, + values, + verticalLevelCount, + verticalExtrusions + ); + if ( index < g->datasets.size() ) // we have new dataset + return static_cast< MDAL_DatasetGroupH >( g->datasets[ index ].get() ); + else + return nullptr; +} + bool MDAL_G_isInEditMode( MDAL_DatasetGroupH group ) { if ( !group ) @@ -1319,4 +1495,3 @@ void MDAL_M_setProjection( MDAL_MeshH mesh, const char *projection ) static_cast( mesh )->setSourceCrsFromWKT( std::string( projection ) ); } - diff --git a/external/mdal/mdal_data_model.cpp b/external/mdal/mdal_data_model.cpp index be522d9e0d9..d1c53173e09 100644 --- a/external/mdal/mdal_data_model.cpp +++ b/external/mdal/mdal_data_model.cpp @@ -192,9 +192,9 @@ void MDAL::DatasetGroup::setMetadata( const std::string &key, const std::string metadata.push_back( std::make_pair( key, val ) ); } -void MDAL::DatasetGroup::setMetadata( const MDAL::Metadata &metadata ) +void MDAL::DatasetGroup::setMetadata( const MDAL::Metadata &new_metadata ) { - for ( const auto &meta : metadata ) + for ( const auto &meta : new_metadata ) setMetadata( meta.first, meta.second ); } @@ -363,6 +363,40 @@ void MDAL::Mesh::setSourceCrsFromPrjFile( const std::string &filename ) setSourceCrs( proj ); } +std::string MDAL::Mesh::getMetadata( const std::string &key ) +{ + for ( auto &pair : metadata ) + { + if ( pair.first == key ) + { + return pair.second; + } + } + return std::string(); +} + +void MDAL::Mesh::setMetadata( const std::string &key, const std::string &val ) +{ + bool found = false; + for ( auto &pair : metadata ) + { + if ( pair.first == key ) + { + found = true; + pair.second = val; + } + } + if ( !found ) + metadata.push_back( std::make_pair( key, val ) ); +} + +void MDAL::Mesh::setMetadata( const MDAL::Metadata &new_metadata ) +{ + for ( const auto &meta : new_metadata ) + setMetadata( meta.first, meta.second ); +} + + std::string MDAL::Mesh::uri() const { return mUri; diff --git a/external/mdal/mdal_data_model.hpp b/external/mdal/mdal_data_model.hpp index b7bfa00590c..5b6a1f1484e 100644 --- a/external/mdal/mdal_data_model.hpp +++ b/external/mdal/mdal_data_model.hpp @@ -152,7 +152,7 @@ namespace MDAL std::string getMetadata( const std::string &key ); void setMetadata( const std::string &key, const std::string &val ); - void setMetadata( const Metadata &metadata ); + void setMetadata( const Metadata &new_metadata ); std::string name(); void setName( const std::string &name ); @@ -267,6 +267,12 @@ namespace MDAL std::string crs() const; size_t faceVerticesMaximumCount() const; + std::string getMetadata( const std::string &key ); + void setMetadata( const std::string &key, const std::string &val ); + void setMetadata( const Metadata &new_metadata ); + + Metadata metadata; + virtual void closeSource() {}; virtual bool isEditable() const {return false;} diff --git a/external/mdal/mdal_driver_manager.cpp b/external/mdal/mdal_driver_manager.cpp index 30c9cb96dff..d53a0f0b8c9 100644 --- a/external/mdal/mdal_driver_manager.cpp +++ b/external/mdal/mdal_driver_manager.cpp @@ -163,13 +163,25 @@ void MDAL::DriverManager::loadDatasets( Mesh *mesh, const std::string &datasetFi MDAL::Log::error( MDAL_Status::Err_UnknownFormat, "No driver was able to load requested file: " + datasetFile ); } -void MDAL::DriverManager::save( MDAL::Mesh *mesh, const std::string &uri, const std::string &driverName ) const +void MDAL::DriverManager::save( Mesh *mesh, const std::string &uri ) const { - auto selectedDriver = driver( driverName ); + std::string driverName; + std::string meshName; + std::string fileName; + + MDAL::parseDriverAndMeshFromUri( uri, driverName, fileName, meshName ); + + std::shared_ptr selectedDriver = driver( driverName ); + + if ( !selectedDriver ) + { + MDAL::Log::error( MDAL_Status::Err_MissingDriver, "Could not find driver with name: " + driverName ); + return; + } std::unique_ptr drv( selectedDriver->create() ); - drv->save( uri, mesh ); + drv->save( fileName, meshName, mesh ); } size_t MDAL::DriverManager::driversCount() const diff --git a/external/mdal/mdal_driver_manager.hpp b/external/mdal/mdal_driver_manager.hpp index 7c9eec42820..4926756b887 100644 --- a/external/mdal/mdal_driver_manager.hpp +++ b/external/mdal/mdal_driver_manager.hpp @@ -38,7 +38,7 @@ namespace MDAL const std::string &meshName ) const; void loadDatasets( Mesh *mesh, const std::string &datasetFile ) const; - void save( Mesh *mesh, const std::string &uri, const std::string &driver ) const; + void save( Mesh *mesh, const std::string &uri ) const; size_t driversCount() const; std::shared_ptr driver( const std::string &driverName ) const; diff --git a/external/mdal/mdal_memory_data_model.cpp b/external/mdal/mdal_memory_data_model.cpp index 10f67ef7ca5..024d10d25a0 100644 --- a/external/mdal/mdal_memory_data_model.cpp +++ b/external/mdal/mdal_memory_data_model.cpp @@ -117,6 +117,106 @@ size_t MDAL::MemoryDataset2D::vectorData( size_t indexStart, size_t count, doubl return copyValues; } +MDAL::MemoryDataset3D::MemoryDataset3D( + DatasetGroup *grp, + size_t volumes, + size_t maxVerticalLevelCount, + const int *verticalLevelCounts, + const double *verticalExtrusions +) : Dataset3D( grp, volumes, maxVerticalLevelCount ), + mValues( group()->isScalar() ? volumes : 2 * volumes, + std::numeric_limits::quiet_NaN() ), + mFaceToVolume( grp->mesh()->facesCount(), 0 ), + mVerticalLevelCounts( verticalLevelCounts, verticalLevelCounts + grp->mesh()->facesCount() ), + mVerticalExtrusions( verticalExtrusions, verticalExtrusions + grp->mesh()->facesCount() + volumes ) +{ + updateIndices(); +} + +MDAL::MemoryDataset3D::~MemoryDataset3D() = default; + +void MDAL::MemoryDataset3D::updateIndices() +{ + size_t offset = 0; + for ( size_t i = 0; i < mVerticalLevelCounts.size(); i++ ) + { + mFaceToVolume[i] = offset; + offset += mVerticalLevelCounts[i]; + if ( offset > volumesCount() ) + { + MDAL::Log::error( Err_InvalidData, "Incompatible volume count" ); + return; + } + } +} + +size_t MDAL::MemoryDataset3D::verticalLevelCountData( size_t indexStart, size_t count, int *buffer ) +{ + size_t nValues = group()->mesh()->facesCount(); + assert( mVerticalLevelCounts.size() == nValues ); + + if ( ( count < 1 ) || ( indexStart >= nValues ) ) + return 0; + + size_t copyValues = std::min( nValues - indexStart, count ); + memcpy( buffer, mVerticalLevelCounts.data() + indexStart, copyValues * sizeof( int ) ); + return copyValues; +} + +size_t MDAL::MemoryDataset3D::verticalLevelData( size_t indexStart, size_t count, double *buffer ) +{ + size_t nValues = group()->mesh()->facesCount() + valuesCount(); + assert( mVerticalExtrusions.size() == nValues ); + + if ( ( count < 1 ) || ( indexStart >= nValues ) ) + return 0; + + size_t copyValues = std::min( nValues - indexStart, count ); + memcpy( buffer, mVerticalExtrusions.data() + indexStart, copyValues * sizeof( double ) ); + return copyValues; +} + +size_t MDAL::MemoryDataset3D::faceToVolumeData( size_t indexStart, size_t count, int *buffer ) +{ + size_t nValues = group()->mesh()->facesCount(); + assert( mFaceToVolume.size() == nValues ); + + if ( ( count < 1 ) || ( indexStart >= nValues ) ) + return 0; + + size_t copyValues = std::min( nValues - indexStart, count ); + memcpy( buffer, mFaceToVolume.data() + indexStart, copyValues * sizeof( int ) ); + return copyValues; +} + +size_t MDAL::MemoryDataset3D::scalarVolumesData( size_t indexStart, size_t count, double *buffer ) +{ + assert( group()->isScalar() ); //checked in C API interface + size_t nValues = valuesCount(); + assert( mValues.size() == nValues ); + + if ( ( count < 1 ) || ( indexStart >= nValues ) ) + return 0; + + size_t copyValues = std::min( nValues - indexStart, count ); + memcpy( buffer, mValues.data() + indexStart, copyValues * sizeof( double ) ); + return copyValues; +} + +size_t MDAL::MemoryDataset3D::vectorVolumesData( size_t indexStart, size_t count, double *buffer ) +{ + assert( !group()->isScalar() ); //checked in C API interface + size_t nValues = valuesCount(); + assert( mValues.size() == nValues * 2 ); + + if ( ( count < 1 ) || ( indexStart >= nValues ) ) + return 0; + + size_t copyValues = std::min( nValues - indexStart, count ); + memcpy( buffer, mValues.data() + 2 * indexStart, 2 * copyValues * sizeof( double ) ); + return copyValues; +} + MDAL::MemoryMesh::MemoryMesh( const std::string &driverName, size_t faceVerticesMaximumCount, const std::string &uri ) diff --git a/external/mdal/mdal_memory_data_model.hpp b/external/mdal/mdal_memory_data_model.hpp index 447e8e234d0..6678f795213 100644 --- a/external/mdal/mdal_memory_data_model.hpp +++ b/external/mdal/mdal_memory_data_model.hpp @@ -134,9 +134,11 @@ namespace MDAL return mValues[index]; } - //! Returns pointer to internal buffer with values - //! Never null, already allocated - //! for vector datasets in form x1, y1, ..., xN, yN + /** + * Returns pointer to internal buffer with values + * Never null, already allocated + * for vector datasets in form x1, y1, ..., xN, yN + */ double *values() { return mValues.data(); @@ -168,6 +170,123 @@ namespace MDAL std::vector mActive; }; + class MemoryDataset3D: public Dataset3D + { + public: + + MemoryDataset3D( + DatasetGroup *grp, + size_t volumes, + size_t maxVerticalLevelCount, + const int *verticalLevelCounts, + const double *verticalExtrusions + ); + + ~MemoryDataset3D() override; + + + void setScalarValue( size_t index, double value ) + { + assert( mValues.size() > index ); + assert( group()->isScalar() ); + mValues[index] = value; + } + + void setVectorValue( size_t index, double x, double y ) + { + assert( mValues.size() > 2 * index + 1 ); + assert( !group()->isScalar() ); + mValues[2 * index] = x; + mValues[2 * index + 1] = y; + } + + void setValueX( size_t index, double x ) + { + assert( mValues.size() > 2 * index ); + assert( !group()->isScalar() ); + + mValues[2 * index] = x; + } + + void setValueY( size_t index, double x ) + { + assert( mValues.size() > 2 * index + 1 ); + assert( !group()->isScalar() ); + mValues[2 * index + 1] = x; + } + + double valueX( size_t index ) const + { + assert( mValues.size() > 2 * index + 1 ); + assert( !group()->isScalar() ); + return mValues[2 * index]; + } + + double valueY( size_t index ) const + { + assert( mValues.size() > 2 * index + 1 ); + assert( !group()->isScalar() ); + return mValues[2 * index + 1]; + } + + double scalarValue( size_t index ) const + { + assert( mValues.size() > index ); + assert( group()->isScalar() ); + return mValues[index]; + } + + void updateIndices(); + + /** + * Returns pointer to internal buffer with values + * Never null, already allocated + * for vector datasets in form x1, y1, ..., xN, yN + */ + double *values() + { + return mValues.data(); + } + + size_t verticalLevelCountData( size_t indexStart, size_t count, int *buffer ) override; + size_t verticalLevelData( size_t indexStart, size_t count, double *buffer ) override; + size_t faceToVolumeData( size_t indexStart, size_t count, int *buffer ) override; + size_t scalarVolumesData( size_t indexStart, size_t count, double *buffer ) override; + size_t vectorVolumesData( size_t indexStart, size_t count, double *buffer ) override; + + private: + /** + * Stores vector2d/scalar data for dataset in form + * scalars: x1, x2, x3, ..., xN + * vector2D: x1, y1, x2, y2, x3, y3, .... , xN, yN + * + * all values are initialized to std::numerical_limits::quiet_NaN ( == NODATA ) + * + */ + std::vector mValues; + + /** + * Stores the first index of 3D volume for particular mesh’s face in 3D Stacked Meshes + * + * All values are initialised to actual values + */ + std::vector mFaceToVolume; + + /** + * Stores number of vertical level for particular mesh’s face in 3D Stacked Meshes. + * + * All values are initialised to actual values + */ + std::vector mVerticalLevelCounts; + + /** + * Stores vertical level extrusion for particular mesh’s face in 3D Stacked Meshes. + * + * All values are initialised to actual values + */ + std::vector mVerticalExtrusions; + }; + class MemoryMesh: public Mesh { public: