~ubuntu-branches/ubuntu/hardy/qgis/hardy

« back to all changes in this revision

Viewing changes to src/gui/qgsspatialrefsys.cpp

  • Committer: Bazaar Package Importer
  • Author(s): William Grant
  • Date: 2007-05-06 13:42:32 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070506134232-pyli6t388w5asd8x
Tags: 0.8.0-3ubuntu1
* Merge from Debian unstable. Remaining Ubuntu changes:
  - debian/rules, debian/qgis.install, debian/qgis.dirs debian/qgis.desktop:
    Add and install .desktop.
* debian/qgis.desktop: Remove Applications category; it's not real.
* Modify Maintainer value to match Debian-Maintainer-Field Spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "qgsspatialrefsys.h"
 
2
 
 
3
#include <cassert>
 
4
#include <cmath>
 
5
#include <iostream>
 
6
#include <sqlite3.h>
 
7
#include <QSettings>
 
8
#include <QRegExp>
 
9
#include <QFileInfo>
 
10
#include <QDir>
 
11
#include <projects.h>
 
12
#include <QDomNode>
 
13
#include <QDomElement>
 
14
#include <QMessageBox>
 
15
 
 
16
#include <qgsapplication.h>
 
17
#include <qgslayerprojectionselector.h>
 
18
#include "qgslogger.h"
 
19
#include <qgsproject.h>
 
20
#include <qgis.h> //const vals declared here
 
21
 
 
22
 
 
23
//gdal and ogr includes (needed for == operator)
 
24
#include <ogr_api.h>
 
25
#include <ogr_spatialref.h>
 
26
#include <cpl_error.h>
 
27
 
 
28
 
 
29
//--------------------------
 
30
 
 
31
QgsSpatialRefSys::QgsSpatialRefSys()
 
32
  : mMapUnits(QGis::UNKNOWN),
 
33
    mIsValidFlag(0)
 
34
{
 
35
  // NOOP
 
36
}
 
37
 
 
38
QgsSpatialRefSys::QgsSpatialRefSys(QString theWkt)
 
39
  : mMapUnits(QGis::UNKNOWN),
 
40
    mIsValidFlag(0)
 
41
{
 
42
  createFromWkt(theWkt);
 
43
}
 
44
 
 
45
QgsSpatialRefSys::QgsSpatialRefSys(long theSrsId,
 
46
                                   QString theDescription,
 
47
                                   QString theProjectionAcronym,
 
48
                                   QString theEllipsoidAcronym,
 
49
                                   QString theProj4String,
 
50
                                   long theSRID,
 
51
                                   long theEpsg, 
 
52
                                   bool theGeoFlag)
 
53
  : mMapUnits(QGis::UNKNOWN),
 
54
    mIsValidFlag(0)
 
55
{
 
56
  // NOOP
 
57
}
 
58
 
 
59
QgsSpatialRefSys::QgsSpatialRefSys(const long theId, SRS_TYPE theType)
 
60
  : mMapUnits(QGis::UNKNOWN),
 
61
    mIsValidFlag(0)
 
62
{
 
63
  createFromId(theId, theType);
 
64
}
 
65
 
 
66
void QgsSpatialRefSys::createFromId(const long theId, SRS_TYPE theType)
 
67
{
 
68
  switch (theType)
 
69
  {
 
70
  case QGIS_SRSID:
 
71
    createFromSrsId(theId);
 
72
    break;
 
73
  case POSTGIS_SRID:
 
74
    createFromSrid(theId);
 
75
    break;
 
76
  case EPSG:
 
77
    createFromEpsg(theId);
 
78
    break;
 
79
  default:
 
80
    //THIS IS BAD...THIS PART OF CODE SHOULD NEVER BE REACHED...
 
81
    QgsLogger::critical("Unexpected case reached in " + QString(__FILE__) + " : " + QString(__LINE__));
 
82
  };
 
83
 
 
84
}
 
85
 
 
86
 
 
87
bool QgsSpatialRefSys::createFromOgcWmsCrs(QString theCrs)
 
88
{
 
89
  QStringList parts = theCrs.split(":");
 
90
 
 
91
  if (parts.at(0) == "EPSG")
 
92
  {
 
93
    createFromEpsg( parts.at(1).toLong() );
 
94
  }
 
95
  else if (parts.at(0) == "CRS")
 
96
  {
 
97
    if (parts.at(1) == "84")
 
98
    {
 
99
      //! \todo - CRS:84 is hardcoded to EPSG:4326 - see if this is appropriate
 
100
      /**
 
101
       *  See WMS 1.3 standard appendix B3 for details
 
102
       */
 
103
      createFromEpsg( 4326 );
 
104
    }
 
105
  }
 
106
  else
 
107
  {
 
108
    return FALSE;
 
109
  }
 
110
 
 
111
  return TRUE;
 
112
}
 
113
 
 
114
 
 
115
// Assignment operator
 
116
QgsSpatialRefSys& QgsSpatialRefSys::operator=(const QgsSpatialRefSys& srs)
 
117
{
 
118
  if (&srs != this)
 
119
  {
 
120
    mSrsId = srs.mSrsId;
 
121
    mDescription = srs.mDescription;
 
122
    mProjectionAcronym = srs.mProjectionAcronym;
 
123
    mEllipsoidAcronym = srs.mEllipsoidAcronym;
 
124
    mProj4String = srs.mProj4String;
 
125
    mGeoFlag = srs.mGeoFlag;
 
126
    mMapUnits = srs.mMapUnits;
 
127
    mSRID = srs.mSRID;
 
128
    mEpsg = srs.mEpsg;
 
129
    mIsValidFlag = srs.mIsValidFlag;
 
130
  }
 
131
  return *this;
 
132
}
 
133
 
 
134
// Misc helper functions -----------------------
 
135
 
 
136
 
 
137
void QgsSpatialRefSys::validate()
 
