Skip to content
Permalink
Browse files

Ensure that proj strings in different parameter order are matched

to user CRS on proj 6 builds
  • Loading branch information
nyalldawson committed Dec 17, 2019
1 parent a2c6bb9 commit 3f0af6e72ab8c6972df85183b51e78bbf4943d50
@@ -831,14 +831,25 @@ bool QgsCoordinateReferenceSystem::createFromProj( const QString &projString )
}
}
}
#endif

#if PROJ_VERSION_MAJOR>=6
// try to match against known user crses
// try a direct match against user crses
QgsCoordinateReferenceSystem::RecordMap myRecord = getRecord( "select * from tbl_srs where parameters=" + QgsSqliteUtils::quotedString( myProj4String ) + " order by deprecated" );
long id = 0;
if ( !myRecord.empty() )
{
long id = myRecord[QStringLiteral( "srs_id" )].toLong();
id = myRecord[QStringLiteral( "srs_id" )].toLong();
if ( id >= USER_CRS_START_ID )
{
createFromSrsId( id );
}
}
if ( id < USER_CRS_START_ID )
{
// no direct matches, so go ahead and create a new proj object based on the proj string alone.
setProj4String( myProj4String );

// lastly, try a tolerant match of the created proj object against all user CRSes (allowing differences in parameter order during the comparison)
id = matchToUserCrs();
if ( id >= USER_CRS_START_ID )
{
createFromSrsId( id );
@@ -1006,7 +1017,6 @@ bool QgsCoordinateReferenceSystem::createFromProj( const QString &projString )
d->mIsValid = false;
}
}
#endif

// if we failed to look up the projection in database, don't worry. we can still use it :)
if ( !d->mIsValid )
@@ -1015,6 +1025,7 @@ bool QgsCoordinateReferenceSystem::createFromProj( const QString &projString )
//setProj4String will set mIsValidFlag to true if there is no issue
setProjString( myProj4String );
}
#endif

locker.changeMode( QgsReadWriteLocker::Write );
if ( !sDisableProjCache )
@@ -2348,6 +2359,74 @@ bool QgsCoordinateReferenceSystem::loadFromAuthCode( const QString &auth, const

return true;
}

QList<long> QgsCoordinateReferenceSystem::userSrsIds()
{
QList<long> results;
// check user defined projection database
const QString db = QgsApplication::qgisUserDatabaseFilePath();

QFileInfo myInfo( db );
if ( !myInfo.exists() )
{
QgsDebugMsg( "failed : " + db + " does not exist!" );
return results;
}

sqlite3_database_unique_ptr database;
sqlite3_statement_unique_ptr statement;

//check the db is available
int result = openDatabase( db, database );
if ( result != SQLITE_OK )
{
QgsDebugMsg( "failed : " + db + " could not be opened!" );
return results;
}

QString sql = QStringLiteral( "select srs_id from tbl_srs where srs_id >= %1" ).arg( USER_CRS_START_ID );
int rc;
statement = database.prepare( sql, rc );
while ( true )
{
int ret = statement.step();

if ( ret == SQLITE_DONE )
{
// there are no more rows to fetch - we can stop looping
break;
}

if ( ret == SQLITE_ROW )
{
results.append( statement.columnAsInt64( 0 ) );
}
else
{
QgsMessageLog::logMessage( QObject::tr( "SQLite error: %2\nSQL: %1" ).arg( sql, sqlite3_errmsg( database.get() ) ), QObject::tr( "SpatiaLite" ) );
break;
}
}

return results;
}

long QgsCoordinateReferenceSystem::matchToUserCrs() const
{
if ( !d->mPj )
return 0;

const QList< long > ids = userSrsIds();
for ( long id : ids )
{
QgsCoordinateReferenceSystem candidate = QgsCoordinateReferenceSystem::fromSrsId( id );
if ( candidate.projObject() && proj_is_equivalent_to( d->mPj.get(), candidate.projObject(), PJ_COMP_EQUIVALENT ) )
{
return id;
}
}
return 0;
}
#endif

#if PROJ_VERSION_MAJOR<6
@@ -931,6 +931,20 @@ class CORE_EXPORT QgsCoordinateReferenceSystem

#if PROJ_VERSION_MAJOR>=6
bool loadFromAuthCode( const QString &auth, const QString &code );

/**
* Returns a list of all users SRS IDs present in the CRS database.
*/
static QList< long > userSrsIds();

/**
* Tries to match the current definition of the CRS to user CRSes.
*
* Uses proj's equivalent testing API so that matches are tolerant to differences in
* parameter order and naming for proj or WKT strings (internally, uses the PJ_COMP_EQUIVALENT
* criteria).
*/
long matchToUserCrs() const;
#endif

/**
@@ -1410,6 +1410,14 @@ void TestQgsCoordinateReferenceSystem::customProjString()
QCOMPARE( crs.toWkt(), QStringLiteral( R"""(COMPD_CS["unknown",PROJCS["unknown",GEOGCS["unknown",DATUM["Unknown_based_on_Bessel_1841_ellipsoid",SPHEROID["Bessel 1841",6377397.155,299.1528128],TOWGS84[595.75,121.09,515.5,8.227,-1.5193,5.5971,-2.6729]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]]],PROJECTION["Oblique_Stereographic"],PARAMETER["latitude_of_origin",47.4860018439082],PARAMETER["central_meridian",19.0491441390302],PARAMETER["scale_factor",1],PARAMETER["false_easting",500000],PARAMETER["false_northing",500000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH]],VERT_CS["unknown",VERT_DATUM["unknown",2005],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Gravity-related height",UP]]])""" ) );
QCOMPARE( crs.authid(), QStringLiteral( "USER:%1" ).arg( id ) );

// make sure it matches to user crs when parameter order is different
QgsCoordinateReferenceSystem::invalidateCache();
crs = QgsCoordinateReferenceSystem::fromProj4( QStringLiteral( "+proj=sterea +lon_0=19.0491441390302 +lat_0=47.4860018439082 +k=1 +y_0=500000 +ellps=bessel +x_0=500000 +towgs84=595.75,121.09,515.50,8.2270,-1.5193,5.5971,-2.6729 +units=m +vunits=m +no_defs" ) );
QVERIFY( crs.isValid() );
QCOMPARE( crs.authid(), QStringLiteral( "USER:%1" ).arg( id ) );
QCOMPARE( crs.toProj4(), QStringLiteral( "+proj=sterea +lat_0=47.4860018439082 +lon_0=19.0491441390302 +k=1 +x_0=500000 +y_0=500000 +ellps=bessel +towgs84=595.75,121.09,515.50,8.2270,-1.5193,5.5971,-2.6729 +units=m +vunits=m +no_defs" ) );
QCOMPARE( crs.toWkt(), QStringLiteral( R"""(COMPD_CS["unknown",PROJCS["unknown",GEOGCS["unknown",DATUM["Unknown_based_on_Bessel_1841_ellipsoid",SPHEROID["Bessel 1841",6377397.155,299.1528128],TOWGS84[595.75,121.09,515.5,8.227,-1.5193,5.5971,-2.6729]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]]],PROJECTION["Oblique_Stereographic"],PARAMETER["latitude_of_origin",47.4860018439082],PARAMETER["central_meridian",19.0491441390302],PARAMETER["scale_factor",1],PARAMETER["false_easting",500000],PARAMETER["false_northing",500000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH]],VERT_CS["unknown",VERT_DATUM["unknown",2005],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Gravity-related height",UP]]])""" ) );

#endif
}

0 comments on commit 3f0af6e

Please sign in to comment.
You can’t perform that action at this time.