Skip to content
Permalink
Browse files

Don't equate a BoundCRS with an identified SourceCRS as the SourceCRS…

… when identifying

CRSes

May result in some CRSes which were previously identified as known standard CRSes
now being shown as User CRSes, but they aren't the same to we can't equate them.

If previously identified CRSes are showing as User CRSes now, then we should
investigate these upstream in the proj or gdal libraries, and get all fixes
in place upstream rather then trying to do this in QGIS code (which is
inevitably going to end up with an unmaintainable mess)
  • Loading branch information
nyalldawson committed Dec 17, 2019
1 parent 550dede commit c8d5c434020e825b9a941167dc98971e4e8d8b2c
Showing with 42 additions and 3 deletions.
  1. +13 −2 src/core/qgsprojutils.cpp
  2. +29 −1 tests/src/core/testqgscoordinatereferencesystem.cpp
@@ -204,11 +204,22 @@ bool QgsProjUtils::identifyCrs( const PJ *crs, QString &authName, QString &authC
{
if ( confidence[i] >= bestConfidence )
{
// prefer EPSG codes for compatibility with earlier qgis conversions
QgsProjUtils::proj_pj_unique_ptr candidateCrs( proj_list_get( QgsProjContext::get(), crsList, i ) );
switch ( proj_get_type( candidateCrs.get() ) )
{
case PJ_TYPE_BOUND_CRS:
// proj_identify also matches bound CRSes to the source CRS. But they are not the same as the source CRS, so we don't
// consider them a candidate for a match here
continue;

default:
break;
}

candidateCrs = QgsProjUtils::crsToSingleCrs( candidateCrs.get() );
const QString authName( proj_get_id_auth_name( candidateCrs.get(), 0 ) );
if ( confidence[i] > bestConfidence || authName == QLatin1String( "EPSG" ) )
// if a match is identical confidence, we prefer EPSG codes for compatibility with earlier qgis conversions
if ( confidence[i] > bestConfidence || ( confidence[i] == bestConfidence && authName == QLatin1String( "EPSG" ) ) )
{
bestConfidence = confidence[i];
matchedCrs = std::move( candidateCrs );
@@ -51,7 +51,6 @@ class TestQgsCoordinateReferenceSystem: public QObject
void createFromSrid();
void sridCache();
void createFromWkt();
void createFromWktWithIdentify();
void createFromWktUnknown();
void fromWkt();
void wktCache();
@@ -92,6 +91,8 @@ class TestQgsCoordinateReferenceSystem: public QObject
void customProjString();
void recentProjections();
void displayIdentifier();
void createFromWktWithIdentify();
void fromProj4EPSG20936();

private:
void debugPrint( QgsCoordinateReferenceSystem &crs );
@@ -407,14 +408,41 @@ void TestQgsCoordinateReferenceSystem::createFromWktWithIdentify()
#if PROJ_VERSION_MAJOR>=6
QgsCoordinateReferenceSystem crs;
// see https://github.com/qgis/QGIS/issues/33007, WKT string from a MapInfo tabfile in GDA2020 projection

// currently GDAL gives this BoundCRS WKT, but that's an issue in GDAL -- see https://github.com/OSGeo/PROJ/issues/1752
crs.createFromWkt( QStringLiteral( "BOUNDCRS[SOURCECRS[PROJCRS[\"unnamed\",BASEGEOGCRS[\"unnamed\",DATUM[\"Geocentric Datum of Australia 2020\",ELLIPSOID[\"GRS 80\",6378137,298.257222101,LENGTHUNIT[\"metre\",1,ID[\"EPSG\",9001]]]],PRIMEM[\"Greenwich\",0,ANGLEUNIT[\"degree\",0.0174532925199433,ID[\"EPSG\",9122]]]],CONVERSION[\"UTM zone 55S\",METHOD[\"Transverse Mercator\",ID[\"EPSG\",9807]],PARAMETER[\"Latitude of natural origin\",0,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8801]],PARAMETER[\"Longitude of natural origin\",147,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8802]],PARAMETER[\"Scale factor at natural origin\",0.9996,SCALEUNIT[\"unity\",1],ID[\"EPSG\",8805]],PARAMETER[\"False easting\",500000,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8806]],PARAMETER[\"False northing\",10000000,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8807]],ID[\"EPSG\",17055]],CS[Cartesian,2],AXIS[\"easting\",east,ORDER[1],LENGTHUNIT[\"metre\",1,ID[\"EPSG\",9001]]],AXIS[\"northing\",north,ORDER[2],LENGTHUNIT[\"metre\",1,ID[\"EPSG\",9001]]]]],TARGETCRS[GEOGCRS[\"WGS 84\",DATUM[\"World Geodetic System 1984\",ELLIPSOID[\"WGS 84\",6378137,298.257223563,LENGTHUNIT[\"metre\",1]]],PRIMEM[\"Greenwich\",0,ANGLEUNIT[\"degree\",0.0174532925199433]],CS[ellipsoidal,2],AXIS[\"geodetic latitude (Lat)\",north,ORDER[1],ANGLEUNIT[\"degree\",0.0174532925199433]],AXIS[\"geodetic longitude (Lon)\",east,ORDER[2],ANGLEUNIT[\"degree\",0.0174532925199433]],USAGE[SCOPE[\"unknown\"],AREA[\"World\"],BBOX[-90,-180,90,180]],ID[\"EPSG\",4326]]],ABRIDGEDTRANSFORMATION[\"Transformation to WGS84\",METHOD[\"Position Vector transformation (geog2D domain)\",ID[\"EPSG\",9606]],PARAMETER[\"X-axis translation\",-0.06155,ID[\"EPSG\",8605]],PARAMETER[\"Y-axis translation\",0.01087,ID[\"EPSG\",8606]],PARAMETER[\"Z-axis translation\",0.04019,ID[\"EPSG\",8607]],PARAMETER[\"X-axis rotation\",-0.0394924,ID[\"EPSG\",8608]],PARAMETER[\"Y-axis rotation\",-0.0327221,ID[\"EPSG\",8609]],PARAMETER[\"Z-axis rotation\",-0.0328979,ID[\"EPSG\",8610]],PARAMETER[\"Scale difference\",1.000000009994,ID[\"EPSG\",8611]]]]" ) );
QVERIFY( crs.isValid() );
// this must be a user CRS -- it's a boundcrs of EPSG:7855, not EPSG:7855 itself
QCOMPARE( crs.authid(), QStringLiteral( "USER:100010" ) );
QCOMPARE( crs.ellipsoidAcronym(), QStringLiteral( "PARAMETER:6378137:6356752.31414035614579916" ) );

// here's the correct (desirable) WKT we should get from GDAL
crs.createFromWkt( QStringLiteral( "PROJCS[\"unnamed\",GEOGCS[\"unnamed\",DATUM[\"Geocentric_Datum_of_Australia_2020\",SPHEROID[\"GRS 80\",6378137,298.257222101]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",147],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",10000000],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]" ) );
QVERIFY( crs.isValid() );
QCOMPARE( crs.authid(), QStringLiteral( "EPSG:7855" ) );

QCOMPARE( crs.ellipsoidAcronym(), QStringLiteral( "EPSG:7019" ) );
#endif
}

void TestQgsCoordinateReferenceSystem::fromProj4EPSG20936()
{
#if PROJ_VERSION_MAJOR>=6
QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem::fromProj4( QStringLiteral( "+proj=utm +zone=36 +south +a=6378249.145 +b=6356514.966398753 +towgs84=-143,-90,-294,0,0,0,0 +units=m +no_defs" ) );
QVERIFY( crs.isValid() );
QCOMPARE( crs.toWkt(), QStringLiteral( R"""(PROJCS["unknown",GEOGCS["unknown",DATUM["unknown",SPHEROID["unknown",6378249.145,293.466307699995],TOWGS84[-143,-90,-294,0,0,0,0]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",33],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",10000000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH]])""" ) );
QCOMPARE( crs.toProj4(), QStringLiteral( "+proj=utm +zone=36 +south +a=6378249.145 +b=6356514.966398753 +towgs84=-143,-90,-294,0,0,0,0 +units=m +no_defs" ) );

// should ideally be EPSG:20936, but see https://github.com/OSGeo/PROJ/issues/1805
// so instead we get a BoundCRS of EPSG:20936 created from the proj string, which must be a user CRS (not EPSG:20936 itself!)
#if 0
QCOMPARE( crs.authid(), QStringLiteral( "EPSG:20936" ) );
#endif

QCOMPARE( crs.ellipsoidAcronym(), QStringLiteral( "EPSG:7013" ) );
#endif
}

void TestQgsCoordinateReferenceSystem::createFromWktUnknown()
{
QgsCoordinateReferenceSystem crs;

0 comments on commit c8d5c43

Please sign in to comment.
You can’t perform that action at this time.