138
{
 
139
  QgsDebugMsg("QgsSpatialRefSys::validate");
 
140
  //dont bother trying to do an initial test with gdal if
 
141
  //the proj4String is not even populated
 
142
  if (QString::null!=mProj4String && !mProj4String.isEmpty())
 
143
  {
 
144
    //first of all use gdal to test if this is an ok srs already
 
145
    //if not we will prompt the user for and srs
 
146
    //then retest using gdal
 
147
    //if the retest fails we will then set  this srs to the GEOCS/WGS84 default
 
148
 
 
149
 
 
150
    /* Here are the possible OGR error codes :
 
151
       typedef int OGRErr;
 
152
 
 
153
       #define OGRERR_NONE                0
 
154
       #define OGRERR_NOT_ENOUGH_DATA     1    --> not enough data to deserialize
 
155
       #define OGRERR_NOT_ENOUGH_MEMORY   2
 
156
       #define OGRERR_UNSUPPORTED_GEOMETRY_TYPE 3
 
157
       #define OGRERR_UNSUPPORTED_OPERATION 4
 
158
       #define OGRERR_CORRUPT_DATA        5
 
159
       #define OGRERR_FAILURE             6
 
160
       #define OGRERR_UNSUPPORTED_SRS     7 */
 
161
 
 
162
    //get the wkt into ogr
 
163
    //this is really ugly but we need to get a QString to a char**
 
164
    const char *mySourceCharArrayPointer = mProj4String.latin1();
 
165
    //create the sr and populate it from a wkt proj definition
 
166
    OGRSpatialReference myOgrSpatialRef;
 
167
    OGRErr myInputResult = myOgrSpatialRef.importFromProj4( mySourceCharArrayPointer );
 
168
 
 
169
    if (myInputResult==OGRERR_NONE)
 
170
    {
 
171
      //srs is valid so nothing more to do...
 
172
      createFromProj4(mProj4String);
 
173
      return;
 
174
    }
 
175
  }
 
176
 
 
177
  QSettings mySettings;
 
178
  QString myDefaultProjectionOption =
 
179
    mySettings.readEntry("/Projections/defaultBehaviour");
 
180
 
 
181
  if (myDefaultProjectionOption=="prompt")
 
182
  {
 
183
    //@note this class is not a descendent of QWidget so we cant pass
 
184
    //it in the ctor of the layer projection selector
 
185
 
 
186
    QgsLayerProjectionSelector * mySelector = new QgsLayerProjectionSelector();
 
187
    long myDefaultSRS =
 
188
      QgsProject::instance()->readNumEntry("SpatialRefSys","/ProjectSRSID",GEOSRS_ID);
 
189
    mySelector->setSelectedSRSID(myDefaultSRS);
 
190
    if(mySelector->exec())
 
191
    {
 
192
      createFromSrsId(mySelector->getCurrentSRSID());
 
193
      delete mySelector;
 
194
      return;
 
195
    }
 
196
    else
 
197
    {
 
198
      QApplication::restoreOverrideCursor();
 
199
    }
 
200
    delete mySelector;
 
201
  }
 
202
  else if (myDefaultProjectionOption=="useProject")
 
203
  {
 
204
    // XXX TODO: Change project to store selected CS as 'projectSRS' not 'selectedWKT'
 
205
    mProj4String = QgsProject::instance()->readEntry("SpatialRefSys","//ProjectSRSProj4String",GEOPROJ4);
 
206
  }
 
207
  else ///Projections/defaultBehaviour==useGlobal
 
208
  {
 
209
    // XXX TODO: Change global settings to store default CS as 'defaultSRS' not 'defaultProjectionWKT'
 
210
    int srs_id = mySettings.readNumEntry("/Projections/defaultProjectionSRSID",GEOSRS_ID);
 
211
    createFromSrsId(srs_id);
 
212
    return;
 
213
  }
 
214
 
 
215
  //
 
216
  // This is the second check after the user assigned SRS has been retrieved
 
217
  // If it still does not work, we will simply use the QgsSpatialRefSys const GEOPROJ4 for the job
 
218
  //
 
219
 
 
220
  //this is really ugly but we need to get a QString to a char**
 
221
  const char *mySourceCharArrayPointer = mProj4String.latin1();
 
222
  //create the sr and populate it from a wkt proj definition
 
223
  OGRSpatialReference myOgrSpatialRef;
 
224
  OGRErr myInputResult = myOgrSpatialRef.importFromProj4( mySourceCharArrayPointer );
 
225
 
 
226
  if (! myInputResult==OGRERR_NONE)
 
227
  {
 
228
    //default to proj 4..if all else fails we will use that for this srs
 
229
    mProj4String = GEOPROJ4;
 
230
  }
 
231
 
 
232
  createFromProj4(mProj4String);
 
233
 
 
234
  return;
 
235
}
 
236
 
 
237
bool QgsSpatialRefSys::createFromSrid(long theSrid)
 
238
{
 
239
  QgsDebugMsg("QgsSpatialRefSys::createFromSrid");
 
240
 
 
241
  // Get the full path name to the sqlite3 spatial reference database.
 
242
  QString myDatabaseFileName = QgsApplication::srsDbFilePath();
 
243
 
 
244
 
 
245
  sqlite3      *myDatabase;
 
246
  const char   *myTail;
 
247
  sqlite3_stmt *myPreparedStatement;
 
248
  int           myResult;
 
249
  //check the db is available
 
250
  myResult = openDb(myDatabaseFileName, &myDatabase);
 
251
  if(myResult)
 
252
  {
 
253
      return false;
 
254
  }
 
255
 
 
256
  /*
 
257
    srs_id INTEGER PRIMARY KEY,
 
258
    description text NOT NULL,
 
259
    projection_acronym text NOT NULL,
 
260
    ellipsoid_acronym NOT NULL,
 
261
    parameters text NOT NULL,
 
262
    srid integer NOT NULL,
 
263
    epsg integer NOT NULL,
 
264
    is_geo integer NOT NULL);
 
265
  */
 
266
 
 
267
  QString mySql = "select srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,epsg,is_geo from tbl_srs where srid='" + QString::number(theSrid) + "'";
 
268
  myResult = sqlite3_prepare(myDatabase, mySql.utf8(), mySql.length(), &myPreparedStatement, &myTail);
 
269
  // XXX Need to free memory from the error msg if one is set
 
270
  if(myResult == SQLITE_OK && sqlite3_step(myPreparedStatement) == SQLITE_ROW)
 
271
  {
 
272
    mSrsId = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,0)).toLong();
 
273
    mDescription = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,1));
 
274
    mProjectionAcronym = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,2));
 
275
    mEllipsoidAcronym = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,3));
 
276
    mProj4String = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,4));
 
277
    mSRID = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,5)).toLong();
 
278
    mEpsg = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,6)).toLong();
 
279
    int geo = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,7)).toInt();
 
280
    mGeoFlag = (geo == 0 ? false : true);
 
281
    setMapUnits();
 
282
    mIsValidFlag = true;
 
283
 
 
284
  }
 
285
  else
 
286
  {
 
287
    QgsDebugMsg("QgsSpatialRefSys::createFromSrid failed : " + mySql);
 
288
    mIsValidFlag = false;
 
289
  }
 
290
  sqlite3_finalize(myPreparedStatement);
 
291
  sqlite3_close(myDatabase);
 
292
  return mIsValidFlag;
 
293
}
 
294
 
 
295
bool QgsSpatialRefSys::createFromWkt(QString theWkt)
 
