[QGIS Commit] r8263 - in trunk/qgis: python/core src/core

svn_qgis at osgeo.org svn_qgis at osgeo.org
Mon Mar 24 14:31:09 EDT 2008


Author: jef
Date: 2008-03-24 14:31:08 -0400 (Mon, 24 Mar 2008)
New Revision: 8263

Modified:
   trunk/qgis/python/core/qgsspatialrefsys.sip
   trunk/qgis/src/core/qgsspatialrefsys.cpp
   trunk/qgis/src/core/qgsspatialrefsys.h
Log:
- speed up QgsSpatialRefSys after migration to OGR C-API:
  - create and destroy OGRSpatialReferenceH in constructor/destructor
  - move the PROJ.4 strings to OGR instead of a member variable and keep
    track its validity in mIsValidFlag.
  This reduces the need to allocate/deallocate of OGR structures and PROJ.4
  parsing and thereby speeds it up quite a bit.  Especially when on-the-fly
  projection is in use.
- collect common code of createFromSrid, createFromEpsg and createFromSrsId
  in the new loadFromDb method

NOTE: invalid PROJ.4 strings are now lost, I hope that doesn't break
      anything.


Modified: trunk/qgis/python/core/qgsspatialrefsys.sip
===================================================================
--- trunk/qgis/python/core/qgsspatialrefsys.sip	2008-03-24 16:22:32 UTC (rev 8262)
+++ trunk/qgis/python/core/qgsspatialrefsys.sip	2008-03-24 18:31:08 UTC (rev 8263)
@@ -20,6 +20,8 @@
         
         //! Default constructor
         QgsSpatialRefSys();
+
+        ~QgsSpatialRefSys();
         
         /*! 
          * Constructs a SRS object from a WKT string
@@ -34,7 +36,6 @@
          */
         QgsSpatialRefSys(const long theId, SRS_TYPE theType=POSTGIS_SRID);
 
-
         // Misc helper functions -----------------------
 
         void createFromId(const long theId, SRS_TYPE theType=POSTGIS_SRID);

Modified: trunk/qgis/src/core/qgsspatialrefsys.cpp
===================================================================
--- trunk/qgis/src/core/qgsspatialrefsys.cpp	2008-03-24 16:22:32 UTC (rev 8262)
+++ trunk/qgis/src/core/qgsspatialrefsys.cpp	2008-03-24 18:31:08 UTC (rev 8263)
@@ -45,13 +45,14 @@
   : mMapUnits(QGis::UNKNOWN),
     mIsValidFlag(0)
 {
-  // NOOP
+  mSRS = OSRNewSpatialReference(NULL);
 }
 
 QgsSpatialRefSys::QgsSpatialRefSys(QString theWkt)
   : mMapUnits(QGis::UNKNOWN),
     mIsValidFlag(0)
 {
+  mSRS = OSRNewSpatialReference(NULL);
   createFromWkt(theWkt);
 }
 
@@ -60,9 +61,15 @@
   : mMapUnits(QGis::UNKNOWN),
     mIsValidFlag(0)
 {
+  mSRS = OSRNewSpatialReference(NULL);
   createFromId(theId, theType);
 }
 
+QgsSpatialRefSys::~QgsSpatialRefSys()
+{
+  OSRDestroySpatialReference( mSRS );
+}
+
 void QgsSpatialRefSys::createFromId(const long theId, SRS_TYPE theType)
 {
   switch (theType)
@@ -80,10 +87,8 @@
     //THIS IS BAD...THIS PART OF CODE SHOULD NEVER BE REACHED...
     QgsLogger::critical("Unexpected case reached in " + QString(__FILE__) + " : " + QString(__LINE__));
   };
-
 }
 
-
 bool QgsSpatialRefSys::createFromOgcWmsCrs(QString theCrs)
 {
   QStringList parts = theCrs.split(":");
@@ -111,6 +116,11 @@
   return TRUE;
 }
 
+QgsSpatialRefSys::QgsSpatialRefSys(const QgsSpatialRefSys &srs)
+{
+  mSRS = OSRNewSpatialReference(NULL);
+  *this = srs;
+}
 
 // Assignment operator
 QgsSpatialRefSys& QgsSpatialRefSys::operator=(const QgsSpatialRefSys& srs)
@@ -121,12 +131,18 @@
     mDescription = srs.mDescription;
     mProjectionAcronym = srs.mProjectionAcronym;
     mEllipsoidAcronym = srs.mEllipsoidAcronym;
-    mProj4String = srs.mProj4String;
     mGeoFlag = srs.mGeoFlag;
     mMapUnits = srs.mMapUnits;
     mSRID = srs.mSRID;
     mEpsg = srs.mEpsg;
     mIsValidFlag = srs.mIsValidFlag;
+    if(mIsValidFlag)
+    {
+      char *proj4src = NULL;
+      OSRExportToProj4(srs.mSRS, &proj4src);
+      OSRImportFromProj4(mSRS, proj4src);
+      CPLFree(proj4src);
+    }
   }
   return *this;
 }
