diff --git a/Applications/FileIO/AsciiRasterInterface.cpp b/Applications/FileIO/AsciiRasterInterface.cpp index feb49a25d1e4deeeb3dc25cb28d514b5fa7247a2..a6b65d5eba9a5fcefb321bec2e66f1c2daeceba0 100644 --- a/Applications/FileIO/AsciiRasterInterface.cpp +++ b/Applications/FileIO/AsciiRasterInterface.cpp @@ -13,12 +13,12 @@ #include "AsciiRasterInterface.h" -#include <optional> +#include <tuple> #include "BaseLib/FileTools.h" #include "BaseLib/Logging.h" #include "BaseLib/StringTools.h" -#include "GeoLib/Raster.h" + namespace FileIO { @@ -37,49 +37,21 @@ GeoLib::Raster* AsciiRasterInterface::readRaster(std::string const& fname) return nullptr; } -GeoLib::Raster* AsciiRasterInterface::getRasterFromASCFile( - std::string const& fname) +/// Reads a double replacing comma by point. +static double readDoubleFromStream(std::istream& in) { - std::ifstream in(fname.c_str()); - - if (!in.is_open()) - { - WARN("Raster::getRasterFromASCFile(): Could not open file {:s}.", - fname); - return nullptr; - } - - // header information - GeoLib::RasterHeader header; - if (readASCHeader(in, header)) - { - std::vector<double> values(header.n_cols * header.n_rows); - std::string s; - // read the data into the double-array - for (std::size_t j(0); j < header.n_rows; ++j) - { - const std::size_t idx((header.n_rows - j - 1) * header.n_cols); - for (std::size_t i(0); i < header.n_cols; ++i) - { - in >> s; - values[idx + i] = strtod( - BaseLib::replaceString(",", ".", s).c_str(), nullptr); - } - } - in.close(); - GeoLib::Raster* raster(new GeoLib::Raster( - std::move(header), values.data(), values.data() + values.size())); - - return raster; - } - WARN("Raster::getRasterFromASCFile(): Could not read header of file {:s}", - fname); - return nullptr; + std::string value; + in >> value; + return std::strtod(BaseLib::replaceString(",", ".", value).c_str(), + nullptr); } -bool AsciiRasterInterface::readASCHeader(std::ifstream& in, - GeoLib::RasterHeader& header) +/// Reads the header of a Esri asc-file. +/// If the return value is empty, reading was not successful. +static std::optional<GeoLib::RasterHeader> readASCHeader(std::ifstream& in) { + GeoLib::RasterHeader header; + std::string tag; std::string value; @@ -91,7 +63,7 @@ bool AsciiRasterInterface::readASCHeader(std::ifstream& in, } else { - return false; + return {}; } in >> tag; @@ -102,7 +74,7 @@ bool AsciiRasterInterface::readASCHeader(std::ifstream& in, } else { - return false; + return {}; } header.n_depth = 1; @@ -110,103 +82,87 @@ bool AsciiRasterInterface::readASCHeader(std::ifstream& in, in >> tag; if (tag == "xllcorner" || tag == "xllcenter") { - in >> value; - header.origin[0] = - strtod(BaseLib::replaceString(",", ".", value).c_str(), nullptr); + header.origin[0] = readDoubleFromStream(in); } else { - return false; + return {}; } in >> tag; if (tag == "yllcorner" || tag == "yllcenter") { - in >> value; - header.origin[1] = - strtod(BaseLib::replaceString(",", ".", value).c_str(), nullptr); + header.origin[1] = readDoubleFromStream(in); } else { - return false; + return {}; } header.origin[2] = 0; in >> tag; if (tag == "cellsize") { - in >> value; - header.cell_size = - strtod(BaseLib::replaceString(",", ".", value).c_str(), nullptr); + header.cell_size = readDoubleFromStream(in); } else { - return false; + return {}; } in >> tag; if (tag == "NODATA_value" || tag == "nodata_value") { - in >> value; - header.no_data = - strtod(BaseLib::replaceString(",", ".", value).c_str(), nullptr); + header.no_data = readDoubleFromStream(in); } else { - return false; + return {}; } - return true; + return header; } -GeoLib::Raster* AsciiRasterInterface::getRasterFromSurferFile( +GeoLib::Raster* AsciiRasterInterface::getRasterFromASCFile( std::string const& fname) { std::ifstream in(fname.c_str()); if (!in.is_open()) { - ERR("Raster::getRasterFromSurferFile() - Could not open file {:s}", - fname); + WARN("Raster::getRasterFromASCFile(): Could not open file {:s}.", + fname); return nullptr; } - // header information - GeoLib::RasterHeader header; - double min(0.0); - double max(0.0); + auto const header = readASCHeader(in); + if (!header) + { + WARN( + "Raster::getRasterFromASCFile(): Could not read header of file " + "{:s}", + fname); + return nullptr; + } - if (readSurferHeader(in, header, min, max)) + std::vector<double> values(header->n_cols * header->n_rows); + // read the data into the double-array + for (std::size_t j(0); j < header->n_rows; ++j) { - const double no_data_val(min - 1); - std::vector<double> values(header.n_cols * header.n_rows); - std::string s; - // read the data into the double-array - for (std::size_t j(0); j < header.n_rows; ++j) + const std::size_t idx((header->n_rows - j - 1) * header->n_cols); + for (std::size_t i(0); i < header->n_cols; ++i) { - const std::size_t idx(j * header.n_cols); - for (std::size_t i(0); i < header.n_cols; ++i) - { - in >> s; - const double val(strtod( - BaseLib::replaceString(",", ".", s).c_str(), nullptr)); - values[idx + i] = (val > max || val < min) ? no_data_val : val; - } + values[idx + i] = readDoubleFromStream(in); } - in.close(); - GeoLib::Raster* raster(new GeoLib::Raster( - std::move(header), values.data(), values.data() + values.size())); - - return raster; } - ERR("Raster::getRasterFromASCFile() - could not read header of file {:s}", - fname); - return nullptr; + + return new GeoLib::Raster(*header, values.begin(), values.end()); } -bool AsciiRasterInterface::readSurferHeader(std::ifstream& in, - GeoLib::RasterHeader& header, - double& min, double& max) +/// Reads the header of a Surfer grd-file with minimum and maximum values. +/// If the return value is empty, reading was not successful. +static std::optional<std::tuple<GeoLib::RasterHeader, double, double>> +readSurferHeader(std::ifstream& in) { std::string tag; @@ -215,10 +171,12 @@ bool AsciiRasterInterface::readSurferHeader(std::ifstream& in, if (tag != "DSAA") { ERR("Error in readSurferHeader() - No Surfer file."); - return false; + return {}; } + GeoLib::RasterHeader header; in >> header.n_cols >> header.n_rows; + double min, max; in >> min >> max; header.origin[0] = min; header.cell_size = (max - min) / static_cast<double>(header.n_cols); @@ -235,13 +193,51 @@ bool AsciiRasterInterface::readSurferHeader(std::ifstream& in, else { ERR("Error in readSurferHeader() - Anisotropic cellsize detected."); - return false; + return {}; } header.n_depth = 1; header.no_data = min - 1; in >> min >> max; - return true; + return {{header, min, max}}; +} + +GeoLib::Raster* AsciiRasterInterface::getRasterFromSurferFile( + std::string const& fname) +{ + std::ifstream in(fname.c_str()); + + if (!in.is_open()) + { + ERR("Raster::getRasterFromSurferFile() - Could not open file {:s}", + fname); + return nullptr; + } + + auto const optional_header = readSurferHeader(in); + if (!optional_header) + { + ERR("Raster::getRasterFromASCFile() - could not read header of file " + "{:s}", + fname); + return nullptr; + } + + auto const [header, min, max] = *optional_header; + const double no_data_val(min - 1); + std::vector<double> values(header.n_cols * header.n_rows); + // read the data into the double-array + for (std::size_t j(0); j < header.n_rows; ++j) + { + const std::size_t idx(j * header.n_cols); + for (std::size_t i(0); i < header.n_cols; ++i) + { + const double val = readDoubleFromStream(in); + values[idx + i] = (val > max || val < min) ? no_data_val : val; + } + } + + return new GeoLib::Raster(header, values.begin(), values.end()); } void AsciiRasterInterface::writeRasterAsASC(GeoLib::Raster const& raster, diff --git a/Applications/FileIO/AsciiRasterInterface.h b/Applications/FileIO/AsciiRasterInterface.h index e9fc471eb5513bda1ad617caf9a1024cf5451c56..dc17ebed64c8bd6d7042c62721791b144d6ce93c 100644 --- a/Applications/FileIO/AsciiRasterInterface.h +++ b/Applications/FileIO/AsciiRasterInterface.h @@ -40,15 +40,6 @@ public: /// Writes an Esri asc-file static void writeRasterAsASC(GeoLib::Raster const& raster, std::string const& file_name); - - -private: - /// Reads the header of a Esri asc-file. - static bool readASCHeader(std::ifstream &in, GeoLib::RasterHeader &header); - - /// Reads the header of a Surfer grd-file. - static bool readSurferHeader(std::ifstream &in, GeoLib::RasterHeader &header, - double &min, double &max); }; /// Reads a vector of rasters given by file names. On error nothing is returned,