From cfb78529a670c1cdf159d07a1f216f33b0911fa1 Mon Sep 17 00:00:00 2001 From: rahv <karsten.rink@ufz.de> Date: Wed, 3 Jun 2015 11:05:39 +0200 Subject: [PATCH] fixes for issues #677 and #678 --- GeoLib/Raster.cpp | 105 +++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 48 deletions(-) diff --git a/GeoLib/Raster.cpp b/GeoLib/Raster.cpp index 7b93f3edeea..6aa37aec30d 100644 --- a/GeoLib/Raster.cpp +++ b/GeoLib/Raster.cpp @@ -123,58 +123,67 @@ double Raster::getValueAtPoint(const MathLib::Point3d &pnt) const 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); - // raster cell index - std::size_t const xIdx (static_cast<size_t>(std::floor(xPos))); - std::size_t const yIdx (static_cast<size_t>(std::floor(yPos))); - - // 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; - std::array<double,4> weight = {{ (1-xShift)*(1-xShift), xShift*(1-yShift), xShift*yShift, (1-xShift)*yShift }}; - - // neightbors to include in interpolation - int const xShiftIdx = (xPos-xIdx-half_delta>=0) ? 1 : -1; - int const yShiftIdx = (yPos-yIdx-half_delta>=0) ? 1 : -1; - std::array<int,4> const x_nb = {{ 0, xShiftIdx, xShiftIdx, 0 }}; - std::array<int,4> const y_nb = {{ 0, 0, yShiftIdx, yShiftIdx }}; - - // get pixel values - std::array<double,4> pix_val; - unsigned no_data_count (0); - for (unsigned j=0; j<4; ++j) - { - pix_val[j] = _raster_data[(yIdx + y_nb[j])*_n_cols + (xIdx + x_nb[j])]; - if (std::fabs(pix_val[j] - _no_data_val) < std::numeric_limits<double>::epsilon()) - { - weight[j] = 0; - no_data_count++; - } - } - - // adjust weights if necessary - 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; - - const double norm = (double)(4)/(4-no_data_count); - std::for_each(weight.begin(), weight.end(), [&norm](double &val){val*=norm;}); - } - - // new value - return MathLib::scalarProduct<double,4>(weight.data(), pix_val.data()); -} + // position in raster + double const xPos ((pnt[0] - _ll_pnt[0]) / _cell_size); + double const yPos ((pnt[1] - _ll_pnt[1]) / _cell_size); + // raster cell index + std::size_t const xIdx (static_cast<size_t>(std::floor(xPos))); + std::size_t const yIdx (static_cast<size_t>(std::floor(yPos))); + + // 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; + std::array<double,4> weight = {{ (1-xShift)*(1-yShift), xShift*(1-yShift), xShift*yShift, (1-xShift)*yShift }}; + + // neightbors to include in interpolation + int const xShiftIdx = (xPos-xIdx-half_delta>=0) ? 1 : -1; + int const yShiftIdx = (yPos-yIdx-half_delta>=0) ? 1 : -1; + std::array<int,4> const x_nb = {{ 0, xShiftIdx, xShiftIdx, 0 }}; + std::array<int,4> const y_nb = {{ 0, 0, yShiftIdx, yShiftIdx }}; + + // get pixel values + std::array<double,4> pix_val; + unsigned no_data_count (0); + for (unsigned j=0; j<4; ++j) + { + // check if neighbour pixel is still on the raster, otherwise substitute a no data value + if ( (xIdx + x_nb[j]) < 0 || + (yIdx + y_nb[j]) < 0 || + (xIdx + x_nb[j]) > _ll_pnt[0]+(_n_cols*_cell_size) || + (yIdx + y_nb[j]) > _ll_pnt[1]+(_n_rows*_cell_size) ) + pix_val[j] = _no_data_val; + else + pix_val[j] = _raster_data[(yIdx + y_nb[j])*_n_cols + (xIdx + x_nb[j])]; + + // remove no data values + if (std::fabs(pix_val[j] - _no_data_val) < std::numeric_limits<double>::epsilon()) + { + weight[j] = 0; + no_data_count++; + } + } + + // adjust weights if necessary + 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; + + 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;}); + } + + // new value + return MathLib::scalarProduct<double,4>(weight.data(), pix_val.data()); + } 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]<_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))) return false; - return true; + return true; } } // end namespace GeoLib -- GitLab