Skip to content

Commit

Permalink
MDAL version 1.3.0 (#59354)
Browse files Browse the repository at this point in the history
* MDAL version 1.3.0

* change type

* change types

* fix clang-tidy issues

* fix error

* update expected 2DM mesh with scientific notation

* XMDF driver can have slash (/) in layer name (path in file)
  • Loading branch information
JanCaha authored Nov 8, 2024
1 parent b251c95 commit 3fe0eca
Show file tree
Hide file tree
Showing 9 changed files with 334 additions and 17 deletions.
15 changes: 15 additions & 0 deletions external/mdal/api/mdal.h
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,14 @@ MDAL_EXPORT MDAL_DatasetGroupH MDAL_M_addDatasetGroup(
MDAL_DriverH driver,
const char *datasetGroupFile );

/**
* Removes DatasetGroup from Mesh based on it's index. On error see MDAL_LastStatus
* for error type.
*
* \since MDAL 1.3.0
*/
MDAL_EXPORT void MDAL_M_RemoveDatasetGroup( MDAL_MeshH mesh, int index );

/**
* Returns name of MDAL driver
* not thread-safe and valid only till next call
Expand Down Expand Up @@ -587,6 +595,13 @@ MDAL_EXPORT void MDAL_G_setMetadata( MDAL_DatasetGroupH group, const char *key,
*/
MDAL_EXPORT const char *MDAL_G_name( MDAL_DatasetGroupH group );

/**
* Sets dataset group name
*
* \since MDAL 1.3.0
*/
MDAL_EXPORT void MDAL_G_setName( MDAL_DatasetGroupH group, const char *name );

/**
* Returns name of MDAL driver
* not thread-safe and valid only till next call
Expand Down
2 changes: 1 addition & 1 deletion external/mdal/frmts/mdal_2dm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ void MDAL::Driver2dm::save( const std::string &fileName, const std::string &, MD
for ( size_t j = 0; j < 2; ++j )
{
line.append( " " );
line.append( MDAL::coordinateToString( vertex[j] ) );
line.append( MDAL::doubleToString( vertex[j], 8, true ) );
}
line.append( " " );
line.append( MDAL::doubleToString( vertex[2] ) );
Expand Down
253 changes: 251 additions & 2 deletions external/mdal/frmts/mdal_xmdf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ size_t MDAL::XmdfDataset::activeData( size_t indexStart, size_t count, int *buff
MDAL::DriverXmdf::DriverXmdf()
: Driver( "XMDF",
"TUFLOW XMDF",
"*.xmdf",
Capability::ReadDatasets )
"*.xmdf;;*.h5",
Capability::ReadDatasets | Capability::ReadMesh )
{
}

Expand Down Expand Up @@ -206,6 +206,17 @@ void MDAL::DriverXmdf::addDatasetGroupsFromXmdfGroup( DatasetGroups &groups,
size_t vertexCount,
size_t faceCount ) const
{
// check if this root group can be loaded as a dataset group and if so, then load it
std::vector<std::string> gDataNames = rootGroup.datasets();
if ( MDAL::contains( gDataNames, "Times" ) &&
MDAL::contains( gDataNames, "Values" ) &&
MDAL::contains( gDataNames, "Mins" ) &&
MDAL::contains( gDataNames, "Maxs" ) )
{
std::shared_ptr<DatasetGroup> ds = readXmdfGroupAsDatasetGroup( rootGroup, rootGroup.name() + nameSuffix, vertexCount, faceCount );
groups.push_back( ds );
}

for ( const std::string &groupName : rootGroup.groups() )
{
HdfGroup g = rootGroup.group( groupName );
Expand Down Expand Up @@ -331,3 +342,241 @@ std::shared_ptr<MDAL::DatasetGroup> MDAL::DriverXmdf::readXmdfGroupAsDatasetGrou

return group;
}

bool MDAL::DriverXmdf::canReadMesh( const std::string &uri )
{
HdfFile file( uri, HdfFile::ReadOnly );
if ( !file.isValid() )
{
return false;
}

HdfDataset dsFileType = file.dataset( "/File Type" );
if ( dsFileType.readString() != "Xmdf" )
{
return false;
}

std::vector<std::string> meshPaths = meshGroupPaths( file );

return !meshPaths.empty();
}

std::string MDAL::DriverXmdf::buildUri( const std::string &meshFile )
{
mDatFile = meshFile;

std::vector<std::string> meshNames = findMeshesNames();

return MDAL::buildAndMergeMeshUris( meshFile, meshNames, name() );
}

std::vector<std::string> MDAL::DriverXmdf::findMeshesNames() const
{
std::vector<std::string> meshesInFile;

HdfFile file( mDatFile, HdfFile::ReadOnly );
if ( !file.isValid() )
{
return meshesInFile;
}

meshesInFile = meshGroupPaths( file );

return meshesInFile;
}

std::vector<std::string> MDAL::DriverXmdf::meshGroupPaths( const HdfFile &file ) const
{
std::vector<std::string> meshPaths;

std::vector<std::string> rootGroups = file.groups();

for ( const std::string &groupName : rootGroups )
{
HdfGroup g = file.group( groupName );
std::vector<std::string> paths = meshGroupPaths( g );
meshPaths.insert( meshPaths.end(), paths.begin(), paths.end() );
}

return meshPaths;
}

std::vector<std::string> MDAL::DriverXmdf::meshGroupPaths( const HdfGroup &group ) const
{
std::vector<std::string> meshPaths;

std::vector<std::string> gDataNames = group.groups();

if ( MDAL::contains( gDataNames, "Nodes" ) ||
MDAL::contains( gDataNames, "Elements" ) )
{
meshPaths.push_back( group.name() );
}

for ( const std::string &groupName : gDataNames )
{
HdfGroup g = group.group( groupName );
std::vector<std::string> paths = meshGroupPaths( g );
meshPaths.insert( meshPaths.end(), paths.begin(), paths.end() );
}

return meshPaths;
}

std::unique_ptr< MDAL::Mesh > MDAL::DriverXmdf::load( const std::string &meshFile, const std::string &meshName )
{
mDatFile = meshFile;

MDAL::Log::resetLastStatus();

HdfFile file( mDatFile, HdfFile::ReadOnly );
if ( !file.isValid() )
{
MDAL::Log::error( MDAL_Status::Err_UnknownFormat, name(), "File " + mDatFile + " is not valid" );
return nullptr;
}

HdfDataset dsFileType = file.dataset( "/File Type" );
if ( dsFileType.readString() != "Xmdf" )
{
MDAL::Log::error( MDAL_Status::Err_UnknownFormat, name(), "Unknown dataset file type" );
return nullptr;
}

std::vector<std::string> meshNames = findMeshesNames();

if ( meshNames.empty() )
{
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, name(), "No meshes found in file " + mDatFile );
return nullptr;
}

std::string meshNameToLoad = meshName;

if ( meshNameToLoad.empty() )
{
meshNameToLoad = meshNames[0];
}

if ( !MDAL::contains( meshNames, meshNameToLoad ) )
{
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, name(), "No meshes with name " + meshNameToLoad + " found in file " + mDatFile );
return nullptr;
}

HdfGroup groupMeshModule = file.group( meshNameToLoad );

std::vector<std::string> gDataNames = groupMeshModule.groups();

HdfGroup gNodes = groupMeshModule.group( "Nodes" );

std::vector<std::string> namesNodes = gNodes.datasets();
HdfDataset nodes = gNodes.dataset( namesNodes[0] );

std::vector<hsize_t> nodesDims = nodes.dims();
hsize_t nodesRows = nodesDims[0];
size_t vertexDims = nodesDims[1];

if ( vertexDims < 2 || vertexDims > 3 )
{
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, name(), "Vertices have unsupported number of dimensions " + std::to_string( vertexDims ) + " only 2 (X,Y) or 3 (X, Y, Z) dimensions are allowed." );
return nullptr;
}

std::vector<double> nodesData = nodes.readArrayDouble();

Vertices vertices( nodesRows );

size_t currentVertexIndex = 0;
size_t i = 0;
while ( i < nodesData.size() )
{
Vertex &vertex = vertices[currentVertexIndex];

vertex.x = nodesData[i];
i++;
vertex.y = nodesData[i];
i++;
if ( vertexDims == 3 )
{
vertex.z = nodesData[i];
i++;
}
currentVertexIndex++;
}

nodesData.clear();

HdfGroup gElements = groupMeshModule.group( "Elements" );

std::vector<std::string> namesElements = gElements.datasets();
HdfDataset elements = gElements.dataset( namesElements[0] );

std::vector<hsize_t> elementsDims = elements.dims();
hsize_t elementsRows = elementsDims[0];
hsize_t elementsRowsDims = elementsDims[1];

std::vector<int> facesData = elements.readArrayInt();

Faces faces( elementsRows );
size_t maxVerticesPerFace = 0;

size_t currentFaceIndex = 0;
i = 0;
while ( i < facesData.size() )
{
std::vector<size_t> tempFace;
for ( hsize_t j = 0; j < elementsRowsDims; j++ )
{
int vertexIndex = facesData[i];
if ( vertexIndex > 0 )
{
// XMDF is 1-based, MDAL is 0-based
tempFace.push_back( facesData[i] - 1 );
}
i++;
}

// only store faces with more than 2 vertices
if ( tempFace.size() > static_cast<size_t>( 2 ) )
{
Face &face = faces[currentFaceIndex];
std::copy( tempFace.begin(), tempFace.end(), std::back_inserter( face ) );

if ( tempFace.size() > maxVerticesPerFace )
{
maxVerticesPerFace = tempFace.size();
}

currentFaceIndex++;
}
}

facesData.clear();

// copy only the faces that have been properly filled
faces = Faces( faces.begin(), faces.begin() + static_cast<long>( currentFaceIndex ) );

// create the mesh and set the required data
std::unique_ptr< MemoryMesh > mesh(
new MemoryMesh(
name(),
maxVerticesPerFace,
mDatFile
)
);

std::vector<double> values( vertices.size() );
for ( size_t i = 0; i < vertices.size(); ++i )
{
values[i] = vertices[i].z;
}

mesh->setFaces( std::move( faces ) );
mesh->setVertices( std::move( vertices ) );

addVertexScalarDatasetGroup( mesh.get(), values, "Z-Values" );

return mesh;
}
8 changes: 8 additions & 0 deletions external/mdal/frmts/mdal_xmdf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ namespace MDAL
bool canReadDatasets( const std::string &uri ) override;
void load( const std::string &datFile, Mesh *mesh ) override;

bool canReadMesh( const std::string &uri ) override;
std::unique_ptr< Mesh > load( const std::string &meshFile, const std::string &meshName = "" ) override;

private:
MDAL::Mesh *mMesh = nullptr;
std::string mDatFile;
Expand All @@ -111,6 +114,11 @@ namespace MDAL
size_t vertexCount,
size_t faceCount ) const;

std::string buildUri( const std::string &meshFile ) override;
std::vector<std::string> findMeshesNames() const;

std::vector<std::string> meshGroupPaths( const HdfGroup &group ) const;
std::vector<std::string> meshGroupPaths( const HdfFile &file ) const;
};

} // namespace MDAL
Expand Down
42 changes: 41 additions & 1 deletion external/mdal/mdal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ static const char *EMPTY_STR = "";

const char *MDAL_Version()
{
return "1.2.0";
return "1.3.0";
}

MDAL_Status MDAL_LastStatus()
Expand Down Expand Up @@ -580,6 +580,34 @@ MDAL_DatasetGroupH MDAL_M_addDatasetGroup(
return nullptr;
}

void MDAL_M_RemoveDatasetGroup( MDAL_MeshH mesh, int index )
{
MDAL::Log::resetLastStatus();

if ( !mesh )
{
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, "Mesh is not valid (null)" );
return;
}

if ( index < 0 )
{
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, "Requested index is not valid: " + std::to_string( index ) );
return;
}

MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh );
int len = static_cast<int>( m->datasetGroups.size() );
if ( len <= index )
{
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, "Requested index " + std::to_string( index ) + " is bigger than datasets count" );
return;
}
size_t i = static_cast<size_t>( index );

m->datasetGroups.erase( m->datasetGroups.begin() + static_cast<long>( i ) );
}

const char *MDAL_M_driverName( MDAL_MeshH mesh )
{
if ( !mesh )
Expand Down Expand Up @@ -847,6 +875,18 @@ const char *MDAL_G_name( MDAL_DatasetGroupH group )
return _return_str( g->name() );
}

void MDAL_G_setName( MDAL_DatasetGroupH group, const char *name )
{
if ( !group )
{
MDAL::Log::error( MDAL_Status::Err_IncompatibleDataset, "Dataset Group is not valid (null)" );
return;
}

MDAL::DatasetGroup *g = static_cast< MDAL::DatasetGroup * >( group );
g->setName( name );
}

bool MDAL_G_hasScalarData( MDAL_DatasetGroupH group )
{
if ( !group )
Expand Down
Loading

0 comments on commit 3fe0eca

Please sign in to comment.