diff --git a/external/mdal/frmts/mdal_grib.cpp b/external/mdal/frmts/mdal_gdal_grib.cpp similarity index 75% rename from external/mdal/frmts/mdal_grib.cpp rename to external/mdal/frmts/mdal_gdal_grib.cpp index 2655967323f..6c5b8d8a093 100644 --- a/external/mdal/frmts/mdal_grib.cpp +++ b/external/mdal/frmts/mdal_gdal_grib.cpp @@ -4,20 +4,20 @@ */ -#include "mdal_grib.hpp" +#include "mdal_gdal_grib.hpp" #include "mdal_utils.hpp" #include #include -MDAL::LoaderGrib::LoaderGrib( const std::string &gribFile ) +MDAL::LoaderGdalGrib::LoaderGdalGrib( const std::string &gribFile ) : MDAL::LoaderGdal( gribFile, "GRIB" ), mRefTime( std::numeric_limits::min() ) {} -bool MDAL::LoaderGrib::parseBandInfo( const MDAL::GdalDataset *cfGDALDataset, - const metadata_hash &metadata, std::string &band_name, - double *time, bool *is_vector, bool *is_x - ) +bool MDAL::LoaderGdalGrib::parseBandInfo( const MDAL::GdalDataset *cfGDALDataset, + const metadata_hash &metadata, std::string &band_name, + double *time, bool *is_vector, bool *is_x + ) { MDAL_UNUSED( cfGDALDataset ); diff --git a/external/mdal/frmts/mdal_grib.hpp b/external/mdal/frmts/mdal_gdal_grib.hpp similarity index 81% rename from external/mdal/frmts/mdal_grib.hpp rename to external/mdal/frmts/mdal_gdal_grib.hpp index fd869160cfb..7cdc528b555 100644 --- a/external/mdal/frmts/mdal_grib.hpp +++ b/external/mdal/frmts/mdal_gdal_grib.hpp @@ -3,8 +3,8 @@ Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com) */ -#ifndef MDAL_GRIB_HPP -#define MDAL_GRIB_HPP +#ifndef MDAL_GDAL_GRIB_HPP +#define MDAL_GDAL_GRIB_HPP #include "mdal_gdal.hpp" #include "mdal_data_model.hpp" @@ -14,10 +14,10 @@ namespace MDAL { - class LoaderGrib: public LoaderGdal + class LoaderGdalGrib: public LoaderGdal { public: - LoaderGrib( const std::string &gribFile ); + LoaderGdalGrib( const std::string &gribFile ); private: bool parseBandInfo( const MDAL::GdalDataset *cfGDALDataset, const metadata_hash &metadata, std::string &band_name, @@ -35,4 +35,4 @@ namespace MDAL }; } // namespace MDAL -#endif // MDAL_GRIB_HPP +#endif // MDAL_GDAL_GRIB_HPP diff --git a/external/mdal/frmts/mdal_gdal_netcdf.cpp b/external/mdal/frmts/mdal_gdal_netcdf.cpp new file mode 100644 index 00000000000..e9024afcf6a --- /dev/null +++ b/external/mdal/frmts/mdal_gdal_netcdf.cpp @@ -0,0 +1,79 @@ +/* + MDAL - Mesh Data Abstraction Library (MIT License) + Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com) +*/ + +#include "mdal_gdal_netcdf.hpp" +#include "mdal_utils.hpp" + +MDAL::LoaderGdalNetCDF::LoaderGdalNetCDF( const std::string &netCDFFile ) + : MDAL::LoaderGdal( netCDFFile, "GRIB" ) + , mTimeDiv( 1.0 ) +{ +} + +std::string MDAL::LoaderGdalNetCDF::GDALFileName( const std::string &fileName ) +{ +#ifdef WIN32 + // Force usage of the predefined GDAL driver + // http://gis.stackexchange.com/a/179167 + // on Windows, HDF5 driver is checked before NETCDF driver in GDAL + return "NETCDF:\"" + fileName + "\""; +#else + return fileName; +#endif +} + +bool MDAL::LoaderGdalNetCDF::parseBandInfo( const MDAL::GdalDataset *cfGDALDataset, const MDAL::LoaderGdal::metadata_hash &metadata, std::string &band_name, double *time, bool *is_vector, bool *is_x ) +{ + MDAL_UNUSED( cfGDALDataset ); + + metadata_hash::const_iterator iter; + + iter = metadata.find( "netcdf_dim_time" ); + if ( iter == metadata.end() ) return true; //FAILURE, skip no-time bands + *time = parseMetadataTime( iter->second ) / mTimeDiv; + + // NAME + iter = metadata.find( "long_name" ); + if ( iter == metadata.end() ) + { + iter = metadata.find( "netcdf_varname" ); + if ( iter == metadata.end() ) return true; //FAILURE, should be always present + band_name = iter->second; + } + else + { + band_name = iter->second; + } + + // Loop throught all additional dimensions but time + for ( iter = metadata.begin(); iter != metadata.end(); ++iter ) + { + std::string key = iter->first; + if ( MDAL::contains( key, "netcdf_dim_" ) ) + { + key = MDAL::replace( key, "netcdf_dim_", "" ); + if ( key != "time" ) + { + band_name += "_" + key + ":" + iter->second; + } + } + } + + // Parse X, Y components if present + parseBandIsVector( band_name, is_vector, is_x ); + + return false; // SUCCESS +} + +void MDAL::LoaderGdalNetCDF::parseGlobals( const MDAL::LoaderGdal::metadata_hash &metadata ) +{ + metadata_hash::const_iterator iter = metadata.find( "time#units" ); + if ( iter != metadata.end() ) + { + std::string units = iter->second; + mTimeDiv = MDAL::parseTimeUnits( units ); + // TODO store reference time from iter->second too, see crayfish_netcdf.cpp + } +} diff --git a/external/mdal/frmts/mdal_gdal_netcdf.hpp b/external/mdal/frmts/mdal_gdal_netcdf.hpp new file mode 100644 index 00000000000..cee50321c52 --- /dev/null +++ b/external/mdal/frmts/mdal_gdal_netcdf.hpp @@ -0,0 +1,34 @@ +/* + MDAL - Mesh Data Abstraction Library (MIT License) + Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com) +*/ + +#ifndef MDAL_GDAL_NETCDF_HPP +#define MDAL_GDAL_NETCDF_HPP + +#include "mdal_gdal.hpp" +#include "mdal_data_model.hpp" +#include "mdal.h" +#include + +namespace MDAL +{ + + class LoaderGdalNetCDF: public LoaderGdal + { + public: + LoaderGdalNetCDF( const std::string &netCDFFile ); + private: + std::string GDALFileName( const std::string &fileName ) override; + bool parseBandInfo( const MDAL::GdalDataset *cfGDALDataset, + const metadata_hash &metadata, std::string &band_name, + double *time, bool *is_vector, bool *is_x + ) override; + void parseGlobals( const metadata_hash &metadata ) override; + + //! delimiter to get time in hours + double mTimeDiv; + }; + +} // namespace MDAL +#endif // MDAL_GDAL_NETCDF_HPP diff --git a/external/mdal/mdal_loader.cpp b/external/mdal/mdal_loader.cpp index b02fe2ba4bb..a7cb9ad7704 100644 --- a/external/mdal/mdal_loader.cpp +++ b/external/mdal/mdal_loader.cpp @@ -15,13 +15,17 @@ #endif #ifdef HAVE_GDAL -#include "frmts/mdal_grib.hpp" +#include "frmts/mdal_gdal_grib.hpp" #endif #ifdef HAVE_NETCDF #include "frmts/mdal_3di.hpp" #endif +#if defined HAVE_GDAL && defined HAVE_NETCDF +#include "frmts/mdal_gdal_netcdf.hpp" +#endif + std::unique_ptr MDAL::Loader::load( const std::string &meshFile, MDAL_Status *status ) { if ( !MDAL::fileExists( meshFile ) ) @@ -44,11 +48,22 @@ std::unique_ptr MDAL::Loader::load( const std::string &meshFile, MDA #ifdef HAVE_GDAL if ( !mesh && status && *status == MDAL_Status::Err_UnknownFormat ) { - MDAL::LoaderGrib loader( meshFile ); - mesh = loader.load( status ); +#ifdef HAVE_NETCDF + if ( MDAL::endsWith( meshFile, ".nc" ) ) + { + MDAL::LoaderGdalNetCDF loader( meshFile ); + mesh = loader.load( status ); + } + else + { +#endif // HAVE_GDAL && HAVE_NETCDF + MDAL::LoaderGdalGrib loader( meshFile ); + mesh = loader.load( status ); + } +#ifdef HAVE_NETCDF } -#endif - +#endif // HAVE_GDAL && HAVE_NETCDF +#endif // HAVE_GDAL return mesh; } diff --git a/src/providers/mdal/CMakeLists.txt b/src/providers/mdal/CMakeLists.txt index 12fcfce9907..4e2c50c52e2 100644 --- a/src/providers/mdal/CMakeLists.txt +++ b/src/providers/mdal/CMakeLists.txt @@ -66,11 +66,11 @@ IF (WITH_INTERNAL_MDAL) IF(GDAL_FOUND) SET(MDAL_LIB_SRCS ${MDAL_LIB_SRCS} ${CMAKE_SOURCE_DIR}/external/mdal/frmts/mdal_gdal.cpp - ${CMAKE_SOURCE_DIR}/external/mdal/frmts/mdal_grib.cpp + ${CMAKE_SOURCE_DIR}/external/mdal/frmts/mdal_gdal_grib.cpp ) SET(MDAL_LIB_HDRS ${MDAL_LIB_HDRS} ${CMAKE_SOURCE_DIR}/external/mdal/frmts/mdal_gdal.hpp - ${CMAKE_SOURCE_DIR}/external/mdal/frmts/mdal_grib.hpp + ${CMAKE_SOURCE_DIR}/external/mdal/frmts/mdal_gdal_grib.hpp ) SET (HAVE_GDAL TRUE) ENDIF(GDAL_FOUND) @@ -88,6 +88,15 @@ IF (WITH_INTERNAL_MDAL) SET (HAVE_NETCDF TRUE) ENDIF(NETCDF_FOUND) + IF(GDAL_FOUND AND NETCDF_FOUND) + SET(MDAL_LIB_SRCS ${MDAL_LIB_SRCS} + ${CMAKE_SOURCE_DIR}/external/mdal/frmts/mdal_gdal_netcdf.cpp + ) + SET(MDAL_LIB_HDRS ${MDAL_LIB_HDRS} + ${CMAKE_SOURCE_DIR}/external/mdal/frmts/mdal_gdal_netcdf.hpp + ) + ENDIF(GDAL_FOUND AND NETCDF_FOUND) + # create mdal_config.h CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/external/mdal/cmake_templates/mdal_config.hpp.in ${CMAKE_BINARY_DIR}/mdal_config.hpp) INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})