From 1c2f40fadc5c667156d79925967722ff8e915704 Mon Sep 17 00:00:00 2001 From: rinkk <karsten.rink@ufz.de> Date: Fri, 29 Jan 2016 15:56:23 +0100 Subject: [PATCH] introduced RasterHeader container and removed lots of parameters --- .../DataView/NetCdfConfigureDialog.cpp | 12 +-- .../DataExplorer/VtkVis/VtkRaster.cpp | 26 +++---- Applications/DataExplorer/VtkVis/VtkRaster.h | 9 +-- FileIO/AsciiRasterInterface.cpp | 68 ++++++++--------- FileIO/AsciiRasterInterface.h | 11 +-- GeoLib/Raster.cpp | 73 +++++++++--------- GeoLib/Raster.h | 62 ++++++--------- MeshLib/MeshGenerators/VtkMeshConverter.cpp | 75 ++++++++----------- MeshLib/MeshGenerators/VtkMeshConverter.h | 20 ++--- 9 files changed, 151 insertions(+), 205 deletions(-) diff --git a/Applications/DataExplorer/DataView/NetCdfConfigureDialog.cpp b/Applications/DataExplorer/DataView/NetCdfConfigureDialog.cpp index 490f89bf42c..7866dfc23bf 100644 --- a/Applications/DataExplorer/DataView/NetCdfConfigureDialog.cpp +++ b/Applications/DataExplorer/DataView/NetCdfConfigureDialog.cpp @@ -3,6 +3,8 @@ #include "NetCdfConfigureDialog.h" +#include "MathLib/Point3d.h" +#include "GeoLib/Raster.h" #include "MeshGenerators/VtkMeshConverter.h" #include "MeshLib/MeshEnums.h" #include "VtkGeoImageSource.h" @@ -352,13 +354,14 @@ void NetCdfConfigureDialog::createDataObject() double origin_x = (originLon < lastLon) ? originLon : lastLon; double origin_y = (originLat < lastLat) ? originLat : lastLat; - double originNetCdf[3] = {origin_x, origin_y, 0}; + MathLib::Point3d origin({{origin_x, origin_y, 0}}); double resolution = (doubleSpinBoxResolution->value()); if (originLat > lastLat) // reverse lines in vertical direction if the original file has its origin in the northwest corner this->reverseNorthSouth(data_array, sizeLon, sizeLat); + GeoLib::RasterHeader header = {sizeLon,sizeLat,origin,resolution,-9999}; if (this->radioMesh->isChecked()) { MeshLib::MeshElemType meshElemType = MeshLib::MeshElemType::QUAD; @@ -375,14 +378,13 @@ void NetCdfConfigureDialog::createDataObject() }else{ useIntensity = MeshLib::UseIntensityAs::DATAVECTOR; } - - _currentMesh = MeshLib::VtkMeshConverter::convertImgToMesh(data_array,originNetCdf,sizeLon,sizeLat,resolution,meshElemType,useIntensity); + _currentMesh = MeshLib::VtkMeshConverter::convertImgToMesh(data_array, header, meshElemType, useIntensity); } else { - vtkImageImport* image = VtkRaster::loadImageFromArray(data_array, originNetCdf[0], originNetCdf[1], sizeLon, sizeLat, resolution, -9999.0); + vtkImageImport* image = VtkRaster::loadImageFromArray(data_array, header); _currentRaster = VtkGeoImageSource::New(); - _currentRaster->setImage(image, QString::fromStdString(this->getName()), originNetCdf[0], originNetCdf[1], resolution); + _currentRaster->setImage(image, QString::fromStdString(this->getName()), origin[0], origin[1], resolution); } delete[] length; diff --git a/Applications/DataExplorer/VtkVis/VtkRaster.cpp b/Applications/DataExplorer/VtkVis/VtkRaster.cpp index dea54ab1f38..c04b1644b61 100644 --- a/Applications/DataExplorer/VtkVis/VtkRaster.cpp +++ b/Applications/DataExplorer/VtkVis/VtkRaster.cpp @@ -54,15 +54,8 @@ vtkImageAlgorithm* VtkRaster::loadImage(const std::string &fileName, { raster = FileIO::AsciiRasterInterface::getRasterFromSurferFile(fileName); } - if (raster) { - x0 = raster->getOrigin()[0]; - y0 = raster->getOrigin()[1]; - delta = raster->getRasterPixelSize(); - double const*const data (raster->begin()); - return VtkRaster::loadImageFromArray(data, x0, y0, - raster->getNCols(), raster->getNRows(), delta, - raster->getNoDataValue()); - } + if (raster) + return VtkRaster::loadImageFromArray(raster->begin(), raster->getHeader()); else if ((fileInfo.suffix().toLower() == "tif") || (fileInfo.suffix().toLower() == "tiff")) { #ifdef GEOTIFF_FOUND @@ -75,16 +68,15 @@ vtkImageAlgorithm* VtkRaster::loadImage(const std::string &fileName, else return loadImageFromFile(fileName); } - -vtkImageImport* VtkRaster::loadImageFromArray(double const*const data_array, double x0, double y0, std::size_t width, std::size_t height, double delta, double noData) +vtkImageImport* VtkRaster::loadImageFromArray(double const*const data_array, GeoLib::RasterHeader header) { - const unsigned length = height*width; + const unsigned length = header.n_rows*header.n_cols; float* data = new float[length*2]; float max_val = *std::max_element(data_array, data_array+length); for (unsigned j=0; j<length; ++j) { data[j*2] = static_cast<float>(data_array[j]); - if (fabs(data[j*2]-noData) < std::numeric_limits<double>::epsilon()) + if (fabs(data[j*2]-header.no_data) < std::numeric_limits<double>::epsilon()) { data[j*2] = max_val; data[j*2+1] = 0; @@ -94,10 +86,10 @@ vtkImageImport* VtkRaster::loadImageFromArray(double const*const data_array, dou } vtkImageImport* image = vtkImageImport::New(); - image->SetDataSpacing(delta, delta, delta); - image->SetDataOrigin(x0+(delta/2.0), y0+(delta/2.0), 0); // translate whole mesh by half a pixel in x and y - image->SetWholeExtent(0, width-1, 0, height-1, 0, 0); - image->SetDataExtent(0, width-1, 0, height-1, 0, 0); + image->SetDataSpacing(header.cell_size, header.cell_size, header.cell_size); + image->SetDataOrigin(header.origin[0]+(header.cell_size/2.0), header.origin[1]+(header.cell_size/2.0), 0); // translate whole mesh by half a pixel in x and y + image->SetWholeExtent(0, header.n_rows-1, 0, header.n_cols-1, 0, 0); + image->SetDataExtent(0, header.n_rows-1, 0, header.n_cols-1, 0, 0); image->SetDataExtentToWholeExtent(); image->SetDataScalarTypeToFloat(); image->SetNumberOfScalarComponents(2); diff --git a/Applications/DataExplorer/VtkVis/VtkRaster.h b/Applications/DataExplorer/VtkVis/VtkRaster.h index f5ba39c9e03..ae32757a130 100644 --- a/Applications/DataExplorer/VtkVis/VtkRaster.h +++ b/Applications/DataExplorer/VtkVis/VtkRaster.h @@ -15,6 +15,7 @@ #define VTKRASTER_H #include <string> +#include "GeoLib/Raster.h" class vtkImageAlgorithm; class vtkImageImport; @@ -32,13 +33,7 @@ public: /** * \brief Returns a VtkImageAlgorithm from an array of pixel values and some image meta data. */ - static vtkImageImport* loadImageFromArray(double const*const data_array, - double x0, - double y0, - std::size_t width, - std::size_t height, - double delta, - double no_data = -9999); + static vtkImageImport* loadImageFromArray(double const*const data_array, GeoLib::RasterHeader header); /** * \brief Loads an image- or raster-file into an vtkImageAlgorithm-Object. * diff --git a/FileIO/AsciiRasterInterface.cpp b/FileIO/AsciiRasterInterface.cpp index 8ef729016c7..bfa3f081163 100644 --- a/FileIO/AsciiRasterInterface.cpp +++ b/FileIO/AsciiRasterInterface.cpp @@ -43,24 +43,21 @@ GeoLib::Raster* AsciiRasterInterface::getRasterFromASCFile(std::string const& fn } // header information - std::size_t n_cols(0), n_rows(0); - double xllcorner(0.0), yllcorner(0.0), cell_size(0.0), no_data_val(-9999); - - if (readASCHeader(in, n_cols, n_rows, xllcorner, yllcorner, cell_size, no_data_val)) { - double* values = new double[n_cols*n_rows]; + GeoLib::RasterHeader header; + if (readASCHeader(in, header)) { + double* values = new double[header.n_cols*header.n_rows]; std::string s; // read the data into the double-array - for (std::size_t j(0); j < n_rows; ++j) { - const std::size_t idx ((n_rows - j - 1) * n_cols); - for (std::size_t i(0); i < n_cols; ++i) { + 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(),0); } } in.close(); - GeoLib::Raster *raster(new GeoLib::Raster(n_cols, n_rows, xllcorner, yllcorner, - cell_size, values, values+n_cols*n_rows, no_data_val)); + GeoLib::Raster *raster(new GeoLib::Raster(header, values, values+header.n_cols*header.n_rows)); delete [] values; return raster; } else { @@ -69,45 +66,45 @@ GeoLib::Raster* AsciiRasterInterface::getRasterFromASCFile(std::string const& fn } } -bool AsciiRasterInterface::readASCHeader(std::ifstream &in, std::size_t &n_cols, std::size_t &n_rows, - double &xllcorner, double &yllcorner, double &cell_size, double &no_data_val) +bool AsciiRasterInterface::readASCHeader(std::ifstream &in, GeoLib::RasterHeader &header) { std::string tag, value; in >> tag; if (tag.compare("ncols") == 0) { in >> value; - n_cols = atoi(value.c_str()); + header.n_cols = atoi(value.c_str()); } else return false; in >> tag; if (tag.compare("nrows") == 0) { in >> value; - n_rows = atoi(value.c_str()); + header.n_rows = atoi(value.c_str()); } else return false; in >> tag; if (tag.compare("xllcorner") == 0 || tag.compare("xllcenter") == 0) { in >> value; - xllcorner = strtod(BaseLib::replaceString(",", ".", value).c_str(), 0); + header.origin[0] = strtod(BaseLib::replaceString(",", ".", value).c_str(), 0); } else return false; in >> tag; if (tag.compare("yllcorner") == 0 || tag.compare("yllcenter") == 0) { in >> value; - yllcorner = strtod(BaseLib::replaceString(",", ".", value).c_str(), 0); + header.origin[1] = strtod(BaseLib::replaceString(",", ".", value).c_str(), 0); } else return false; + header.origin[2] = 0; in >> tag; if (tag.compare("cellsize") == 0) { in >> value; - cell_size = strtod(BaseLib::replaceString(",", ".", value).c_str(), 0); + header.cell_size = strtod(BaseLib::replaceString(",", ".", value).c_str(), 0); } else return false; in >> tag; if (tag.compare("NODATA_value") == 0 || tag.compare("nodata_value") == 0) { in >> value; - no_data_val = strtod(BaseLib::replaceString(",", ".", value).c_str(), 0); + header.no_data = strtod(BaseLib::replaceString(",", ".", value).c_str(), 0); } else return false; return true; @@ -123,19 +120,19 @@ GeoLib::Raster* AsciiRasterInterface::getRasterFromSurferFile(std::string const& } // header information - std::size_t n_cols(0), n_rows(0); - double xllcorner(0.0), yllcorner(0.0), cell_size(0.0), min(0.0), max(0.0); + GeoLib::RasterHeader header; + double min(0.0), max(0.0); - if (readSurferHeader(in, n_cols, n_rows, xllcorner, yllcorner, cell_size, min, max)) + if (readSurferHeader(in, header, min, max)) { const double no_data_val (min-1); - double* values = new double[n_cols*n_rows]; + double* values = new double[header.n_cols*header.n_rows]; std::string s; // read the data into the double-array - for (std::size_t j(0); j < n_rows; ++j) + for (std::size_t j(0); j < header.n_rows; ++j) { - const std::size_t idx (j * n_cols); - for (std::size_t i(0); i < 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(),0)); @@ -143,8 +140,7 @@ GeoLib::Raster* AsciiRasterInterface::getRasterFromSurferFile(std::string const& } } in.close(); - GeoLib::Raster *raster(new GeoLib::Raster(n_cols, n_rows, xllcorner, yllcorner, cell_size, - values, values+n_cols*n_rows, no_data_val)); + GeoLib::Raster *raster(new GeoLib::Raster(header, values, values+header.n_cols*header.n_rows)); delete [] values; return raster; } else { @@ -153,8 +149,8 @@ GeoLib::Raster* AsciiRasterInterface::getRasterFromSurferFile(std::string const& } } -bool AsciiRasterInterface::readSurferHeader(std::ifstream &in, std::size_t &n_cols, std::size_t &n_rows, - double &xllcorner, double &yllcorner, double &cell_size, double &min, double &max) +bool AsciiRasterInterface::readSurferHeader(std::ifstream &in, GeoLib::RasterHeader &header, + double &min, double &max) { std::string tag; @@ -167,21 +163,23 @@ bool AsciiRasterInterface::readSurferHeader(std::ifstream &in, std::size_t &n_co } else { - in >> n_cols >> n_rows; + in >> header.n_cols >> header.n_rows; in >> min >> max; - xllcorner = min; - cell_size = (max-min)/static_cast<double>(n_cols); + header.origin[0] = min; + header.cell_size = (max-min)/static_cast<double>(header.n_cols); in >> min >> max; - yllcorner = min; + header.origin[1] = min; + header.origin[2] = 0; - if (ceil((max-min)/static_cast<double>(n_rows)) == ceil(cell_size)) - cell_size = ceil(cell_size); + if (ceil((max-min)/static_cast<double>(header.n_rows)) == ceil(header.cell_size)) + header.cell_size = ceil(header.cell_size); else { ERR("Error in readSurferHeader() - Anisotropic cellsize detected."); return 0; } + header.no_data = min-1; in >> min >> max; } diff --git a/FileIO/AsciiRasterInterface.h b/FileIO/AsciiRasterInterface.h index 6cd7bc1a413..f4898c3c1c3 100644 --- a/FileIO/AsciiRasterInterface.h +++ b/FileIO/AsciiRasterInterface.h @@ -16,9 +16,7 @@ #include <fstream> -namespace GeoLib { - class Raster; -} +#include "GeoLib/Raster.h" namespace FileIO { @@ -44,13 +42,10 @@ public: private: /// Reads the header of a Esri asc-file. - static bool readASCHeader(std::ifstream &in, std::size_t &n_cols, std::size_t &n_rows, - double &xllcorner, double &yllcorner, double &cell_size, - double &no_data_val); + static bool readASCHeader(std::ifstream &in, GeoLib::RasterHeader &header); /// Reads the header of a Surfer grd-file. - static bool readSurferHeader(std::ifstream &in, std::size_t &n_cols, std::size_t &n_rows, - double &xllcorner, double &yllcorner, double &cell_size, + static bool readSurferHeader(std::ifstream &in, GeoLib::RasterHeader &header, double &min, double &max); }; diff --git a/GeoLib/Raster.cpp b/GeoLib/Raster.cpp index 85b2c247ada..e5a2f079462 100644 --- a/GeoLib/Raster.cpp +++ b/GeoLib/Raster.cpp @@ -28,13 +28,13 @@ namespace GeoLib { void Raster::refineRaster(std::size_t scaling) { - double *new_raster_data(new double[_n_rows*_n_cols*scaling*scaling]); + double *new_raster_data(new double[_header.n_rows*_header.n_cols*scaling*scaling]); - for (std::size_t row(0); row<_n_rows; row++) { - for (std::size_t col(0); col<_n_cols; col++) { - const std::size_t idx(row*_n_cols+col); + for (std::size_t row(0); row<_header.n_rows; row++) { + for (std::size_t col(0); col<_header.n_cols; col++) { + const std::size_t idx(row*_header.n_cols+col); for (std::size_t new_row(row*scaling); new_row<(row+1)*scaling; new_row++) { - const std::size_t idx0(new_row*_n_cols*scaling); + const std::size_t idx0(new_row*_header.n_cols*scaling); for (std::size_t new_col(col*scaling); new_col<(col+1)*scaling; new_col++) { new_raster_data[idx0+new_col] = _raster_data[idx]; } @@ -43,9 +43,9 @@ void Raster::refineRaster(std::size_t scaling) } std::swap(_raster_data, new_raster_data); - _cell_size /= scaling; - _n_cols *= scaling; - _n_rows *= scaling; + _header.cell_size /= scaling; + _header.n_cols *= scaling; + _header.n_rows *= scaling; delete [] new_raster_data; } @@ -57,17 +57,17 @@ Raster::~Raster() void Raster::setCellSize(double cell_size) { - _cell_size = cell_size; + _header.cell_size = cell_size; } void Raster::setNoDataVal (double no_data_val) { - _no_data_val = no_data_val; + _header.no_data = no_data_val; } -GeoLib::Point const& Raster::getOrigin() const +GeoLib::Point const Raster::getOrigin() const { - return _ll_pnt; + return GeoLib::Point(_header.origin,0); } Raster* Raster::getRasterFromSurface(Surface const& sfc, double cell_size, double no_data_val) @@ -100,42 +100,43 @@ Raster* Raster::getRasterFromSurface(Surface const& sfc, double cell_size, doubl } } - return new Raster(n_cols, n_rows, ll[0], ll[1], cell_size, z_vals, z_vals+n_cols*n_rows ,-9999); + RasterHeader header = {std::size_t(n_cols), std::size_t(n_rows), MathLib::Point3d(ll), cell_size, static_cast<double>(-9999)}; + return new Raster(header, z_vals, z_vals+n_cols*n_rows); } double Raster::getValueAtPoint(const MathLib::Point3d &pnt) const { - if (pnt[0]>=_ll_pnt[0] && pnt[0]<(_ll_pnt[0]+(_cell_size*_n_cols)) && - pnt[1]>=_ll_pnt[1] && pnt[1]<(_ll_pnt[1]+(_cell_size*_n_rows))) + if (pnt[0]>=_header.origin[0] && pnt[0]<(_header.origin[0]+(_header.cell_size*_header.n_cols)) && + pnt[1]>=_header.origin[1] && pnt[1]<(_header.origin[1]+(_header.cell_size*_header.n_rows))) { - int cell_x = static_cast<int>(std::floor((pnt[0] - _ll_pnt[0])/_cell_size)); - int cell_y = static_cast<int>(std::floor((pnt[1] - _ll_pnt[1])/_cell_size)); + int cell_x = static_cast<int>(std::floor((pnt[0] - _header.origin[0])/_header.cell_size)); + int cell_y = static_cast<int>(std::floor((pnt[1] - _header.origin[1])/_header.cell_size)); // use raster boundary values if node is outside raster due to rounding errors or floating point arithmetic - cell_x = (cell_x < 0) ? 0 : ((cell_x > static_cast<int>(_n_cols)) ? - static_cast<int>(_n_cols-1) : cell_x); - cell_y = (cell_y < 0) ? 0 : ((cell_y > static_cast<int>(_n_rows)) ? - static_cast<int>(_n_rows-1) : cell_y); + cell_x = (cell_x < 0) ? 0 : ((cell_x > static_cast<int>(_header.n_cols)) ? + static_cast<int>(_header.n_cols-1) : cell_x); + cell_y = (cell_y < 0) ? 0 : ((cell_y > static_cast<int>(_header.n_rows)) ? + static_cast<int>(_header.n_rows-1) : cell_y); - const std::size_t index = cell_y*_n_cols+cell_x; + const std::size_t index = cell_y*_header.n_cols+cell_x; return _raster_data[index]; } - return _no_data_val; + return _header.no_data; } double Raster::interpolateValueAtPoint(MathLib::Point3d const& pnt) const { // position in raster - double const xPos ((pnt[0] - _ll_pnt[0]) / _cell_size); - double const yPos ((pnt[1] - _ll_pnt[1]) / _cell_size); + double const xPos ((pnt[0] - _header.origin[0]) / _header.cell_size); + double const yPos ((pnt[1] - _header.origin[1]) / _header.cell_size); // raster cell index double const xIdx (std::floor(xPos)); //carry out computions in double double const yIdx (std::floor(yPos)); // so not to over- or underflow. // weights for bilinear interpolation - double const half_delta = 0.5*_cell_size; - double const xShift = std::fabs(xPos-(xIdx+half_delta)) / _cell_size; - double const yShift = std::fabs(yPos-(yIdx+half_delta)) / _cell_size; + double const half_delta = 0.5*_header.cell_size; + double const xShift = std::fabs(xPos-(xIdx+half_delta)) / _header.cell_size; + double const yShift = std::fabs(yPos-(yIdx+half_delta)) / _header.cell_size; std::array<double,4> weight = {{ (1-xShift)*(1-yShift), xShift*(1-yShift), xShift*yShift, (1-xShift)*yShift }}; // neighbors to include in interpolation @@ -153,16 +154,16 @@ double Raster::interpolateValueAtPoint(MathLib::Point3d const& pnt) const // a no data value. This also allows the cast to unsigned type. if ( (xIdx + x_nb[j]) < 0 || (yIdx + y_nb[j]) < 0 || - (xIdx + x_nb[j]) > (_n_cols-1) || - (yIdx + y_nb[j]) > (_n_rows-1) ) - pix_val[j] = _no_data_val; + (xIdx + x_nb[j]) > (_header.n_cols-1) || + (yIdx + y_nb[j]) > (_header.n_rows-1) ) + pix_val[j] = _header.no_data; else pix_val[j] = _raster_data[ - static_cast<std::size_t>(yIdx + y_nb[j]) * _n_cols + + static_cast<std::size_t>(yIdx + y_nb[j]) * _header.n_cols + static_cast<std::size_t>(xIdx + x_nb[j])]; // remove no data values - if (std::fabs(pix_val[j] - _no_data_val) < std::numeric_limits<double>::epsilon()) + if (std::fabs(pix_val[j] - _header.no_data) < std::numeric_limits<double>::epsilon()) { weight[j] = 0; no_data_count++; @@ -173,7 +174,7 @@ double Raster::interpolateValueAtPoint(MathLib::Point3d const& pnt) const if (no_data_count > 0) { if (no_data_count == 4) // if there is absolutely no data just use the default value - return _no_data_val; + return _header.no_data; const double norm = 1.0 / (weight[0]+weight[1]+weight[2]+weight[3]); std::for_each(weight.begin(), weight.end(), [&norm](double &val){val*=norm;}); @@ -185,8 +186,8 @@ double Raster::interpolateValueAtPoint(MathLib::Point3d const& pnt) const bool Raster::isPntOnRaster(MathLib::Point3d const& pnt) const { - if ((pnt[0]<_ll_pnt[0]) || (pnt[0]>_ll_pnt[0]+(_n_cols*_cell_size)) || - (pnt[1]<_ll_pnt[1]) || (pnt[1]>_ll_pnt[1]+(_n_rows*_cell_size))) + if ((pnt[0]<_header.origin[0]) || (pnt[0]>_header.origin[0]+(_header.n_cols*_header.cell_size)) || + (pnt[1]<_header.origin[1]) || (pnt[1]>_header.origin[1]+(_header.n_rows*_header.cell_size))) return false; return true; } diff --git a/GeoLib/Raster.h b/GeoLib/Raster.h index abb05c32a69..78183ee72f5 100644 --- a/GeoLib/Raster.h +++ b/GeoLib/Raster.h @@ -18,6 +18,16 @@ namespace GeoLib { +/// Contains the relevant information when handling with geoscientific raster data +struct RasterHeader +{ + std::size_t n_cols; // width + std::size_t n_rows; // height + MathLib::Point3d origin; // lower left corner + double cell_size; // edge length of each pixel + double no_data; // no data value +}; + /** * @brief Class Raster is used for managing raster data. * @@ -36,20 +46,13 @@ public: * to be handed over via input iterators. Deploying iterators has the * advantage that the use of the class is independent from the input * container. - * @param n_cols number of columns - * @param n_rows number of rows - * @param xllcorner the \f$x\f$ coordinate of lower left point - * @param yllcorner the \f$y\f$ coordinate of lower left point - * @param cell_size the size of a raster pixel + * @param header meta-information about the raster (height, width, etc.) * @param begin input iterator pointing to the first element of the data * @param end input iterator pointing to the last element of the data, end have to be reachable from begin - * @param no_data_val value for raster pixels that have not valid values */ template<typename InputIterator> - Raster(std::size_t n_cols, std::size_t n_rows, double xllcorner, double yllcorner, - double cell_size, InputIterator begin, InputIterator end, double no_data_val = -9999) : - _n_cols(n_cols), _n_rows(n_rows), _ll_pnt(xllcorner, yllcorner, 0.0), _cell_size(cell_size), - _no_data_val(no_data_val), _raster_data(new double[n_cols*n_rows]) + Raster(RasterHeader header, InputIterator begin, InputIterator end) : + _header(header), _raster_data(new double[_header.n_cols*_header.n_rows]) { iterator raster_it(_raster_data); for (InputIterator it(begin); it != end; ++it) { @@ -58,32 +61,35 @@ public: } } + /// Returns the complete header information + RasterHeader const& getHeader() const { return _header; } + /** * get the number of columns for the raster */ - std::size_t getNCols() const { return _n_cols; } + std::size_t getNCols() const { return _header.n_cols; } /** * get the number of rows for the raster */ - std::size_t getNRows() const { return _n_rows; } + std::size_t getNRows() const { return _header.n_rows; } /** * get the distance between raster pixels */ - double getRasterPixelSize() const { return _cell_size; } + double getRasterPixelSize() const { return _header.cell_size; } /** * get the origin of lower left raster cell * @return the origin of the raster */ - GeoLib::Point const& getOrigin() const; + GeoLib::Point const getOrigin() const; /** * Refine the raster using scaling as a refinement parameter. */ void refineRaster(std::size_t scaling); - double getNoDataValue() const { return _no_data_val; } + double getNoDataValue() const { return _header.no_data; } /** * Constant iterator that is pointing to the first raster pixel value. @@ -94,7 +100,7 @@ public: * Constant iterator that is pointing to the last raster pixel value. * @return constant iterator */ - const_iterator end() const { return _raster_data + _n_rows*_n_cols; } + const_iterator end() const { return _raster_data + _header.n_rows*_header.n_cols; } /** * Returns the raster value at the position of the given point. @@ -116,29 +122,7 @@ private: void setCellSize(double cell_size); void setNoDataVal (double no_data_val); - /** - * number of columns of the raster - */ - std::size_t _n_cols; - /** - * number of rows of the raster - */ - std::size_t _n_rows; - /** - * lower left point of the raster - */ - GeoLib::Point _ll_pnt; - /** - * cell size - each cell is quadratic - */ - double _cell_size; - /** - * value for cells there is no data for - */ - double _no_data_val; - /** - * raw raster data - */ + GeoLib::RasterHeader _header; double* _raster_data; }; diff --git a/MeshLib/MeshGenerators/VtkMeshConverter.cpp b/MeshLib/MeshGenerators/VtkMeshConverter.cpp index 18e876aba01..f7a6f55b086 100644 --- a/MeshLib/MeshGenerators/VtkMeshConverter.cpp +++ b/MeshLib/MeshGenerators/VtkMeshConverter.cpp @@ -71,18 +71,17 @@ MeshLib::Mesh* VtkMeshConverter::convertImgToMesh(vtkImageData* img, return nullptr; } - const std::size_t imgHeight = dims[0]; - const std::size_t imgWidth = dims[1]; - const std::size_t incHeight = imgHeight+1; - const std::size_t incWidth = imgWidth+1; + MathLib::Point3d orig ({{origin[0], origin[1], origin[2]}}); + GeoLib::RasterHeader header = {dims[1], dims[0], orig, scalingFactor, -9999}; + const std::size_t incHeight = header.n_rows+1; + const std::size_t incWidth = header.n_cols+1; std::vector<double> pix_val (incHeight * incWidth, std::numeric_limits<double>::max()); - std::vector<bool> pix_vis (imgHeight * imgWidth, false); + std::vector<bool> pix_vis (header.n_rows * header.n_cols, false); - for (std::size_t i = 0; i < imgWidth; i++) - { - for (std::size_t j = 0; j < imgHeight; j++) + for (std::size_t i = 0; i < header.n_cols; i++) + for (std::size_t j = 0; j < header.n_rows; j++) { - std::size_t const img_idx = i*imgHeight + j; + std::size_t const img_idx = i*header.n_rows + j; std::size_t const fld_idx = i*incHeight + j; // colour of current pixel @@ -92,7 +91,7 @@ MeshLib::Mesh* VtkMeshConverter::convertImgToMesh(vtkImageData* img, if (!visible) continue; - double const value = (nTuple < 3) ? + double const value = (nTuple < 3) ? colour[0] : // grey (+ alpha) (0.3 * colour[0] + 0.6 * colour[1] + 0.1 * colour[2]); // rgb(a) pix_vis[img_idx] = true; @@ -101,17 +100,13 @@ MeshLib::Mesh* VtkMeshConverter::convertImgToMesh(vtkImageData* img, pix_val[fld_idx+incHeight] = value; pix_val[fld_idx+incHeight+1] = value; } - } - - return constructMesh(pix_val, pix_vis, origin, imgHeight, imgWidth, scalingFactor, elem_type, intensity_type); + + return constructMesh(pix_val, pix_vis, header, elem_type, intensity_type); } MeshLib::Mesh* VtkMeshConverter::convertImgToMesh( const double* img, - const double origin[3], - const std::size_t imgHeight, - const std::size_t imgWidth, - const double &scalingFactor, + GeoLib::RasterHeader const& header, MeshElemType elem_type, UseIntensityAs intensity_type) { @@ -121,15 +116,15 @@ MeshLib::Mesh* VtkMeshConverter::convertImgToMesh( return nullptr; } - std::size_t const incHeight (imgHeight+1); - std::size_t const incWidth (imgWidth+1); + std::size_t const incHeight (header.n_rows+1); + std::size_t const incWidth (header.n_cols+1); std::vector<double> pix_val (incHeight * incWidth, std::numeric_limits<double>::max()); std::vector<bool> pix_vis (incHeight * incWidth, false); - for (std::size_t i = 0; i < imgWidth; i++) - for (std::size_t j = 0; j < imgHeight; j++) + for (std::size_t i = 0; i < header.n_cols; i++) + for (std::size_t j = 0; j < header.n_rows; j++) { - std::size_t const img_idx = i*imgHeight + j; + std::size_t const img_idx = i*header.n_rows + j; std::size_t const fld_idx = i*incHeight + j; if (img[img_idx] == -9999) continue; @@ -141,26 +136,23 @@ MeshLib::Mesh* VtkMeshConverter::convertImgToMesh( pix_val[fld_idx+incHeight+1] = img[img_idx]; } - return constructMesh(pix_val, pix_vis, origin, imgHeight, imgWidth, scalingFactor, elem_type, intensity_type); + return constructMesh(pix_val, pix_vis, header, elem_type, intensity_type); } MeshLib::Mesh* VtkMeshConverter::constructMesh( std::vector<double> const& pix_val, std::vector<bool> const& pix_vis, - double const origin[3], - std::size_t const imgHeight, - std::size_t const imgWidth, - double const scalingFactor, + GeoLib::RasterHeader const& header, MeshLib::MeshElemType elem_type, MeshLib::UseIntensityAs intensity_type) { - std::vector<int> node_idx_map ((imgHeight+1) * (imgWidth+1), -1); + std::vector<int> node_idx_map ((header.n_rows+1) * (header.n_cols+1), -1); bool const use_elevation (intensity_type == MeshLib::UseIntensityAs::ELEVATION); - std::vector<MeshLib::Node*> nodes (createNodeVector(pix_val, node_idx_map, imgHeight, imgWidth, origin, scalingFactor, use_elevation)); + std::vector<MeshLib::Node*> nodes (createNodeVector(pix_val, node_idx_map, header, use_elevation)); if (nodes.empty()) return nullptr; - std::vector<MeshLib::Element*> elements (createElementVector(pix_val, pix_vis, nodes, node_idx_map, imgHeight, imgWidth, elem_type)); + std::vector<MeshLib::Element*> elements (createElementVector(pix_val, pix_vis, nodes, node_idx_map, header.n_rows, header.n_cols, elem_type)); if (elements.empty()) return nullptr; @@ -169,13 +161,13 @@ MeshLib::Mesh* VtkMeshConverter::constructMesh( { boost::optional< MeshLib::PropertyVector<int>& > prop_vec = properties.createNewPropertyVector<int>("MaterialIDs", MeshLib::MeshItemType::Cell, 1); - fillPropertyVector<int>(*prop_vec, pix_val, pix_vis, imgHeight, imgWidth, elem_type); - } + fillPropertyVector<int>(*prop_vec, pix_val, pix_vis, header.n_rows, header.n_cols, elem_type); + } else if (intensity_type == MeshLib::UseIntensityAs::DATAVECTOR) { boost::optional< MeshLib::PropertyVector<double>& > prop_vec = properties.createNewPropertyVector<double>("Colour", MeshLib::MeshItemType::Cell, 1); - fillPropertyVector<double>(*prop_vec, pix_val, pix_vis, imgHeight, imgWidth, elem_type); + fillPropertyVector<double>(*prop_vec, pix_val, pix_vis, header.n_rows, header.n_cols, elem_type); } return new MeshLib::Mesh("RasterDataMesh", nodes, elements, properties); @@ -184,25 +176,22 @@ MeshLib::Mesh* VtkMeshConverter::constructMesh( std::vector<MeshLib::Node*> VtkMeshConverter::createNodeVector( std::vector<double> const& elevation, std::vector<int> & node_idx_map, - std::size_t const imgHeight, - std::size_t const imgWidth, - double const origin[3], - double const scalingFactor, + GeoLib::RasterHeader const& header, bool use_elevation) { std::size_t node_idx_count(0); - double const x_offset(origin[0] - scalingFactor/2.0); - double const y_offset(origin[1] - scalingFactor/2.0); + double const x_offset(header.origin[0] - header.cell_size/2.0); + double const y_offset(header.origin[1] - header.cell_size/2.0); std::vector<MeshLib::Node*> nodes; - for (std::size_t i = 0; i < (imgWidth+1); i++) - for (std::size_t j = 0; j < (imgHeight+1); j++) + for (std::size_t i = 0; i < (header.n_cols+1); i++) + for (std::size_t j = 0; j < (header.n_rows+1); j++) { - std::size_t const index = i * (imgHeight+1) + j; + std::size_t const index = i * (header.n_rows+1) + j; if (elevation[index] == std::numeric_limits<double>::max()) continue; double const zValue = (use_elevation) ? elevation[index] : 0; - MeshLib::Node* node (new MeshLib::Node(x_offset + (scalingFactor * j), y_offset + (scalingFactor * i), zValue)); + MeshLib::Node* node (new MeshLib::Node(x_offset + (header.cell_size * j), y_offset + (header.cell_size * i), zValue)); nodes.push_back(node); node_idx_map[index] = node_idx_count; node_idx_count++; diff --git a/MeshLib/MeshGenerators/VtkMeshConverter.h b/MeshLib/MeshGenerators/VtkMeshConverter.h index c8db6ed8b08..b195daade6e 100644 --- a/MeshLib/MeshGenerators/VtkMeshConverter.h +++ b/MeshLib/MeshGenerators/VtkMeshConverter.h @@ -22,6 +22,7 @@ #include "logog/include/logog.hpp" +#include "GeoLib/Raster.h" #include "MeshLib/Node.h" #include "MeshLib/Location.h" #include "MeshLib/MeshEnums.h" @@ -61,10 +62,7 @@ public: * \param intensity_type defines how image intensities are interpreted */ static MeshLib::Mesh* convertImgToMesh(const double* img, - const double origin[3], - const std::size_t imgHeight, - const std::size_t imgWidth, - const double &scalingFactor, + GeoLib::RasterHeader const& header, MeshElemType elem_type, UseIntensityAs intensity_type); @@ -73,27 +71,19 @@ public: std::string const& mesh_name = "vtkUnstructuredGrid"); private: - /// Constructs mesh components based on image data. static MeshLib::Mesh* constructMesh( std::vector<double> const& pix_val, std::vector<bool> const& pix_vis, - double const origin[3], - std::size_t const imgHeight, - std::size_t const imgWidth, - double const scalingFactor, + GeoLib::RasterHeader const& header, MeshLib::MeshElemType elem_type, MeshLib::UseIntensityAs intensity_type); static void convertScalarArrays(vtkUnstructuredGrid &grid, MeshLib::Mesh &mesh); - /// Creates a mesh node vector based on image data - static std::vector<MeshLib::Node*> createNodeVector( + static std::vector<MeshLib::Node*> VtkMeshConverter::createNodeVector( std::vector<double> const& elevation, std::vector<int> &node_idx_map, - std::size_t const incHeight, - std::size_t const incWidth, - double const origin[3], - double const scalingFactor, + GeoLib::RasterHeader const& header, bool use_elevation); /// Creates a mesh element vector based on image data -- GitLab