24 #include <QTemporaryFile> 26 #include <QDomElement> 29 #include <QTextStream> 31 #include <QRegularExpression> 41 #ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 42 #define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 47 #include <ogr_srs_api.h> 48 #include <cpl_error.h> 58 QReadWriteLock QgsCoordinateReferenceSystem::sSrIdCacheLock;
59 QHash< long, QgsCoordinateReferenceSystem > QgsCoordinateReferenceSystem::sSrIdCache;
60 QReadWriteLock QgsCoordinateReferenceSystem::sOgcLock;
61 QHash< QString, QgsCoordinateReferenceSystem > QgsCoordinateReferenceSystem::sOgcCache;
62 QReadWriteLock QgsCoordinateReferenceSystem::sProj4CacheLock;
63 QHash< QString, QgsCoordinateReferenceSystem > QgsCoordinateReferenceSystem::sProj4Cache;
64 QReadWriteLock QgsCoordinateReferenceSystem::sCRSWktLock;
65 QHash< QString, QgsCoordinateReferenceSystem > QgsCoordinateReferenceSystem::sWktCache;
66 QReadWriteLock QgsCoordinateReferenceSystem::sCRSSrsIdLock;
67 QHash< long, QgsCoordinateReferenceSystem > QgsCoordinateReferenceSystem::sSrsIdCache;
68 QReadWriteLock QgsCoordinateReferenceSystem::sCrsStringLock;
69 QHash< QString, QgsCoordinateReferenceSystem > QgsCoordinateReferenceSystem::sStringCache;
75 d =
new QgsCoordinateReferenceSystemPrivate();
80 d =
new QgsCoordinateReferenceSystemPrivate();
86 d =
new QgsCoordinateReferenceSystemPrivate();
107 Q_FOREACH (
const QString &db, dbs )
109 QFileInfo myInfo( db );
110 if ( !myInfo.exists() )
112 QgsDebugMsg(
"failed : " + db +
" does not exist!" );
120 int result = openDatabase( db, database );
121 if ( result != SQLITE_OK )
123 QgsDebugMsg(
"failed : " + db +
" could not be opened!" );
127 QString sql = QStringLiteral(
"select srs_id from tbl_srs" );
129 statement = database.
prepare( sql, rc );
133 int ret = statement.
step();
135 if ( ret == SQLITE_DONE )
141 if ( ret == SQLITE_ROW )
147 QgsMessageLog::logMessage( QObject::tr(
"SQLite error: %2\nSQL: %1" ).arg( sql, sqlite3_errmsg( database.get() ) ), QObject::tr(
"SpatiaLite" ) );
152 std::sort( results.begin(), results.end() );
209 QgsDebugMsg( QStringLiteral(
"Unexpected case reached!" ) );
216 sCrsStringLock.lockForRead();
217 QHash< QString, QgsCoordinateReferenceSystem >::const_iterator crsIt = sStringCache.constFind( definition );
218 if ( crsIt != sStringCache.constEnd() )
221 *
this = crsIt.value();
222 sCrsStringLock.unlock();
225 sCrsStringLock.unlock();
228 QRegularExpression reCrsId(
"^(epsg|postgis|internal|user)\\:(\\d+)$", QRegularExpression::CaseInsensitiveOption );
229 QRegularExpressionMatch match = reCrsId.match( definition );
230 if ( match.capturedStart() == 0 )
232 QString authName = match.captured( 1 ).toLower();
234 if ( authName == QLatin1String(
"epsg" ) )
236 if ( authName == QLatin1String(
"postgis" ) )
238 long id = match.captured( 2 ).toLong();
243 QRegularExpression reCrsStr(
"^(?:(wkt|proj4)\\:)?(.+)$", QRegularExpression::CaseInsensitiveOption );
244 match = reCrsStr.match( definition );
245 if ( match.capturedStart() == 0 )
247 if ( match.captured( 1 ).compare( QLatin1String(
"proj4" ), Qt::CaseInsensitive ) == 0 )
256 QString myName = QStringLiteral(
" * %1 (%2)" )
257 .arg( QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ),
269 sCrsStringLock.lockForWrite();
270 sStringCache.insert( definition, *
this );
271 sCrsStringLock.unlock();
282 if ( definition.startsWith( QLatin1String(
"ESRI::" ) ) )
287 if ( OSRSetFromUserInput( crs, definition.toLocal8Bit().constData() ) == OGRERR_NONE )
289 if ( OSRExportToWkt( crs, &wkt ) == OGRERR_NONE )
294 OSRDestroySpatialReference( crs );
304 const char *configOld = CPLGetConfigOption(
"GDAL_FIX_ESRI_WKT",
"" );
305 const char *configNew =
"GEOGCS";
307 if ( strcmp( configOld,
"" ) == 0 )
309 CPLSetConfigOption(
"GDAL_FIX_ESRI_WKT", configNew );
310 if ( strcmp( configNew, CPLGetConfigOption(
"GDAL_FIX_ESRI_WKT",
"" ) ) != 0 )
312 .arg( configNew, CPLGetConfigOption(
"GDAL_FIX_ESRI_WKT",
"" ) ) );
313 QgsDebugMsgLevel( QStringLiteral(
"set GDAL_FIX_ESRI_WKT : %1" ).arg( configNew ), 4 );
317 QgsDebugMsgLevel( QStringLiteral(
"GDAL_FIX_ESRI_WKT was already set : %1" ).arg( configNew ), 4 );
323 sOgcLock.lockForRead();
324 QHash< QString, QgsCoordinateReferenceSystem >::const_iterator crsIt = sOgcCache.constFind( crs );
325 if ( crsIt != sOgcCache.constEnd() )
328 *
this = crsIt.value();
334 QString wmsCrs =
crs;
336 QRegExp re(
"urn:ogc:def:crs:([^:]+).+([^:]+)", Qt::CaseInsensitive );
337 if ( re.exactMatch( wmsCrs ) )
339 wmsCrs = re.cap( 1 ) +
':' + re.cap( 2 );
343 re.setPattern( QStringLiteral(
"(user|custom|qgis):(\\d+)" ) );
344 if ( re.exactMatch( wmsCrs ) &&
createFromSrsId( re.cap( 2 ).toInt() ) )
346 sOgcLock.lockForWrite();
347 sOgcCache.insert( crs, *
this );
355 sOgcLock.lockForWrite();
356 sOgcCache.insert( crs, *
this );
362 if ( wmsCrs.compare( QLatin1String(
"CRS:27" ), Qt::CaseInsensitive ) == 0 ||
363 wmsCrs.compare( QLatin1String(
"OGC:CRS27" ), Qt::CaseInsensitive ) == 0 )
370 if ( wmsCrs.compare( QLatin1String(
"CRS:83" ), Qt::CaseInsensitive ) == 0 ||
371 wmsCrs.compare( QLatin1String(
"OGC:CRS83" ), Qt::CaseInsensitive ) == 0 )
378 if ( wmsCrs.compare( QLatin1String(
"CRS:84" ), Qt::CaseInsensitive ) == 0 ||
379 wmsCrs.compare( QLatin1String(
"OGC:CRS84" ), Qt::CaseInsensitive ) == 0 )
384 d->mAxisInverted =
false;
385 d->mAxisInvertedDirty =
false;
387 sOgcLock.lockForWrite();
388 sOgcCache.insert( crs, *
this );
394 sOgcLock.lockForWrite();
411 if ( mCustomSrsValidation )
412 mCustomSrsValidation( *
this );
422 sSrIdCacheLock.lockForRead();
423 QHash< long, QgsCoordinateReferenceSystem >::const_iterator crsIt = sSrIdCache.constFind(
id );
424 if ( crsIt != sSrIdCache.constEnd() )
427 *
this = crsIt.value();
428 sSrIdCacheLock.unlock();
431 sSrIdCacheLock.unlock();
435 sSrIdCacheLock.lockForWrite();
436 sSrIdCache.insert(
id, *
this );
437 sSrIdCacheLock.unlock();
444 sCRSSrsIdLock.lockForRead();
445 QHash< long, QgsCoordinateReferenceSystem >::const_iterator crsIt = sSrsIdCache.constFind(
id );
446 if ( crsIt != sSrsIdCache.constEnd() )
449 *
this = crsIt.value();
450 sCRSSrsIdLock.unlock();
453 sCRSSrsIdLock.unlock();
457 QStringLiteral(
"srs_id" ), QString::number(
id ) );
459 sCRSSrsIdLock.lockForWrite();
460 sSrsIdCache.insert(
id, *
this );
461 sCRSSrsIdLock.unlock();
466 bool QgsCoordinateReferenceSystem::loadFromDatabase(
const QString &db,
const QString &expression,
const QString &value )
470 QgsDebugMsgLevel(
"load CRS from " + db +
" where " + expression +
" is " + value, 3 );
474 QFileInfo myInfo( db );
475 if ( !myInfo.exists() )
477 QgsDebugMsg(
"failed : " + db +
" does not exist!" );
485 myResult = openDatabase( db, database );
486 if ( myResult != SQLITE_OK )
503 QString mySql =
"select srs_id,description,projection_acronym," 504 "ellipsoid_acronym,parameters,srid,auth_name||':'||auth_id,is_geo " 506 statement = database.
prepare( mySql, myResult );
508 if ( myResult == SQLITE_OK && statement.
step() == SQLITE_ROW )
517 d->mIsGeographic = statement.
columnAsText( 7 ).toInt() != 0;
518 d->mAxisInvertedDirty =
true;
522 d->mAuthId = QStringLiteral(
"USER:%1" ).arg( d->mSrsId );
524 else if ( d->mAuthId.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
526 OSRDestroySpatialReference( d->mCRS );
527 d->mCRS = OSRNewSpatialReference(
nullptr );
528 d->mIsValid = OSRSetFromUserInput( d->mCRS, d->mAuthId.toLower().toLatin1() ) == OGRERR_NONE;
534 setProj4String( d->mProj4 );
546 if ( d->mAxisInvertedDirty )
548 OGRAxisOrientation orientation;
549 OSRGetAxis( d->mCRS, OSRIsGeographic( d->mCRS ) ?
"GEOGCS" :
"PROJCS", 0, &orientation );
552 if ( orientation == OAO_Other && d->mAuthId.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
556 if ( OSRImportFromEPSGA( crs, d->mAuthId.midRef( 5 ).toInt() ) == OGRERR_NONE )
558 OSRGetAxis( crs, OSRIsGeographic( crs ) ?
"GEOGCS" :
"PROJCS", 0, &orientation );
561 OSRDestroySpatialReference( crs );
564 d->mAxisInverted = orientation == OAO_North;
565 d->mAxisInvertedDirty =
false;
568 return d->mAxisInverted;
575 sCRSWktLock.lockForRead();
576 QHash< QString, QgsCoordinateReferenceSystem >::const_iterator crsIt = sWktCache.constFind( wkt );
577 if ( crsIt != sWktCache.constEnd() )
580 *
this = crsIt.value();
581 sCRSWktLock.unlock();
584 sCRSWktLock.unlock();
592 QgsDebugMsgLevel( QStringLiteral(
"theWkt is uninitialized, operation failed" ), 4 );
595 QByteArray ba = wkt.toLatin1();
596 const char *pWkt = ba.data();
598 OGRErr myInputResult = OSRImportFromWkt( d->mCRS, const_cast< char ** >( & pWkt ) );
600 if ( myInputResult != OGRERR_NONE )
602 QgsDebugMsg( QStringLiteral(
"\n---------------------------------------------------------------" ) );
603 QgsDebugMsg( QStringLiteral(
"This CRS could *** NOT *** be set from the supplied Wkt " ) );
605 QgsDebugMsg( QStringLiteral(
"UNUSED WKT: %1" ).arg( pWkt ) );
606 QgsDebugMsg( QStringLiteral(
"---------------------------------------------------------------\n" ) );
608 sCRSWktLock.lockForWrite();
609 sWktCache.insert( wkt, *
this );
610 sCRSWktLock.unlock();
614 if ( OSRAutoIdentifyEPSG( d->mCRS ) == OGRERR_NONE )
616 QString
authid = QStringLiteral(
"%1:%2" )
617 .arg( OSRGetAuthorityName( d->mCRS,
nullptr ),
618 OSRGetAuthorityCode( d->mCRS,
nullptr ) );
620 sCRSWktLock.lockForWrite();
621 sWktCache.insert( wkt, *
this );
622 sCRSWktLock.unlock();
631 char *proj4src =
nullptr;
632 OSRExportToProj4( d->mCRS, &proj4src );
641 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(2,5,0) 646 OSRExportToProj4( d->mCRS, &proj4src );
654 if ( d->mSrsId == 0 )
656 QString myName = QStringLiteral(
" * %1 (%2)" )
657 .arg( QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ),
664 sCRSWktLock.lockForWrite();
665 sWktCache.insert( wkt, *
this );
666 sCRSWktLock.unlock();
681 sProj4CacheLock.lockForRead();
682 QHash< QString, QgsCoordinateReferenceSystem >::const_iterator crsIt = sProj4Cache.constFind( proj4String );
683 if ( crsIt != sProj4Cache.constEnd() )
686 *
this = crsIt.value();
687 sProj4CacheLock.unlock();
690 sProj4CacheLock.unlock();
700 QString myProj4String = proj4String.trimmed();
704 QRegExp myProjRegExp(
"\\+proj=(\\S+)" );
705 int myStart = myProjRegExp.indexIn( myProj4String );
708 sProj4CacheLock.lockForWrite();
709 sProj4Cache.insert( proj4String, *
this );
710 sProj4CacheLock.unlock();
715 d->mProjectionAcronym = myProjRegExp.cap( 1 );
717 QRegExp myEllipseRegExp(
"\\+ellps=(\\S+)" );
718 myStart = myEllipseRegExp.indexIn( myProj4String );
721 d->mEllipsoidAcronym.clear();
725 d->mEllipsoidAcronym = myEllipseRegExp.cap( 1 );
728 QRegExp myAxisRegExp(
"\\+a=(\\S+)" );
729 myStart = myAxisRegExp.indexIn( myProj4String );
732 QgsCoordinateReferenceSystem::RecordMap myRecord;
738 myRecord = getRecord(
"select * from tbl_srs where parameters=" +
QgsSqliteUtils::quotedString( myProj4String ) +
" order by deprecated" );
739 if ( myRecord.empty() )
744 QRegExp myLat1RegExp(
"\\+lat_1=\\S+" );
745 QRegExp myLat2RegExp(
"\\+lat_2=\\S+" );
752 myStart1 = myLat1RegExp.indexIn( myProj4String, myStart1 );
753 myStart2 = myLat2RegExp.indexIn( myProj4String, myStart2 );
754 if ( myStart1 != -1 && myStart2 != -1 )
756 myLength1 = myLat1RegExp.matchedLength();
757 myLength2 = myLat2RegExp.matchedLength();
762 if ( !lat1Str.isEmpty() && !lat2Str.isEmpty() )
765 QString proj4StringModified = myProj4String;
770 myStart2 = myLat2RegExp.indexIn( proj4String, myStart2 );
772 QgsDebugMsgLevel( QStringLiteral(
"trying proj4string match with swapped lat_1,lat_2" ), 4 );
773 myRecord = getRecord(
"select * from tbl_srs where parameters=" +
QgsSqliteUtils::quotedString( proj4StringModified.trimmed() ) +
" order by deprecated" );
777 if ( myRecord.empty() )
784 QString sql = QStringLiteral(
"SELECT * FROM tbl_srs WHERE " );
791 QStringList myParams;
792 Q_FOREACH (
const QString ¶m, myProj4String.split( QRegExp(
"\\s+(?=\\+)" ), QString::SkipEmptyParts ) )
794 QString arg = QStringLiteral(
"' '||parameters||' ' LIKE %1" ).arg(
QgsSqliteUtils::quotedString( QStringLiteral(
"% %1 %" ).arg( param.trimmed() ) ) );
795 if ( param.startsWith( QLatin1String(
"+datum=" ) ) )
802 delim = QStringLiteral(
" AND " );
803 myParams << param.trimmed();
807 if ( !datum.isEmpty() )
809 myRecord = getRecord( sql + delim + datum +
" order by deprecated" );
812 if ( myRecord.empty() )
815 myRecord = getRecord( sql +
" order by deprecated" );
818 if ( !myRecord.empty() )
821 QStringList foundParams;
822 Q_FOREACH (
const QString ¶m, myRecord[
"parameters"].split( QRegExp(
"\\s+(?=\\+)" ), QString::SkipEmptyParts ) )
824 if ( !param.startsWith( QLatin1String(
"+datum=" ) ) )
825 foundParams << param.trimmed();
831 if ( myParams != foundParams )
838 if ( !myRecord.empty() )
840 mySrsId = myRecord[QStringLiteral(
"srs_id" )].toLong();
849 setProj4String( myProj4String );
864 QgsDebugMsgLevel( QStringLiteral(
"Projection is not found in databases." ), 4 );
866 setProj4String( myProj4String );
869 sProj4CacheLock.lockForWrite();
870 sProj4Cache.insert( proj4String, *
this );
871 sProj4CacheLock.unlock();
877 QgsCoordinateReferenceSystem::RecordMap QgsCoordinateReferenceSystem::getRecord(
const QString &sql )
879 QString myDatabaseFileName;
880 QgsCoordinateReferenceSystem::RecordMap myMap;
882 QString myFieldValue;
889 QFileInfo myInfo( myDatabaseFileName );
890 if ( !myInfo.exists() )
892 QgsDebugMsg(
"failed : " + myDatabaseFileName +
" does not exist!" );
897 myResult = openDatabase( myDatabaseFileName, database );
898 if ( myResult != SQLITE_OK )
903 statement = database.
prepare( sql, myResult );
905 if ( myResult == SQLITE_OK && statement.
step() == SQLITE_ROW )
909 for (
int myColNo = 0; myColNo < myColumnCount; myColNo++ )
911 myFieldName = statement.
columnName( myColNo );
913 myMap[myFieldName] = myFieldValue;
915 if ( statement.
step() != SQLITE_DONE )
917 QgsDebugMsgLevel( QStringLiteral(
"Multiple records found in srs.db" ), 4 );
929 QFileInfo myFileInfo;
930 myFileInfo.setFile( myDatabaseFileName );
931 if ( !myFileInfo.exists() )
933 QgsDebugMsg( QStringLiteral(
"user qgis.db not found" ) );
938 myResult = openDatabase( myDatabaseFileName, database );
939 if ( myResult != SQLITE_OK )
944 statement = database.
prepare( sql, myResult );
946 if ( myResult == SQLITE_OK && statement.
step() == SQLITE_ROW )
950 for (
int myColNo = 0; myColNo < myColumnCount; myColNo++ )
952 myFieldName = statement.
columnName( myColNo );
954 myMap[myFieldName] = myFieldValue;
957 if ( statement.
step() != SQLITE_DONE )
959 QgsDebugMsgLevel( QStringLiteral(
"Multiple records found in srs.db" ), 4 );
990 if ( d->mDescription.isNull() )
996 return d->mDescription;
1002 if ( d->mProjectionAcronym.isNull() )
1008 return d->mProjectionAcronym;
1014 if ( d->mEllipsoidAcronym.isNull() )
1020 return d->mEllipsoidAcronym;
1029 if ( d->mProj4.isEmpty() )
1031 char *proj4src =
nullptr;
1032 OSRExportToProj4( d->mCRS, &proj4src );
1033 d->mProj4 = proj4src;
1034 CPLFree( proj4src );
1037 return d->mProj4.trimmed();
1042 return d->mIsGeographic;
1050 return d->mMapUnits;
1064 int result = openDatabase( databaseFileName, database );
1065 if ( result != SQLITE_OK )
1070 QString sql = QStringLiteral(
"select west_bound_lon, north_bound_lat, east_bound_lon, south_bound_lat from tbl_bounds " 1073 statement = database.
prepare( sql, result );
1076 if ( result == SQLITE_OK )
1078 if ( statement.
step() == SQLITE_ROW )
1099 void QgsCoordinateReferenceSystem::setInternalId(
long srsId )
1104 void QgsCoordinateReferenceSystem::setAuthId(
const QString &authId )
1107 d->mAuthId = authId;
1109 void QgsCoordinateReferenceSystem::setSrid(
long srid )
1114 void QgsCoordinateReferenceSystem::setDescription(
const QString &
description )
1119 void QgsCoordinateReferenceSystem::setProj4String(
const QString &proj4String )
1122 d->mProj4 = proj4String;
1126 OSRDestroySpatialReference( d->mCRS );
1127 d->mCRS = OSRNewSpatialReference(
nullptr );
1128 d->mIsValid = OSRImportFromProj4( d->mCRS, proj4String.trimmed().toLatin1().constData() ) == OGRERR_NONE;
1133 projCtx pContext = pj_ctx_alloc();
1134 projPJ proj = pj_init_plus_ctx( pContext, proj4String.trimmed().toLatin1().constData() );
1137 QgsDebugMsgLevel( QStringLiteral(
"proj.4 string rejected by pj_init_plus_ctx()" ), 4 );
1138 d->mIsValid =
false;
1144 pj_ctx_free( pContext );
1149 void QgsCoordinateReferenceSystem::setGeographicFlag(
bool geoFlag )
1152 d->mIsGeographic = geoFlag;
1154 void QgsCoordinateReferenceSystem::setEpsg(
long epsg )
1157 d->mAuthId = QStringLiteral(
"EPSG:%1" ).arg( epsg );
1159 void QgsCoordinateReferenceSystem::setProjectionAcronym(
const QString &
projectionAcronym )
1164 void QgsCoordinateReferenceSystem::setEllipsoidAcronym(
const QString &
ellipsoidAcronym )
1170 void QgsCoordinateReferenceSystem::setMapUnits()
1179 char *unitName =
nullptr;
1181 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(2,5,0) 1184 OSRFixup( d->mCRS );
1187 if ( OSRIsProjected( d->mCRS ) )
1189 double toMeter = OSRGetLinearUnits( d->mCRS, &unitName );
1190 QString unit( unitName );
1198 static const double SMALL_NUM = 1e-3;
1200 if ( std::fabs( toMeter - FEET_TO_METER ) < SMALL_NUM )
1201 unit = QStringLiteral(
"Foot" );
1205 else if ( unit == QLatin1String(
"Foot" ) )
1214 OSRGetAngularUnits( d->mCRS, &unitName );
1215 QString unit( unitName );
1216 if ( unit == QLatin1String(
"degree" ) )
1228 if ( d->mEllipsoidAcronym.isNull() || d->mProjectionAcronym.isNull()
1231 QgsDebugMsgLevel(
"QgsCoordinateReferenceSystem::findMatchingProj will only " 1232 "work if prj acr ellipsoid acr and proj4string are set" 1233 " and the current projection is valid!", 4 );
1243 QString mySql = QString(
"select srs_id,parameters from tbl_srs where " 1244 "projection_acronym=%1 and ellipsoid_acronym=%2 order by deprecated" )
1251 myResult = openDatabase( myDatabaseFileName, database );
1252 if ( myResult != SQLITE_OK )
1257 statement = database.
prepare( mySql, myResult );
1258 if ( myResult == SQLITE_OK )
1261 while ( statement.
step() == SQLITE_ROW )
1265 if (
toProj4() == myProj4String.trimmed() )
1267 return mySrsId.toLong();
1278 myResult = openDatabase( myDatabaseFileName, database );
1279 if ( myResult != SQLITE_OK )
1284 statement = database.
prepare( mySql, myResult );
1286 if ( myResult == SQLITE_OK )
1288 while ( statement.
step() == SQLITE_ROW )
1292 if (
toProj4() == myProj4String.trimmed() )
1294 return mySrsId.toLong();
1304 return ( !d->mIsValid && !srs.d->mIsValid ) ||
1305 ( d->mIsValid && srs.d->mIsValid && srs.
authid() ==
authid() );
1310 return !( *
this == srs );
1315 if ( d->mWkt.isEmpty() )
1317 char *wkt =
nullptr;
1318 if ( OSRExportToWkt( d->mCRS, &wkt ) == OGRERR_NONE )
1331 QDomNode srsNode = node.namedItem( QStringLiteral(
"spatialrefsys" ) );
1333 if ( ! srsNode.isNull() )
1335 bool initialized =
false;
1337 long srsid = srsNode.namedItem( QStringLiteral(
"srsid" ) ).toElement().text().toLong();
1343 myNode = srsNode.namedItem( QStringLiteral(
"authid" ) );
1344 if ( !myNode.isNull() )
1355 myNode = srsNode.namedItem( QStringLiteral(
"epsg" ) );
1356 if ( !myNode.isNull() )
1369 myNode = srsNode.namedItem( QStringLiteral(
"proj4" ) );
1375 myNode = srsNode.namedItem( QStringLiteral(
"proj4" ) );
1376 setProj4String( myNode.toElement().text() );
1378 myNode = srsNode.namedItem( QStringLiteral(
"srsid" ) );
1379 setInternalId( myNode.toElement().text().toLong() );
1381 myNode = srsNode.namedItem( QStringLiteral(
"srid" ) );
1382 setSrid( myNode.toElement().text().toLong() );
1384 myNode = srsNode.namedItem( QStringLiteral(
"authid" ) );
1385 setAuthId( myNode.toElement().text() );
1387 myNode = srsNode.namedItem( QStringLiteral(
"description" ) );
1388 setDescription( myNode.toElement().text() );
1390 myNode = srsNode.namedItem( QStringLiteral(
"projectionacronym" ) );
1391 setProjectionAcronym( myNode.toElement().text() );
1393 myNode = srsNode.namedItem( QStringLiteral(
"ellipsoidacronym" ) );
1394 setEllipsoidAcronym( myNode.toElement().text() );
1396 myNode = srsNode.namedItem( QStringLiteral(
"geographicflag" ) );
1397 if ( myNode.toElement().text().compare( QLatin1String(
"true" ) ) )
1399 setGeographicFlag(
true );
1403 setGeographicFlag(
false );
1413 if ( d->mSrsId == 0 )
1415 QString myName = QStringLiteral(
" * %1 (%2)" )
1416 .arg( QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ),
1426 d =
new QgsCoordinateReferenceSystemPrivate();
1435 QDomElement myLayerNode = node.toElement();
1436 QDomElement mySrsElement = doc.createElement( QStringLiteral(
"spatialrefsys" ) );
1438 QDomElement myProj4Element = doc.createElement( QStringLiteral(
"proj4" ) );
1439 myProj4Element.appendChild( doc.createTextNode(
toProj4() ) );
1440 mySrsElement.appendChild( myProj4Element );
1442 QDomElement mySrsIdElement = doc.createElement( QStringLiteral(
"srsid" ) );
1443 mySrsIdElement.appendChild( doc.createTextNode( QString::number(
srsid() ) ) );
1444 mySrsElement.appendChild( mySrsIdElement );
1446 QDomElement mySridElement = doc.createElement( QStringLiteral(
"srid" ) );
1447 mySridElement.appendChild( doc.createTextNode( QString::number(
postgisSrid() ) ) );
1448 mySrsElement.appendChild( mySridElement );
1450 QDomElement myEpsgElement = doc.createElement( QStringLiteral(
"authid" ) );
1451 myEpsgElement.appendChild( doc.createTextNode(
authid() ) );
1452 mySrsElement.appendChild( myEpsgElement );
1454 QDomElement myDescriptionElement = doc.createElement( QStringLiteral(
"description" ) );
1455 myDescriptionElement.appendChild( doc.createTextNode(
description() ) );
1456 mySrsElement.appendChild( myDescriptionElement );
1458 QDomElement myProjectionAcronymElement = doc.createElement( QStringLiteral(
"projectionacronym" ) );
1459 myProjectionAcronymElement.appendChild( doc.createTextNode(
projectionAcronym() ) );
1460 mySrsElement.appendChild( myProjectionAcronymElement );
1462 QDomElement myEllipsoidAcronymElement = doc.createElement( QStringLiteral(
"ellipsoidacronym" ) );
1463 myEllipsoidAcronymElement.appendChild( doc.createTextNode(
ellipsoidAcronym() ) );
1464 mySrsElement.appendChild( myEllipsoidAcronymElement );
1466 QDomElement myGeographicFlagElement = doc.createElement( QStringLiteral(
"geographicflag" ) );
1467 QString myGeoFlagText = QStringLiteral(
"false" );
1470 myGeoFlagText = QStringLiteral(
"true" );
1473 myGeographicFlagElement.appendChild( doc.createTextNode( myGeoFlagText ) );
1474 mySrsElement.appendChild( myGeographicFlagElement );
1476 myLayerNode.appendChild( mySrsElement );
1490 QString QgsCoordinateReferenceSystem::proj4FromSrsId(
const int srsId )
1492 QString myDatabaseFileName;
1493 QString myProjString;
1494 QString mySql = QStringLiteral(
"select parameters from tbl_srs where srs_id = %1 order by deprecated" ).arg( srsId );
1503 QFileInfo myFileInfo;
1504 myFileInfo.setFile( myDatabaseFileName );
1505 if ( !myFileInfo.exists() )
1507 QgsDebugMsg( QStringLiteral(
"users qgis.db not found" ) );
1520 rc = openDatabase( myDatabaseFileName, database );
1526 statement = database.
prepare( mySql, rc );
1528 if ( rc == SQLITE_OK )
1530 if ( statement.
step() == SQLITE_ROW )
1536 return myProjString;
1543 myResult = database.
open_v2( path, SQLITE_OPEN_READONLY,
nullptr );
1545 myResult = database.
open( path );
1547 if ( myResult != SQLITE_OK )
1556 .arg( database.
errorMessage() ), QObject::tr(
"CRS" ) );
1563 mCustomSrsValidation = f;
1568 return mCustomSrsValidation;
1571 void QgsCoordinateReferenceSystem::debugPrint()
1573 QgsDebugMsg( QStringLiteral(
"***SpatialRefSystem***" ) );
1574 QgsDebugMsg(
"* Valid : " + ( d->mIsValid ? QString(
"true" ) : QString(
"false" ) ) );
1575 QgsDebugMsg(
"* SrsId : " + QString::number( d->mSrsId ) );
1581 QgsDebugMsg( QStringLiteral(
"* Units : meters" ) );
1585 QgsDebugMsg( QStringLiteral(
"* Units : feet" ) );
1589 QgsDebugMsg( QStringLiteral(
"* Units : degrees" ) );
1596 d->mValidationHint = html;
1601 return d->mValidationHint;
1617 QString proj4String = d->mProj4;
1618 if ( proj4String.isEmpty() )
1631 if ( getRecordCount() == 0 )
1633 mySql =
"insert into tbl_srs (srs_id,description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values (" 1637 +
',' + quotedEllipsoidString
1643 mySql =
"insert into tbl_srs (description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values (" 1646 +
',' + quotedEllipsoidString
1655 if ( myResult != SQLITE_OK )
1657 QgsDebugMsg( QStringLiteral(
"Can't open or create database %1: %2" )
1662 statement = database.
prepare( mySql, myResult );
1665 if ( myResult == SQLITE_OK && statement.
step() == SQLITE_DONE )
1669 returnId = sqlite3_last_insert_rowid( database.get() );
1670 setInternalId( returnId );
1671 if (
authid().isEmpty() )
1672 setAuthId( QStringLiteral(
"USER:%1" ).arg( returnId ) );
1673 setDescription( name );
1678 QStringList projectionsProj4 = settings.
value( QStringLiteral(
"UI/recentProjectionsProj4" ) ).toStringList();
1679 QStringList projectionsAuthId = settings.
value( QStringLiteral(
"UI/recentProjectionsAuthId" ) ).toStringList();
1682 projectionsProj4.append(
toProj4() );
1683 projectionsAuthId.append(
authid() );
1684 settings.
setValue( QStringLiteral(
"UI/recentProjectionsProj4" ), projectionsProj4 );
1685 settings.
setValue( QStringLiteral(
"UI/recentProjectionsAuthId" ), projectionsAuthId );
1695 long QgsCoordinateReferenceSystem::getRecordCount()
1700 long myRecordCount = 0;
1703 if ( myResult != SQLITE_OK )
1709 QString mySql = QStringLiteral(
"select count(*) from tbl_srs" );
1710 statement = database.
prepare( mySql, myResult );
1711 if ( myResult == SQLITE_OK )
1713 if ( statement.
step() == SQLITE_ROW )
1715 QString myRecordCountString = statement.
columnAsText( 0 );
1716 myRecordCount = myRecordCountString.toLong();
1719 return myRecordCount;
1723 bool QgsCoordinateReferenceSystem::loadWkts( QHash<int, QString> &wkts,
const char *filename )
1726 const char *pszFilename = CPLFindFile(
"gdal", filename );
1730 QFile csv( pszFilename );
1731 if ( !csv.open( QIODevice::ReadOnly ) )
1734 QTextStream lines( &csv );
1738 QString line = lines.readLine();
1739 if ( line.isNull() )
1742 if ( line.trimmed().isEmpty() || line.startsWith(
'#' ) )
1746 else if ( line.startsWith( QLatin1String(
"include " ) ) )
1748 if ( !loadWkts( wkts, line.mid( 8 ).toUtf8() ) )
1753 int pos = line.indexOf(
',' );
1758 int epsg = line.leftRef( pos ).toInt( &ok );
1762 wkts.insert( epsg, line.mid( pos + 1 ) );
1771 bool QgsCoordinateReferenceSystem::loadIds( QHash<int, QString> &wkts )
1775 Q_FOREACH (
const QString &csv, QStringList() <<
"gcs.csv" <<
"pcs.csv" <<
"vertcs.csv" <<
"compdcs.csv" <<
"geoccs.csv" )
1777 QString filename = CPLFindFile(
"gdal", csv.toUtf8() );
1779 QFile f( filename );
1780 if ( !f.open( QIODevice::ReadOnly ) )
1783 QTextStream lines( &f );
1790 QString line = lines.readLine();
1791 if ( line.isNull() )
1794 if ( line.trimmed().isEmpty() )
1797 int pos = line.indexOf(
',' );
1800 qWarning(
"No id found in: %s", qPrintable( line ) );
1805 int epsg = line.leftRef( pos ).toInt( &ok );
1808 qWarning(
"No valid id found in: %s", qPrintable( line ) );
1813 if ( epsg == 2218 || epsg == 2221 || epsg == 2296 || epsg == 2297 || epsg == 2298 || epsg == 2299 || epsg == 2300 || epsg == 2301 || epsg == 2302 ||
1814 epsg == 2303 || epsg == 2304 || epsg == 2305 || epsg == 2306 || epsg == 2307 || epsg == 2963 || epsg == 2985 || epsg == 2986 || epsg == 3052 ||
1815 epsg == 3053 || epsg == 3139 || epsg == 3144 || epsg == 3145 || epsg == 3173 || epsg == 3295 || epsg == 3993 || epsg == 4087 || epsg == 4088 ||
1816 epsg == 5017 || epsg == 5221 || epsg == 5224 || epsg == 5225 || epsg == 5514 || epsg == 5515 || epsg == 5516 || epsg == 5819 || epsg == 5820 ||
1817 epsg == 5821 || epsg == 6200 || epsg == 6201 || epsg == 6202 || epsg == 6244 || epsg == 6245 || epsg == 6246 || epsg == 6247 || epsg == 6248 ||
1818 epsg == 6249 || epsg == 6250 || epsg == 6251 || epsg == 6252 || epsg == 6253 || epsg == 6254 || epsg == 6255 || epsg == 6256 || epsg == 6257 ||
1819 epsg == 6258 || epsg == 6259 || epsg == 6260 || epsg == 6261 || epsg == 6262 || epsg == 6263 || epsg == 6264 || epsg == 6265 || epsg == 6266 ||
1820 epsg == 6267 || epsg == 6268 || epsg == 6269 || epsg == 6270 || epsg == 6271 || epsg == 6272 || epsg == 6273 || epsg == 6274 || epsg == 6275 ||
1821 epsg == 6966 || epsg == 7082 || epsg == 32600 || epsg == 32663 || epsg == 32700 )
1824 if ( OSRImportFromEPSG( crs, epsg ) != OGRERR_NONE )
1826 qDebug(
"EPSG %d: not imported", epsg );
1830 char *wkt =
nullptr;
1831 if ( OSRExportToWkt( crs, &wkt ) != OGRERR_NONE )
1833 qWarning(
"EPSG %d: not exported to WKT", epsg );
1837 wkts.insert( epsg, wkt );
1845 QgsDebugMsgLevel( QStringLiteral(
"Loaded %1/%2 from %3" ).arg( QString::number( n ), QString::number( l ), filename.toUtf8().constData() ), 4 );
1848 OSRDestroySpatialReference( crs );
1855 setlocale( LC_ALL,
"C" );
1857 syncDatumTransform( dbFilePath );
1859 int inserted = 0, updated = 0, deleted = 0, errors = 0;
1864 if ( database.
open( dbFilePath ) != SQLITE_OK )
1870 if ( sqlite3_exec( database.get(),
"BEGIN TRANSACTION",
nullptr,
nullptr, nullptr ) != SQLITE_OK )
1877 if ( sqlite3_exec( database.get(),
"alter table tbl_srs add noupdate boolean",
nullptr,
nullptr, nullptr ) == SQLITE_OK )
1878 ( void )sqlite3_exec( database.get(),
"update tbl_srs set noupdate=(auth_name='EPSG' and auth_id in (5513,5514,5221,2065,102067,4156,4818))",
nullptr,
nullptr, nullptr );
1880 ( void )sqlite3_exec( database.get(),
"UPDATE tbl_srs SET srid=141001 WHERE srid=41001 AND auth_name='OSGEO' AND auth_id='41001'",
nullptr,
nullptr, nullptr );
1885 char *errMsg =
nullptr;
1889 QHash<int, QString> wkts;
1891 loadWkts( wkts,
"epsg.wkt" );
1893 QgsDebugMsgLevel( QStringLiteral(
"%1 WKTs loaded" ).arg( wkts.count() ), 4 );
1895 for ( QHash<int, QString>::const_iterator it = wkts.constBegin(); it != wkts.constEnd(); ++it )
1897 QByteArray ba( it.value().toUtf8() );
1898 char *psz = ba.data();
1901 OSRDestroySpatialReference( crs );
1903 crs = OSRNewSpatialReference(
nullptr );
1905 OGRErr ogrErr = OSRImportFromWkt( crs, &psz );
1906 if ( ogrErr != OGRERR_NONE )
1909 if ( OSRExportToProj4( crs, &psz ) != OGRERR_NONE )
1916 proj4 = proj4.trimmed();
1920 if ( proj4.isEmpty() )
1923 QString name( OSRIsGeographic( crs ) ? OSRGetAttrValue( crs,
"GEOGCS", 0 ) :
1924 OSRIsGeocentric( crs ) ? OSRGetAttrValue( crs,
"GEOCCS", 0 ) :
1925 OSRGetAttrValue( crs,
"PROJCS", 0 ) );
1926 if ( name.isEmpty() )
1927 name = QObject::tr(
"Imported from GDAL" );
1929 bool deprecated = name.contains( QLatin1Literal(
"(deprecated)" ) );
1931 sql = QStringLiteral(
"SELECT parameters,description,deprecated,noupdate FROM tbl_srs WHERE auth_name='EPSG' AND auth_id='%1'" ).arg( it.key() );
1932 statement = database.
prepare( sql, result );
1933 if ( result != SQLITE_OK )
1941 bool srsDeprecated = deprecated;
1942 if ( statement.
step() == SQLITE_ROW )
1946 srsDeprecated = statement.
columnAsText( 2 ).toInt() != 0;
1954 if ( !srsProj4.isEmpty() || !srsDesc.isEmpty() )
1956 if ( proj4 != srsProj4 || name != srsDesc || deprecated != srsDeprecated )
1959 sql = QStringLiteral(
"UPDATE tbl_srs SET parameters=%1,description=%2,deprecated=%3 WHERE auth_name='EPSG' AND auth_id=%4" )
1962 .arg( deprecated ? 1 : 0 )
1965 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, &errMsg ) != SQLITE_OK )
1967 QgsDebugMsg( QStringLiteral(
"Could not execute: %1 [%2/%3]\n" ).arg(
1970 errMsg ? errMsg :
"(unknown error)" ) );
1972 sqlite3_free( errMsg );
1983 QRegExp projRegExp(
"\\+proj=(\\S+)" );
1984 if ( projRegExp.indexIn( proj4 ) < 0 )
1986 QgsDebugMsgLevel( QStringLiteral(
"EPSG %1: no +proj argument found [%2]" ).arg( it.key() ).arg( proj4 ), 4 );
1990 QRegExp ellipseRegExp(
"\\+ellps=(\\S+)" );
1992 if ( ellipseRegExp.indexIn( proj4 ) >= 0 )
1994 ellps = ellipseRegExp.cap( 1 );
2006 sql = QStringLiteral(
"INSERT INTO tbl_srs(description,projection_acronym,ellipsoid_acronym,parameters,srid,auth_name,auth_id,is_geo,deprecated) VALUES (%1,%2,%3,%4,%5,'EPSG',%5,%6,%7)" )
2012 .arg( OSRIsGeographic( crs ) )
2013 .arg( deprecated ? 1 : 0 );
2016 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, &errMsg ) == SQLITE_OK )
2022 qCritical(
"Could not execute: %s [%s/%s]\n",
2023 sql.toLocal8Bit().constData(),
2024 sqlite3_errmsg( database.get() ),
2025 errMsg ? errMsg :
"(unknown error)" );
2029 sqlite3_free( errMsg );
2035 OSRDestroySpatialReference( crs );
2038 sql = QStringLiteral(
"DELETE FROM tbl_srs WHERE auth_name='EPSG' AND NOT auth_id IN (" );
2040 QHash<int, QString>::const_iterator it = wkts.constBegin();
2041 for ( ; it != wkts.constEnd(); ++it )
2043 sql += delim + QString::number( it.key() );
2046 sql += QLatin1String(
") AND NOT noupdate" );
2048 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, nullptr ) == SQLITE_OK )
2050 deleted = sqlite3_changes( database.get() );
2055 qCritical(
"Could not execute: %s [%s]\n",
2056 sql.toLocal8Bit().constData(),
2057 sqlite3_errmsg( database.get() ) );
2060 projCtx pContext = pj_ctx_alloc();
2062 #if !defined(PJ_VERSION) || PJ_VERSION!=470 2063 sql = QStringLiteral(
"select auth_name,auth_id,parameters from tbl_srs WHERE auth_name<>'EPSG' AND NOT deprecated AND NOT noupdate" );
2064 statement = database.
prepare( sql, result );
2065 if ( result == SQLITE_OK )
2067 while ( statement.
step() == SQLITE_ROW )
2073 QString input = QStringLiteral(
"+init=%1:%2" ).arg( auth_name.toLower(), auth_id );
2074 projPJ pj = pj_init_plus_ctx( pContext, input.toLatin1() );
2077 input = QStringLiteral(
"+init=%1:%2" ).arg( auth_name.toUpper(), auth_id );
2078 pj = pj_init_plus_ctx( pContext, input.toLatin1() );
2083 char *def = pj_get_def( pj, 0 );
2089 input.prepend(
' ' ).append(
' ' );
2090 if ( proj4.startsWith( input ) )
2092 proj4 = proj4.mid( input.size() );
2093 proj4 = proj4.trimmed();
2096 if ( proj4 != params )
2098 sql = QStringLiteral(
"UPDATE tbl_srs SET parameters=%1 WHERE auth_name=%2 AND auth_id=%3" )
2103 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, &errMsg ) == SQLITE_OK )
2109 qCritical(
"Could not execute: %s [%s/%s]\n",
2110 sql.toLocal8Bit().constData(),
2111 sqlite3_errmsg( database.get() ),
2112 errMsg ? errMsg :
"(unknown error)" );
2114 sqlite3_free( errMsg );
2121 QgsDebugMsgLevel( QStringLiteral(
"could not retrieve proj string for %1 from PROJ" ).arg( input ), 4 );
2126 QgsDebugMsgLevel( QStringLiteral(
"could not retrieve crs for %1 from PROJ" ).arg( input ), 3 );
2135 QgsDebugMsg( QStringLiteral(
"Could not execute: %1 [%2]\n" ).arg(
2137 sqlite3_errmsg( database.get() ) ) );
2141 pj_ctx_free( pContext );
2143 if ( sqlite3_exec( database.get(),
"COMMIT",
nullptr,
nullptr, nullptr ) != SQLITE_OK )
2145 QgsDebugMsg( QStringLiteral(
"Could not commit transaction: %1 [%2]\n" ).arg(
2147 sqlite3_errmsg( database.get() ) )
2152 Q_UNUSED( deleted );
2153 QgsDebugMsgLevel( QStringLiteral(
"CRS update (inserted:%1 updated:%2 deleted:%3 errors:%4)" ).arg( QString::number( inserted ), QString::number( updated ), QString::number( deleted ), QString::number( errors ) ), 4 );
2158 return updated + inserted;
2161 bool QgsCoordinateReferenceSystem::syncDatumTransform(
const QString &dbPath )
2163 const char *filename = CSVFilename(
"datum_shift.csv" );
2164 FILE *fp = VSIFOpen( filename,
"rb" );
2170 char **fieldnames = CSVReadParseLine( fp );
2182 {
"SOURCE_CRS_CODE",
"source_crs_code", -1 },
2183 {
"TARGET_CRS_CODE",
"target_crs_code", -1 },
2184 {
"REMARKS",
"remarks", -1 },
2185 {
"COORD_OP_SCOPE",
"scope", -1 },
2186 {
"AREA_OF_USE_CODE",
"area_of_use_code", -1 },
2192 {
"DEPRECATED",
"deprecated", -1 },
2193 {
"COORD_OP_METHOD_CODE",
"coord_op_method_code", -1 },
2201 {
"PREFERRED",
"preferred", -1 },
2202 {
"COORD_OP_CODE",
"coord_op_code", -1 },
2205 QString update = QStringLiteral(
"UPDATE tbl_datum_transform SET " );
2206 QString insert, values;
2208 int n = CSLCount( fieldnames );
2210 int idxid = -1, idxrx = -1, idxry = -1, idxrz = -1, idxmcode = -1;
2211 for (
unsigned int i = 0; i <
sizeof( map ) /
sizeof( *map ); i++ )
2213 bool last = i ==
sizeof( map ) /
sizeof( *map ) - 1;
2215 map[i].idx = CSLFindString( fieldnames, map[i].src );
2216 if ( map[i].idx < 0 )
2218 qWarning(
"field %s not found", map[i].src );
2219 CSLDestroy( fieldnames );
2224 if ( strcmp( map[i].src,
"COORD_OP_CODE" ) == 0 )
2226 if ( strcmp( map[i].src,
"RX" ) == 0 )
2228 if ( strcmp( map[i].src,
"RY" ) == 0 )
2230 if ( strcmp( map[i].src,
"RZ" ) == 0 )
2232 if ( strcmp( map[i].src,
"COORD_OP_METHOD_CODE" ) == 0 )
2242 update += QLatin1String(
" WHERE " );
2250 update += QStringLiteral(
"%1=%%2" ).arg( map[i].dst ).arg( i + 1 );
2252 insert += map[i].dst;
2253 values += QStringLiteral(
"%%1" ).arg( i + 1 );
2256 insert =
"INSERT INTO tbl_datum_transform(" + insert +
") VALUES (" + values +
')';
2258 CSLDestroy( fieldnames );
2260 Q_ASSERT( idxid >= 0 );
2261 Q_ASSERT( idxrx >= 0 );
2262 Q_ASSERT( idxry >= 0 );
2263 Q_ASSERT( idxrz >= 0 );
2266 int openResult = database.
open( dbPath );
2267 if ( openResult != SQLITE_OK )
2273 if ( sqlite3_exec( database.get(),
"BEGIN TRANSACTION",
nullptr,
nullptr, nullptr ) != SQLITE_OK )
2281 v.reserve(
sizeof( map ) /
sizeof( *map ) );
2285 char **values = CSVReadParseLine( fp );
2291 if ( CSLCount( values ) == 0 )
2293 CSLDestroy( values );
2297 if ( CSLCount( values ) < n )
2299 qWarning(
"Only %d columns", CSLCount( values ) );
2300 CSLDestroy( values );
2304 for (
unsigned int i = 0; i <
sizeof( map ) /
sizeof( *map ); i++ )
2306 int idx = map[i].idx;
2307 Q_ASSERT( idx != -1 );
2308 Q_ASSERT( idx < n );
2311 CSLDestroy( values );
2314 if ( v.at( idxmcode ).compare( QLatin1String(
"'9607'" ) ) == 0 )
2316 v[ idxmcode ] = QStringLiteral(
"'9606'" );
2317 v[ idxrx ] =
'\'' +
qgsDoubleToString( -( v[ idxrx ].
remove(
'\'' ).toDouble() ) ) +
'\'';
2318 v[ idxry ] =
'\'' +
qgsDoubleToString( -( v[ idxry ].
remove(
'\'' ).toDouble() ) ) +
'\'';
2319 v[ idxrz ] =
'\'' +
qgsDoubleToString( -( v[ idxrz ].
remove(
'\'' ).toDouble() ) ) +
'\'';
2325 QString sql = QStringLiteral(
"SELECT coord_op_code FROM tbl_datum_transform WHERE coord_op_code=%1" ).arg( v[ idxid ] );
2327 statement = database.
prepare( sql, prepareRes );
2328 if ( prepareRes != SQLITE_OK )
2331 if ( statement.
step() == SQLITE_ROW )
2336 sql = cOpCode.isEmpty() ? insert : update;
2337 for (
int i = 0; i < v.size(); i++ )
2339 sql = sql.arg( v[i] );
2342 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, nullptr ) != SQLITE_OK )
2344 qCritical(
"SQL: %s", sql.toUtf8().constData() );
2345 qCritical(
"Error: %s", sqlite3_errmsg( database.get() ) );
2349 if ( sqlite3_exec( database.get(),
"COMMIT",
nullptr,
nullptr, nullptr ) != SQLITE_OK )
2366 return OSRGetAuthorityName( d->mCRS,
"GEOGCS" ) + QStringLiteral(
":" ) + OSRGetAuthorityCode( d->mCRS,
"GEOGCS" );
2376 QStringList projections;
2380 projections = settings.
value( QStringLiteral(
"UI/recentProjections" ) ).toStringList();
2384 QStringList projectionsProj4 = settings.
value( QStringLiteral(
"UI/recentProjectionsProj4" ) ).toStringList();
2385 QStringList projectionsAuthId = settings.
value( QStringLiteral(
"UI/recentProjectionsAuthId" ) ).toStringList();
2386 if ( projectionsAuthId.size() >= projections.size() )
2390 projections.clear();
2391 for (
int i = 0; i < projectionsAuthId.size(); i++ )
2399 if ( i >= projectionsProj4.size() || !crs.
createFromProj4( projectionsProj4.at( i ) ) )
2405 if ( crs.
srsid() == 0 )
2410 projections << QString::number( crs.
srsid() );
2418 sSrIdCacheLock.lockForWrite();
2420 sSrIdCacheLock.unlock();
2421 sOgcLock.lockForWrite();
2424 sProj4CacheLock.lockForWrite();
2425 sProj4Cache.clear();
2426 sProj4CacheLock.unlock();
2427 sCRSWktLock.lockForWrite();
2429 sCRSWktLock.unlock();
2430 sCRSSrsIdLock.lockForWrite();
2431 sSrsIdCache.clear();
2432 sCRSSrsIdLock.unlock();
2433 sCrsStringLock.lockForWrite();
2434 sStringCache.clear();
2435 sCrsStringLock.unlock();
QString geographicCrsAuthId() const
Returns auth id of related geographic CRS.
QgsCoordinateReferenceSystem()
Constructs an invalid CRS object.
bool createFromId(long id, CrsType type=PostgisCrsId)
Sets this CRS by lookup of the given ID in the CRS database.
bool operator!=(const QgsCoordinateReferenceSystem &srs) const
Overloaded != operator used to compare to CRS's.
A rectangle specified with double values.
static QgsCoordinateReferenceSystem fromProj4(const QString &proj4)
Creates a CRS from a proj4 style formatted string.
bool createFromString(const QString &definition)
Set up this CRS from a string definition.
static QList< long > validSrsIds()
Returns a list of all valid SRS IDs present in the CRS database.
void setXMaximum(double x)
Set the maximum x value.
This class is a composition of two QSettings instances:
static QString qgisUserDatabaseFilePath()
Returns the path to the user qgis.db file.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void validate()
Perform some validation on this CRS.
static void warning(const QString &msg)
Goes to qWarning.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
static void setCustomCrsValidation(CUSTOM_CRS_VALIDATION f)
Sets custom function to force valid CRS.
QString toProj4() const
Returns a Proj4 string representation of this CRS.
const int LAT_PREFIX_LEN
The length of the string "+lat_1=".
const QgsCoordinateReferenceSystem & crs
Internal ID used by QGIS in the local SQLite database.
long saveAsUserCrs(const QString &name)
Save the proj4-string as a custom CRS.
bool createFromOgcWmsCrs(const QString &crs)
Sets this CRS to the given OGC WMS-format Coordinate Reference Systems.
QString errorMessage() const
Returns the most recent error message encountered by the database.
static Q_INVOKABLE QgsCoordinateReferenceSystem fromEpsgId(long epsg)
Creates a CRS from a given EPSG ID.
void setValidationHint(const QString &html)
Set user hint for validation.
QString ellipsoidAcronym() const
Returns the ellipsoid acronym for the ellipsoid used by the CRS.
static QgsCoordinateReferenceSystem fromWkt(const QString &wkt)
Creates a CRS from a WKT spatial ref sys definition string.
#define QgsDebugMsgLevel(str, level)
bool createFromSrid(long srid)
Sets this CRS by lookup of the given PostGIS SRID in the CRS database.
static QStringList recentProjections()
Returns a list of recently used projections.
int step()
Steps to the next record in the statement, returning the sqlite3 result code.
QString validationHint()
Gets user hint for validation.
long postgisSrid() const
Returns PostGIS SRID for the CRS.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
long findMatchingProj()
Walks the CRS databases (both system and user database) trying to match stored PROJ string to a datab...
void setYMinimum(double y)
Set the minimum y value.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
int columnCount() const
Gets the number of columns that this statement returns.
QString description() const
Returns the descriptive name of the CRS, e.g., "WGS 84" or "GDA 94 / Vicgrid94".
Degrees, for planar geographic CRS distance measurements.
QgsCoordinateReferenceSystem & operator=(const QgsCoordinateReferenceSystem &srs)
Assignment operator.
QString columnAsText(int column) const
Returns the column value from the current statement row as a string.
const QString GEO_EPSG_CRS_AUTHID
Geographic coord sys from EPSG authority.
bool isGeographic() const
Returns whether the CRS is a geographic CRS (using lat/lon coordinates)
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
int open(const QString &path)
Opens the database at the specified file path.
bool createFromWkt(const QString &wkt)
Sets this CRS using a WKT definition.
~QgsCoordinateReferenceSystem()
CrsType
Enumeration of types of IDs accepted in createFromId() method.
static CUSTOM_CRS_VALIDATION customCrsValidation()
Gets custom function.
QString projectionAcronym() const
Returns the projection acronym for the projection used by the CRS.
DistanceUnit
Units of distance.
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
const int USER_CRS_START_ID
Magick number that determines whether a projection crsid is a system (srs.db) or user (~/...
bool createFromSrsId(long srsId)
Sets this CRS by lookup of internal QGIS CRS ID in the CRS database.
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool createFromUserInput(const QString &definition)
Set up this CRS from various text formats.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
void setYMaximum(double y)
Set the maximum y value.
bool hasAxisInverted() const
Returns whether axis is inverted (e.g., for WMS 1.3) for the CRS.
This class represents a coordinate reference system (CRS).
QString toWkt() const
Returns a WKT representation of this CRS.
bool createFromProj4(const QString &projString)
Sets this CRS by passing it a PROJ style formatted string.
static QString srsDatabaseFilePath()
Returns the path to the srs.db file.
QgsUnitTypes::DistanceUnit mapUnits() const
Returns the units for the projection used by the CRS.
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
static void invalidateCache()
Clears the internal cache used to initialize QgsCoordinateReferenceSystem objects.
void(* CUSTOM_CRS_VALIDATION)(QgsCoordinateReferenceSystem &)
QgsRectangle bounds() const
Returns the approximate bounds for the region the CRS is usable within.
long srsid() const
Returns the internal CRS ID, if available.
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
bool operator==(const QgsCoordinateReferenceSystem &srs) const
Overloaded == operator used to compare to CRS's.
QString columnName(int column) const
Returns the name of column.
double columnAsDouble(int column) const
Gets column value from the current statement row as a double.
qlonglong columnAsInt64(int column) const
Gets column value from the current statement row as a long long integer (64 bits).
static int syncDatabase()
Update proj.4 parameters in our database from proj.4.
QString authid() const
Returns the authority identifier for the CRS.
static void setupESRIWktFix()
Make sure that ESRI WKT import is done properly.
void setXMinimum(double x)
Set the minimum x value.
static QgsCoordinateReferenceSystem fromSrsId(long srsId)
Creates a CRS from a specified QGIS SRS ID.
void * OGRSpatialReferenceH
static QString quotedString(const QString &value)
Returns a quoted string value, surround by ' characters and with special characters correctly escaped...
bool isValid() const
Returns whether this CRS is correctly initialized and usable.