Skip to content
Permalink
Browse files

Require Proj version 6 or later, drop old proj 4 compatibility code

  • Loading branch information
nyalldawson committed Feb 23, 2021
1 parent c238d46 commit e11801d34e11dd1e7edfbcb2f3cda7bf476ea599
Showing with 84 additions and 3,563 deletions.
  1. +1 −6 python/plugins/processing/algs/gdal/GdalUtils.py
  2. +1 −5 python/plugins/processing/algs/qgis/DefineProjection.py
  3. +4 −15 python/plugins/processing/tests/GdalAlgorithmsGeneralTest.py
  4. +1 −4 python/plugins/processing/tests/GdalAlgorithmsRasterTest.py
  5. +2 −8 resources/CMakeLists.txt
  6. +0 −2 src/analysis/processing/qgsalgorithmtransform.cpp
  7. +0 −4 src/app/georeferencer/qgsimagewarper.cpp
  8. +0 −8 src/app/qgisapp.cpp
  9. +11 −152 src/app/qgscustomprojectiondialog.cpp
  10. +1 −79 src/app/qgsdatumtransformtablewidget.cpp
  11. +0 −7 src/app/qgsdatumtransformtablewidget.h
  12. +0 −8 src/core/processing/qgsprocessingfeedback.cpp
  13. +0 −2 src/core/processing/qgsprocessingregistry.cpp
  14. +0 −40 src/core/providers/ogr/qgsogrprovider.cpp
  15. +0 −16 src/core/qgis.h
  16. +0 −12 src/core/qgsapplication.cpp
  17. +3 −1,080 src/core/qgscoordinatereferencesystem.cpp
  18. +1 −17 src/core/qgscoordinatereferencesystem.h
  19. +0 −2 src/core/qgscoordinatereferencesystem_legacy.h
  20. +0 −35 src/core/qgscoordinatereferencesystem_p.h
  21. +1 −151 src/core/qgscoordinatetransform.cpp
  22. +1 −9 src/core/qgscoordinatetransform.h
  23. +1 −178 src/core/qgscoordinatetransform_p.cpp
  24. +0 −56 src/core/qgscoordinatetransform_p.h
  25. +0 −175 src/core/qgscoordinatetransformcontext.cpp
  26. +0 −4 src/core/qgscoordinatetransformcontext_p.h
  27. +0 −10 src/core/qgsdatumtransform.cpp
  28. +0 −4 src/core/qgsdatumtransform.h
  29. +0 −164 src/core/qgsellipsoidutils.cpp
  30. +0 −20 src/core/qgsprojutils.cpp
  31. +1 −8 src/core/qgsprojutils.h
  32. +0 −13 src/core/qgsvectorfilewriter.cpp
  33. +1 −256 src/gui/qgscoordinateoperationwidget.cpp
  34. +1 −4 src/gui/qgscoordinateoperationwidget.h
  35. +0 −18 src/gui/qgsdatumtransformdialog.cpp
  36. +0 −3 src/plugins/grass/qgsgrassnewmapset.cpp
  37. +0 −8 src/process/qgsprocess.cpp
  38. +0 −3 src/providers/grass/qgis.g.info.c
  39. +0 −3 src/providers/grass/qgsgrass.cpp
  40. +0 −3 src/providers/grass/qgsgrassprovider.cpp
  41. +0 −3 src/providers/grass/qgsgrassvector.cpp
  42. +0 −3 src/providers/grass/qgsgrassvectormap.cpp
  43. +0 −3 src/providers/grass/qgsgrassvectormaplayer.cpp
  44. +0 −3 src/providers/grass/qgsgrassvectormaplayer.h
  45. +0 −20 src/providers/hana/qgshanacrsutils.cpp
  46. +0 −19 tests/src/analysis/testqgsalignraster.cpp
  47. +0 −2 tests/src/app/testqgsdecorationscalebar.cpp
  48. +0 −44 tests/src/app/testqgsprojectproperties.cpp
  49. +0 −4 tests/src/core/testqgsarcgisrestutils.cpp
  50. +3 −244 tests/src/core/testqgscoordinatereferencesystem.cpp
  51. +0 −40 tests/src/core/testqgscoordinatetransform.cpp
  52. +0 −17 tests/src/core/testqgsdistancearea.cpp
  53. +0 −19 tests/src/core/testqgsgdalutils.cpp
  54. +0 −8 tests/src/core/testqgslayoutmap.cpp
  55. +0 −4 tests/src/core/testqgsmapsettings.cpp
  56. +0 −12 tests/src/core/testqgsproject.cpp
  57. +0 −10 tests/src/core/testqgsprojutils.cpp
  58. +0 −2 tests/src/gui/testprocessinggui.cpp
  59. +1 −52 tests/src/gui/testqgsdatumtransformdialog.cpp
  60. +10 −11 tests/src/python/test_provider_memory.py
  61. +1 −2 tests/src/python/test_qgscoordinateoperationwidget.py
  62. +0 −116 tests/src/python/test_qgscoordinatetransform.py
  63. +0 −284 tests/src/python/test_qgscoordinatetransformcontext.py
  64. +0 −1 tests/src/python/test_qgsdatumtransforms.py
  65. +38 −47 tests/src/python/test_qgsellipsoidutils.py
  66. +0 −1 tests/src/python/test_qgsprojectionselectionwidgets.py