@@ -136,99 +152,55 @@
 
 void QgsSpatialRefSys::validate()
 {
-  QgsDebugMsg("QgsSpatialRefSys::validate");
-  //dont bother trying to do an initial test with gdal if
-  //the proj4String is not even populated
-  if (QString::null!=mProj4String && !mProj4String.isEmpty())
-  {
-    //first of all use gdal to test if this is an ok srs already
-    //if not we will prompt the user for and srs
-    //then retest using gdal
-    //if the retest fails we will then set  this srs to the GEOCS/WGS84 default
-    QgsDebugMsg("Use GDAL to vaildate");
+  if(mIsValidFlag)
+    return;
 
-    /* Here are the possible OGR error codes :
-       typedef int OGRErr;
-
-       #define OGRERR_NONE                0
-       #define OGRERR_NOT_ENOUGH_DATA     1    --> not enough data to deserialize
-       #define OGRERR_NOT_ENOUGH_MEMORY   2
-       #define OGRERR_UNSUPPORTED_GEOMETRY_TYPE 3
-       #define OGRERR_UNSUPPORTED_OPERATION 4
-       #define OGRERR_CORRUPT_DATA        5
-       #define OGRERR_FAILURE             6
-       #define OGRERR_UNSUPPORTED_SRS     7 */
-
-    //get the wkt into ogr
-    //this is really ugly but we need to get a QString to a char**
-    const char *mySourceCharArrayPointer = mProj4String.latin1();
-    //create the sr and populate it from a wkt proj definition
-    OGRSpatialReferenceH myOgrSpatialRef = OSRNewSpatialReference(NULL);
-    
-    OGRErr myInputResult = 
-        OSRImportFromProj4( myOgrSpatialRef, mySourceCharArrayPointer );
-
-    OSRDestroySpatialReference( myOgrSpatialRef );
-
-    if (myInputResult==OGRERR_NONE)
-    {
-      //srs is valid so nothing more to do...
-      createFromProj4(mProj4String);
-      return;
-    }
-  }
-
   // try to validate using custom validation routines
   if (mCustomSrsValidation)
     mCustomSrsValidation(this);
 
-  //
-  // This is the second check after the user assigned SRS has been retrieved
-  // If it still does not work, we will simply use the QgsSpatialRefSys const GEOPROJ4 for the job
-  //
+  if(!mIsValidFlag)
+    // set the default
+    createFromProj4(GEOPROJ4);  
+}
 
-  //this is really ugly but we need to get a QString to a char**
-  const char *mySourceCharArrayPointer = mProj4String.latin1();
-  //create the sr and populate it from a wkt proj definition
-  OGRSpatialReferenceH myOgrSpatialRef = OSRNewSpatialReference(NULL);
-  OGRErr myInputResult = OSRImportFromProj4( myOgrSpatialRef, mySourceCharArrayPointer );
+bool QgsSpatialRefSys::createFromSrid(long id)
+{
+  return loadFromDb( QgsApplication::srsDbFilePath(), "srid", id);
+}
 
-  OSRDestroySpatialReference( myOgrSpatialRef );
+bool QgsSpatialRefSys::createFromEpsg(long id)
+{
+  return loadFromDb( QgsApplication::srsDbFilePath(), "epsg", id);
+}
 
-  if (! myInputResult==OGRERR_NONE)
-  {
-    //default to proj 4..if all else fails we will use that for this srs
-    mProj4String = GEOPROJ4;
-  }
-  createFromProj4(mProj4String);  
-
+bool QgsSpatialRefSys::createFromSrsId(long id)
+{
+  return loadFromDb( id<100000 ? QgsApplication::srsDbFilePath() : QgsApplication::qgisUserDbFilePath(), "srs_id", id);
 }
 
-bool QgsSpatialRefSys::createFromSrid(long theSrid)
+bool QgsSpatialRefSys::loadFromDb(QString db, QString field, long id)
 {
-  QgsDebugMsg("QgsSpatialRefSys::createFromSrid");
+  QgsDebugMsg("load SRS from " + db + " where " + field + " is " + QString::number(id));
+  mIsValidFlag=false;
 
-  // Get the full path name to the sqlite3 spatial reference database.
-  QString myDatabaseFileName = QgsApplication::srsDbFilePath();
-
-  QFileInfo myInfo (myDatabaseFileName);
-  if (!myInfo.exists())
+  QFileInfo myInfo(db);
+  if(!myInfo.exists())
   {
-    QgsDebugMsg("QgsSpatialRefSys::createFromSrid failed : " + myDatabaseFileName + 
-        " does not exist!");
-    return false;
+    QgsDebugMsg("failed : " + db + " does not exist!");
+    return mIsValidFlag;
   }
 
-
   sqlite3      *myDatabase;
   const char   *myTail;
   sqlite3_stmt *myPreparedStatement;
   int           myResult;
   //check the db is available
-  myResult = openDb(myDatabaseFileName, &myDatabase);
+  myResult = openDb(db, &myDatabase);
   if(myResult)
   {
-      return false;
+    QgsDebugMsg("failed : " + db + " could not be opened!");
+    return mIsValidFlag;
   }
 
   /*
@@ -242,7 +214,7 @@
     is_geo integer NOT NULL);
   */
 
-  QString mySql = "select srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,epsg,is_geo from tbl_srs where srid='" + QString::number(theSrid) + "'";
+  QString mySql = "select srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,epsg,is_geo from tbl_srs where " + field + "='" + QString::number(id) + "'";
   myResult = sqlite3_prepare(myDatabase, mySql.utf8(), mySql.length(), &myPreparedStatement, &myTail);
   // XXX Need to free memory from the error msg if one is set
   if(myResult == SQLITE_OK && sqlite3_step(myPreparedStatement) == SQLITE_ROW)
@@ -251,19 +223,18 @@
     mDescription = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,1));
     mProjectionAcronym = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,2));
     mEllipsoidAcronym = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,3));
-    mProj4String = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,4));
+    QString proj4String = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,4));
     mSRID = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,5)).toLong();
     mEpsg = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,6)).toLong();
     int geo = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,7)).toInt();
     mGeoFlag = (geo == 0 ? false : true);
     setMapUnits();
     mIsValidFlag = true;
-
+    OSRImportFromProj4( mSRS, (const char *)proj4String.latin1() );
   }
   else
   {
-    QgsDebugMsg("QgsSpatialRefSys::createFromSrid failed : " + mySql);
-    mIsValidFlag = false;
+    QgsDebugMsg("failed : " + mySql);
   }
   sqlite3_finalize(myPreparedStatement);
   sqlite3_close(myDatabase);
