mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
update to MDAL 0.0.3
This commit is contained in:
parent
ee7240f70d
commit
bfbc64ce6c
71
external/mdal/api/mdal.h
vendored
71
external/mdal/api/mdal.h
vendored
@ -6,6 +6,12 @@
|
||||
#ifndef MDAL_H
|
||||
#define MDAL_H
|
||||
|
||||
/**********************************************************************/
|
||||
/**********************************************************************/
|
||||
/* API is considered EXPERIMENTAL and can be changed without a notice */
|
||||
/**********************************************************************/
|
||||
/**********************************************************************/
|
||||
|
||||
#ifdef MDAL_STATIC
|
||||
# define MDAL_EXPORT
|
||||
#else
|
||||
@ -46,6 +52,7 @@ enum MDAL_Status
|
||||
Err_UnknownFormat,
|
||||
Err_IncompatibleMesh,
|
||||
Err_InvalidData,
|
||||
Err_IncompatibleDataset,
|
||||
Err_MissingDriver,
|
||||
// Warnings
|
||||
Warn_UnsupportedElement,
|
||||
@ -57,6 +64,7 @@ enum MDAL_Status
|
||||
|
||||
//! Mesh
|
||||
typedef void *MeshH;
|
||||
typedef void *DatasetH;
|
||||
|
||||
//! Return MDAL version
|
||||
MDAL_EXPORT const char *MDAL_Version();
|
||||
@ -68,7 +76,6 @@ MDAL_EXPORT MDAL_Status MDAL_LastStatus();
|
||||
MDAL_EXPORT MeshH MDAL_LoadMesh( const char *meshFile );
|
||||
//! Close mesh, free the memory
|
||||
MDAL_EXPORT void MDAL_CloseMesh( MeshH mesh );
|
||||
|
||||
//! Return vertex count for the mesh
|
||||
MDAL_EXPORT int MDAL_M_vertexCount( MeshH mesh );
|
||||
//! Return vertex X coord for the mesh
|
||||
@ -82,6 +89,68 @@ MDAL_EXPORT int MDAL_M_faceVerticesCountAt( MeshH mesh, int index );
|
||||
//! Return vertex index for face
|
||||
MDAL_EXPORT int MDAL_M_faceVerticesIndexAt( MeshH mesh, int face_index, int vertex_index );
|
||||
|
||||
/**
|
||||
* Load dataset file. On error see MDAL_LastStatus for error type.
|
||||
* This may effectively load whole dataset in-memory for some providers
|
||||
* Datasets will be closed automatically on mesh destruction or memory
|
||||
* can be freed manually with MDAL_CloseDataset if needed
|
||||
*/
|
||||
MDAL_EXPORT void MDAL_M_LoadDatasets( MeshH mesh, const char *datasetFile );
|
||||
|
||||
//! Free the memory used to get dataset values
|
||||
MDAL_EXPORT void MDAL_M_CloseDataset( DatasetH dataset );
|
||||
|
||||
//! Return dataset count
|
||||
MDAL_EXPORT int MDAL_M_datasetCount( MeshH mesh );
|
||||
|
||||
//! Return dataset handle
|
||||
MDAL_EXPORT DatasetH MDAL_M_dataset( MeshH mesh, int index );
|
||||
|
||||
//! Whether dataset has scalar data associated
|
||||
MDAL_EXPORT bool MDAL_D_hasScalarData( DatasetH dataset );
|
||||
|
||||
//! Whether dataset is on vertices
|
||||
MDAL_EXPORT bool MDAL_D_isOnVertices( DatasetH dataset );
|
||||
|
||||
//! Return number of metadata values
|
||||
MDAL_EXPORT int MDAL_D_metadataCount( DatasetH dataset );
|
||||
|
||||
//! Return dataset metadata key
|
||||
MDAL_EXPORT const char *MDAL_D_metadataKey( DatasetH dataset, int index );
|
||||
|
||||
//! Return dataset metadata value
|
||||
MDAL_EXPORT const char *MDAL_D_metadataValue( DatasetH dataset, int index );
|
||||
|
||||
//! Return number of values
|
||||
MDAL_EXPORT int MDAL_D_valueCount( DatasetH dataset );
|
||||
|
||||
/**
|
||||
* Return scalar value associated with the index from the dataset
|
||||
* for nodata return numeric_limits<double>:quiet_NaN
|
||||
*/
|
||||
MDAL_EXPORT double MDAL_D_value( DatasetH dataset, int valueIndex );
|
||||
|
||||
/**
|
||||
* Return X value associated with the index from the vector dataset
|
||||
* for nodata return numeric_limits<double>:quiet_NaN
|
||||
*/
|
||||
MDAL_EXPORT double MDAL_D_valueX( DatasetH dataset, int valueIndex );
|
||||
|
||||
/**
|
||||
* Return Y value associated with the index from the vector dataset
|
||||
* for nodata return numeric_limits<double>:quiet_NaN
|
||||
*/
|
||||
MDAL_EXPORT double MDAL_D_valueY( DatasetH dataset, int valueIndex );
|
||||
|
||||
/**
|
||||
* Whether element is active - should be taken into account
|
||||
* Some formats support switching off the element for particular timestep
|
||||
*/
|
||||
MDAL_EXPORT bool MDAL_D_active( DatasetH dataset, int faceIndex );
|
||||
|
||||
//! Return whether dataset is valid
|
||||
MDAL_EXPORT bool MDAL_D_isValid( DatasetH dataset );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
85
external/mdal/frmts/mdal_2dm.cpp
vendored
85
external/mdal/frmts/mdal_2dm.cpp
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
|
||||
Copyright (C) 2018 Lutra Consulting Ltd.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
@ -22,14 +22,14 @@ MDAL::Loader2dm::Loader2dm( const std::string &meshFile ):
|
||||
{
|
||||
}
|
||||
|
||||
MDAL::Mesh *MDAL::Loader2dm::load( MDAL_Status *status )
|
||||
std::unique_ptr<MDAL::Mesh> MDAL::Loader2dm::load( MDAL_Status *status )
|
||||
{
|
||||
if ( status ) *status = MDAL_Status::None;
|
||||
|
||||
if ( !MDAL::fileExists( mMeshFile ) )
|
||||
{
|
||||
if ( status ) *status = MDAL_Status::Err_FileNotFound;
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::ifstream in( mMeshFile, std::ifstream::in );
|
||||
@ -37,11 +37,11 @@ MDAL::Mesh *MDAL::Loader2dm::load( MDAL_Status *status )
|
||||
if ( !std::getline( in, line ) || !startsWith( line, "MESH2D" ) )
|
||||
{
|
||||
if ( status ) *status = MDAL_Status::Err_UnknownFormat;
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t elemCount = 0;
|
||||
size_t nodeCount = 0;
|
||||
size_t faceCount = 0;
|
||||
size_t vertexCount = 0;
|
||||
|
||||
// Find out how many nodes and elements are contained in the .2dm mesh file
|
||||
while ( std::getline( in, line ) )
|
||||
@ -49,11 +49,11 @@ MDAL::Mesh *MDAL::Loader2dm::load( MDAL_Status *status )
|
||||
if ( startsWith( line, "E4Q" ) ||
|
||||
startsWith( line, "E3T" ) )
|
||||
{
|
||||
elemCount++;
|
||||
faceCount++;
|
||||
}
|
||||
else if ( startsWith( line, "ND" ) )
|
||||
{
|
||||
nodeCount++;
|
||||
vertexCount++;
|
||||
}
|
||||
else if ( startsWith( line, "E2L" ) ||
|
||||
startsWith( line, "E3L" ) ||
|
||||
@ -62,63 +62,63 @@ MDAL::Mesh *MDAL::Loader2dm::load( MDAL_Status *status )
|
||||
startsWith( line, "E9Q" ) )
|
||||
{
|
||||
if ( status ) *status = MDAL_Status::Warn_UnsupportedElement;
|
||||
elemCount += 1; // We still count them as elements
|
||||
faceCount += 1; // We still count them as elements
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate memory
|
||||
std::vector<Vertex> vertices( nodeCount );
|
||||
std::vector<Face> faces( elemCount );
|
||||
std::vector<Vertex> vertices( vertexCount );
|
||||
std::vector<Face> faces( faceCount );
|
||||
|
||||
in.clear();
|
||||
in.seekg( 0, std::ios::beg );
|
||||
|
||||
std::vector<std::string> chunks;
|
||||
|
||||
size_t elemIndex = 0;
|
||||
size_t nodeIndex = 0;
|
||||
std::map<size_t, size_t> elemIDtoIndex;
|
||||
std::map<size_t, size_t> nodeIDtoIndex;
|
||||
size_t faceIndex = 0;
|
||||
size_t vertexIndex = 0;
|
||||
std::map<size_t, size_t> faceIDtoIndex;
|
||||
std::map<size_t, size_t> vertexIDtoIndex;
|
||||
|
||||
while ( std::getline( in, line ) )
|
||||
{
|
||||
if ( startsWith( line, "E4Q" ) )
|
||||
{
|
||||
chunks = split( line, " ", SplitBehaviour::SkipEmptyParts );
|
||||
assert( elemIndex < elemCount );
|
||||
assert( faceIndex < faceCount );
|
||||
|
||||
size_t elemID = toSizeT( chunks[1] );
|
||||
|
||||
std::map<size_t, size_t>::iterator search = elemIDtoIndex.find( elemID );
|
||||
if ( search != elemIDtoIndex.end() )
|
||||
std::map<size_t, size_t>::iterator search = faceIDtoIndex.find( elemID );
|
||||
if ( search != faceIDtoIndex.end() )
|
||||
{
|
||||
if ( status ) *status = MDAL_Status::Warn_ElementNotUnique;
|
||||
continue;
|
||||
}
|
||||
elemIDtoIndex[elemID] = elemIndex;
|
||||
Face &face = faces[elemIndex];
|
||||
faceIDtoIndex[elemID] = faceIndex;
|
||||
Face &face = faces[faceIndex];
|
||||
face.resize( 4 );
|
||||
// Right now we just store node IDs here - we will convert them to node indices afterwards
|
||||
for ( size_t i = 0; i < 4; ++i )
|
||||
face[i] = toSizeT( chunks[i + 2] );
|
||||
|
||||
elemIndex++;
|
||||
faceIndex++;
|
||||
}
|
||||
else if ( startsWith( line, "E3T" ) )
|
||||
{
|
||||
chunks = split( line, " ", SplitBehaviour::SkipEmptyParts );
|
||||
assert( elemIndex < elemCount );
|
||||
assert( faceIndex < faceCount );
|
||||
|
||||
size_t elemID = toSizeT( chunks[1] );
|
||||
|
||||
std::map<size_t, size_t>::iterator search = elemIDtoIndex.find( elemID );
|
||||
if ( search != elemIDtoIndex.end() )
|
||||
std::map<size_t, size_t>::iterator search = faceIDtoIndex.find( elemID );
|
||||
if ( search != faceIDtoIndex.end() )
|
||||
{
|
||||
if ( status ) *status = MDAL_Status::Warn_ElementNotUnique;
|
||||
continue;
|
||||
}
|
||||
elemIDtoIndex[elemID] = elemIndex;
|
||||
Face &face = faces[elemIndex];
|
||||
faceIDtoIndex[elemID] = faceIndex;
|
||||
Face &face = faces[faceIndex];
|
||||
face.resize( 3 );
|
||||
// Right now we just store node IDs here - we will convert them to node indices afterwards
|
||||
for ( size_t i = 0; i < 3; ++i )
|
||||
@ -126,7 +126,7 @@ MDAL::Mesh *MDAL::Loader2dm::load( MDAL_Status *status )
|
||||
face[i] = toSizeT( chunks[i + 2] );
|
||||
}
|
||||
|
||||
elemIndex++;
|
||||
faceIndex++;
|
||||
}
|
||||
else if ( startsWith( line, "E2L" ) ||
|
||||
startsWith( line, "E3L" ) ||
|
||||
@ -136,39 +136,39 @@ MDAL::Mesh *MDAL::Loader2dm::load( MDAL_Status *status )
|
||||
{
|
||||
// We do not yet support these elements
|
||||
chunks = split( line, " ", SplitBehaviour::SkipEmptyParts );
|
||||
assert( elemIndex < elemCount );
|
||||
assert( faceIndex < faceCount );
|
||||
|
||||
size_t elemID = toSizeT( chunks[1] );
|
||||
|
||||
std::map<size_t, size_t>::iterator search = elemIDtoIndex.find( elemID );
|
||||
if ( search != elemIDtoIndex.end() )
|
||||
std::map<size_t, size_t>::iterator search = faceIDtoIndex.find( elemID );
|
||||
if ( search != faceIDtoIndex.end() )
|
||||
{
|
||||
if ( status ) *status = MDAL_Status::Warn_ElementNotUnique;
|
||||
continue;
|
||||
}
|
||||
elemIDtoIndex[elemID] = elemIndex;
|
||||
faceIDtoIndex[elemID] = faceIndex;
|
||||
assert( false ); //TODO mark element as unusable
|
||||
|
||||
elemIndex++;
|
||||
faceIndex++;
|
||||
}
|
||||
else if ( startsWith( line, "ND" ) )
|
||||
{
|
||||
chunks = split( line, " ", SplitBehaviour::SkipEmptyParts );
|
||||
size_t nodeID = toSizeT( chunks[1] );
|
||||
|
||||
std::map<size_t, size_t>::iterator search = nodeIDtoIndex.find( nodeID );
|
||||
if ( search != nodeIDtoIndex.end() )
|
||||
std::map<size_t, size_t>::iterator search = vertexIDtoIndex.find( nodeID );
|
||||
if ( search != vertexIDtoIndex.end() )
|
||||
{
|
||||
if ( status ) *status = MDAL_Status::Warn_NodeNotUnique;
|
||||
continue;
|
||||
}
|
||||
nodeIDtoIndex[nodeID] = nodeIndex;
|
||||
assert( nodeIndex < nodeCount );
|
||||
Vertex &vertex = vertices[nodeIndex];
|
||||
vertexIDtoIndex[nodeID] = vertexIndex;
|
||||
assert( vertexIndex < vertexCount );
|
||||
Vertex &vertex = vertices[vertexIndex];
|
||||
vertex.x = toDouble( chunks[2] );
|
||||
vertex.y = toDouble( chunks[3] );
|
||||
|
||||
nodeIndex++;
|
||||
vertexIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,8 +179,8 @@ MDAL::Mesh *MDAL::Loader2dm::load( MDAL_Status *status )
|
||||
{
|
||||
size_t nodeID = face[nd];
|
||||
|
||||
std::map<size_t, size_t>::iterator ni2i = nodeIDtoIndex.find( nodeID );
|
||||
if ( ni2i != nodeIDtoIndex.end() )
|
||||
std::map<size_t, size_t>::iterator ni2i = vertexIDtoIndex.find( nodeID );
|
||||
if ( ni2i != vertexIDtoIndex.end() )
|
||||
{
|
||||
face[nd] = ni2i->second; // convert from ID to index
|
||||
}
|
||||
@ -196,9 +196,12 @@ MDAL::Mesh *MDAL::Loader2dm::load( MDAL_Status *status )
|
||||
//check that we have distinct nodes
|
||||
}
|
||||
|
||||
Mesh *mesh = new Mesh;
|
||||
std::unique_ptr< Mesh > mesh( new Mesh );
|
||||
mesh->uri = mMeshFile;
|
||||
mesh->faces = faces;
|
||||
mesh->vertices = vertices;
|
||||
mesh->faceIDtoIndex = faceIDtoIndex;
|
||||
mesh->vertexIDtoIndex = vertexIDtoIndex;
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
3
external/mdal/frmts/mdal_2dm.hpp
vendored
3
external/mdal/frmts/mdal_2dm.hpp
vendored
@ -7,6 +7,7 @@
|
||||
#define MDAL_2DM_HPP
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "mdal_defines.hpp"
|
||||
#include "mdal.h"
|
||||
@ -18,7 +19,7 @@ namespace MDAL
|
||||
{
|
||||
public:
|
||||
Loader2dm( const std::string &meshFile );
|
||||
Mesh *load( MDAL_Status *status );
|
||||
std::unique_ptr< Mesh > load( MDAL_Status *status );
|
||||
|
||||
private:
|
||||
std::string mMeshFile;
|
||||
|
305
external/mdal/frmts/mdal_ascii_dat.cpp
vendored
Normal file
305
external/mdal/frmts/mdal_ascii_dat.cpp
vendored
Normal file
@ -0,0 +1,305 @@
|
||||
/*
|
||||
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||
Copyright (C) 2018 Lutra Consulting Ltd.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <iosfwd>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
#include "mdal_ascii_dat.hpp"
|
||||
#include "mdal.h"
|
||||
#include "mdal_utils.hpp"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define EXIT_WITH_ERROR(error) { if (status) *status = (error); return; }
|
||||
|
||||
MDAL::LoaderAsciiDat::LoaderAsciiDat( const std::string &datFile ):
|
||||
mDatFile( datFile )
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* The DAT format contains "datasets" and each dataset has N-outputs. One output
|
||||
* represents data for all vertices/faces for one timestep
|
||||
*
|
||||
* In MDAL we convert one output to one MDAL dataset;
|
||||
*
|
||||
*/
|
||||
void MDAL::LoaderAsciiDat::load( MDAL::Mesh *mesh, MDAL_Status *status )
|
||||
{
|
||||
if ( status ) *status = MDAL_Status::None;
|
||||
|
||||
if ( !MDAL::fileExists( mDatFile ) )
|
||||
{
|
||||
if ( status ) *status = MDAL_Status::Err_FileNotFound;
|
||||
return;
|
||||
}
|
||||
|
||||
std::ifstream in( mDatFile, std::ifstream::in );
|
||||
std::string line;
|
||||
if ( !std::getline( in, line ) )
|
||||
{
|
||||
if ( status ) *status = MDAL_Status::Err_UnknownFormat;
|
||||
return;
|
||||
}
|
||||
line = trim( line );
|
||||
std::string basename = baseName( mDatFile );
|
||||
|
||||
// http://www.xmswiki.com/xms/SMS:ASCII_Dataset_Files_*.dat
|
||||
// Apart from the format specified above, there is an older supported format used in BASEMENT (and SMS?)
|
||||
// which is simpler (has only one dataset in one file, no status flags etc)
|
||||
bool oldFormat;
|
||||
bool isVector = false;
|
||||
bool readingDataset = false; // whether we are in process of reading the dataset
|
||||
|
||||
std::string baseDatasetName( basename );
|
||||
std::vector<std::shared_ptr<Dataset>> datOutputs; // DAT outputs data
|
||||
|
||||
if ( line == "DATASET" )
|
||||
oldFormat = false;
|
||||
else if ( line == "SCALAR" || line == "VECTOR" )
|
||||
{
|
||||
oldFormat = true;
|
||||
isVector = ( line == "VECTOR" );
|
||||
baseDatasetName = basename;
|
||||
readingDataset = true;
|
||||
}
|
||||
else
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
|
||||
// see if it contains element-centered results - supported by BASEMENT
|
||||
bool elementCentered = false;
|
||||
if ( !oldFormat && contains( basename, "_els_" ) )
|
||||
elementCentered = true;
|
||||
|
||||
while ( std::getline( in, line ) )
|
||||
{
|
||||
std::vector<std::string> items = split( line, " ", SplitBehaviour::SkipEmptyParts );
|
||||
if ( items.size() < 1 )
|
||||
continue; // empty line?? let's skip it
|
||||
|
||||
std::string cardType = items[0];
|
||||
if ( cardType == "ND" && items.size() >= 2 )
|
||||
{
|
||||
size_t fileNodeCount = toSizeT( items[1] );
|
||||
if ( mesh->vertexIDtoIndex.size() != fileNodeCount )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh );
|
||||
}
|
||||
else if ( !oldFormat && cardType == "NC" && items.size() >= 2 )
|
||||
{
|
||||
size_t fileElemCount = toSizeT( items[1] );
|
||||
if ( mesh->faceIDtoIndex.size() != fileElemCount )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh );
|
||||
}
|
||||
else if ( !oldFormat && cardType == "OBJTYPE" )
|
||||
{
|
||||
if ( items[1] != "mesh2d" && items[1] != "\"mesh2d\"" )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
}
|
||||
else if ( !oldFormat && ( cardType == "BEGSCL" || cardType == "BEGVEC" ) )
|
||||
{
|
||||
if ( readingDataset )
|
||||
{
|
||||
debug( "New dataset while previous one is still active!" );
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
}
|
||||
isVector = cardType == "BEGVEC";
|
||||
baseDatasetName = basename;
|
||||
readingDataset = true;
|
||||
}
|
||||
else if ( !oldFormat && cardType == "ENDDS" )
|
||||
{
|
||||
if ( !readingDataset )
|
||||
{
|
||||
debug( "ENDDS card for no active dataset!" );
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
}
|
||||
|
||||
addDatasets( mesh, baseDatasetName, datOutputs );
|
||||
}
|
||||
else if ( !oldFormat && cardType == "NAME" && items.size() >= 2 )
|
||||
{
|
||||
if ( !readingDataset )
|
||||
{
|
||||
debug( "NAME card for no active dataset!" );
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
}
|
||||
|
||||
size_t quoteIdx1 = line.find( '\"' );
|
||||
size_t quoteIdx2 = line.find( '\"', quoteIdx1 + 1 );
|
||||
if ( quoteIdx1 != std::string::npos && quoteIdx2 != std::string::npos )
|
||||
baseDatasetName = line.substr( quoteIdx1 + 1, quoteIdx2 - quoteIdx1 - 1 );
|
||||
}
|
||||
else if ( oldFormat && ( cardType == "SCALAR" || cardType == "VECTOR" ) )
|
||||
{
|
||||
// just ignore - we know the type from earlier...
|
||||
}
|
||||
else if ( cardType == "TS" && items.size() >= ( oldFormat ? 2 : 3 ) )
|
||||
{
|
||||
double t = toDouble( items[oldFormat ? 1 : 2] );
|
||||
|
||||
if ( elementCentered )
|
||||
{
|
||||
readFaceTimestep( mesh, datOutputs, t, isVector, in );
|
||||
}
|
||||
else
|
||||
{
|
||||
bool hasStatus = ( oldFormat ? false : toBool( items[1] ) );
|
||||
readVertexTimestep( mesh, datOutputs, t, isVector, hasStatus, in );
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream str;
|
||||
str << " Unknown card:" << line;
|
||||
debug( str.str() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( oldFormat )
|
||||
{
|
||||
if ( datOutputs.size() == 0 )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
|
||||
addDatasets( mesh, baseDatasetName, datOutputs );
|
||||
}
|
||||
}
|
||||
|
||||
void MDAL::LoaderAsciiDat::addDatasets( MDAL::Mesh *mesh,
|
||||
const std::string &name,
|
||||
const std::vector<std::shared_ptr<Dataset>> &datOutputs ) const
|
||||
{
|
||||
for ( const std::shared_ptr<Dataset> &ds : datOutputs )
|
||||
{
|
||||
ds->uri = mDatFile;
|
||||
ds->setName( name );
|
||||
ds->isValid = true;
|
||||
}
|
||||
|
||||
//https://stackoverflow.com/a/2551785/2838364
|
||||
mesh->datasets.insert(
|
||||
mesh->datasets.end(),
|
||||
datOutputs.begin(),
|
||||
datOutputs.end()
|
||||
);
|
||||
}
|
||||
|
||||
void MDAL::LoaderAsciiDat::readVertexTimestep( const MDAL::Mesh *mesh, std::vector<std::shared_ptr<MDAL::Dataset> > &datOutputs, double t, bool isVector, bool hasStatus, std::ifstream &stream )
|
||||
{
|
||||
size_t vertexCount = mesh->vertices.size();
|
||||
size_t faceCount = mesh->faces.size();
|
||||
|
||||
std::shared_ptr<MDAL::Dataset> dataset( new MDAL::Dataset );
|
||||
dataset->isScalar = !isVector; //everything else to be set in addDatasets
|
||||
dataset->setMetadata( "time", std::to_string( t / 3600. ) );
|
||||
dataset->values.resize( vertexCount );
|
||||
dataset->active.resize( faceCount );
|
||||
dataset->isOnVertices = true;
|
||||
|
||||
// only for new format
|
||||
for ( size_t i = 0; i < faceCount; ++i )
|
||||
{
|
||||
if ( hasStatus )
|
||||
{
|
||||
std::string line;
|
||||
std::getline( stream, line );
|
||||
dataset->active[i] = toBool( line );
|
||||
}
|
||||
else
|
||||
dataset->active[i] = true;
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < mesh->vertexIDtoIndex.size(); ++i )
|
||||
{
|
||||
std::string line;
|
||||
std::getline( stream, line );
|
||||
std::vector<std::string> tsItems = split( line, " ", SplitBehaviour::SkipEmptyParts );
|
||||
|
||||
auto idx = mesh->vertexIDtoIndex.find( i + 1 ); // ID in 2dm are numbered from 1
|
||||
if ( idx == mesh->vertexIDtoIndex.end() )
|
||||
continue; // node ID that does not exist in the mesh
|
||||
|
||||
size_t index = idx->second;
|
||||
|
||||
if ( isVector )
|
||||
{
|
||||
if ( tsItems.size() >= 2 ) // BASEMENT files with vectors have 3 columns
|
||||
{
|
||||
dataset->values[index].x = toDouble( tsItems[0] );
|
||||
dataset->values[index].y = toDouble( tsItems[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( "invalid timestep line" );
|
||||
dataset->values[index].noData = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( tsItems.size() >= 1 )
|
||||
dataset->values[index].x = toDouble( tsItems[0] );
|
||||
else
|
||||
{
|
||||
debug( "invalid timestep line" );
|
||||
dataset->values[index].noData = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
datOutputs.push_back( std::move( dataset ) );
|
||||
}
|
||||
|
||||
void MDAL::LoaderAsciiDat::readFaceTimestep( const MDAL::Mesh *mesh, std::vector<std::shared_ptr<MDAL::Dataset> > &datOutputs, double t, bool isVector, std::ifstream &stream )
|
||||
{
|
||||
size_t faceCount = mesh->faces.size();
|
||||
|
||||
std::shared_ptr<MDAL::Dataset> dataset( new MDAL::Dataset );
|
||||
dataset->isScalar = !isVector; //everything else to be set in addDatasets
|
||||
dataset->setMetadata( "time", std::to_string( t / 3600. ) );
|
||||
dataset->values.resize( faceCount );
|
||||
dataset->isOnVertices = false;
|
||||
|
||||
// TODO: hasStatus
|
||||
for ( size_t index = 0; index < faceCount; ++index )
|
||||
{
|
||||
std::string line;
|
||||
std::getline( stream, line );
|
||||
std::vector<std::string> tsItems = split( line, " ", SplitBehaviour::SkipEmptyParts );
|
||||
|
||||
if ( isVector )
|
||||
{
|
||||
if ( tsItems.size() >= 2 ) // BASEMENT files with vectors have 3 columns
|
||||
{
|
||||
dataset->values[index].x = toDouble( tsItems[0] );
|
||||
dataset->values[index].y = toDouble( tsItems[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( "invalid timestep line" );
|
||||
dataset->values[index].noData = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( tsItems.size() >= 1 )
|
||||
dataset->values[index].x = toDouble( tsItems[0] );
|
||||
else
|
||||
{
|
||||
debug( "invalid timestep line" );
|
||||
dataset->values[index].noData = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
datOutputs.push_back( std::move( dataset ) );
|
||||
}
|
52
external/mdal/frmts/mdal_ascii_dat.hpp
vendored
Normal file
52
external/mdal/frmts/mdal_ascii_dat.hpp
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
|
||||
*/
|
||||
|
||||
#ifndef MDAL_ASCII_DAT_HPP
|
||||
#define MDAL_ASCII_DAT_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <iosfwd>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "mdal_defines.hpp"
|
||||
#include "mdal.h"
|
||||
|
||||
namespace MDAL
|
||||
{
|
||||
|
||||
class LoaderAsciiDat
|
||||
{
|
||||
public:
|
||||
LoaderAsciiDat( const std::string &datFile );
|
||||
void load( Mesh *mesh, MDAL_Status *status );
|
||||
|
||||
private:
|
||||
void readVertexTimestep(
|
||||
const Mesh *mesh,
|
||||
std::vector<std::shared_ptr<Dataset>> &datOutputs,
|
||||
double t,
|
||||
bool isVector,
|
||||
bool hasStatus,
|
||||
std::ifstream &stream );
|
||||
|
||||
void readFaceTimestep(
|
||||
const Mesh *mesh,
|
||||
std::vector<std::shared_ptr<Dataset>> &datOutputs,
|
||||
double t,
|
||||
bool isVector,
|
||||
std::ifstream &stream );
|
||||
|
||||
void addDatasets( MDAL::Mesh *mesh,
|
||||
const std::string &name,
|
||||
const std::vector<std::shared_ptr<Dataset>> &datOutputs ) const;
|
||||
|
||||
std::string mDatFile;
|
||||
};
|
||||
|
||||
} // namespace MDAL
|
||||
#endif //MDAL_ASCII_DAT_HPP
|
307
external/mdal/frmts/mdal_binary_dat.cpp
vendored
Normal file
307
external/mdal/frmts/mdal_binary_dat.cpp
vendored
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||
Copyright (C) 2018 Lutra Consulting Ltd.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <iosfwd>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
#include "mdal_binary_dat.hpp"
|
||||
#include "mdal.h"
|
||||
#include "mdal_utils.hpp"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
static const int CT_VERSION = 3000;
|
||||
static const int CT_OBJTYPE = 100;
|
||||
static const int CT_SFLT = 110;
|
||||
static const int CT_SFLG = 120;
|
||||
static const int CT_BEGSCL = 130;
|
||||
static const int CT_BEGVEC = 140;
|
||||
static const int CT_VECTYPE = 150;
|
||||
static const int CT_OBJID = 160;
|
||||
static const int CT_NUMDATA = 170;
|
||||
static const int CT_NUMCELLS = 180;
|
||||
static const int CT_NAME = 190;
|
||||
static const int CT_TS = 200;
|
||||
static const int CT_ENDDS = 210;
|
||||
static const int CT_RT_JULIAN = 240;
|
||||
static const int CT_TIMEUNITS = 250;
|
||||
|
||||
static const int CT_2D_MESHES = 3;
|
||||
static const int CT_FLOAT_SIZE = 4;
|
||||
static const int CF_FLAG_SIZE = 1;
|
||||
static const int CF_FLAG_INT_SIZE = 4;
|
||||
|
||||
#define EXIT_WITH_ERROR(error) { if (status) *status = (error); return; }
|
||||
|
||||
static bool read( std::ifstream &in, char *s, int n )
|
||||
{
|
||||
in.read( s, n );
|
||||
if ( !in )
|
||||
return true; //error
|
||||
else
|
||||
return false; //OK
|
||||
}
|
||||
|
||||
static bool readIStat( std::ifstream &in, int sflg, char *flag )
|
||||
{
|
||||
if ( sflg == CF_FLAG_SIZE )
|
||||
{
|
||||
in.read( flag, sflg );
|
||||
if ( !in )
|
||||
return true; // error
|
||||
}
|
||||
else
|
||||
{
|
||||
int istat;
|
||||
in.read( ( char * )&istat, sflg );
|
||||
if ( !in )
|
||||
return true; // error
|
||||
else
|
||||
*flag = ( istat == 1 );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
MDAL::LoaderBinaryDat::LoaderBinaryDat( const std::string &datFile ):
|
||||
mDatFile( datFile )
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* The DAT format contains "datasets" and each dataset has N-outputs. One output
|
||||
* represents data for all vertices/faces for one timestep
|
||||
*
|
||||
* in TUFLOW results there could be also a special timestep (99999) with maximums
|
||||
* we will put it into a separate dataset with name suffixed with "/Maximums"
|
||||
*
|
||||
* In MDAL we convert one output to one MDAL dataset;
|
||||
*
|
||||
*/
|
||||
void MDAL::LoaderBinaryDat::load( MDAL::Mesh *mesh, MDAL_Status *status )
|
||||
{
|
||||
if ( status ) *status = MDAL_Status::None;
|
||||
|
||||
if ( !MDAL::fileExists( mDatFile ) )
|
||||
{
|
||||
if ( status ) *status = MDAL_Status::Err_FileNotFound;
|
||||
return;
|
||||
}
|
||||
|
||||
std::ifstream in( mDatFile, std::ifstream::in | std::ifstream::binary );
|
||||
|
||||
// implementation based on information from:
|
||||
// http://www.xmswiki.com/wiki/SMS:Binary_Dataset_Files_*.dat
|
||||
if ( !in )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_FileNotFound ); // Couldn't open the file
|
||||
|
||||
size_t vertexCount = mesh->vertices.size();
|
||||
size_t elemCount = mesh->faces.size();
|
||||
|
||||
int card = 0;
|
||||
int version;
|
||||
int objecttype;
|
||||
int sflt;
|
||||
int sflg;
|
||||
int vectype;
|
||||
int objid;
|
||||
int numdata;
|
||||
int numcells;
|
||||
char name[40];
|
||||
char istat;
|
||||
float time;
|
||||
|
||||
if ( read( in, ( char * )&version, 4 ) )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
|
||||
if ( version != CT_VERSION ) // Version should be 3000
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
|
||||
bool isVector = false;
|
||||
std::string baseDatasetName;
|
||||
std::vector<std::shared_ptr<Dataset>> datOutputs; // DAT outputs data
|
||||
|
||||
while ( card != CT_ENDDS )
|
||||
{
|
||||
if ( read( in, ( char * )&card, 4 ) )
|
||||
{
|
||||
// We've reached the end of the file and there was no ends card
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( card )
|
||||
{
|
||||
|
||||
case CT_OBJTYPE:
|
||||
// Object type
|
||||
if ( read( in, ( char * )&objecttype, 4 ) || objecttype != CT_2D_MESHES )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
break;
|
||||
|
||||
case CT_SFLT:
|
||||
// Float size
|
||||
if ( read( in, ( char * )&sflt, 4 ) || sflt != CT_FLOAT_SIZE )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
break;
|
||||
|
||||
case CT_SFLG:
|
||||
// Flag size
|
||||
if ( read( in, ( char * )&sflg, 4 ) )
|
||||
if ( sflg != CF_FLAG_SIZE && sflg != CF_FLAG_INT_SIZE )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
break;
|
||||
|
||||
case CT_BEGSCL:
|
||||
isVector = false;
|
||||
break;
|
||||
|
||||
case CT_BEGVEC:
|
||||
isVector = true;
|
||||
break;
|
||||
|
||||
case CT_VECTYPE:
|
||||
// Vector type
|
||||
if ( read( in, ( char * )&vectype, 4 ) || vectype != 0 )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
break;
|
||||
|
||||
case CT_OBJID:
|
||||
// Object id
|
||||
if ( read( in, ( char * )&objid, 4 ) )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
break;
|
||||
|
||||
case CT_NUMDATA:
|
||||
// Num data
|
||||
if ( read( in, ( char * )&numdata, 4 ) )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
if ( numdata != ( int ) vertexCount )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh );
|
||||
break;
|
||||
|
||||
case CT_NUMCELLS:
|
||||
// Num data
|
||||
if ( read( in, ( char * )&numcells, 4 ) )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
if ( numcells != ( int ) elemCount )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh );
|
||||
break;
|
||||
|
||||
case CT_NAME:
|
||||
// Name
|
||||
if ( read( in, ( char * )&name, 40 ) )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
if ( name[39] != 0 )
|
||||
name[39] = 0;
|
||||
baseDatasetName = trim( std::string( name ) );
|
||||
break;
|
||||
|
||||
case CT_TS:
|
||||
// Time step!
|
||||
if ( readIStat( in, sflg, &istat ) )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
|
||||
if ( read( in, ( char * )&time, 4 ) )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
|
||||
if ( readVertexTimestep( mesh, datOutputs, time, isVector, istat, sflg, in ) )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( datOutputs.size() == 0 )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
|
||||
addDatasets( mesh, baseDatasetName, datOutputs );
|
||||
}
|
||||
|
||||
|
||||
void MDAL::LoaderBinaryDat::addDatasets( MDAL::Mesh *mesh,
|
||||
const std::string &name,
|
||||
const std::vector<std::shared_ptr<Dataset>> &datOutputs ) const
|
||||
{
|
||||
for ( const std::shared_ptr<Dataset> &ds : datOutputs )
|
||||
{
|
||||
ds->uri = mDatFile;
|
||||
std::string suffix = ds->name();
|
||||
ds->setName( name + suffix );
|
||||
ds->isValid = true;
|
||||
}
|
||||
|
||||
//https://stackoverflow.com/a/2551785/2838364
|
||||
mesh->datasets.insert(
|
||||
mesh->datasets.end(),
|
||||
datOutputs.begin(),
|
||||
datOutputs.end()
|
||||
);
|
||||
}
|
||||
|
||||
bool MDAL::LoaderBinaryDat::readVertexTimestep( const MDAL::Mesh *mesh, std::vector<std::shared_ptr<MDAL::Dataset> > &datOutputs, float time,
|
||||
bool isVector, bool hasStatus, int sflg, std::ifstream &in )
|
||||
{
|
||||
size_t vertexCount = mesh->vertices.size();
|
||||
size_t faceCount = mesh->faces.size();
|
||||
|
||||
std::shared_ptr<MDAL::Dataset> dataset( new MDAL::Dataset );
|
||||
dataset->isScalar = !isVector; //everything else to be set in addDatasets
|
||||
dataset->setMetadata( "time", std::to_string( time / 3600.0f ) );
|
||||
dataset->values.resize( vertexCount );
|
||||
dataset->active.resize( faceCount );
|
||||
dataset->isOnVertices = true;
|
||||
|
||||
// name will be set properly in the addDatasets at the end.
|
||||
if ( time == 99999 ) // Special TUFLOW dataset with maximus
|
||||
dataset->setName( "/Maximums" );
|
||||
|
||||
bool active = true;
|
||||
for ( size_t i = 0; i < faceCount; ++i )
|
||||
{
|
||||
if ( hasStatus )
|
||||
{
|
||||
if ( readIStat( in, sflg, ( char * )&active ) )
|
||||
return true; //error
|
||||
|
||||
}
|
||||
dataset->active[i] = active;
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < vertexCount; ++i )
|
||||
{
|
||||
if ( isVector )
|
||||
{
|
||||
float x, y;
|
||||
|
||||
if ( read( in, ( char * )&x, 4 ) )
|
||||
return true; //error
|
||||
if ( read( in, ( char * )&y, 4 ) )
|
||||
return true; //error
|
||||
|
||||
dataset->values[i].x = x;
|
||||
dataset->values[i].y = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
float scalar;
|
||||
|
||||
if ( read( in, ( char * )&scalar, 4 ) )
|
||||
return true; //error
|
||||
|
||||
dataset->values[i].x = scalar;
|
||||
}
|
||||
}
|
||||
|
||||
datOutputs.push_back( std::move( dataset ) );
|
||||
|
||||
return false; //OK
|
||||
}
|
46
external/mdal/frmts/mdal_binary_dat.hpp
vendored
Normal file
46
external/mdal/frmts/mdal_binary_dat.hpp
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
|
||||
*/
|
||||
|
||||
#ifndef MDAL_BINARY_DAT_HPP
|
||||
#define MDAL_BINARY_DAT_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <iosfwd>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "mdal_defines.hpp"
|
||||
#include "mdal.h"
|
||||
|
||||
namespace MDAL
|
||||
{
|
||||
|
||||
class LoaderBinaryDat
|
||||
{
|
||||
public:
|
||||
LoaderBinaryDat( const std::string &datFile );
|
||||
void load( Mesh *mesh, MDAL_Status *status );
|
||||
|
||||
private:
|
||||
bool readVertexTimestep(
|
||||
const Mesh *mesh,
|
||||
std::vector<std::shared_ptr<Dataset>> &datOutputs,
|
||||
float time,
|
||||
bool isVector,
|
||||
bool hasStatus,
|
||||
int sflg,
|
||||
std::ifstream &in );
|
||||
|
||||
void addDatasets( MDAL::Mesh *mesh,
|
||||
const std::string &name,
|
||||
const std::vector<std::shared_ptr<Dataset>> &datOutputs ) const;
|
||||
|
||||
std::string mDatFile;
|
||||
};
|
||||
|
||||
} // namespace MDAL
|
||||
#endif //MDAL_BINARY_DAT_HPP
|
341
external/mdal/mdal.cpp
vendored
341
external/mdal/mdal.cpp
vendored
@ -1,16 +1,19 @@
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <stddef.h>
|
||||
#include <limits>
|
||||
|
||||
#include "mdal.h"
|
||||
#include "mdal_loader.hpp"
|
||||
#include "mdal_defines.hpp"
|
||||
|
||||
#define NODATA std::numeric_limits<double>::quiet_NaN()
|
||||
static const char *EMPTY_STR = "";
|
||||
|
||||
static MDAL_Status sLastStatus;
|
||||
|
||||
const char *MDAL_Version()
|
||||
{
|
||||
return "0.0.2";
|
||||
return "0.0.3";
|
||||
}
|
||||
|
||||
MDAL_Status MDAL_LastStatus()
|
||||
@ -21,10 +24,13 @@ MDAL_Status MDAL_LastStatus()
|
||||
MeshH MDAL_LoadMesh( const char *meshFile )
|
||||
{
|
||||
if ( !meshFile )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_FileNotFound;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string filename( meshFile );
|
||||
return ( MeshH ) MDAL::Loader::load( filename, &sLastStatus );
|
||||
return static_cast< MeshH >( MDAL::Loader::load( filename, &sLastStatus ).release() );
|
||||
}
|
||||
|
||||
|
||||
@ -32,7 +38,7 @@ void MDAL_CloseMesh( MeshH mesh )
|
||||
{
|
||||
if ( mesh )
|
||||
{
|
||||
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||
MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh );
|
||||
delete m;
|
||||
}
|
||||
}
|
||||
@ -40,61 +46,344 @@ void MDAL_CloseMesh( MeshH mesh )
|
||||
|
||||
int MDAL_M_vertexCount( MeshH mesh )
|
||||
{
|
||||
assert( mesh );
|
||||
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||
if ( !mesh )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh );
|
||||
int len = static_cast<int>( m->vertices.size() );
|
||||
return len;
|
||||
}
|
||||
|
||||
double MDAL_M_vertexXCoordinatesAt( MeshH mesh, int index )
|
||||
{
|
||||
assert( mesh );
|
||||
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||
assert( index > -1 );
|
||||
if ( !mesh )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return NODATA;
|
||||
}
|
||||
MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh );
|
||||
if ( index < 0 )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return NODATA;
|
||||
}
|
||||
size_t i = static_cast<size_t>( index );
|
||||
assert( m->vertices.size() > i );
|
||||
if ( m->vertices.size() <= i )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return NODATA;
|
||||
}
|
||||
return m->vertices[i].x;
|
||||
}
|
||||
|
||||
double MDAL_M_vertexYCoordinatesAt( MeshH mesh, int index )
|
||||
{
|
||||
assert( mesh );
|
||||
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||
assert( index > -1 );
|
||||
if ( !mesh )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return NODATA;
|
||||
}
|
||||
MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh );
|
||||
if ( index < 0 )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return NODATA;
|
||||
}
|
||||
size_t i = static_cast<size_t>( index );
|
||||
assert( m->vertices.size() > i );
|
||||
if ( m->vertices.size() <= i )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return NODATA;
|
||||
}
|
||||
return m->vertices[i].y;
|
||||
}
|
||||
|
||||
int MDAL_M_faceCount( MeshH mesh )
|
||||
{
|
||||
assert( mesh );
|
||||
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||
if ( !mesh )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return 0;
|
||||
}
|
||||
MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh );
|
||||
int len = static_cast<int>( m->faces.size() );
|
||||
return len;
|
||||
}
|
||||
|
||||
int MDAL_M_faceVerticesCountAt( MeshH mesh, int index )
|
||||
{
|
||||
assert( mesh );
|
||||
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||
assert( index > -1 );
|
||||
if ( !mesh )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return 0;
|
||||
}
|
||||
MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh );
|
||||
if ( index < 0 )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return 0;
|
||||
}
|
||||
size_t i = static_cast<size_t>( index );
|
||||
assert( m->faces.size() > i );
|
||||
if ( m->faces.size() <= i )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return 0;
|
||||
}
|
||||
int len = static_cast<int>( m->faces[i].size() );
|
||||
return len;
|
||||
}
|
||||
|
||||
int MDAL_M_faceVerticesIndexAt( MeshH mesh, int face_index, int vertex_index )
|
||||
{
|
||||
assert( mesh );
|
||||
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||
assert( face_index > -1 );
|
||||
if ( !mesh )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return 0;
|
||||
}
|
||||
MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh );
|
||||
if ( face_index < 0 )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return 0;
|
||||
}
|
||||
size_t fi = static_cast<size_t>( face_index );
|
||||
assert( m->faces.size() > fi );
|
||||
assert( vertex_index > -1 );
|
||||
if ( m->faces.size() <= fi )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return 0;
|
||||
}
|
||||
if ( vertex_index < 0 )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return 0;
|
||||
}
|
||||
size_t vi = static_cast<size_t>( vertex_index );
|
||||
assert( m->faces[fi].size() > vi );
|
||||
if ( m->faces[fi].size() <= vi )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return 0;
|
||||
}
|
||||
int len = static_cast<int>( m->faces[fi][vi] );
|
||||
return len;
|
||||
}
|
||||
|
||||
void MDAL_M_LoadDatasets( MeshH mesh, const char *datasetFile )
|
||||
{
|
||||
if ( !datasetFile )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_FileNotFound;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !mesh )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return;
|
||||
}
|
||||
|
||||
MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh );
|
||||
|
||||
std::string filename( datasetFile );
|
||||
MDAL::Loader::loadDatasets( m, datasetFile, &sLastStatus );
|
||||
}
|
||||
|
||||
void MDAL_M_CloseDataset( DatasetH dataset )
|
||||
{
|
||||
if ( !dataset )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MDAL::Dataset *d = static_cast< MDAL::Dataset * >( dataset );
|
||||
d->free();
|
||||
}
|
||||
|
||||
int MDAL_M_datasetCount( MeshH mesh )
|
||||
{
|
||||
if ( !mesh )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return 0;
|
||||
}
|
||||
MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh );
|
||||
int len = static_cast<int>( m->datasets.size() );
|
||||
return len;
|
||||
}
|
||||
|
||||
DatasetH MDAL_M_dataset( MeshH mesh, int index )
|
||||
{
|
||||
if ( !mesh )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return nullptr;
|
||||
}
|
||||
MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh );
|
||||
int len = static_cast<int>( m->datasets.size() );
|
||||
if ( len <= index )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return nullptr;
|
||||
}
|
||||
size_t i = static_cast<size_t>( index );
|
||||
return static_cast< DatasetH >( m->datasets[i].get() );
|
||||
}
|
||||
|
||||
bool MDAL_D_hasScalarData( DatasetH dataset )
|
||||
{
|
||||
if ( !dataset )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return true;
|
||||
}
|
||||
MDAL::Dataset *d = static_cast< MDAL::Dataset * >( dataset );
|
||||
return d->isScalar;
|
||||
}
|
||||
|
||||
bool MDAL_D_isOnVertices( DatasetH dataset )
|
||||
{
|
||||
if ( !dataset )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return true;
|
||||
}
|
||||
MDAL::Dataset *d = static_cast< MDAL::Dataset * >( dataset );
|
||||
return d->isOnVertices;
|
||||
}
|
||||
|
||||
int MDAL_D_metadataCount( DatasetH dataset )
|
||||
{
|
||||
if ( !dataset )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return 0;
|
||||
}
|
||||
MDAL::Dataset *d = static_cast< MDAL::Dataset * >( dataset );
|
||||
int len = static_cast<int>( d->metadata.size() );
|
||||
return len;
|
||||
}
|
||||
|
||||
const char *MDAL_D_metadataKey( DatasetH dataset, int index )
|
||||
{
|
||||
if ( !dataset )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
MDAL::Dataset *d = static_cast< MDAL::Dataset * >( dataset );
|
||||
int len = static_cast<int>( d->metadata.size() );
|
||||
if ( len <= index )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return nullptr;
|
||||
}
|
||||
size_t i = static_cast<size_t>( index );
|
||||
return d->metadata[i].first.c_str();
|
||||
}
|
||||
|
||||
const char *MDAL_D_metadataValue( DatasetH dataset, int index )
|
||||
{
|
||||
if ( !dataset )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return EMPTY_STR;
|
||||
}
|
||||
MDAL::Dataset *d = static_cast< MDAL::Dataset * >( dataset );
|
||||
int len = static_cast<int>( d->metadata.size() );
|
||||
if ( len <= index )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return nullptr;
|
||||
}
|
||||
size_t i = static_cast<size_t>( index );
|
||||
return d->metadata[i].second.c_str();
|
||||
}
|
||||
|
||||
int MDAL_D_valueCount( DatasetH dataset )
|
||||
{
|
||||
if ( !dataset )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return 0;
|
||||
}
|
||||
MDAL::Dataset *d = static_cast< MDAL::Dataset * >( dataset );
|
||||
int len = static_cast<int>( d->values.size() );
|
||||
return len;
|
||||
}
|
||||
|
||||
double MDAL_D_value( DatasetH dataset, int valueIndex )
|
||||
{
|
||||
return MDAL_D_valueX( dataset, valueIndex );
|
||||
}
|
||||
|
||||
double MDAL_D_valueX( DatasetH dataset, int valueIndex )
|
||||
{
|
||||
if ( !dataset )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return NODATA;
|
||||
}
|
||||
MDAL::Dataset *d = static_cast< MDAL::Dataset * >( dataset );
|
||||
int len = static_cast<int>( d->values.size() );
|
||||
if ( len <= valueIndex )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return NODATA;
|
||||
}
|
||||
size_t i = static_cast<size_t>( valueIndex );
|
||||
if ( d->values[i].noData )
|
||||
{
|
||||
return NODATA;
|
||||
}
|
||||
else
|
||||
return d->values[i].x;
|
||||
}
|
||||
|
||||
double MDAL_D_valueY( DatasetH dataset, int valueIndex )
|
||||
{
|
||||
if ( !dataset )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return NODATA;
|
||||
}
|
||||
MDAL::Dataset *d = static_cast< MDAL::Dataset * >( dataset );
|
||||
int len = static_cast<int>( d->values.size() );
|
||||
if ( len <= valueIndex )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return NODATA;
|
||||
}
|
||||
size_t i = static_cast<size_t>( valueIndex );
|
||||
if ( d->values[i].noData )
|
||||
{
|
||||
return NODATA;
|
||||
}
|
||||
else
|
||||
return d->values[i].y;
|
||||
}
|
||||
|
||||
bool MDAL_D_isValid( DatasetH dataset )
|
||||
{
|
||||
if ( !dataset )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return false;
|
||||
}
|
||||
MDAL::Dataset *d = static_cast< MDAL::Dataset * >( dataset );
|
||||
return d->isValid;
|
||||
}
|
||||
|
||||
bool MDAL_D_active( DatasetH dataset, int faceIndex )
|
||||
{
|
||||
if ( !dataset )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return false;
|
||||
}
|
||||
MDAL::Dataset *d = static_cast< MDAL::Dataset * >( dataset );
|
||||
size_t i = static_cast<size_t>( faceIndex );
|
||||
return d->isActive( i );
|
||||
}
|
||||
|
101
external/mdal/mdal_defines.hpp
vendored
101
external/mdal/mdal_defines.hpp
vendored
@ -8,6 +8,8 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
namespace MDAL
|
||||
{
|
||||
@ -20,12 +22,105 @@ namespace MDAL
|
||||
|
||||
typedef std::vector<size_t> Face;
|
||||
|
||||
struct Mesh
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
std::vector<Vertex> vertices;
|
||||
std::vector<Face> faces;
|
||||
double x;
|
||||
double y;
|
||||
|
||||
bool noData = false;
|
||||
} Value; //Dataset Value
|
||||
|
||||
class Dataset
|
||||
{
|
||||
public:
|
||||
|
||||
std::string getMetadata( const std::string &key )
|
||||
{
|
||||
for ( auto pair : metadata )
|
||||
{
|
||||
if ( pair.first == key )
|
||||
{
|
||||
return pair.second;
|
||||
}
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void 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 ) );
|
||||
}
|
||||
|
||||
std::string name()
|
||||
{
|
||||
return getMetadata( "name" );
|
||||
}
|
||||
|
||||
void setName( const std::string &name )
|
||||
{
|
||||
setMetadata( "name", name );
|
||||
}
|
||||
|
||||
std::vector< std::pair< std::string, std::string > > metadata;
|
||||
std::vector<Value> values; // size - vertex count if isOnVertices
|
||||
// size - face count if !isOnVertices
|
||||
std::vector<bool> active; // size - face count. Whether the output for this is active...
|
||||
|
||||
bool isScalar = true;
|
||||
bool isOnVertices = true;
|
||||
bool isValid = true;
|
||||
|
||||
std::string uri; // file/uri from where it came
|
||||
|
||||
|
||||
void free()
|
||||
{
|
||||
values.clear();
|
||||
metadata.clear();
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
bool isActive( size_t faceIndex )
|
||||
{
|
||||
if ( isOnVertices )
|
||||
{
|
||||
if ( active.size() > faceIndex )
|
||||
return active[faceIndex];
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Mesh
|
||||
{
|
||||
std::string uri; // file/uri from where it came
|
||||
|
||||
std::vector<Vertex> vertices;
|
||||
std::map<size_t, size_t> vertexIDtoIndex; // only for 2DM and DAT files
|
||||
|
||||
std::vector<Face> faces;
|
||||
std::map<size_t, size_t> faceIDtoIndex; // only for 2DM and DAT files
|
||||
|
||||
std::vector<std::shared_ptr<Dataset>> datasets;
|
||||
};
|
||||
} // namespace MDAL
|
||||
#endif //MDAL_DEFINES_HPP
|
||||
|
||||
|
16
external/mdal/mdal_loader.cpp
vendored
16
external/mdal/mdal_loader.cpp
vendored
@ -5,9 +5,23 @@
|
||||
|
||||
#include "mdal_loader.hpp"
|
||||
#include "frmts/mdal_2dm.hpp"
|
||||
#include "frmts/mdal_ascii_dat.hpp"
|
||||
#include "frmts/mdal_binary_dat.hpp"
|
||||
|
||||
MDAL::Mesh *MDAL::Loader::load( const std::string &meshFile, MDAL_Status *status )
|
||||
std::unique_ptr<MDAL::Mesh> MDAL::Loader::load( const std::string &meshFile, MDAL_Status *status )
|
||||
{
|
||||
MDAL::Loader2dm loader( meshFile );
|
||||
return loader.load( status );
|
||||
}
|
||||
|
||||
void MDAL::Loader::loadDatasets( Mesh *mesh, const std::string &datasetFile, MDAL_Status *status )
|
||||
{
|
||||
MDAL::LoaderAsciiDat loader( datasetFile );
|
||||
loader.load( mesh, status );
|
||||
|
||||
if ( status && *status == MDAL_Status::Err_UnknownFormat )
|
||||
{
|
||||
MDAL::LoaderBinaryDat loader( datasetFile );
|
||||
loader.load( mesh, status );
|
||||
}
|
||||
}
|
||||
|
5
external/mdal/mdal_loader.hpp
vendored
5
external/mdal/mdal_loader.hpp
vendored
@ -7,6 +7,8 @@
|
||||
#define MDAL_LOADER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "mdal.h"
|
||||
#include "mdal_defines.hpp"
|
||||
@ -17,7 +19,8 @@ namespace MDAL
|
||||
class Loader
|
||||
{
|
||||
public:
|
||||
static Mesh *load( const std::string &meshFile, MDAL_Status *status );
|
||||
static std::unique_ptr< Mesh > load( const std::string &meshFile, MDAL_Status *status );
|
||||
static void loadDatasets( Mesh *mesh, const std::string &datasetFile, MDAL_Status *status );
|
||||
};
|
||||
|
||||
} // namespace MDAL
|
||||
|
42
external/mdal/mdal_utils.cpp
vendored
42
external/mdal/mdal_utils.cpp
vendored
@ -5,6 +5,7 @@
|
||||
|
||||
#include "mdal_utils.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
bool MDAL::fileExists( const std::string &filename )
|
||||
{
|
||||
@ -47,10 +48,49 @@ size_t MDAL::toSizeT( const std::string &str )
|
||||
int i = atoi( str.c_str() );
|
||||
if ( i < 0 ) // consistent with atoi return
|
||||
i = 0;
|
||||
return i;
|
||||
return static_cast< size_t >( i );
|
||||
}
|
||||
|
||||
double MDAL::toDouble( const std::string &str )
|
||||
{
|
||||
return atof( str.c_str() );
|
||||
}
|
||||
|
||||
std::string MDAL::baseName( const std::string &filename )
|
||||
{
|
||||
// https://stackoverflow.com/a/8520815/2838364
|
||||
std::string fname( filename );
|
||||
|
||||
// Remove directory if present.
|
||||
// Do this before extension removal incase directory has a period character.
|
||||
const size_t last_slash_idx = fname.find_last_of( "\\/" );
|
||||
if ( std::string::npos != last_slash_idx )
|
||||
{
|
||||
fname.erase( 0, last_slash_idx + 1 );
|
||||
}
|
||||
|
||||
// Remove extension if present.
|
||||
const size_t period_idx = fname.rfind( '.' );
|
||||
if ( std::string::npos != period_idx )
|
||||
{
|
||||
fname.erase( period_idx );
|
||||
}
|
||||
return fname;
|
||||
}
|
||||
|
||||
bool MDAL::contains( const std::string &str, const std::string &substr )
|
||||
{
|
||||
return str.find( substr ) != std::string::npos;
|
||||
}
|
||||
|
||||
void MDAL::debug( const std::string &message )
|
||||
{
|
||||
//TODO something smarter
|
||||
std::cout << message << std::endl;
|
||||
}
|
||||
|
||||
bool MDAL::toBool( const std::string &str )
|
||||
{
|
||||
int i = atoi( str.c_str() );
|
||||
return i != 0;
|
||||
}
|
||||
|
30
external/mdal/mdal_utils.hpp
vendored
30
external/mdal/mdal_utils.hpp
vendored
@ -13,15 +13,21 @@
|
||||
namespace MDAL
|
||||
{
|
||||
|
||||
// debugging
|
||||
void debug( const std::string &message );
|
||||
|
||||
/** Return whether file exists */
|
||||
bool fileExists( const std::string &filename );
|
||||
std::string baseName( const std::string &filename );
|
||||
|
||||
// strings
|
||||
bool startsWith( const std::string &str, const std::string &substr );
|
||||
bool contains( const std::string &str, const std::string &substr );
|
||||
|
||||
/** Return 0 if not possible to convert */
|
||||
size_t toSizeT( const std::string &str );
|
||||
double toDouble( const std::string &str );
|
||||
bool toBool( const std::string &str );
|
||||
|
||||
enum SplitBehaviour
|
||||
{
|
||||
@ -30,5 +36,29 @@ namespace MDAL
|
||||
};
|
||||
std::vector<std::string> split( const std::string &str, const std::string &delimiter, SplitBehaviour behaviour );
|
||||
|
||||
// http://www.cplusplus.com/faq/sequences/strings/trim/
|
||||
inline std::string rtrim(
|
||||
const std::string &s,
|
||||
const std::string &delimiters = " \f\n\r\t\v" )
|
||||
{
|
||||
return s.substr( 0, s.find_last_not_of( delimiters ) + 1 );
|
||||
}
|
||||
|
||||
// http://www.cplusplus.com/faq/sequences/strings/trim/
|
||||
inline std::string ltrim(
|
||||
const std::string &s,
|
||||
const std::string &delimiters = " \f\n\r\t\v" )
|
||||
{
|
||||
return s.substr( s.find_first_not_of( delimiters ) );
|
||||
}
|
||||
|
||||
// http://www.cplusplus.com/faq/sequences/strings/trim/
|
||||
inline std::string trim(
|
||||
const std::string &s,
|
||||
const std::string &delimiters = " \f\n\r\t\v" )
|
||||
{
|
||||
return ltrim( rtrim( s, delimiters ), delimiters );
|
||||
}
|
||||
|
||||
} // namespace MDAL
|
||||
#endif //MDAL_UTILS_HPP
|
||||
|
Loading…
x
Reference in New Issue
Block a user