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