@@ -272,32 +243,20 @@
 
 bool QgsSpatialRefSys::createFromWkt(QString theWkt)
 {
+  mIsValidFlag = false;
+
   if (theWkt.isEmpty())
   {
     QgsDebugMsg("QgsSpatialRefSys::createFromWkt -- theWkt is uninitialised, operation failed")
     QgsLogger::critical("QgsSpatialRefSys::createFromWkt -- theWkt is uninitialised, operation failed");
-    mIsValidFlag = false;
-    return false;
+    return mIsValidFlag;
   }
   QgsDebugMsg("QgsSpatialRefSys::createFromWkt(QString theWkt) using: " + theWkt);
   //this is really ugly but we need to get a QString to a char**
-  const char *myCharArrayPointer = theWkt.latin1(); //Why doesn't it work with toLocal8Bit().data()?
-  char *pWkt = (char *)myCharArrayPointer;
-  /* Here are the possible OGR error codes :
-     typedef int OGRErr;
-     #define OGRERR_NONE                0
-     #define OGRERR_NOT_ENOUGH_DATA     1    --> not enough data to deserialize 
-     #define OGRERR_NOT_ENOUGH_MEMORY   2
-     #define OGRERR_UNSUPPORTED_GEOMETRY_TYPE 3
-     #define OGRERR_UNSUPPORTED_OPERATION 4
-     #define OGRERR_CORRUPT_DATA        5
-     #define OGRERR_FAILURE             6
-     #define OGRERR_UNSUPPORTED_SRS     7 
-  */
+  char *pWkt = (char *)theWkt.latin1();
 
-  OGRSpatialReferenceH myOgrSpatialRef = OSRNewSpatialReference( NULL );
+  OGRErr myInputResult = OSRImportFromWkt( mSRS, &pWkt );
 
-  OGRErr myInputResult = OSRImportFromWkt( myOgrSpatialRef, &pWkt );
   if (myInputResult != OGRERR_NONE)
   {
     QgsDebugMsg("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
@@ -305,20 +264,16 @@
     QgsDebugMsg("This SRS could *** NOT *** be set from the supplied WKT ");
     QgsDebugMsg("INPUT: " + theWkt);
     QgsDebugMsg("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
-    mIsValidFlag = false;
-    OSRDestroySpatialReference( myOgrSpatialRef );
-    return false;
+    return mIsValidFlag;
   }
 
-
   // always morph from esri as it doesn't hurt anything
   // FW: Hey, that's not right!  It can screw stuff up! Disable
   //myOgrSpatialRef.morphFromESRI();
 
   // create the proj4 structs needed for transforming
   char *proj4src = NULL;
-  OSRExportToProj4(myOgrSpatialRef, &proj4src);
-  OSRDestroySpatialReference( myOgrSpatialRef );
+  OSRExportToProj4(mSRS, &proj4src);
 
   //now that we have the proj4string, delegate to createFromProj4String so
   // that we can try to fill in the remaining class members...
@@ -330,173 +285,18 @@
   //setMapunits will be called by createfromproj above
 }
 
-bool QgsSpatialRefSys::createFromEpsg(long theEpsg)
+bool QgsSpatialRefSys::isValid() const
 {
-  QgsDebugMsg("QgsSpatialRefSys::createFromEpsg with " + QString::number(theEpsg));
-  // Get the full path name to the sqlite3 spatial reference database.
-  QString myDatabaseFileName = QgsApplication::srsDbFilePath();
+  if (mIsValidFlag)
+    return true;
 
+  QgsDebugMsg("It's an invalid SRS without valid proj4 string");
 
-  sqlite3      *myDatabase;
-  const char   *myTail;
-  sqlite3_stmt *myPreparedStatement;
-  int           myResult;
-  //check the db is available
-  myResult = openDb(myDatabaseFileName, &myDatabase);
-  if(myResult)
-  {
-      return false;
-  }
-
-  /*
-    srs_id INTEGER PRIMARY KEY,
-    description text NOT NULL,
-    projection_acronym text NOT NULL,
-    ellipsoid_acronym NOT NULL,
-    parameters text NOT NULL,
-    srid integer NOT NULL,
-    epsg integer NOT NULL,
-    is_geo integer NOT NULL);
-  */
-
-  QString mySql = "select srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,epsg,is_geo from tbl_srs where epsg='" + QString::number(theEpsg) + "'";
-  myResult = sqlite3_prepare(myDatabase, mySql.utf8(), mySql.length(), &myPreparedStatement, &myTail);
-  // XXX Need to free memory from the error msg if one is set
-  if(myResult == SQLITE_OK && sqlite3_step(myPreparedStatement) == SQLITE_ROW)
-  {
-    mSrsId = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,0)).toLong();
-    mDescription = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,1));
-    mProjectionAcronym = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,2));
-    mEllipsoidAcronym = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,3));
-    mProj4String = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,4));
-    mSRID = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,5)).toLong();
-    mEpsg = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,6)).toLong();
-    int geo = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,7)).toInt();
-    mGeoFlag = (geo == 0 ? false : true);
-    setMapUnits();
-    mIsValidFlag = true;
-
-  }
-  else
-  {
-    QgsLogger::critical(" QgsSpatialRefSys::createFromEpsg failed :  " + mySql);
-    mIsValidFlag = false;
-  }
-  sqlite3_finalize(myPreparedStatement);
-  sqlite3_close(myDatabase);
-  return mIsValidFlag;
+  return false;
 }
 
