Skip to content
Permalink
Browse files

Add API to skip identification of CRS created from proj strings

The identification can be time consuming, so in the rare cases that
we are SURE that the definition doesn't correspond to a known or
user CRS, we can optionally skip it to save some time.
  • Loading branch information
nyalldawson committed May 19, 2020
1 parent a2e8cde commit 0acb7fcc29d57bbc80b5d355ec6520890071436c
@@ -474,6 +474,9 @@ We try to match the Proj string to internal QGIS CRS ID using the following logi
- if none of the above match, use the Proj string to create the CRS and do not associated an internal CRS ID to it.

:param projString: A Proj format string
:param identify: if ``False``, no attempts will be made to match the proj string against known CRS authorities. This is much
faster, but should only ever be used when it is known in advance that the definition does not correspond to a known or user CRS. This
argument is not available in Python.

:return: ``True`` on success else ``False``

@@ -897,7 +897,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString &proj4String )
return createFromProj( proj4String );
}

bool QgsCoordinateReferenceSystem::createFromProj( const QString &projString )
bool QgsCoordinateReferenceSystem::createFromProj( const QString &projString, const bool identify )
{
d.detach();

@@ -937,51 +937,60 @@ bool QgsCoordinateReferenceSystem::createFromProj( const QString &projString )
d->mIsValid = false;
d->mWktPreferred.clear();
#if PROJ_VERSION_MAJOR>=6
// first, try to use proj to do this for us...
const QString projCrsString = myProj4String + ( myProj4String.contains( QStringLiteral( "+type=crs" ) ) ? QString() : QStringLiteral( " +type=crs" ) );
QgsProjUtils::proj_pj_unique_ptr crs( proj_create( QgsProjContext::get(), projCrsString.toLatin1().constData() ) );
if ( crs )
if ( identify )
{
QString authName;
QString authCode;
if ( QgsProjUtils::identifyCrs( crs.get(), authName, authCode, QgsProjUtils::FlagMatchBoundCrsToUnderlyingSourceCrs ) )
// first, try to use proj to do this for us...
const QString projCrsString = myProj4String + ( myProj4String.contains( QStringLiteral( "+type=crs" ) ) ? QString() : QStringLiteral( " +type=crs" ) );
QgsProjUtils::proj_pj_unique_ptr crs( proj_create( QgsProjContext::get(), projCrsString.toLatin1().constData() ) );
if ( crs )
{
const QString authid = QStringLiteral( "%1:%2" ).arg( authName, authCode );
if ( createFromOgcWmsCrs( authid ) )
QString authName;
QString authCode;
if ( QgsProjUtils::identifyCrs( crs.get(), authName, authCode, QgsProjUtils::FlagMatchBoundCrsToUnderlyingSourceCrs ) )
{
locker.changeMode( QgsReadWriteLocker::Write );
if ( !sDisableProjCache )
sProj4Cache()->insert( projString, *this );
return true;
const QString authid = QStringLiteral( "%1:%2" ).arg( authName, authCode );
if ( createFromOgcWmsCrs( authid ) )
{
locker.changeMode( QgsReadWriteLocker::Write );
if ( !sDisableProjCache )
sProj4Cache()->insert( projString, *this );
return true;
}
}
}
}

// 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() )
{
id = myRecord[QStringLiteral( "srs_id" )].toLong();
if ( id >= USER_CRS_START_ID )
// 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() )
{
createFromSrsId( id );
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.
setProjString( 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 );
}
}
}
if ( id < USER_CRS_START_ID )
else
{
// no direct matches, so go ahead and create a new proj object based on the proj string alone.
setProjString( 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 );
}
}

#else
Q_UNUSED( identify )

QRegExp myProjRegExp( "\\+proj=(\\S+)" );
int myStart = myProjRegExp.indexIn( myProj4String );
if ( myStart == -1 )
@@ -451,13 +451,21 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
* - if none of the above match, use the Proj string to create the CRS and do not associated an internal CRS ID to it.
*
* \param projString A Proj format string
* \param identify if FALSE, no attempts will be made to match the proj string against known CRS authorities. This is much
* faster, but should only ever be used when it is known in advance that the definition does not correspond to a known or user CRS. This
* argument is not available in Python.
*
* \returns TRUE on success else FALSE
* \note Some members may be left blank if no match can be found in CRS database.
* \note This method uses an internal cache. Call invalidateCache() to clear the cache.
* \see fromProj()
* \since QGIS 3.10.3
*/
#ifndef SIP_RUN
bool createFromProj( const QString &projString, bool identify = true );
#else
bool createFromProj( const QString &projString );
#endif

/**
* Set up this CRS from a string definition.

0 comments on commit 0acb7fc

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