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