mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-05 00:04:40 -05:00
apply #3645: synchronization of srs.db with GDAL/PROJ on installation
This commit is contained in:
parent
86bcdc4bac
commit
a9aafd0713
1
debian/qgis-providers.install
vendored
1
debian/qgis-providers.install
vendored
@ -8,3 +8,4 @@ usr/lib/qgis/plugins/libmemoryprovider.so
|
||||
usr/lib/qgis/plugins/libspatialiteprovider.so
|
||||
usr/lib/qgis/plugins/libosmprovider.so
|
||||
usr/lib/qgis/plugins/libgdalprovider.so
|
||||
usr/lib/qgis/crssync
|
||||
|
||||
@ -8,3 +8,5 @@ set O4W_ROOT=%OSGEO4W_ROOT%
|
||||
set OSGEO4W_ROOT=%OSGEO4W_ROOT:\=\\%
|
||||
textreplace -std -t "%O4W_ROOT%\apps\@package@\bin\qgis.reg"
|
||||
"%WINDIR%\regedit" /s "%O4W_ROOT%\apps\@package@\bin\qgis.reg"
|
||||
|
||||
start "CRS synchronization" /wait %OSGEO4W_ROOT%\apps\@package@\crssync
|
||||
|
||||
@ -253,8 +253,10 @@ class QgsCoordinateReferenceSystem
|
||||
* @return QGis::UnitType that gives the units for the coordinate system
|
||||
*/
|
||||
QGis::UnitType mapUnits() const;
|
||||
|
||||
|
||||
/*! Update proj.4 parameters in our database from proj.4
|
||||
* @returns number of updated CRS on success and
|
||||
* negative number of failed updates in case of errors.
|
||||
* @note added in 1.8
|
||||
*/
|
||||
static int syncDb();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
SUBDIRS(astyle core analysis ui gui app providers plugins helpviewer)
|
||||
SUBDIRS(astyle core analysis ui gui app providers plugins helpviewer crssync)
|
||||
|
||||
IF (WITH_BINDINGS)
|
||||
SUBDIRS(python)
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#include "qgis.h" //const vals declared here
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include <proj_api.h>
|
||||
|
||||
//gdal and ogr includes (needed for == operator)
|
||||
#include <ogr_srs_api.h>
|
||||
@ -1353,3 +1354,139 @@ QString QgsCoordinateReferenceSystem::quotedValue( QString value )
|
||||
value.replace( "'", "''" );
|
||||
return value.prepend( "'" ).append( "'" );
|
||||
}
|
||||
|
||||
int QgsCoordinateReferenceSystem::syncDb()
|
||||
{
|
||||
int updated = 0, errors = 0;
|
||||
sqlite3 *database;
|
||||
if ( sqlite3_open( QgsApplication::srsDbFilePath().toUtf8().constData(), &database ) != SQLITE_OK )
|
||||
{
|
||||
qCritical( "Can't open database: %s [%s]\n", QgsApplication::srsDbFilePath().toLocal8Bit().constData(), sqlite3_errmsg( database ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *tail;
|
||||
sqlite3_stmt *select;
|
||||
QString sql = "select auth_name,auth_id,parameters from tbl_srs WHERE auth_name IS NOT NULL AND auth_id IS NOT NULL";
|
||||
if ( sqlite3_prepare( database, sql.toAscii(), sql.size(), &select, &tail ) != SQLITE_OK )
|
||||
{
|
||||
qCritical( "Could not prepare: %s [%s]\n", sql.toAscii().constData(), sqlite3_errmsg( database ) );
|
||||
sqlite3_close( database );
|
||||
return -1;
|
||||
}
|
||||
|
||||
OGRSpatialReferenceH crs = OSRNewSpatialReference( NULL );
|
||||
|
||||
while ( sqlite3_step( select ) == SQLITE_ROW )
|
||||
{
|
||||
const char *auth_name = ( const char * ) sqlite3_column_text( select, 0 );
|
||||
const char *auth_id = ( const char * ) sqlite3_column_text( select, 1 );
|
||||
const char *params = ( const char * ) sqlite3_column_text( select, 2 );
|
||||
|
||||
QString proj4;
|
||||
|
||||
if ( QString( auth_name ).compare( "epsg", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
OGRErr ogrErr = OSRSetFromUserInput( crs, QString( "epsg:%1" ).arg( auth_id ).toAscii() );
|
||||
|
||||
if ( ogrErr == OGRERR_NONE )
|
||||
{
|
||||
char *output = 0;
|
||||
|
||||
if ( OSRExportToProj4( crs, &output ) == OGRERR_NONE )
|
||||
{
|
||||
proj4 = output;
|
||||
proj4 = proj4.trimmed();
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( QString( "could not retrieve proj.4 string for epsg:%1 from OGR" ).arg( auth_id ) );
|
||||
}
|
||||
|
||||
if ( output )
|
||||
CPLFree( output );
|
||||
}
|
||||
}
|
||||
#if !defined(PJ_VERSION) || PJ_VERSION!=470
|
||||
// 4.7.0 has a bug that crashes after 16 consecutive pj_init_plus with different strings
|
||||
else
|
||||
{
|
||||
input = QString( "+init=%1:%2" ).arg( QString( auth_name ).toLower() ).arg( auth_id );
|
||||
projPJ pj = pj_init_plus( input.toAscii() );
|
||||
if ( !pj )
|
||||
{
|
||||
input = QString( "+init=%1:%2" ).arg( QString( auth_name ).toUpper() ).arg( auth_id );
|
||||
pj = pj_init_plus( input.toAscii() );
|
||||
}
|
||||
|
||||
if ( pj )
|
||||
{
|
||||
char *def = pj_get_def( pj, 0 );
|
||||
if ( def )
|
||||
{
|
||||
proj4 = def;
|
||||
pj_dalloc( def );
|
||||
|
||||
input.prepend( ' ' ).append( ' ' );
|
||||
if ( proj4.startsWith( input ) )
|
||||
{
|
||||
proj4 = proj4.mid( input.size() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( QString( "could not retrieve proj string for %1 from PROJ" ).arg( input ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsgLevel( QString( "could not retrieve crs for %1 from PROJ" ).arg( input ), 3 );
|
||||
}
|
||||
|
||||
pj_free( pj );
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( proj4.isEmpty() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( proj4 != params )
|
||||
{
|
||||
char *errMsg = NULL;
|
||||
|
||||
sql = QString( "UPDATE tbl_srs SET parameters=%1 WHERE auth_name=%2 AND auth_id=%3" )
|
||||
.arg( quotedValue( proj4 ) )
|
||||
.arg( quotedValue( auth_name ) )
|
||||
.arg( quotedValue( auth_id ) );
|
||||
|
||||
if ( sqlite3_exec( database, sql.toUtf8(), 0, 0, &errMsg ) != SQLITE_OK )
|
||||
{
|
||||
qCritical( "Could not execute: %s [%s/%s]\n",
|
||||
sql.toLocal8Bit().constData(),
|
||||
sqlite3_errmsg( database ),
|
||||
errMsg ? errMsg : "(unknown error)" );
|
||||
errors++;
|
||||
}
|
||||
else
|
||||
{
|
||||
updated++;
|
||||
QgsDebugMsgLevel( QString( "SQL: %1\n OLD:%2\n NEW:%3" ).arg( sql ).arg( params ).arg( proj4 ), 3 );
|
||||
}
|
||||
|
||||
if ( errMsg )
|
||||
sqlite3_free( errMsg );
|
||||
}
|
||||
}
|
||||
|
||||
OSRDestroySpatialReference( crs );
|
||||
|
||||
sqlite3_finalize( select );
|
||||
sqlite3_close( database );
|
||||
|
||||
if ( errors > 0 )
|
||||
return -errors;
|
||||
else
|
||||
return updated;
|
||||
}
|
||||
|
||||
@ -322,6 +322,13 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
|
||||
/*! Get user hint for validation
|
||||
*/
|
||||
QString validationHint();
|
||||
/*! Update proj.4 parameters in our database from proj.4
|
||||
* @returns number of updated CRS on success and
|
||||
* negative number of failed updates in case of errors.
|
||||
* @note added in 1.8
|
||||
*/
|
||||
static int syncDb();
|
||||
|
||||
// Mutators -----------------------------------
|
||||
// We don't want to expose these to the public api since they wont create
|
||||
// a fully valid crs. Programmers should use the createFrom* methods rather
|
||||
@ -418,7 +425,7 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
|
||||
long getRecordCount();
|
||||
|
||||
//! Helper for sql-safe value quoting
|
||||
QString quotedValue( QString value );
|
||||
static QString quotedValue( QString value );
|
||||
|
||||
void *mCRS;
|
||||
|
||||
|
||||
15
src/crssync/CMakeLists.txt
Normal file
15
src/crssync/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
||||
ADD_EXECUTABLE(crssync main.cpp)
|
||||
INCLUDE_DIRECTORIES(
|
||||
../core
|
||||
${GDAL_INCLUDE_DIR}
|
||||
${PROJ_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(crssync
|
||||
qgis_core
|
||||
${PROJ_LIBRARY}
|
||||
${GDAL_LIBRARY}
|
||||
)
|
||||
|
||||
INSTALL(CODE "MESSAGE(\"Installing crssync ...\")")
|
||||
INSTALL(TARGETS crssync RUNTIME DESTINATION ${QGIS_LIBEXEC_DIR})
|
||||
77
src/crssync/main.cpp
Normal file
77
src/crssync/main.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
/***************************************************************************
|
||||
crssync.cpp
|
||||
sync srs.db with proj
|
||||
-------------------
|
||||
begin : 2011
|
||||
copyright : (C) 2011 by Juergen E. Fischer, norBIT GmbH
|
||||
email : jef at norbit dot de
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include "qgsapplication.h"
|
||||
#include "qgscoordinatereferencesystem.h"
|
||||
#include "qgsconfig.h"
|
||||
|
||||
#include <QRegExp>
|
||||
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
#include <cpl_error.h>
|
||||
|
||||
void CPL_STDCALL showError( CPLErr errClass, int errNo, const char *msg )
|
||||
{
|
||||
QRegExp re( "EPSG PCS/GCS code \\d+ not found in EPSG support files. Is this a valid\nEPSG coordinate system?" );
|
||||
if ( errNo != 6 && !re.exactMatch( msg ) )
|
||||
{
|
||||
std::cerr << msg;
|
||||
}
|
||||
}
|
||||
|
||||
int main( int argc, char ** argv )
|
||||
{
|
||||
QgsApplication a( argc, argv, false );
|
||||
|
||||
#if defined(Q_WS_MACX)
|
||||
// If we're on Mac, we have the resource library way above us...
|
||||
a.setPkgDataPath( QgsApplication::prefixPath() + "/../../../../" + QString( QGIS_DATA_SUBDIR ) );
|
||||
#elif defined(Q_WS_WIN)
|
||||
a.setPkgDataPath( QgsApplication::prefixPath() + "/" QGIS_DATA_SUBDIR );
|
||||
#else
|
||||
a.setPkgDataPath( QgsApplication::prefixPath() + "/../" QGIS_DATA_SUBDIR );
|
||||
#endif
|
||||
|
||||
std::cout << "Synchronizing CRS database with PROJ definitions." << std::endl;
|
||||
|
||||
CPLPushErrorHandler( showError );
|
||||
|
||||
int res = QgsCoordinateReferenceSystem::syncDb();
|
||||
|
||||
CPLPopErrorHandler();
|
||||
|
||||
if ( res == 0 )
|
||||
{
|
||||
std::cout << "No CRS updates were necessary." << std::endl;
|
||||
}
|
||||
else if ( res > 0 )
|
||||
{
|
||||
std::cout << res << " CRSs updated." << std::endl;
|
||||
}
|
||||
else if ( res == std::numeric_limits<int>::min() )
|
||||
{
|
||||
std::cout << "CRSs synchronization not possible." << std::endl;
|
||||
}
|
||||
else if ( res < 0 )
|
||||
{
|
||||
std::cout << -res << " CRSs could not be updated." << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user