23 #include <QTemporaryFile>
25 #include <QDomElement>
28 #include <QTextStream>
42 #include <ogr_srs_api.h>
43 #include <cpl_error.h>
54 , mMapUnits(
QGis::UnknownUnit )
57 , mValidationHint(
"" )
58 , mAxisInverted( false )
60 mCRS = OSRNewSpatialReference( NULL );
66 , mMapUnits(
QGis::UnknownUnit )
69 , mValidationHint(
"" )
70 , mAxisInverted( false )
72 mCRS = OSRNewSpatialReference( NULL );
80 , mMapUnits(
QGis::UnknownUnit )
83 , mValidationHint(
"" )
84 , mAxisInverted( false )
86 mCRS = OSRNewSpatialReference( NULL );
92 OSRDestroySpatialReference(
mCRS );
119 QRegExp reCrsId(
"^(epsg|postgis|internal)\\:(\\d+)$", Qt::CaseInsensitive );
120 if ( reCrsId.indexIn( theDefinition ) == 0 )
122 QString authName = reCrsId.cap( 1 ).toLower();
124 if ( authName ==
"epsg" )
126 if ( authName ==
"postgis" )
128 long id = reCrsId.cap( 2 ).toLong();
133 QRegExp reCrsStr(
"^(?:(wkt|proj4)\\:)?(.+)$", Qt::CaseInsensitive );
134 if ( reCrsStr.indexIn( theDefinition ) == 0 )
136 if ( reCrsStr.cap( 1 ).toLower() ==
"proj4" )
145 QString myName = QString(
" * %1 (%2)" )
146 .arg(
QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ) )
167 #if GDAL_VERSION_NUM >= 1900
168 if ( theDefinition.startsWith(
"ESRI::" ) )
174 if ( OSRSetFromUserInput( crs, theDefinition.toLocal8Bit().constData() ) == OGRERR_NONE )
176 if ( OSRExportToWkt( crs, &wkt ) == OGRERR_NONE )
181 OSRDestroySpatialReference( crs );
191 #if GDAL_VERSION_NUM >= 1900
192 const char* configOld = CPLGetConfigOption(
"GDAL_FIX_ESRI_WKT",
"" );
193 const char* configNew =
"GEOGCS";
195 if ( strcmp( configOld,
"" ) == 0 )
197 CPLSetConfigOption(
"GDAL_FIX_ESRI_WKT", configNew );
198 if ( strcmp( configNew, CPLGetConfigOption(
"GDAL_FIX_ESRI_WKT",
"" ) ) != 0 )
200 .arg( configNew ).arg( CPLGetConfigOption(
"GDAL_FIX_ESRI_WKT",
"" ) ) ) ;
201 QgsDebugMsg( QString(
"set GDAL_FIX_ESRI_WKT : %1" ).arg( configNew ) );
205 QgsDebugMsg( QString(
"GDAL_FIX_ESRI_WKT was already set : %1" ).arg( configNew ) );
212 QRegExp re(
"urn:ogc:def:crs:([^:]+).+([^:]+)", Qt::CaseInsensitive );
213 if ( re.exactMatch( theCrs ) )
215 theCrs = re.cap( 1 ) +
":" + re.cap( 2 );
219 re.setPattern(
"(user|custom|qgis):(\\d+)" );
220 if ( re.exactMatch( theCrs ) &&
createFromSrsId( re.cap( 2 ).toInt() ) )
230 if ( theCrs.compare(
"CRS:27", Qt::CaseInsensitive ) == 0 ||
231 theCrs.compare(
"OGC:CRS27", Qt::CaseInsensitive ) == 0 )
238 if ( theCrs.compare(
"CRS:83", Qt::CaseInsensitive ) == 0 ||
239 theCrs.compare(
"OGC:CRS83", Qt::CaseInsensitive ) == 0 )
246 if ( theCrs.compare(
"CRS:84", Qt::CaseInsensitive ) == 0 ||
247 theCrs.compare(
"OGC:CRS84", Qt::CaseInsensitive ) == 0 )
259 mCRS = OSRNewSpatialReference( NULL );
283 OSRDestroySpatialReference(
mCRS );
317 "srs_id", QString::number(
id ) );
322 QgsDebugMsgLevel(
"load CRS from " + db +
" where " + expression +
" is " + value, 3 );
326 QFileInfo myInfo( db );
327 if ( !myInfo.exists() )
329 QgsDebugMsg(
"failed : " + db +
" does not exist!" );
335 sqlite3_stmt *myPreparedStatement;
338 myResult =
openDb( db, &myDatabase );
339 if ( myResult != SQLITE_OK )
341 QgsDebugMsg(
"failed : " + db +
" could not be opened!" );
357 QString mySql =
"select srs_id,description,projection_acronym,"
358 "ellipsoid_acronym,parameters,srid,auth_name||':'||auth_id,is_geo "
359 "from tbl_srs where " + expression +
"=" +
quotedValue( value ) +
" order by deprecated";
360 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(),
361 mySql.toUtf8().length(),
362 &myPreparedStatement, &myTail );
364 if ( myResult == SQLITE_OK && sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
366 mSrsId = QString::fromUtf8((
char * )sqlite3_column_text(
367 myPreparedStatement, 0 ) ).toLong();
368 mDescription = QString::fromUtf8((
char * )sqlite3_column_text(
369 myPreparedStatement, 1 ) );
370 mProjectionAcronym = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 2 ) );
371 mEllipsoidAcronym = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 3 ) );
372 mProj4 = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 4 ) );
373 mSRID = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 5 ) ).toLong();
374 mAuthId = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 6 ) );
375 mGeoFlag = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 7 ) ).toInt() != 0;
382 else if (
mAuthId.startsWith(
"EPSG:", Qt::CaseInsensitive ) )
384 OSRDestroySpatialReference(
mCRS );
385 mCRS = OSRNewSpatialReference( NULL );
399 sqlite3_finalize( myPreparedStatement );
400 sqlite3_close( myDatabase );
408 OGRAxisOrientation orientation;
409 OSRGetAxis(
mCRS, OSRIsGeographic(
mCRS ) ?
"GEOGCS" :
"PROJCS", 0, &orientation );
412 if ( orientation == OAO_Other &&
mAuthId.startsWith(
"EPSG:", Qt::CaseInsensitive ) )
416 if ( OSRImportFromEPSGA( crs,
mAuthId.mid( 5 ).toInt() ) == OGRERR_NONE )
418 OSRGetAxis( crs, OSRIsGeographic( crs ) ?
"GEOGCS" :
"PROJCS", 0, &orientation );
421 OSRDestroySpatialReference( crs );
436 if ( theWkt.isEmpty() )
438 QgsDebugMsg(
"theWkt is uninitialised, operation failed" );
442 QByteArray ba = theWkt.toLatin1();
443 const char *pWkt = ba.data();
445 OGRErr myInputResult = OSRImportFromWkt(
mCRS, (
char ** ) & pWkt );
447 if ( myInputResult != OGRERR_NONE )
449 QgsDebugMsg(
"\n---------------------------------------------------------------" );
450 QgsDebugMsg(
"This CRS could *** NOT *** be set from the supplied Wkt " );
452 QgsDebugMsg( QString(
"UNUSED WKT: %1" ).arg( pWkt ) );
453 QgsDebugMsg(
"---------------------------------------------------------------\n" );
457 if ( OSRAutoIdentifyEPSG(
mCRS ) == OGRERR_NONE )
459 QString
authid = QString(
"%1:%2" )
460 .arg( OSRGetAuthorityName(
mCRS, NULL ) )
461 .arg( OSRGetAuthorityCode(
mCRS, NULL ) );
471 char *proj4src = NULL;
472 OSRExportToProj4(
mCRS, &proj4src );
484 OSRExportToProj4(
mCRS, &proj4src );
494 QString myName = QString(
" * %1 (%2)" )
495 .arg(
QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ) )
521 QString myProj4String = theProj4String.trimmed();
526 QRegExp myProjRegExp(
"\\+proj=(\\S+)" );
527 int myStart = myProjRegExp.indexIn( myProj4String );
530 QgsDebugMsg(
"proj string supplied has no +proj argument" );
536 QRegExp myEllipseRegExp(
"\\+ellps=(\\S+)" );
537 myStart = myEllipseRegExp.indexIn( myProj4String );
540 QgsDebugMsg(
"proj string supplied has no +ellps argument" );
548 QRegExp myAxisRegExp(
"\\+a=(\\S+)" );
549 myStart = myAxisRegExp.indexIn( myProj4String );
552 QgsDebugMsg(
"proj string supplied has no +a argument" );
570 myRecord =
getRecord(
"select * from tbl_srs where parameters=" +
quotedValue( myProj4String ) +
" order by deprecated" );
571 if ( myRecord.empty() )
576 QRegExp myLat1RegExp(
"\\+lat_1=\\S+" );
577 QRegExp myLat2RegExp(
"\\+lat_2=\\S+" );
582 QString lat1Str =
"";
583 QString lat2Str =
"";
584 myStart1 = myLat1RegExp.indexIn( myProj4String, myStart1 );
585 myStart2 = myLat2RegExp.indexIn( myProj4String, myStart2 );
586 if ( myStart1 != -1 && myStart2 != -1 )
588 myLength1 = myLat1RegExp.matchedLength();
589 myLength2 = myLat2RegExp.matchedLength();
594 if ( lat1Str !=
"" && lat2Str !=
"" )
597 QString theProj4StringModified = myProj4String;
602 myStart2 = myLat2RegExp.indexIn( theProj4String, myStart2 );
604 QgsDebugMsg(
"trying proj4string match with swapped lat_1,lat_2" );
605 myRecord =
getRecord(
"select * from tbl_srs where parameters=" +
quotedValue( theProj4StringModified.trimmed() ) +
" order by deprecated" );
609 if ( myRecord.empty() )
616 QString sql =
"SELECT * FROM tbl_srs WHERE ";
623 QStringList myParams;
624 foreach ( QString param, myProj4String.split( QRegExp(
"\\s+(?=\\+)" ), QString::SkipEmptyParts ) )
626 QString arg = QString(
"' '||parameters||' ' LIKE %1" ).arg(
quotedValue( QString(
"% %1 %" ).arg( param.trimmed() ) ) );
627 if ( param.startsWith(
"+datum=" ) )
635 myParams << param.trimmed();
639 if ( !datum.isEmpty() )
641 myRecord =
getRecord( sql + delim + datum +
" order by deprecated" );
644 if ( myRecord.empty() )
647 myRecord =
getRecord( sql +
" order by deprecated" );
650 if ( !myRecord.empty() )
653 QStringList foundParams;
654 foreach ( QString param, myRecord[
"parameters"].split( QRegExp(
"\\s+(?=\\+)" ), QString::SkipEmptyParts ) )
656 if ( !param.startsWith(
"+datum=" ) )
657 foundParams << param.trimmed();
663 if ( myParams != foundParams )
670 if ( !myRecord.empty() )
672 mySrsId = myRecord[
"srs_id"].toLong();
673 QgsDebugMsg(
"proj4string param match search for srsid returned srsid: " + QString::number( mySrsId ) );
682 QgsDebugMsg(
"globbing search for srsid from this proj string" );
685 QgsDebugMsg(
"globbing search for srsid returned srsid: " + QString::number( mySrsId ) );
699 QgsDebugMsg(
"Projection is not found in databases." );
710 QString myDatabaseFileName;
713 QString myFieldValue;
716 sqlite3_stmt *myPreparedStatement;
722 QFileInfo myInfo( myDatabaseFileName );
723 if ( !myInfo.exists() )
725 QgsDebugMsg(
"failed : " + myDatabaseFileName +
" does not exist!" );
730 myResult =
openDb( myDatabaseFileName, &myDatabase );
731 if ( myResult != SQLITE_OK )
736 myResult = sqlite3_prepare( myDatabase, theSql.toUtf8(), theSql.toUtf8().length(), &myPreparedStatement, &myTail );
738 if ( myResult == SQLITE_OK && sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
741 int myColumnCount = sqlite3_column_count( myPreparedStatement );
743 for (
int myColNo = 0; myColNo < myColumnCount; myColNo++ )
745 myFieldName = QString::fromUtf8((
char * )sqlite3_column_name( myPreparedStatement, myColNo ) );
746 myFieldValue = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, myColNo ) );
747 myMap[myFieldName] = myFieldValue;
749 if ( sqlite3_step( myPreparedStatement ) != SQLITE_DONE )
763 sqlite3_finalize( myPreparedStatement );
764 sqlite3_close( myDatabase );
767 QFileInfo myFileInfo;
768 myFileInfo.setFile( myDatabaseFileName );
769 if ( !myFileInfo.exists( ) )
776 myResult =
openDb( myDatabaseFileName, &myDatabase );
777 if ( myResult != SQLITE_OK )
782 myResult = sqlite3_prepare( myDatabase, theSql.toUtf8(), theSql.toUtf8().length(), &myPreparedStatement, &myTail );
784 if ( myResult == SQLITE_OK && sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
786 int myColumnCount = sqlite3_column_count( myPreparedStatement );
788 for (
int myColNo = 0; myColNo < myColumnCount; myColNo++ )
790 myFieldName = QString::fromUtf8((
char * )sqlite3_column_name( myPreparedStatement, myColNo ) );
791 myFieldValue = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, myColNo ) );
792 myMap[myFieldName] = myFieldValue;
795 if ( sqlite3_step( myPreparedStatement ) != SQLITE_DONE )
806 sqlite3_finalize( myPreparedStatement );
807 sqlite3_close( myDatabase );
811 RecordMap::Iterator it;
812 for ( it = myMap.begin(); it != myMap.end(); ++it )
882 char *proj4src = NULL;
883 OSRExportToProj4(
mCRS, &proj4src );
924 char *oldlocale = setlocale( LC_NUMERIC, NULL );
927 oldlocale = strdup( oldlocale );
929 setlocale( LC_NUMERIC,
"C" );
930 OSRDestroySpatialReference(
mCRS );
931 mCRS = OSRNewSpatialReference( NULL );
933 OSRImportFromProj4(
mCRS, theProj4String.trimmed().toLatin1().constData() )
938 #if defined(QGISDEBUG) && QGISDEBUG>=3
942 setlocale( LC_NUMERIC, oldlocale );
951 mAuthId = QString(
"EPSG:%1" ).arg( theEpsg );
976 if ( OSRIsProjected(
mCRS ) )
978 double toMeter = OSRGetLinearUnits(
mCRS, &unitName );
979 QString unit( unitName );
986 static const double feetToMeter = 0.3048;
987 static const double smallNum = 1e-3;
989 if ( qAbs( toMeter - feetToMeter ) < smallNum )
992 QgsDebugMsg(
"Projection has linear units of " + unit );
996 else if ( unit ==
"Foot" )
1000 QgsDebugMsg(
"Unsupported map units of " + unit );
1006 OSRGetAngularUnits(
mCRS, &unitName );
1007 QString unit( unitName );
1008 if ( unit ==
"degree" )
1012 QgsDebugMsg(
"Unsupported map units of " + unit );
1034 QgsDebugMsg(
"QgsCoordinateReferenceSystem::findMatchingProj will only "
1035 "work if prj acr ellipsoid acr and proj4string are set"
1036 " and the current projection is valid!" );
1042 sqlite3_stmt *myPreparedStatement;
1047 QString mySql = QString(
"select srs_id,parameters from tbl_srs where "
1048 "projection_acronym=%1 and ellipsoid_acronym=%2 order by deprecated" )
1055 myResult =
openDb( myDatabaseFileName, &myDatabase );
1056 if ( myResult != SQLITE_OK )
1061 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1063 if ( myResult == SQLITE_OK )
1066 while ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
1068 QString mySrsId = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 0 ) );
1069 QString myProj4String = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 1 ) );
1070 if (
toProj4() == myProj4String.trimmed() )
1072 QgsDebugMsg(
"-------> MATCH FOUND in srs.db srsid: " + mySrsId );
1074 sqlite3_finalize( myPreparedStatement );
1075 sqlite3_close( myDatabase );
1076 return mySrsId.toLong();
1084 QgsDebugMsg(
"no match found in srs.db, trying user db now!" );
1086 sqlite3_finalize( myPreparedStatement );
1087 sqlite3_close( myDatabase );
1094 myResult =
openDb( myDatabaseFileName, &myDatabase );
1095 if ( myResult != SQLITE_OK )
1100 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1102 if ( myResult == SQLITE_OK )
1105 while ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
1107 QString mySrsId = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 0 ) );
1108 QString myProj4String = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 1 ) );
1109 if (
toProj4() == myProj4String.trimmed() )
1111 QgsDebugMsg(
"-------> MATCH FOUND in user qgis.db srsid: " + mySrsId );
1113 sqlite3_finalize( myPreparedStatement );
1114 sqlite3_close( myDatabase );
1115 return mySrsId.toLong();
1126 sqlite3_finalize( myPreparedStatement );
1127 sqlite3_close( myDatabase );
1139 return !( *
this == theSrs );
1144 if (
mWkt.isEmpty() )
1147 if ( OSRExportToWkt(
mCRS, &wkt ) == OGRERR_NONE )
1158 QgsDebugMsg(
"Reading Spatial Ref Sys from xml ------------------------!" );
1159 QDomNode srsNode = theNode.namedItem(
"spatialrefsys" );
1161 if ( ! srsNode.isNull() )
1163 bool initialized =
false;
1165 long srsid = srsNode.namedItem(
"srsid" ).toElement().text().toLong();
1171 myNode = srsNode.namedItem(
"authid" );
1172 if ( !myNode.isNull() )
1183 myNode = srsNode.namedItem(
"epsg" );
1184 if ( !myNode.isNull() )
1196 QgsDebugMsg(
"Ignoring authid/epsg for user crs." );
1205 myNode = srsNode.namedItem(
"proj4" );
1214 QgsDebugMsg(
"Setting from elements one by one" );
1216 myNode = srsNode.namedItem(
"proj4" );
1219 myNode = srsNode.namedItem(
"srsid" );
1222 myNode = srsNode.namedItem(
"srid" );
1223 setSrid( myNode.toElement().text().toLong() );
1225 myNode = srsNode.namedItem(
"authid" );
1228 myNode = srsNode.namedItem(
"description" );
1231 myNode = srsNode.namedItem(
"projectionacronym" );
1234 myNode = srsNode.namedItem(
"ellipsoidacronym" );
1237 myNode = srsNode.namedItem(
"geographicflag" );
1238 if ( myNode.toElement().text().compare(
"true" ) )
1259 QString myName = QString(
" * %1 (%2)" )
1260 .arg(
QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ) )
1278 QDomElement myLayerNode = theNode.toElement();
1279 QDomElement mySrsElement = theDoc.createElement(
"spatialrefsys" );
1281 QDomElement myProj4Element = theDoc.createElement(
"proj4" );
1282 myProj4Element.appendChild( theDoc.createTextNode(
toProj4() ) );
1283 mySrsElement.appendChild( myProj4Element );
1285 QDomElement mySrsIdElement = theDoc.createElement(
"srsid" );
1286 mySrsIdElement.appendChild( theDoc.createTextNode( QString::number(
srsid() ) ) );
1287 mySrsElement.appendChild( mySrsIdElement );
1289 QDomElement mySridElement = theDoc.createElement(
"srid" );
1290 mySridElement.appendChild( theDoc.createTextNode( QString::number(
postgisSrid() ) ) );
1291 mySrsElement.appendChild( mySridElement );
1293 QDomElement myEpsgElement = theDoc.createElement(
"authid" );
1294 myEpsgElement.appendChild( theDoc.createTextNode(
authid() ) );
1295 mySrsElement.appendChild( myEpsgElement );
1297 QDomElement myDescriptionElement = theDoc.createElement(
"description" );
1298 myDescriptionElement.appendChild( theDoc.createTextNode(
description() ) );
1299 mySrsElement.appendChild( myDescriptionElement );
1301 QDomElement myProjectionAcronymElement = theDoc.createElement(
"projectionacronym" );
1302 myProjectionAcronymElement.appendChild( theDoc.createTextNode(
projectionAcronym() ) );
1303 mySrsElement.appendChild( myProjectionAcronymElement );
1305 QDomElement myEllipsoidAcronymElement = theDoc.createElement(
"ellipsoidacronym" );
1306 myEllipsoidAcronymElement.appendChild( theDoc.createTextNode(
ellipsoidAcronym() ) );
1307 mySrsElement.appendChild( myEllipsoidAcronymElement );
1309 QDomElement myGeographicFlagElement = theDoc.createElement(
"geographicflag" );
1310 QString myGeoFlagText =
"false";
1313 myGeoFlagText =
"true";
1316 myGeographicFlagElement.appendChild( theDoc.createTextNode( myGeoFlagText ) );
1317 mySrsElement.appendChild( myGeographicFlagElement );
1319 myLayerNode.appendChild( mySrsElement );
1336 QString myDatabaseFileName;
1337 QString myProjString;
1338 QString mySql = QString(
"select parameters from tbl_srs where srs_id = %1 order by deprecated" ).arg( theSrsId );
1340 QgsDebugMsg(
"mySrsId = " + QString::number( theSrsId ) );
1351 QFileInfo myFileInfo;
1352 myFileInfo.setFile( myDatabaseFileName );
1353 if ( !myFileInfo.exists( ) )
1367 rc =
openDb( myDatabaseFileName, &db );
1374 sqlite3_stmt *ppStmt;
1376 rc = sqlite3_prepare( db, mySql.toUtf8(), mySql.toUtf8().length(), &ppStmt, &pzTail );
1379 if ( rc == SQLITE_OK )
1381 if ( sqlite3_step( ppStmt ) == SQLITE_ROW )
1383 myProjString = QString::fromUtf8((
char* )sqlite3_column_text( ppStmt, 0 ) );
1387 sqlite3_finalize( ppStmt );
1389 sqlite3_close( db );
1392 return myProjString;
1398 int myResult = readonly
1399 ? sqlite3_open_v2( path.toUtf8().data(), db, SQLITE_OPEN_READONLY, NULL )
1400 : sqlite3_open( path.toUtf8().data(), db );
1402 if ( myResult != SQLITE_OK )
1404 QgsDebugMsg(
"Can't open database: " + QString( sqlite3_errmsg( *db ) ) );
1411 .arg( sqlite3_errmsg( *db ) ),
QObject::tr(
"CRS" ) );
1471 QString proj4String =
mProj4;
1472 if ( proj4String.isEmpty() )
1483 mySql =
"insert into tbl_srs (srs_id,description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values ("
1493 mySql =
"insert into tbl_srs (description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values ("
1502 sqlite3_stmt *myPreparedStatement;
1506 if ( myResult != SQLITE_OK )
1508 QgsDebugMsg( QString(
"Can't open or create database %1: %2" )
1510 .arg( sqlite3_errmsg( myDatabase ) ) );
1513 QgsDebugMsg( QString(
"Update or insert sql \n%1" ).arg( mySql ) );
1514 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1515 sqlite3_step( myPreparedStatement );
1520 if ( myResult == SQLITE_OK )
1522 return_id = sqlite3_last_insert_rowid( myDatabase );
1528 QStringList projectionsProj4 = settings.value(
"/UI/recentProjectionsProj4" ).toStringList();
1529 QStringList projectionsAuthId = settings.value(
"/UI/recentProjectionsAuthId" ).toStringList();
1532 projectionsProj4.append(
toProj4() );
1533 projectionsAuthId.append(
authid() );
1534 settings.setValue(
"/UI/recentProjectionsProj4", projectionsProj4 );
1535 settings.setValue(
"/UI/recentProjectionsAuthId", projectionsAuthId );
1547 sqlite3_stmt *myPreparedStatement;
1549 long myRecordCount = 0;
1552 if ( myResult != SQLITE_OK )
1554 QgsDebugMsg( QString(
"Can't open database: %1" ).arg( sqlite3_errmsg( myDatabase ) ) );
1558 QString mySql =
"select count(*) from tbl_srs";
1559 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1561 if ( myResult == SQLITE_OK )
1563 if ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
1565 QString myRecordCountString = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 0 ) );
1566 myRecordCount = myRecordCountString.toLong();
1570 sqlite3_finalize( myPreparedStatement );
1571 sqlite3_close( myDatabase );
1572 return myRecordCount;
1577 value.replace(
"'",
"''" );
1578 return value.prepend(
"'" ).append(
"'" );
1584 qDebug(
"Loading %s", filename );
1585 const char *pszFilename = CPLFindFile(
"gdal", filename );
1589 QFile csv( pszFilename );
1590 if ( !csv.open( QIODevice::ReadOnly ) )
1593 QTextStream lines( &csv );
1597 QString line = lines.readLine();
1598 if ( line.isNull() )
1601 if ( line.startsWith(
'#' ) )
1605 else if ( line.startsWith(
"include " ) )
1607 if ( !
loadWkts( wkts, line.mid( 8 ).toUtf8() ) )
1612 int pos = line.indexOf(
"," );
1617 int epsg = line.left( pos ).toInt( &ok );
1621 wkts.insert( epsg, line.mid( pos + 1 ) );
1634 foreach ( QString csv, QStringList() <<
"gcs.csv" <<
"pcs.csv" <<
"vertcs.csv" <<
"compdcs.csv" <<
"geoccs.csv" )
1636 QString filename = CPLFindFile(
"gdal", csv.toUtf8() );
1638 QFile f( filename );
1639 if ( !f.open( QIODevice::ReadOnly ) )
1642 QTextStream lines( &f );
1649 QString line = lines.readLine();
1650 if ( line.isNull() )
1653 int pos = line.indexOf(
"," );
1658 int epsg = line.left( pos ).toInt( &ok );
1663 if ( epsg == 2218 || epsg == 2221 || epsg == 2296 || epsg == 2297 || epsg == 2298 || epsg == 2299 || epsg == 2300 || epsg == 2301 || epsg == 2302 ||
1664 epsg == 2303 || epsg == 2304 || epsg == 2305 || epsg == 2306 || epsg == 2307 || epsg == 2963 || epsg == 2985 || epsg == 2986 || epsg == 3052 ||
1665 epsg == 3053 || epsg == 3139 || epsg == 3144 || epsg == 3145 || epsg == 3173 || epsg == 3295 || epsg == 3993 || epsg == 4087 || epsg == 4088 ||
1666 epsg == 5017 || epsg == 5221 || epsg == 5224 || epsg == 5225 || epsg == 5514 || epsg == 5515 || epsg == 5516 || epsg == 5819 || epsg == 5820 ||
1667 epsg == 5821 || epsg == 32600 || epsg == 32663 || epsg == 32700 )
1670 if ( OSRImportFromEPSG( crs, epsg ) != OGRERR_NONE )
1672 qDebug(
"EPSG %d: not imported", epsg );
1677 if ( OSRExportToWkt( crs, &wkt ) != OGRERR_NONE )
1679 qWarning(
"EPSG %d: not exported to WKT", epsg );
1683 wkts.insert( epsg, wkt );
1691 qDebug(
"Loaded %d/%d from %s", n, l, filename.toUtf8().constData() );
1694 OSRDestroySpatialReference( crs );
1704 int inserted = 0, updated = 0, deleted = 0, errors = 0;
1709 if ( sqlite3_open( dbFilePath.toUtf8().constData(), &database ) != SQLITE_OK )
1715 if ( sqlite3_exec( database,
"BEGIN TRANSACTION", 0, 0, 0 ) != SQLITE_OK )
1717 qCritical(
"Could not begin transaction: %s [%s]\n",
QgsApplication::srsDbFilePath().toLocal8Bit().constData(), sqlite3_errmsg( database ) );
1723 if ( sqlite3_exec( database,
"alter table tbl_srs add noupdate boolean", 0, 0, 0 ) == SQLITE_OK )
1724 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 );
1726 sqlite3_exec( database,
"UPDATE tbl_srs SET srid=141001 WHERE srid=41001 AND auth_name='OSGEO' AND auth_id='41001'", 0, 0, 0 );
1730 sqlite3_stmt *select;
1731 char *errMsg = NULL;
1735 QHash<int, QString> wkts;
1739 qDebug(
"%d WKTs loaded", wkts.count() );
1741 for ( QHash<int, QString>::const_iterator it = wkts.constBegin(); it != wkts.constEnd(); ++it )
1743 QByteArray ba( it.value().toUtf8() );
1744 char *psz = ba.data();
1745 OGRErr ogrErr = OSRImportFromWkt( crs, &psz );
1746 if ( ogrErr != OGRERR_NONE )
1749 if ( OSRExportToProj4( crs, &psz ) != OGRERR_NONE )
1753 proj4 = proj4.trimmed();
1757 if ( proj4.isEmpty() )
1760 sql = QString(
"SELECT parameters,noupdate FROM tbl_srs WHERE auth_name='EPSG' AND auth_id='%1'" ).arg( it.key() );
1761 if ( sqlite3_prepare( database, sql.toAscii(), sql.size(), &select, &tail ) != SQLITE_OK )
1763 qCritical(
"Could not prepare: %s [%s]\n", sql.toAscii().constData(), sqlite3_errmsg( database ) );
1768 if ( sqlite3_step( select ) == SQLITE_ROW )
1770 srsProj4 = (
const char * ) sqlite3_column_text( select, 0 );
1772 if ( QString::fromUtf8((
char * )sqlite3_column_text( select, 1 ) ).toInt() != 0 )
1776 sqlite3_finalize( select );
1778 if ( !srsProj4.isEmpty() )
1780 if ( proj4 != srsProj4 )
1783 sql = QString(
"UPDATE tbl_srs SET parameters=%1 WHERE auth_name='EPSG' AND auth_id=%2" ).arg(
quotedValue( proj4 ) ).arg( it.key() );
1785 if ( sqlite3_exec( database, sql.toUtf8(), 0, 0, &errMsg ) != SQLITE_OK )
1787 qCritical(
"Could not execute: %s [%s/%s]\n",
1788 sql.toLocal8Bit().constData(),
1789 sqlite3_errmsg( database ),
1790 errMsg ? errMsg :
"(unknown error)" );
1796 QgsDebugMsgLevel( QString(
"SQL: %1\n OLD:%2\n NEW:%3" ).arg( sql ).arg( srsProj4 ).arg( proj4 ), 3 );
1802 QRegExp projRegExp(
"\\+proj=(\\S+)" );
1803 if ( projRegExp.indexIn( proj4 ) < 0 )
1805 QgsDebugMsg( QString(
"EPSG %1: no +proj argument found [%2]" ).arg( it.key() ).arg( proj4 ) );
1809 QRegExp ellipseRegExp(
"\\+ellps=(\\S+)" );
1811 if ( ellipseRegExp.indexIn( proj4 ) >= 0 )
1813 ellps = ellipseRegExp.cap( 1 );
1816 QString name( OSRIsGeographic( crs ) ? OSRGetAttrValue( crs,
"GEOCS", 0 ) : OSRGetAttrValue( crs,
"PROJCS", 0 ) );
1817 if ( name.isEmpty() )
1820 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)" )
1826 .arg( OSRIsGeographic( crs ) );
1829 if ( sqlite3_exec( database, sql.toUtf8(), 0, 0, &errMsg ) == SQLITE_OK )
1835 qCritical(
"Could not execute: %s [%s/%s]\n",
1836 sql.toLocal8Bit().constData(),
1837 sqlite3_errmsg( database ),
1838 errMsg ? errMsg :
"(unknown error)" );
1842 sqlite3_free( errMsg );
1847 sql =
"DELETE FROM tbl_srs WHERE auth_name='EPSG' AND NOT auth_id IN (";
1849 foreach (
int i, wkts.keys() )
1851 sql += delim + QString::number( i );
1854 sql +=
") AND NOT noupdate";
1856 if ( sqlite3_exec( database, sql.toUtf8(), 0, 0, 0 ) == SQLITE_OK )
1858 deleted = sqlite3_changes( database );
1863 qCritical(
"Could not execute: %s [%s]\n",
1864 sql.toLocal8Bit().constData(),
1865 sqlite3_errmsg( database ) );
1868 #if !defined(PJ_VERSION) || PJ_VERSION!=470
1869 sql = QString(
"select auth_name,auth_id,parameters from tbl_srs WHERE auth_name<>'EPSG' AND NOT deprecated AND NOT noupdate" );
1870 if ( sqlite3_prepare( database, sql.toAscii(), sql.size(), &select, &tail ) == SQLITE_OK )
1872 while ( sqlite3_step( select ) == SQLITE_ROW )
1874 const char *auth_name = (
const char * ) sqlite3_column_text( select, 0 );
1875 const char *auth_id = (
const char * ) sqlite3_column_text( select, 1 );
1876 const char *params = (
const char * ) sqlite3_column_text( select, 2 );
1878 QString input = QString(
"+init=%1:%2" ).arg( QString( auth_name ).toLower() ).arg( auth_id );
1879 projPJ pj = pj_init_plus( input.toAscii() );
1882 input = QString(
"+init=%1:%2" ).arg( QString( auth_name ).toUpper() ).arg( auth_id );
1883 pj = pj_init_plus( input.toAscii() );
1888 char *def = pj_get_def( pj, 0 );
1894 input.prepend(
' ' ).append(
' ' );
1895 if ( proj4.startsWith( input ) )
1897 proj4 = proj4.mid( input.size() );
1898 proj4 = proj4.trimmed();
1901 if ( proj4 != params )
1903 sql = QString(
"UPDATE tbl_srs SET parameters=%1 WHERE auth_name=%2 AND auth_id=%3" )
1908 if ( sqlite3_exec( database, sql.toUtf8(), 0, 0, &errMsg ) == SQLITE_OK )
1911 QgsDebugMsgLevel( QString(
"SQL: %1\n OLD:%2\n NEW:%3" ).arg( sql ).arg( params ).arg( proj4 ), 3 );
1915 qCritical(
"Could not execute: %s [%s/%s]\n",
1916 sql.toLocal8Bit().constData(),
1917 sqlite3_errmsg( database ),
1918 errMsg ? errMsg :
"(unknown error)" );
1925 QgsDebugMsg( QString(
"could not retrieve proj string for %1 from PROJ" ).arg( input ) );
1930 QgsDebugMsgLevel( QString(
"could not retrieve crs for %1 from PROJ" ).arg( input ), 3 );
1939 qCritical(
"Could not execute: %s [%s]\n",
1940 sql.toLocal8Bit().constData(),
1941 sqlite3_errmsg( database ) );
1945 OSRDestroySpatialReference( crs );
1947 if ( sqlite3_exec( database,
"COMMIT", 0, 0, 0 ) != SQLITE_OK )
1949 qCritical(
"Could not commit transaction: %s [%s]\n",
QgsApplication::srsDbFilePath().toLocal8Bit().constData(), sqlite3_errmsg( database ) );
1953 sqlite3_close( database );
1955 qWarning(
"CRS update (inserted:%d updated:%d deleted:%d errors:%d)", inserted, updated, deleted, errors );
1960 return updated + inserted;
1965 const char *filename = CSVFilename(
"datum_shift.csv" );
1966 FILE *fp = VSIFOpen( filename,
"rb" );
1972 char **fieldnames = CSVReadParseLine( fp );
1984 {
"SOURCE_CRS_CODE",
"source_crs_code", -1 },
1985 {
"TARGET_CRS_CODE",
"target_crs_code", -1 },
1986 {
"REMARKS",
"remarks", -1 },
1987 {
"COORD_OP_SCOPE",
"scope", -1 },
1988 {
"AREA_OF_USE_CODE",
"area_of_use_code", -1 },
1994 {
"DEPRECATED",
"deprecated", -1 },
1995 {
"COORD_OP_METHOD_CODE",
"coord_op_method_code", -1 },
2003 {
"PREFERRED",
"preferred", -1 },
2004 {
"COORD_OP_CODE",
"coord_op_code", -1 },
2007 QString update =
"UPDATE tbl_datum_transform SET ";
2008 QString insert, values;
2010 int n = CSLCount( fieldnames );
2012 int idxid = -1, idxrx = -1, idxry = -1, idxrz = -1, idxmcode = -1;
2013 for (
unsigned int i = 0; i <
sizeof( map ) /
sizeof( *map ); i++ )
2015 bool last = i ==
sizeof( map ) /
sizeof( *map ) - 1;
2017 map[i].idx = CSLFindString( fieldnames, map[i].src );
2018 if ( map[i].idx < 0 )
2020 qWarning(
"field %s not found", map[i].src );
2021 CSLDestroy( fieldnames );
2026 if ( strcmp( map[i].src,
"COORD_OP_CODE" ) == 0 )
2028 if ( strcmp( map[i].src,
"RX" ) == 0 )
2030 if ( strcmp( map[i].src,
"RY" ) == 0 )
2032 if ( strcmp( map[i].src,
"RZ" ) == 0 )
2034 if ( strcmp( map[i].src,
"COORD_OP_METHOD_CODE" ) == 0 )
2044 update +=
" WHERE ";
2052 update += QString(
"%1=%%2" ).arg( map[i].dst ).arg( i + 1 );
2054 insert += map[i].dst;
2055 values += QString(
"%%1" ).arg( i + 1 );
2058 insert =
"INSERT INTO tbl_datum_transform(" + insert +
") VALUES (" + values +
")";
2063 CSLDestroy( fieldnames );
2065 Q_ASSERT( idxid >= 0 );
2066 Q_ASSERT( idxrx >= 0 );
2067 Q_ASSERT( idxry >= 0 );
2068 Q_ASSERT( idxrz >= 0 );
2071 int openResult = sqlite3_open( dbPath.toUtf8().constData(), &db );
2072 if ( openResult != SQLITE_OK )
2078 if ( sqlite3_exec( db,
"BEGIN TRANSACTION", 0, 0, 0 ) != SQLITE_OK )
2081 sqlite3_close( db );
2087 v.reserve(
sizeof( map ) /
sizeof( *map ) );
2089 while ( !feof( fp ) )
2091 char **values = CSVReadParseLine( fp );
2095 if ( CSLCount( values ) < n )
2097 qWarning(
"Only %d columns", CSLCount( values ) );
2101 for (
unsigned int i = 0; i <
sizeof( map ) /
sizeof( *map ); i++ )
2103 int idx = map[i].idx;
2104 Q_ASSERT( idx != -1 );
2105 Q_ASSERT( idx < n );
2106 v.insert( i, *values[ idx ] ?
quotedValue( values[idx] ) :
"NULL" );
2110 if ( v.at( idxmcode ).compare( QString(
"'9607'" ) ) == 0 )
2112 v[ idxmcode ] =
"'9606'";
2113 v[ idxrx ] =
"'" +
qgsDoubleToString( -( v[ idxrx ].
remove(
"'" ).toDouble() ) ) +
"'";
2114 v[ idxry ] =
"'" +
qgsDoubleToString( -( v[ idxry ].
remove(
"'" ).toDouble() ) ) +
"'";
2115 v[ idxrz ] =
"'" +
qgsDoubleToString( -( v[ idxrz ].
remove(
"'" ).toDouble() ) ) +
"'";
2121 QString sql = QString(
"SELECT coord_op_code FROM tbl_datum_transform WHERE coord_op_code=%1" ).arg( v[ idxid ] );
2122 int prepareRes = sqlite3_prepare( db, sql.toAscii(), sql.size(), &stmt, NULL );
2123 if ( prepareRes != SQLITE_OK )
2126 if ( sqlite3_step( stmt ) == SQLITE_ROW )
2128 cOpCode = (
const char * ) sqlite3_column_text( stmt, 0 );
2130 sqlite3_finalize( stmt );
2132 sql = cOpCode.isEmpty() ? insert : update;
2133 for (
int i = 0; i < v.size(); i++ )
2135 sql = sql.arg( v[i] );
2138 if ( sqlite3_exec( db, sql.toUtf8(), 0, 0, 0 ) != SQLITE_OK )
2140 qCritical(
"SQL: %s", sql.toUtf8().constData() );
2141 qCritical(
"Error: %s", sqlite3_errmsg( db ) );
2145 if ( sqlite3_exec( db,
"COMMIT", 0, 0, 0 ) != SQLITE_OK )
2151 sqlite3_close( db );
2163 return OSRGetAuthorityName(
mCRS,
"GEOGCS" ) + QString(
":" ) + OSRGetAuthorityCode(
mCRS,
"GEOGCS" );
QGis::UnitType mMapUnits
The map units.
QgsCoordinateReferenceSystem()
Default constructor.
bool createFromSrid(const long theSrid)
const QgsCoordinateReferenceSystem & crsByAuthId(const QString &authid)
Returns the CRS for authid, e.g.
QMap< QString, QString > RecordMap
void setValidationHint(QString html)
bool createFromWkt(const QString &theWkt)
bool mIsValidFlag
Whether this srs is properly defined and valid.
static bool loadIDs(QHash< int, QString > &wkts)
QString geographicCRSAuthId() const
Returns auth id of related geographic CRS.
bool saveAsUserCRS(QString name)
Copied from QgsCustomProjectionDialog /// Please refactor into SQL handler !!! ///.
static void warning(const QString &msg)
Goes to qWarning.
QString qgsDoubleToString(const double &a)
void setMapUnits()
Work out the projection units and set the appropriate local variable.
static int openDb(QString path, sqlite3 **db, bool readonly=true)
bool createFromId(const long theId, CrsType theType=PostgisCrsId)
QString mAuthId
If available the authority identifier for this srs.
long getRecordCount()
Helper for getting number of user CRS already in db.
bool mGeoFlag
Whether this is a geographic or projected coordinate system.
void setGeographicFlag(bool theGeoFlag)
The QGis class provides global constants for use throughout the application.
bool axisInverted() const
void setAuthId(QString theID)
static CUSTOM_CRS_VALIDATION customSrsValidation()
Gets custom function.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
bool createFromString(const QString &theDefinition)
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
RecordMap getRecord(QString theSql)
static void setCustomSrsValidation(CUSTOM_CRS_VALIDATION f)
Sets custom function to force valid CRS QGIS uses implementation in QgisGui::customSrsValidation.
void setEllipsoidAcronym(QString theEllipsoidAcronym)
bool createFromOgcWmsCrs(QString theCrs)
Set up this CRS from the given OGC CRS.
long mSRID
If available, the Postgis spatial_ref_sys identifier for this srs (defaults to 0) ...
QString mEllipsoidAcronym
The official proj4 acronym for the ellipoid.
bool createFromSrsId(const long theSrsId)
static CUSTOM_CRS_VALIDATION mCustomSrsValidation
#define QgsDebugMsgLevel(str, level)
OGRSpatialReferenceH mCRS
bool createFromUserInput(const QString &theDefinition)
const long GEOCRS_ID
Magic number for a geographic coord sys in QGIS srs.db tbl_srs.srs_id.
static QString quotedValue(QString value)
Helper for sql-safe value quoting.
QgsCoordinateReferenceSystem & operator=(const QgsCoordinateReferenceSystem &srs)
Assignment operator.
static bool loadWkts(QHash< int, QString > &wkts, const char *filename)
void setProj4String(QString theProj4String)
QString mDescription
A textual description of the srs.
QString ellipsoidAcronym() const
int mAxisInverted
Whether this is a coordinate system has inverted axis.
~QgsCoordinateReferenceSystem()
long mSrsId
The internal sqlite3 srs.db primary key for this srs.
void setSrid(long theSrid)
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
void setDescription(QString theDescription)
QString projectionAcronym() const
void setEpsg(long theEpsg)
Class for storing a coordinate reference system (CRS)
static const QString srsDbFilePath()
Returns the path to the srs.db file.
static QString proj4FromSrsId(const int theSrsId)
A static helper function to find out the proj4 string for a srsid.
static bool syncDatumTransform(const QString &dbPath)
const int LAT_PREFIX_LEN
The length of the string "+lat_1=".
UnitType
Map units that qgis supports.
bool readXML(QDomNode &theNode)
void setProjectionAcronym(QString theProjectionAcronym)
QString description() const
bool loadFromDb(QString db, QString expression, QString value)
bool operator!=(const QgsCoordinateReferenceSystem &theSrs) const
void(* CUSTOM_CRS_VALIDATION)(QgsCoordinateReferenceSystem &)
bool operator==(const QgsCoordinateReferenceSystem &theSrs) const
bool geographicFlag() const
static const QString qgisUserDbFilePath()
Returns the path to the user qgis.db file.
void setInternalId(long theSrsId)
static QgsCRSCache * instance()
static void setupESRIWktFix()
const CORE_EXPORT QString GEO_EPSG_CRS_AUTHID
Geographic coord sys from EPSG authority.
bool createFromProj4(const QString &theProjString)
void * OGRSpatialReferenceH
QString toProj4() const
Get the Proj Proj4 string representation of this srs.
QString mProjectionAcronym
The official proj4 acronym for the projection family.
QGis::UnitType mapUnits() const