Skip to content

Commit cd26796

Browse files
authored
ProjectedCRS::identify(): do not return CRS whose ellipsoid is totally different from the input one (#4635)
2 parents 1faf789 + 13b6fb7 commit cd26796

File tree

3 files changed

+75
-8
lines changed

3 files changed

+75
-8
lines changed

src/iso19111/crs.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5039,6 +5039,8 @@ ProjectedCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
50395039
}
50405040
hasNonMatchingId = true;
50415041
} else if (!insignificantName) {
5042+
const double semiMajorAxis =
5043+
ellipsoid->semiMajorAxis().getSIValue();
50425044
for (int ipass = 0; ipass < 2; ipass++) {
50435045
const bool approximateMatch = ipass == 1;
50445046
auto objects = authorityFactory->createObjectsFromNameEx(
@@ -5053,8 +5055,14 @@ ProjectedCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
50535055
thisName.c_str(), pairObjName.second.c_str());
50545056
foundEquivalentName |= eqName;
50555057

5056-
if (addCRS(crsNN, eqName, false).second == 100) {
5057-
return res;
5058+
if (std::fabs(semiMajorAxis - crsNN->baseCRS()
5059+
->ellipsoid()
5060+
->semiMajorAxis()
5061+
.getSIValue()) <=
5062+
1e-4 * semiMajorAxis) {
5063+
if (addCRS(crsNN, eqName, false).second == 100) {
5064+
return res;
5065+
}
50585066
}
50595067
}
50605068
if (!res.empty()) {

src/iso19111/factory.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10008,13 +10008,27 @@ AuthorityFactory::createProjectedCRSFromExisting(
1000810008
}
1000910009
}
1001010010

10011-
std::string sql("SELECT projected_crs.auth_name, projected_crs.code, "
10012-
"projected_crs.name FROM projected_crs "
10013-
"JOIN conversion_table conv ON "
10014-
"projected_crs.conversion_auth_name = conv.auth_name AND "
10015-
"projected_crs.conversion_code = conv.code WHERE "
10016-
"projected_crs.deprecated = 0 AND ");
10011+
std::string sql(
10012+
"SELECT projected_crs.auth_name, projected_crs.code, "
10013+
"projected_crs.name FROM projected_crs "
10014+
"JOIN conversion_table conv ON "
10015+
"projected_crs.conversion_auth_name = conv.auth_name AND "
10016+
"projected_crs.conversion_code = conv.code "
10017+
"JOIN geodetic_crs gcrs ON "
10018+
"gcrs.auth_name = projected_crs.geodetic_crs_auth_name AND "
10019+
"gcrs.code = projected_crs.geodetic_crs_code "
10020+
"JOIN geodetic_datum datum ON "
10021+
"datum.auth_name = gcrs.datum_auth_name AND "
10022+
"datum.code = gcrs.datum_code "
10023+
"JOIN ellipsoid ellps ON "
10024+
"ellps.auth_name = datum.ellipsoid_auth_name AND "
10025+
"ellps.code = datum.ellipsoid_code "
10026+
"WHERE "
10027+
"abs(ellps.semi_major_axis - ?) <= 1e-4 * ellps.semi_major_axis AND "
10028+
"projected_crs.deprecated = 0 AND ");
1001710029
ListOfParams params;
10030+
params.emplace_back(
10031+
toString(crs->baseCRS()->ellipsoid()->semiMajorAxis().value()));
1001810032
if (!candidatesGeodCRS.empty()) {
1001910033
sql += buildSqlLookForAuthNameCode(candidatesGeodCRS, params,
1002010034
"projected_crs.geodetic_crs_");

test/unit/test_crs.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3765,6 +3765,51 @@ TEST(crs, projectedCRS_identify_db) {
37653765
EXPECT_EQ(*(res.front().first->identifiers()[0]->codeSpace()), "EPSG");
37663766
EXPECT_EQ(res.front().second, 100);
37673767
}
3768+
{
3769+
// The ellipsoid definition uses a unusual value for the inverse
3770+
// flattening Check that we only identify CRS whose ellipsoid shape is
3771+
// close to the input one (in particular no IAU_2015...)
3772+
auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(
3773+
"PROJCRS[\"Transverse Mercator\",\n"
3774+
" BASEGEOGCRS[\"DE_DHDN (whole country, 2001) to ETRS89\",\n"
3775+
" DATUM[\"DE_DHDN (whole country, 2001) to ETRS89\",\n"
3776+
" ELLIPSOID[\"Bessel\",6377397.155,299.15281310608,\n"
3777+
" LENGTHUNIT[\"metre\",1,\n"
3778+
" ID[\"EPSG\",9001]]]],\n"
3779+
" PRIMEM[\"Greenwich\",0,\n"
3780+
" ANGLEUNIT[\"degree\",0.0174532925199433,\n"
3781+
" ID[\"EPSG\",9122]]]],\n"
3782+
" CONVERSION[\"Transverse Mercator\",\n"
3783+
" METHOD[\"Transverse Mercator\",\n"
3784+
" ID[\"EPSG\",9807]],\n"
3785+
" PARAMETER[\"Latitude of natural origin\",0,\n"
3786+
" ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3787+
" ID[\"EPSG\",8801]],\n"
3788+
" PARAMETER[\"Longitude of natural origin\",12,\n"
3789+
" ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3790+
" ID[\"EPSG\",8802]],\n"
3791+
" PARAMETER[\"Scale factor at natural origin\",1,\n"
3792+
" SCALEUNIT[\"unity\",1],\n"
3793+
" ID[\"EPSG\",8805]],\n"
3794+
" PARAMETER[\"False easting\",4500000,\n"
3795+
" LENGTHUNIT[\"metre\",1],\n"
3796+
" ID[\"EPSG\",8806]],\n"
3797+
" PARAMETER[\"False northing\",0,\n"
3798+
" LENGTHUNIT[\"metre\",1],\n"
3799+
" ID[\"EPSG\",8807]]],\n"
3800+
" CS[Cartesian,2],\n"
3801+
" AXIS[\"easting\",east,\n"
3802+
" ORDER[1],\n"
3803+
" LENGTHUNIT[\"meters\",1]],\n"
3804+
" AXIS[\"northing\",north,\n"
3805+
" ORDER[2],\n"
3806+
" LENGTHUNIT[\"meters\",1]]]");
3807+
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
3808+
ASSERT_TRUE(crs != nullptr);
3809+
auto factoryAll = AuthorityFactory::create(dbContext, std::string());
3810+
auto res = crs->identify(factoryAll);
3811+
EXPECT_EQ(res.size(), 13U);
3812+
}
37683813
}
37693814

37703815
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)