OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimGpkgSpatialRefSysRecord.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // File: ossimGpkgSpatialRefSysRecord.cpp
4 //
5 // License: LGPL
6 //
7 // See LICENSE.txt file in the top level directory for more details.
8 //
9 // Description: Container class for gpkg_spatial_ref_sys table.
10 //
11 //----------------------------------------------------------------------------
12 // $Id$
13 
15 #include "ossimSqliteUtil.h"
16 
17 #include <ossim/base/ossimGpt.h>
19 #include <ossim/base/ossimNotify.h>
20 #include <ossim/base/ossimTrace.h>
21 
26 
27 #include <sqlite3.h>
28 
29 #include <sstream>
30 
31 //---
32 // For trace debugging. To enable at runtime do:
33 // your_app -T "ossimGpkgSpatialRefSysRecord:debug" your_app_args
34 //---
35 static ossimTrace traceDebug("ossimGpkgSpatialRefSysRecord:debug");
36 
37 static std::string TABLE_NAME = "gpkg_spatial_ref_sys";
38 
40  :
42  m_srs_name(),
43  m_srs_id(0),
44  m_organization(),
45  m_organization_coordsys_id(0),
46  m_definition(),
47  m_description()
48 {
49 }
50 
52  :
54  m_srs_name(obj.m_srs_name),
55  m_srs_id(obj.m_srs_id),
56  m_organization(obj.m_organization),
57  m_organization_coordsys_id(obj.m_organization_coordsys_id),
58  m_definition(obj.m_definition),
59  m_description(obj.m_description)
60 {
61 }
62 
65 {
66  if ( this != &obj )
67  {
68  m_srs_name = obj.m_srs_name;
69  m_srs_id = obj.m_srs_id;
74  }
75  return *this;
76 }
77 
79 {
80 }
81 
83 {
84  return TABLE_NAME;
85 }
86 
87 bool ossimGpkgSpatialRefSysRecord::init( sqlite3_stmt* pStmt )
88 {
89  static const char M[] = "ossimGpkgSpatialRefSysRecord::init(pStmt)";
90 
91  bool status = false;
92 
93  if ( pStmt )
94  {
95  const ossim_int32 EXPECTED_COLUMNS = 6;
96  ossim_int32 nCol = sqlite3_column_count( pStmt );
97 
98  if ( nCol != EXPECTED_COLUMNS )
99  {
101  << M << " WARNING:\nUnexpected number of columns: " << nCol
102  << "Expected column count: " << EXPECTED_COLUMNS
103  << std::endl;
104  }
105 
106  if ( nCol >= EXPECTED_COLUMNS )
107  {
108  ossim_int32 columnsFound = 0;
109  std::string colName;
110  const char* c = 0; // To catch null so not to pass to string.
111 
112  for ( ossim_int32 i = 0; i < nCol; ++i )
113  {
114  colName = sqlite3_column_name(pStmt, i);
115  if ( colName.size() )
116  {
117  if ( colName == "srs_name" )
118  {
119  c = (const char*)sqlite3_column_text(pStmt, i);
120  m_srs_name = (c ? c : "");
121  ++columnsFound;
122  }
123  else if ( colName == "srs_id" )
124  {
125  m_srs_id = sqlite3_column_int(pStmt, i);
126  ++columnsFound;
127  }
128  else if ( colName == "organization" )
129  {
130  c = (const char*)sqlite3_column_text(pStmt, i);
131  m_organization = (c ? c : "");
132  ++columnsFound;
133  }
134  else if ( colName == "organization_coordsys_id" )
135  {
136  m_organization_coordsys_id = sqlite3_column_int(pStmt, i);
137  ++columnsFound;
138  }
139  else if ( colName == "definition" )
140  {
141  c = (const char*)sqlite3_column_text(pStmt, i);
142  m_definition = (c ? c : "");
143  ++columnsFound;
144  }
145  else if ( colName == "description" )
146  {
147  c = (const char*)sqlite3_column_text(pStmt, i);
148  m_description = (c ? c : "" );
149  ++columnsFound;
150  }
151  else
152  {
154  << M << " Unhandled column name[" << i << "]: "
155  << colName << std::endl;
156  }
157 
158  } // Matches: if ( colName.size() )
159 
160  if ( columnsFound == EXPECTED_COLUMNS )
161  {
162  status = true;
163  break;
164  }
165 
166  } // Matches: for ( int i = 0; i < nCol; ++i )
167  }
168 
169  } // Matches: if ( pStmt )
170 
171  return status;
172 
173 } // End: ossimGpkgSpatialRefSysRecord::init( pStmt )
174 
177 {
178  //---
179  // Data taken from document:
180  // National System for Geospatial-Intelligence (NSG) GeoPackage Encoding
181  // Standard 1.0 Implementation Interoperability Standard (2014-10-29)
182  //---
184 
185  static const char M[] = "ossimGpkgSpatialRefSysRecord::init(proj)";
186 
187  if ( db && proj )
188  {
189  ossim_int32 pcsCode = (ossim_int32)proj->getPcsCode();
190 
191  if ( pcsCode == 4326 )
192  {
193  m_srs_name = "WGS 84 Geographic 2D lat/lon";
194  m_definition = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
195  m_organization = "EPSG";
197  m_description = "Horizontal component of 3D system. Used by the GPS satellite navigation system and for NATO military geodetic surveying.";
198 
200  }
201  else if ( pcsCode == 3395 )
202  {
203  m_srs_name = "WGS 84 / World Mercator";
204  m_definition = "PROJCS[\"WGS 84 / World Mercator\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"3395\"],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]";
205  m_organization = "EPSG";
207  m_description = "Mercator (1SP)";
208 
210  }
211  else if ( pcsCode == 3857 )
212  {
213  m_srs_name = "WGS 84 / Pseudo-Mercator"; // ???
214  m_definition = "PROJCS[\"WGS 84 / Pseudo-Mercator\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"X\",EAST],AXIS[\"Y\",NORTH],EXTENSION[\"PROJ4\",\"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs\"],AUTHORITY[\"EPSG\",\"3857\"]]";
215  m_organization = "EPSG";
217  m_description = "Google Projection"; // ?
218 
220  }
221  else
222  {
223  ossimString projName = proj->getClassName();
224  ossimString datumCode = proj->getDatum()->code();
225 
226  if ( projName == "ossimUtmProjection" )
227  {
228  if ( datumCode == "WGE" )
229  {
230  const ossimUtmProjection* utmProj =
231  dynamic_cast<const ossimUtmProjection*>( proj );
232  if ( utmProj )
233  {
234  ossimGpt origin = proj->origin();
235  ossimString centralMeridian = ossimString::toString( origin.lond() );
236  ossimString zone = ossimString::toString( utmProj->getZone() );
237  char hemisphere = utmProj->getHemisphere();
238 
239  m_srs_name = "WGS 84 / UTM zone ";
240  m_srs_name += zone.string();
241  if ( hemisphere == 'N' )
242  {
243  m_srs_name += "north";
244  }
245  else
246  {
247  m_srs_name += "south";
248  }
249 
250  m_definition = "PROJCS[\"WGS 84 / UTM zone ";
251  m_definition += zone.string();
252  m_definition += hemisphere;
253  m_definition += "\",GEOGCS[\"WGS 84\",DATUM[\"World Geodetic System_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Transverse Mercator\",AUTHORITY[\"EPSG\",\"9807\"]],PARAMETER[\"Latitude of natural origin\",0],PARAMETER[\"Longitude of natural origin\",";
254  m_definition += centralMeridian.string();
255  m_definition += "],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",";
256  if ( hemisphere == 'N' )
257  {
258  m_definition += "0";
259  }
260  else
261  {
262  m_definition += "10000000";
263  }
264  m_definition += "],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",AUTHORITY[\"EPSG\",\"";
266  m_definition += "\"]]";
267 
268  m_organization = "EPSG";
269  m_organization_coordsys_id = pcsCode;
270  m_description = "Large and medium scale topographic mapping and engineering survey.";
272  }
273 
274  } // Matches: if ( datumCode == "WGE" )
275 
276  if ( initCode == ossimGpkgSpatialRefSysRecord::ERROR )
277  {
279  << M
280  << "\nUnhandled projection: " << proj->getClassName()
281  << "\n datum: " << proj->getDatum()->code() << std::endl;
282  }
283 
284  } // Matches: if ( projName == "ossimUtmProjection" )
285  }
286 
287  if ( initCode == ossimGpkgSpatialRefSysRecord::OK )
288  {
289  m_srs_id = getSrsId( db );
290  if ( m_srs_id != -1 )
291  {
292  // Record was found in database.
294  }
295  else
296  {
297  m_srs_id = getNextSrsId( db );
298  }
299  }
300 
301  } // Matches: if ( proj )
302 
303  return initCode;
304 
305 } // End: ossimGpkgSpatialRefSysRecord::init( proj )
306 
308 {
309  bool status = false;
310  if ( db )
311  {
312  status = ossim_sqlite::tableExists( db, TABLE_NAME );
313 
314  if ( !status )
315  {
316  std::ostringstream sql;
317  sql << "CREATE TABLE " << TABLE_NAME << " ( "
318  << "srs_name TEXT NOT NULL, "
319  << "srs_id INTEGER NOT NULL PRIMARY KEY, "
320  << "organization TEXT NOT NULL, "
321  << "organization_coordsys_id INTEGER NOT NULL, "
322  << "definition TEXT NOT NULL, "
323  << "description TEXT )";
324 
325  if ( ossim_sqlite::exec( db, sql.str() ) == SQLITE_DONE )
326  {
327  // Requirement 11: Create the three required record entries.
329  record.m_srs_id = -1;
330  record.m_organization = "NONE";
331  record.m_organization_coordsys_id = -1;
332  record.m_definition = "undefined";
333 
334  if ( record.insert( db ) )
335  {
336  record.m_srs_id = 0;
337  record.m_organization_coordsys_id = 0;
338 
339  if ( record.insert( db ) )
340  {
341  record.m_srs_id = 1;
342  record.m_srs_name = "WGS 84 Geographic 2D lat/lon";
343  record.m_definition = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
344  record.m_organization = "EPSG";
345  record.m_organization_coordsys_id = 4326;
346  record.m_description = "Horizontal component of 3D system. Used by the GPS satellite navigation system and for NATO military geodetic surveying.";
347 
348  status = record.insert( db );
349  }
350  }
351  }
352  }
353  }
354 
355  return status;
356 
357 } // End: ossimGpkgSpatialRefSysRecord::createTable( sqlite3* db )
358 
360 {
361  bool status = false;
362  if ( db )
363  {
364  std::ostringstream sql;
365  sql << "INSERT INTO gpkg_spatial_ref_sys VALUES ( "
366  << "'" << m_srs_name << "', "
367  << m_srs_id << ", "
368  << "'" << m_organization << "', "
369  << m_organization_coordsys_id << ", '"
370  << m_definition << "', '"
371  << m_description << "' )";
372 
373  if ( ossim_sqlite::exec( db, sql.str() ) == SQLITE_DONE )
374  {
375  status = true;
376  }
377  }
378  return status;
379 }
380 
382  const std::string& prefix ) const
383 {
384  std::string myPref = prefix.size() ? prefix : std::string("gpkg_spatial_ref_sys.");
385  std::string value;
386 
387  std::string key = "srs_name";
388  kwl.addPair(myPref, key, m_srs_name, true);
389 
390  key = "srs_id";
392  kwl.addPair(myPref, key, value, true);
393 
394  key = "organization";
395  kwl.addPair(myPref, key, m_organization, true);
396 
397  key = "organization_coordsys_id";
399  kwl.addPair( myPref, key, value, true);
400 
401  key = "definition";
402  kwl.addPair(myPref, key, m_definition, true);
403 
404  key = "description";
405  kwl.addPair(myPref, key, m_description, true);
406 }
407 
409 {
410  ossim_int32 result = -1;
411  if ( db )
412  {
413  std::ostringstream sql;
414  sql << "SELECT srs_id FROM gpkg_spatial_ref_sys WHERE organization == '"
415  << m_organization
416  << "' AND organization_coordsys_id == "
418 
419  const char *zLeftover; // Tail of unprocessed SQL
420  sqlite3_stmt *pStmt = 0; // The current SQL statement
421  int rc = sqlite3_prepare_v2(db, // Database handle
422  sql.str().c_str(), // SQL statement, UTF-8 encoded
423  -1, // Maximum length of zSql in bytes.
424  &pStmt, // OUT: Statement handle
425  &zLeftover); // OUT: Pointer to unused portion of zSql
426  if ( rc == SQLITE_OK )
427  {
428  // Read the row:
429  rc = sqlite3_step(pStmt);
430  if ( rc == SQLITE_ROW )
431  {
432  result = sqlite3_column_int(pStmt, 0);
433  }
434  }
435  sqlite3_finalize(pStmt);
436  }
437  return result;
438 }
439 
441 {
442  ossim_int32 result = 2; // -1, 0, and 1 are created by create table...
443  if ( db )
444  {
445  std::string sql = "SELECT srs_id FROM gpkg_spatial_ref_sys ORDER BY srs_id DESC LIMIT 1";
446 
447  const char *zLeftover; // Tail of unprocessed SQL
448  sqlite3_stmt *pStmt = 0; // The current SQL statement
449  int rc = sqlite3_prepare_v2(db, // Database handle
450  sql.c_str(), // SQL statement, UTF-8 encoded
451  -1, // Maximum length of zSql in bytes.
452  &pStmt, // OUT: Statement handle
453  &zLeftover); // OUT: Pointer to unused portion of zSql
454  if ( rc == SQLITE_OK )
455  {
456  // Read the row:
457  rc = sqlite3_step(pStmt);
458  if ( rc == SQLITE_ROW )
459  {
460  result = sqlite3_column_int(pStmt, 0);
461  ++result;
462  }
463  }
464  sqlite3_finalize(pStmt);
465  }
466  return result;
467 }
bool insert(sqlite3 *db)
Inserst this record into gpkg_contents table.
static const std::string & getTableName()
Get the table name "gpkg_spatial_ref_sys".
std::basic_ostringstream< char > ostringstream
Class for char output memory streams.
Definition: ossimIosFwd.h:35
double lond() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:97
Represents serializable keyword/value map.
virtual ossim_uint32 getPcsCode() const
Returns the EPSG PCS code or 32767 if the projection is a custom (non-EPSG) projection.
int exec(sqlite3 *db, const std::string &sql)
Preforms sqlite3_prepare_v2, sqlite3_step and sqlite3_finalize.
bool tableExists(sqlite3 *db, const std::string &tableName)
Checks for existance of table.
virtual const ossimString & code() const
Definition: ossimDatum.h:57
static ossimString toString(bool aValue)
Numeric to string methods.
const ossimGpkgSpatialRefSysRecord & operator=(const ossimGpkgSpatialRefSysRecord &obj)
void addPair(const std::string &key, const std::string &value, bool overwrite=true)
virtual ossimString getClassName() const
Definition: ossimObject.cpp:64
static bool createTable(sqlite3 *db)
Creates gpkg_contents table in database.
virtual const ossimDatum * getDatum() const
virtual ossimGpt origin() const
ossimGpkgSpatialRefSysRecord()
default constructor
virtual void saveState(ossimKeywordlist &kwl, const std::string &prefix) const
Saves the state of object.
return status
ossim_int32 getSrsId(sqlite3 *db)
Looks in database for matching record and returns the id if found.
ossim_int32 getZone() const
ossim_int32 getNextSrsId(sqlite3 *db)
Looks in database for matching record and returns the id if found.
virtual bool init(sqlite3_stmt *pStmt)
Initialize from database.
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
int ossim_int32
const std::string & string() const
Definition: ossimString.h:414