All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Interpolator.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008-2013 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/raster/Interpolator.cpp
22 
23  \brief It interpolates one pixel based on a selected algorithm.
24 */
25 
26 // TerraLib
27 #include "Interpolator.h"
28 #include "Band.h"
29 #include "BandProperty.h"
30 #include "Utils.h"
31 
32 // STL
33 #include <cassert>
34 
35 #define BICUBIC_MODULE( x ) ( ( x < 0 ) ? ( -1 * x ) : x )
36 #define BICUBIC_K1( x , a ) ( ( ( a + 2 ) * x * x * x ) - \
37  ( ( a + 3 ) * x * x ) + 1 )
38 #define BICUBIC_K2( x , a ) ( ( a * x * x * x ) - ( 5 * a * x * x ) + \
39  ( 8 * a * x ) - ( 4 * a ) )
40 #define BICUBIC_RANGES(x,a) \
41  ( ( ( 0 <= x ) && ( x <= 1 ) ) ? \
42  BICUBIC_K1(x,a) \
43  : ( ( ( 1 < x ) && ( x <= 2 ) ) ? \
44  BICUBIC_K2(x,a) \
45  : 0 ) )
46 #define BICUBIC_KERNEL( x , a ) BICUBIC_RANGES( BICUBIC_MODULE(x) , a )
47 
49  : m_raster(r),
50  m_method(m)
51 {
52  switch(m_method)
53  {
54  case Bicubic:
56  break;
57  case Bilinear:
59  break;
60  case NearestNeighbor:
62  break;
63  }
64 
65  // raster no-data values (for each band)
66 
67  for( unsigned int bandIdx = 0 ; bandIdx < r->getNumberOfBands() ; ++bandIdx )
68  m_noDataValues.push_back( r->getBand( bandIdx )->getProperty()->m_noDataValue );
69 
70  // ancillary values for nearest Neighbor interpolation
71 
72  m_nnLastRow = ( (double) m_raster->getNumberOfRows() ) - 0.5;
73  m_nnLastCol = ( (double) m_raster->getNumberOfColumns() ) - 0.5;
74 
75  // ancillary values for bilinear interpolation
76  m_bilValues.resize(4, 0);
77 
78  m_bilLastRow = (double) m_raster->getNumberOfRows() - 1.0;
79 
80  m_bilLastCol = (double) m_raster->getNumberOfColumns() - 1.0;
81 
82  // ancillary values for bicubic interpolation
83  m_bicKernel = -1.0;
84 
86 
88 }
89 
91 {
92  m_function = 0;
93 }
94 
95 void te::rst::Interpolator::getValues(const double& c, const double& r, std::vector<std::complex<double> >& values)
96 {
97  values.clear();
98 
99  std::complex<double> v;
100 
101  for(std::size_t b = 0; b < m_raster->getNumberOfBands(); b++)
102  {
103  getValue(c, r, v, b);
104 
105  values.push_back(v);
106  }
107 }
108 
109 void te::rst::Interpolator::nearestNeighborGetValue(const double& c, const double& r, std::complex<double>& v, const std::size_t& b)
110 {
111  if( ( c > (-0.5) ) && ( r > (-0.5) ) && ( c < m_nnLastCol ) && ( r < m_nnLastRow ) )
112  {
113  m_nnCR = (unsigned int) te::rst::Round(c);
114  m_nnRR = (unsigned int) te::rst::Round(r);
115 
116  m_raster->getValue(m_nnCR, m_nnRR, v, b);
117  }
118  else
119  {
120  v = std::complex<double>( m_noDataValues[ b ], m_noDataValues[ b ] );
121  }
122 }
123 
124 void te::rst::Interpolator::bilinearGetValue(const double& c, const double& r, std::complex<double>& v, const std::size_t& b)
125 {
126  if( (r < 0.0) || (c < 0.0) || (r > m_bilLastRow) || (c > m_bilLastCol) )
127  {
128  nearestNeighborGetValue(c, r, v, b);
129  return;
130  }
131 
132  m_bilRowMin = std::floor(r);
133  m_bilRowMax = (m_bilRowMin == r)? m_bilRowMin: (m_bilRowMin + 1.0);
134 
135  m_bilColMin = std::floor(c);
136  m_bilColMax = (m_bilColMin == c)? m_bilColMin: (m_bilColMin + 1.0);
137 
138  m_bilRowDifMin = r - m_bilRowMin;
139  m_bilRowDifMax = m_bilRowMax - r;
140 
141  m_bilColDifMin = c - m_bilColMin;
142  m_bilColDifMax = m_bilColMax - c;
143 
144  m_bilDistances[0] = std::sqrt((m_bilRowDifMin * m_bilRowDifMin) + (m_bilColDifMin * m_bilColDifMin));
145  m_bilDistances[1] = std::sqrt((m_bilRowDifMin * m_bilRowDifMin) + (m_bilColDifMax * m_bilColDifMax));
146  m_bilDistances[2] = std::sqrt((m_bilRowDifMax * m_bilRowDifMax) + (m_bilColDifMin * m_bilColDifMin));
147  m_bilDistances[3] = std::sqrt((m_bilRowDifMax * m_bilRowDifMax) + (m_bilColDifMin * m_bilColDifMax));
148 
149  m_bilWeights[0] = (m_bilDistances[0] == 0)? 1.0: (1 / m_bilDistances[0]);
150  m_bilWeights[1] = (m_bilDistances[1] == 0)? 1.0: (1 / m_bilDistances[1]);
151  m_bilWeights[2] = (m_bilDistances[2] == 0)? 1.0: (1 / m_bilDistances[2]);
152  m_bilWeights[3] = (m_bilDistances[3] == 0)? 1.0: (1 / m_bilDistances[3]);
153 
154  m_raster->getValue((unsigned) m_bilColMin, (unsigned) m_bilRowMin, m_bilValues[0], b);
155  m_raster->getValue((unsigned) m_bilColMax, (unsigned) m_bilRowMin, m_bilValues[1], b);
156  m_raster->getValue((unsigned) m_bilColMin, (unsigned) m_bilRowMax, m_bilValues[2], b);
157  m_raster->getValue((unsigned) m_bilColMax, (unsigned) m_bilRowMax, m_bilValues[3], b);
158 
159  double vr = ( (m_bilValues[0].real() * m_bilWeights[0]) +
160  (m_bilValues[1].real() * m_bilWeights[1]) +
161  (m_bilValues[2].real() * m_bilWeights[2]) +
162  (m_bilValues[3].real() * m_bilWeights[3]) ) /
163  (m_bilWeights[0] + m_bilWeights[1] + m_bilWeights[2] + m_bilWeights[3]);
164  double vi = ( (m_bilValues[0].imag() * m_bilWeights[0]) +
165  (m_bilValues[1].imag() * m_bilWeights[1]) +
166  (m_bilValues[2].imag() * m_bilWeights[2]) +
167  (m_bilValues[3].imag() * m_bilWeights[3]) ) /
168  (m_bilWeights[0] + m_bilWeights[1] + m_bilWeights[2] + m_bilWeights[3]);
169  v = std::complex<double>(vr,vi);
170 
171  // if the output value is equal to dummy, call nearest neighbor method
172  if( (v.real() == m_raster->getBand(b)->getProperty()->m_noDataValue) ||
173  (v.imag() == m_raster->getBand(b)->getProperty()->m_noDataValue) )
174  nearestNeighborGetValue(c, r, v, b);
175 }
176 
177 void te::rst::Interpolator::bicubicGetValue(const double& c, const double& r, std::complex<double>& v, const std::size_t& b)
178 {
179  if( (r <= 1.0) || (c <= 1.0) || (r >= m_bicRowBound) || (c >= m_bicColBound) )
180  {
181  nearestNeighborGetValue(c, r, v, b);
182  return;
183  }
184 
185  m_bicGridRow = ((unsigned) std::floor(r)) - 1;
186  m_bicGridCol = ((unsigned) std::floor(c)) - 1;
187 
188  // fill buffer
189  for(m_bicBufRow = 0; m_bicBufRow < 4; ++m_bicBufRow)
190  {
191  for(m_bicBufCol = 0; m_bicBufCol < 4 ; ++m_bicBufCol)
192  {
193  m_raster->getValue(m_bicGridCol + m_bicBufCol, m_bicGridRow + m_bicBufRow,
194  m_bicBbufferReal[m_bicBufRow][m_bicBufCol], b);
195  m_raster->getIValue(m_bicGridCol + m_bicBufCol, m_bicGridRow + m_bicBufRow,
196  m_bicBbufferImag[m_bicBufRow][m_bicBufCol], b);
197  }
198  }
199 
200  // calcule weights for the required position.
201  m_bicOffsetX = c - (double)(m_bicGridCol + 1);
202  m_bicOffsetY = r - (double)(m_bicGridRow + 1);
203 
204  m_bicHWeights[0] = BICUBIC_KERNEL(1.0 + m_bicOffsetX, m_bicKernel);
205  m_bicHWeights[1] = BICUBIC_KERNEL(m_bicOffsetX, m_bicKernel);
206  m_bicHWeights[2] = BICUBIC_KERNEL(1.0 - m_bicOffsetX, m_bicKernel);
207  m_bicHWeights[3] = BICUBIC_KERNEL(2.0 - m_bicOffsetX, m_bicKernel);
208 
209  m_bicVWeights[0] = BICUBIC_KERNEL(1.0 + m_bicOffsetY, m_bicKernel);
210  m_bicVWeights[1] = BICUBIC_KERNEL(m_bicOffsetY, m_bicKernel);
211  m_bicVWeights[2] = BICUBIC_KERNEL(1.0 - m_bicOffsetY, m_bicKernel);
212  m_bicVWeights[3] = BICUBIC_KERNEL(2.0 - m_bicOffsetY, m_bicKernel);
213 
214  m_bicHSum = m_bicHWeights[0] + m_bicHWeights[1] + m_bicHWeights[2] + m_bicHWeights[3];
215  m_bicVSum = m_bicVWeights[0] + m_bicVWeights[1] + m_bicVWeights[2] + m_bicVWeights[3];
216 
217  // interpolating the value
218  for(m_bicBufRow = 0 ; m_bicBufRow < 4 ; ++m_bicBufRow)
219  {
220  m_bicRowAccumReal = 0.0;
221  m_bicRowAccumImag = 0.0;
222  for(m_bicBufCol = 0; m_bicBufCol < 4; ++m_bicBufCol)
223  {
224  m_bicRowAccumReal += m_bicBbufferReal[m_bicBufRow][m_bicBufCol] *
225  m_bicHWeights[m_bicBufCol];
226  m_bicRowAccumImag += m_bicBbufferImag[m_bicBufRow][m_bicBufCol] *
227  m_bicHWeights[m_bicBufCol];
228  }
229 
230  m_bicRowsValuesReal[m_bicBufRow] = m_bicRowAccumReal / m_bicHSum;
231  m_bicRowsValuesImag[m_bicBufRow] = m_bicRowAccumImag / m_bicHSum;
232  }
233  double vr = ( m_bicRowsValuesReal[0] * m_bicVWeights[0] +
234  m_bicRowsValuesReal[1] * m_bicVWeights[1] +
235  m_bicRowsValuesReal[2] * m_bicVWeights[2] +
236  m_bicRowsValuesReal[3] * m_bicVWeights[3] ) / m_bicVSum;
237 
238  double vi = ( m_bicRowsValuesImag[0] * m_bicVWeights[0] +
239  m_bicRowsValuesImag[1] * m_bicVWeights[1] +
240  m_bicRowsValuesImag[2] * m_bicVWeights[2] +
241  m_bicRowsValuesImag[3] * m_bicVWeights[3] ) / m_bicVSum;
242  v = std::complex<double>(vr,vi);
243 
244  // if the output value is equal to dummy, call nearest neighbor method
245  if( (v.real() == m_raster->getBand(b)->getProperty()->m_noDataValue) ||
246  (v.imag() == m_raster->getBand(b)->getProperty()->m_noDataValue) )
247  nearestNeighborGetValue(c, r, v, b);
248 }
It gives access to values in one band (dimension) of a raster.
Interpolator(Raster const *r, int m)
Constructor.
TERASTEREXPORT int Round(double val)
Round a double value to a integer value.
Definition: Utils.cpp:295
unsigned int getNumberOfRows() const
Returns the raster number of rows.
Definition: Raster.cpp:208
It describes one band (or dimension) of a raster.
#define BICUBIC_KERNEL(x, a)
virtual std::size_t getNumberOfBands() const =0
Returns the number of bands (dimension of cells attribute values) in the raster.
void bilinearGetValue(const double &c, const double &r, std::complex< double > &v, const std::size_t &b)
Bilinear interpolation method.
int m_method
The interpolation method.
Definition: Interpolator.h:144
virtual ~Interpolator()
Destructor.
double m_bilLastRow
Last row available for bilinear interpolation.
Definition: Interpolator.h:168
Bilinear interpolation method.
Definition: Interpolator.h:61
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
Definition: Raster.cpp:213
Bicubic interpolation method.
Definition: Interpolator.h:62
double m_bicColBound
Last column available for bicubic interpolation.
Definition: Interpolator.h:190
double m_bilLastCol
Last column available for bilinear interpolation.
Definition: Interpolator.h:169
double m_noDataValue
Value to indicate elements where there is no data, default is std::numeric_limits&lt;double&gt;::max().
Definition: BandProperty.h:136
std::vector< std::complex< double > > m_bilValues
Bilinear values;.
Definition: Interpolator.h:167
InterpolationFunction m_function
The current interpolation function pointer.
Definition: Interpolator.h:145
double m_nnLastRow
Last row available for nearest Neighbor interpolation.
Definition: Interpolator.h:152
void getValues(const double &c, const double &r, std::vector< std::complex< double > > &values)
Get the interpolated value for all bands.
It interpolates one pixel based on a selected algorithm.
An abstract class for raster data strucutures.
Definition: Raster.h:70
BandProperty * getProperty()
Returns the band property.
Definition: Band.cpp:370
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
void nearestNeighborGetValue(const double &c, const double &r, std::complex< double > &v, const std::size_t &b)
Nearest neighbor interpolation method.
void bicubicGetValue(const double &c, const double &r, std::complex< double > &v, const std::size_t &b)
Bicubic interpolation method.
double m_nnLastCol
Last column available for nearest Neighbor interpolation.
Definition: Interpolator.h:153
std::vector< double > m_noDataValues
Raster no-data values (for each band);.
Definition: Interpolator.h:146
double m_bicRowBound
Last row available for bicubic interpolation.
Definition: Interpolator.h:189
Near neighborhood interpolation method.
Definition: Interpolator.h:60
Utility functions for the raster module.
Raster const * m_raster
My input raster.
Definition: Interpolator.h:143