All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Grid.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/Grid.cpp
22 
23  \brief A rectified grid is the spatial support for raster data.
24 */
25 
26 // TerraLib
27 #include "../geometry/Coord2D.h"
28 #include "../geometry/Envelope.h"
29 #include "Grid.h"
30 #include "Exception.h"
31 
32 // STL
33 #include <algorithm>
34 #include <cmath>
35 #include <cstring>
36 
37 te::rst::Grid::Grid(unsigned int nCols,
38  unsigned int nRows,
39  te::gm::Envelope* mbr,
40  int srid)
41  : m_extent(mbr),
42  m_nCols(nCols),
43  m_nRows(nRows),
44  m_srid(srid)
45 {
46  if(m_extent)
47  {
49  nCols, nRows, m_extent->m_llx, m_extent->m_ury, m_geoT, m_geoTInverse ) )
50  {
51  throw te::rst::Exception("Unable to compute affine parameters");
52  }
53  }
54  else
55  {
56  setGeoreference(te::gm::Coord2D(0, 0), srid, 1.0, 1.0);
57  computeExtent();
58  }
59 }
60 
61 te::rst::Grid::Grid(unsigned int nCols, unsigned int nRows,
62  double resX, double resY,
63  const te::gm::Coord2D* ulc, int srid)
64  : m_extent(0),
65  m_nCols(nCols),
66  m_nRows(nRows),
67  m_srid(srid)
68 {
69  if(ulc)
70  setGeoreference(*ulc, srid, resX, resY);
71  else
72  setGeoreference(te::gm::Coord2D(0, 0), srid, resX, resY);
73  computeExtent();
74 }
75 
76 te::rst::Grid::Grid(unsigned int nCols, unsigned int nRows,
77  double resX, double resY,
78  te::gm::Envelope* mbr, int srid)
79  : m_extent(mbr),
80  m_nCols(nCols),
81  m_nRows(nRows),
82  m_srid(srid)
83 {
84  if(m_extent)
85  {
87  nCols, nRows, m_extent->m_llx, m_extent->m_ury, m_geoT, m_geoTInverse ) )
88  {
89  throw te::rst::Exception("Unable to compute affine parameters");
90  }
91  }
92  else
93  {
94  setGeoreference(te::gm::Coord2D(0, 0), srid, resX, resY);
95  computeExtent();
96  }
97 }
98 
99 te::rst::Grid::Grid(double resX,
100  double resY,
101  te::gm::Envelope* mbr,
102  int srid)
103  : m_extent(mbr),
104  m_nCols(0),
105  m_nRows(0),
106  m_srid(srid)
107 {
108  if( m_extent == 0 )
109  {
110  throw te::rst::Exception("Missing extent");
111  }
112 
113  m_nCols = static_cast<unsigned int> (mbr->getWidth() / resX + 0.5);
114  m_nRows = static_cast<unsigned int> (mbr->getHeight() / resY + 0.5);
115 
118  {
119  throw te::rst::Exception("Unable to compute affine parameters");
120  }
121 }
122 
123 te::rst::Grid::Grid( const double geoTrans[], unsigned int nCols, unsigned int nRows,
124  int srid)
125  : m_extent(0),
126  m_nCols(nCols),
127  m_nRows(nRows),
128  m_srid(srid)
129 {
130  setGeoreference(geoTrans, srid);
131  computeExtent();
132 }
133 
135  : m_extent(0),
136  m_nCols(rhs.m_nCols),
137  m_nRows(rhs.m_nRows),
138  m_srid(rhs.m_srid)
139 {
140  operator=( rhs );
141 }
142 
144 {
145  if (m_extent)
146  {
147  delete m_extent;
148  }
149 }
150 
152 {
153  if(this != &rhs)
154  {
155  m_nCols = rhs.m_nCols;
156 
157  m_nRows = rhs.m_nRows;
158 
159  m_srid = rhs.m_srid;
160 
161  memcpy(m_geoT, rhs.m_geoT, sizeof(double) * 6);
162  memcpy(m_geoTInverse, rhs.m_geoTInverse, sizeof(double) * 6);
163 
164  if (m_extent)
165  {
166  delete m_extent;
167  m_extent = 0;
168  }
169  if( rhs.m_extent )
170  {
171  m_extent = new te::gm::Envelope(*rhs.m_extent);
172  }
173  else
174  {
175  computeExtent();
176  }
177  }
178 
179  return *this;
180 }
181 
182 void te::rst::Grid::setNumberOfColumns(unsigned int nCols)
183 {
184  m_nCols = nCols;
185 
186  if( ! computeAffineParameters( m_extent->getWidth(), m_extent->getHeight(),
187  m_nCols, m_nRows, m_extent->m_llx, m_extent->m_ury, m_geoT, m_geoTInverse ) )
188  {
189  throw te::rst::Exception("Unable to compute affine parameters");
190  }
191 }
192 
194 {
195  return m_nCols;
196 }
197 
198 void te::rst::Grid::setNumberOfRows(unsigned int nRows)
199 {
200  m_nRows = nRows;
201 
202  if( ! computeAffineParameters( m_extent->getWidth(), m_extent->getHeight(),
203  m_nCols, m_nRows, m_extent->m_llx, m_extent->m_ury, m_geoT, m_geoTInverse ) )
204  {
205  throw te::rst::Exception("Unable to compute affine parameters");
206  }
207 }
208 
209 unsigned int te::rst::Grid::getNumberOfRows() const
210 {
211  return m_nRows;
212 }
213 
214 void te::rst::Grid::setGeoreference(const te::gm::Coord2D& ulLocation, int srid, double resX, double resY)
215 {
216  m_srid = srid;
217 
218  const double extentWidth = ((double)m_nCols) * resX;
219  const double extentheight = ((double)m_nRows) * resY;
220 
221  if( ! computeAffineParameters( extentWidth, extentheight,
222  m_nCols, m_nRows, ulLocation.x, ulLocation.y, m_geoT, m_geoTInverse ) )
223  {
224  throw te::rst::Exception("Unable to compute affine parameters");
225  }
226 
227  computeExtent();
228 }
229 
230 void te::rst::Grid::setGeoreference(const double geoTrans[], int srid)
231 {
232  m_srid = srid;
233  m_geoT[0] = geoTrans[0];
234  m_geoT[1] = geoTrans[1];
235  m_geoT[2] = geoTrans[2];
236  m_geoT[3] = geoTrans[3];
237  m_geoT[4] = geoTrans[4];
238  m_geoT[5] = geoTrans[5];
239 
240  if( ! computeInverseParameters( m_geoT, m_geoTInverse ) )
241  {
242  throw te::rst::Exception("Unable to compute the inverse affine parameters");
243  }
244 
245  computeExtent();
246 }
247 
248 const double* te::rst::Grid::getGeoreference() const
249 {
250  return m_geoT;
251 }
252 
254 {
255  assert( m_extent );
256  return m_extent->getWidth() / ((double)m_nCols );
257 }
258 
260 {
261  assert( m_extent );
262  return m_extent->getHeight() / ((double)m_nRows );
263 }
264 
266 {
267  return m_srid;
268 }
269 
271 {
272  m_srid = srid;
273 }
274 
276 {
277  return m_extent;
278 }
279 
281 {
282  return m_extent;
283 }
284 
286 {
287  te::gm::Coord2D ll = gridToGeo( -0.5, ((double)m_nRows) - 0.5 );
288  te::gm::Coord2D lr = gridToGeo( ((double)m_nCols) - 0.5, ((double)m_nRows) - 0.5 );
289  te::gm::Coord2D ur = gridToGeo( ((double)m_nCols) - 0.5, -0.5 );
290  te::gm::Coord2D ul = gridToGeo( -0.5, -0.5 );
291 
292  if(m_extent)
293  {
294  delete m_extent;
295  }
296 
297  m_extent = new te::gm::Envelope( std::min(ll.x, ul.x), std::min(ll.y, lr.y),
298  std::max(ur.x, lr.x), std::max(ul.y, ur.y) );
299 }
300 
301 void te::rst::Grid::gridToGeo(const double& col, const double& row, double& x, double& y) const
302 {
303  x = col * m_geoT[0] + row * m_geoT[1] + m_geoT[2];
304  y = col * m_geoT[3] + row * m_geoT[4] + m_geoT[5];
305 }
306 
307 void te::rst::Grid::geoToGrid(const double& x, const double& y, double& col, double& row) const
308 {
309  col = x * m_geoTInverse[0] + y * m_geoTInverse[1] + m_geoTInverse[2];
310  row = x * m_geoTInverse[3] + y * m_geoTInverse[4] + m_geoTInverse[5];
311 }
312 
313 bool te::rst::Grid::operator==(const Grid& rhs) const
314 {
315  computeExtent();
316  rhs.computeExtent();
317 
318  if (!m_extent->equals(*rhs.m_extent) ||
319  m_nCols != rhs.m_nCols ||
320  m_nRows != rhs.m_nRows ||
321  m_srid != rhs.m_srid ||
322  getGeoreference()[0] != rhs.getGeoreference()[0] ||
323  getGeoreference()[1] != rhs.getGeoreference()[1] ||
324  getGeoreference()[2] != rhs.getGeoreference()[2] ||
325  getGeoreference()[3] != rhs.getGeoreference()[3] ||
326  getGeoreference()[4] != rhs.getGeoreference()[4] ||
327  getGeoreference()[5] != rhs.getGeoreference()[5])
328  return false;
329  else
330  return true;
331 }
332 
333 bool te::rst::Grid::computeAffineParameters( const double extentWidth,
334  const double extentHeight, const unsigned int nColumns,
335  const unsigned int nRows, const double extentULX,
336  const double extentULY, double* affineParamsPtr,
337  double* inverseAffineParamsPtr ) const
338 {
339  affineParamsPtr[0] = extentWidth / ((double)nColumns);
340  affineParamsPtr[1] = 0.0;
341  affineParamsPtr[2] = extentULX + ( extentWidth / static_cast<double>(nColumns) / 2.0 );
342  affineParamsPtr[3] = 0.0;
343  affineParamsPtr[4] = -1.0 * extentHeight / ((double)nRows);
344  affineParamsPtr[5] = extentULY - ( extentHeight / static_cast<double>(nRows) / 2.0 );
345 
346  return computeInverseParameters( affineParamsPtr, inverseAffineParamsPtr );
347 }
348 
349 bool te::rst::Grid::computeInverseParameters( double* const affineParamsPtr,
350  double* inverseAffineParamsPtr ) const
351 {
352  const double determinant = ( affineParamsPtr[0] * affineParamsPtr[4] ) -
353  ( affineParamsPtr[1] * affineParamsPtr[3] );
354  if( determinant == 0.0 )
355  {
356  return false;
357  }
358 
359  inverseAffineParamsPtr[0] = affineParamsPtr[4] / determinant;
360  inverseAffineParamsPtr[1] = ( -1.0 * affineParamsPtr[1] ) / determinant;
361  inverseAffineParamsPtr[2] =
362  (
363  ( affineParamsPtr[1] * affineParamsPtr[5] )
364  -
365  ( affineParamsPtr[2] * affineParamsPtr[4] )
366  )
367  /
368  determinant;
369  inverseAffineParamsPtr[3] = ( -1.0 * affineParamsPtr[3] ) / determinant;
370  inverseAffineParamsPtr[4] = ( affineParamsPtr[0] ) / determinant;
371  inverseAffineParamsPtr[5] =
372  (
373  ( -1.0 * ( affineParamsPtr[0] * affineParamsPtr[5] ) )
374  +
375  ( affineParamsPtr[3] * affineParamsPtr[2] )
376  )
377  /
378  determinant;
379 
380  return true;
381 }
unsigned int getNumberOfRows() const
Returns the grid number of rows.
Definition: Grid.cpp:209
te::gm::Envelope * m_extent
The grid extent.
Definition: Grid.h:292
bool computeInverseParameters(double *const affineParamsPtr, double *inverseAffineParamsPtr) const
Compute inverse affine parameters.
Definition: Grid.cpp:349
double y
y-coordinate.
Definition: Coord2D.h:114
double x
x-coordinate.
Definition: Coord2D.h:113
int getSRID() const
Returns the grid spatial reference system identifier.
Definition: Grid.cpp:265
Grid & operator=(const Grid &rhs)
Assignment operator.
Definition: Grid.cpp:151
Grid(unsigned int nCols=0, unsigned int nRows=0, te::gm::Envelope *mbr=0, int srid=TE_UNKNOWN_SRS)
Constructor.
Definition: Grid.cpp:37
double getWidth() const
It returns the envelope width.
Definition: Envelope.h:443
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
void setGeoreference(const te::gm::Coord2D &ulLocation, int srid, double resX, double resY)
Sets the information needed to georeference the grid.
Definition: Grid.cpp:214
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
double getResolutionY() const
Returns the grid vertical (y-axis) resolution.
Definition: Grid.cpp:259
An exception class for the Raster module.
double m_llx
Lower left corner x-coordinate.
Definition: Envelope.h:344
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
int m_srid
The associated SRS.
Definition: Grid.h:295
unsigned int m_nCols
Number of columns.
Definition: Grid.h:293
const double * getGeoreference() const
Returns a list of 6 coefficients describing an affine transformation to georeference a grid...
Definition: Grid.cpp:248
bool operator==(const Grid &rhs) const
Equal operator.
Definition: Grid.cpp:313
double m_geoT[6]
A list of 6 coefficients describing an affine transformation to georeference a grid.
Definition: Grid.h:296
unsigned int getNumberOfColumns() const
Returns the grid number of columns.
Definition: Grid.cpp:193
double getResolutionX() const
Returns the grid horizontal (x-axis) resolution.
Definition: Grid.cpp:253
void setNumberOfRows(unsigned int nRows)
Sets the grid number of rows.
Definition: Grid.cpp:198
bool computeAffineParameters(const double extentWidth, const double extentHeight, const unsigned int nColumns, const unsigned int nRows, const double extentULX, const double extentULY, double *affineParamsPtr, double *inverseAffineParamsPtr) const
Compute affine parameters from the given input parameters.
Definition: Grid.cpp:333
void setNumberOfColumns(unsigned int nCols)
Sets the grid number of columns.
Definition: Grid.cpp:182
~Grid()
Destructor.
Definition: Grid.cpp:143
double m_ury
Upper right corner y-coordinate.
Definition: Envelope.h:347
te::gm::Envelope * getExtent()
Returns the geographic extension of the grid.
Definition: Grid.cpp:275
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.
void setSRID(int srid)
Just sets the grid spatial reference system identifier.
Definition: Grid.cpp:270
A rectified grid is the spatial support for raster data.
Definition: Grid.h:68
double getHeight() const
It returns the envelope height.
Definition: Envelope.h:448
void computeExtent() const
Computes the geographic extension of the grid.
Definition: Grid.cpp:285
double m_geoTInverse[6]
A list of 6 coefficients describing an inverse affine transformation to georeference a grid...
Definition: Grid.h:297
unsigned int m_nRows
Number of rows.
Definition: Grid.h:294