296
{
 
297
  if (theWkt.isEmpty())
 
298
  {
 
299
    QgsLogger::critical("QgsSpatialRefSys::createFromWkt -- theWkt is uninitialised, operation failed");
 
300
    mIsValidFlag = false;
 
301
    return false;
 
302
  }
 
303
  QgsDebugMsg("QgsSpatialRefSys::createFromWkt(QString theWkt) using: " + theWkt);
 
304
  //this is really ugly but we need to get a QString to a char**
 
305
  const char *myCharArrayPointer = theWkt.latin1(); //Why doesn't it work with toLocal8Bit().data()?
 
306
  char *pWkt = (char *)myCharArrayPointer;
 
307
  /* Here are the possible OGR error codes :
 
308
     typedef int OGRErr;
 
309
     #define OGRERR_NONE                0
 
310
     #define OGRERR_NOT_ENOUGH_DATA     1    --> not enough data to deserialize 
 
311
     #define OGRERR_NOT_ENOUGH_MEMORY   2
 
312
     #define OGRERR_UNSUPPORTED_GEOMETRY_TYPE 3
 
313
     #define OGRERR_UNSUPPORTED_OPERATION 4
 
314
     #define OGRERR_CORRUPT_DATA        5
 
315
     #define OGRERR_FAILURE             6
 
316
     #define OGRERR_UNSUPPORTED_SRS     7 
 
317
  */
 
318
 
 
319
  OGRSpatialReference myOgrSpatialRef;
 
320
 
 
321
  OGRErr myInputResult = myOgrSpatialRef.importFromWkt( &pWkt );
 
322
  if (myInputResult != OGRERR_NONE)
 
323
  {
 
324
    QgsDebugMsg("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
 
325
    QgsDebugMsg("QgsSpatialRefSys::createFromWkt(QString theWkt) ");
 
326
    QgsDebugMsg("This SRS could *** NOT *** be set from the supplied WKT ");
 
327
    QgsDebugMsg("INPUT: " + theWkt);
 
328
    QgsDebugMsg("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
 
329
    mIsValidFlag = false;
 
330
    return false;
 
331
  }
 
332
 
 
333
 
 
334
  // always morph from esri as it doesn't hurt anything
 
335
  myOgrSpatialRef.morphFromESRI();
 
336
  // create the proj4 structs needed for transforming
 
337
  char *proj4src;
 
338
  myOgrSpatialRef.exportToProj4(&proj4src);
 
339
 
 
340
  //now that we have the proj4string, delegate to createFromProj4String so
 
341
  // that we can try to fill in the remaining class members...
 
342
  //create from Proj wil set the isValidFalg
 
343
  createFromProj4(QString(proj4src));
 
344
  return mIsValidFlag;
 
345
  //setMapunits will be called by createfromproj above
 
346
}
 
347
 
 
348
bool QgsSpatialRefSys::createFromEpsg(long theEpsg)
 
349
{
 
350
  QgsDebugMsg("QgsSpatialRefSys::createFromEpsg with " + QString::number(theEpsg));
 
351
  // Get the full path name to the sqlite3 spatial reference database.
 
352
  QString myDatabaseFileName = QgsApplication::srsDbFilePath();
 
353
 
 
354
 
 
355
  sqlite3      *myDatabase;
 
356
  const char   *myTail;
 
357
  sqlite3_stmt *myPreparedStatement;
 
358
  int           myResult;
 
359
  //check the db is available
 
360
  myResult = openDb(myDatabaseFileName, &myDatabase);
 
361
  if(myResult)
 
362
  {
 
363
      return false;
 
364
  }
 
365
 
 
366
  /*
 
367
    srs_id INTEGER PRIMARY KEY,
 
368
    description text NOT NULL,
 
369
    projection_acronym text NOT NULL,
 
370
    ellipsoid_acronym NOT NULL,
 
371
    parameters text NOT NULL,
 
372
    srid integer NOT NULL,
 
373
    epsg integer NOT NULL,
 
374
    is_geo integer NOT NULL);
 
375
  */
 
376
 
 
377
  QString mySql = "select srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,epsg,is_geo from tbl_srs where epsg='" + QString::number(theEpsg) + "'";
 
378
  myResult = sqlite3_prepare(myDatabase, mySql.utf8(), mySql.length(), &myPreparedStatement, &myTail);
 
379
  // XXX Need to free memory from the error msg if one is set
 
380
  if(myResult == SQLITE_OK && sqlite3_step(myPreparedStatement) == SQLITE_ROW)
 
381
  {
 
382
    mSrsId = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,0)).toLong();
 
383
    mDescription = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,1));
 
384
    mProjectionAcronym = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,2));
 
385
    mEllipsoidAcronym = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,3));
 
386
    mProj4String = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,4));
 
387
    mSRID = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,5)).toLong();
 
388
    mEpsg = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,6)).toLong();
 
389
    int geo = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,7)).toInt();
 
390
    mGeoFlag = (geo == 0 ? false : true);
 
391
    setMapUnits();
 
392
    mIsValidFlag = true;
 
393
 
 
394
  }
 
395
  else
 
396
  {
 
397
    QgsLogger::critical(" QgsSpatialRefSys::createFromEpsg failed :  " + mySql);
 
398
    mIsValidFlag = false;
 
399
  }
 
400
  sqlite3_finalize(myPreparedStatement);
 
401
  sqlite3_close(myDatabase);
 
402
  return mIsValidFlag;
 
403
}
 
404
 
 
405
 
 
406
bool QgsSpatialRefSys::createFromSrsId (long theSrsId)
 
407
{
 
408
  QgsDebugMsg("QgsSpatialRefSys::createFromSrsId");
 
409
  QString myDatabaseFileName;
 
410
  //
 
411
  // Determine if this is a user projection or a system on
 
412
  // user projection defs all have srs_id >= 100000
 
413
  //
 
414
  if (theSrsId>= USER_PROJECTION_START_ID)
 
415
  {
 
416
    myDatabaseFileName = QgsApplication::qgisUserDbFilePath();
 
417
    QFileInfo myFileInfo;
 
418
    myFileInfo.setFile(myDatabaseFileName);
 
419
    if ( !myFileInfo.exists( ) )
 
420
    {
 
421
      mIsValidFlag = false;
 
422
      QgsLogger::warning("QgsSpatialRefSys::createFromSrid failed :  users qgis.db not found");
 
423
      return mIsValidFlag;
 
424
    }
 
425
  }
 
426
  else //must be  a system projection then
 
427
  {
 
428
    // Get the full path name to the sqlite3 spatial reference database.
 
429
    myDatabaseFileName = QgsApplication::srsDbFilePath();
 
430
  }
 
431
 
 
432
 
 
433
  sqlite3      *myDatabase;
 
434
  const char   *myTail;
 
435
  sqlite3_stmt *myPreparedStatement;
 
436
  int           myResult;
 
437
  //check the db is available
 
438
  myResult = openDb(myDatabaseFileName, &myDatabase);
 
439
  if(myResult)
 
440
  {
 
441
      return false;
 
442
  }
 
443
 
 
444
  /*
 
445
    srs_id INTEGER PRIMARY KEY,
 
446
    description text NOT NULL,
 
447
    projection_acronym text NOT NULL,
 
448
    ellipsoid_acronym NOT NULL,
 
449
    parameters text NOT NULL,
 
450
    srid integer NOT NULL,
 
451
    epsg integer NOT NULL,
 
452
    is_geo integer NOT NULL);
 
453
  */
 
454
 
 
455
  QString mySql = "select srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,epsg,is_geo from tbl_srs where srs_id='" + QString::number(theSrsId) + "'";
 
456
  myResult = sqlite3_prepare(myDatabase, mySql.utf8(), mySql.length(), &myPreparedStatement, &myTail);
 
457
  // XXX Need to free memory from the error msg if one is set
 
458
  if(myResult == SQLITE_OK && sqlite3_step(myPreparedStatement) == SQLITE_ROW)
 
459
  {
 
460
    mSrsId = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,0)).toLong();
 
461
    mDescription = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,1));
 
462
    mProjectionAcronym = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,2));
 
463
    mEllipsoidAcronym = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,3));
 
464
    mProj4String = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,4));
 
465
    mSRID = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,5)).toLong();
 
466
    mEpsg = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,6)).toLong();
 
467
    int geo = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,7)).toInt();
 
468
    mGeoFlag = (geo == 0 ? false : true);
 
469
    setMapUnits();
 
470
    mIsValidFlag = true;
 
471
 
 
472
  }
 
473
  else
 
474
  {
 
475
    QgsLogger::warning("QgsSpatialRefSys::createFromSrsId failed :  " + mySql);
 
476
    mIsValidFlag = false;
 
477
  }
 
478
  sqlite3_finalize(myPreparedStatement);
 
479
  sqlite3_close(myDatabase);
 
480
  return mIsValidFlag;
 
481
}
 
482
 
 
483
 
 
484
 
 
485
 
 
486
 
 
487
bool QgsSpatialRefSys::isValid() const
 
