24 #include <QTemporaryFile> 26 #include <QDomElement> 29 #include <QTextStream> 31 #include <QRegularExpression> 44 #include <ogr_srs_api.h> 45 #include <cpl_error.h> 54 QReadWriteLock QgsCoordinateReferenceSystem::sSrIdCacheLock;
55 QHash< long, QgsCoordinateReferenceSystem > QgsCoordinateReferenceSystem::sSrIdCache;
56 QReadWriteLock QgsCoordinateReferenceSystem::sOgcLock;
57 QHash< QString, QgsCoordinateReferenceSystem > QgsCoordinateReferenceSystem::sOgcCache;
58 QReadWriteLock QgsCoordinateReferenceSystem::sProj4CacheLock;
59 QHash< QString, QgsCoordinateReferenceSystem > QgsCoordinateReferenceSystem::sProj4Cache;
60 QReadWriteLock QgsCoordinateReferenceSystem::sCRSWktLock;
61 QHash< QString, QgsCoordinateReferenceSystem > QgsCoordinateReferenceSystem::sWktCache;
62 QReadWriteLock QgsCoordinateReferenceSystem::sCRSSrsIdLock;
63 QHash< long, QgsCoordinateReferenceSystem > QgsCoordinateReferenceSystem::sSrsIdCache;
64 QReadWriteLock QgsCoordinateReferenceSystem::sCrsStringLock;
65 QHash< QString, QgsCoordinateReferenceSystem > QgsCoordinateReferenceSystem::sStringCache;
71 d =
new QgsCoordinateReferenceSystemPrivate();
76 d =
new QgsCoordinateReferenceSystemPrivate();
82 d =
new QgsCoordinateReferenceSystemPrivate();
103 Q_FOREACH (
const QString &db, dbs )
105 QFileInfo myInfo( db );
106 if ( !myInfo.exists() )
108 QgsDebugMsg(
"failed : " + db +
" does not exist!" );
116 int result = openDatabase( db, database );
117 if ( result != SQLITE_OK )
119 QgsDebugMsg(
"failed : " + db +
" could not be opened!" );
123 QString sql = QStringLiteral(
"select srs_id from tbl_srs" );
125 statement = database.
prepare( sql, rc );
129 int ret = statement.
step();
131 if ( ret == SQLITE_DONE )
137 if ( ret == SQLITE_ROW )
143 QgsMessageLog::logMessage( QObject::tr(
"SQLite error: %2\nSQL: %1" ).arg( sql, sqlite3_errmsg( database.get() ) ), QObject::tr(
"SpatiaLite" ) );
148 std::sort( results.begin(), results.end() );
212 sCrsStringLock.lockForRead();
213 QHash< QString, QgsCoordinateReferenceSystem >::const_iterator crsIt = sStringCache.constFind( definition );
214 if ( crsIt != sStringCache.constEnd() )
217 *
this = crsIt.value();
218 sCrsStringLock.unlock();
221 sCrsStringLock.unlock();
224 QRegularExpression reCrsId(
"^(epsg|postgis|internal|user)\\:(\\d+)$", QRegularExpression::CaseInsensitiveOption );
225 QRegularExpressionMatch match = reCrsId.match( definition );
226 if ( match.capturedStart() == 0 )
228 QString authName = match.captured( 1 ).toLower();
230 if ( authName == QLatin1String(
"epsg" ) )
232 if ( authName == QLatin1String(
"postgis" ) )
234 long id = match.captured( 2 ).toLong();
239 QRegularExpression reCrsStr(
"^(?:(wkt|proj4)\\:)?(.+)$", QRegularExpression::CaseInsensitiveOption );
240 match = reCrsStr.match( definition );
241 if ( match.capturedStart() == 0 )
243 if ( match.captured( 1 ).toLower() == QLatin1String(
"proj4" ) )
252 QString myName = QStringLiteral(
" * %1 (%2)" )
253 .arg( QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ),
265 sCrsStringLock.lockForWrite();
266 sStringCache.insert( definition, *
this );
267 sCrsStringLock.unlock();
278 if ( definition.startsWith( QLatin1String(
"ESRI::" ) ) )
283 if ( OSRSetFromUserInput( crs, definition.toLocal8Bit().constData() ) == OGRERR_NONE )
285 if ( OSRExportToWkt( crs, &wkt ) == OGRERR_NONE )
290 OSRDestroySpatialReference( crs );
300 const char *configOld = CPLGetConfigOption(
"GDAL_FIX_ESRI_WKT",
"" );
301 const char *configNew =
"GEOGCS";
303 if ( strcmp( configOld,
"" ) == 0 )
305 CPLSetConfigOption(
"GDAL_FIX_ESRI_WKT", configNew );
306 if ( strcmp( configNew, CPLGetConfigOption(
"GDAL_FIX_ESRI_WKT",
"" ) ) != 0 )
308 .arg( configNew, CPLGetConfigOption(
"GDAL_FIX_ESRI_WKT",
"" ) ) );
309 QgsDebugMsgLevel( QString(
"set GDAL_FIX_ESRI_WKT : %1" ).arg( configNew ), 4 );
313 QgsDebugMsgLevel( QString(
"GDAL_FIX_ESRI_WKT was already set : %1" ).arg( configNew ), 4 );
319 sOgcLock.lockForRead();
320 QHash< QString, QgsCoordinateReferenceSystem >::const_iterator crsIt = sOgcCache.constFind( crs );
321 if ( crsIt != sOgcCache.constEnd() )
324 *
this = crsIt.value();
330 QString wmsCrs = crs;
332 QRegExp re(
"urn:ogc:def:crs:([^:]+).+([^:]+)", Qt::CaseInsensitive );
333 if ( re.exactMatch( wmsCrs ) )
335 wmsCrs = re.cap( 1 ) +
':' + re.cap( 2 );
339 re.setPattern( QStringLiteral(
"(user|custom|qgis):(\\d+)" ) );
340 if ( re.exactMatch( wmsCrs ) &&
createFromSrsId( re.cap( 2 ).toInt() ) )
342 sOgcLock.lockForWrite();
343 sOgcCache.insert( crs, *
this );
351 sOgcLock.lockForWrite();
352 sOgcCache.insert( crs, *
this );
358 if ( wmsCrs.compare( QLatin1String(
"CRS:27" ), Qt::CaseInsensitive ) == 0 ||
359 wmsCrs.compare( QLatin1String(
"OGC:CRS27" ), Qt::CaseInsensitive ) == 0 )
366 if ( wmsCrs.compare( QLatin1String(
"CRS:83" ), Qt::CaseInsensitive ) == 0 ||
367 wmsCrs.compare( QLatin1String(
"OGC:CRS83" ), Qt::CaseInsensitive ) == 0 )
374 if ( wmsCrs.compare( QLatin1String(
"CRS:84" ), Qt::CaseInsensitive ) == 0 ||
375 wmsCrs.compare( QLatin1String(
"OGC:CRS84" ), Qt::CaseInsensitive ) == 0 )
380 d->mAxisInverted =
false;
381 d->mAxisInvertedDirty =
false;
383 sOgcLock.lockForWrite();
384 sOgcCache.insert( crs, *
this );
390 sOgcLock.lockForWrite();
407 if ( mCustomSrsValidation )
408 mCustomSrsValidation( *
this );
418 sSrIdCacheLock.lockForRead();
419 QHash< long, QgsCoordinateReferenceSystem >::const_iterator crsIt = sSrIdCache.constFind(
id );
420 if ( crsIt != sSrIdCache.constEnd() )
423 *
this = crsIt.value();
424 sSrIdCacheLock.unlock();
427 sSrIdCacheLock.unlock();
431 sSrIdCacheLock.lockForWrite();
432 sSrIdCache.insert(
id, *
this );
433 sSrIdCacheLock.unlock();
440 sCRSSrsIdLock.lockForRead();
441 QHash< long, QgsCoordinateReferenceSystem >::const_iterator crsIt = sSrsIdCache.constFind(
id );
442 if ( crsIt != sSrsIdCache.constEnd() )
445 *
this = crsIt.value();
446 sCRSSrsIdLock.unlock();
449 sCRSSrsIdLock.unlock();
453 QStringLiteral(
"srs_id" ), QString::number(
id ) );
455 sCRSSrsIdLock.lockForWrite();
456 sSrsIdCache.insert(
id, *
this );
457 sCRSSrsIdLock.unlock();
462 bool QgsCoordinateReferenceSystem::loadFromDatabase(
const QString &db,
const QString &expression,
const QString &value )
466 QgsDebugMsgLevel(
"load CRS from " + db +
" where " + expression +
" is " + value, 3 );
470 QFileInfo myInfo( db );
471 if ( !myInfo.exists() )
473 QgsDebugMsg(
"failed : " + db +
" does not exist!" );
481 myResult = openDatabase( db, database );
482 if ( myResult != SQLITE_OK )
499 QString mySql =
"select srs_id,description,projection_acronym," 500 "ellipsoid_acronym,parameters,srid,auth_name||':'||auth_id,is_geo " 501 "from tbl_srs where " + expression +
'=' + quotedValue( value ) +
" order by deprecated";
502 statement = database.
prepare( mySql, myResult );
504 if ( myResult == SQLITE_OK && statement.
step() == SQLITE_ROW )
513 d->mIsGeographic = statement.
columnAsText( 7 ).toInt() != 0;
514 d->mAxisInvertedDirty =
true;
518 d->mAuthId = QStringLiteral(
"USER:%1" ).arg( d->mSrsId );
520 else if ( d->mAuthId.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
522 OSRDestroySpatialReference( d->mCRS );
523 d->mCRS = OSRNewSpatialReference(
nullptr );
524 d->mIsValid = OSRSetFromUserInput( d->mCRS, d->mAuthId.toLower().toLatin1() ) == OGRERR_NONE;
530 setProj4String( d->mProj4 );
542 if ( d->mAxisInvertedDirty )
544 OGRAxisOrientation orientation;
545 OSRGetAxis( d->mCRS, OSRIsGeographic( d->mCRS ) ?
"GEOGCS" :
"PROJCS", 0, &orientation );
548 if ( orientation == OAO_Other && d->mAuthId.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
552 if ( OSRImportFromEPSGA( crs, d->mAuthId.midRef( 5 ).toInt() ) == OGRERR_NONE )
554 OSRGetAxis( crs, OSRIsGeographic( crs ) ?
"GEOGCS" :
"PROJCS", 0, &orientation );
557 OSRDestroySpatialReference( crs );
560 d->mAxisInverted = orientation == OAO_North;
561 d->mAxisInvertedDirty =
false;
564 return d->mAxisInverted;
571 sCRSWktLock.lockForRead();
572 QHash< QString, QgsCoordinateReferenceSystem >::const_iterator crsIt = sWktCache.constFind( wkt );
573 if ( crsIt != sWktCache.constEnd() )
576 *
this = crsIt.value();
577 sCRSWktLock.unlock();
580 sCRSWktLock.unlock();
591 QByteArray ba = wkt.toLatin1();
592 const char *pWkt = ba.data();
594 OGRErr myInputResult = OSRImportFromWkt( d->mCRS, const_cast< char ** >( & pWkt ) );
596 if ( myInputResult != OGRERR_NONE )
598 QgsDebugMsg(
"\n---------------------------------------------------------------" );
599 QgsDebugMsg(
"This CRS could *** NOT *** be set from the supplied Wkt " );
601 QgsDebugMsg( QString(
"UNUSED WKT: %1" ).arg( pWkt ) );
602 QgsDebugMsg(
"---------------------------------------------------------------\n" );
604 sCRSWktLock.lockForWrite();
605 sWktCache.insert( wkt, *
this );
606 sCRSWktLock.unlock();
610 if ( OSRAutoIdentifyEPSG( d->mCRS ) == OGRERR_NONE )
612 QString
authid = QStringLiteral(
"%1:%2" )
613 .arg( OSRGetAuthorityName( d->mCRS,
nullptr ),
614 OSRGetAuthorityCode( d->mCRS,
nullptr ) );
616 sCRSWktLock.lockForWrite();
617 sWktCache.insert( wkt, *
this );
618 sCRSWktLock.unlock();
627 char *proj4src =
nullptr;
628 OSRExportToProj4( d->mCRS, &proj4src );
640 OSRExportToProj4( d->mCRS, &proj4src );
648 if ( d->mSrsId == 0 )
650 QString myName = QStringLiteral(
" * %1 (%2)" )
651 .arg( QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ),
658 sCRSWktLock.lockForWrite();
659 sWktCache.insert( wkt, *
this );
660 sCRSWktLock.unlock();
675 sProj4CacheLock.lockForRead();
676 QHash< QString, QgsCoordinateReferenceSystem >::const_iterator crsIt = sProj4Cache.constFind( proj4String );
677 if ( crsIt != sProj4Cache.constEnd() )
680 *
this = crsIt.value();
681 sProj4CacheLock.unlock();
684 sProj4CacheLock.unlock();
694 QString myProj4String = proj4String.trimmed();
698 QRegExp myProjRegExp(
"\\+proj=(\\S+)" );
699 int myStart = myProjRegExp.indexIn( myProj4String );
702 sProj4CacheLock.lockForWrite();
703 sProj4Cache.insert( proj4String, *
this );
704 sProj4CacheLock.unlock();
709 d->mProjectionAcronym = myProjRegExp.cap( 1 );
711 QRegExp myEllipseRegExp(
"\\+ellps=(\\S+)" );
712 myStart = myEllipseRegExp.indexIn( myProj4String );
715 d->mEllipsoidAcronym.clear();
719 d->mEllipsoidAcronym = myEllipseRegExp.cap( 1 );
722 QRegExp myAxisRegExp(
"\\+a=(\\S+)" );
723 myStart = myAxisRegExp.indexIn( myProj4String );
726 QgsCoordinateReferenceSystem::RecordMap myRecord;
732 myRecord = getRecord(
"select * from tbl_srs where parameters=" + quotedValue( myProj4String ) +
" order by deprecated" );
733 if ( myRecord.empty() )
738 QRegExp myLat1RegExp(
"\\+lat_1=\\S+" );
739 QRegExp myLat2RegExp(
"\\+lat_2=\\S+" );
746 myStart1 = myLat1RegExp.indexIn( myProj4String, myStart1 );
747 myStart2 = myLat2RegExp.indexIn( myProj4String, myStart2 );
748 if ( myStart1 != -1 && myStart2 != -1 )
750 myLength1 = myLat1RegExp.matchedLength();
751 myLength2 = myLat2RegExp.matchedLength();
756 if ( !lat1Str.isEmpty() && !lat2Str.isEmpty() )
759 QString proj4StringModified = myProj4String;
764 myStart2 = myLat2RegExp.indexIn( proj4String, myStart2 );
767 myRecord = getRecord(
"select * from tbl_srs where parameters=" + quotedValue( proj4StringModified.trimmed() ) +
" order by deprecated" );
771 if ( myRecord.empty() )
778 QString sql = QStringLiteral(
"SELECT * FROM tbl_srs WHERE " );
785 QStringList myParams;
786 Q_FOREACH (
const QString ¶m, myProj4String.split( QRegExp(
"\\s+(?=\\+)" ), QString::SkipEmptyParts ) )
788 QString arg = QStringLiteral(
"' '||parameters||' ' LIKE %1" ).arg( quotedValue( QStringLiteral(
"% %1 %" ).arg( param.trimmed() ) ) );
789 if ( param.startsWith( QLatin1String(
"+datum=" ) ) )
796 delim = QStringLiteral(
" AND " );
797 myParams << param.trimmed();
801 if ( !datum.isEmpty() )
803 myRecord = getRecord( sql + delim + datum +
" order by deprecated" );
806 if ( myRecord.empty() )
809 myRecord = getRecord( sql +
" order by deprecated" );
812 if ( !myRecord.empty() )
815 QStringList foundParams;
816 Q_FOREACH (
const QString ¶m, myRecord[
"parameters"].split( QRegExp(
"\\s+(?=\\+)" ), QString::SkipEmptyParts ) )
818 if ( !param.startsWith( QLatin1String(
"+datum=" ) ) )
819 foundParams << param.trimmed();
825 if ( myParams != foundParams )
832 if ( !myRecord.empty() )
834 mySrsId = myRecord[QStringLiteral(
"srs_id" )].toLong();
843 setProj4String( myProj4String );
860 setProj4String( myProj4String );
863 sProj4CacheLock.lockForWrite();
864 sProj4Cache.insert( proj4String, *
this );
865 sProj4CacheLock.unlock();
871 QgsCoordinateReferenceSystem::RecordMap QgsCoordinateReferenceSystem::getRecord(
const QString &sql )
873 QString myDatabaseFileName;
874 QgsCoordinateReferenceSystem::RecordMap myMap;
876 QString myFieldValue;
883 QFileInfo myInfo( myDatabaseFileName );
884 if ( !myInfo.exists() )
886 QgsDebugMsg(
"failed : " + myDatabaseFileName +
" does not exist!" );
891 myResult = openDatabase( myDatabaseFileName, database );
892 if ( myResult != SQLITE_OK )
897 statement = database.
prepare( sql, myResult );
899 if ( myResult == SQLITE_OK && statement.
step() == SQLITE_ROW )
903 for (
int myColNo = 0; myColNo < myColumnCount; myColNo++ )
905 myFieldName = statement.
columnName( myColNo );
907 myMap[myFieldName] = myFieldValue;
909 if ( statement.
step() != SQLITE_DONE )
923 QFileInfo myFileInfo;
924 myFileInfo.setFile( myDatabaseFileName );
925 if ( !myFileInfo.exists() )
932 myResult = openDatabase( myDatabaseFileName, database );
933 if ( myResult != SQLITE_OK )
938 statement = database.
prepare( sql, myResult );
940 if ( myResult == SQLITE_OK && statement.
step() == SQLITE_ROW )
944 for (
int myColNo = 0; myColNo < myColumnCount; myColNo++ )
946 myFieldName = statement.
columnName( myColNo );
948 myMap[myFieldName] = myFieldValue;
951 if ( statement.
step() != SQLITE_DONE )
984 if ( d->mDescription.isNull() )
990 return d->mDescription;
996 if ( d->mProjectionAcronym.isNull() )
1002 return d->mProjectionAcronym;
1008 if ( d->mEllipsoidAcronym.isNull() )
1014 return d->mEllipsoidAcronym;
1023 if ( d->mProj4.isEmpty() )
1025 char *proj4src =
nullptr;
1026 OSRExportToProj4( d->mCRS, &proj4src );
1027 d->mProj4 = proj4src;
1028 CPLFree( proj4src );
1031 return d->mProj4.trimmed();
1036 return d->mIsGeographic;
1044 return d->mMapUnits;
1058 int result = openDatabase( databaseFileName, database );
1059 if ( result != SQLITE_OK )
1064 QString sql = QStringLiteral(
"select west_bound_lon, north_bound_lat, east_bound_lon, south_bound_lat from tbl_bounds " 1067 statement = database.
prepare( sql, result );
1070 if ( result == SQLITE_OK )
1072 if ( statement.
step() == SQLITE_ROW )
1093 void QgsCoordinateReferenceSystem::setInternalId(
long srsId )
1098 void QgsCoordinateReferenceSystem::setAuthId(
const QString &authId )
1101 d->mAuthId = authId;
1103 void QgsCoordinateReferenceSystem::setSrid(
long srid )
1108 void QgsCoordinateReferenceSystem::setDescription(
const QString &
description )
1113 void QgsCoordinateReferenceSystem::setProj4String(
const QString &proj4String )
1116 d->mProj4 = proj4String;
1120 OSRDestroySpatialReference( d->mCRS );
1121 d->mCRS = OSRNewSpatialReference(
nullptr );
1122 d->mIsValid = OSRImportFromProj4( d->mCRS, proj4String.trimmed().toLatin1().constData() ) == OGRERR_NONE;
1127 projCtx pContext = pj_ctx_alloc();
1128 projPJ proj = pj_init_plus_ctx( pContext, proj4String.trimmed().toLatin1().constData() );
1132 d->mIsValid =
false;
1138 pj_ctx_free( pContext );
1143 void QgsCoordinateReferenceSystem::setGeographicFlag(
bool geoFlag )
1146 d->mIsGeographic = geoFlag;
1148 void QgsCoordinateReferenceSystem::setEpsg(
long epsg )
1151 d->mAuthId = QStringLiteral(
"EPSG:%1" ).arg( epsg );
1153 void QgsCoordinateReferenceSystem::setProjectionAcronym(
const QString &
projectionAcronym )
1158 void QgsCoordinateReferenceSystem::setEllipsoidAcronym(
const QString &
ellipsoidAcronym )
1164 void QgsCoordinateReferenceSystem::setMapUnits()
1173 char *unitName =
nullptr;
1177 OSRFixup( d->mCRS );
1179 if ( OSRIsProjected( d->mCRS ) )
1181 double toMeter = OSRGetLinearUnits( d->mCRS, &unitName );
1182 QString unit( unitName );
1190 static const double SMALL_NUM = 1e-3;
1192 if ( std::fabs( toMeter - FEET_TO_METER ) < SMALL_NUM )
1193 unit = QStringLiteral(
"Foot" );
1197 else if ( unit == QLatin1String(
"Foot" ) )
1206 OSRGetAngularUnits( d->mCRS, &unitName );
1207 QString unit( unitName );
1208 if ( unit == QLatin1String(
"degree" ) )
1220 if ( d->mEllipsoidAcronym.isNull() || d->mProjectionAcronym.isNull()
1223 QgsDebugMsgLevel(
"QgsCoordinateReferenceSystem::findMatchingProj will only " 1224 "work if prj acr ellipsoid acr and proj4string are set" 1225 " and the current projection is valid!", 4 );
1235 QString mySql = QString(
"select srs_id,parameters from tbl_srs where " 1236 "projection_acronym=%1 and ellipsoid_acronym=%2 order by deprecated" )
1237 .arg( quotedValue( d->mProjectionAcronym ),
1238 quotedValue( d->mEllipsoidAcronym ) );
1243 myResult = openDatabase( myDatabaseFileName, database );
1244 if ( myResult != SQLITE_OK )
1249 statement = database.
prepare( mySql, myResult );
1250 if ( myResult == SQLITE_OK )
1253 while ( statement.
step() == SQLITE_ROW )
1257 if (
toProj4() == myProj4String.trimmed() )
1259 return mySrsId.toLong();
1270 myResult = openDatabase( myDatabaseFileName, database );
1271 if ( myResult != SQLITE_OK )
1276 statement = database.
prepare( mySql, myResult );
1278 if ( myResult == SQLITE_OK )
1280 while ( statement.
step() == SQLITE_ROW )
1284 if (
toProj4() == myProj4String.trimmed() )
1286 return mySrsId.toLong();
1296 return ( !d->mIsValid && !srs.d->mIsValid ) ||
1297 ( d->mIsValid && srs.d->mIsValid && srs.
authid() ==
authid() );
1302 return !( *
this == srs );
1307 if ( d->mWkt.isEmpty() )
1309 char *wkt =
nullptr;
1310 if ( OSRExportToWkt( d->mCRS, &wkt ) == OGRERR_NONE )
1323 QDomNode srsNode = node.namedItem( QStringLiteral(
"spatialrefsys" ) );
1325 if ( ! srsNode.isNull() )
1327 bool initialized =
false;
1329 long srsid = srsNode.namedItem( QStringLiteral(
"srsid" ) ).toElement().text().toLong();
1335 myNode = srsNode.namedItem( QStringLiteral(
"authid" ) );
1336 if ( !myNode.isNull() )
1347 myNode = srsNode.namedItem( QStringLiteral(
"epsg" ) );
1348 if ( !myNode.isNull() )
1361 myNode = srsNode.namedItem( QStringLiteral(
"proj4" ) );
1367 myNode = srsNode.namedItem( QStringLiteral(
"proj4" ) );
1368 setProj4String( myNode.toElement().text() );
1370 myNode = srsNode.namedItem( QStringLiteral(
"srsid" ) );
1371 setInternalId( myNode.toElement().text().toLong() );
1373 myNode = srsNode.namedItem( QStringLiteral(
"srid" ) );
1374 setSrid( myNode.toElement().text().toLong() );
1376 myNode = srsNode.namedItem( QStringLiteral(
"authid" ) );
1377 setAuthId( myNode.toElement().text() );
1379 myNode = srsNode.namedItem( QStringLiteral(
"description" ) );
1380 setDescription( myNode.toElement().text() );
1382 myNode = srsNode.namedItem( QStringLiteral(
"projectionacronym" ) );
1383 setProjectionAcronym( myNode.toElement().text() );
1385 myNode = srsNode.namedItem( QStringLiteral(
"ellipsoidacronym" ) );
1386 setEllipsoidAcronym( myNode.toElement().text() );
1388 myNode = srsNode.namedItem( QStringLiteral(
"geographicflag" ) );
1389 if ( myNode.toElement().text().compare( QLatin1String(
"true" ) ) )
1391 setGeographicFlag(
true );
1395 setGeographicFlag(
false );
1405 if ( d->mSrsId == 0 )
1407 QString myName = QStringLiteral(
" * %1 (%2)" )
1408 .arg( QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ),
1418 d =
new QgsCoordinateReferenceSystemPrivate();
1427 QDomElement myLayerNode = node.toElement();
1428 QDomElement mySrsElement = doc.createElement( QStringLiteral(
"spatialrefsys" ) );
1430 QDomElement myProj4Element = doc.createElement( QStringLiteral(
"proj4" ) );
1431 myProj4Element.appendChild( doc.createTextNode(
toProj4() ) );
1432 mySrsElement.appendChild( myProj4Element );
1434 QDomElement mySrsIdElement = doc.createElement( QStringLiteral(
"srsid" ) );
1435 mySrsIdElement.appendChild( doc.createTextNode( QString::number(
srsid() ) ) );
1436 mySrsElement.appendChild( mySrsIdElement );
1438 QDomElement mySridElement = doc.createElement( QStringLiteral(
"srid" ) );
1439 mySridElement.appendChild( doc.createTextNode( QString::number(
postgisSrid() ) ) );
1440 mySrsElement.appendChild( mySridElement );
1442 QDomElement myEpsgElement = doc.createElement( QStringLiteral(
"authid" ) );
1443 myEpsgElement.appendChild( doc.createTextNode(
authid() ) );
1444 mySrsElement.appendChild( myEpsgElement );
1446 QDomElement myDescriptionElement = doc.createElement( QStringLiteral(
"description" ) );
1447 myDescriptionElement.appendChild( doc.createTextNode(
description() ) );
1448 mySrsElement.appendChild( myDescriptionElement );
1450 QDomElement myProjectionAcronymElement = doc.createElement( QStringLiteral(
"projectionacronym" ) );
1451 myProjectionAcronymElement.appendChild( doc.createTextNode(
projectionAcronym() ) );
1452 mySrsElement.appendChild( myProjectionAcronymElement );
1454 QDomElement myEllipsoidAcronymElement = doc.createElement( QStringLiteral(
"ellipsoidacronym" ) );
1455 myEllipsoidAcronymElement.appendChild( doc.createTextNode(
ellipsoidAcronym() ) );
1456 mySrsElement.appendChild( myEllipsoidAcronymElement );
1458 QDomElement myGeographicFlagElement = doc.createElement( QStringLiteral(
"geographicflag" ) );
1459 QString myGeoFlagText = QStringLiteral(
"false" );
1462 myGeoFlagText = QStringLiteral(
"true" );
1465 myGeographicFlagElement.appendChild( doc.createTextNode( myGeoFlagText ) );
1466 mySrsElement.appendChild( myGeographicFlagElement );
1468 myLayerNode.appendChild( mySrsElement );
1482 QString QgsCoordinateReferenceSystem::proj4FromSrsId(
const int srsId )
1484 QString myDatabaseFileName;
1485 QString myProjString;
1486 QString mySql = QStringLiteral(
"select parameters from tbl_srs where srs_id = %1 order by deprecated" ).arg( srsId );
1495 QFileInfo myFileInfo;
1496 myFileInfo.setFile( myDatabaseFileName );
1497 if ( !myFileInfo.exists() )
1512 rc = openDatabase( myDatabaseFileName, database );
1518 statement = database.
prepare( mySql, rc );
1520 if ( rc == SQLITE_OK )
1522 if ( statement.
step() == SQLITE_ROW )
1528 return myProjString;
1535 myResult = database.
open_v2( path, SQLITE_OPEN_READONLY,
nullptr );
1537 myResult = database.
open( path );
1539 if ( myResult != SQLITE_OK )
1548 .arg( database.
errorMessage() ), QObject::tr(
"CRS" ) );
1555 mCustomSrsValidation =
f;
1560 return mCustomSrsValidation;
1563 void QgsCoordinateReferenceSystem::debugPrint()
1566 QgsDebugMsg(
"* Valid : " + ( d->mIsValid ? QString(
"true" ) : QString(
"false" ) ) );
1567 QgsDebugMsg(
"* SrsId : " + QString::number( d->mSrsId ) );
1588 d->mValidationHint = html;
1593 return d->mValidationHint;
1609 QString proj4String = d->mProj4;
1610 if ( proj4String.isEmpty() )
1619 if ( getRecordCount() == 0 )
1621 mySql =
"insert into tbl_srs (srs_id,description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values (" 1623 +
',' + quotedValue( name )
1626 +
',' + quotedValue(
toProj4() )
1631 mySql =
"insert into tbl_srs (description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values (" 1632 + quotedValue( name )
1635 +
',' + quotedValue(
toProj4() )
1643 if ( myResult != SQLITE_OK )
1645 QgsDebugMsg( QString(
"Can't open or create database %1: %2" )
1650 statement = database.
prepare( mySql, myResult );
1653 if ( myResult == SQLITE_OK && statement.
step() == SQLITE_DONE )
1657 returnId = sqlite3_last_insert_rowid( database.get() );
1658 setInternalId( returnId );
1659 if (
authid().isEmpty() )
1660 setAuthId( QStringLiteral(
"USER:%1" ).arg( returnId ) );
1661 setDescription( name );
1666 QStringList projectionsProj4 = settings.
value( QStringLiteral(
"UI/recentProjectionsProj4" ) ).toStringList();
1667 QStringList projectionsAuthId = settings.
value( QStringLiteral(
"UI/recentProjectionsAuthId" ) ).toStringList();
1670 projectionsProj4.append(
toProj4() );
1671 projectionsAuthId.append(
authid() );
1672 settings.
setValue( QStringLiteral(
"UI/recentProjectionsProj4" ), projectionsProj4 );
1673 settings.
setValue( QStringLiteral(
"UI/recentProjectionsAuthId" ), projectionsAuthId );
1683 long QgsCoordinateReferenceSystem::getRecordCount()
1688 long myRecordCount = 0;
1691 if ( myResult != SQLITE_OK )
1697 QString mySql = QStringLiteral(
"select count(*) from tbl_srs" );
1698 statement = database.
prepare( mySql, myResult );
1699 if ( myResult == SQLITE_OK )
1701 if ( statement.
step() == SQLITE_ROW )
1703 QString myRecordCountString = statement.
columnAsText( 0 );
1704 myRecordCount = myRecordCountString.toLong();
1707 return myRecordCount;
1710 QString QgsCoordinateReferenceSystem::quotedValue( QString value )
1712 value.replace(
'\'', QLatin1String(
"''" ) );
1713 return value.prepend(
'\'' ).append(
'\'' );
1717 bool QgsCoordinateReferenceSystem::loadWkts( QHash<int, QString> &wkts,
const char *filename )
1720 const char *pszFilename = CPLFindFile(
"gdal", filename );
1724 QFile csv( pszFilename );
1725 if ( !csv.open( QIODevice::ReadOnly ) )
1728 QTextStream lines( &csv );
1732 QString line = lines.readLine();
1733 if ( line.isNull() )
1736 if ( line.startsWith(
'#' ) )
1740 else if ( line.startsWith( QLatin1String(
"include " ) ) )
1742 if ( !loadWkts( wkts, line.mid( 8 ).toUtf8() ) )
1747 int pos = line.indexOf(
',' );
1752 int epsg = line.leftRef( pos ).toInt( &ok );
1756 wkts.insert( epsg, line.mid( pos + 1 ) );
1765 bool QgsCoordinateReferenceSystem::loadIds( QHash<int, QString> &wkts )
1769 Q_FOREACH (
const QString &csv, QStringList() <<
"gcs.csv" <<
"pcs.csv" <<
"vertcs.csv" <<
"compdcs.csv" <<
"geoccs.csv" )
1771 QString filename = CPLFindFile(
"gdal", csv.toUtf8() );
1773 QFile
f( filename );
1774 if ( !f.open( QIODevice::ReadOnly ) )
1777 QTextStream lines( &f );
1784 QString line = lines.readLine();
1785 if ( line.isNull() )
1788 int pos = line.indexOf(
',' );
1793 int epsg = line.leftRef( pos ).toInt( &ok );
1798 if ( epsg == 2218 || epsg == 2221 || epsg == 2296 || epsg == 2297 || epsg == 2298 || epsg == 2299 || epsg == 2300 || epsg == 2301 || epsg == 2302 ||
1799 epsg == 2303 || epsg == 2304 || epsg == 2305 || epsg == 2306 || epsg == 2307 || epsg == 2963 || epsg == 2985 || epsg == 2986 || epsg == 3052 ||
1800 epsg == 3053 || epsg == 3139 || epsg == 3144 || epsg == 3145 || epsg == 3173 || epsg == 3295 || epsg == 3993 || epsg == 4087 || epsg == 4088 ||
1801 epsg == 5017 || epsg == 5221 || epsg == 5224 || epsg == 5225 || epsg == 5514 || epsg == 5515 || epsg == 5516 || epsg == 5819 || epsg == 5820 ||
1802 epsg == 5821 || epsg == 6200 || epsg == 6201 || epsg == 6202 || epsg == 6244 || epsg == 6245 || epsg == 6246 || epsg == 6247 || epsg == 6248 ||
1803 epsg == 6249 || epsg == 6250 || epsg == 6251 || epsg == 6252 || epsg == 6253 || epsg == 6254 || epsg == 6255 || epsg == 6256 || epsg == 6257 ||
1804 epsg == 6258 || epsg == 6259 || epsg == 6260 || epsg == 6261 || epsg == 6262 || epsg == 6263 || epsg == 6264 || epsg == 6265 || epsg == 6266 ||
1805 epsg == 6267 || epsg == 6268 || epsg == 6269 || epsg == 6270 || epsg == 6271 || epsg == 6272 || epsg == 6273 || epsg == 6274 || epsg == 6275 ||
1806 epsg == 6966 || epsg == 7082 || epsg == 32600 || epsg == 32663 || epsg == 32700 )
1809 if ( OSRImportFromEPSG( crs, epsg ) != OGRERR_NONE )
1811 qDebug(
"EPSG %d: not imported", epsg );
1815 char *wkt =
nullptr;
1816 if ( OSRExportToWkt( crs, &wkt ) != OGRERR_NONE )
1818 qWarning(
"EPSG %d: not exported to WKT", epsg );
1822 wkts.insert( epsg, wkt );
1830 QgsDebugMsgLevel( QStringLiteral(
"Loaded %1/%2 from %3" ).arg( QString::number( n ), QString::number( l ), filename.toUtf8().constData() ), 4 );
1833 OSRDestroySpatialReference( crs );
1841 syncDatumTransform( dbFilePath );
1843 int inserted = 0, updated = 0, deleted = 0, errors = 0;
1848 if ( database.
open( dbFilePath ) != SQLITE_OK )
1854 if ( sqlite3_exec( database.get(),
"BEGIN TRANSACTION",
nullptr,
nullptr, nullptr ) != SQLITE_OK )
1861 if ( sqlite3_exec( database.get(),
"alter table tbl_srs add noupdate boolean",
nullptr,
nullptr, nullptr ) == SQLITE_OK )
1862 ( 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 );
1864 ( 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 );
1869 char *errMsg =
nullptr;
1873 QHash<int, QString> wkts;
1875 loadWkts( wkts,
"epsg.wkt" );
1877 QgsDebugMsgLevel( QStringLiteral(
"%1 WKTs loaded" ).arg( wkts.count() ), 4 );
1879 for ( QHash<int, QString>::const_iterator it = wkts.constBegin(); it != wkts.constEnd(); ++it )
1881 QByteArray ba( it.value().toUtf8() );
1882 char *psz = ba.data();
1885 OSRDestroySpatialReference( crs );
1887 crs = OSRNewSpatialReference(
nullptr );
1889 OGRErr ogrErr = OSRImportFromWkt( crs, &psz );
1890 if ( ogrErr != OGRERR_NONE )
1893 if ( OSRExportToProj4( crs, &psz ) != OGRERR_NONE )
1900 proj4 = proj4.trimmed();
1904 if ( proj4.isEmpty() )
1907 sql = QStringLiteral(
"SELECT parameters,noupdate FROM tbl_srs WHERE auth_name='EPSG' AND auth_id='%1'" ).arg( it.key() );
1908 statement = database.
prepare( sql, result );
1909 if ( result != SQLITE_OK )
1916 if ( statement.
step() == SQLITE_ROW )
1926 if ( !srsProj4.isEmpty() )
1928 if ( proj4 != srsProj4 )
1931 sql = QStringLiteral(
"UPDATE tbl_srs SET parameters=%1 WHERE auth_name='EPSG' AND auth_id=%2" ).arg( quotedValue( proj4 ) ).arg( it.key() );
1933 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, &errMsg ) != SQLITE_OK )
1935 QgsDebugMsg( QStringLiteral(
"Could not execute: %1 [%2/%3]\n" ).arg(
1938 errMsg ? errMsg :
"(unknown error)" ) );
1940 sqlite3_free( errMsg );
1951 QRegExp projRegExp(
"\\+proj=(\\S+)" );
1952 if ( projRegExp.indexIn( proj4 ) < 0 )
1954 QgsDebugMsgLevel( QString(
"EPSG %1: no +proj argument found [%2]" ).arg( it.key() ).arg( proj4 ), 4 );
1958 QRegExp ellipseRegExp(
"\\+ellps=(\\S+)" );
1960 if ( ellipseRegExp.indexIn( proj4 ) >= 0 )
1962 ellps = ellipseRegExp.cap( 1 );
1965 QString name( OSRIsGeographic( crs ) ? OSRGetAttrValue( crs,
"GEOGCS", 0 ) : OSRGetAttrValue( crs,
"PROJCS", 0 ) );
1966 if ( name.isEmpty() )
1967 name = QObject::tr(
"Imported from GDAL" );
1969 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,0)" )
1970 .arg( quotedValue( name ),
1971 quotedValue( projRegExp.cap( 1 ) ),
1972 quotedValue( ellps ),
1973 quotedValue( proj4 ) )
1975 .arg( OSRIsGeographic( crs ) );
1978 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, &errMsg ) == SQLITE_OK )
1984 qCritical(
"Could not execute: %s [%s/%s]\n",
1985 sql.toLocal8Bit().constData(),
1986 sqlite3_errmsg( database.get() ),
1987 errMsg ? errMsg :
"(unknown error)" );
1991 sqlite3_free( errMsg );
1997 OSRDestroySpatialReference( crs );
2000 sql = QStringLiteral(
"DELETE FROM tbl_srs WHERE auth_name='EPSG' AND NOT auth_id IN (" );
2002 QHash<int, QString>::const_iterator it = wkts.constBegin();
2003 for ( ; it != wkts.constEnd(); ++it )
2005 sql += delim + QString::number( it.key() );
2008 sql += QLatin1String(
") AND NOT noupdate" );
2010 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, nullptr ) == SQLITE_OK )
2012 deleted = sqlite3_changes( database.get() );
2017 qCritical(
"Could not execute: %s [%s]\n",
2018 sql.toLocal8Bit().constData(),
2019 sqlite3_errmsg( database.get() ) );
2022 projCtx pContext = pj_ctx_alloc();
2024 #if !defined(PJ_VERSION) || PJ_VERSION!=470 2025 sql = QStringLiteral(
"select auth_name,auth_id,parameters from tbl_srs WHERE auth_name<>'EPSG' AND NOT deprecated AND NOT noupdate" );
2026 statement = database.
prepare( sql, result );
2027 if ( result == SQLITE_OK )
2029 while ( statement.
step() == SQLITE_ROW )
2035 QString input = QStringLiteral(
"+init=%1:%2" ).arg( auth_name.toLower(), auth_id );
2036 projPJ pj = pj_init_plus_ctx( pContext, input.toLatin1() );
2039 input = QStringLiteral(
"+init=%1:%2" ).arg( auth_name.toUpper(), auth_id );
2040 pj = pj_init_plus_ctx( pContext, input.toLatin1() );
2045 char *def = pj_get_def( pj, 0 );
2051 input.prepend(
' ' ).append(
' ' );
2052 if ( proj4.startsWith( input ) )
2054 proj4 = proj4.mid( input.size() );
2055 proj4 = proj4.trimmed();
2058 if ( proj4 != params )
2060 sql = QStringLiteral(
"UPDATE tbl_srs SET parameters=%1 WHERE auth_name=%2 AND auth_id=%3" )
2061 .arg( quotedValue( proj4 ),
2062 quotedValue( auth_name ),
2063 quotedValue( auth_id ) );
2065 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, &errMsg ) == SQLITE_OK )
2071 qCritical(
"Could not execute: %s [%s/%s]\n",
2072 sql.toLocal8Bit().constData(),
2073 sqlite3_errmsg( database.get() ),
2074 errMsg ? errMsg :
"(unknown error)" );
2076 sqlite3_free( errMsg );
2083 QgsDebugMsgLevel( QString(
"could not retrieve proj string for %1 from PROJ" ).arg( input ), 4 );
2088 QgsDebugMsgLevel( QString(
"could not retrieve crs for %1 from PROJ" ).arg( input ), 3 );
2097 QgsDebugMsg( QStringLiteral(
"Could not execute: %1 [%2]\n" ).arg(
2099 sqlite3_errmsg( database.get() ) ) );
2103 pj_ctx_free( pContext );
2105 if ( sqlite3_exec( database.get(),
"COMMIT",
nullptr,
nullptr, nullptr ) != SQLITE_OK )
2107 QgsDebugMsg( QStringLiteral(
"Could not commit transaction: %1 [%2]\n" ).arg(
2109 sqlite3_errmsg( database.get() ) )
2114 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 );
2119 return updated + inserted;
2122 bool QgsCoordinateReferenceSystem::syncDatumTransform(
const QString &dbPath )
2124 const char *filename = CSVFilename(
"datum_shift.csv" );
2125 FILE *fp = VSIFOpen( filename,
"rb" );
2131 char **fieldnames = CSVReadParseLine( fp );
2143 {
"SOURCE_CRS_CODE",
"source_crs_code", -1 },
2144 {
"TARGET_CRS_CODE",
"target_crs_code", -1 },
2145 {
"REMARKS",
"remarks", -1 },
2146 {
"COORD_OP_SCOPE",
"scope", -1 },
2147 {
"AREA_OF_USE_CODE",
"area_of_use_code", -1 },
2153 {
"DEPRECATED",
"deprecated", -1 },
2154 {
"COORD_OP_METHOD_CODE",
"coord_op_method_code", -1 },
2162 {
"PREFERRED",
"preferred", -1 },
2163 {
"COORD_OP_CODE",
"coord_op_code", -1 },
2166 QString update = QStringLiteral(
"UPDATE tbl_datum_transform SET " );
2167 QString insert, values;
2169 int n = CSLCount( fieldnames );
2171 int idxid = -1, idxrx = -1, idxry = -1, idxrz = -1, idxmcode = -1;
2172 for (
unsigned int i = 0; i <
sizeof( map ) /
sizeof( *map ); i++ )
2174 bool last = i ==
sizeof( map ) /
sizeof( *map ) - 1;
2176 map[i].idx = CSLFindString( fieldnames, map[i].src );
2177 if ( map[i].idx < 0 )
2179 qWarning(
"field %s not found", map[i].src );
2180 CSLDestroy( fieldnames );
2185 if ( strcmp( map[i].src,
"COORD_OP_CODE" ) == 0 )
2187 if ( strcmp( map[i].src,
"RX" ) == 0 )
2189 if ( strcmp( map[i].src,
"RY" ) == 0 )
2191 if ( strcmp( map[i].src,
"RZ" ) == 0 )
2193 if ( strcmp( map[i].src,
"COORD_OP_METHOD_CODE" ) == 0 )
2203 update += QLatin1String(
" WHERE " );
2211 update += QStringLiteral(
"%1=%%2" ).arg( map[i].dst ).arg( i + 1 );
2213 insert += map[i].dst;
2214 values += QStringLiteral(
"%%1" ).arg( i + 1 );
2217 insert =
"INSERT INTO tbl_datum_transform(" + insert +
") VALUES (" + values +
')';
2219 CSLDestroy( fieldnames );
2221 Q_ASSERT( idxid >= 0 );
2222 Q_ASSERT( idxrx >= 0 );
2223 Q_ASSERT( idxry >= 0 );
2224 Q_ASSERT( idxrz >= 0 );
2227 int openResult = database.
open( dbPath );
2228 if ( openResult != SQLITE_OK )
2234 if ( sqlite3_exec( database.get(),
"BEGIN TRANSACTION",
nullptr,
nullptr, nullptr ) != SQLITE_OK )
2242 v.reserve(
sizeof( map ) /
sizeof( *map ) );
2246 char **values = CSVReadParseLine( fp );
2252 if ( CSLCount( values ) == 0 )
2254 CSLDestroy( values );
2258 if ( CSLCount( values ) < n )
2260 qWarning(
"Only %d columns", CSLCount( values ) );
2261 CSLDestroy( values );
2265 for (
unsigned int i = 0; i <
sizeof( map ) /
sizeof( *map ); i++ )
2267 int idx = map[i].idx;
2268 Q_ASSERT( idx != -1 );
2269 Q_ASSERT( idx < n );
2270 v.insert( i, *values[ idx ] ? quotedValue( values[idx] ) : QStringLiteral(
"NULL" ) );
2272 CSLDestroy( values );
2275 if ( v.at( idxmcode ).compare( QLatin1String(
"'9607'" ) ) == 0 )
2277 v[ idxmcode ] = QStringLiteral(
"'9606'" );
2278 v[ idxrx ] =
'\'' +
qgsDoubleToString( -( v[ idxrx ].
remove(
'\'' ).toDouble() ) ) +
'\'';
2279 v[ idxry ] =
'\'' +
qgsDoubleToString( -( v[ idxry ].
remove(
'\'' ).toDouble() ) ) +
'\'';
2280 v[ idxrz ] =
'\'' +
qgsDoubleToString( -( v[ idxrz ].
remove(
'\'' ).toDouble() ) ) +
'\'';
2286 QString sql = QStringLiteral(
"SELECT coord_op_code FROM tbl_datum_transform WHERE coord_op_code=%1" ).arg( v[ idxid ] );
2288 statement = database.
prepare( sql, prepareRes );
2289 if ( prepareRes != SQLITE_OK )
2292 if ( statement.
step() == SQLITE_ROW )
2297 sql = cOpCode.isEmpty() ? insert : update;
2298 for (
int i = 0; i < v.size(); i++ )
2300 sql = sql.arg( v[i] );
2303 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, nullptr ) != SQLITE_OK )
2305 qCritical(
"SQL: %s", sql.toUtf8().constData() );
2306 qCritical(
"Error: %s", sqlite3_errmsg( database.get() ) );
2310 if ( sqlite3_exec( database.get(),
"COMMIT",
nullptr,
nullptr, nullptr ) != SQLITE_OK )
2327 return OSRGetAuthorityName( d->mCRS,
"GEOGCS" ) + QStringLiteral(
":" ) + OSRGetAuthorityCode( d->mCRS,
"GEOGCS" );
2337 QStringList projections;
2341 projections = settings.
value( QStringLiteral(
"UI/recentProjections" ) ).toStringList();
2345 QStringList projectionsProj4 = settings.
value( QStringLiteral(
"UI/recentProjectionsProj4" ) ).toStringList();
2346 QStringList projectionsAuthId = settings.
value( QStringLiteral(
"UI/recentProjectionsAuthId" ) ).toStringList();
2347 if ( projectionsAuthId.size() >= projections.size() )
2351 projections.clear();
2352 for (
int i = 0; i < projectionsAuthId.size(); i++ )
2360 if ( i >= projectionsProj4.size() || !crs.
createFromProj4( projectionsProj4.at( i ) ) )
2366 if ( crs.
srsid() == 0 )
2371 projections << QString::number( crs.
srsid() );
2379 sSrIdCacheLock.lockForWrite();
2381 sSrIdCacheLock.unlock();
2382 sOgcLock.lockForWrite();
2385 sProj4CacheLock.lockForWrite();
2386 sProj4Cache.clear();
2387 sProj4CacheLock.unlock();
2388 sCRSWktLock.lockForWrite();
2390 sCRSWktLock.unlock();
2391 sCRSSrsIdLock.lockForWrite();
2392 sSrsIdCache.clear();
2393 sCRSSrsIdLock.unlock();
2394 sCrsStringLock.lockForWrite();
2395 sStringCache.clear();
2396 sCrsStringLock.unlock();
QString geographicCrsAuthId() const
Returns auth id of related geographic CRS.
QgsCoordinateReferenceSystem()
Constructs an invalid CRS object.
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 ...
void validate()
Perform some validation on this CRS.
static void warning(const QString &msg)
Goes to qWarning.
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=".
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning)
add a message to the instance (and create it if necessary)
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 setValue(const QString &key, const QVariant &value, const QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
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 createFromSrsId(const long srsId)
Sets this CRS by lookup of internal QGIS CRS ID 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()
Get 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.
int columnCount() const
Get 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 (~/...
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 setYMaximum(double y)
Set the maximum y value.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
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.
bool createFromId(const long id, CrsType type=PostgisCrsId)
Sets this CRS by lookup of the given ID in the CRS database.
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
Get column value from the current statement row as a double.
qlonglong columnAsInt64(int column) const
Get 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.
bool createFromSrid(const long srid)
Sets this CRS by lookup of the given PostGIS SRID in the CRS database.
static QgsCoordinateReferenceSystem fromSrsId(long srsId)
Creates a CRS from a specified QGIS SRS ID.
void * OGRSpatialReferenceH
bool isValid() const
Returns whether this CRS is correctly initialized and usable.