All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Reprojection.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 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/Reprojection.cpp
22 
23  \brief It contains the algorithm to reproject raster data.
24 */
25 
26 // TerraLib
27 #include "../common/STLUtils.h"
28 #include "../geometry/Coord2D.h"
29 #include "../geometry/Envelope.h"
30 #include "../srs/Converter.h"
31 #include "Band.h"
32 #include "BandProperty.h"
33 #include "Exception.h"
34 #include "Grid.h"
35 #include "Interpolator.h"
36 #include "Raster.h"
37 #include "RasterFactory.h"
38 #include "Reprojection.h"
39 
40 // STL
41 #include <algorithm> // for max and min
42 #include <cstdlib> // for abs
43 
45 
47 
48 te::rst::Raster* te::rst::Reproject(te::rst::Raster const * const rin, int srid, const std::map<std::string, std::string>& routinfo, int m)
49 {
50  return te::rst::Reproject(rin, srid, 1, 1, -1, -1, 0, 0, routinfo, m);
51 }
52 
53 te::rst::Raster* te::rst::Reproject(te::rst::Raster const * const rin, int srid, double llx, double lly, double urx, double ury, const std::map<std::string, std::string>& routinfo, int m)
54 {
55  return te::rst::Reproject(rin, srid, llx, lly, urx, ury, 0, 0, routinfo, m);
56 }
57 
58 te::rst::Raster* te::rst::Reproject(te::rst::Raster const * const rin, int srid, double llx, double lly, double urx, double ury, double resx, double resy, const std::map<std::string, std::string>& routinfo, int m)
59 {
60  if (srid == rin->getSRID())
61  return 0;
62 
63  te::srs::Converter* converter = new te::srs::Converter();
64  try
65  {
66  converter->setSourceSRID(rin->getSRID());
67  converter->setTargetSRID(srid);
68  }
69  catch(...)
70  {
71  throw te::rst::Exception("Input/Output SRID not recognized.");
72  }
73 
74  unsigned int ncols = rin->getNumberOfColumns();
75  unsigned int nrows = rin->getNumberOfRows();
76 
77  te::gm::Envelope* roi = new te::gm::Envelope(llx, lly, urx, ury);
78  if (!roi->isValid())
79  {
80  delete roi;
81  roi = 0;
82  }
83  else
84  {
85  ncols = static_cast<unsigned int>((urx-llx)/rin->getResolutionX())+1;
86  nrows = static_cast<unsigned int>((ury-lly)/rin->getResolutionY())+1;
87  }
88 
89  te::gm::Envelope* env = rin->getExtent(srid, roi);
90  delete roi;
91 
92  if (resx == 0 || resy == 0)
93  {
94 // maintain the same number of pixels
95  resx = env->getWidth() / ncols;
96  resy = env->getHeight() / nrows;
97  }
98  else
99  {
100  ncols = static_cast<unsigned int>(env->getWidth() / resx) + 1;
101  nrows = static_cast<unsigned int>(env->getHeight() / resy) + 1;
102  }
103 
104  te::rst::Grid* g = new te::rst::Grid(ncols, nrows, resx, resy, env, srid);
105 
106 // copy the band definitions
107  std::vector<te::rst::BandProperty*> bands;
108  for (unsigned int b=0; b<rin->getNumberOfBands(); ++b)
109  {
111  bands.push_back(bb);
112  }
113 
114 // create output raster
115  te::rst::Raster* rout = te::rst::RasterFactory::make(g, bands, routinfo);
116 
117  bool res = InterpolateIn(rin, rout, env, converter, m);
118 
119  if (!res)
120  {
121  delete rout;
122  return 0;
123  }
124 
125  return rout;
126 }
127 
128 bool InterpolateIn(te::rst::Raster const * const rin, te::rst::Raster* rout, te::gm::Envelope* box, te::srs::Converter* conv, int m)
129 {
130  te::gm::Coord2D poll = box->getLowerLeft();
131  te::gm::Coord2D pour = box->getUpperRight();
132 
133 // Bring output coordinates to output line/column domain
134  te::gm::Coord2D pxoll = rout->getGrid()->geoToGrid(poll.x, poll.y);
135  te::gm::Coord2D pxour = rout->getGrid()->geoToGrid(pour.x, pour.y);
136 
137 // Round output coordinates to nearest exact pixel
138  int x1 = (int) (pxoll.x-0.5);
139  int y1 = (int) (pxoll.y+0.5);
140  pxoll = te::gm::Coord2D(x1, y1);
141 
142  int x2 = (int)(pxour.x+0.5);
143  int y2 = (int)(pxour.y-0.5);
144  pxour = te::gm::Coord2D(x2, y2);
145 
146  poll = rout->getGrid()->gridToGeo((int)pxoll.x, (int)pxoll.y);
147 
148  te::gm::Coord2D poul = te::gm::Coord2D(poll.x, pour.y);
149  te::gm::Coord2D polr = te::gm::Coord2D(pour.x, poll.y);
150 
151 // Bring coordinates of box four corners to input raster projection
152 
153  te::gm::Coord2D pill(poll);
154  te::gm::Coord2D piur(pour);
155  te::gm::Coord2D piul(poul);
156  te::gm::Coord2D pilr(polr);
157 
158  conv->invert(pill.x,pill.y);
159  conv->invert(piur.x,piur.y);
160  conv->invert(piul.x,piul.y);
161  conv->invert(pilr.x,pilr.y);
162 
163 // Check if linear interpolation may be performed on input raster
164 // Evaluate point at middle of the edges in output domain and check if their
165 // corresponding points belong to the edges in input domain. If they belong,
166 // a linear interpolation may be performed, else divide output image
167 // in four quadrants and try interpolating again.
168 
169  te::gm::Coord2D pou((pour.x-poul.x)/2.+poul.x, poul.y), // upper edge
170  pob((polr.x-poll.x)/2.+poll.x, poll.y), // bottom edge
171  pol(poll.x, (poul.y-poll.y)/2.+poll.y), // left edge
172  por(polr.x, (pour.y-polr.y)/2.+polr.y); // right edge
173 
174 // Evaluate corresponding points in input raster domain
175  te::gm::Coord2D piu(pou); conv->invert(piu.x, piu.y);
176  te::gm::Coord2D pib(pob); conv->invert(pib.x, pib.y);
177  te::gm::Coord2D pil(pol); conv->invert(pil.x, pil.y);
178  te::gm::Coord2D pir(por); conv->invert(pir.x, pir.y);
179 
180 // Check if middle points belong to the edges
181 // If one of them does not belong to corresponding edge, divide output in four quadrants
182  double tol = std::max(rin->getResolutionX(), rin->getResolutionY());
183 
184  if (!IsPointOnLine(piul, piur, piu, tol) ||
185  !IsPointOnLine(pilr, piur, pir, tol) ||
186  !IsPointOnLine(pill, pilr, pib, tol) ||
187  !IsPointOnLine(pill, piul, pil, tol))
188  {
189 // center point
190  te::gm::Coord2D pom((por.x-pol.x)/2.+pol.x, (pou.y-pob.y)/2.+pob.y);
191 
192  te::gm::Envelope quadrantul(pol.x, pol.y, pou.x, pou.y);
193  if(!InterpolateIn(rin,rout,&quadrantul,conv))
194  return false;
195 
196  te::gm::Envelope quadrantur(pom.x, pom.y, pour.x, pour.y);
197  if(!InterpolateIn(rin, rout, &quadrantur, conv))
198  return false;
199 
200  te::gm::Envelope quadrantll(poll.x, poll.y, pom.x, pom.y);
201  if(!InterpolateIn(rin, rout, &quadrantll, conv))
202  return false;
203 
204  te::gm::Envelope quadrantlr(pob.x, pob.y, por.x, por.y);
205  if(!InterpolateIn(rin, rout, &quadrantlr, conv))
206  return false;
207 
208  return true;
209  }
210 
211 // Start linear interpolation on input image.
212  te::gm::Coord2D pxill = rin->getGrid()->geoToGrid(pill.x, pill.y);
213  te::gm::Coord2D pxiul = rin->getGrid()->geoToGrid(piul.x, piul.y);
214  te::gm::Coord2D pxilr = rin->getGrid()->geoToGrid(pilr.x, pilr.y);
215  te::gm::Coord2D pxiur = rin->getGrid()->geoToGrid(piur.x, piur.y);
216 
217 // Evaluate the increments in x and y on both sides of input image
218  x1 = (int)pxoll.x-1;
219  y1 = (int)pxour.y-1;
220 
221  x2 = (int)pxour.x+1;
222  y2 = (int)pxoll.y+1;
223 
224  double dxl((pxill.x-pxiul.x)/(y2-y1)); // x increment at the beginning of line
225  double dyl((pxill.y-pxiul.y)/(y2-y1)); // y increment at the beginning of line
226  double dxr((pxilr.x-pxiur.x)/(y2-y1)); // x increment at the end of line
227  double dyr((pxilr.y-pxiur.y)/(y2-y1)); // Y increment at the end of line
228 
229  // Set initial values for x and y at beginning point on input image
230  double xl = pxiul.x-1; // x at the beginning of the line
231  double yl = pxiul.y-1; // y at the beginning of the line
232 
233  // Set initial values for x and y at end point on input image
234  double xr = pxiur.x+1; // x at the end of the line
235  double yr = pxiur.y+1; // y at the end of the line
236 
237  // Evaluate increments for the first line
238  double dx = (xr-xl)/(x2-x1); // inner loop x increment
239  double dy = (yr-yl)/(x2-x1); // inner loop y increment
240 
241  double x = xl; // round to left pixel
242  double y = yl; // round to left pixel
243 
244  // Create the interpolator
245  te::rst::Interpolator* interpolator = new te::rst::Interpolator(rin, m);
246 
247  int i, j;
248  std::complex<double> value;
249  for (j = y1; j <= y2; ++j)
250  {
251  for (i = x1; i <= x2; ++i)
252  {
253  if (rin->getGrid()->isPointInGrid((unsigned int)(x+0.5), (unsigned int)(y+0.5)) &&
254  rout->getGrid()->isPointInGrid(i, j))
255  {
256  for (std::size_t b = 0; b < rin->getNumberOfBands(); ++b)
257  {
258  //rin->getValue((int)(x+0.5), (int)(y+0.5), value, b);
259  interpolator->getValue(x, y, value, b);
260  rout->setValue(i, j, value, b);
261  }
262  }
263  x += dx;
264  y += dy;
265  }
266  xl += dxl;
267  yl += dyl;
268 
269  xr += dxr;
270  yr += dyr;
271 
272  x = xl;
273  y = yl;
274 
275  dx = (xr-xl)/(x2-x1);
276  dy = (yr-yl)/(x2-x1);
277  }
278  return true;
279 }
280 
281 
283 {
284  int px = (int)(p.x/tol);
285  int py = (int)(p.y/tol);
286 
287  int qx = (int)(q.x/tol);
288  int qy = (int)(q.y/tol);
289 
290  int tx = (int)(t.x/tol);
291  int ty = (int)(t.y/tol);
292 
293  int dx = abs(px-qx);
294  int dy = abs(py-qy);
295 
296  if (dx <= 2 && dy <= 2)
297  return true;
298 
299  int q1 = (qy-py)*(tx-px);
300  int q2 = (ty-py)*(qx-px);
301  int q3 = qx-px;
302  int q4 = qy-py;
303 
304  if (q1 == 0 && q2 == 0 && q3 == 0 && q4 == 0)
305  return true;
306 
307  if (abs(q1 - q2) > (std::max(abs(q3), abs(q4))))
308  return false;
309 
310  return true;
311 }
bool isPointInGrid(unsigned int col, unsigned int row) const
Definition: Grid.h:349
virtual void setValue(unsigned int c, unsigned int r, const double value, std::size_t b=0)
Sets the attribute value in a band of a cell.
Definition: Raster.cpp:233
te::gm::Envelope * getExtent()
Returns the geographic extension of the raster data.
Definition: Raster.cpp:104
bool IsPointOnLine(te::gm::Coord2D &p, te::gm::Coord2D &q, te::gm::Coord2D &t, double tol)
Near neighborhood interpolation method.
Definition: Enums.h:95
double y
y-coordinate.
Definition: Coord2D.h:114
It describes one band (or dimension) of a raster.
It contains the algorithm to reproject raster data.
A raster band description.
Definition: BandProperty.h:61
double x
x-coordinate.
Definition: Coord2D.h:113
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
Definition: Raster.cpp:213
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
It interpolates one pixel based on a selected algorithm. Methods currently available are Nearest Neig...
Definition: Interpolator.h:55
bool invert(double *xIn, double *yIn, double *xOut, double *yOut, long numCoord, int coordOffset=1) const
Inverts a vector of coordinates from target SRS to dource SRS.
Definition: Converter.cpp:342
double getWidth() const
It returns the envelope width.
Definition: Envelope.h:443
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
void getValue(const double &c, const double &r, std::complex< double > &v, const std::size_t &b)
Get the interpolated value at specific band.
Definition: Interpolator.h:92
void geoToGrid(const double &x, const double &y, double &col, double &row) const
Get the grid point associated to a spatial location.
Definition: Grid.cpp:307
void setSourceSRID(int sourceSRID)
Sets the source SRS identifier.
Definition: Converter.cpp:105
An exception class for the Raster module.
An abstract class for raster data strucutures.
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
An abstract class for raster data strucutures.
Definition: Raster.h:71
unsigned int getNumberOfRows() const
Returns the raster number of rows.
Definition: Raster.cpp:208
BandProperty * getProperty()
Returns the band property.
Definition: Band.cpp:428
virtual std::size_t getNumberOfBands() const =0
Returns the number of bands (dimension of cells attribute values) in the raster.
double getResolutionX() const
Returns the raster horizontal (x-axis) resolution.
Definition: Raster.cpp:218
bool InterpolateIn(te::rst::Raster const *const rin, te::rst::Raster *rout, te::gm::Envelope *box, te::srs::Converter *conv, int m=te::rst::NearestNeighbor)
void setTargetSRID(int targetSRID)
Sets the target SRS identifier.
Definition: Converter.cpp:173
It gives access to values in one band (dimension) of a raster.
Grid * getGrid()
It returns the raster grid.
Definition: Raster.cpp:94
A Converter is responsible for the conversion of coordinates between different Coordinate Systems (CS...
Definition: Converter.h:53
int getSRID() const
Returns the raster spatial reference system identifier.
Definition: Raster.cpp:203
TERASTEREXPORT te::rst::Raster * Reproject(te::rst::Raster const *const rin, int srid, const std::map< std::string, std::string > &routinfo, int m=te::rst::NearestNeighbor)
Reprojects a raster to another SRS.
static Raster * make()
It creates and returns an empty raster with default raster driver.
void gridToGeo(const double &col, const double &row, double &x, double &y) const
Get the spatial location of a grid point.
Definition: Grid.cpp:301
A rectified grid is the spatial support for raster data.
double getResolutionY() const
Returns the raster vertical (y-axis) resolution.
Definition: Raster.cpp:223
Coord2D getUpperRight() const
It returns the upper right coordinate of the envelope.
Definition: Envelope.cpp:46
This is the abstract factory for Rasters.
A rectified grid is the spatial support for raster data.
Definition: Grid.h:68
Coord2D getLowerLeft() const
It returns the lower left coordinate of the envelope.
Definition: Envelope.cpp:41
double getHeight() const
It returns the envelope height.
Definition: Envelope.h:448
bool isValid() const
It tells if the rectangle is valid or not.
Definition: Envelope.h:438
It interpolates one pixel based on a selected algorithm.