24 #include <QDomElement>
27 #include <QTextStream>
37 #include <ogr_srs_api.h>
38 #include <cpl_error.h>
46 : mMapUnits(
QGis::UnknownUnit )
48 , mValidationHint(
"" )
50 mCRS = OSRNewSpatialReference( NULL );
54 : mMapUnits(
QGis::UnknownUnit )
56 , mValidationHint(
"" )
58 mCRS = OSRNewSpatialReference( NULL );
64 : mMapUnits(
QGis::UnknownUnit )
66 , mValidationHint(
"" )
68 mCRS = OSRNewSpatialReference( NULL );
74 OSRDestroySpatialReference(
mCRS );
101 QRegExp reCrsId(
"^(epsg|postgis|internal)\\:(\\d+)$", Qt::CaseInsensitive );
102 if ( reCrsId.indexIn( theDefinition ) == 0 )
104 QString authName = reCrsId.cap( 1 ).toLower();
106 if ( authName ==
"epsg" ) type =
EpsgCrsId;
108 long id = reCrsId.cap( 2 ).toLong();
113 QRegExp reCrsStr(
"^(?:(wkt|proj4)\\:)?(.+)$", Qt::CaseInsensitive );
114 if ( reCrsStr.indexIn( theDefinition ) == 0 )
116 if ( reCrsStr.cap( 1 ).toLower() ==
"proj4" )
131 QRegExp re(
"(user|custom|qgis):(\\d+)", Qt::CaseInsensitive );
132 if ( re.exactMatch( theCrs ) &&
createFromSrsId( re.cap( 2 ).toInt() ) )
140 if ( theCrs.compare(
"CRS:84", Qt::CaseInsensitive ) == 0 )
151 mCRS = OSRNewSpatialReference( NULL );
172 OSRDestroySpatialReference(
mCRS );
209 "srs_id", QString::number(
id ) );
214 QgsDebugMsgLevel(
"load CRS from " + db +
" where " + expression +
" is " + value, 3 );
217 QFileInfo myInfo( db );
218 if ( !myInfo.exists() )
220 QgsDebugMsg(
"failed : " + db +
" does not exist!" );
226 sqlite3_stmt *myPreparedStatement;
229 myResult =
openDb( db, &myDatabase );
230 if ( myResult != SQLITE_OK )
232 QgsDebugMsg(
"failed : " + db +
" could not be opened!" );
248 QString mySql =
"select srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,auth_name||':'||auth_id,is_geo from tbl_srs where " + expression +
"=" +
quotedValue( value );
249 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
251 if ( myResult == SQLITE_OK && sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
253 mSrsId = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 0 ) ).toLong();
254 mDescription = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 1 ) );
255 mProjectionAcronym = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 2 ) );
256 mEllipsoidAcronym = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 3 ) );
257 QString
toProj4 = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 4 ) );
258 mSRID = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 5 ) ).toLong();
259 mAuthId = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 6 ) );
260 mGeoFlag = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 7 ) ).toInt() != 0;
266 else if (
mAuthId.startsWith(
"EPSG:", Qt::CaseInsensitive ) )
268 OSRDestroySpatialReference(
mCRS );
269 mCRS = OSRNewSpatialReference( NULL );
283 sqlite3_finalize( myPreparedStatement );
284 sqlite3_close( myDatabase );
292 if ( theWkt.isEmpty() )
294 QgsDebugMsg(
"theWkt is uninitialised, operation failed" );
298 QByteArray ba = theWkt.toLatin1();
299 const char *pWkt = ba.data();
301 OGRErr myInputResult = OSRImportFromWkt(
mCRS, (
char ** ) & pWkt );
303 if ( myInputResult != OGRERR_NONE )
305 QgsDebugMsg(
"\n---------------------------------------------------------------" );
306 QgsDebugMsg(
"This CRS could *** NOT *** be set from the supplied Wkt " );
308 QgsDebugMsg( QString(
"UNUSED WKT: %1" ).arg( pWkt ) );
309 QgsDebugMsg(
"---------------------------------------------------------------\n" );
313 if ( OSRAutoIdentifyEPSG(
mCRS ) == OGRERR_NONE )
315 QString
authid = QString(
"%1:%2" )
316 .arg( OSRGetAuthorityName(
mCRS, NULL ) )
317 .arg( OSRGetAuthorityCode(
mCRS, NULL ) );
327 char *proj4src = NULL;
328 OSRExportToProj4(
mCRS, &proj4src );
340 OSRExportToProj4(
mCRS, &proj4src );
369 QRegExp myProjRegExp(
"\\+proj=(\\S+)" );
370 int myStart = myProjRegExp.indexIn( theProj4String );
373 QgsDebugMsg(
"proj string supplied has no +proj argument" );
379 QRegExp myEllipseRegExp(
"\\+ellps=(\\S+)" );
380 myStart = myEllipseRegExp.indexIn( theProj4String );
383 QgsDebugMsg(
"proj string supplied has no +ellps argument" );
391 QRegExp myAxisRegExp(
"\\+a=(\\S+)" );
392 myStart = myAxisRegExp.indexIn( theProj4String );
395 QgsDebugMsg(
"proj string supplied has no +a argument" );
413 myRecord =
getRecord(
"select * from tbl_srs where parameters=" +
quotedValue( theProj4String.trimmed() ) );
414 if ( myRecord.empty() )
419 QRegExp myLat1RegExp(
"\\+lat_1=\\S+" );
420 QRegExp myLat2RegExp(
"\\+lat_2=\\S+" );
425 QString lat1Str =
"";
426 QString lat2Str =
"";
427 myStart1 = myLat1RegExp.indexIn( theProj4String, myStart1 );
428 myStart2 = myLat2RegExp.indexIn( theProj4String, myStart2 );
429 if ( myStart1 != -1 && myStart2 != -1 )
431 myLength1 = myLat1RegExp.matchedLength();
432 myLength2 = myLat2RegExp.matchedLength();
437 if ( lat1Str !=
"" && lat2Str !=
"" )
440 QString theProj4StringModified = theProj4String;
445 myStart2 = myLat2RegExp.indexIn( theProj4String, myStart2 );
447 QgsDebugMsg(
"trying proj4string match with swapped lat_1,lat_2" );
448 myRecord =
getRecord(
"select * from tbl_srs where parameters=" +
quotedValue( theProj4StringModified.trimmed() ) );
452 if ( myRecord.empty() )
459 QString sql =
"SELECT * FROM tbl_srs WHERE ";
462 foreach( QString param, theProj4String.split(
" ", QString::SkipEmptyParts ) )
464 QString arg = QString(
"' '||parameters||' ' LIKE %1" ).arg(
quotedValue( QString(
"% %1 %" ).arg( param ) ) );
465 if ( param.startsWith(
"+datum=" ) )
476 if ( !datum.isEmpty() )
478 myRecord =
getRecord( sql + delim + datum );
481 if ( myRecord.empty() )
488 if ( !myRecord.empty() )
490 mySrsId = myRecord[
"srs_id"].toLong();
491 QgsDebugMsg(
"proj4string param match search for srsid returned srsid: " + QString::number( mySrsId ) );
500 QgsDebugMsg(
"globbing search for srsid from this proj string" );
503 QgsDebugMsg(
"globbing search for srsid returned srsid: " + QString::number( mySrsId ) );
517 QgsDebugMsg(
"Projection is not found in databases." );
525 if ( myRecord.empty() )
528 QgsDebugMsg(
"Projection appears to be valid. Save to database!" );
538 if ( !myRecord.empty() )
541 mySrsId = myRecord[
"srs_id"].toLong();
542 QgsDebugMsg(
"proj4string match search for srsid returned srsid: " + QString::number( mySrsId ) );
549 QgsDebugMsg( QString(
"invalid srid %1 found" ).arg( mySrsId ) );
555 QgsDebugMsg(
"Couldn't find newly added proj string?" );
568 QString myDatabaseFileName;
571 QString myFieldValue;
574 sqlite3_stmt *myPreparedStatement;
580 QFileInfo myInfo( myDatabaseFileName );
581 if ( !myInfo.exists() )
584 " does not exist!" );
589 myResult =
openDb( myDatabaseFileName, &myDatabase );
590 if ( myResult != SQLITE_OK )
595 myResult = sqlite3_prepare( myDatabase, theSql.toUtf8(), theSql.toUtf8().length(), &myPreparedStatement, &myTail );
597 if ( myResult == SQLITE_OK && sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
600 int myColumnCount = sqlite3_column_count( myPreparedStatement );
602 for (
int myColNo = 0; myColNo < myColumnCount; myColNo++ )
604 myFieldName = QString::fromUtf8((
char * )sqlite3_column_name( myPreparedStatement, myColNo ) );
605 myFieldValue = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, myColNo ) );
606 myMap[myFieldName] = myFieldValue;
612 sqlite3_finalize( myPreparedStatement );
613 sqlite3_close( myDatabase );
616 QFileInfo myFileInfo;
617 myFileInfo.setFile( myDatabaseFileName );
618 if ( !myFileInfo.exists( ) )
625 myResult =
openDb( myDatabaseFileName, &myDatabase );
626 if ( myResult != SQLITE_OK )
631 myResult = sqlite3_prepare( myDatabase, theSql.toUtf8(), theSql.toUtf8().length(), &myPreparedStatement, &myTail );
633 if ( myResult == SQLITE_OK && sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
635 int myColumnCount = sqlite3_column_count( myPreparedStatement );
637 for (
int myColNo = 0; myColNo < myColumnCount; myColNo++ )
639 myFieldName = QString::fromUtf8((
char * )sqlite3_column_name( myPreparedStatement, myColNo ) );
640 myFieldValue = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, myColNo ) );
641 myMap[myFieldName] = myFieldValue;
650 sqlite3_finalize( myPreparedStatement );
651 sqlite3_close( myDatabase );
655 RecordMap::Iterator it;
656 for ( it = myMap.begin(); it != myMap.end(); ++it )
681 if (
mAuthId.startsWith(
"EPSG:", Qt::CaseInsensitive ) )
682 return mAuthId.mid( 5 ).toLong();
734 char *proj4src = NULL;
735 OSRExportToProj4(
mCRS, &proj4src );
740 return toProj4.trimmed();
775 const char *oldlocale = setlocale( LC_NUMERIC, NULL );
777 setlocale( LC_NUMERIC,
"C" );
778 OSRDestroySpatialReference(
mCRS );
779 mCRS = OSRNewSpatialReference( NULL );
780 mIsValidFlag = OSRImportFromProj4(
mCRS, theProj4String.toLatin1().constData() ) == OGRERR_NONE;
783 #if defined(QGISDEBUG) && QGISDEBUG>=3
787 setlocale( LC_NUMERIC, oldlocale );
795 mAuthId = QString(
"EPSG:%1" ).arg( theEpsg );
820 if ( OSRIsProjected(
mCRS ) )
822 double toMeter = OSRGetLinearUnits(
mCRS, &unitName );
823 QString unit( unitName );
830 static const double feetToMeter = 0.3048;
831 static const double smallNum = 1e-3;
833 if ( qAbs( toMeter - feetToMeter ) < smallNum )
836 QgsDebugMsg(
"Projection has linear units of " + unit );
840 else if ( unit ==
"Foot" )
850 OSRGetAngularUnits(
mCRS, &unitName );
851 QString unit( unitName );
852 if ( unit ==
"degree" )
877 QgsDebugMsg(
"QgsCoordinateReferenceSystem::findMatchingProj will only work if prj acr ellipsoid acr and proj4string are set"
878 " and the current projection is valid!" );
884 sqlite3_stmt *myPreparedStatement;
888 QString mySql = QString(
"select srs_id,parameters from tbl_srs where projection_acronym=%1 and ellipsoid_acronym=%2" )
895 myResult =
openDb( myDatabaseFileName, &myDatabase );
896 if ( myResult != SQLITE_OK )
901 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
903 if ( myResult == SQLITE_OK )
906 while ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
908 QString mySrsId = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 0 ) );
909 QString myProj4String = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 1 ) );
910 if (
equals( myProj4String ) )
912 QgsDebugMsg(
"-------> MATCH FOUND in srs.db srsid: " + mySrsId );
914 sqlite3_finalize( myPreparedStatement );
915 sqlite3_close( myDatabase );
916 return mySrsId.toLong();
924 QgsDebugMsg(
"no match found in srs.db, trying user db now!" );
926 sqlite3_finalize( myPreparedStatement );
927 sqlite3_close( myDatabase );
934 myResult =
openDb( myDatabaseFileName, &myDatabase );
935 if ( myResult != SQLITE_OK )
940 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
942 if ( myResult == SQLITE_OK )
945 while ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
947 QString mySrsId = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 0 ) );
948 QString myProj4String = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 1 ) );
949 if (
equals( myProj4String ) )
951 QgsDebugMsg(
"-------> MATCH FOUND in user qgis.db srsid: " + mySrsId );
953 sqlite3_finalize( myPreparedStatement );
954 sqlite3_close( myDatabase );
955 return mySrsId.toLong();
966 sqlite3_finalize( myPreparedStatement );
967 sqlite3_close( myDatabase );
982 if (( OSRExportToWkt(
mCRS, &thisStr ) == OGRERR_NONE ) )
984 if ( OSRExportToWkt( theSrs.
mCRS, &otherStr ) == OGRERR_NONE )
988 if ( !strcmp( thisStr, otherStr ) )
1004 return !( *
this == theSrs );
1018 if ( OSRExportToWkt(
mCRS, &Wkt ) == OGRERR_NONE )
1029 QgsDebugMsg(
"Reading Spatial Ref Sys from xml ------------------------!" );
1030 QDomNode srsNode = theNode.namedItem(
"spatialrefsys" );
1032 if ( ! srsNode.isNull() )
1034 bool initialized =
false;
1036 QDomNode myNode = srsNode.namedItem(
"authid" );
1037 if ( !myNode.isNull() )
1044 myNode = srsNode.namedItem(
"epsg" );
1045 if ( !myNode.isNull() )
1046 initialized =
createFromOgcWmsCrs( QString(
"EPSG:%1" ).arg( myNode.toElement().text().toLong() ) );
1055 myNode = srsNode.namedItem(
"proj4" );
1064 QgsDebugMsg(
"Setting from elements one by one" );
1066 myNode = srsNode.namedItem(
"proj4" );
1069 myNode = srsNode.namedItem(
"srsid" );
1072 myNode = srsNode.namedItem(
"srid" );
1073 setSrid( myNode.toElement().text().toLong() );
1075 myNode = srsNode.namedItem(
"authid" );
1078 myNode = srsNode.namedItem(
"description" );
1081 myNode = srsNode.namedItem(
"projectionacronym" );
1084 myNode = srsNode.namedItem(
"ellipsoidacronym" );
1087 myNode = srsNode.namedItem(
"geographicflag" );
1088 if ( myNode.toElement().text().compare(
"true" ) )
1116 QDomElement myLayerNode = theNode.toElement();
1117 QDomElement mySrsElement = theDoc.createElement(
"spatialrefsys" );
1119 QDomElement myProj4Element = theDoc.createElement(
"proj4" );
1120 myProj4Element.appendChild( theDoc.createTextNode(
toProj4() ) );
1121 mySrsElement.appendChild( myProj4Element );
1123 QDomElement mySrsIdElement = theDoc.createElement(
"srsid" );
1124 mySrsIdElement.appendChild( theDoc.createTextNode( QString::number(
srsid() ) ) );
1125 mySrsElement.appendChild( mySrsIdElement );
1127 QDomElement mySridElement = theDoc.createElement(
"srid" );
1128 mySridElement.appendChild( theDoc.createTextNode( QString::number(
postgisSrid() ) ) );
1129 mySrsElement.appendChild( mySridElement );
1131 QDomElement myEpsgElement = theDoc.createElement(
"authid" );
1132 myEpsgElement.appendChild( theDoc.createTextNode(
authid() ) );
1133 mySrsElement.appendChild( myEpsgElement );
1135 QDomElement myDescriptionElement = theDoc.createElement(
"description" );
1136 myDescriptionElement.appendChild( theDoc.createTextNode(
description() ) );
1137 mySrsElement.appendChild( myDescriptionElement );
1139 QDomElement myProjectionAcronymElement = theDoc.createElement(
"projectionacronym" );
1140 myProjectionAcronymElement.appendChild( theDoc.createTextNode(
projectionAcronym() ) );
1141 mySrsElement.appendChild( myProjectionAcronymElement );
1143 QDomElement myEllipsoidAcronymElement = theDoc.createElement(
"ellipsoidacronym" );
1144 myEllipsoidAcronymElement.appendChild( theDoc.createTextNode(
ellipsoidAcronym() ) );
1145 mySrsElement.appendChild( myEllipsoidAcronymElement );
1147 QDomElement myGeographicFlagElement = theDoc.createElement(
"geographicflag" );
1148 QString myGeoFlagText =
"false";
1151 myGeoFlagText =
"true";
1154 myGeographicFlagElement.appendChild( theDoc.createTextNode( myGeoFlagText ) );
1155 mySrsElement.appendChild( myGeographicFlagElement );
1157 myLayerNode.appendChild( mySrsElement );
1174 QString myDatabaseFileName;
1175 QString myProjString;
1176 QString mySql =
"select parameters from tbl_srs where srs_id = ";
1177 mySql += QString::number( theSrsId );
1179 QgsDebugMsg(
"mySrsId = " + QString::number( theSrsId ) );
1190 QFileInfo myFileInfo;
1191 myFileInfo.setFile( myDatabaseFileName );
1192 if ( !myFileInfo.exists( ) )
1206 rc =
openDb( myDatabaseFileName, &db );
1213 sqlite3_stmt *ppStmt;
1215 rc = sqlite3_prepare( db, mySql.toUtf8(), mySql.toUtf8().length(), &ppStmt, &pzTail );
1218 if ( rc == SQLITE_OK )
1220 if ( sqlite3_step( ppStmt ) == SQLITE_ROW )
1222 myProjString = QString::fromUtf8((
char* )sqlite3_column_text( ppStmt, 0 ) );
1226 sqlite3_finalize( ppStmt );
1228 sqlite3_close( db );
1231 return myProjString;
1237 int myResult = sqlite3_open( path.toUtf8().data(), db );
1239 if ( myResult != SQLITE_OK )
1241 QgsDebugMsg(
"Can't open database: " + QString( sqlite3_errmsg( *db ) ) );
1247 output->
setMessage( QObject::tr(
"Could not open CRS database %1<br>Error(%2): %3" )
1310 QString myName = QString(
" * %1 (%2)" )
1311 .arg( QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ) )
1320 mySql =
"insert into tbl_srs (srs_id,description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values ("
1330 mySql =
"insert into tbl_srs (description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values ("
1339 sqlite3_stmt *myPreparedStatement;
1343 if ( myResult != SQLITE_OK )
1345 QgsDebugMsg( QString(
"Can't open or create database %1: %2" )
1347 .arg( sqlite3_errmsg( myDatabase ) ) );
1350 QgsDebugMsg( QString(
"Update or insert sql \n%1" ).arg( mySql ) );
1351 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1352 sqlite3_step( myPreparedStatement );
1354 return myResult == SQLITE_OK;
1361 sqlite3_stmt *myPreparedStatement;
1363 long myRecordCount = 0;
1366 if ( myResult != SQLITE_OK )
1368 QgsDebugMsg( QString(
"Can't open database: %1" ).arg( sqlite3_errmsg( myDatabase ) ) );
1372 QString mySql =
"select count(*) from tbl_srs";
1373 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1375 if ( myResult == SQLITE_OK )
1377 if ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
1379 QString myRecordCountString = QString::fromUtf8((
char * )sqlite3_column_text( myPreparedStatement, 0 ) );
1380 myRecordCount = myRecordCountString.toLong();
1384 sqlite3_finalize( myPreparedStatement );
1385 sqlite3_close( myDatabase );
1386 return myRecordCount;
1391 value.replace(
"'",
"''" );
1392 return value.prepend(
"'" ).append(
"'" );