crs-syncdb.diff
python/core/qgscoordinatereferencesystem.sip (working copy) | ||
---|---|---|
253 | 253 |
* @return QGis::UnitType that gives the units for the coordinate system |
254 | 254 |
*/ |
255 | 255 |
QGis::UnitType mapUnits() const; |
256 | ||
257 | ||
256 |
/*! Update proj.4 parameters in our database from proj.4 |
|
257 |
* @returns number of updated CRS on success and |
|
258 |
* negative number of failed updates in case of errors. |
|
259 |
* @note added in 1.7 |
|
260 |
*/ |
|
261 |
static int syncDb(); |
|
258 | 262 |
}; |
259 | ||
260 |
debian/qgis-providers.install (working copy) | ||
---|---|---|
8 | 8 |
usr/lib/qgis/plugins/libspatialiteprovider.so |
9 | 9 |
usr/lib/qgis/plugins/libosmprovider.so |
10 | 10 |
usr/lib/qgis/plugins/libgdalprovider.so |
11 |
usr/lib/qgis/crssync |
debian/qgis-providers.postinst (revision 0) | ||
---|---|---|
1 |
#!/bin/sh |
|
2 | ||
3 |
set -e |
|
4 | ||
5 |
case "$1" in |
|
6 |
configure) |
|
7 |
/usr/lib/qgis/crssync |
|
8 |
;; |
|
9 |
esac |
src/crssync/main.cpp (revision 0) | ||
---|---|---|
1 |
/*************************************************************************** |
|
2 |
crssync.cpp |
|
3 |
sync srs.db with proj |
|
4 |
------------------- |
|
5 |
begin : 2011 |
|
6 |
copyright : (C) 2011 by Juergen E. Fischer, norBIT GmbH |
|
7 |
email : jef at norbit dot de |
|
8 |
***************************************************************************/ |
|
9 | ||
10 |
/*************************************************************************** |
|
11 |
* * |
|
12 |
* This program is free software; you can redistribute it and/or modify * |
|
13 |
* it under the terms of the GNU General Public License as published by * |
|
14 |
* the Free Software Foundation; either version 2 of the License, or * |
|
15 |
* (at your option) any later version. * |
|
16 |
* * |
|
17 |
***************************************************************************/ |
|
18 |
#include "qgsapplication.h" |
|
19 |
#include "qgscoordinatereferencesystem.h" |
|
20 |
#include "qgsconfig.h" |
|
21 | ||
22 |
#include <QRegExp> |
|
23 | ||
24 |
#include <iostream> |
|
25 |
#include <limits> |
|
26 | ||
27 |
#include <cpl_error.h> |
|
28 | ||
29 |
void CPL_STDCALL showError( CPLErr errClass, int errNo, const char *msg ) |
|
30 |
{ |
|
31 |
QRegExp re( "EPSG PCS/GCS code \\d+ not found in EPSG support files. Is this a valid\nEPSG coordinate system?" ); |
|
32 |
if ( errNo != 6 && !re.exactMatch( msg ) ) |
|
33 |
{ |
|
34 |
std::cerr << msg; |
|
35 |
} |
|
36 |
} |
|
37 | ||
38 |
int main( int argc, char ** argv ) |
|
39 |
{ |
|
40 |
QgsApplication a( argc, argv, false ); |
|
41 | ||
42 |
#if defined(Q_WS_MACX) |
|
43 |
// If we're on Mac, we have the resource library way above us... |
|
44 |
a.setPkgDataPath( QgsApplication::prefixPath() + "/../../../../" + QString( QGIS_DATA_SUBDIR ) ); |
|
45 |
#elif defined(Q_WS_WIN) |
|
46 |
a.setPkgDataPath( QgsApplication::prefixPath() + "/" QGIS_DATA_SUBDIR ); |
|
47 |
#else |
|
48 |
a.setPkgDataPath( QgsApplication::prefixPath() + "/../" QGIS_DATA_SUBDIR ); |
|
49 |
#endif |
|
50 | ||
51 |
std::cout << "Synchronizing CRS database with PROJ definitions." << std::endl; |
|
52 | ||
53 |
CPLPushErrorHandler( showError ); |
|
54 | ||
55 |
int res = QgsCoordinateReferenceSystem::syncDb(); |
|
56 | ||
57 |
CPLPopErrorHandler(); |
|
58 | ||
59 |
if ( res == 0 ) |
|
60 |
{ |
|
61 |
std::cout << "No CRS updates were necessary." << std::endl; |
|
62 |
} |
|
63 |
else if ( res > 0 ) |
|
64 |
{ |
|
65 |
std::cout << res << " CRSs updated." << std::endl; |
|
66 |
} |
|
67 |
else if ( res == std::numeric_limits<int>::min() ) |
|
68 |
{ |
|
69 |
std::cout << "CRSs synchronization not possible." << std::endl; |
|
70 |
} |
|
71 |
else if ( res < 0 ) |
|
72 |
{ |
|
73 |
std::cout << -res << " CRSs could not be updated." << std::endl; |
|
74 |
} |
|
75 | ||
76 |
return 0; |
|
77 |
} |
src/core/qgscoordinatereferencesystem.cpp (working copy) | ||
---|---|---|
32 | 32 |
#include "qgis.h" //const vals declared here |
33 | 33 | |
34 | 34 |
#include <sqlite3.h> |
35 |
#include <proj_api.h> |
|
35 | 36 | |
36 | 37 |
//gdal and ogr includes (needed for == operator) |
37 | 38 |
#include <ogr_srs_api.h> |
... | ... | |
1353 | 1354 |
value.replace( "'", "''" ); |
1354 | 1355 |
return value.prepend( "'" ).append( "'" ); |
1355 | 1356 |
} |
1357 | ||
1358 |
int QgsCoordinateReferenceSystem::syncDb() |
|
1359 |
{ |
|
1360 |
int updated = 0, errors = 0; |
|
1361 |
sqlite3 *database; |
|
1362 |
if ( sqlite3_open( QgsApplication::srsDbFilePath().toUtf8().constData(), &database ) != SQLITE_OK ) |
|
1363 |
{ |
|
1364 |
qCritical( "Can't open database: %s [%s]\n", QgsApplication::srsDbFilePath().toLocal8Bit().constData(), sqlite3_errmsg( database ) ); |
|
1365 |
return -1; |
|
1366 |
} |
|
1367 | ||
1368 |
const char *tail; |
|
1369 |
sqlite3_stmt *select; |
|
1370 |
QString sql = "select auth_name,auth_id,parameters from tbl_srs WHERE auth_name IS NOT NULL AND auth_id IS NOT NULL"; |
|
1371 |
if ( sqlite3_prepare( database, sql.toAscii(), sql.size(), &select, &tail ) != SQLITE_OK ) |
|
1372 |
{ |
|
1373 |
qCritical( "Could not prepare: %s [%s]\n", sql.toAscii().constData(), sqlite3_errmsg( database ) ); |
|
1374 |
sqlite3_close( database ); |
|
1375 |
return -1; |
|
1376 |
} |
|
1377 | ||
1378 |
OGRSpatialReferenceH crs = OSRNewSpatialReference( NULL ); |
|
1379 | ||
1380 |
while ( sqlite3_step( select ) == SQLITE_ROW ) |
|
1381 |
{ |
|
1382 |
const char *auth_name = ( const char * ) sqlite3_column_text( select, 0 ); |
|
1383 |
const char *auth_id = ( const char * ) sqlite3_column_text( select, 1 ); |
|
1384 |
const char *params = ( const char * ) sqlite3_column_text( select, 2 ); |
|
1385 | ||
1386 |
QString proj4; |
|
1387 | ||
1388 |
QString input = QString( "%1:%2" ).arg( QString( auth_name ).toLower() ).arg( auth_id ); |
|
1389 |
QgsDebugMsgLevel( QString( "fetching crs %1" ).arg( input ), 3 ); |
|
1390 | ||
1391 |
#if !defined(PJ_VERSION) || PJ_VERSION!=470 |
|
1392 |
// 4.7.0 has a bug that crashes after 16 consecutive pj_init_plus with different strings |
|
1393 |
if ( proj4.isEmpty() ) |
|
1394 |
{ |
|
1395 |
input = QString( "+init=%1:%2" ).arg( QString( auth_name ).toLower() ).arg( auth_id ); |
|
1396 |
projPJ pj = pj_init_plus( input.toAscii() ); |
|
1397 |
if ( !pj ) |
|
1398 |
{ |
|
1399 |
input = QString( "+init=%1:%2" ).arg( QString( auth_name ).toUpper() ).arg( auth_id ); |
|
1400 |
pj = pj_init_plus( input.toAscii() ); |
|
1401 |
} |
|
1402 | ||
1403 |
if ( pj ) |
|
1404 |
{ |
|
1405 |
char *def = pj_get_def( pj, 0 ); |
|
1406 |
if ( def ) |
|
1407 |
{ |
|
1408 |
proj4 = def; |
|
1409 |
pj_dalloc( def ); |
|
1410 | ||
1411 |
input.prepend( ' ' ).append( ' ' ); |
|
1412 |
if ( proj4.startsWith( input ) ) |
|
1413 |
{ |
|
1414 |
proj4 = proj4.mid( input.size() ); |
|
1415 |
} |
|
1416 |
} |
|
1417 |
else |
|
1418 |
{ |
|
1419 |
QgsDebugMsg( QString( "could not retrieve proj string for %1 from PROJ" ).arg( input ) ); |
|
1420 |
} |
|
1421 |
} |
|
1422 |
else |
|
1423 |
{ |
|
1424 |
QgsDebugMsgLevel( QString( "could not retrieve crs for %1 from PROJ" ).arg( input ), 3 ); |
|
1425 |
} |
|
1426 | ||
1427 |
pj_free( pj ); |
|
1428 |
} |
|
1429 |
#else |
|
1430 |
// otherwise check OGR |
|
1431 |
if ( !proj4.isEmpty() ) |
|
1432 |
{ |
|
1433 |
OGRErr ogrErr = OSRSetFromUserInput( crs, input.toAscii() ); |
|
1434 |
if ( ogrErr != OGRERR_NONE ) |
|
1435 |
{ |
|
1436 |
input = QString( "%1:%2" ).arg( QString( auth_name ).toUpper() ).arg( auth_id ); |
|
1437 |
ogrErr = OSRSetFromUserInput( crs, input.toAscii() ); |
|
1438 |
} |
|
1439 | ||
1440 |
if ( ogrErr == OGRERR_NONE ) |
|
1441 |
{ |
|
1442 |
char *output = 0; |
|
1443 | ||
1444 |
if ( OSRExportToProj4( crs, &output ) == OGRERR_NONE ) |
|
1445 |
{ |
|
1446 |
QString proj4ogr = output; |
|
1447 | ||
1448 |
#if 0 |
|
1449 |
QString proj4proj = proj4; |
|
1450 | ||
1451 |
proj4proj.replace( QRegExp( "\\.0+([, ])" ), "\\1" ); |
|
1452 |
proj4proj.replace( QRegExp( "(\\.\\d*[1-9])0+([, ])" ), "\\1\\2" ); |
|
1453 |
proj4proj.replace( ".0000000001 ", " " ); |
|
1454 |
proj4proj.replace( ".10000000000001 ", ".1 " ); |
|
1455 |
proj4proj.replace( ".50000000000001 ", ".5 " ); |
|
1456 |
proj4proj.replace( ".399999999999999 ", ".4 " ); |
|
1457 |
proj4proj.replace( ".16500000000001 ", ".165 " ); |
|
1458 |
proj4proj.replace( " +towgs84=0,0,0,0,0,0,0 ", " +datum=WGS84 " ); |
|
1459 | ||
1460 |
if ( proj4proj.contains( " +datum=WGS84 " ) && proj4proj.endsWith( " +towgs84=0,0,0" ) ) |
|
1461 |
{ |
|
1462 |
proj4proj.replace( " +towgs84=0,0,0", "" ); |
|
1463 |
} |
|
1464 | ||
1465 |
proj4ogr.replace( " +towgs84=0,0,0,0,0,0,0 ", " +datum=WGS84 " ); |
|
1466 |
proj4ogr.replace( " +a=6378249.145 +b=6356514.96582849 ", " +ellps=clrk80 " ); |
|
1467 |
proj4ogr.replace( " +gamma=0 ", " " ); |
|
1468 |
proj4ogr.replace( " +alpha=0 ", " " ); |
|
1469 | ||
1470 |
if ( proj4ogr != proj4proj ) |
|
1471 |
{ |
|
1472 |
qWarning( "%s", QString( "Mismatch for %1:%2 in OGR and PROJ found:\n PROJ:'%3'\n OGR :'%4'" ).arg( auth_name ).arg( auth_id ).arg( proj4proj ).arg( proj4ogr ).toAscii().constData() ); |
|
1473 |
} |
|
1474 |
#endif |
|
1475 | ||
1476 |
proj4 = proj4ogr.trimmed(); |
|
1477 |
} |
|
1478 |
else |
|
1479 |
{ |
|
1480 |
QgsDebugMsg( QString( "could not retrieve proj.4 string for %1 from OGR" ).arg( input ) ); |
|
1481 |
} |
|
1482 | ||
1483 |
if ( output ) |
|
1484 |
CPLFree( output ); |
|
1485 |
} |
|
1486 |
} |
|
1487 |
#endif |
|
1488 | ||
1489 |
if ( proj4.isEmpty() ) |
|
1490 |
{ |
|
1491 |
continue; |
|
1492 |
} |
|
1493 | ||
1494 |
if ( proj4 != params ) |
|
1495 |
{ |
|
1496 |
char *errMsg = NULL; |
|
1497 | ||
1498 |
sql = QString( "UPDATE tbl_srs SET parameters=%1 WHERE auth_name=%2 AND auth_id=%3" ) |
|
1499 |
.arg( quotedValue( proj4 ) ) |
|
1500 |
.arg( quotedValue( auth_name ) ) |
|
1501 |
.arg( quotedValue( auth_id ) ); |
|
1502 | ||
1503 |
if ( sqlite3_exec( database, sql.toUtf8(), 0, 0, &errMsg ) != SQLITE_OK ) |
|
1504 |
{ |
|
1505 |
qCritical( "Could not execute: %s [%s/%s]\n", |
|
1506 |
sql.toLocal8Bit().constData(), |
|
1507 |
sqlite3_errmsg( database ), |
|
1508 |
errMsg ? errMsg : "(unknown error)" ); |
|
1509 |
errors++; |
|
1510 |
} |
|
1511 |
else |
|
1512 |
{ |
|
1513 |
updated++; |
|
1514 |
QgsDebugMsgLevel( "Updated: " + sql, 3 ); |
|
1515 |
} |
|
1516 | ||
1517 |
if ( errMsg ) |
|
1518 |
sqlite3_free( errMsg ); |
|
1519 |
} |
|
1520 |
} |
|
1521 | ||
1522 |
OSRDestroySpatialReference( crs ); |
|
1523 | ||
1524 |
sqlite3_finalize( select ); |
|
1525 |
sqlite3_close( database ); |
|
1526 | ||
1527 |
if ( errors > 0 ) |
|
1528 |
return -errors; |
|
1529 |
else |
|
1530 |
return updated; |
|
1531 |
} |
src/crssync/CMakeLists.txt (revision 0) | ||
---|---|---|
1 |
ADD_EXECUTABLE(crssync main.cpp) |
|
2 |
INCLUDE_DIRECTORIES( |
|
3 |
../core |
|
4 |
${GDAL_INCLUDE_DIR} |
|
5 |
${PROJ_INCLUDE_DIR} |
|
6 |
) |
|
7 | ||
8 |
TARGET_LINK_LIBRARIES(crssync |
|
9 |
qgis_core |
|
10 |
${PROJ_LIBRARY} |
|
11 |
${GDAL_LIBRARY} |
|
12 |
) |
|
13 | ||
14 |
INSTALL(CODE "MESSAGE(\"Installing crssync ...\")") |
|
15 |
INSTALL(TARGETS crssync RUNTIME DESTINATION ${QGIS_LIBEXEC_DIR}) |
src/core/qgscoordinatereferencesystem.h (working copy) | ||
---|---|---|
322 | 322 |
/*! Get user hint for validation |
323 | 323 |
*/ |
324 | 324 |
QString validationHint(); |
325 |
/*! Update proj.4 parameters in our database from proj.4 |
|
326 |
* @returns number of updated CRS on success and |
|
327 |
* negative number of failed updates in case of errors. |
|
328 |
* @note added in 1.7 |
|
329 |
*/ |
|
330 |
static int syncDb(); |
|
331 | ||
325 | 332 |
// Mutators ----------------------------------- |
326 | 333 |
// We don't want to expose these to the public api since they wont create |
327 | 334 |
// a fully valid crs. Programmers should use the createFrom* methods rather |
... | ... | |
418 | 425 |
long getRecordCount(); |
419 | 426 | |
420 | 427 |
//! Helper for sql-safe value quoting |
421 |
QString quotedValue( QString value ); |
|
428 |
static QString quotedValue( QString value );
|
|
422 | 429 | |
423 | 430 |
void *mCRS; |
424 | 431 |
src/CMakeLists.txt (working copy) | ||
---|---|---|
1 |
SUBDIRS(astyle core analysis ui gui app providers plugins helpviewer) |
|
1 |
SUBDIRS(astyle core analysis ui gui app providers plugins helpviewer crssync)
|
|
2 | 2 | |
3 | 3 |
IF (WITH_BINDINGS) |
4 | 4 |
SUBDIRS(python) |
ms-windows/osgeo4w/postinstall.bat (working copy) | ||
---|---|---|
8 | 8 |
set OSGEO4W_ROOT=%OSGEO4W_ROOT:\=\\% |
9 | 9 |
textreplace -std -t "%O4W_ROOT%\apps\@package@\bin\qgis.reg" |
10 | 10 |
"%WINDIR%\regedit" /s "%O4W_ROOT%\apps\@package@\bin\qgis.reg" |
11 |
|
|
12 |
start "CRS synchronization" /wait %OSGEO4W_ROOT%\apps\@package@\crssync |