@@ -471,12 +471,7 @@ def gdal_crs_string(crs):
if crs.authid().upper().startswith('EPSG:') or crs.authid().upper().startswith('IGNF:') or crs.authid().upper().startswith('ESRI:'):
return crs.authid()

if QgsProjUtils.projVersionMajor() >= 6:
# use WKT
return crs.toWkt(QgsCoordinateReferenceSystem.WKT_PREFERRED_GDAL)

# fallback to proj4 string, stripping out newline characters
return crs.toProj().replace('\n', ' ').replace('\r', ' ')
return crs.toWkt(QgsCoordinateReferenceSystem.WKT_PREFERRED_GDAL)

@classmethod
def tr(cls, string, context=''):
@@ -90,11 +90,7 @@ def processAlgorithm(self, parameters, context, feedback):

qpjFile = dsPath + '.qpj'
if os.path.exists(qpjFile):
if QgsProjUtils.projVersionMajor() < 6:
with open(qpjFile, 'w') as f:
f.write(wkt)
else:
os.remove(qpjFile)
os.remove(qpjFile)
else:
feedback.pushConsoleInfo(self.tr("Data source isn't a Shapefile, skipping .prj/.qpj creation"))

@@ -332,21 +332,10 @@ def testCrsConversion(self):
'+proj=utm +zone=36 +south +a=600000 +b=70000 +towgs84=-143,-90,-294,0,0,0,0 +units=m +no_defs')
self.assertTrue(crs.isValid())

if QgsProjUtils.projVersionMajor() >= 6:
# proj 6, WKT should be used
self.assertEqual(GdalUtils.gdal_crs_string(crs)[:40], 'BOUNDCRS[SOURCECRS[PROJCRS["unknown",BAS')

self.assertEqual(GdalUtils.gdal_crs_string(QgsCoordinateReferenceSystem('ESRI:102003')), 'ESRI:102003')
else:
self.assertEqual(GdalUtils.gdal_crs_string(crs),
'+proj=utm +zone=36 +south +a=600000 +b=70000 +towgs84=-143,-90,-294,0,0,0,0 +units=m +no_defs')
# check that newlines are stripped
crs = QgsCoordinateReferenceSystem()
crs.createFromProj(
'+proj=utm +zone=36 +south\n +a=600000 +b=70000 \r\n +towgs84=-143,-90,-294,0,0,0,0 +units=m\n+no_defs')
self.assertTrue(crs.isValid())
self.assertEqual(GdalUtils.gdal_crs_string(crs),
'+proj=utm +zone=36 +south +a=600000 +b=70000 +towgs84=-143,-90,-294,0,0,0,0 +units=m +no_defs')
# proj 6, WKT should be used
self.assertEqual(GdalUtils.gdal_crs_string(crs)[:40], 'BOUNDCRS[SOURCECRS[PROJCRS["unknown",BAS')

self.assertEqual(GdalUtils.gdal_crs_string(QgsCoordinateReferenceSystem('ESRI:102003')), 'ESRI:102003')

def testEscapeAndJoin(self):
self.assertEqual(GdalUtils.escapeAndJoin([1, "a", "a b", "a&b", "a(b)"]), '1 a "a b" "a&b" "a(b)"')
@@ -100,10 +100,7 @@ def test_definition_file(self):
def get_param_value_and_expected_string_for_custom_crs(proj_def):
crs = QgsCoordinateReferenceSystem.fromProj(proj_def)
custom_crs = f'proj4: {proj_def}'
if QgsProjUtils.projVersionMajor() >= 6:
return custom_crs, crs.toWkt(QgsCoordinateReferenceSystem.WKT_PREFERRED_GDAL).replace('"', '"""')
else:
return custom_crs, proj_def
return custom_crs, crs.toWkt(QgsCoordinateReferenceSystem.WKT_PREFERRED_GDAL).replace('"', '"""')