-
-bool QgsSpatialRefSys::createFromSrsId (long theSrsId)
-{
-  QgsDebugMsg("QgsSpatialRefSys::createFromSrsId");
-  QString myDatabaseFileName;
-  //
-  // Determine if this is a user projection or a system on
-  // user projection defs all have srs_id >= 100000
-  //
-  if (theSrsId>= USER_PROJECTION_START_ID)
-  {
-    myDatabaseFileName = QgsApplication::qgisUserDbFilePath();
-    QFileInfo myFileInfo;
-    myFileInfo.setFile(myDatabaseFileName);
-    if ( !myFileInfo.exists( ) )
-    {
-      mIsValidFlag = false;
-      QgsLogger::warning("QgsSpatialRefSys::createFromSrid failed :  users qgis.db not found");
-      return mIsValidFlag;
-    }
-  }
-  else //must be  a system projection then
-  {
-    // Get the full path name to the sqlite3 spatial reference database.
-    myDatabaseFileName = QgsApplication::srsDbFilePath();
-  }
-
-
-  sqlite3      *myDatabase;
-  const char   *myTail;
-  sqlite3_stmt *myPreparedStatement;
-  int           myResult;
-  //check the db is available
-  myResult = openDb(myDatabaseFileName, &myDatabase);
-  if(myResult)
-  {
-      return false;
-  }
-
-  /*
-    srs_id INTEGER PRIMARY KEY,
-    description text NOT NULL,
-    projection_acronym text NOT NULL,
-    ellipsoid_acronym NOT NULL,
-    parameters text NOT NULL,
-    srid integer NOT NULL,
-    epsg integer NOT NULL,
-    is_geo integer NOT NULL);
-  */
-
-  QString mySql = "select srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,epsg,is_geo from tbl_srs where srs_id='" + QString::number(theSrsId) + "'";
-  myResult = sqlite3_prepare(myDatabase, mySql.utf8(), mySql.length(), &myPreparedStatement, &myTail);
-  // XXX Need to free memory from the error msg if one is set
-  if(myResult == SQLITE_OK && sqlite3_step(myPreparedStatement) == SQLITE_ROW)
-  {
-    mSrsId = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,0)).toLong();
-    mDescription = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,1));
-    mProjectionAcronym = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,2));
-    mEllipsoidAcronym = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,3));
-    mProj4String = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,4));
-    mSRID = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,5)).toLong();
-    mEpsg = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,6)).toLong();
-    int geo = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,7)).toInt();
-    mGeoFlag = (geo == 0 ? false : true);
-    setMapUnits();
-    mIsValidFlag = true;
-  }
-  else
-  {
-    QgsLogger::warning("QgsSpatialRefSys::createFromSrsId failed :  " + mySql);
-    mIsValidFlag = false;
-  }
-  sqlite3_finalize(myPreparedStatement);
-  sqlite3_close(myDatabase);
-  return mIsValidFlag;
-}
-
-
-
-
-
-bool QgsSpatialRefSys::isValid() const
-{
-  if (mProj4String.isEmpty())
-    return false;
-
-  //this is really ugly but we need to get a QString to a char**
-  const char *mySourceCharArrayPointer = mProj4String.latin1();
-  //create the sr and populate it from a wkt proj definition
-  OGRSpatialReferenceH myOgrSpatialRef = OSRNewSpatialReference( NULL );
-  OGRErr myResult = OSRImportFromProj4( myOgrSpatialRef, mySourceCharArrayPointer );
-  OSRDestroySpatialReference( myOgrSpatialRef );
-  if (myResult==OGRERR_NONE)
-  {
-    //QgsDebugMsg("The OGRe says it's a valid SRS with proj4 string: " +  mProj4String);
-    //srs is valid so nothing more to do...
-    return true;
-  }
-  else
-  {
-    QgsDebugMsg("The OGRe says it's an invalid SRS (OGRErr = "
-                + QString::number(myResult)
-                + ") with proj4 string: " + mProj4String);
-    return false;
-  }
-}
-
 bool QgsSpatialRefSys::createFromProj4 (const QString theProj4String)
 {
-
   //
   // Examples:
   // +proj=tmerc +lat_0=0 +lon_0=-62 +k=0.999500 +x_0=400000 +y_0=0
@@ -513,7 +313,7 @@
   myStart = myProjRegExp.search(theProj4String, myStart);
   if (myStart==-1)
   {
-    QgsLogger::warning("QgsSpatialRefSys::createFromProj4 error proj string supplied has no +proj argument");
+    QgsDebugMsg("error proj string supplied has no +proj argument");
     return mIsValidFlag;
   }
   else
@@ -540,13 +340,9 @@
   if (myStart==-1 && mEllipsoidAcronym.isNull())
   {
     QgsLogger::warning("QgsSpatialRefSys::createFromProj4 error proj string supplied has no +ellps or +a argument");
-
     return mIsValidFlag;
   }
-  //mproj4string must be set here for the rest of this method to behave in a meaningful way...
-  mProj4String = theProj4String;
 
-
   /*
   * We try to match the proj string to and srsid using the following logic: 
   *
@@ -559,15 +355,18 @@
   QgsSpatialRefSys::RecordMap myRecord;
   if (!mDescription.stripWhiteSpace ().isEmpty())
   {
-     myRecord = getRecord("select * from tbl_srs where description='" + mDescription.stripWhiteSpace () + "'");
+    myRecord = getRecord("select * from tbl_srs where description='" + mDescription.stripWhiteSpace () + "'");
   }
-//  if (!myRecord.empty())
-// What if descriptions aren't unique?
-  if (false)
+
+  /*
+  * - if the above does not match perform a whole text search on proj4 string (if not null)
+  */
+  QgsDebugMsg("QgsSpatialRefSys::createFromProj4 wholetext match on name failed, trying proj4string match");
+  myRecord = getRecord("select * from tbl_srs where parameters='" + theProj4String.stripWhiteSpace () + "'");
+  if (!myRecord.empty())
   {
     mySrsId=myRecord["srs_id"].toLong();
-    QgsDebugMsg("QgsSpatialRefSys::createFromProj4 Projection Description match search for srsid returned srsid: "\
-		+ QString::number(mySrsId));
+    QgsDebugMsg("QgsSpatialRefSys::createFromProj4 proj4string match search for srsid returned srsid: " + QString::number(mySrsId));
     if (mySrsId > 0)
     {
       createFromSrsId(mySrsId);
@@ -575,93 +374,70 @@
   }
   else
   {
-    /*
-    * - if the above does not match perform a whole text search on proj4 string (if not null)
-    */
-    QgsDebugMsg("QgsSpatialRefSys::createFromProj4 wholetext match on name failed, trying proj4string match");
-    myRecord = getRecord("select * from tbl_srs where parameters='" + mProj4String.stripWhiteSpace () + "'");
-    if (!myRecord.empty())
+    // Ticket #722 - aaronr
+    // Check if we can swap the lat_1 and lat_2 params (if they exist) to see if we match...
+    // First we check for lat_1 and lat_2
+    QRegExp myLat1RegExp( "\\+lat_1=\\S+" );
+    QRegExp myLat2RegExp( "\\+lat_2=\\S+" );
+    int myStart1 = 0;
+    int myLength1 = 0;
+    int myStart2 = 0;
+    int myLength2 = 0;
+    QString lat1Str = "";
+    QString lat2Str = "";
+    myStart1 = myLat1RegExp.search(theProj4String, myStart1);
+    myStart2 = myLat2RegExp.search(theProj4String, myStart2);
+    if ((myStart1 != -1) && (myStart2 != -1))
     {
-      mySrsId=myRecord["srs_id"].toLong();
-      QgsDebugMsg("QgsSpatialRefSys::createFromProj4 proj4string match search for srsid returned srsid: " \
-		  + QString::number(mySrsId));
-      if (mySrsId > 0)
+      myLength1 = myLat1RegExp.matchedLength();
+      myLength2 = myLat2RegExp.matchedLength();
+      lat1Str = theProj4String.mid(myStart1+LAT_PREFIX_LEN,myLength1-LAT_PREFIX_LEN);
+      lat2Str = theProj4String.mid(myStart2+LAT_PREFIX_LEN,myLength2-LAT_PREFIX_LEN);
+    }
+    // If we found the lat_1 and lat_2 we need to swap and check to see if we can find it...
+    if ((lat1Str != "") && (lat2Str != ""))
+    {
+      // Make our new string to check...
+      QString theProj4StringModified = theProj4String;
+      // First just swap in the lat_2 value for lat_1 value
+      theProj4StringModified.replace(myStart1+LAT_PREFIX_LEN,myLength1-LAT_PREFIX_LEN,lat2Str);
+      // Now we have to find the lat_2 location again since it has potentially moved...
+      myStart2 = 0;
+      myStart2 = myLat2RegExp.search(theProj4String, myStart2);
+      theProj4StringModified.replace(myStart2+LAT_PREFIX_LEN,myLength2-LAT_PREFIX_LEN,lat1Str);
+      QgsDebugMsg("QgsSpatialRefSys::createFromProj4 - trying proj4string match with swapped lat_1,lat_2");
+      myRecord = getRecord("select * from tbl_srs where parameters='" + theProj4StringModified.stripWhiteSpace () + "'");
+      if (!myRecord.empty())
       {
-        createFromSrsId(mySrsId);
+        // Success!  We have found the proj string by swapping the lat_1 and lat_2
+        OSRImportFromProj4(mSRS, (const char *)theProj4StringModified.latin1() );
+        mySrsId=myRecord["srs_id"].toLong();
+        QgsDebugMsg("QgsSpatialRefSys::createFromProj4 proj4string match search for srsid returned srsid: " + QString::number(mySrsId));
+        if (mySrsId > 0)
+        {
+          createFromSrsId(mySrsId);
+        }
       }
     }
     else
     {
-      // Ticket #722 - aaronr
-      // Check if we can swap the lat_1 and lat_2 params (if they exist) to see if we match...
-      // First we check for lat_1 and lat_2
-      QRegExp myLat1RegExp( "\\+lat_1=\\S+" );
-      QRegExp myLat2RegExp( "\\+lat_2=\\S+" );
-      int myStart1 = 0;
-      int myLength1 = 0;
-      int myStart2 = 0;
-      int myLength2 = 0;
-      QString lat1Str = "";
-      QString lat2Str = "";
-      myStart1 = myLat1RegExp.search(theProj4String, myStart1);
-      myStart2 = myLat2RegExp.search(theProj4String, myStart2);
-      if ((myStart1 != -1) && (myStart2 != -1))
-	{
-	  myLength1 = myLat1RegExp.matchedLength();
-	  myLength2 = myLat2RegExp.matchedLength();
-	  lat1Str = theProj4String.mid(myStart1+LAT_PREFIX_LEN,myLength1-LAT_PREFIX_LEN);
-	  lat2Str = theProj4String.mid(myStart2+LAT_PREFIX_LEN,myLength2-LAT_PREFIX_LEN);
-	}
-      // If we found the lat_1 and lat_2 we need to swap and check to see if we can find it...
-      if ((lat1Str != "") && (lat2Str != ""))
-	{
-	  // Make our new string to check...
-	  QString theProj4StringModified = theProj4String;
-	  // First just swap in the lat_2 value for lat_1 value
-	  theProj4StringModified.replace(myStart1+LAT_PREFIX_LEN,myLength1-LAT_PREFIX_LEN,lat2Str);
-	  // Now we have to find the lat_2 location again since it has potentially moved...
-	  myStart2 = 0;
-	  myStart2 = myLat2RegExp.search(theProj4String, myStart2);
-	  theProj4StringModified.replace(myStart2+LAT_PREFIX_LEN,myLength2-LAT_PREFIX_LEN,lat1Str);
-	  QgsDebugMsg("QgsSpatialRefSys::createFromProj4 - trying proj4string match with swapped lat_1,lat_2");
-	  myRecord = getRecord("select * from tbl_srs where parameters='" + theProj4StringModified.stripWhiteSpace () + "'");
-	  if (!myRecord.empty())
-	    {
-	      // Success!  We have found the proj string by swapping the lat_1 and lat_2
-	      mProj4String = theProj4StringModified;
-	      mySrsId=myRecord["srs_id"].toLong();
-	      QgsDebugMsg("QgsSpatialRefSys::createFromProj4 proj4string match search for srsid returned srsid: " \
-			  + QString::number(mySrsId));
-	      if (mySrsId > 0)
-		{
-		  createFromSrsId(mySrsId);
-		}
-	    }
-	}
-      else
-	{
-	  // Last ditch attempt to piece together what we know of the projection to find a match...
-	  QgsDebugMsg("QgsSpatialRefSys::createFromProj4 globbing search for srsid from this proj string");
-	  mySrsId = findMatchingProj();
-	  QgsDebugMsg("QgsSpatialRefSys::createFromProj4 globbing search for srsid returned srsid: "\
-		      + QString::number(mySrsId));
-	  if (mySrsId > 0)
-	    {
-	      createFromSrsId(mySrsId);
-	    }
-	}
+      // Last ditch attempt to piece together what we know of the projection to find a match...
+      QgsDebugMsg("QgsSpatialRefSys::createFromProj4 globbing search for srsid from this proj string");
+      mySrsId = findMatchingProj();
+      QgsDebugMsg("QgsSpatialRefSys::createFromProj4 globbing search for srsid returned srsid: " + QString::number(mySrsId));
+      if (mySrsId > 0)
+      {
+        createFromSrsId(mySrsId);
+      }
     }
   }
 
-  /* If its still empty after all the above steps then all we can do is keep the proj string
-  * with what was passed in and hope for the best...If its not empty we can fill other member details in 
-    from the record*/
+  // NOTE: if its still empty after all the above steps then, the projection string is lost. Is that bad?
   return mIsValidFlag;
 }
 
 QgsSpatialRefSys::RecordMap QgsSpatialRefSys::getRecord(QString theSql)
 {
-
   QString myDatabaseFileName;
   QgsSpatialRefSys::RecordMap myMap;
   QString myFieldName;
@@ -826,14 +602,16 @@
  */
 QString QgsSpatialRefSys::proj4String() const
 {
-  if (mProj4String.isNull())
-  {
+  if(!mIsValidFlag)
     return "";
-  }
-  else
-  {
-    return mProj4String;
-  }
+
+  QString proj4String;
+  char *proj4src = NULL;
+  OSRExportToProj4(mSRS, &proj4src);
+  proj4String = proj4src;
+  CPLFree(proj4src);
+
+  return proj4String;
 }
 /*! Get this Geographic? flag
  * @return  bool theGeoFlag Whether this is a geographic or projected coordinate system
@@ -882,7 +660,7 @@
 }
 void QgsSpatialRefSys::setProj4String (QString theProj4String)
 {
-  mProj4String = theProj4String;
+  mIsValidFlag = OSRImportFromProj4(mSRS, (const char *)theProj4String.latin1())==OGRERR_NONE;
 }
 void QgsSpatialRefSys::setGeographicFlag (bool theGeoFlag)
 {
@@ -905,24 +683,22 @@
  */
 void QgsSpatialRefSys::setMapUnits()
 {
-  if (mProj4String.isEmpty())
+  if (!mIsValidFlag)
   {
-    QgsLogger::warning("No proj4 projection string. Unable to set map units.");
+    QgsLogger::warning("No valid projection. Unable to set map units.");
     mMapUnits = QGis::UNKNOWN;
     return;
   }
 
   char *unitName;
-  OGRSpatialReferenceH myOgrSpatialRef = OSRNewSpatialReference(NULL);
-  OSRImportFromProj4(myOgrSpatialRef, mProj4String.latin1());
 
   // Of interest to us is that this call adds in a unit parameter if
   // one doesn't already exist.
-  OSRFixup(myOgrSpatialRef);
+  OSRFixup(mSRS);
 
-  if (OSRIsProjected(myOgrSpatialRef))
+  if (OSRIsProjected(mSRS))
   {
-    double toMeter = OSRGetLinearUnits(myOgrSpatialRef,&unitName);
+    double toMeter = OSRGetLinearUnits(mSRS,&unitName);
     QString unit(unitName);
 
     // If the units parameter was created during the Fixup() call
@@ -950,7 +726,7 @@
   }
   else
   {
-    OSRGetAngularUnits(myOgrSpatialRef, &unitName);
+    OSRGetAngularUnits(mSRS, &unitName);
     QString unit(unitName);
     if (unit == "degree")
       mMapUnits = QGis::DEGREES;
@@ -961,10 +737,8 @@
     }
     QgsDebugMsg("Projection has angular units of " + unit);
   }
-  OSRDestroySpatialReference( myOgrSpatialRef );
 }
 
-
 /*
 *    check if srs is a geocs or a proj cs (using ogr isGeographic)
 *   then sequentially walk through the database (first users qgis.db srs tbl then
@@ -977,7 +751,7 @@
 long QgsSpatialRefSys::findMatchingProj()
 {
   QgsDebugMsg("QgsSpatialRefSys::findMatchingProj...");
-  if (mEllipsoidAcronym.isNull() ||  mProjectionAcronym.isNull() || mProj4String.isNull())
+  if (mEllipsoidAcronym.isNull() ||  mProjectionAcronym.isNull() || !mIsValidFlag)
   {
     QgsLogger::warning("QgsSpatialRefSys::findMatchingProj will only work if prj acr ellipsoid acr and proj4string are set!...");
     return 0;
@@ -994,7 +768,6 @@
   // Get the full path name to the sqlite3 spatial reference database.
   QString myDatabaseFileName = QgsApplication::srsDbFilePath();
 
-
   //check the db is available
   myResult = openDb(myDatabaseFileName, &myDatabase);
   if(myResult)
@@ -1011,9 +784,9 @@
     {
       QString mySrsId = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,0));
       QString myProj4String = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement, 1));
-      if (this->equals(myProj4String))
+      if (equals(myProj4String))
       {
-	QgsDebugMsg("QgsSpatialRefSys::findMatchingProj -------> MATCH FOUND in srs.db srsid: " + mySrsId);
+        QgsDebugMsg("QgsSpatialRefSys::findMatchingProj -------> MATCH FOUND in srs.db srsid: " + mySrsId);
         // close the sqlite3 statement
         sqlite3_finalize(myPreparedStatement);
         sqlite3_close(myDatabase);
@@ -1051,9 +824,9 @@
     {
       QString mySrsId = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement,0));
       QString myProj4String = QString::fromUtf8((char *)sqlite3_column_text(myPreparedStatement, 1));
-      if (this->equals(myProj4String))
+      if (equals(myProj4String))
       {
-	QgsDebugMsg("QgsSpatialRefSys::findMatchingProj -------> MATCH FOUND in user qgis.db srsid: " + mySrsId);
+        QgsDebugMsg("QgsSpatialRefSys::findMatchingProj -------> MATCH FOUND in user qgis.db srsid: " + mySrsId);
         // close the sqlite3 statement
         sqlite3_finalize(myPreparedStatement);
         sqlite3_close(myDatabase);
@@ -1071,15 +844,28 @@
   sqlite3_finalize(myPreparedStatement);
   sqlite3_close(myDatabase);
   return 0;
-
 }
 
 bool QgsSpatialRefSys::operator==(const QgsSpatialRefSys &theSrs)
 {
-  //qWarning("QgsSpatialRefSys::operator==(const QgsSpatialRefSys &theSrs) called ");
-  //simply delegate to the overloaded == operator  below...
-  return this->equals(theSrs.mProj4String);
-
+  if (!mIsValidFlag || !theSrs.mIsValidFlag)
+  {
+    return false;
+  }
+  else if (OSRIsGeographic(mSRS) && OSRIsGeographic(theSrs.mSRS))
+  {
+    // qWarning("QgsSpatialRefSys::operator== srs1 and srs2 are geographic ");
+    return OSRIsSameGeogCS(mSRS,theSrs.mSRS);
+  }
+  else if (OSRIsProjected(mSRS) && OSRIsProjected(theSrs.mSRS))
+  {
+    // qWarning("QgsSpatialRefSys::operator== srs1 and srs2 are projected ");
+    return OSRIsSame(mSRS, theSrs.mSRS);
+  }
+  else
+  {
+    return false;
+  }
 }
 
 bool QgsSpatialRefSys::operator!=(const QgsSpatialRefSys &theSrs)
@@ -1087,84 +873,23 @@
   return  ! (*this == theSrs);
 }
 
-
-bool QgsSpatialRefSys::equals(QString theProj4CharArray)
+bool QgsSpatialRefSys::equals(QString theProj4String)
 {
-  //qWarning("QgsSpatialRefSys::operator==(const char *theProj4CharArray) called ");
-  bool myMatchFlag = false; //guilty until proven innocent
-
-  /* Here are the possible OGR error codes :
-     typedef int OGRErr;
-
-     #define OGRERR_NONE                0
-     #define OGRERR_NOT_ENOUGH_DATA     1    --> not enough data to deserialize
-     #define OGRERR_NOT_ENOUGH_MEMORY   2
-     #define OGRERR_UNSUPPORTED_GEOMETRY_TYPE 3
-     #define OGRERR_UNSUPPORTED_OPERATION 4
-     #define OGRERR_CORRUPT_DATA        5
-     #define OGRERR_FAILURE             6
-     #define OGRERR_UNSUPPORTED_SRS     7 */
-
-  //get the wkt into ogr
-  //this is really ugly but we need to get a QString to a char**
-  const char *myCharArrayPointer1 = mProj4String.latin1();
-
-  //note that the proj strings above do not neccessarily need to be exactly the
-  //same for the projections they define to be equivalent, which is why I dont just
-  //compare the proj parameter strings and return the result
-
-
-  //create the sr and populate it from a wkt proj definition
-  OGRSpatialReferenceH myOgrSpatialRef1 = OSRNewSpatialReference( NULL );
-  OGRSpatialReferenceH myOgrSpatialRef2 = OSRNewSpatialReference( NULL );
-  OGRErr myInputResult1 = OSRImportFromProj4( myOgrSpatialRef1, myCharArrayPointer1 );
-  OGRErr myInputResult2 = OSRImportFromProj4( myOgrSpatialRef1, theProj4CharArray.latin1() );
-
-  // Could do some error reporting here...
-  if (myInputResult1 != OGRERR_NONE)
-    {}
-  if (myInputResult2 != OGRERR_NONE)
-    {}
-
-  if (OSRIsGeographic(myOgrSpatialRef1) && OSRIsGeographic(myOgrSpatialRef2))
-  {
-//    qWarning("QgsSpatialRefSys::operator== srs1 and srs2 are geographic ");
-    myMatchFlag = OSRIsSameGeogCS(myOgrSpatialRef1,myOgrSpatialRef2);
-  }
-  else if (OSRIsProjected(myOgrSpatialRef1) && OSRIsProjected(myOgrSpatialRef2))
-  {
-//    qWarning("QgsSpatialRefSys::operator== srs1 and srs2 are projected ");
-    myMatchFlag = OSRIsSame(myOgrSpatialRef1,myOgrSpatialRef2);
-  } else {
-//    qWarning("QgsSpatialRefSys::operator== srs1 and srs2 are different types ");
-    myMatchFlag = false;
-  }
-
-  OSRDestroySpatialReference( myOgrSpatialRef1 );
-  OSRDestroySpatialReference( myOgrSpatialRef2 );
-
-  return myMatchFlag;
+  QgsSpatialRefSys r;
+  r.setProj4String(theProj4String);
+  return *this==r;
 }
 
 QString QgsSpatialRefSys::toWkt() const
 {
-  OGRSpatialReferenceH myOgrSpatialRef = OSRNewSpatialReference(NULL);
-  OGRErr myInputResult = OSRImportFromProj4(myOgrSpatialRef,mProj4String.latin1());
-  
   QString myWkt;
-
-  if (myInputResult == OGRERR_NONE)
+  char* WKT;
+  if(OSRExportToWkt(mSRS,&WKT) == OGRERR_NONE)
   {
-    char* WKT;
-    if(OSRExportToWkt(myOgrSpatialRef,&WKT) == OGRERR_NONE)
-    {
-      myWkt = WKT;
-      OGRFree(WKT);
-    }    
-  }
+    myWkt = WKT;
+    OGRFree(WKT);
+  }    
 
