All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Converter.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008-2011 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/srs/Converter.cpp
22 */
23 
24 // TerraLib
25 #include "../common/Translator.h"
26 #include "Config.h"
27 #include "Converter.h"
28 #include "Exception.h"
29 #include "Module.h"
31 
32 #ifdef TERRALIB_PROJ4_ENABLED
33 // proj4
34 #include <proj_api.h>
35 #endif
36 
37 // STL
38 #include <cassert>
39 #include <cstring>
40 
42  m_targetSRID(TE_UNKNOWN_SRS),
43  m_sourceSRID(TE_UNKNOWN_SRS),
44  m_sourcePj4Handler(0),
45  m_targetPj4Handler(0)
46 {
47 }
48 
49 te::srs::Converter::Converter(int sourceSRID, int targetSRID):
50  m_targetSRID(targetSRID),
51  m_sourceSRID(sourceSRID),
52  m_sourcePj4Handler(0),
53  m_targetPj4Handler(0)
54 {
55 #ifdef TERRALIB_PROJ4_ENABLED
56  std::string description = te::srs::SpatialReferenceSystemManager::getInstance().getP4Txt(sourceSRID);
57  if (description.empty())
58  throw te::srs::Exception(TE_TR("Source SRS ID not recognized."));
59 
60  m_sourcePj4Handler = pj_init_plus(description.c_str());
61  if (!m_sourcePj4Handler)
62  {
63  std::string exceptionTxt = TE_TR("Source SRS description is not valid: ");
64  char* pjError = pj_strerrno(*(pj_get_errno_ref()));
65  exceptionTxt += std::string(pjError);
66  throw te::srs::Exception(exceptionTxt);
67  }
68 
69  description = te::srs::SpatialReferenceSystemManager::getInstance().getP4Txt(targetSRID);
70  if ( description.empty())
71  throw te::srs::Exception(TE_TR("Target SRS ID not recognized."));
72 
73  m_targetPj4Handler = pj_init_plus(description.c_str());
74  if (!m_targetPj4Handler)
75  {
76  std::string exceptionTxt = TE_TR("Target SRS description is not valid: ");
77  char* pjError = pj_strerrno(*(pj_get_errno_ref()));
78  exceptionTxt += std::string(pjError);
79  throw te::srs::Exception(exceptionTxt);
80  }
81 #endif
82 }
83 
85 {
86  m_sourceSRID = TE_UNKNOWN_SRS;
87  m_targetSRID= TE_UNKNOWN_SRS;
88 
89 #ifdef TERRALIB_PROJ4_ENABLED
90  if (m_sourcePj4Handler)
91  pj_free(m_sourcePj4Handler);
92 
93  if (m_targetPj4Handler)
94  pj_free(m_targetPj4Handler);
95 #endif
96  m_sourcePj4Handler = 0;
97  m_targetPj4Handler = 0;
98 }
99 
100 void
102 {
103 #ifdef TERRALIB_PROJ4_ENABLED
104  if (m_sourcePj4Handler)
105  {
106  pj_free(m_sourcePj4Handler);
107  m_sourcePj4Handler = 0;
108  }
109 
110  std::string description = te::srs::SpatialReferenceSystemManager::getInstance().getP4Txt(sourceSRID);
111  if ( description.empty())
112  throw te::srs::Exception(TE_TR("Source SRS ID not recognized."));
113 
114  m_sourcePj4Handler = pj_init_plus(description.c_str());
115  if (!m_sourcePj4Handler)
116  {
117  std::string exceptionTxt = TE_TR("Source SRS description is not valid: ");
118  char* pjError = pj_strerrno(*(pj_get_errno_ref()));
119  exceptionTxt += std::string(pjError);
120  throw te::srs::Exception(exceptionTxt);
121  }
122 #endif
123  m_sourceSRID = sourceSRID;
124 }
125 
126 void te::srs::Converter::setSourcePJ4txt(const std::string& pj4txt)
127 {
128  assert(!pj4txt.empty());
129 
130 #ifdef TERRALIB_PROJ4_ENABLED
131  if (m_sourcePj4Handler)
132  {
133  pj_free(m_sourcePj4Handler);
134  m_sourcePj4Handler = 0;
135  }
136 
137  m_sourcePj4Handler = pj_init_plus(pj4txt.c_str());
138  if (!m_sourcePj4Handler)
139  {
140  std::string exceptionTxt = TE_TR("Source SRS PROJ4 description is not valid: ");
141  char* pjError = pj_strerrno(*(pj_get_errno_ref()));
142  exceptionTxt += std::string(pjError);
143  throw te::srs::Exception(exceptionTxt);
144  }
145 #endif
146  m_sourceSRID = TE_UNKNOWN_SRS;
147 }
148 
149 int
151 {
152  return m_sourceSRID;
153 }
154 
155 void
157 {
158 #ifdef TERRALIB_PROJ4_ENABLED
159  if (m_targetPj4Handler)
160  {
161  pj_free(m_targetPj4Handler);
162  m_targetPj4Handler = 0;
163  }
164 
165  std::string description = te::srs::SpatialReferenceSystemManager::getInstance().getP4Txt(targetSRID);
166  if ( description.empty())
167  throw te::srs::Exception(TE_TR("Target SRS ID not recognized."));
168 
169  m_targetPj4Handler = pj_init_plus(description.c_str());
170  if (!m_targetPj4Handler)
171  {
172  std::string exceptionTxt = TE_TR("Target SRS description is not valid: ");
173  char* pjError = pj_strerrno(*(pj_get_errno_ref()));
174  exceptionTxt += std::string(pjError);
175  throw te::srs::Exception(exceptionTxt);
176  }
177 #endif
178  m_targetSRID = targetSRID;
179 }
180 
181 void te::srs::Converter::setTargetPJ4txt(const std::string& pj4txt)
182 {
183  assert(!pj4txt.empty());
184 
185 #ifdef TERRALIB_PROJ4_ENABLED
186  if (m_targetPj4Handler)
187  {
188  pj_free(m_targetPj4Handler);
189  m_targetPj4Handler = 0;
190  }
191 
192  m_targetPj4Handler = pj_init_plus(pj4txt.c_str());
193  if (!m_targetPj4Handler)
194  {
195  std::string exceptionTxt = TE_TR("Target SRS PROJ4 description is not valid: ");
196  char* pjError = pj_strerrno(*(pj_get_errno_ref()));
197  exceptionTxt += std::string(pjError);
198  throw te::srs::Exception(exceptionTxt);
199  }
200 #endif
201  m_targetSRID = TE_UNKNOWN_SRS;
202 }
203 
204 int
206 {
207  return m_targetSRID;
208 }
209 
210 bool
211 te::srs::Converter::convert(double *xIn, double *yIn, double *xOut, double* yOut, long numCoord, int coordOffset) const
212 {
213 #ifdef TERRALIB_PROJ4_ENABLED
214  assert(m_sourcePj4Handler);
215  assert(m_targetPj4Handler);
216 
217  memcpy(xOut, xIn, numCoord*sizeof(double));
218  memcpy(yOut, yIn, numCoord*sizeof(double));
219 
220  if (pj_is_latlong(m_sourcePj4Handler))
221  for (long i=0; i<numCoord; xOut[i*coordOffset]*=DEG_TO_RAD, yOut[i*coordOffset]*=DEG_TO_RAD, ++i);
222 
223  int res = pj_transform(m_sourcePj4Handler, m_targetPj4Handler, numCoord, coordOffset, xOut, yOut, 0);
224 
225  if (res==0 && pj_is_latlong(m_targetPj4Handler))
226  for (long i=0; i<numCoord; xOut[i*coordOffset]*=RAD_TO_DEG,yOut[i*coordOffset]*=RAD_TO_DEG, ++i);
227 
228  return (res == 0);
229 #else
230  throw te::srs::Exception(TE_TR("PROJ4 library has to be enabled in order to support coordinate conversion."));
231 #endif
232 }
233 
234 bool
235 te::srs::Converter::convert(double *x, double* y, long numCoord, int coordOffset) const
236 {
237 #ifdef TERRALIB_PROJ4_ENABLED
238  assert(m_sourcePj4Handler);
239  assert(m_targetPj4Handler);
240 
241  if (pj_is_latlong(m_sourcePj4Handler))
242  for (long i=0; i<numCoord; x[i*coordOffset]*=DEG_TO_RAD, y[i*coordOffset]*=DEG_TO_RAD, ++i);
243 
244  int res = pj_transform(m_sourcePj4Handler, m_targetPj4Handler, numCoord, coordOffset, x, y, 0);
245 
246  if (res==0 && pj_is_latlong(m_targetPj4Handler))
247  for (long i=0; i<numCoord; x[i*coordOffset]*=RAD_TO_DEG,y[i*coordOffset]*=RAD_TO_DEG, ++i);
248 
249  return (res == 0);
250 #else
251  throw te::srs::Exception(TE_TR("PROJ4 library has to be enabled in order to support coordinate conversion."));
252 #endif
253 }
254 
255 bool
256 te::srs::Converter::convert(const double xIn, const double yIn, double &xOut, double &yOut) const
257 {
258 #ifdef TERRALIB_PROJ4_ENABLED
259  assert(m_sourcePj4Handler);
260  assert(m_targetPj4Handler);
261 
262  xOut = xIn;
263  yOut = yIn;
264 
265  if (pj_is_latlong(m_sourcePj4Handler))
266  {
267  xOut *= DEG_TO_RAD;
268  yOut *= DEG_TO_RAD;
269  }
270 
271  int res = pj_transform(m_sourcePj4Handler, m_targetPj4Handler, 1, 1, &xOut, &yOut, 0);
272 
273  if (pj_is_latlong(m_targetPj4Handler))
274  {
275  xOut *= RAD_TO_DEG;
276  yOut *= RAD_TO_DEG;
277  }
278  return (res == 0);
279 #else
280  throw te::srs::Exception(TE_TR("PROJ4 library has to be enabled in order to support coordinate conversion."));
281 #endif
282 }
283 
284 bool
285 te::srs::Converter::convert(double &x, double &y) const
286 {
287 #ifdef TERRALIB_PROJ4_ENABLED
288  assert(m_sourcePj4Handler);
289  assert(m_targetPj4Handler);
290 
291  if (pj_is_latlong(m_sourcePj4Handler))
292  {
293  x *= DEG_TO_RAD;
294  y *= DEG_TO_RAD;
295  }
296 
297  int res = pj_transform(m_sourcePj4Handler, m_targetPj4Handler, 1, 1, &x, &y, 0);
298 
299  if (pj_is_latlong(m_targetPj4Handler))
300  {
301  x *= RAD_TO_DEG;
302  y *= RAD_TO_DEG;
303  }
304  return (res == 0);
305 #else
306  throw te::srs::Exception(TE_TR("PROJ4 library has to be enabled in order to support coordinate conversion."));
307 #endif
308 }
309 
310 bool
311 te::srs::Converter::invert(double *xIn, double *yIn, double *xOut, double* yOut, long numCoord, int coordOffset) const
312 {
313 #ifdef TERRALIB_PROJ4_ENABLED
314  assert(m_sourcePj4Handler);
315  assert(m_targetPj4Handler);
316 
317  memcpy(xOut, xIn, numCoord*sizeof(double));
318  memcpy(yOut, yIn, numCoord*sizeof(double));
319 
320  if (pj_is_latlong(m_targetPj4Handler))
321  for (long i=0; i<numCoord; xOut[i*coordOffset]*=DEG_TO_RAD, yOut[i*coordOffset]*=DEG_TO_RAD, ++i);
322 
323  int res = pj_transform(m_targetPj4Handler, m_sourcePj4Handler, numCoord, coordOffset, xOut, yOut, 0);
324 
325  if (res==0 && pj_is_latlong(m_sourcePj4Handler))
326  for (long i=0; i<numCoord; xOut[i*coordOffset]*=RAD_TO_DEG, yOut[i*coordOffset]*=RAD_TO_DEG, ++i);
327 
328  return (res == 0);
329 #else
330  throw te::srs::Exception(TE_TR("PROJ4 library has to be enabled in order to support coordinate conversion."));
331 #endif
332 }
333 
334 bool
335 te::srs::Converter::invert(double *x, double* y, long numCoord, int coordOffset) const
336 {
337 #ifdef TERRALIB_PROJ4_ENABLED
338  assert(m_sourcePj4Handler);
339  assert(m_targetPj4Handler);
340 
341  if (pj_is_latlong(m_targetPj4Handler))
342  for (long i=0; i<numCoord; x[i*coordOffset]*=DEG_TO_RAD, y[i]*=DEG_TO_RAD, ++i);
343 
344  int res = pj_transform(m_targetPj4Handler, m_sourcePj4Handler, numCoord, coordOffset, x, y, 0);
345 
346  if (res==0 && pj_is_latlong(m_sourcePj4Handler))
347  for (long i=0; i<numCoord; x[i*coordOffset]*=RAD_TO_DEG, y[i]*=RAD_TO_DEG, ++i);
348 
349  return (res == 0);
350 #else
351  throw te::srs::Exception(TE_TR("PROJ4 library has to be enabled in order to support coordinate conversion."));
352 #endif
353 }
354 
355 bool
356 te::srs::Converter::invert(const double xIn, const double yIn, double &xOut, double &yOut) const
357 {
358 #ifdef TERRALIB_PROJ4_ENABLED
359  assert(m_sourcePj4Handler);
360  assert(m_targetPj4Handler);
361 
362  xOut = xIn;
363  yOut = yIn;
364 
365  if (pj_is_latlong(m_targetPj4Handler))
366  {
367  xOut *= DEG_TO_RAD;
368  yOut *= DEG_TO_RAD;
369  }
370 
371  int res = pj_transform(m_targetPj4Handler, m_sourcePj4Handler, 1, 1, &xOut, &yOut, 0);
372 
373  if (res==0 && pj_is_latlong(m_sourcePj4Handler))
374  {
375  xOut *= RAD_TO_DEG;
376  yOut *= RAD_TO_DEG;
377  }
378 
379  return (res == 0);
380 #else
381  throw te::srs::Exception(TE_TR("PROJ4 library has to be enabled in order to support coordinate conversion."));
382 #endif
383 }
384 
385 bool
386 te::srs::Converter::invert(double &x, double &y) const
387 {
388 #ifdef TERRALIB_PROJ4_ENABLED
389  assert(m_sourcePj4Handler);
390  assert(m_targetPj4Handler);
391 
392  if (pj_is_latlong(m_targetPj4Handler))
393  {
394  x *= DEG_TO_RAD;
395  y *= DEG_TO_RAD;
396  }
397 
398  int res = pj_transform(m_targetPj4Handler, m_sourcePj4Handler, 1, 1, &x, &y, 0);
399 
400  if (res==0 && pj_is_latlong(m_sourcePj4Handler))
401  {
402  x *= RAD_TO_DEG;
403  y *= RAD_TO_DEG;
404  }
405 
406  return (res == 0);
407 #else
408  throw te::srs::Exception(TE_TR("PROJ4 library has to be enabled in order to support coordinates conversion."));
409 #endif
410 }
411 
412 
413 bool
414 te::srs::Converter::convertToGeographic(double &x, double &y, int SRID) const
415 {
416 #ifdef TERRALIB_PROJ4_ENABLED
417 
418  std::string description = te::srs::SpatialReferenceSystemManager::getInstance().getP4Txt(SRID);
419  if (description.empty())
420  throw te::common::Exception(TE_TR("Source SRS ID not recognized."));
421 
422  projPJ pjhProj = pj_init_plus(description.c_str());
423  if (!pjhProj)
424  {
425  std::string exceptionTxt = TE_TR("srs Source SRS description is not valid: ");
426  char* pjError = pj_strerrno(*(pj_get_errno_ref()));
427  exceptionTxt += std::string(pjError);
428  throw te::common::Exception(exceptionTxt);
429  }
430 
431  if (pj_is_latlong(pjhProj))
432  {
433  pj_free(pjhProj);
434  return true;
435  }
436 
437  projPJ pjhGeog = pj_latlong_from_proj(pjhProj);
438  int res = pj_transform(pjhProj, pjhGeog, 1, 1, &x, &y, 0);
439  pj_free(pjhProj);
440  pj_free(pjhGeog);
441 
442  if (res == 0)
443  {
444  x *= RAD_TO_DEG;
445  y *= RAD_TO_DEG;
446  return true;
447  }
448  return false;
449 #else
450  throw te::srs::Exception(TE_TR("PROJ4 library has to be enabled in order to support coordinate conversion."));
451 #endif
452 }
453 
454 bool te::srs::Converter::convertToProjected(double &lon, double &lat, int SRID) const
455 {
456 #ifdef TERRALIB_PROJ4_ENABLED
457  std::string description = te::srs::SpatialReferenceSystemManager::getInstance().getP4Txt(SRID);
458  if (description.empty())
459  throw te::srs::Exception(TE_TR("Source SRS ID not recognized."));
460 
461  projPJ pjhProj = pj_init_plus(description.c_str());
462  if (!pjhProj)
463  {
464  std::string exceptionTxt = TE_TR("Source SRS description is not valid: ");
465  char* pjError = pj_strerrno(*(pj_get_errno_ref()));
466  exceptionTxt += std::string(pjError);
467  throw te::common::Exception(exceptionTxt);
468  }
469  projPJ pjhGeog = pj_latlong_from_proj(pjhProj);
470 
471  lon *= DEG_TO_RAD;
472  lat *= DEG_TO_RAD;
473  int res = pj_transform(pjhGeog, pjhProj, 1, 1, &lon, &lat, 0);
474 
475  pj_free(pjhProj);
476  pj_free(pjhGeog);
477  return (res == 0);
478 
479 #else
480  throw te::srs::Exception(TE_TR("PROJ4 library has to be enabled in order to support coordinate conversion."));
481 #endif
482 
483 }
bool convertToGeographic(double &x, double &y, int SRID) const
Converts a coordinate from a projected SRS to its underlying geographic SRS (same Datum)...
Definition: Converter.cpp:414
bool convert(double *xIn, double *yIn, double *xOut, double *yOut, long numCoord, int coordOffset=1) const
Converts a vector of coordinates from source SRS to target SRS.
Definition: Converter.cpp:211
bool convertToProjected(double &lon, double &lat, int SRID) const
Converts a coordinate from a geographic SRS to a projected SRS based on the same Datum.
Definition: Converter.cpp:454
void setTargetPJ4txt(const std::string &pj4txt)
Sets the target SRS PROJ4 description.
Definition: Converter.cpp:181
A class to manage Coordinate Systems representations.
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:311
std::string getP4Txt(unsigned int id, const std::string &authName="EPSG") const
Returns a coordinate system PROJ4 description given an identification.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:345
An exception class for the SRS module.
void setSourcePJ4txt(const std::string &pj4txt)
Sets the source SRS PROJ4 description.
Definition: Converter.cpp:126
void setSourceSRID(int sourceSRID)
Sets the source SRS identifier.
Definition: Converter.cpp:101
void * m_sourcePj4Handler
Definition: Converter.h:218
int getSourceSRID() const
Gets source SRS identifier.
Definition: Converter.cpp:150
int getTargetSRID() const
Gets target SRS identifier.
Definition: Converter.cpp:205
static SpatialReferenceSystemManager & getInstance()
It returns a reference to the singleton instance.
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
Definition: Config.h:44
void setTargetSRID(int targetSRID)
Sets the target SRS identifier.
Definition: Converter.cpp:156
Converter()
Default empty constructor.
Definition: Converter.cpp:41
~Converter()
Destructor.
Definition: Converter.cpp:84
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Definition: Exception.h:58
void * m_targetPj4Handler
Definition: Converter.h:219
This file contains the support to convert coordinates from a SRS to another.