def testAssignProjection(self):
context = QgsProcessingContext()
@@ -42,14 +42,8 @@ endif()

ADD_QGIS_RESOURCES("${CMAKE_CURRENT_SOURCE_DIR}" resources DEST_RESOURCE_FILES "${RESOURCES_FILES}")

# srs.db -- special handling because there is a switch and rename depending on proj version
if (PROJ_VERSION_MAJOR GREATER 5)
message(STATUS "Using PROJ >= 6 srs database.")
set(SRSDB srs6.db)
else()
message(STATUS "Using PROJ <6 srs database.")
set(SRSDB srs.db)
endif()
message(STATUS "Using PROJ >= 6 srs database.")
set(SRSDB srs6.db)

add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/srs.db"
@@ -24,12 +24,10 @@ void QgsTransformAlgorithm::initParameters( const QVariantMap & )
{
addParameter( new QgsProcessingParameterCrs( QStringLiteral( "TARGET_CRS" ), QObject::tr( "Target CRS" ), QStringLiteral( "EPSG:4326" ) ) );

#if PROJ_VERSION_MAJOR>=6
std::unique_ptr< QgsProcessingParameterCoordinateOperation > crsOpParam = qgis::make_unique< QgsProcessingParameterCoordinateOperation >( QStringLiteral( "OPERATION" ), QObject::tr( "Coordinate operation" ),
QVariant(), QStringLiteral( "INPUT" ), QStringLiteral( "TARGET_CRS" ), QVariant(), QVariant(), true );
crsOpParam->setFlags( crsOpParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
addParameter( crsOpParam.release() );
#endif
}

QgsCoordinateReferenceSystem QgsTransformAlgorithm::outputCrs( const QgsCoordinateReferenceSystem & ) const
@@ -97,11 +97,7 @@ bool QgsImageWarper::createDestinationDataset( const QString &outputName, GDALDa
if ( crs.isValid() )
{
OGRSpatialReference oTargetSRS;
#if PROJ_VERSION_MAJOR>=6
oTargetSRS.importFromWkt( crs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED_GDAL ).toUtf8().data() );
#else
oTargetSRS.importFromProj4( crs.toProj().toLatin1().data() );
#endif

char *wkt = nullptr;
OGRErr err = oTargetSRS.exportToWkt( &wkt );
@@ -412,11 +412,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
//
#include <ogr_api.h>
#include <gdal_version.h>
#if PROJ_VERSION_MAJOR > 4
#include <proj.h>
#else
#include <proj_api.h>
#endif

#ifdef HAVE_PDAL
#include <pdal/pdal.hpp>
@@ -5335,13 +5331,9 @@ void QgisApp::about()

versionString += QLatin1String( "</tr><tr>" );

#if PROJ_VERSION_MAJOR > 4
PJ_INFO info = proj_info();
versionString += QStringLiteral( "<td>%1</td><td>%2.%3.%4</td>" ).arg( tr( "Compiled against PROJ" ) ).arg( PROJ_VERSION_MAJOR ).arg( PROJ_VERSION_MINOR ).arg( PROJ_VERSION_PATCH );
versionString += QStringLiteral( "<td>%1</td><td>%2</td>" ).arg( tr( "Running against PROJ" ) ).arg( info.release );
#else
versionString += QStringLiteral( "<td>%1</td><td colspan=3>%2</td>" ).arg( tr( "PROJ.4 Version" ), QString::number( PJ_VERSION ) );
#endif

versionString += QLatin1String( "</tr><tr>" );

@@ -33,13 +33,9 @@
#include <QMessageBox>
#include <QLocale>

//proj4 includes
#if PROJ_VERSION_MAJOR>=6
//proj includes
#include "qgsprojutils.h"
#include <proj.h>
#else
#include <proj_api.h>
#endif

#include "qgsogrutils.h"
#include <ogr_srs_api.h>
@@ -424,7 +420,6 @@ void QgsCustomProjectionDialog::updateListFromCurrentItem()
item->setData( 0, FormattedWktRole, teParameters->toPlainText() );
}

#if PROJ_VERSION_MAJOR>=6
static void proj_collecting_logger( void *user_data, int /*level*/, const char *message )
{
QStringList *dest = reinterpret_cast< QStringList * >( user_data );
@@ -433,13 +428,10 @@ static void proj_collecting_logger( void *user_data, int /*level*/, const char *
dest->append( messageString );
}

#endif

void QgsCustomProjectionDialog::validateCurrent()
{
const QString projDef = teParameters->toPlainText();

#if PROJ_VERSION_MAJOR>=6
PJ_CONTEXT *context = proj_context_create();

QStringList projErrors;
@@ -497,52 +489,6 @@ void QgsCustomProjectionDialog::validateCurrent()
proj_log_func( context, nullptr, nullptr );
proj_context_destroy( context );
context = nullptr;
#else
switch ( static_cast< QgsCoordinateReferenceSystem::Format >( mFormatComboBox->currentData().toInt() ) )
{
case QgsCoordinateReferenceSystem::FormatWkt:
{
QByteArray ba = projDef.toLatin1();
const char *pWkt = ba.data();
OGRSpatialReferenceH crs = OSRNewSpatialReference( nullptr );

OGRErr myInputResult = OSRImportFromWkt( crs, const_cast< char ** >( & pWkt ) );
if ( myInputResult == OGRERR_NONE )
{
QMessageBox::information( this, tr( "Custom Coordinate Reference System" ),
tr( "This WKT projection definition is valid." ) );
}
else
{
QMessageBox::warning( this, tr( "Custom Coordinate Reference System" ),
tr( "This WKT projection definition is not valid." ) );
}

OSRDestroySpatialReference( crs );
break;
}
case QgsCoordinateReferenceSystem::FormatProj:
{
projCtx pContext = pj_ctx_alloc();
projPJ proj = pj_init_plus_ctx( pContext, projDef.toLocal8Bit().data() );

if ( proj )
{
QMessageBox::information( this, tr( "Custom Coordinate Reference System" ),
tr( "This proj projection definition is valid." ) );
}
else
{
QMessageBox::warning( this, tr( "Custom Coordinate Reference System" ),
tr( "This proj projection definition is not valid" ) );
}
pj_free( proj );
pj_ctx_free( pContext );
break;
}
}

#endif
}

void QgsCustomProjectionDialog::formatChanged()
@@ -561,25 +507,17 @@ void QgsCustomProjectionDialog::formatChanged()

case QgsCoordinateReferenceSystem::FormatWkt:
{
#if PROJ_VERSION_MAJOR>=6
PJ_CONTEXT *pjContext = QgsProjContext::get();
QString proj = teParameters->toPlainText();
proj.replace( QLatin1String( "+type=crs" ), QString() );
proj += QLatin1String( " +type=crs" );
QgsProjUtils::proj_pj_unique_ptr crs( proj_create( QgsProjContext::get(), proj.toLatin1().constData() ) );
if ( crs )
{
PJ_CONTEXT *pjContext = QgsProjContext::get();
QString proj = teParameters->toPlainText();
proj.replace( QLatin1String( "+type=crs" ), QString() );
proj += QLatin1String( " +type=crs" );
QgsProjUtils::proj_pj_unique_ptr crs( proj_create( QgsProjContext::get(), proj.toLatin1().constData() ) );
if ( crs )
{
const QByteArray multiLineOption = QStringLiteral( "MULTILINE=YES" ).toLocal8Bit();
const char *const options[] = {multiLineOption.constData(), nullptr};
newFormatString = QString( proj_as_wkt( pjContext, crs.get(), PJ_WKT2_2019, options ) );
}
const QByteArray multiLineOption = QStringLiteral( "MULTILINE=YES" ).toLocal8Bit();
const char *const options[] = {multiLineOption.constData(), nullptr};
newFormatString = QString( proj_as_wkt( pjContext, crs.get(), PJ_WKT2_2019, options ) );
}
#else
crs.createFromProj( teParameters->toPlainText() );
if ( crs.isValid() )
newFormatString = crs.toWkt( QgsCoordinateReferenceSystem::WKT2_2018, false );
#endif
break;
}
}
@@ -590,74 +528,24 @@ void QgsCustomProjectionDialog::formatChanged()
void QgsCustomProjectionDialog::pbnCalculate_clicked()
{
// We must check the prj def is valid!
#if PROJ_VERSION_MAJOR>=6
PJ_CONTEXT *pContext = QgsProjContext::get();
QString projDef = teParameters->toPlainText();
QgsDebugMsgLevel( QStringLiteral( "Proj: %1" ).arg( projDef ), 3 );
#else
if ( static_cast< QgsCoordinateReferenceSystem::Format >( mFormatComboBox->currentData().toInt() ) == QgsCoordinateReferenceSystem::FormatWkt )
{
// it's not trivial to implement, and we've gotta draw the line somewhere...
QMessageBox::warning( this, tr( "Custom Coordinate Reference System" ),
tr( "Testing WKT based CRS definitions requires Proj version 6 or later." ) );
return;
}

projCtx pContext = pj_ctx_alloc();
projPJ proj = pj_init_plus_ctx( pContext, teParameters->toPlainText().toLocal8Bit().data() );
QgsDebugMsgLevel( QStringLiteral( "Proj: %1" ).arg( teParameters->toPlainText() ), 3 );

if ( !proj )
{
QMessageBox::warning( this, tr( "Custom Coordinate Reference System" ),
tr( "This proj projection definition is not valid." ) );
projectedX->clear();
projectedY->clear();
pj_free( proj );
pj_ctx_free( pContext );
return;

}
#endif
// Get the WGS84 coordinates
bool okN, okE;
double latitude = northWGS84->text().toDouble( &okN );
double longitude = eastWGS84->text().toDouble( &okE );

#if PROJ_VERSION_MAJOR<6
latitude *= DEG_TO_RAD;
longitude *= DEG_TO_RAD;
#endif

if ( !okN || !okE )
{
QMessageBox::warning( this, tr( "Custom Coordinate Reference System" ),
tr( "Northing and Easting must be in decimal form." ) );
projectedX->clear();
projectedY->clear();
#if PROJ_VERSION_MAJOR<6
pj_free( proj );
pj_ctx_free( pContext );
#endif
return;
}

#if PROJ_VERSION_MAJOR < 6
projPJ wgs84Proj = pj_init_plus_ctx( pContext, geoProj4().data() ); //defined in qgis.h

if ( !wgs84Proj )
{
QMessageBox::critical( this, tr( "Custom Coordinate Reference System" ),
tr( "Internal Error (source projection invalid?)" ) );
projectedX->clear();
projectedY->clear();
pj_free( wgs84Proj );
pj_ctx_free( pContext );
return;
}
#endif

#if PROJ_VERSION_MAJOR>=6
if ( static_cast< QgsCoordinateReferenceSystem::Format >( mFormatComboBox->currentData().toInt() ) == QgsCoordinateReferenceSystem::FormatProj )
projDef = projDef + ( projDef.contains( QStringLiteral( "+type=crs" ) ) ? QString() : QStringLiteral( " +type=crs" ) );
QgsProjUtils::proj_pj_unique_ptr res( proj_create_crs_to_crs( pContext, "EPSG:4326", projDef.toUtf8(), nullptr ) );
@@ -677,19 +565,12 @@ void QgsCustomProjectionDialog::pbnCalculate_clicked()
nullptr, sizeof( double ), 0,
nullptr, sizeof( double ), 0 );
int projResult = proj_errno( res.get() );
#else
double z = 0.0;
int projResult = pj_transform( wgs84Proj, proj, 1, 0, &longitude, &latitude, &z );
#endif

if ( projResult != 0 )
{
projectedX->setText( tr( "Error" ) );
projectedY->setText( tr( "Error" ) );
#if PROJ_VERSION_MAJOR>=6
QgsDebugMsg( proj_errno_string( projResult ) );
#else
QgsDebugMsg( pj_strerrno( projResult ) );
#endif
}
else
{
@@ -698,39 +579,17 @@ void QgsCustomProjectionDialog::pbnCalculate_clicked()
int precision = 4;
bool isLatLong = false;

#if PROJ_VERSION_MAJOR>= 6
isLatLong = QgsProjUtils::usesAngularUnit( projDef );
#else
isLatLong = pj_is_latlong( proj );
if ( isLatLong )
{
latitude *= RAD_TO_DEG;
longitude *= RAD_TO_DEG;
}
#endif
if ( isLatLong )
{
precision = 7;
}

#if PROJ_VERSION_MAJOR>= 6
tmp = QLocale().toString( longitude, 'f', precision );
projectedX->setText( tmp );
tmp = QLocale().toString( latitude, 'f', precision );
projectedY->setText( tmp );
#else
tmp = QLocale().toString( latitude, 'f', precision );
projectedX->setText( tmp );
tmp = QLocale().toString( longitude, 'f', precision );
projectedY->setText( tmp );
#endif
}

#if PROJ_VERSION_MAJOR<6
pj_free( proj );
pj_free( wgs84Proj );
pj_ctx_free( pContext );
#endif
}

void QgsCustomProjectionDialog::showHelp()

0 comments on commit e11801d

Please sign in to comment.