-  OSRDestroySpatialReference( myOgrSpatialRef );
-
   return myWkt;
 }
 
@@ -1294,8 +1019,7 @@
       mySql += QString::number(theSrsId);
 
       QgsDebugMsg("QgsSpatialRefSys::getProj4FromSrsId :  mySrsId = " + QString::number(theSrsId));
-      QgsDebugMsg("QgsSpatialRefSys::getProj4FromSrsId :  USER_PROJECTION_START_ID = " +\
-QString::number(USER_PROJECTION_START_ID));
+      QgsDebugMsg("QgsSpatialRefSys::getProj4FromSrsId :  USER_PROJECTION_START_ID = " + QString::number(USER_PROJECTION_START_ID));
       QgsDebugMsg("QgsSpatialRefSys::getProj4FromSrsId :Selection sql : " + mySql);
 	  
       //
@@ -1380,6 +1104,6 @@
   QgsDebugMsg("***SpatialRefSystem***");
   QgsDebugMsg("* Valid : " + (mIsValidFlag?QString("true"):QString("false")));
   QgsDebugMsg("* SrsId : " + QString::number(mSrsId));
-  QgsDebugMsg("* Proj4 : " + mProj4String);
+  QgsDebugMsg("* Proj4 : " + proj4String() );
   QgsDebugMsg("* Desc. : " + mDescription);
 }