488
{
 
489
  if (mProj4String.isEmpty())
 
490
    return false;
 
491
 
 
492
  //this is really ugly but we need to get a QString to a char**
 
493
  const char *mySourceCharArrayPointer = mProj4String.latin1();
 
494
  //create the sr and populate it from a wkt proj definition
 
495
  OGRSpatialReference myOgrSpatialRef;
 
496
  OGRErr myResult = myOgrSpatialRef.importFromProj4( mySourceCharArrayPointer );
 
497
  if (myResult==OGRERR_NONE)
 
498
  {
 
499
    //srs is valid so nothing more to do...
 
500
    return true;
 
501
  }
 
502
  else
 
503
  {
 
504
    return false;
 
505
  }
 
506
}
 
507
 
 
508
bool QgsSpatialRefSys::createFromProj4 (const QString theProj4String)
 
509
{
 
510
 
 
511
  //
 
512
  // Example:
 
513
  // +proj=tmerc +lat_0=0 +lon_0=-62 +k=0.999500 +x_0=400000 +y_0=0
 
514
  // +ellps=clrk80 +towgs84=-255,-15,71,0,0,0,0 +units=m +no_defs
 
515
  //
 
516
  mIsValidFlag=false;
 
517
 
 
518
  QRegExp myProjRegExp( "\\+proj=\\S+" );
 
519
  int myStart= 0;
 
520
  int myLength=0;
 
521
  myStart = myProjRegExp.search(theProj4String, myStart);
 
522
  if (myStart==-1)
 
523
  {
 
524
    QgsLogger::warning("QgsSpatialRefSys::createFromProj4 error proj string supplied has no +proj argument");
 
525
    return mIsValidFlag;
 
526
  }
 
527
  else
 
528
  {
 
529
    myLength = myProjRegExp.matchedLength();
 
530
  }
 
531
 
 
532
  mProjectionAcronym = theProj4String.mid(myStart+PROJ_PREFIX_LEN,myLength-PROJ_PREFIX_LEN);
 
533
 
 
534
  QRegExp myEllipseRegExp( "\\+ellps=\\S+" );
 
535
  myStart= 0;
 
536
  myLength=0;
 
537
  myStart = myEllipseRegExp.search(theProj4String, myStart);
 
538
  if (myStart==-1)
 
539
  {
 
540
    std::cout << "QgsSpatialRefSys::createFromProj4 error proj string supplied has no +ellps argument" << std::endl;
 
541
 
 
542
    return mIsValidFlag;
 
543
  }
 
544
  else
 
545
  {
 
546
    myLength = myEllipseRegExp.matchedLength();
 
547
  }
 
548
  mEllipsoidAcronym = theProj4String.mid(myStart+ELLPS_PREFIX_LEN,myLength-ELLPS_PREFIX_LEN);
 
549
  //mproj4string must be set here for the rest of this method to behave in a meaningful way...
 
550
  mProj4String = theProj4String;
 
551
 
 
552
 
 
553
  /*
 
554
  * We try to match the proj string to and srsid using the following logic: 
 
555
  *
 
556
  * - perform a whole text search on srs name (if not null). The srs name will 
 
557
  *   have been set if this method has been delegated to from createFromWkt.
 
558
  * Normally we wouldnt expect this to work, but its worth trying first
 
559
  * as its quicker than methods below..
 
560
  */
 
561
  long mySrsId = 0;
 
562
  QgsSpatialRefSys::RecordMap myRecord;
 
563
  if (!mDescription.stripWhiteSpace ().isEmpty())
 
564
  {
 
565
     myRecord = getRecord("select * from tbl_srs where description='" + mDescription.stripWhiteSpace () + "'");
 
566
  }
 
567
  if (!myRecord.empty())
 
568
  {
 
569
    mySrsId=myRecord["srs_id"].toLong();
 
570
    QgsDebugMsg("QgsSpatialRefSys::createFromProj4 Projection Description match search for srsid returned srsid: "\
 
571
                + QString::number(mySrsId));
 
572
    if (mySrsId > 0)
 
573
    {
 
574
      createFromSrsId(mySrsId);
 
575
    }
 
576
  }
 
577
  else
 
578
  {
 
579
    /*
 
580
    * - if the above does not match perform a whole text search on proj4 string (if not null)
 
581
    */
 
582
    QgsDebugMsg("QgsSpatialRefSys::createFromProj4 wholetext match on name failed, trying proj4string match");
 
583
    myRecord = getRecord("select * from tbl_srs where parameters='" + mProj4String.stripWhiteSpace () + "'");
 
584
    if (!myRecord.empty())
 
585
    {
 
586
      mySrsId=myRecord["srs_id"].toLong();
 
587
      QgsDebugMsg("QgsSpatialRefSys::createFromProj4 proj4string match search for srsid returned srsid: " \
 
588
+ QString::number(mySrsId));
 
589
      if (mySrsId > 0)
 
590
      {
 
591
        createFromSrsId(mySrsId);
 
592
      }
 
593
    }
 
594
 
 
595
    else
 
596
    {
 
597
      QgsDebugMsg("QgsSpatialRefSys::createFromProj4 globbing search for srsid from this proj string");
 
598
      mySrsId = findMatchingProj();
 
599
      QgsDebugMsg("QgsSpatialRefSys::createFromProj4 globbing search for srsid returned srsid: "\
 
600
                  + QString::number(mySrsId));
 
601
      if (mySrsId > 0)
 
602
      {
 
603
        createFromSrsId(mySrsId);
 
604
      }
 
605
    }
 
606
  }
 
607
 
 
608
  /* If its still empty after all the above steps then all we can do is keep the proj string
 
609
  * with what was passed in and hope for the best...If its not empty we can fill other member details in 
 
610
    from the record*/
 
611
  return mIsValidFlag;
 
612
}
 
613
 
 
614
QgsSpatialRefSys::RecordMap QgsSpatialRefSys::getRecord(QString theSql)
 
615
{
 
616
 
 
617
  QString myDatabaseFileName;
 
618
  QgsSpatialRefSys::RecordMap myMap;
 
619
  QString myFieldName;
 
620
  QString myFieldValue;
 
621
  sqlite3      *myDatabase;
 
622
  const char   *myTail;
 
623
  sqlite3_stmt *myPreparedStatement;
 
624
  int           myResult;
 
625
 
 
626
  QgsDebugMsg("QgsSpatialRefSys::getRecord...running query: " + theSql);
 
627
  // Get the full path name to the sqlite3 spatial reference database.
 
628
  myDatabaseFileName = QgsApplication::srsDbFilePath();
 
629
 
 
630
  //check the db is available
 
631
  myResult = openDb(myDatabaseFileName, &myDatabase);
 
632
  if(myResult)
 
633
  {
 
634
    return myMap;
 
635
  }
 
636
 
 
637
  myResult = sqlite3_prepare(myDatabase, theSql.utf8(), theSql.length(), &myPreparedStatement, &myTail);
 
638
  // XXX Need to free memory from the error msg if one is set
 
639
  if(myResult == SQLITE_OK && sqlite3_step(myPreparedStatement) == SQLITE_ROW)
 
640
  {
 
641
    int myColumnCount = sqlite3_column_count(myPreparedStatement);
 
642
    //loop through each column in the record adding its field name and vvalue to the map
 
643
    for (int myColNo=0;myColNo < myColumnCount;myColNo++)
 
644
    {
 
645
      myFieldName = QString::fromUtf8((char *)sqlite3_column_name(myPreparedStatement,myColNo));
 
646
      myFieldValue = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,myColNo));
 
647
      myMap[myFieldName]=myFieldValue;
 
648
    }
 
