23 #include <QTemporaryFile>
25 #include <QDomElement>
28 #include <QTextStream>
43 #include <ogr_srs_api.h>
44 #include <cpl_error.h>
55 , mMapUnits(
QGis::UnknownUnit )
58 , mValidationHint(
"" )
59 , mAxisInverted( false )
61 mCRS = OSRNewSpatialReference( NULL );
67 , mMapUnits(
QGis::UnknownUnit )
70 , mValidationHint(
"" )
71 , mAxisInverted( false )
73 mCRS = OSRNewSpatialReference( NULL );
81 , mMapUnits(
QGis::UnknownUnit )
84 , mValidationHint(
"" )
85 , mAxisInverted( false )
87 mCRS = OSRNewSpatialReference( NULL );
93 OSRDestroySpatialReference( mCRS );
120 QRegExp reCrsId(
"^(epsg|postgis|internal)\\:(\\d+)$", Qt::CaseInsensitive );
121 if ( reCrsId.
indexIn( theDefinition ) == 0 )
125 if ( authName ==
"epsg" )
127 if ( authName ==
"postgis" )
134 QRegExp reCrsStr(
"^(?:(wkt|proj4)\\:)?(.+)$", Qt::CaseInsensitive );
135 if ( reCrsStr.
indexIn( theDefinition ) == 0 )
147 .
arg(
QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ),
168 #if GDAL_VERSION_NUM >= 1900
177 if ( OSRExportToWkt( crs, &wkt ) == OGRERR_NONE )
182 OSRDestroySpatialReference( crs );
192 #if GDAL_VERSION_NUM >= 1900
193 const char* configOld = CPLGetConfigOption(
"GDAL_FIX_ESRI_WKT",
"" );
194 const char* configNew =
"GEOGCS";
196 if ( strcmp( configOld,
"" ) == 0 )
198 CPLSetConfigOption(
"GDAL_FIX_ESRI_WKT", configNew );
199 if ( strcmp( configNew, CPLGetConfigOption(
"GDAL_FIX_ESRI_WKT",
"" ) ) != 0 )
201 .arg( configNew, CPLGetConfigOption(
"GDAL_FIX_ESRI_WKT",
"" ) ) );
213 QRegExp re(
"urn:ogc:def:crs:([^:]+).+([^:]+)", Qt::CaseInsensitive );
216 theCrs = re.
cap( 1 ) +
":" + re.
cap( 2 );
231 if ( theCrs.
compare(
"CRS:27", Qt::CaseInsensitive ) == 0 ||
232 theCrs.
compare(
"OGC:CRS27", Qt::CaseInsensitive ) == 0 )
239 if ( theCrs.
compare(
"CRS:83", Qt::CaseInsensitive ) == 0 ||
240 theCrs.
compare(
"OGC:CRS83", Qt::CaseInsensitive ) == 0 )
247 if ( theCrs.
compare(
"CRS:84", Qt::CaseInsensitive ) == 0 ||
248 theCrs.
compare(
"OGC:CRS84", Qt::CaseInsensitive ) == 0 )
260 mCRS = OSRNewSpatialReference( NULL );
270 mDescription = srs.mDescription;
271 mProjectionAcronym = srs.mProjectionAcronym;
272 mEllipsoidAcronym = srs.mEllipsoidAcronym;
273 mGeoFlag = srs.mGeoFlag;
274 mAxisInverted = srs.mAxisInverted;
275 mMapUnits = srs.mMapUnits;
277 mAuthId = srs.mAuthId;
278 mIsValidFlag = srs.mIsValidFlag;
279 mValidationHint = srs.mValidationHint;
284 OSRDestroySpatialReference( mCRS );
285 mCRS = OSRClone( srs.mCRS );
300 if ( mCustomSrsValidation )
301 mCustomSrsValidation( *
this );
321 bool QgsCoordinateReferenceSystem::loadFromDb(
const QString& db,
const QString& expression,
const QString& value )
323 QgsDebugMsgLevel(
"load CRS from " + db +
" where " + expression +
" is " + value, 3 );
324 mIsValidFlag =
false;
328 if ( !myInfo.exists() )
330 QgsDebugMsg(
"failed : " + db +
" does not exist!" );
336 sqlite3_stmt *myPreparedStatement;
339 myResult = openDb( db, &myDatabase );
340 if ( myResult != SQLITE_OK )
342 QgsDebugMsg(
"failed : " + db +
" could not be opened!" );
358 QString mySql =
"select srs_id,description,projection_acronym,"
359 "ellipsoid_acronym,parameters,srid,auth_name||':'||auth_id,is_geo "
360 "from tbl_srs where " + expression +
"=" + quotedValue( value ) +
" order by deprecated";
361 myResult = sqlite3_prepare( myDatabase, mySql.
toUtf8(),
363 &myPreparedStatement, &myTail );
365 if ( myResult == SQLITE_OK && sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
368 myPreparedStatement, 0 ) ).
toLong();
370 myPreparedStatement, 1 ) );
371 mProjectionAcronym =
QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 2 ) );
372 mEllipsoidAcronym =
QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 3 ) );
373 mProj4 =
QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 4 ) );
375 mAuthId =
QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 6 ) );
383 else if ( mAuthId.
startsWith(
"EPSG:", Qt::CaseInsensitive ) )
385 OSRDestroySpatialReference( mCRS );
386 mCRS = OSRNewSpatialReference( NULL );
387 mIsValidFlag = OSRSetFromUserInput( mCRS, mAuthId.
toLower().
toAscii() ) == OGRERR_NONE;
393 setProj4String( mProj4 );
400 sqlite3_finalize( myPreparedStatement );
401 sqlite3_close( myDatabase );
407 if ( mAxisInverted == -1 )
409 OGRAxisOrientation orientation;
410 OSRGetAxis( mCRS, OSRIsGeographic( mCRS ) ?
"GEOGCS" :
"PROJCS", 0, &orientation );
413 if ( orientation == OAO_Other && mAuthId.
startsWith(
"EPSG:", Qt::CaseInsensitive ) )
417 if ( OSRImportFromEPSGA( crs, mAuthId.
mid( 5 ).
toInt() ) == OGRERR_NONE )
419 OSRGetAxis( crs, OSRIsGeographic( crs ) ?
"GEOGCS" :
"PROJCS", 0, &orientation );
422 OSRDestroySpatialReference( crs );
425 mAxisInverted = orientation == OAO_North;
428 return mAxisInverted != 0;
433 mIsValidFlag =
false;
439 QgsDebugMsg(
"theWkt is uninitialised, operation failed" );
444 const char *pWkt = ba.
data();
446 OGRErr myInputResult = OSRImportFromWkt( mCRS, (
char ** ) & pWkt );
448 if ( myInputResult != OGRERR_NONE )
450 QgsDebugMsg(
"\n---------------------------------------------------------------" );
451 QgsDebugMsg(
"This CRS could *** NOT *** be set from the supplied Wkt " );
454 QgsDebugMsg(
"---------------------------------------------------------------\n" );
458 if ( OSRAutoIdentifyEPSG( mCRS ) == OGRERR_NONE )
461 .
arg( OSRGetAuthorityName( mCRS, NULL ),
462 OSRGetAuthorityCode( mCRS, NULL ) );
472 char *proj4src = NULL;
473 OSRExportToProj4( mCRS, &proj4src );
485 OSRExportToProj4( mCRS, &proj4src );
496 .
arg(
QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ),
524 mIsValidFlag =
false;
527 QRegExp myProjRegExp(
"\\+proj=(\\S+)" );
528 int myStart = myProjRegExp.
indexIn( myProj4String );
531 QgsDebugMsg(
"proj string supplied has no +proj argument" );
535 mProjectionAcronym = myProjRegExp.
cap( 1 );
537 QRegExp myEllipseRegExp(
"\\+ellps=(\\S+)" );
538 myStart = myEllipseRegExp.
indexIn( myProj4String );
541 QgsDebugMsg(
"proj string supplied has no +ellps argument" );
542 mEllipsoidAcronym =
"";
546 mEllipsoidAcronym = myEllipseRegExp.
cap( 1 );
549 QRegExp myAxisRegExp(
"\\+a=(\\S+)" );
550 myStart = myAxisRegExp.
indexIn( myProj4String );
553 QgsDebugMsg(
"proj string supplied has no +a argument" );
571 myRecord = getRecord(
"select * from tbl_srs where parameters=" + quotedValue( myProj4String ) +
" order by deprecated" );
572 if ( myRecord.
empty() )
577 QRegExp myLat1RegExp(
"\\+lat_1=\\S+" );
578 QRegExp myLat2RegExp(
"\\+lat_2=\\S+" );
585 myStart1 = myLat1RegExp.
indexIn( myProj4String, myStart1 );
586 myStart2 = myLat2RegExp.
indexIn( myProj4String, myStart2 );
587 if ( myStart1 != -1 && myStart2 != -1 )
595 if ( lat1Str !=
"" && lat2Str !=
"" )
598 QString theProj4StringModified = myProj4String;
603 myStart2 = myLat2RegExp.
indexIn( theProj4String, myStart2 );
605 QgsDebugMsg(
"trying proj4string match with swapped lat_1,lat_2" );
606 myRecord = getRecord(
"select * from tbl_srs where parameters=" + quotedValue( theProj4StringModified.
trimmed() ) +
" order by deprecated" );
610 if ( myRecord.
empty() )
617 QString sql =
"SELECT * FROM tbl_srs WHERE ";
625 Q_FOREACH (
const QString& param, myProj4String.
split(
QRegExp(
"\\s+(?=\\+)" ), QString::SkipEmptyParts ) )
642 myRecord = getRecord( sql + delim + datum +
" order by deprecated" );
645 if ( myRecord.
empty() )
648 myRecord = getRecord( sql +
" order by deprecated" );
651 if ( !myRecord.
empty() )
655 Q_FOREACH (
const QString& param, myRecord[
"parameters"].split(
QRegExp(
"\\s+(?=\\+)" ), QString::SkipEmptyParts ) )
658 foundParams << param.
trimmed();
664 if ( myParams != foundParams )
671 if ( !myRecord.
empty() )
673 mySrsId = myRecord[
"srs_id"].toLong();
683 QgsDebugMsg(
"globbing search for srsid from this proj string" );
684 setProj4String( myProj4String );
693 mIsValidFlag =
false;
700 QgsDebugMsg(
"Projection is not found in databases." );
702 setProj4String( myProj4String );
717 sqlite3_stmt *myPreparedStatement;
724 if ( !myInfo.exists() )
726 QgsDebugMsg(
"failed : " + myDatabaseFileName +
" does not exist!" );
731 myResult = openDb( myDatabaseFileName, &myDatabase );
732 if ( myResult != SQLITE_OK )
737 myResult = sqlite3_prepare( myDatabase, theSql.
toUtf8(), theSql.
toUtf8().
length(), &myPreparedStatement, &myTail );
739 if ( myResult == SQLITE_OK && sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
742 int myColumnCount = sqlite3_column_count( myPreparedStatement );
744 for (
int myColNo = 0; myColNo < myColumnCount; myColNo++ )
746 myFieldName =
QString::fromUtf8((
char * )sqlite3_column_name( myPreparedStatement, myColNo ) );
747 myFieldValue =
QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, myColNo ) );
748 myMap[myFieldName] = myFieldValue;
750 if ( sqlite3_step( myPreparedStatement ) != SQLITE_DONE )
764 sqlite3_finalize( myPreparedStatement );
765 sqlite3_close( myDatabase );
769 myFileInfo.
setFile( myDatabaseFileName );
770 if ( !myFileInfo.
exists() )
777 myResult = openDb( myDatabaseFileName, &myDatabase );
778 if ( myResult != SQLITE_OK )
783 myResult = sqlite3_prepare( myDatabase, theSql.
toUtf8(), theSql.
toUtf8().
length(), &myPreparedStatement, &myTail );
785 if ( myResult == SQLITE_OK && sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
787 int myColumnCount = sqlite3_column_count( myPreparedStatement );
789 for (
int myColNo = 0; myColNo < myColumnCount; myColNo++ )
791 myFieldName =
QString::fromUtf8((
char * )sqlite3_column_name( myPreparedStatement, myColNo ) );
792 myFieldValue =
QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, myColNo ) );
793 myMap[myFieldName] = myFieldValue;
796 if ( sqlite3_step( myPreparedStatement ) != SQLITE_DONE )
807 sqlite3_finalize( myPreparedStatement );
808 sqlite3_close( myDatabase );
813 for ( it = myMap.
begin(); it != myMap.
end(); ++it )
841 if ( mDescription.
isNull() )
853 if ( mProjectionAcronym.
isNull() )
859 return mProjectionAcronym;
865 if ( mEllipsoidAcronym.
isNull() )
871 return mEllipsoidAcronym;
883 char *proj4src = NULL;
884 OSRExportToProj4( mCRS, &proj4src );
906 void QgsCoordinateReferenceSystem::setInternalId(
long theSrsId )
910 void QgsCoordinateReferenceSystem::setAuthId(
const QString& authId )
914 void QgsCoordinateReferenceSystem::setSrid(
long theSrid )
918 void QgsCoordinateReferenceSystem::setDescription(
const QString& theDescription )
920 mDescription = theDescription;
922 void QgsCoordinateReferenceSystem::setProj4String(
const QString& theProj4String )
924 mProj4 = theProj4String;
928 OSRDestroySpatialReference( mCRS );
929 mCRS = OSRNewSpatialReference( NULL );
934 #if defined(QGISDEBUG) && QGISDEBUG>=3
938 void QgsCoordinateReferenceSystem::setGeographicFlag(
bool theGeoFlag )
940 mGeoFlag = theGeoFlag;
942 void QgsCoordinateReferenceSystem::setEpsg(
long theEpsg )
944 mAuthId =
QString(
"EPSG:%1" ).
arg( theEpsg );
946 void QgsCoordinateReferenceSystem::setProjectionAcronym(
const QString& theProjectionAcronym )
948 mProjectionAcronym = theProjectionAcronym;
950 void QgsCoordinateReferenceSystem::setEllipsoidAcronym(
const QString& theEllipsoidAcronym )
952 mEllipsoidAcronym = theEllipsoidAcronym;
955 void QgsCoordinateReferenceSystem::setMapUnits()
969 if ( OSRIsProjected( mCRS ) )
971 double toMeter = OSRGetLinearUnits( mCRS, &unitName );
979 static const double feetToMeter = 0.3048;
980 static const double smallNum = 1e-3;
982 if ( qAbs( toMeter - feetToMeter ) < smallNum )
985 QgsDebugMsg(
"Projection has linear units of " + unit );
989 else if ( unit ==
"Foot" )
999 OSRGetAngularUnits( mCRS, &unitName );
1001 if ( unit ==
"degree" )
1005 QgsDebugMsg(
"Unsupported map units of " + unit );
1024 if ( mEllipsoidAcronym.
isNull() || mProjectionAcronym.
isNull()
1027 QgsDebugMsg(
"QgsCoordinateReferenceSystem::findMatchingProj will only "
1028 "work if prj acr ellipsoid acr and proj4string are set"
1029 " and the current projection is valid!" );
1035 sqlite3_stmt *myPreparedStatement;
1040 QString mySql =
QString(
"select srs_id,parameters from tbl_srs where "
1041 "projection_acronym=%1 and ellipsoid_acronym=%2 order by deprecated" )
1042 .
arg( quotedValue( mProjectionAcronym ),
1043 quotedValue( mEllipsoidAcronym ) );
1048 myResult = openDb( myDatabaseFileName, &myDatabase );
1049 if ( myResult != SQLITE_OK )
1054 myResult = sqlite3_prepare( myDatabase, mySql.
toUtf8(), mySql.
toUtf8().
length(), &myPreparedStatement, &myTail );
1056 if ( myResult == SQLITE_OK )
1059 while ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
1065 QgsDebugMsg(
"-------> MATCH FOUND in srs.db srsid: " + mySrsId );
1067 sqlite3_finalize( myPreparedStatement );
1068 sqlite3_close( myDatabase );
1077 QgsDebugMsg(
"no match found in srs.db, trying user db now!" );
1079 sqlite3_finalize( myPreparedStatement );
1080 sqlite3_close( myDatabase );
1087 myResult = openDb( myDatabaseFileName, &myDatabase );
1088 if ( myResult != SQLITE_OK )
1093 myResult = sqlite3_prepare( myDatabase, mySql.
toUtf8(), mySql.
toUtf8().
length(), &myPreparedStatement, &myTail );
1095 if ( myResult == SQLITE_OK )
1098 while ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
1104 QgsDebugMsg(
"-------> MATCH FOUND in user qgis.db srsid: " + mySrsId );
1106 sqlite3_finalize( myPreparedStatement );
1107 sqlite3_close( myDatabase );
1119 sqlite3_finalize( myPreparedStatement );
1120 sqlite3_close( myDatabase );
1126 return ( !mIsValidFlag && !theSrs.mIsValidFlag ) ||
1127 ( mIsValidFlag && theSrs.mIsValidFlag && theSrs.
authid() ==
authid() );
1132 return !( *
this == theSrs );
1140 if ( OSRExportToWkt( mCRS, &wkt ) == OGRERR_NONE )
1151 QgsDebugMsg(
"Reading Spatial Ref Sys from xml ------------------------!" );
1154 if ( ! srsNode.
isNull() )
1156 bool initialized =
false;
1189 QgsDebugMsg(
"Ignoring authid/epsg for user crs." );
1207 QgsDebugMsg(
"Setting from elements one by one" );
1213 setInternalId( myNode.toElement().text().toLong() );
1216 setSrid( myNode.toElement().text().toLong() );
1219 setAuthId( myNode.toElement().text() );
1221 myNode = srsNode.
namedItem(
"description" );
1222 setDescription( myNode.toElement().text() );
1224 myNode = srsNode.
namedItem(
"projectionacronym" );
1225 setProjectionAcronym( myNode.toElement().text() );
1227 myNode = srsNode.
namedItem(
"ellipsoidacronym" );
1228 setEllipsoidAcronym( myNode.toElement().text() );
1230 myNode = srsNode.
namedItem(
"geographicflag" );
1231 if ( myNode.toElement().text().compare(
"true" ) )
1233 setGeographicFlag(
true );
1237 setGeographicFlag(
false );
1244 mIsValidFlag =
true;
1253 .
arg(
QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ),
1296 mySrsElement.
appendChild( myProjectionAcronymElement );
1300 mySrsElement.
appendChild( myEllipsoidAcronymElement );
1303 QString myGeoFlagText =
"false";
1306 myGeoFlagText =
"true";
1310 mySrsElement.
appendChild( myGeographicFlagElement );
1326 QString QgsCoordinateReferenceSystem::proj4FromSrsId(
const int theSrsId )
1331 QString mySql =
QString(
"select parameters from tbl_srs where srs_id = %1 order by deprecated" ).
arg( theSrsId );
1345 myFileInfo.
setFile( myDatabaseFileName );
1346 if ( !myFileInfo.
exists() )
1360 rc = openDb( myDatabaseFileName, &db );
1367 sqlite3_stmt *ppStmt;
1369 rc = sqlite3_prepare( db, mySql.
toUtf8(), mySql.
toUtf8().
length(), &ppStmt, &pzTail );
1372 if ( rc == SQLITE_OK )
1374 if ( sqlite3_step( ppStmt ) == SQLITE_ROW )
1380 sqlite3_finalize( ppStmt );
1382 sqlite3_close( db );
1385 return myProjString;
1388 int QgsCoordinateReferenceSystem::openDb(
const QString& path,
sqlite3 **db,
bool readonly )
1391 int myResult = readonly
1392 ? sqlite3_open_v2( path.
toUtf8().
data(), db, SQLITE_OPEN_READONLY, NULL )
1395 if ( myResult != SQLITE_OK )
1404 .arg( sqlite3_errmsg( *db ) ),
QObject::tr(
"CRS" ) );
1411 mCustomSrsValidation = f;
1416 return mCustomSrsValidation;
1419 void QgsCoordinateReferenceSystem::debugPrint()
1443 mValidationHint = html;
1448 return mValidationHint;
1456 if ( ! mIsValidFlag )
1474 if ( getRecordCount() == 0 )
1476 mySql =
"insert into tbl_srs (srs_id,description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values ("
1478 +
"," + quotedValue( name )
1481 +
"," + quotedValue(
toProj4() )
1486 mySql =
"insert into tbl_srs (description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values ("
1487 + quotedValue( name )
1490 +
"," + quotedValue(
toProj4() )
1495 sqlite3_stmt *myPreparedStatement;
1499 if ( myResult != SQLITE_OK )
1503 sqlite3_errmsg( myDatabase ) ) );
1507 myResult = sqlite3_prepare( myDatabase, mySql.
toUtf8(), mySql.
toUtf8().
length(), &myPreparedStatement, &myTail );
1510 if ( myResult == SQLITE_OK && sqlite3_step( myPreparedStatement ) == SQLITE_DONE )
1514 return_id = sqlite3_last_insert_rowid( myDatabase );
1515 setInternalId( return_id );
1526 settings.
setValue(
"/UI/recentProjectionsProj4", projectionsProj4 );
1527 settings.
setValue(
"/UI/recentProjectionsAuthId", projectionsAuthId );
1535 long QgsCoordinateReferenceSystem::getRecordCount()
1539 sqlite3_stmt *myPreparedStatement;
1541 long myRecordCount = 0;
1544 if ( myResult != SQLITE_OK )
1546 QgsDebugMsg(
QString(
"Can't open database: %1" ).arg( sqlite3_errmsg( myDatabase ) ) );
1550 QString mySql =
"select count(*) from tbl_srs";
1551 myResult = sqlite3_prepare( myDatabase, mySql.
toUtf8(), mySql.
toUtf8().
length(), &myPreparedStatement, &myTail );
1553 if ( myResult == SQLITE_OK )
1555 if ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
1558 myRecordCount = myRecordCountString.
toLong();
1562 sqlite3_finalize( myPreparedStatement );
1563 sqlite3_close( myDatabase );
1564 return myRecordCount;
1567 QString QgsCoordinateReferenceSystem::quotedValue(
QString value )
1574 bool QgsCoordinateReferenceSystem::loadWkts(
QHash<int, QString> &wkts,
const char *filename )
1576 qDebug(
"Loading %s", filename );
1577 const char *pszFilename = CPLFindFile(
"gdal", filename );
1581 QFile csv( pszFilename );
1582 if ( !csv.open( QIODevice::ReadOnly ) )
1589 QString line = lines.readLine();
1599 if ( !loadWkts( wkts, line.
mid( 8 ).
toUtf8() ) )
1604 int pos = line.
indexOf(
"," );
1609 int epsg = line.
left( pos ).
toInt( &ok );
1613 wkts.
insert( epsg, line.
mid( pos + 1 ) );
1626 Q_FOREACH (
const QString& csv,
QStringList() <<
"gcs.csv" <<
"pcs.csv" <<
"vertcs.csv" <<
"compdcs.csv" <<
"geoccs.csv" )
1630 QFile f( filename );
1631 if ( !f.open( QIODevice::ReadOnly ) )
1641 QString line = lines.readLine();
1645 int pos = line.
indexOf(
"," );
1650 int epsg = line.
left( pos ).
toInt( &ok );
1655 if ( epsg == 2218 || epsg == 2221 || epsg == 2296 || epsg == 2297 || epsg == 2298 || epsg == 2299 || epsg == 2300 || epsg == 2301 || epsg == 2302 ||
1656 epsg == 2303 || epsg == 2304 || epsg == 2305 || epsg == 2306 || epsg == 2307 || epsg == 2963 || epsg == 2985 || epsg == 2986 || epsg == 3052 ||
1657 epsg == 3053 || epsg == 3139 || epsg == 3144 || epsg == 3145 || epsg == 3173 || epsg == 3295 || epsg == 3993 || epsg == 4087 || epsg == 4088 ||
1658 epsg == 5017 || epsg == 5221 || epsg == 5224 || epsg == 5225 || epsg == 5514 || epsg == 5515 || epsg == 5516 || epsg == 5819 || epsg == 5820 ||
1659 epsg == 5821 || epsg == 32600 || epsg == 32663 || epsg == 32700 )
1662 if ( OSRImportFromEPSG( crs, epsg ) != OGRERR_NONE )
1664 qDebug(
"EPSG %d: not imported", epsg );
1669 if ( OSRExportToWkt( crs, &wkt ) != OGRERR_NONE )
1671 qWarning(
"EPSG %d: not exported to WKT", epsg );
1675 wkts.
insert( epsg, wkt );
1683 qDebug(
"Loaded %d/%d from %s", n, l, filename.
toUtf8().
constData() );
1686 OSRDestroySpatialReference( crs );
1694 syncDatumTransform( dbFilePath );
1696 int inserted = 0, updated = 0, deleted = 0, errors = 0;
1701 if ( sqlite3_open( dbFilePath.
toUtf8().
constData(), &database ) != SQLITE_OK )
1707 if ( sqlite3_exec( database,
"BEGIN TRANSACTION", 0, 0, 0 ) != SQLITE_OK )
1709 qCritical(
"Could not begin transaction: %s [%s]\n",
QgsApplication::srsDbFilePath().toLocal8Bit().constData(), sqlite3_errmsg( database ) );
1714 if ( sqlite3_exec( database,
"alter table tbl_srs add noupdate boolean", 0, 0, 0 ) == SQLITE_OK )
1715 ( void )sqlite3_exec( database,
"update tbl_srs set noupdate=(auth_name='EPSG' and auth_id in (5513,5514,5221,2065,102067,4156,4818))", 0, 0, 0 );
1717 ( void )sqlite3_exec( database,
"UPDATE tbl_srs SET srid=141001 WHERE srid=41001 AND auth_name='OSGEO' AND auth_id='41001'", 0, 0, 0 );
1721 sqlite3_stmt *select;
1722 char *errMsg = NULL;
1728 loadWkts( wkts,
"epsg.wkt" );
1730 qDebug(
"%d WKTs loaded", wkts.
count() );
1735 char *psz = ba.
data();
1736 OGRErr ogrErr = OSRImportFromWkt( crs, &psz );
1737 if ( ogrErr != OGRERR_NONE )
1740 if ( OSRExportToProj4( crs, &psz ) != OGRERR_NONE )
1751 sql =
QString(
"SELECT parameters,noupdate FROM tbl_srs WHERE auth_name='EPSG' AND auth_id='%1'" ).
arg( it.key() );
1752 if ( sqlite3_prepare( database, sql.
toAscii(), sql.
size(), &select, &tail ) != SQLITE_OK )
1754 qCritical(
"Could not prepare: %s [%s]\n", sql.
toAscii().
constData(), sqlite3_errmsg( database ) );
1759 if ( sqlite3_step( select ) == SQLITE_ROW )
1761 srsProj4 = (
const char * ) sqlite3_column_text( select, 0 );
1763 if (
QString::fromUtf8((
char * )sqlite3_column_text( select, 1 ) ).toInt() != 0 )
1767 sqlite3_finalize( select );
1771 if ( proj4 != srsProj4 )
1774 sql =
QString(
"UPDATE tbl_srs SET parameters=%1 WHERE auth_name='EPSG' AND auth_id=%2" ).
arg( quotedValue( proj4 ) ).
arg( it.key() );
1776 if ( sqlite3_exec( database, sql.
toUtf8(), 0, 0, &errMsg ) != SQLITE_OK )
1778 qCritical(
"Could not execute: %s [%s/%s]\n",
1780 sqlite3_errmsg( database ),
1781 errMsg ? errMsg :
"(unknown error)" );
1793 QRegExp projRegExp(
"\\+proj=(\\S+)" );
1794 if ( projRegExp.
indexIn( proj4 ) < 0 )
1796 QgsDebugMsg(
QString(
"EPSG %1: no +proj argument found [%2]" ).arg( it.key() ).arg( proj4 ) );
1800 QRegExp ellipseRegExp(
"\\+ellps=(\\S+)" );
1802 if ( ellipseRegExp.
indexIn( proj4 ) >= 0 )
1804 ellps = ellipseRegExp.
cap( 1 );
1807 QString name( OSRIsGeographic( crs ) ? OSRGetAttrValue( crs,
"GEOCS", 0 ) : OSRGetAttrValue( crs,
"PROJCS", 0 ) );
1811 sql =
QString(
"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)" )
1812 .
arg( quotedValue( name ),
1813 quotedValue( projRegExp.
cap( 1 ) ),
1814 quotedValue( ellps ),
1815 quotedValue( proj4 ) )
1817 .arg( OSRIsGeographic( crs ) );
1820 if ( sqlite3_exec( database, sql.
toUtf8(), 0, 0, &errMsg ) == SQLITE_OK )
1826 qCritical(
"Could not execute: %s [%s/%s]\n",
1828 sqlite3_errmsg( database ),
1829 errMsg ? errMsg :
"(unknown error)" );
1833 sqlite3_free( errMsg );
1838 sql =
"DELETE FROM tbl_srs WHERE auth_name='EPSG' AND NOT auth_id IN (";
1840 Q_FOREACH (
int i, wkts.
keys() )
1845 sql +=
") AND NOT noupdate";
1847 if ( sqlite3_exec( database, sql.
toUtf8(), 0, 0, 0 ) == SQLITE_OK )
1849 deleted = sqlite3_changes( database );
1854 qCritical(
"Could not execute: %s [%s]\n",
1856 sqlite3_errmsg( database ) );
1859 #if !defined(PJ_VERSION) || PJ_VERSION!=470
1860 sql =
QString(
"select auth_name,auth_id,parameters from tbl_srs WHERE auth_name<>'EPSG' AND NOT deprecated AND NOT noupdate" );
1861 if ( sqlite3_prepare( database, sql.
toAscii(), sql.
size(), &select, &tail ) == SQLITE_OK )
1863 while ( sqlite3_step( select ) == SQLITE_ROW )
1865 const char *auth_name = (
const char * ) sqlite3_column_text( select, 0 );
1866 const char *auth_id = (
const char * ) sqlite3_column_text( select, 1 );
1867 const char *params = (
const char * ) sqlite3_column_text( select, 2 );
1873 input =
QString(
"+init=%1:%2" ).
arg(
QString( auth_name ).toUpper(), auth_id );
1874 pj = pj_init_plus( input.
toAscii() );
1879 char *def = pj_get_def( pj, 0 );
1888 proj4 = proj4.
mid( input.
size() );
1892 if ( proj4 != params )
1894 sql =
QString(
"UPDATE tbl_srs SET parameters=%1 WHERE auth_name=%2 AND auth_id=%3" )
1895 .
arg( quotedValue( proj4 ),
1896 quotedValue( auth_name ),
1897 quotedValue( auth_id ) );
1899 if ( sqlite3_exec( database, sql.
toUtf8(), 0, 0, &errMsg ) == SQLITE_OK )
1906 qCritical(
"Could not execute: %s [%s/%s]\n",
1908 sqlite3_errmsg( database ),
1909 errMsg ? errMsg :
"(unknown error)" );
1916 QgsDebugMsg(
QString(
"could not retrieve proj string for %1 from PROJ" ).arg( input ) );
1930 qCritical(
"Could not execute: %s [%s]\n",
1932 sqlite3_errmsg( database ) );
1936 OSRDestroySpatialReference( crs );
1938 if ( sqlite3_exec( database,
"COMMIT", 0, 0, 0 ) != SQLITE_OK )
1940 qCritical(
"Could not commit transaction: %s [%s]\n",
QgsApplication::srsDbFilePath().toLocal8Bit().constData(), sqlite3_errmsg( database ) );
1944 sqlite3_close( database );
1946 qWarning(
"CRS update (inserted:%d updated:%d deleted:%d errors:%d)", inserted, updated, deleted, errors );
1951 return updated + inserted;
1954 bool QgsCoordinateReferenceSystem::syncDatumTransform(
const QString& dbPath )
1956 const char *filename = CSVFilename(
"datum_shift.csv" );
1957 FILE *fp = VSIFOpen( filename,
"rb" );
1963 char **fieldnames = CSVReadParseLine( fp );
1975 {
"SOURCE_CRS_CODE",
"source_crs_code", -1 },
1976 {
"TARGET_CRS_CODE",
"target_crs_code", -1 },
1977 {
"REMARKS",
"remarks", -1 },
1978 {
"COORD_OP_SCOPE",
"scope", -1 },
1979 {
"AREA_OF_USE_CODE",
"area_of_use_code", -1 },
1985 {
"DEPRECATED",
"deprecated", -1 },
1986 {
"COORD_OP_METHOD_CODE",
"coord_op_method_code", -1 },
1994 {
"PREFERRED",
"preferred", -1 },
1995 {
"COORD_OP_CODE",
"coord_op_code", -1 },
1998 QString update =
"UPDATE tbl_datum_transform SET ";
2001 int n = CSLCount( fieldnames );
2003 int idxid = -1, idxrx = -1, idxry = -1, idxrz = -1, idxmcode = -1;
2004 for (
unsigned int i = 0; i <
sizeof(
map ) /
sizeof( *map ); i++ )
2006 bool last = i ==
sizeof(
map ) /
sizeof( *map ) - 1;
2008 map[i].idx = CSLFindString( fieldnames, map[i].src );
2009 if ( map[i].idx < 0 )
2011 qWarning(
"field %s not found", map[i].src );
2012 CSLDestroy( fieldnames );
2017 if ( strcmp( map[i].src,
"COORD_OP_CODE" ) == 0 )
2019 if ( strcmp( map[i].src,
"RX" ) == 0 )
2021 if ( strcmp( map[i].src,
"RY" ) == 0 )
2023 if ( strcmp( map[i].src,
"RZ" ) == 0 )
2025 if ( strcmp( map[i].src,
"COORD_OP_METHOD_CODE" ) == 0 )
2035 update +=
" WHERE ";
2043 update +=
QString(
"%1=%%2" ).
arg( map[i].dst ).
arg( i + 1 );
2045 insert +=
map[i].dst;
2049 insert =
"INSERT INTO tbl_datum_transform(" + insert +
") VALUES (" + values +
")";
2054 CSLDestroy( fieldnames );
2056 Q_ASSERT( idxid >= 0 );
2057 Q_ASSERT( idxrx >= 0 );
2058 Q_ASSERT( idxry >= 0 );
2059 Q_ASSERT( idxrz >= 0 );
2063 if ( openResult != SQLITE_OK )
2069 if ( sqlite3_exec( db,
"BEGIN TRANSACTION", 0, 0, 0 ) != SQLITE_OK )
2072 sqlite3_close( db );
2078 v.
reserve(
sizeof( map ) /
sizeof( *map ) );
2080 while ( !feof( fp ) )
2082 char **values = CSVReadParseLine( fp );
2086 if ( CSLCount( values ) < n )
2088 qWarning(
"Only %d columns", CSLCount( values ) );
2092 for (
unsigned int i = 0; i <
sizeof(
map ) /
sizeof( *map ); i++ )
2094 int idx =
map[i].idx;
2095 Q_ASSERT( idx != -1 );
2096 Q_ASSERT( idx < n );
2097 v.
insert( i, *values[ idx ] ? quotedValue( values[idx] ) :
"NULL" );
2103 v[ idxmcode ] =
"'9606'";
2104 v[ idxrx ] =
"'" +
qgsDoubleToString( -( v[ idxrx ].
remove(
"'" ).toDouble() ) ) +
"'";
2105 v[ idxry ] =
"'" +
qgsDoubleToString( -( v[ idxry ].
remove(
"'" ).toDouble() ) ) +
"'";
2106 v[ idxrz ] =
"'" +
qgsDoubleToString( -( v[ idxrz ].
remove(
"'" ).toDouble() ) ) +
"'";
2112 QString sql =
QString(
"SELECT coord_op_code FROM tbl_datum_transform WHERE coord_op_code=%1" ).
arg( v[ idxid ] );
2113 int prepareRes = sqlite3_prepare( db, sql.
toAscii(), sql.
size(), &stmt, NULL );
2114 if ( prepareRes != SQLITE_OK )
2117 if ( sqlite3_step( stmt ) == SQLITE_ROW )
2119 cOpCode = (
const char * ) sqlite3_column_text( stmt, 0 );
2121 sqlite3_finalize( stmt );
2123 sql = cOpCode.
isEmpty() ? insert : update;
2124 for (
int i = 0; i < v.
size(); i++ )
2126 sql = sql.
arg( v[i] );
2129 if ( sqlite3_exec( db, sql.
toUtf8(), 0, 0, 0 ) != SQLITE_OK )
2132 qCritical(
"Error: %s", sqlite3_errmsg( db ) );
2136 if ( sqlite3_exec( db,
"COMMIT", 0, 0, 0 ) != SQLITE_OK )
2142 sqlite3_close( db );
2154 return OSRGetAuthorityName( mCRS,
"GEOGCS" ) +
QLatin1String(
":" ) + OSRGetAuthorityCode( mCRS,
"GEOGCS" );
2174 if ( projectionsAuthId.
size() >= projections.
size() )
2178 projections.
clear();
2179 for (
int i = 0; i < projectionsAuthId.
size(); i++ )
2193 if ( crs.
srsid() == 0 )
QgsCoordinateReferenceSystem()
Default constructor.
bool createFromSrid(const long theSrid)
Set up this srs by fetching the appropriate information from the sqlite backend.
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QString cap(int nth) const
QString & append(QChar ch)
const QgsCoordinateReferenceSystem & crsByAuthId(const QString &authid)
Returns the CRS for authid, e.g.
iterator insert(const Key &key, const T &value)
bool createFromWkt(const QString &theWkt)
Set up this srs using a Wkt spatial ref sys definition.
static QString qgisUserDbFilePath()
Returns the path to the user qgis.db file.
QDomNode appendChild(const QDomNode &newChild)
long srsid() const
Get the SrsId - if possible.
void validate()
Perform some validation on this CRS.
QString geographicCRSAuthId() const
Returns auth id of related geographic CRS.
UnitType
Map units that qgis supports.
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
QString & prepend(QChar ch)
static void warning(const QString &msg)
Goes to qWarning.
void setFile(const QString &file)
const T & at(int i) const
QString toWkt() const
A helper to get an wkt representation of this srs.
long postgisSrid() const
Get the postgis srid for this srs.
bool createFromId(const long theId, CrsType theType=PostgisCrsId)
The QGis class provides global constants for use throughout the application.
bool axisInverted() const
Return if axis is inverted (eg.
static CUSTOM_CRS_VALIDATION customSrsValidation()
Gets custom function.
int count(const Key &key) const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
bool createFromString(const QString &theDefinition)
Set up this srs from a string definition, by default a WKT definition.
static void setCustomSrsValidation(CUSTOM_CRS_VALIDATION f)
Sets custom function to force valid CRS QGIS uses implementation in QgisGui::customSrsValidation.
void setPattern(const QString &pattern)
QDomElement toElement() const
int matchedLength() const
void setValue(const QString &key, const QVariant &value)
int indexIn(const QString &str, int offset, CaretMode caretMode) const
bool createFromOgcWmsCrs(QString theCrs)
Set up this CRS from the given OGC CRS.
void setValidationHint(const QString &html)
Set user hint for validation.
QString number(int n, int base)
bool createFromSrsId(const long theSrsId)
Set up this srs by fetching the appropriate information from the sqlite backend.
void append(const T &value)
QString fromUtf8(const char *str, int size)
const_iterator constEnd() const
#define QgsDebugMsgLevel(str, level)
static QStringList recentProjections()
Returns a list of recently used projections.
QString validationHint()
Get user hint for validation.
bool createFromUserInput(const QString &theDefinition)
Set up this srs from a various text formats.
int toInt(bool *ok, int base) const
long findMatchingProj()
This is a globbing function to try to find a record in the database that matches a CRS defined only b...
const char * constData() const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
const long GEOCRS_ID
Magic number for a geographic coord sys in QGIS srs.db tbl_srs.srs_id.
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
QgsCoordinateReferenceSystem & operator=(const QgsCoordinateReferenceSystem &srs)
Assignment operator.
const QString GEO_EPSG_CRS_AUTHID
Geographic coord sys from EPSG authority.
static int syncDb()
Update proj.4 parameters in our database from proj.4.
QFuture< void > map(Sequence &sequence, MapFunction function)
QString ellipsoidAcronym() const
Get the Ellipsoid Acronym.
bool saveAsUserCRS(const QString &name)
Save the proj4-string as a custom CRS.
QList< Key > keys() const
~QgsCoordinateReferenceSystem()
QDomText createTextNode(const QString &value)
QByteArray toLocal8Bit() const
QDomNode namedItem(const QString &name) const
QString qgsDoubleToString(const double &a, const int &precision=17)
long toLong(bool *ok, int base) const
bool isValid() const
Find out whether this CRS is correctly initialised and usable.
QString & replace(int position, int n, QChar after)
QVariant value(const QString &key, const QVariant &defaultValue) const
const_iterator constBegin() const
const int USER_CRS_START_ID
Magick number that determines whether a projection crsid is a system (srs.db) or user (~/...
bool writeXML(QDomNode &theNode, QDomDocument &theDoc) const
Stores state to the given Dom node in the given document.
QByteArray toLatin1() const
QString mid(int position, int n) const
QStringList toStringList() const
QString projectionAcronym() const
Get the Projection Acronym.
void insert(int i, const T &value)
Class for storing a coordinate reference system (CRS)
const int LAT_PREFIX_LEN
The length of the string "+lat_1=".
QString authid() const
Get the authority identifier for this srs.
QString left(int n) const
bool readXML(QDomNode &theNode)
Restores state from the given Dom node.
static QString srsDbFilePath()
Returns the path to the srs.db file.
QString description() const
Get the Description.
bool operator!=(const QgsCoordinateReferenceSystem &theSrs) const
Overloaded != operator used to compare to CRS's.
void(* CUSTOM_CRS_VALIDATION)(QgsCoordinateReferenceSystem &)
QDomElement createElement(const QString &tagName)
bool operator==(const QgsCoordinateReferenceSystem &theSrs) const
Overloaded == operator used to compare to CRS's.
bool geographicFlag() const
Get this Geographic? flag.
int compare(const QString &other) const
bool exactMatch(const QString &str) const
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
static QgsCRSCache * instance()
static void setupESRIWktFix()
Make sure that ESRI WKT import is done properly.
QByteArray toAscii() const
bool createFromProj4(const QString &theProjString)
Set up this srs by passing it a proj4 style formatted string.
void * OGRSpatialReferenceH
QString toProj4() const
Get the Proj Proj4 string representation of this srs.
QByteArray toUtf8() const
QGis::UnitType mapUnits() const
Get the units that the projection is in.