Modified: trunk/qgis/src/core/qgsspatialrefsys.h
===================================================================
--- trunk/qgis/src/core/qgsspatialrefsys.h	2008-03-24 16:22:32 UTC (rev 8262)
+++ trunk/qgis/src/core/qgsspatialrefsys.h	2008-03-24 18:31:08 UTC (rev 8263)
@@ -53,6 +53,8 @@
         
         //! Default constructor
         QgsSpatialRefSys();
+
+        ~QgsSpatialRefSys();
         
         /*! 
          * Constructs a SRS object from a WKT string
@@ -67,6 +69,8 @@
          */
         QgsSpatialRefSys(const long theId, SRS_TYPE theType=POSTGIS_SRID);
 
+        //! copy constructor
+        QgsSpatialRefSys(const QgsSpatialRefSys& srs);
 
         //! Assignment operator
         QgsSpatialRefSys& operator=(const QgsSpatialRefSys& srs);
@@ -158,14 +162,15 @@
 
         /*! Find out whether this SRS is correctly initialised and useable */
         bool isValid() const;
-        /*! Perform some validation on this SRS. If the sts doesnt validate the
-         *  default behaviour settings for layers with unknown SRS will be 
+
+        /*! Perform some validation on this SRS. If the sts doesn't validate the
+         * default behaviour settings for layers with unknown SRS will be 
          * consulted and acted on accordingly. By hell or high water this
          * method will do its best to make sure that this SRS is valid - even
          * if that involves resorting to a hard coded default of geocs:wgs84.
          *
          * @note It is not usually neccessary to use this function, unless you
-         * are trying to force theis srs to be valid.
+         * are trying to force this srs to be valid.
          */
         void validate();
 
@@ -330,7 +335,7 @@
 
         /*! Print the description if debugging
          */
-	void debugPrint();
+        void debugPrint();
     private:
         // Open SQLite db and show message if ccannot be opened
         // returns the same code as sqlite3_open
@@ -344,8 +349,6 @@
         QString mProjectionAcronym ;
         //!The official proj4 acronym for the ellipoid
         QString mEllipsoidAcronym;
-        //!Proj4 format specifies (excluding proj and ellips) that define this srs.
-        QString mProj4String ;
         //!Whether this is a geographic or projected coordinate system
         bool    mGeoFlag;
         //! The map units
@@ -359,6 +362,10 @@
 
         //! Work out the projection units and set the appropriate local variable
         void setMapUnits();
+
+        void *mSRS;
+
+        bool loadFromDb(QString db, QString field, long id);
         
         static CUSTOM_SRS_VALIDATION mCustomSrsValidation;
 };



More information about the QGIS-commit mailing list