649
  }
 
650
  else
 
651
  {
 
652
    QgsDebugMsg("QgsSpatialRefSys::getRecord...trying system users.db");
 
653
    sqlite3_finalize(myPreparedStatement);
 
654
    sqlite3_close(myDatabase);
 
655
 
 
656
    myDatabaseFileName = QgsApplication::qgisUserDbFilePath();
 
657
    QFileInfo myFileInfo;
 
658
    myFileInfo.setFile(myDatabaseFileName);
 
659
    if ( !myFileInfo.exists( ) )
 
660
    {
 
661
      QgsLogger::warning("QgsSpatialRefSys::getRecord failed :  users qgis.db not found");
 
662
      return myMap;
 
663
    }
 
664
 
 
665
    //check the db is available
 
666
    myResult = openDb(myDatabaseFileName, &myDatabase);
 
667
    if(myResult)
 
668
    {
 
669
      return myMap;
 
670
    }
 
671
 
 
672
    myResult = sqlite3_prepare(myDatabase, theSql.utf8(), theSql.length(), &myPreparedStatement, &myTail);
 
673
    // XXX Need to free memory from the error msg if one is set
 
674
    if(myResult == SQLITE_OK && sqlite3_step(myPreparedStatement) == SQLITE_ROW)
 
675
    {
 
676
      int myColumnCount = sqlite3_column_count(myPreparedStatement);
 
677
      //loop through each column in the record adding its field name and vvalue to the map
 
678
      for (int myColNo=0;myColNo < myColumnCount;myColNo++)
 
679
      {
 
680
        myFieldName = QString::fromUtf8((char *)sqlite3_column_name(myPreparedStatement,myColNo));
 
681
        myFieldValue = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,myColNo));
 
682
        myMap[myFieldName]=myFieldValue;
 
683
      }
 
684
    }
 
685
    else
 
686
    {
 
687
      QgsLogger::warning("QgsSpatialRefSys::getRecord failed :  " + theSql);
 
688
 
 
689
    }
 
690
  }
 
691
  sqlite3_finalize(myPreparedStatement);
 
692
  sqlite3_close(myDatabase);
 
693
 
 
694
#ifdef QGISDEBUG
 
695
         QgsDebugMsg("QgsSpatialRefSys::getRecord retrieved:  " + theSql);
 
696
         RecordMap::Iterator it;
 
697
         for ( it = myMap.begin(); it != myMap.end(); ++it )
 
698
           {
 
699
             QgsDebugMsgLevel(it.key() + " => " + it.data(), 2);
 
700
           }
 
701
#endif
 
702
 
 
703
  return myMap;
 
704
 
 
705
 
 
706
 
 
707
}
 
708
 
 
709
// Accessors -----------------------------------
 
710
/*! Get the SrsId
 
711
 *  @return  long theSrsId The internal sqlite3 srs.db primary key for this srs 
 
712
 */
 
713
long QgsSpatialRefSys::srsid() const
 
714
{
 
715
  return mSrsId;
 
716
}
 
717
/*! Get the Postgis SRID - if possible
 
718
 *  @return  long theSRID The internal postgis SRID for this SRS
 
719
 */
 
720
long QgsSpatialRefSys::srid() const
 
721
{
 
722
 
 
723
  return mSRID;
 
724
 
 
725
}
 
726
/*! Get the Description
 
727
 * @return  QString the Description A textual description of the srs.
 
728
 */
 
729
QString QgsSpatialRefSys::description () const
 
730
{
 
731
  if (mDescription.isNull())
 
732
  {
 
733
    return "";
 
734
  }
 
735
  else
 
736
  {
 
737
    return mDescription;
 
738
  }
 
739
}
 
740
/*! Get the Projection Acronym
 
741
 * @return  QString theProjectionAcronym The official proj4 acronym for the projection family
 
742
 */
 
743
QString QgsSpatialRefSys::projectionAcronym() const
 
744
{
 
745
  if (mProjectionAcronym.isNull())
 
746
  {
 
747
    return "";
 
748
  }
 
749
  else
 
750
  {
 
751
    return mProjectionAcronym;
 
752
  }
 
753
}
 
754
/*! Get the Ellipsoid Acronym
 
755
 * @return  QString theEllipsoidAcronym The official proj4 acronym for the ellipoid
 
756
 */
 
757
QString QgsSpatialRefSys::ellipsoidAcronym () const
 
758
{
 
759
  if (mEllipsoidAcronym.isNull())
 
760
  {
 
761
    return "";
 
762
  }
 
763
  else
 
764
  {
 
765
    return mEllipsoidAcronym;
 
766
  }
 
767
}
 
768
/* Get the Proj Proj4String.
 
769
 * @return  QString theProj4String Proj4 format specifies that define this srs.
 
770
 */
 
771
QString QgsSpatialRefSys::proj4String() const
 
772
{
 
773
  if (mProj4String.isNull())
 
774
  {
 
775
    return "";
 
776
  }
 
777
  else
 
778
  {
 
779
    return mProj4String;
 
780
  }
 
781
}
 
782
/*! Get this Geographic? flag
 
783
 * @return  bool theGeoFlag Whether this is a geographic or projected coordinate system
 
784
 */
 
785
bool QgsSpatialRefSys::geographicFlag () const
 
786
{
 
787
  return mGeoFlag;
 
788
}
 
789
/*! Get the units that the projection is in
 
790
 * @return QGis::units
 
791
 */
 
792
QGis::units QgsSpatialRefSys::mapUnits() const
 
793
{
 
794
  return mMapUnits;
 
795
}
 
796
 
 
797
/*! Set the postgis srid for this srs
 
798
 * @return  long theSRID the Postgis spatial_ref_sys identifier for this srs (defaults to 0)
 
799
 */
 
800
long QgsSpatialRefSys::postgisSrid () const
 
801
{
 
802
  return mSRID ;
 
803
}
 
804
/*! Set the EPSG identifier for this srs
 
805
 * @return  long theEpsg the ESPG identifier for this srs (defaults to 0)
 
806
 */
 
807
long QgsSpatialRefSys::epsg () const
 
808
{
 
809
  return mEpsg;
 
810
}
 
811
 
 
812
// Mutators -----------------------------------
 
813
 
 
814
 
 
815
void QgsSpatialRefSys::setSrsId(long theSrsId)
 
816
{
 
817
  mSrsId = theSrsId;
 
818
}
 
819
void QgsSpatialRefSys::setSrid(long theSrid)
 
820
{
 
821
  mSRID=theSrid;
 
822
}
 
823
void QgsSpatialRefSys::setDescription (QString theDescription)
 
824
{
 
825
  mDescription = theDescription;
 
826
}
 
827
void QgsSpatialRefSys::setProj4String (QString theProj4String)
 
828
{
 
829
  mProj4String = theProj4String;
 
830
}
 
831
void QgsSpatialRefSys::setGeographicFlag (bool theGeoFlag)
 
832
{
 
833
  mGeoFlag=theGeoFlag;
 
834
}
 
835
void QgsSpatialRefSys::setEpsg (long theEpsg)
 
836
{
 
837
  mEpsg=theEpsg;
 
838
}
 
839
void  QgsSpatialRefSys::setProjectionAcronym(QString theProjectionAcronym)
 
840
{
 
841
  mProjectionAcronym=theProjectionAcronym;
 
842
}
 
843
void  QgsSpatialRefSys::setEllipsoidAcronym(QString theEllipsoidAcronym)
 
