Skip to content

Commit 3a14b53

Browse files
committedNov 8, 2013
[FEATURE] selection of datum transformation for otf-reprojection
2 parents b21adc1 + 6aa4d95 commit 3a14b53

26 files changed

+876
-73
lines changed
 

‎python/core/qgsmaprenderer.sip

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ class QgsMapRenderer : QObject
245245
//! Added in QGIS v1.4
246246
void setLabelingEngine( QgsLabelingEngineInterface* iface /Transfer/ );
247247

248+
const QgsCoordinateTransform* transformation( const QgsMapLayer *layer ) const;
249+
248250
signals:
249251

250252
void drawingProgress( int current, int total );

‎python/core/qgsvectorfilewriter.sip

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,29 @@ class QgsVectorFileWriter
2828
ErrInvalidLayer, // added in 2.0
2929
};
3030

31+
//added in 2.0
32+
enum SymbologyExport
33+
{
34+
NoSymbology = 0, //export only data
35+
FeatureSymbology, //Keeps the number of features and export symbology per feature
36+
SymbolLayerSymbology //Exports one feature per symbol layer (considering symbol levels)
37+
};
38+
39+
static WriterError writeAsVectorFormat( QgsVectorLayer* layer,
40+
const QString& fileName,
41+
const QString& fileEncoding,
42+
const QgsCoordinateTransform* ct,
43+
const QString& driverName = "ESRI Shapefile",
44+
bool onlySelected = false,
45+
QString *errorMessage = 0,
46+
const QStringList &datasourceOptions = QStringList(), // added in 1.6
47+
const QStringList &layerOptions = QStringList(), // added in 1.6
48+
bool skipAttributeCreation = false, // added in 1.6
49+
QString *newFilename = 0, // added in 1.9
50+
SymbologyExport symbologyExport = NoSymbology, //added in 2.0
51+
double symbologyScale = 1.0 // added in 2.0
52+
);
53+
3154
/** Write contents of vector layer to an (OGR supported) vector formt
3255
@note: this method was added in version 1.5*/
3356
static WriterError writeAsVectorFormat( QgsVectorLayer* layer,
@@ -40,7 +63,9 @@ class QgsVectorFileWriter
4063
const QStringList &datasourceOptions = QStringList(), // added in 1.6
4164
const QStringList &layerOptions = QStringList(), // added in 1.6
4265
bool skipAttributeCreation = false, // added in 1.6
43-
QString *newFilename = 0 // added in 1.9
66+
QString *newFilename = 0, // added in 1.9
67+
SymbologyExport symbologyExport = NoSymbology, //added in 2.0
68+
double symbologyScale = 1.0 // added in 2.0
4469
);
4570

4671
/** create shapefile and initialize it */

‎resources/srs.db

37 KB
Binary file not shown.

