Skip to content

Commit

Permalink
Don't equate a BoundCRS with an identified SourceCRS as the SourceCRS…
Browse files Browse the repository at this point in the history
… 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 20, 2019
1 parent 550dede commit c8d5c43
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 3 deletions.
15 changes: 13 additions & 2 deletions src/core/qgsprojutils.cpp
Expand Up @@ -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 );
Expand Down
30 changes: 29 additions & 1 deletion tests/src/core/testqgscoordinatereferencesystem.cpp
Expand Up @@ -51,7 +51,6 @@ class TestQgsCoordinateReferenceSystem: public QObject
void createFromSrid();
void sridCache();
void createFromWkt();
void createFromWktWithIdentify();
void createFromWktUnknown();
void fromWkt();
void wktCache();
Expand Down Expand Up @@ -92,6 +91,8 @@ class TestQgsCoordinateReferenceSystem: public QObject
void customProjString();
void recentProjections();
void displayIdentifier();
void createFromWktWithIdentify();
void fromProj4EPSG20936();

private:
void debugPrint( QgsCoordinateReferenceSystem &crs );
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit c8d5c43

Please sign in to comment.