844
{
 
845
  mEllipsoidAcronym=theEllipsoidAcronym;
 
846
}
 
847
/*! Work out the projection units and set the appropriate local variable
 
848
 *
 
849
 */
 
850
void QgsSpatialRefSys::setMapUnits()
 
851
{
 
852
  if (mProj4String.isEmpty())
 
853
  {
 
854
    QgsLogger::warning("No proj4 projection string. Unable to set map units.");
 
855
    mMapUnits = QGis::UNKNOWN;
 
856
    return;
 
857
  }
 
858
 
 
859
  char *unitName;
 
860
  OGRSpatialReference myOgrSpatialRef;
 
861
  myOgrSpatialRef.importFromProj4(mProj4String.latin1());
 
862
 
 
863
  // Of interest to us is that this call adds in a unit parameter if
 
864
  // one doesn't already exist.
 
865
  myOgrSpatialRef.Fixup();
 
866
 
 
867
  if (myOgrSpatialRef.IsProjected())
 
868
  {
 
869
    double toMeter = myOgrSpatialRef.GetLinearUnits(&unitName);
 
870
    QString unit(unitName);
 
871
 
 
872
    // If the units parameter was created during the Fixup() call
 
873
    // above, the name of the units is likely to be 'unknown'. Try to
 
874
    // do better than that ... (but perhaps ogr should be enhanced to
 
875
    // do this instead?).
 
876
 
 
877
    static const double feetToMeter = 0.3048;
 
878
    static const double smallNum = 1e-3;
 
879
 
 
880
    if (std::abs(toMeter - feetToMeter) < smallNum)
 
881
      unit = "Foot";
 
882
 
 
883
    QgsDebugMsg("Projection has linear units of " + unit);
 
884
 
 
885
    if (unit == "Meter")
 
886
      mMapUnits = QGis::METERS;
 
887
    else if (unit == "Foot")
 
888
      mMapUnits = QGis::FEET;
 
889
    else
 
890
    {
 
891
      QgsLogger::warning("Unsupported map units of " + unit);
 
892
      mMapUnits = QGis::UNKNOWN;
 
893
    }
 
894
  }
 
895
  else
 
896
  {
 
897
    myOgrSpatialRef.GetAngularUnits(&unitName);
 
898
    QString unit(unitName);
 
899
    if (unit == "degree")
 
900
      mMapUnits = QGis::DEGREES;
 
901
    else
 
902
    {
 
903
      QgsLogger::warning("Unsupported map units of " + unit);
 
904
      mMapUnits = QGis::UNKNOWN;
 
905
    }
 
906
    QgsDebugMsg("Projection has angular units of " + unit);
 
907
  }
 
908
}
 
909
 
 
910
 
 
911
/*
 
912
*    check if srs is a geocs or a proj cs (using ogr isGeographic)
 
913
*   then sequentially walk through the database (first users qgis.db srs tbl then
 
914
*   system srs.db tbl), converting each entry into an ogr srs and using isSame
 
915
*   or isSameGeocs (essentially calling the == overloaded operator). We'll try to 
 
916
*   be smart about this and first parse out the proj and ellpse strings and only 
 
917
*   check for a match in entities that have the same ellps and proj entries so 
 
918
*   that it doesnt munch yer cpu so much.
 
919
*/
 
920
long QgsSpatialRefSys::findMatchingProj()
 
921
{
 
922
  QgsDebugMsg("QgsSpatialRefSys::findMatchingProj...");
 
923
  if (mEllipsoidAcronym.isNull() ||  mProjectionAcronym.isNull() || mProj4String.isNull())
 
924
  {
 
925
    QgsLogger::warning("QgsSpatialRefSys::findMatchingProj will only work if prj acr ellipsoid acr and proj4string are set!...");
 
926
    return 0;
 
927
  }
 
928
 
 
929
  sqlite3      *myDatabase;
 
930
  const char   *myTail;
 
931
  sqlite3_stmt *myPreparedStatement;
 
932
  int           myResult;
 
933
 
 
934
  // Set up the query to retreive the projection information needed to populate the list
 
935
  QString mySql = QString ("select srs_id,parameters from tbl_srs where projection_acronym='" +
 
936
                           mProjectionAcronym + "' and ellipsoid_acronym='" + mEllipsoidAcronym + "'");
 
937
  // Get the full path name to the sqlite3 spatial reference database.
 
938
  QString myDatabaseFileName = QgsApplication::srsDbFilePath();
 
939
 
 
940
 
 
941
  //check the db is available
 
942
  myResult = openDb(myDatabaseFileName, &myDatabase);
 
943
  if(myResult)
 
944
  {
 
945
    return 0;
 
946
  }
 
947
 
 
948
  myResult = sqlite3_prepare(myDatabase, mySql.utf8(), mySql.length(), &myPreparedStatement, &myTail);
 
949
  // XXX Need to free memory from the error msg if one is set
 
950
  if(myResult == SQLITE_OK)
 
951
  {
 
952
 
 
953
    while(sqlite3_step(myPreparedStatement) == SQLITE_ROW)
 
954
    {
 
955
      QString mySrsId = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,0));
 
956
      QString myProj4String = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement, 1));
 
957
      if (this->equals(myProj4String))
 
958
      {
 
959
        QgsDebugMsg("QgsSpatialRefSys::findMatchingProj -------> MATCH FOUND in srs.db srsid: " + mySrsId);
 
960
        // close the sqlite3 statement
 
961
        sqlite3_finalize(myPreparedStatement);
 
962
        sqlite3_close(myDatabase);
 
963
        return mySrsId.toLong();
 
964
      }
 
965
      else
 
966
      {
 
967
        //std::cout << " Not matched : " << myProj4String << std::endl;
 
968
      }
 
969
    }
 
970
  }
 
971
  //std::cout << "QgsSpatialRefSys::findMatchingProj -------> no match found in srs.db, trying user db now!" << std::endl;
 
972
  // close the sqlite3 statement
 
973
  sqlite3_finalize(myPreparedStatement);
 
974
  sqlite3_close(myDatabase);
 
975
  //
 
976
  // Try the users db now
 
977
  //
 
978
 
 
979
  myDatabaseFileName = QgsApplication::qgisUserDbFilePath();
 
980
  //check the db is available
 
981
  myResult = openDb(myDatabaseFileName, &myDatabase);
 
982
  if(myResult)
 
983
  {
 
984
    return 0;
 
985
  }
 
986
 
 
987
  myResult = sqlite3_prepare(myDatabase, mySql.utf8(), mySql.length(), &myPreparedStatement, &myTail);
 
988
  // XXX Need to free memory from the error msg if one is set
 
989
  if(myResult == SQLITE_OK)
 
990
  {
 
991
 
 
992
    while(sqlite3_step(myPreparedStatement) == SQLITE_ROW)
 
993
    {
 
994
      QString mySrsId = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,0));
 
995
      QString myProj4String = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement, 1));
 
996
      if (this->equals(myProj4String))
 
997
      {
 
998
        QgsDebugMsg("QgsSpatialRefSys::findMatchingProj -------> MATCH FOUND in user qgis.db srsid: " + mySrsId);
 
999
        // close the sqlite3 statement
 
1000
        sqlite3_finalize(myPreparedStatement);
 
1001
        sqlite3_close(myDatabase);
 
1002
        return mySrsId.toLong();
 
1003
      }
 
1004
      else
 
1005
      {
 
1006
        //std::cout << " Not matched : " << myProj4String << std::endl;
 
1007
      }
 
1008
    }
 