‎src/app/qgisapp.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
#include "qgscustomization.h"
119119
#include "qgscustomprojectiondialog.h"
120120
#include "qgsdatasourceuri.h"
121+
#include "qgsdatumtransformdialog.h"
121122
#include "qgsdecorationcopyright.h"
122123
#include "qgsdecorationnortharrow.h"
123124
#include "qgsdecorationscalebar.h"
@@ -4611,10 +4612,13 @@ void QgisApp::saveAsVectorFileGeneral( bool saveOnlySelection, QgsVectorLayer* v
46114612
QString format = dialog->format();
46124613
QStringList datasourceOptions = dialog->datasourceOptions();
46134614

4615+
QgsCoordinateTransform* ct = 0;
4616+
46144617
switch ( dialog->crs() )
46154618
{
46164619
case -2: // Project CRS
46174620
destCRS = mMapCanvas->mapRenderer()->destinationCrs();
4621+
46184622
break;
46194623
case -1: // Layer CRS
46204624
destCRS = vlayer->crs();
@@ -4625,14 +4629,39 @@ void QgisApp::saveAsVectorFileGeneral( bool saveOnlySelection, QgsVectorLayer* v
46254629
break;
46264630
}
46274631

4632+
if ( destCRS.isValid() && destCRS != vlayer->crs() )
4633+
{
4634+
ct = new QgsCoordinateTransform( vlayer->crs(), destCRS );
4635+
4636+
//ask user about datum transformation
4637+
QList< QList< int > > dt = QgsCoordinateTransform::datumTransformations( vlayer->crs(), destCRS );
4638+
if ( dt.size() > 1 )
4639+
{
4640+
QgsDatumTransformDialog d( vlayer->name(), dt );
4641+
if ( d.exec() == QDialog::Accepted )
4642+
{
4643+
QList< int > sdt = d.selectedDatumTransform();
4644+
if ( sdt.size() > 0 )
4645+
{
4646+
ct->setSourceDatumTransform( sdt.at( 0 ) );
4647+
}
4648+
if ( sdt.size() > 1 )
4649+
{
4650+
ct->setDestinationDatumTransform( sdt.at( 1 ) );
4651+
}
4652+
ct->initialise();
4653+
}
4654+
}
4655+
}
4656+
46284657
// ok if the file existed it should be deleted now so we can continue...
46294658
QApplication::setOverrideCursor( Qt::WaitCursor );
46304659

46314660
QgsVectorFileWriter::WriterError error;
46324661
QString errorMessage;
46334662
QString newFilename;
46344663
error = QgsVectorFileWriter::writeAsVectorFormat(
4635-
vlayer, vectorFilename, encoding, &destCRS, format,
4664+
vlayer, vectorFilename, encoding, ct, format,
46364665
saveOnlySelection,
46374666
&errorMessage,
46384667
datasourceOptions, dialog->layerOptions(),
@@ -4641,6 +4670,8 @@ void QgisApp::saveAsVectorFileGeneral( bool saveOnlySelection, QgsVectorLayer* v
46414670
( QgsVectorFileWriter::SymbologyExport )( dialog->symbologyExport() ),
46424671
dialog->scaleDenominator() );
46434672

4673+
delete ct;
4674+
46444675
QApplication::restoreOverrideCursor();
46454676

46464677
if ( error == QgsVectorFileWriter::NoError )

‎src/core/qgscoordinatereferencesystem.cpp

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1677,10 +1677,13 @@ bool QgsCoordinateReferenceSystem::loadIDs( QHash<int, QString> &wkts )
16771677

16781678
int QgsCoordinateReferenceSystem::syncDb()
16791679
{
1680+
QString dbFilePath = QgsApplication::srsDbFilePath();
1681+
syncDatumTransform( dbFilePath );
1682+
16801683
int inserted = 0, updated = 0, deleted = 0, errors = 0;
16811684

16821685
sqlite3 *database;
1683-
if ( sqlite3_open( QgsApplication::srsDbFilePath().toUtf8().constData(), &database ) != SQLITE_OK )
1686+
if ( sqlite3_open( dbFilePath.toUtf8().constData(), &database ) != SQLITE_OK )
16841687
{
16851688
qCritical( "Could not open database: %s [%s]\n", QgsApplication::srsDbFilePath().toLocal8Bit().constData(), sqlite3_errmsg( database ) );
16861689
return -1;
@@ -1933,3 +1936,125 @@ int QgsCoordinateReferenceSystem::syncDb()
19331936
else
19341937
return updated + inserted;
19351938
}
1939+
1940+
bool QgsCoordinateReferenceSystem::syncDatumTransform( const QString& dbPath )
1941+
{
1942+
QString filename = CPLFindFile( "gdal", "datum_shift.csv" );
1943+
1944+
QFile f( filename );
1945+
if ( !f.open( QIODevice::ReadOnly ) )
1946+
{
1947+
return false;
1948+
}
1949+
1950+
sqlite3* db;
1951+
int openResult = sqlite3_open( dbPath.toUtf8().constData(), &db );
1952+
if ( openResult != SQLITE_OK )
1953+
{
1954+
return false;
1955+
}
1956+
1957+
if ( sqlite3_exec( db, "BEGIN TRANSACTION", 0, 0, 0 ) != SQLITE_OK )
1958+
{
1959+
qCritical( "Could not begin transaction: %s [%s]\n", QgsApplication::srsDbFilePath().toLocal8Bit().constData(), sqlite3_errmsg( db ) );
1960+
return false;
1961+
}
1962+
1963+
1964+
QTextStream textStream( &f );
1965+
textStream.readLine();
1966+
1967+
QString line, coord_op, source_crs, target_crs, coord_op_method,
1968+
p1, p2, p3, p4, p5, p6, p7;
1969+
1970+
while ( !textStream.atEnd() )
1971+
{
1972+
line = textStream.readLine();
1973+
QStringList csList = line.split( "," );
1974+
int csSize = csList.size();
1975+
if ( csSize < 22 )
1976+
{
1977+
continue;
1978+
}
1979+
1980+
coord_op = csList[1];
1981+
source_crs = csList[2];
1982+
target_crs = csList[3];
1983+
coord_op_method = csList[csSize - 9];
1984+
p1 = csList[csSize - 8];
1985+
p1 = p1.isEmpty() ? "NULL" : p1;
1986+
p2 = csList[csSize - 7];
1987+
p2 = p2.isEmpty() ? "NULL" : p2;
1988+
p3 = csList[csSize - 6];
1989+
p3 = p3.isEmpty() ? "NULL" : p3;
1990+
p4 = csList[csSize - 5];
1991+
p4 = p4.isEmpty() ? "NULL" : p4;
1992+
p5 = csList[csSize - 4];
1993+
p5 = p5.isEmpty() ? "NULL" : p5;
1994+
p6 = csList[csSize - 3];
1995+
p6 = p6.isEmpty() ? "NULL" : p6;
1996+
p7 = csList[csSize - 2];
1997+
p7 = p7.isEmpty() ? "NULL" : p7;
1998+
1999+
//entry already in db?
2000+
sqlite3_stmt* stmt;
2001+
QString cOpCode;
2002+
QString sql = QString( "SELECT coord_op_code FROM tbl_datum_transform WHERE coord_op_code=%1" ).arg( coord_op );
2003+
int prepareRes = sqlite3_prepare( db, sql.toAscii(), sql.size(), &stmt, NULL );
2004+
if ( prepareRes != SQLITE_OK )
2005+
{
2006+
continue;
2007+
}
2008+
2009+
if ( sqlite3_step( stmt ) == SQLITE_ROW )
2010+
{
2011+
cOpCode = ( const char * ) sqlite3_column_text( stmt, 0 );
2012+
}
2013+
sqlite3_finalize( stmt );
2014+
2015+
if ( !cOpCode.isEmpty() )
2016+
{
2017+
//already in database, do update
2018+
QgsDebugMsg( "Trying datum transform update" );
2019+
sql = QString( "UPDATE tbl_datum_transform SET source_crs = %2, target_crs = %3, coord_op_method = %4, p1 = %5, p2 = %6, p3 = %7, p4 = %8, p5 = %9, p6 = %10, p7 = %11 WHERE coord_op = %1" )
2020+
.arg( coord_op ).arg( source_crs ).arg( target_crs ).arg( coord_op_method ).arg( p1 ).arg( p2 ).arg( p3 ).arg( p4 ).arg( p5 ).arg( p6 ).arg( p7 );
2021+
}
2022+
{
2023+
//not yet in database, do insert
2024+
QgsDebugMsg( "Trying datum transform insert" );
2025+
sql = QString( "INSERT INTO tbl_datum_transform ( coord_op_code, source_crs_code, target_crs_code, coord_op_method_code, p1, p2, p3, p4, p5, p6, p7 ) VALUES ( %1, %2, %3, %4, %5, %6, %7, %8, %9, %10, %11 )" )
2026+
.arg( coord_op ).arg( source_crs ).arg( target_crs ).arg( coord_op_method ).arg( p1 ).arg( p2 ).arg( p3 ).arg( p4 ).arg( p5 ).arg( p6 ).arg( p7 );
2027+
2028+
}
2029+
2030+
if ( sqlite3_exec( db, sql.toUtf8(), 0, 0, 0 ) != SQLITE_OK )
2031+
{
2032+
QgsDebugMsg( "Error" );
2033+
}
2034+
}
2035+
2036+
if ( sqlite3_exec( db, "COMMIT", 0, 0, 0 ) != SQLITE_OK )
2037+
{
2038+
qCritical( "Could not commit transaction: %s [%s]\n", QgsApplication::srsDbFilePath().toLocal8Bit().constData(), sqlite3_errmsg( db ) );
2039+
return false;
2040+
}
2041+
2042+
sqlite3_close( db );
2043+
return true;
2044+
}
2045+
2046+
QString QgsCoordinateReferenceSystem::geographicCRSAuthId() const
2047+
{
2048+
if ( geographicFlag() )
2049+
{
2050+
return mAuthId;
2051+
}
2052+
else if ( mCRS )
2053+
{
2054+
return OSRGetAuthorityName( mCRS, "GEOGCS" ) + QString( ":" ) + OSRGetAuthorityCode( mCRS, "GEOGCS" );
2055+
}
2056+
else
2057+
{
2058+
return "";
2059+
}
2060+
}

‎src/core/qgscoordinatereferencesystem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,9 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
354354
*/
355355
bool saveAsUserCRS( QString name );
356356

357+
/**Returns auth id of related geographic CRS*/
358+
QString geographicCRSAuthId() const;
359+
357360
// Mutators -----------------------------------
358361
// We don't want to expose these to the public api since they wont create
359362
// a fully valid crs. Programmers should use the createFrom* methods rather
@@ -465,6 +468,7 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
465468

466469
static bool loadIDs( QHash<int, QString> &wkts );
467470
static bool loadWkts( QHash<int, QString> &wkts, const char *filename );
471+
static bool syncDatumTransform( const QString& dbPath );
468472

469473
//!Whether this is a coordinate system has inverted axis
470474
mutable int mAxisInverted;

0 commit comments

Comments
 (0)