All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SpatialReferenceSystemManager.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/SpatialReferenceSystemManager.cpp
22 
23  \brief A singleton to manage Coordinate Systems representations.
24 */
25 
26 // TerraLib
27 #include "../common/PlatformUtils.h"
28 #include "../common/Translator.h"
29 #include "../common/UnitsOfMeasureManager.h"
30 #include "Exception.h"
32 #include "WKTReader.h"
33 
34 // STL
35 #include <algorithm>
36 #include <cassert>
37 
38 // Boost
39 #include <boost/foreach.hpp>
40 #include <boost/property_tree/ptree.hpp>
41 #include <boost/property_tree/json_parser.hpp>
42 
44 {
45  std::ifstream f;
46 
47  f.open(fileName.c_str());
48 
49  if (!f.is_open())
50  return;
51 
52  boost::property_tree::ptree pt;
53  boost::property_tree::json_parser::read_json(f,pt);
54  BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt.get_child("SRSs"))
55  {
56  if (v.second.get<unsigned int>("srid") > 100000)
57  mger->add(v.second.get<std::string>("name"), v.second.get<std::string>("pj4txt"),
58  v.second.get<std::string>("wkt"), v.second.get<unsigned int>("srid"), "USER");
59  else
60  mger->add(v.second.get<std::string>("name"), v.second.get<std::string>("pj4txt"),
61  v.second.get<std::string>("wkt"), v.second.get<unsigned int>("srid"));
62  }
63  f.close();
64 
65  return;
66 }
67 
68 te::srs::SpatialReferenceSystemManager::srs_desc::srs_desc(const std::string& name, unsigned int auth_id, const std::string& auth_name, const std::string& p4txt, const std::string& wkt):
69  m_name(name),
70  m_auth_id(auth_id),
71  m_auth_name(auth_name),
72  m_p4txt(p4txt),
73  m_wkt(wkt)
74 {}
75 
76 std::string
78 {
79  std::string ssrid = m_auth_name;
80  ssrid += ":";
81  ssrid += boost::lexical_cast<std::string>(m_auth_id);
82  return ssrid;
83 }
84 
86 {
87 }
88 
90 {
91  clear();
92 }
93 
95 {
96  if(!m_set.empty())
97  throw Exception(TE_TR("The spatial reference system manager is already initialized!"));
98 
99 #ifdef NDEBUG
100  std::string jsonf = te::common::FindInTerraLibPath("share/terralib/json/srs.json");
101 #else
102  std::string jsonf = te::common::FindInTerraLibPath("share/terralib/json/srs_incomplete.json");
103 #endif
104  if(jsonf.empty())
105  throw Exception(TE_TR("Could not find srs.json!"));
106 
107  init(jsonf);
108 }
109 
110 void te::srs::SpatialReferenceSystemManager::init(const std::string& fileName)
111 {
112  try
113  {
114  clear();
115  LoadSpatialReferenceSystemManager(fileName, this);
116  }
117  catch(boost::property_tree::json_parser::json_parser_error &je)
118  {
119  std::string errmsg = "Error parsing: " + je.filename() + ": " + je.message();
120  te::srs::Exception ex(TE_TR(errmsg));
121  throw(ex);
122  }
123  catch (std::exception const& e)
124  {
125  std::cerr << e.what() << std::endl;
126  }
127  return;
128 }
129 
130 void te::srs::SpatialReferenceSystemManager::add(const std::string& name, const std::string& p4Txt, const std::string& wkt, unsigned int id, const std::string& authName)
131 {
132  std::string key = authName;
133  key += ":";
134  key += boost::lexical_cast<std::string>(id);
135 
136  boost::multi_index::nth_index<srs_set,0>::type::iterator it = boost::multi_index::get<0>(m_set).find(key);
137  if (it != boost::multi_index::get<0>(m_set).end())
138  throw te::srs::Exception(TE_TR("The CS identification already exists in the manager."));
139 
140  srs_desc record(name, id, authName, p4Txt, wkt);
141  m_set.insert(record);
142 }
143 
144 bool te::srs::SpatialReferenceSystemManager::recognizes(unsigned int id, const std::string& authName) const
145 {
146  std::string key = authName;
147  key += ":";
148  key += boost::lexical_cast<std::string>(id);
149 
150  boost::multi_index::nth_index<srs_set,0>::type::iterator it = boost::multi_index::get<0>(m_set).find(key);
151  if (it == boost::multi_index::get<0>(m_set).end())
152  {
153  key = "USER";
154  key += ":";
155  key += boost::lexical_cast<std::string>(id);
156  it = boost::multi_index::get<0>(m_set).find(key);
157  return (it != boost::multi_index::get<0>(m_set).end());
158  }
159  else
160  return true;
161 }
162 
163 std::auto_ptr<te::srs::SpatialReferenceSystem> te::srs::SpatialReferenceSystemManager::getSpatialReferenceSystem(unsigned int id, const std::string& authName) const
164 {
165  std::string wkt = getWkt(id,authName);
166  if (wkt.empty())
167  return std::auto_ptr<te::srs::SpatialReferenceSystem>();
168 
169  try
170  {
171  return std::auto_ptr<te::srs::SpatialReferenceSystem>(te::srs::WKTReader::read(wkt.c_str()));
172  }
173  catch(...)
174  {
175  throw te::srs::Exception(TE_TR("Error parsing the registered CS WKT."));
176  }
177  return std::auto_ptr<te::srs::SpatialReferenceSystem>();
178 }
179 
180 
181 std::string te::srs::SpatialReferenceSystemManager::getName(unsigned int id, const std::string& authName) const
182 {
183  std::string key = authName;
184  key += ":";
185  key += boost::lexical_cast<std::string>(id);
186 
187  boost::multi_index::nth_index<srs_set,0>::type::iterator it = boost::multi_index::get<0>(m_set).find(key);
188  if (it == boost::multi_index::get<0>(m_set).end())
189  {
190  key = "USER";
191  key += ":";
192  key += boost::lexical_cast<std::string>(id);
193  it = boost::multi_index::get<0>(m_set).find(key);
194  if (it!=boost::multi_index::get<0>(m_set).end())
195  return it->m_name;
196  }
197  else
198  return it->m_name;
199 
200  return "";
201 }
202 
203 std::string te::srs::SpatialReferenceSystemManager::getWkt(unsigned int id, const std::string& authName) const
204 {
205  std::string key = authName;
206  key += ":";
207  key += boost::lexical_cast<std::string>(id);
208 
209  boost::multi_index::nth_index<srs_set,0>::type::iterator it = boost::multi_index::get<0>(m_set).find(key);
210  if (it==boost::multi_index::get<0>(m_set).end())
211  {
212  key = "USER";
213  key += ":";
214  key += boost::lexical_cast<std::string>(id);
215  it = boost::multi_index::get<0>(m_set).find(key);
216  if (it!=boost::multi_index::get<0>(m_set).end())
217  return it->m_wkt;
218  }
219  else
220  return it->m_wkt;
221 
222  return "";
223 }
224 
225 std::string te::srs::SpatialReferenceSystemManager::getP4Txt(unsigned int id, const std::string& authName) const
226 {
227  std::string key = authName;
228  key += ":";
229  key += boost::lexical_cast<std::string>(id);
230 
231  boost::multi_index::nth_index<srs_set,0>::type::iterator it = boost::multi_index::get<0>(m_set).find(key);
232  if (it==boost::multi_index::get<0>(m_set).end())
233  {
234  key = "USER";
235  key += ":";
236  key += boost::lexical_cast<std::string>(id);
237  it = boost::multi_index::get<0>(m_set).find(key);
238  if (it!=boost::multi_index::get<0>(m_set).end())
239  return it->m_p4txt;
240  }
241  else
242  return it->m_p4txt;
243 
244  return "";
245 }
246 
247 std::pair<std::string,unsigned int> te::srs::SpatialReferenceSystemManager::getIdFromName(const std::string& name) const
248 {
249  boost::multi_index::nth_index<srs_set,1>::type::iterator it = boost::multi_index::get<1>(m_set).find(name);
250  if (it==boost::multi_index::get<1>(m_set).end())
251  throw te::srs::Exception(TE_TR("CS name not recognized."));
252 
253  return std::pair<std::string,unsigned int>(it->m_auth_name, it->m_auth_id);
254 }
255 
256 
257 std::pair<std::string,unsigned int> te::srs::SpatialReferenceSystemManager::getIdFromP4Txt(const std::string& p4Txt) const
258 {
259  boost::multi_index::nth_index<srs_set,2>::type::iterator it = boost::multi_index::get<2>(m_set).find(p4Txt);
260  if (it==boost::multi_index::get<2>(m_set).end())
261  throw te::srs::Exception(TE_TR("CS name not recognized."));
262 
263  return std::pair<std::string,unsigned int>(it->m_auth_name, it->m_auth_id);
264 }
265 
266 std::pair<std::string,unsigned int> te::srs::SpatialReferenceSystemManager::getIdFromWkt(const std::string& wkt) const
267 {
268  boost::multi_index::nth_index<srs_set,3>::type::iterator it = boost::multi_index::get<3>(m_set).find(wkt);
269  if (it==boost::multi_index::get<3>(m_set).end())
270  throw te::srs::Exception(TE_TR("CS name not recognized."));
271 
272  return std::pair<std::string,unsigned int>(it->m_auth_name, it->m_auth_id);
273 }
274 
275 void te::srs::SpatialReferenceSystemManager::remove(unsigned int id, const std::string& authName)
276 {
277  std::string key = authName;
278  key += ":";
279  key += boost::lexical_cast<std::string>(id);
280 
281  boost::multi_index::nth_index<srs_set,0>::type::iterator it = boost::multi_index::get<0>(m_set).find(key);
282  if (it==boost::multi_index::get<0>(m_set).end())
283  {
284  key = "USER";
285  key += ":";
286  key += boost::lexical_cast<std::string>(id);
287  it = boost::multi_index::get<0>(m_set).find(key);
288  if (it!=boost::multi_index::get<0>(m_set).end())
289  m_set.erase(it);
290  }
291  else
292  m_set.erase(it);
293 }
294 
296 {
297  m_set.clear();
298 }
299 
300 std::pair<te::srs::SpatialReferenceSystemManager::iterator,te::srs::SpatialReferenceSystemManager::iterator>
302 {
304  te::srs::SpatialReferenceSystemManager::iterator>(boost::multi_index::get<0>(m_set).begin(), boost::multi_index::get<0>(m_set).end());
305 }
306 
308 {
309  return m_set.size();
310 }
311 
313 {
314  std::string unitName= "metre";
315  if (isGeographic(id,authName))
316  unitName = "degree";
317 
318  std::string pjstr = getP4Txt(id,authName);
319  if (pjstr.empty())
321 
322  std::size_t found = pjstr.find("+units=");
323  if (found!=std::string::npos)
324  {
325  std::size_t aux = pjstr.find(" ", found);
326  std::string unitsymbol = pjstr.substr(found+7,aux-(found+7));
328  }
329 
331 }
332 
333 
334 bool te::srs::SpatialReferenceSystemManager::isGeographic(unsigned int id, const std::string& authName)
335 {
336  std::string pjstr = getP4Txt(id,authName);
337  return (pjstr.find("+proj=longlat")!=std::string::npos);
338 }
std::pair< std::string, unsigned int > getIdFromWkt(const std::string &wkt) const
Returns a coordinate system identification given a WKT description.
TECOMMONEXPORT std::string FindInTerraLibPath(const std::string &p)
Returns the path relative to a directory or file in the context of TerraLib.
A class to manage Coordinate Systems representations.
std::pair< te::srs::SpatialReferenceSystemManager::iterator, te::srs::SpatialReferenceSystemManager::iterator > getIterators() const
Returns an iterator mechanism over the coordinate system descriptions in the manager.
size_t size() const
Returns the number of objects in the manager.
UnitOfMeasurePtr findBySymbol(const std::string &symbol) const
Returns a unit of measure identified by its symbol.
void add(const std::string &name, const std::string &p4Txt, const std::string &wkt, unsigned int id, const std::string &authName="EPSG")
Adds a to the manager.
void clear()
Removes all coordinate system representations from the manager.
bool isGeographic(unsigned int id, const std::string &authName)
Checks if a SRS with a given id refers to a geographic spatial reference system.
boost::multi_index::nth_index< srs_set, 0 >::type::iterator iterator
An iterator by SRS
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.
static SpatialReferenceSystem * read(const char *wkt)
It returns a valid SRS from a given WKT.
Definition: WKTReader.cpp:31
static UnitsOfMeasureManager & getInstance()
It returns a reference to the singleton instance.
std::pair< std::string, unsigned int > getIdFromName(const std::string &name) const
Returns a coordinate system identification given a name.
te::common::UnitOfMeasurePtr getUnit(unsigned int id, const std::string &authName="EPSG")
Returns the unit of measure for a SRS with a given id.
srs_desc(const std::string &name, unsigned int auth_id, const std::string &auth_name, const std::string &p4txt, const std::string &wkt)
A class to manage Coordinate Systems representations within TerraLib environment. ...
void remove(unsigned int id, const std::string &authName="EPSG")
Removes a coordinate system representation from the manager, given its identification.
bool recognizes(unsigned int id, const std::string &authName="EPSG") const
Returns true is a pair is recognized by the manager.
void init()
Inializes the manager from a JSON file containing instances of SRSs.
std::string getName(unsigned int id, const std::string &authName="EPSG") const
Returns a coordinate system name given an identification.
boost::shared_ptr< UnitOfMeasure > UnitOfMeasurePtr
std::string getWkt(unsigned int id, const std::string &authName="EPSG") const
Returns a coordinate system WKT description given an id.
void LoadSpatialReferenceSystemManager(const std::string fileName, te::srs::SpatialReferenceSystemManager *mger)
UnitOfMeasurePtr find(unsigned int id) const
Returns a unit of measure identified by its identificaton.
SpatialReferenceSystemPtr getSpatialReferenceSystem(unsigned int id, const std::string &authName="EPSG") const
Returns a pointer to a coordinate system given an identification.
std::pair< std::string, unsigned int > getIdFromP4Txt(const std::string &p4Txt) const
Returns a coordinate system identification given a PROJ4 description.