1009
  }
 
1010
  QgsLogger::warning("QgsSpatialRefSys::findMatchingProj -------> no match found in user db");
 
1011
 
 
1012
  // close the sqlite3 statement
 
1013
  sqlite3_finalize(myPreparedStatement);
 
1014
  sqlite3_close(myDatabase);
 
1015
  return 0;
 
1016
 
 
1017
}
 
1018
 
 
1019
bool QgsSpatialRefSys::operator==(const QgsSpatialRefSys &theSrs)
 
1020
{
 
1021
  //qWarning("QgsSpatialRefSys::operator==(const QgsSpatialRefSys &theSrs) called ");
 
1022
  //simply delegate to the overloaded == operator  below...
 
1023
  return this->equals(theSrs.mProj4String);
 
1024
 
 
1025
}
 
1026
 
 
1027
bool QgsSpatialRefSys::equals(QString theProj4CharArray)
 
1028
{
 
1029
  //qWarning("QgsSpatialRefSys::operator==(const char *theProj4CharArray) called ");
 
1030
  bool myMatchFlag = false; //guilty until proven innocent
 
1031
 
 
1032
  /* Here are the possible OGR error codes :
 
1033
     typedef int OGRErr;
 
1034
 
 
1035
     #define OGRERR_NONE                0
 
1036
     #define OGRERR_NOT_ENOUGH_DATA     1    --> not enough data to deserialize
 
1037
     #define OGRERR_NOT_ENOUGH_MEMORY   2
 
1038
     #define OGRERR_UNSUPPORTED_GEOMETRY_TYPE 3
 
1039
     #define OGRERR_UNSUPPORTED_OPERATION 4
 
1040
     #define OGRERR_CORRUPT_DATA        5
 
1041
     #define OGRERR_FAILURE             6
 
1042
     #define OGRERR_UNSUPPORTED_SRS     7 */
 
1043
 
 
1044
  //get the wkt into ogr
 
1045
  //this is really ugly but we need to get a QString to a char**
 
1046
  const char *myCharArrayPointer1 = mProj4String.latin1();
 
1047
 
 
1048
  //note that the proj strings above do not neccessarily need to be exactly the
 
1049
  //same for the projections they define to be equivalent, which is why I dont just
 
1050
  //compare the proj parameter strings and return the result
 
1051
 
 
1052
 
 
1053
  //create the sr and populate it from a wkt proj definition
 
1054
  OGRSpatialReference myOgrSpatialRef1;
 
1055
  OGRSpatialReference myOgrSpatialRef2;
 
1056
  OGRErr myInputResult1 = myOgrSpatialRef1.importFromProj4(  myCharArrayPointer1 );
 
1057
  OGRErr myInputResult2 = myOgrSpatialRef2.importFromProj4(  theProj4CharArray.latin1() );
 
1058
 
 
1059
  if (myOgrSpatialRef1.IsGeographic() && myOgrSpatialRef2.IsGeographic())
 
1060
  {
 
1061
//    qWarning("QgsSpatialRefSys::operator== srs1 and srs2 are geographic ");
 
1062
    myMatchFlag = myOgrSpatialRef1.IsSameGeogCS(&myOgrSpatialRef2);
 
1063
  }
 
1064
  else if (myOgrSpatialRef1.IsProjected() && myOgrSpatialRef2.IsProjected())
 
1065
  {
 
1066
//    qWarning("QgsSpatialRefSys::operator== srs1 and srs2 are projected ");
 
1067
    myMatchFlag = myOgrSpatialRef1.IsSame(&myOgrSpatialRef2);
 
1068
  } else {
 
1069
//    qWarning("QgsSpatialRefSys::operator== srs1 and srs2 are different types ");
 
1070
    myMatchFlag = false;
 
1071
  }
 
1072
 
 
1073
  //find out the units:
 
1074
  /* Not needed anymore here - keeping here as a note because I am gonna use it elsewhere
 
1075
  const char *myUnitsArrayPointer1;
 
1076
  const char *myUnitsArrayPointer2;
 
1077
  OGRErr myUnitsValid1 = myOgrSpatialRef1.GetLinearUnits(&myUnitsArrayPointer1 );
 
1078
  OGRErr myUnitsValid2 = myOgrSpatialRef2.GetLinearUnits(&myUnitsArrayPointer2 );
 
1079
  QString myUnitsString1(myUnitsArrayPointer1);
 
1080
  QString myUnitsString2(myUnitsArrayPointer2);
 
1081
  */
 
1082
 
 
1083
 
 
1084
 
 
1085
 
 
1086
  //placeholder to be replaced with ogr tests
 
1087
  if (myMatchFlag)
 
1088
  {
 
1089
//    qWarning("QgsSpatialRefSys::operator== result: srs's are equal ");
 
1090
  }
 
1091
  else
 
1092
  {
 
1093
//    qWarning("QgsSpatialRefSys::operator== result: srs's are not equal ");
 
1094
  }
 
1095
  return myMatchFlag;
 
1096
}
 
1097
 
 
1098
OGRSpatialReference QgsSpatialRefSys::toOgrSrs()
 
1099
{
 
1100
  OGRSpatialReference myOgrSpatialRef1;
 
1101
  OGRErr myInputResult1 = myOgrSpatialRef1.importFromProj4(mProj4String.latin1());
 
1102
  return myOgrSpatialRef1;
 
1103
}
 
1104
 
 
1105
bool QgsSpatialRefSys::readXML( QDomNode & theNode )
 
1106
{
 
1107
  QgsDebugMsg("Reading Spatial Ref Sys from xml ------------------------!");
 
1108
     QDomNode myNode = theNode.namedItem("proj4");
 
1109
     QDomElement myElement = myNode.toElement();
 
1110
     setProj4String(myElement.text());
 
1111
 
 
1112
     myNode = theNode.namedItem("srsid");
 
1113
     myElement = myNode.toElement();
 
1114
     setSrsId(myElement.text().toLong());
 
1115
 
 
1116
     myNode = theNode.namedItem("srid");
 
1117
     myElement = myNode.toElement();
 
1118
     setSrid(myElement.text().toLong());
 
1119
 
 
1120
     myNode = theNode.namedItem("epsg");
 
1121
     myElement = myNode.toElement();
 
1122
     setEpsg(myElement.text().toLong());
 
1123
 
 
1124
     myNode = theNode.namedItem("description");
 
1125
     myElement = myNode.toElement();
 
1126
     setDescription(myElement.text());
 
1127
 
 
1128
     myNode = theNode.namedItem("projectionacronym");
 
1129
     myElement = myNode.toElement();
 
1130
     setProjectionAcronym(myElement.text());
 
1131
 
 
1132
     myNode = theNode.namedItem("ellipsoidacronym");
 
1133
     myElement = myNode.toElement();
 
1134
     setEllipsoidAcronym(myElement.text());
 
1135
 
 
1136
     myNode = theNode.namedItem("geographicflag");
 
1137
     myElement = myNode.toElement();
 
1138
     if (myElement.text().compare("true"))
 
1139
     {
 
1140
       setGeographicFlag(true);
 
1141
     }
 
1142
     else
 
1143
     {
 
1144
       setGeographicFlag(false);
 
1145
     }
 
1146
     //make sure the map units have been set
 
1147
 
 
1148
     setMapUnits();
 
1149
 
 
1150
     //@TODO this srs needs to be validated!!!
 
1151
     mIsValidFlag=true;//shamelessly hard coded for now
 
1152
      
 
1153
#ifdef WIN32
 
1154
         return true;
 
1155
#endif
 
1156
 
 
1157
}
 
