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.trimmed().isEmpty() || 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 if ( line.trimmed().isEmpty() )
1791 int pos = line.indexOf(
',' );
1794 qWarning(
"No id found in: %s", qPrintable( line ) );
1799 int epsg = line.leftRef( pos ).toInt( &ok );
1802 qWarning(
"No valid id found in: %s", qPrintable( line ) );
1807 if ( epsg == 2218 || epsg == 2221 || epsg == 2296 || epsg == 2297 || epsg == 2298 || epsg == 2299 || epsg == 2300 || epsg == 2301 || epsg == 2302 ||
1808 epsg == 2303 || epsg == 2304 || epsg == 2305 || epsg == 2306 || epsg == 2307 || epsg == 2963 || epsg == 2985 || epsg == 2986 || epsg == 3052 ||
1809 epsg == 3053 || epsg == 3139 || epsg == 3144 || epsg == 3145 || epsg == 3173 || epsg == 3295 || epsg == 3993 || epsg == 4087 || epsg == 4088 ||
1810 epsg == 5017 || epsg == 5221 || epsg == 5224 || epsg == 5225 || epsg == 5514 || epsg == 5515 || epsg == 5516 || epsg == 5819 || epsg == 5820 ||
1811 epsg == 5821 || epsg == 6200 || epsg == 6201 || epsg == 6202 || epsg == 6244 || epsg == 6245 || epsg == 6246 || epsg == 6247 || epsg == 6248 ||
1812 epsg == 6249 || epsg == 6250 || epsg == 6251 || epsg == 6252 || epsg == 6253 || epsg == 6254 || epsg == 6255 || epsg == 6256 || epsg == 6257 ||
1813 epsg == 6258 || epsg == 6259 || epsg == 6260 || epsg == 6261 || epsg == 6262 || epsg == 6263 || epsg == 6264 || epsg == 6265 || epsg == 6266 ||
1814 epsg == 6267 || epsg == 6268 || epsg == 6269 || epsg == 6270 || epsg == 6271 || epsg == 6272 || epsg == 6273 || epsg == 6274 || epsg == 6275 ||
1815 epsg == 6966 || epsg == 7082 || epsg == 32600 || epsg == 32663 || epsg == 32700 )
1818 if ( OSRImportFromEPSG( crs, epsg ) != OGRERR_NONE )
1820 qDebug(
"EPSG %d: not imported", epsg );
1824 char *wkt =
nullptr;
1825 if ( OSRExportToWkt( crs, &wkt ) != OGRERR_NONE )
1827 qWarning(
"EPSG %d: not exported to WKT", epsg );
1831 wkts.insert( epsg, wkt );
1839 QgsDebugMsgLevel( QStringLiteral(
"Loaded %1/%2 from %3" ).arg( QString::number( n ), QString::number( l ), filename.toUtf8().constData() ), 4 );
1842 OSRDestroySpatialReference( crs );
1850 syncDatumTransform( dbFilePath );
1852 int inserted = 0, updated = 0, deleted = 0, errors = 0;
1857 if ( database.
open( dbFilePath ) != SQLITE_OK )
1863 if ( sqlite3_exec( database.get(),
"BEGIN TRANSACTION",
nullptr,
nullptr, nullptr ) != SQLITE_OK )
1870 if ( sqlite3_exec( database.get(),
"alter table tbl_srs add noupdate boolean",
nullptr,
nullptr, nullptr ) == SQLITE_OK )
1871 ( 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 );
1873 ( 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 );
1878 char *errMsg =
nullptr;
1882 QHash<int, QString> wkts;
1884 loadWkts( wkts,
"epsg.wkt" );
1886 QgsDebugMsgLevel( QStringLiteral(
"%1 WKTs loaded" ).arg( wkts.count() ), 4 );
1888 for ( QHash<int, QString>::const_iterator it = wkts.constBegin(); it != wkts.constEnd(); ++it )
1890 QByteArray ba( it.value().toUtf8() );
1891 char *psz = ba.data();
1894 OSRDestroySpatialReference( crs );
1896 crs = OSRNewSpatialReference(
nullptr );
1898 OGRErr ogrErr = OSRImportFromWkt( crs, &psz );
1899 if ( ogrErr != OGRERR_NONE )
1902 if ( OSRExportToProj4( crs, &psz ) != OGRERR_NONE )
1909 proj4 = proj4.trimmed();
1913 if ( proj4.isEmpty() )
1916 QString name( OSRIsGeographic( crs ) ? OSRGetAttrValue( crs,
"GEOGCS", 0 ) :
1917 OSRIsGeocentric( crs ) ? OSRGetAttrValue( crs,
"GEOCCS", 0 ) :
1918 OSRGetAttrValue( crs,
"PROJCS", 0 ) );
1919 if ( name.isEmpty() )
1920 name = QObject::tr(
"Imported from GDAL" );
1922 bool deprecated = name.contains( QLatin1Literal(
"(deprecated)" ) );
1924 sql = QStringLiteral(
"SELECT parameters,description,deprecated,noupdate FROM tbl_srs WHERE auth_name='EPSG' AND auth_id='%1'" ).arg( it.key() );
1925 statement = database.
prepare( sql, result );
1926 if ( result != SQLITE_OK )
1934 bool srsDeprecated = deprecated;
1935 if ( statement.
step() == SQLITE_ROW )
1939 srsDeprecated = statement.
columnAsText( 2 ).toInt() != 0;
1947 if ( !srsProj4.isEmpty() || !srsDesc.isEmpty() )
1949 if ( proj4 != srsProj4 || name != srsDesc || deprecated != srsDeprecated )
1952 sql = QStringLiteral(
"UPDATE tbl_srs SET parameters=%1,description=%2,deprecated=%3 WHERE auth_name='EPSG' AND auth_id=%4" )
1953 .arg( quotedValue( proj4 ) )
1954 .arg( quotedValue( name ) )
1955 .arg( deprecated ? 1 : 0 )
1958 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, &errMsg ) != SQLITE_OK )
1960 QgsDebugMsg( QStringLiteral(
"Could not execute: %1 [%2/%3]\n" ).arg(
1963 errMsg ? errMsg :
"(unknown error)" ) );
1965 sqlite3_free( errMsg );
1976 QRegExp projRegExp(
"\\+proj=(\\S+)" );
1977 if ( projRegExp.indexIn( proj4 ) < 0 )
1979 QgsDebugMsgLevel( QString(
"EPSG %1: no +proj argument found [%2]" ).arg( it.key() ).arg( proj4 ), 4 );
1983 QRegExp ellipseRegExp(
"\\+ellps=(\\S+)" );
1985 if ( ellipseRegExp.indexIn( proj4 ) >= 0 )
1987 ellps = ellipseRegExp.cap( 1 );
1990 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)" )
1991 .arg( quotedValue( name ),
1992 quotedValue( projRegExp.cap( 1 ) ),
1993 quotedValue( ellps ),
1994 quotedValue( proj4 ) )
1996 .arg( OSRIsGeographic( crs ) )
1997 .arg( deprecated ? 1 : 0 );
2000 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, &errMsg ) == SQLITE_OK )
2006 qCritical(
"Could not execute: %s [%s/%s]\n",
2007 sql.toLocal8Bit().constData(),
2008 sqlite3_errmsg( database.get() ),
2009 errMsg ? errMsg :
"(unknown error)" );
2013 sqlite3_free( errMsg );
2019 OSRDestroySpatialReference( crs );
2022 sql = QStringLiteral(
"DELETE FROM tbl_srs WHERE auth_name='EPSG' AND NOT auth_id IN (" );
2024 QHash<int, QString>::const_iterator it = wkts.constBegin();
2025 for ( ; it != wkts.constEnd(); ++it )
2027 sql += delim + QString::number( it.key() );
2030 sql += QLatin1String(
") AND NOT noupdate" );
2032 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, nullptr ) == SQLITE_OK )
2034 deleted = sqlite3_changes( database.get() );
2039 qCritical(
"Could not execute: %s [%s]\n",
2040 sql.toLocal8Bit().constData(),
2041 sqlite3_errmsg( database.get() ) );
2044 projCtx pContext = pj_ctx_alloc();
2046 #if !defined(PJ_VERSION) || PJ_VERSION!=470 2047 sql = QStringLiteral(
"select auth_name,auth_id,parameters from tbl_srs WHERE auth_name<>'EPSG' AND NOT deprecated AND NOT noupdate" );
2048 statement = database.
prepare( sql, result );
2049 if ( result == SQLITE_OK )
2051 while ( statement.
step() == SQLITE_ROW )
2057 QString input = QStringLiteral(
"+init=%1:%2" ).arg( auth_name.toLower(), auth_id );
2058 projPJ pj = pj_init_plus_ctx( pContext, input.toLatin1() );
2061 input = QStringLiteral(
"+init=%1:%2" ).arg( auth_name.toUpper(), auth_id );
2062 pj = pj_init_plus_ctx( pContext, input.toLatin1() );
2067 char *def = pj_get_def( pj, 0 );
2073 input.prepend(
' ' ).append(
' ' );
2074 if ( proj4.startsWith( input ) )
2076 proj4 = proj4.mid( input.size() );
2077 proj4 = proj4.trimmed();
2080 if ( proj4 != params )
2082 sql = QStringLiteral(
"UPDATE tbl_srs SET parameters=%1 WHERE auth_name=%2 AND auth_id=%3" )
2083 .arg( quotedValue( proj4 ),
2084 quotedValue( auth_name ),
2085 quotedValue( auth_id ) );
2087 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, &errMsg ) == SQLITE_OK )
2093 qCritical(
"Could not execute: %s [%s/%s]\n",
2094 sql.toLocal8Bit().constData(),
2095 sqlite3_errmsg( database.get() ),
2096 errMsg ? errMsg :
"(unknown error)" );
2098 sqlite3_free( errMsg );
2105 QgsDebugMsgLevel( QString(
"could not retrieve proj string for %1 from PROJ" ).arg( input ), 4 );
2110 QgsDebugMsgLevel( QString(
"could not retrieve crs for %1 from PROJ" ).arg( input ), 3 );
2119 QgsDebugMsg( QStringLiteral(
"Could not execute: %1 [%2]\n" ).arg(
2121 sqlite3_errmsg( database.get() ) ) );
2125 pj_ctx_free( pContext );
2127 if ( sqlite3_exec( database.get(),
"COMMIT",
nullptr,
nullptr, nullptr ) != SQLITE_OK )
2129 QgsDebugMsg( QStringLiteral(
"Could not commit transaction: %1 [%2]\n" ).arg(
2131 sqlite3_errmsg( database.get() ) )
2136 Q_UNUSED( deleted );
2137 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 );
2142 return updated + inserted;
2145 bool QgsCoordinateReferenceSystem::syncDatumTransform(
const QString &dbPath )
2147 const char *filename = CSVFilename(
"datum_shift.csv" );
2148 FILE *fp = VSIFOpen( filename,
"rb" );
2154 char **fieldnames = CSVReadParseLine( fp );
2166 {
"SOURCE_CRS_CODE",
"source_crs_code", -1 },
2167 {
"TARGET_CRS_CODE",
"target_crs_code", -1 },
2168 {
"REMARKS",
"remarks", -1 },
2169 {
"COORD_OP_SCOPE",
"scope", -1 },
2170 {
"AREA_OF_USE_CODE",
"area_of_use_code", -1 },
2176 {
"DEPRECATED",
"deprecated", -1 },
2177 {
"COORD_OP_METHOD_CODE",
"coord_op_method_code", -1 },
2185 {
"PREFERRED",
"preferred", -1 },
2186 {
"COORD_OP_CODE",
"coord_op_code", -1 },
2189 QString update = QStringLiteral(
"UPDATE tbl_datum_transform SET " );
2190 QString insert, values;
2192 int n = CSLCount( fieldnames );
2194 int idxid = -1, idxrx = -1, idxry = -1, idxrz = -1, idxmcode = -1;
2195 for (
unsigned int i = 0; i <
sizeof( map ) /
sizeof( *map ); i++ )
2197 bool last = i ==
sizeof( map ) /
sizeof( *map ) - 1;
2199 map[i].idx = CSLFindString( fieldnames, map[i].src );
2200 if ( map[i].idx < 0 )
2202 qWarning(
"field %s not found", map[i].src );
2203 CSLDestroy( fieldnames );
2208 if ( strcmp( map[i].src,
"COORD_OP_CODE" ) == 0 )
2210 if ( strcmp( map[i].src,
"RX" ) == 0 )
2212 if ( strcmp( map[i].src,
"RY" ) == 0 )
2214 if ( strcmp( map[i].src,
"RZ" ) == 0 )
2216 if ( strcmp( map[i].src,
"COORD_OP_METHOD_CODE" ) == 0 )
2226 update += QLatin1String(
" WHERE " );
2234 update += QStringLiteral(
"%1=%%2" ).arg( map[i].dst ).arg( i + 1 );
2236 insert += map[i].dst;
2237 values += QStringLiteral(
"%%1" ).arg( i + 1 );
2240 insert =
"INSERT INTO tbl_datum_transform(" + insert +
") VALUES (" + values +
')';
2242 CSLDestroy( fieldnames );
2244 Q_ASSERT( idxid >= 0 );
2245 Q_ASSERT( idxrx >= 0 );
2246 Q_ASSERT( idxry >= 0 );
2247 Q_ASSERT( idxrz >= 0 );
2250 int openResult = database.
open( dbPath );
2251 if ( openResult != SQLITE_OK )
2257 if ( sqlite3_exec( database.get(),
"BEGIN TRANSACTION",
nullptr,
nullptr, nullptr ) != SQLITE_OK )
2265 v.reserve(
sizeof( map ) /
sizeof( *map ) );
2269 char **values = CSVReadParseLine( fp );
2275 if ( CSLCount( values ) == 0 )
2277 CSLDestroy( values );
2281 if ( CSLCount( values ) < n )
2283 qWarning(
"Only %d columns", CSLCount( values ) );
2284 CSLDestroy( values );
2288 for (
unsigned int i = 0; i <
sizeof( map ) /
sizeof( *map ); i++ )
2290 int idx = map[i].idx;
2291 Q_ASSERT( idx != -1 );
2292 Q_ASSERT( idx < n );
2293 v.insert( i, *values[ idx ] ? quotedValue( values[idx] ) : QStringLiteral(
"NULL" ) );
2295 CSLDestroy( values );
2298 if ( v.at( idxmcode ).compare( QLatin1String(
"'9607'" ) ) == 0 )
2300 v[ idxmcode ] = QStringLiteral(
"'9606'" );
2301 v[ idxrx ] =
'\'' +
qgsDoubleToString( -( v[ idxrx ].
remove(
'\'' ).toDouble() ) ) +
'\'';
2302 v[ idxry ] =
'\'' +
qgsDoubleToString( -( v[ idxry ].
remove(
'\'' ).toDouble() ) ) +
'\'';
2303 v[ idxrz ] =
'\'' +
qgsDoubleToString( -( v[ idxrz ].
remove(
'\'' ).toDouble() ) ) +
'\'';
2309 QString sql = QStringLiteral(
"SELECT coord_op_code FROM tbl_datum_transform WHERE coord_op_code=%1" ).arg( v[ idxid ] );
2311 statement = database.
prepare( sql, prepareRes );
2312 if ( prepareRes != SQLITE_OK )
2315 if ( statement.
step() == SQLITE_ROW )
2320 sql = cOpCode.isEmpty() ? insert : update;
2321 for (
int i = 0; i < v.size(); i++ )
2323 sql = sql.arg( v[i] );
2326 if ( sqlite3_exec( database.get(), sql.toUtf8(),
nullptr,
nullptr, nullptr ) != SQLITE_OK )
2328 qCritical(
"SQL: %s", sql.toUtf8().constData() );
2329 qCritical(
"Error: %s", sqlite3_errmsg( database.get() ) );
2333 if ( sqlite3_exec( database.get(),
"COMMIT",
nullptr,
nullptr, nullptr ) != SQLITE_OK )
2350 return OSRGetAuthorityName( d->mCRS,
"GEOGCS" ) + QStringLiteral(
":" ) + OSRGetAuthorityCode( d->mCRS,
"GEOGCS" );
2360 QStringList projections;
2364 projections = settings.
value( QStringLiteral(
"UI/recentProjections" ) ).toStringList();
2368 QStringList projectionsProj4 = settings.
value( QStringLiteral(
"UI/recentProjectionsProj4" ) ).toStringList();
2369 QStringList projectionsAuthId = settings.
value( QStringLiteral(
"UI/recentProjectionsAuthId" ) ).toStringList();
2370 if ( projectionsAuthId.size() >= projections.size() )
2374 projections.clear();
2375 for (
int i = 0; i < projectionsAuthId.size(); i++ )
2383 if ( i >= projectionsProj4.size() || !crs.
createFromProj4( projectionsProj4.at( i ) ) )
2389 if ( crs.
srsid() == 0 )
2394 projections << QString::number( crs.
srsid() );
2402 sSrIdCacheLock.lockForWrite();
2404 sSrIdCacheLock.unlock();
2405 sOgcLock.lockForWrite();
2408 sProj4CacheLock.lockForWrite();
2409 sProj4Cache.clear();
2410 sProj4CacheLock.unlock();
2411 sCRSWktLock.lockForWrite();
2413 sCRSWktLock.unlock();
2414 sCRSSrsIdLock.lockForWrite();
2415 sSrsIdCache.clear();
2416 sCRSSrsIdLock.unlock();
2417 sCrsStringLock.lockForWrite();
2418 sStringCache.clear();
2419 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=".
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
bool isValid() const
Returns whether this CRS is correctly initialized and usable.