All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Utils.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/ogr/Utils.cpp
22 
23  \brief Utility functions for OGR support.
24 */
25 
26 // TerraLib
27 #include "../common/Exception.h"
28 #include "../common/Globals.h"
29 #include "../common/Translator.h"
30 #include "../dataaccess/dataset/DataSetType.h"
31 #include "../dataaccess/utils/Utils.h"
32 #include "../datatype/ArrayProperty.h"
33 #include "../datatype/DateTime.h"
34 #include "../datatype/DateTimeProperty.h"
35 #include "../datatype/NumericProperty.h"
36 #include "../datatype/Property.h"
37 #include "../datatype/SimpleProperty.h"
38 #include "../datatype/StringProperty.h"
39 #include "../geometry/Envelope.h"
40 #include "../geometry/Geometry.h"
41 #include "../geometry/GeometryProperty.h"
42 #include "../geometry/WKBReader.h"
43 #include "../srs/SpatialReferenceSystemManager.h"
44 #include "../srs/Config.h"
45 #include "Utils.h"
46 
47 // OGR
48 #include <ogrsf_frmts.h>
49 #include <ogr_spatialref.h>
50 
51 // Boost
52 #include <boost/algorithm/string.hpp>
53 #include <boost/filesystem.hpp>
54 
56 {
57  int wkbSize = ogrGeom->WkbSize();
58 
59  unsigned char* wkbArray = new unsigned char[wkbSize];
60 
61  ogrGeom->exportToWkb(wkbNDR, wkbArray);
62 
63  te::gm::Geometry* teGeom = 0;
64 
65  try
66  {
67  teGeom = te::gm::WKBReader::read((const char*)wkbArray);
68  }
69  catch(...)
70  {
71  delete [] wkbArray;
72  throw;
73  }
74 
75  delete [] wkbArray;
76 
77  return teGeom;
78 }
79 
80 OGRGeometry* te::ogr::Convert2OGR(const te::gm::Geometry* teGeom)
81 {
82  size_t size = teGeom->getWkbSize();
83 
84  char* wkbArray = new char[size];
85 
87 
88  OGRSpatialReference* srs = Convert2OGRProjection(teGeom->getSRID());
89 
90  OGRGeometry* ogrGeom = 0;
91 
92  OGRErr result = OGRGeometryFactory::createFromWkb((unsigned char*)wkbArray, srs, &ogrGeom, static_cast<int>(size));
93 
94  delete [] wkbArray;
95 
96  if(result == OGRERR_NONE)
97  return ogrGeom;
98 
99  if(result == OGRERR_NOT_ENOUGH_DATA)
100  throw te::common::Exception(TE_TR("Error when attempting convert the geometry to OGR. Not enough data."));
101 
102  if(result == OGRERR_UNSUPPORTED_GEOMETRY_TYPE)
103  throw te::common::Exception(TE_TR("Error when attempting convert the geometry to OGR. Unsupported geometry type."));
104 
105  if(result == OGRERR_CORRUPT_DATA)
106  throw te::common::Exception(TE_TR("Error when attempting convert the geometry to OGR. Corrupt data."));
107 
108  return 0;
109 }
110 
112 {
113  return new te::gm::Envelope(env->MinX, env->MinY, env->MaxX, env->MaxY);
114 }
115 
116 OGREnvelope* te::ogr::Convert2OGR(const te::gm::Envelope* env)
117 {
118  OGREnvelope* envOGR = new OGREnvelope();
119  envOGR->MinX = env->m_llx;
120  envOGR->MinY = env->m_lly;
121  envOGR->MaxX = env->m_urx;
122  envOGR->MaxY = env->m_ury;
123  return envOGR;
124 }
125 
126 int te::ogr::Convert2TerraLibProjection(OGRSpatialReference* osrs)
127 {
128  if(osrs == 0)
129  return TE_UNKNOWN_SRS;
130 
131  int srid = 0;
132 
133  OGRErr ogrReturn = osrs->AutoIdentifyEPSG();
134  if( ogrReturn == OGRERR_NONE )
135  {
136  const char* srsAuth = osrs->GetAuthorityCode(0);
137 
138  if (srsAuth)
139  {
140  srid = atoi(srsAuth);
141  }
142  }
143 
144  if( srid == TE_UNKNOWN_SRS )
145  {
146  char* wktPtr = 0;
147  ogrReturn = osrs->exportToWkt( &wktPtr );
148 
149  if( ogrReturn == OGRERR_NONE )
150  {
151  std::pair< std::string, unsigned int > customSRID;
152  std::string projRefStr( wktPtr );
153 
154  OGRFree( wktPtr );
155 
156  try
157  {
158  customSRID = te::srs::SpatialReferenceSystemManager::getInstance().getIdFromWkt(
159  projRefStr );
160  srid = (int)customSRID.second;
161  }
162  catch( te::common::Exception& )
163  {
164  }
165  }
166  }
167 
168  if( srid == TE_UNKNOWN_SRS )
169  {
170  char* proj4StrPtr = 0;
171  ogrReturn = osrs->exportToProj4( &proj4StrPtr );
172 
173  if( ogrReturn == OGRERR_NONE )
174  {
175  std::pair< std::string, unsigned int > customSRID;
176  std::string projRefStr( proj4StrPtr );
177 
178  OGRFree( proj4StrPtr );
179 
180  try
181  {
182  customSRID = te::srs::SpatialReferenceSystemManager::getInstance().getIdFromP4Txt(
183  projRefStr );
184  srid = (int)customSRID.second;
185  }
186  catch( te::common::Exception& )
187  {
188  }
189  }
190  }
191 
192  if( srid == TE_UNKNOWN_SRS )
193  {
194  // geographic SIRGAS 2000 Datum
195  std::string straux(osrs->GetRoot()->GetChild(0)->GetValue());
196 
197  if (boost::find_first(straux, "SIRGAS"))
198  {
199  if (osrs->IsGeographic())
200  srid = TE_SRS_SIRGAS2000;
201  }
202  else if (boost::find_first(straux, "UTM "))
203  { // UTM using SIRGAS 2000 Datum
204  double centralm = osrs->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,-1);
205  if (centralm != -1)
206  {
207  int zone = (int)(centralm/6 + 31);
208 
209  double fsnorth = osrs->GetProjParm(SRS_PP_FALSE_NORTHING,-1);
210  if (fsnorth > 0)
211  srid = 31960+zone;
212  else if (fsnorth == 0)
213  srid = 31954+zone;
214  }
215  }
216  }
217 
218  return srid;
219 }
220 
221 OGRSpatialReference* te::ogr::Convert2OGRProjection(int srid)
222 {
223  std::auto_ptr< OGRSpatialReference > osrs( new OGRSpatialReference() );
224 
225  OGRErr error = osrs->importFromEPSG(srid);
226 
227  if( error != OGRERR_NONE )
228  {
229  try
230  {
231  std::string wktStr =
233 
234  if( !wktStr.empty() )
235  {
236  char* wktStrPtr = (char*)wktStr.c_str();
237  error = osrs->importFromWkt( &wktStrPtr );
238  }
239  }
240  catch( te::common::Exception& )
241  {
242  error = OGRERR_UNSUPPORTED_SRS;
243  }
244  }
245 
246  if( error != OGRERR_NONE )
247  {
248  try
249  {
250  std::string proj4Str =
252 
253  if( !proj4Str.empty() )
254  {
255  char* proj4StrPtr = (char*)proj4Str.c_str();
256  error = osrs->importFromProj4( proj4StrPtr );
257  }
258  }
259  catch( te::common::Exception& )
260  {
261  error = OGRERR_UNSUPPORTED_SRS;
262  }
263  }
264 
265  if(error != OGRERR_NONE)
266  throw(te::common::Exception(TE_TR("Error converting spatial reference system.")));
267 
268  return osrs.release();
269 }
270 
271 void te::ogr::Convert2TerraLib(OGRFeatureDefn* featDef, te::da::DataSetType* dt, int srs)
272 {
273  assert(dt);
274 
275  int nFields = featDef->GetFieldCount();
276 
277  for(int i = 0; i < nFields; i++)
278  {
279  OGRFieldDefn* fieldDef = featDef->GetFieldDefn(i);
280  te::dt::Property* p = Convert2TerraLib(fieldDef);
281  dt->add(p);
282  }
283 
284  OGRwkbGeometryType ogrGeomType = featDef->GetGeomType();
285 
286  if(ogrGeomType != wkbNone) // has geometry?
287  {
288  te::gm::GeomType geomType = Convert2TerraLib(ogrGeomType);
289  te::gm::GeometryProperty* geomPropertyType = new te::gm::GeometryProperty("OGR_GEOMETRY", srs, geomType);
290  dt->add(geomPropertyType);
291  }
292 }
293 
294 te::da::DataSetType* te::ogr::Convert2TerraLib(OGRFeatureDefn* featDef, int srs)
295 {
296  te::da::DataSetType* dt = new te::da::DataSetType(featDef->GetName());
297 
298  dt->setTitle(featDef->GetName());
299 
300  te::ogr::Convert2TerraLib(featDef,dt, srs);
301 
302  return dt;
303 }
304 
306 {
307  OGRFeatureDefn* featDef = new OGRFeatureDefn(dt->getName().c_str());
308  std::vector<te::dt::Property*> props = dt->getProperties();
309 
310  for(unsigned int i = 0; i < props.size(); i++)
311  {
312  te::dt::Property* p = props[i];
313  if(p->getType() != te::dt::GEOMETRY_TYPE)
314  featDef->AddFieldDefn(Convert2OGR(p));
315  }
316 
317  if(dt->hasGeom())
318  {
320  featDef->SetGeomType(Convert2OGR(geom->getGeometryType()));
321  }
322 
323  return featDef;
324 }
325 
327 {
328  te::dt::Property* p = 0;
329  std::string name = fieldDef->GetNameRef();
330  switch(fieldDef->GetType())
331  {
332  case OFTInteger:
334  break;
335 
336  case OFTIntegerList:
338  break;
339 
340  case OFTString:
341  {
342  te::dt::StringProperty* sp = 0;
343 
344  if(fieldDef->GetWidth() == 0)
345  sp = new te::dt::StringProperty(name, te::dt::STRING);
346  else
347  sp = new te::dt::StringProperty(name, te::dt::VAR_STRING, fieldDef->GetWidth());
348 
349  //sp->setCharEncoding(te::common::UTF8); // GDAL/OGR handles strings internally in UTF-8 - *** Need review! ***
350 
351  /* The original DBF standard defines to use ISO8859-1, and only ISO8859-1.
352  So, when you get a Shapefile that is really standards conform, it should be ISO8859-1.
353  Of course, this (very old) restriction is a not really usable nowadays.
354  ISO8859-1 - also called "Latin 1"
355  From: http://gis.stackexchange.com/questions/3529/which-character-encoding-is-used-by-the-dbf-file-in-shapefiles */
356  // for while...
358 
359  p = sp;
360  }
361  break;
362 
363  case OFTStringList:
365  break;
366 
367  case OFTReal:
369  break;
370 
371  case OFTRealList:
373  break;
374 
375  case OFTBinary:
377  break;
378 
379  case OFTDate:
380  p = new te::dt::DateTimeProperty(name, te::dt::DATE);
381  break;
382 
383  case OFTTime:
385  break;
386 
387  case OFTDateTime:
389  break;
390 
391  default:
392  throw(te::common::Exception(TE_TR("Unexpected data type.")));
393  }
394 
395  return p;
396 }
397 
399 {
400  OGRFieldDefn* fieldDef = new OGRFieldDefn(p->getName().c_str(), OFTInteger);
401  switch(p->getType())
402  {
403  case te::dt::INT32_TYPE:
404  return fieldDef;
405  break;
406 
407  case te::dt::ARRAY_TYPE:
408  {
409  te::dt::ArrayProperty* at = static_cast<te::dt::ArrayProperty*>(p);
410  int elementType = at->getElementType()->getType();
411 
412  if(elementType == te::dt::INT32_TYPE)
413  fieldDef->SetType(OFTIntegerList);
414  else if(elementType == te::dt::STRING_TYPE)
415  fieldDef->SetType(OFTStringList);
416  else if(elementType == te::dt::DOUBLE_TYPE)
417  fieldDef->SetType(OFTRealList);
418  else
419  throw(te::common::Exception(TE_TR("Unsupported data type by OGR.")));
420  break;
421  }
422 
423  case te::dt::STRING_TYPE:
424  fieldDef->SetType(OFTString);
425  fieldDef->SetWidth(static_cast<int>(static_cast<te::dt::StringProperty*>(p)->size()));
426  break;
427 
428  case te::dt::DOUBLE_TYPE:
429  fieldDef->SetType(OFTReal);
430  break;
431 
433  fieldDef->SetType(OFTReal);
434  fieldDef->SetPrecision(static_cast<te::dt::NumericProperty*>(p)->getScale());
435  break;
436 
438  fieldDef->SetType(OFTBinary);
439  break;
440 
442  {
443  const te::dt::DateTimeProperty* dp = static_cast<const te::dt::DateTimeProperty*>(p);
444  te::dt::DateTimeType elementType = dp->getSubType();
445  if(elementType == te::dt::DATE)
446  fieldDef->SetType(OFTDate);
447  else if(elementType == te::dt::TIME_DURATION)
448  fieldDef->SetType(OFTTime);
449  else if(elementType == te::dt::TIME_INSTANT)
450  fieldDef->SetType(OFTDateTime);
451  else
452  throw(te::common::Exception(TE_TR("Unsupported data type by OGR.")));
453  break;
454  }
455 
456  default:
457  throw(te::common::Exception(TE_TR("Unsupported data type by OGR.")));
458  }
459 
460  return fieldDef;
461 }
462 
463 te::gm::GeomType te::ogr::Convert2TerraLib(OGRwkbGeometryType ogrGeomType)
464 {
465  switch(ogrGeomType)
466  {
467  case wkbPoint:
468  return te::gm::MultiPointType;
469 
470  case wkbLineString:
472 
473  case wkbPolygon:
475 
476  case wkbMultiPoint:
477  return te::gm::MultiPointType;
478 
479  case wkbMultiLineString:
481 
482  case wkbMultiPolygon:
484 
485  case wkbGeometryCollection:
487 
488  case wkbLinearRing:
489  return te::gm::LineStringType;
490 
491  case wkbPoint25D:
492  return te::gm::PointMType;
493 
494  case wkbLineString25D:
496 
497  case wkbPolygon25D:
498  return te::gm::PolygonMType;
499 
500  case wkbMultiPoint25D:
502 
503  case wkbMultiLineString25D:
505 
506  case wkbMultiPolygon25D:
508 
509  case wkbGeometryCollection25D:
511 
512  case wkbUnknown:
513  return te::gm::GeometryType;
514 
515  default:
517  }
518 }
519 
520 OGRwkbGeometryType te::ogr::Convert2OGR(te::gm::GeomType geomType)
521 {
522  switch(geomType)
523  {
525  return wkbUnknown;
526 
527  case te::gm::PointType:
528  return wkbPoint;
529 
531  return wkbLineString;
532 
533  case te::gm::PolygonType:
534  return wkbPolygon;
535 
537  return wkbMultiPoint;
538 
540  return wkbMultiLineString;
541 
543  return wkbMultiPolygon;
544 
546  return wkbGeometryCollection;
547 
548  case te::gm::PointMType:
549  return wkbPoint25D;
550 
552  return wkbLineString25D;
553 
555  return wkbPolygon25D;
556 
558  return wkbMultiPoint25D;
559 
561  return wkbMultiLineString25D;
562 
564  return wkbMultiPolygon25D;
565 
567  return wkbGeometryCollection25D;
568 
569  default:
570  throw(te::common::Exception(TE_TR("Unsupported geometry type by OGR Driver.")));
571  }
572 }
573 
574 std::string te::ogr::GetDriverName(const std::string& path)
575 {
576  boost::filesystem::path mpath(path.c_str());
577 
578  std::string ext = mpath.extension().string();
579 
580  if(ext == ".shp" || ext == ".SHP")
581  return std::string("ESRI Shapefile");
582 
583  if(ext == ".mif" || ext == ".MIF")
584  return std::string("Mapinfo File");
585 
586  if(ext == ".kml" || ext == ".KML")
587  return std::string("KML");
588 
589  if(ext == ".geojson" || ext == ".GEOJSON")
590  return std::string("GeoJSON");
591 
592  if(ext == ".gml" || ext == ".GML")
593  return std::string("GML");
594 
595  if(ext == ".dxf" || ext == ".DXF")
596  return std::string("DXF");
597 
598  if(ext == ".dgn" || ext == ".DGN")
599  return std::string("DGN");
600 
601  return "";
602 }
603 
604 std::vector<std::string> te::ogr::GetOGRDrivers(bool filterCreate
605  )
606 {
607  std::vector<std::string> drivernames;
608 
609  int ndrivers = OGRSFDriverRegistrar::GetRegistrar()->GetDriverCount();
610 
611  for (int i = 0; i < ndrivers; ++i)
612  {
613  OGRSFDriver* driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriver(i);
614  if (filterCreate && !driver->TestCapability(ODrCCreateDataSource))
615  continue;
616  drivernames.push_back(driver->GetName());
617  }
618 
619  return drivernames;
620 }
621 
622 std::string te::ogr::GetOGRConnectionInfo(const std::map<std::string, std::string>& connInfo)
623 {
624  std::map<std::string, std::string>::const_iterator it = connInfo.find("URI");
625 
626  if(it != connInfo.end())
627  return it->second;
628 
629  it = connInfo.find("SOURCE");
630 
631  if(it != connInfo.end())
632  return it->second;
633 
634  throw te::common::Exception(TE_TR("Invalid data source connection information!."));
635 }
636 
637 std::string te::ogr::RemoveSpatialSql(const std::string& sql)
638 {
639  // Try find AND
640  std::size_t pos = sql.find("AND Intersection");
641 
642  // Try find without AND
643  if(pos == std::string::npos)
644  pos = sql.find("WHERE Intersection");
645 
646  if(pos == std::string::npos)
647  return sql;
648 
649  std::string newQuery;
650 
651  std::size_t pos2 = sql.find("))", pos);
652  newQuery = sql.substr(0, pos);
653  newQuery += sql.substr(pos2 + 2);
654 
655  return newQuery;
656 }
657 
void setTitle(const std::string &title)
It sets a human descriptive title for the DataSetType.
Definition: DataSetType.h:137
int getSRID() const
It returns the Spatial Reference System ID associated to this geometric object.
Definition: Geometry.h:189
Geometric property.
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
Definition: Enums.h:41
Utility functions for the data access module.
TEOGREXPORT OGRGeometry * Convert2OGR(const te::gm::Geometry *teGeom)
It converts the TerraLib Geometry to OGR Geometry.
Definition: Utils.cpp:80
An atomic property like an integer or double.
bool hasGeom() const
It returns true if the DataSetType has at least one geometry property; otherwise, it returns false...
Definition: DataSetType.h:655
void getWkb(char *wkb, te::common::MachineByteOrder byteOrder) const
It serializes the geometry to a WKB representation into the specified buffer.
Definition: Geometry.cpp:139
A class that models the description of a dataset.
Definition: DataSetType.h:72
double m_urx
Upper right corner x-coordinate.
Definition: Envelope.h:346
static const MachineByteOrder sm_machineByteOrder
A flag that indicates the machine byte order (Big Endian or Little Endian).
Definition: Globals.h:54
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:347
TEOGREXPORT std::string RemoveSpatialSql(const std::string &sql)
Definition: Utils.cpp:637
std::size_t getWkbSize() const
It returns the size required by a WKB representation for this geometric object.
Definition: Geometry.cpp:134
TEOGREXPORT std::vector< std::string > GetOGRDrivers(bool filterCreate=false)
It returns the list of OGR Drivers available.
Definition: Utils.cpp:604
It models a property definition.
Definition: Property.h:59
std::string GetDriverName(const std::string &path)
It tries extract the driver name used by OGR Library based on the given path.
Definition: Utils.cpp:574
double m_llx
Lower left corner x-coordinate.
Definition: Envelope.h:344
const std::vector< Property * > & getProperties() const
It returns the list of properties describing the CompositeProperty.
static SpatialReferenceSystemManager & getInstance()
It returns a reference to the singleton instance.
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
Definition: Config.h:44
TEOGREXPORT te::gm::Geometry * Convert2TerraLib(OGRGeometry *ogrGeom)
It converts the OGR Geometry to TerraLib Geometry.
Definition: Utils.cpp:55
GeomType getGeometryType() const
It returns the geometry subtype allowed for the property.
The type for string types: FIXED_STRING, VAR_STRING or STRING.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Definition: Exception.h:58
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
Definition: Geometry.h:73
double m_lly
Lower left corner y-coordinate.
Definition: Envelope.h:345
TEOGREXPORT std::string GetOGRConnectionInfo(const std::map< std::string, std::string > &connInfo)
Definition: Utils.cpp:622
int getType() const
It returns the property data type.
Definition: Property.h:161
void add(Constraint *c)
It adds a new constraint.
Property * getElementType() const
It returns the type of array elements.
Definition: ArrayProperty.h:98
The type for variable-length multidimensional arrays.
Definition: ArrayProperty.h:45
double m_ury
Upper right corner y-coordinate.
Definition: Envelope.h:347
The type for date and time types: date, date period, date duration, time duration, time instant, time period, time instant with time zone or time period with time zone.
void setCharEncoding(const te::common::CharEncoding &ce)
It sets the string property character encoding.
#define TE_SRS_SIRGAS2000
Definition: Config.h:71
DateTimeType
The subtype of date and time type, based on ISO 8621.
Definition: Enums.h:45
DateTimeType getSubType() const
It returns the date time property sub type.
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
Definition: Utils.cpp:557
TEOGREXPORT OGRSpatialReference * Convert2OGRProjection(int srid)
It converts the TerraLib Projection to OGR Projection.
Definition: Utils.cpp:221
TEOGREXPORT int Convert2TerraLibProjection(OGRSpatialReference *osrs)
It converts the OGR Projection to TerraLib Projection.
Definition: Utils.cpp:126
static Geometry * read(const char *wkb)
It returns a valid geometry from a given WKB.
Definition: WKBReader.cpp:50
const std::string & getName() const
It returns the property name.
Definition: Property.h:127