1158
 
 
1159
bool QgsSpatialRefSys::writeXML( QDomNode & theNode, QDomDocument & theDoc )
 
1160
{
 
1161
 
 
1162
  QDomElement myLayerNode = theNode.toElement();
 
1163
  QDomElement mySrsElement  = theDoc.createElement( "spatialrefsys" );
 
1164
  
 
1165
  QDomElement myProj4Element  = theDoc.createElement( "proj4" );
 
1166
  myProj4Element.appendChild(theDoc.createTextNode( proj4String()));
 
1167
  mySrsElement.appendChild(myProj4Element);
 
1168
  
 
1169
  QDomElement mySrsIdElement  = theDoc.createElement( "srsid" );
 
1170
  mySrsIdElement.appendChild(theDoc.createTextNode( QString::number(srsid())));
 
1171
  mySrsElement.appendChild(mySrsIdElement);
 
1172
 
 
1173
  QDomElement mySridElement  = theDoc.createElement( "srid" );
 
1174
  mySridElement.appendChild(theDoc.createTextNode( QString::number(srid())));
 
1175
  mySrsElement.appendChild(mySridElement);
 
1176
 
 
1177
  QDomElement myEpsgElement  = theDoc.createElement( "epsg" );
 
1178
  myEpsgElement.appendChild(theDoc.createTextNode( QString::number(epsg())));
 
1179
  mySrsElement.appendChild(myEpsgElement);
 
1180
 
 
1181
  QDomElement myDescriptionElement  = theDoc.createElement( "description" );
 
1182
  myDescriptionElement.appendChild(theDoc.createTextNode( description()));
 
1183
  mySrsElement.appendChild(myDescriptionElement);
 
1184
 
 
1185
  QDomElement myProjectionAcronymElement  = theDoc.createElement( "projectionacronym" );
 
1186
  myProjectionAcronymElement.appendChild(theDoc.createTextNode( projectionAcronym()));
 
1187
  mySrsElement.appendChild(myProjectionAcronymElement);
 
1188
 
 
1189
  QDomElement myEllipsoidAcronymElement  = theDoc.createElement( "ellipsoidacronym" );
 
1190
  myEllipsoidAcronymElement.appendChild(theDoc.createTextNode( ellipsoidAcronym()));
 
1191
  mySrsElement.appendChild(myEllipsoidAcronymElement);
 
1192
 
 
1193
  QDomElement myGeographicFlagElement  = theDoc.createElement( "geographicflag" );
 
1194
  QString myGeoFlagText = "false";
 
1195
  if (geographicFlag())
 
1196
  {
 
1197
    myGeoFlagText="true";
 
1198
  }
 
1199
    
 
1200
  myGeographicFlagElement.appendChild(theDoc.createTextNode( myGeoFlagText ));
 
1201
  mySrsElement.appendChild(myGeographicFlagElement);
 
1202
 
 
1203
  myLayerNode.appendChild( mySrsElement );
 
1204
#ifdef WIN32
 
1205
  return true;
 
1206
#endif
 
1207
 
 
1208
}
 
1209
 
 
1210
 
 
1211
 
 
1212
//
 
1213
// Static helper methods below this point only please!
 
1214
//
 
1215
 
 
1216
 
 
1217
// Returns the whole proj4 string for the selected srsid
 
1218
//this is a static method!
 
1219
QString QgsSpatialRefSys::getProj4FromSrsId(const int theSrsId)
 
1220
{
 
1221
 
 
1222
      QString myDatabaseFileName;
 
1223
      QString myProjString;
 
1224
      QString mySql = "select parameters from tbl_srs where srs_id = ";
 
1225
      mySql += QString::number(theSrsId);
 
1226
 
 
1227
      QgsDebugMsg("QgsSpatialRefSys::getProj4FromSrsId :  mySrsId = " + QString::number(theSrsId));
 
1228
      QgsDebugMsg("QgsSpatialRefSys::getProj4FromSrsId :  USER_PROJECTION_START_ID = " +\
 
1229
QString::number(USER_PROJECTION_START_ID));
 
1230
      QgsDebugMsg("QgsSpatialRefSys::getProj4FromSrsId :Selection sql : " + mySql);
 
1231
          
 
1232
      //
 
1233
      // Determine if this is a user projection or a system on
 
1234
      // user projection defs all have srs_id >= 100000
 
1235
      //
 
1236
      if (theSrsId >= USER_PROJECTION_START_ID)
 
1237
      {
 
1238
        myDatabaseFileName = QgsApplication::qgisUserDbFilePath();
 
1239
        QFileInfo myFileInfo;
 
1240
        myFileInfo.setFile(myDatabaseFileName);
 
1241
        if ( !myFileInfo.exists( ) ) //its unlikely that this condition will ever be reached
 
1242
        {
 
1243
          QgsLogger::critical("QgsSpatialRefSys::getProj4FromSrsId :  users qgis.db not found");
 
1244
          return NULL;
 
1245
        }
 
1246
      }
 
1247
      else //must be  a system projection then
 
1248
      {
 
1249
        myDatabaseFileName = QgsApplication::srsDbFilePath();
 
1250
      }
 
1251
      QgsDebugMsg("QgsSpatialRefSys::getProj4FromSrsId db = " + myDatabaseFileName);
 
1252
 
 
1253
      sqlite3 *db;
 
1254
      int rc;
 
1255
      rc = openDb(myDatabaseFileName, &db);
 
1256
      if(rc)
 
1257
      {
 
1258
        return QString();
 
1259
      }
 
1260
      // prepare the sql statement
 
1261
      const char *pzTail;
 
1262
      sqlite3_stmt *ppStmt;
 
1263
 
 
1264
      rc = sqlite3_prepare(db, mySql.utf8(), mySql.length(), &ppStmt, &pzTail);
 
1265
      // XXX Need to free memory from the error msg if one is set
 
1266
 
 
1267
      if(rc == SQLITE_OK)
 
1268
      {
 
1269
        if(sqlite3_step(ppStmt) == SQLITE_ROW)
 
1270
        {
 
1271
          myProjString = QString::fromUtf8((char*)sqlite3_column_text(ppStmt, 0));
 
1272
        }
 
1273
      }
 
1274
      // close the statement
 
1275
      sqlite3_finalize(ppStmt);
 
1276
      // close the database
 
1277
      sqlite3_close(db);
 
1278
 
 
1279
      //assert(myProjString.length() > 0);
 
1280
      return myProjString;
 
1281
}
 
1282
 
 
1283
int QgsSpatialRefSys::openDb(QString path, sqlite3 **db)
 
1284
{
 
1285
  QgsDebugMsg("QgsSpatialRefSys::openDb path = " + path);
 
1286
  int myResult = sqlite3_open(path.toLocal8Bit().data(), db);
 
1287
 
 
1288
  if(myResult)
 
1289
  {
 
1290
    QgsLogger::critical("Can't open database: " + QString(sqlite3_errmsg(*db)));
 
1291
    // XXX This will likely never happen since on open, sqlite creates the
 
1292
    //     database if it does not exist.
 
1293
    // ... unfortunately it happens on Windows
 
1294
    QMessageBox::warning(0,"Error","Could not open SRS database "
 
1295
                + path + "<br>Error(" + QString::number(myResult)
 
1296
                + "): " + QString(sqlite3_errmsg(*db)) ); 
 
1297
    
 
1298
  }
 
1299
  return myResult;
 
1300
}