Skip to content

Commit 8b0029e

Browse files
authored
Merge pull request OSGeo#3851 from rouault/wkt1_esri_8353
WKT1 ESRI import/export: fix GCS name for EPSG:8353 S-JTSK_[JTSK03]_Krovak_East_North
2 parents c5c7e64 + 57a1eab commit 8b0029e

File tree

4 files changed

+167
-1
lines changed

4 files changed

+167
-1
lines changed

scripts/build_db_from_esri.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ def get_old_esri_name(s):
405405
"""Massage datum/CRS name like old ESRI software did"""
406406

407407
# Needed for EPSG:8353 S_JTSK_JTSK03_Krovak_East_North
408-
# Cf https://github.com/OSGeo/gdal/issues/75054
408+
# Cf https://github.com/OSGeo/gdal/issues/7505
409409
if '[' in s:
410410
s = s.replace('-', '_')
411411
s = s.replace('[', '')

src/iso19111/factory.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3404,6 +3404,25 @@ std::string DatabaseContext::getOldProjGridName(const std::string &gridName) {
34043404

34053405
// ---------------------------------------------------------------------------
34063406

3407+
// scripts/build_db_from_esri.py adds a second alias for
3408+
// names that have '[' in them. See get_old_esri_name()
3409+
// in scripts/build_db_from_esri.py
3410+
// So if we only have two aliases detect that situation to get the official
3411+
// new name
3412+
static std::string getUniqueEsriAlias(const std::list<std::string> &l) {
3413+
std::string first = l.front();
3414+
std::string second = *(std::next(l.begin()));
3415+
if (second.find('[') != std::string::npos)
3416+
std::swap(first, second);
3417+
if (replaceAll(replaceAll(replaceAll(first, "[", ""), "]", ""), "-", "_") ==
3418+
second) {
3419+
return first;
3420+
}
3421+
return std::string();
3422+
}
3423+
3424+
// ---------------------------------------------------------------------------
3425+
34073426
/** \brief Gets the alias name from an official name.
34083427
*
34093428
* @param officialName Official name. Mandatory
@@ -3452,6 +3471,14 @@ DatabaseContext::getAliasFromOfficialName(const std::string &officialName,
34523471
"auth_name = ? AND code = ? AND source = ?",
34533472
{genuineTableName, row[0], row[1], source});
34543473
if (!res2.empty()) {
3474+
if (res2.size() == 2 && source == "ESRI") {
3475+
std::list<std::string> l;
3476+
l.emplace_back(res2.front()[0]);
3477+
l.emplace_back((*(std::next(res2.begin())))[0]);
3478+
const auto uniqueEsriAlias = getUniqueEsriAlias(l);
3479+
if (!uniqueEsriAlias.empty())
3480+
return uniqueEsriAlias;
3481+
}
34553482
return res2.front()[0];
34563483
}
34573484
}
@@ -3527,6 +3554,15 @@ std::list<std::string> DatabaseContext::getAliases(
35273554
for (const auto &row : resSql) {
35283555
res.emplace_back(row[0]);
35293556
}
3557+
3558+
if (res.size() == 2 && source == "ESRI") {
3559+
const auto uniqueEsriAlias = getUniqueEsriAlias(res);
3560+
if (!uniqueEsriAlias.empty()) {
3561+
res.clear();
3562+
res.emplace_back(uniqueEsriAlias);
3563+
}
3564+
}
3565+
35303566
d->cacheAliasNames_.insert(key, res);
35313567
return res;
35323568
}

src/iso19111/io.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3125,6 +3125,21 @@ WKTParser::Private::buildGeodeticCRS(const WKTNodeNNPtr &node) {
31253125
props.set("IMPLICIT_CS", true);
31263126
}
31273127

3128+
const std::string crsName = stripQuotes(nodeP->children()[0]);
3129+
if (esriStyle_ && dbContext_) {
3130+
std::string outTableName;
3131+
std::string authNameFromAlias;
3132+
std::string codeFromAlias;
3133+
auto authFactory =
3134+
AuthorityFactory::create(NN_NO_CHECK(dbContext_), std::string());
3135+
auto officialName = authFactory->getOfficialNameFromAlias(
3136+
crsName, "geodetic_crs", "ESRI", false, outTableName,
3137+
authNameFromAlias, codeFromAlias);
3138+
if (!officialName.empty()) {
3139+
props.set(IdentifiedObject::NAME_KEY, officialName);
3140+
}
3141+
}
3142+
31283143
auto datum =
31293144
!isNull(datumNode)
31303145
? buildGeodeticReferenceFrame(datumNode, primeMeridian, dynamicNode)

test/unit/test_crs.cpp

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,6 +2407,121 @@ TEST(crs, projectedCRS_from_WKT1_ESRI_as_WKT1_ESRI) {
24072407

24082408
// ---------------------------------------------------------------------------
24092409

2410+
TEST(crs, projectedCRS_from_WKT1_ESRI_as_WKT1_ESRI_s_jtsk03_krovak_east_north) {
2411+
// EPSG:8353
2412+
auto wkt = "PROJCS[\"S-JTSK_[JTSK03]_Krovak_East_North\","
2413+
"GEOGCS[\"S-JTSK_[JTSK03]\",DATUM[\"S-JTSK_[JTSK03]\","
2414+
"SPHEROID[\"Bessel_1841\",6377397.155,299.1528128]],"
2415+
"PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],"
2416+
"PROJECTION[\"Krovak\"],"
2417+
"PARAMETER[\"False_Easting\",0.0],"
2418+
"PARAMETER[\"False_Northing\",0.0],"
2419+
"PARAMETER[\"Pseudo_Standard_Parallel_1\",78.5],"
2420+
"PARAMETER[\"Scale_Factor\",0.9999],"
2421+
"PARAMETER[\"Azimuth\",30.2881397527778],"
2422+
"PARAMETER[\"Longitude_Of_Center\",24.8333333333333],"
2423+
"PARAMETER[\"Latitude_Of_Center\",49.5],"
2424+
"PARAMETER[\"X_Scale\",-1.0],"
2425+
"PARAMETER[\"Y_Scale\",1.0],"
2426+
"PARAMETER[\"XY_Plane_Rotation\",90.0],"
2427+
"UNIT[\"Meter\",1.0]]";
2428+
2429+
auto dbContext = DatabaseContext::create();
2430+
auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt);
2431+
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
2432+
ASSERT_TRUE(crs != nullptr);
2433+
2434+
auto expected_wkt2 =
2435+
"PROJCRS[\"S-JTSK [JTSK03] / Krovak East North\",\n"
2436+
" BASEGEOGCRS[\"S-JTSK [JTSK03]\",\n"
2437+
" DATUM[\"System of the Unified Trigonometrical Cadastral "
2438+
"Network [JTSK03]\",\n"
2439+
" ELLIPSOID[\"Bessel 1841\",6377397.155,299.1528128,\n"
2440+
" LENGTHUNIT[\"metre\",1]],\n"
2441+
" ID[\"EPSG\",1201]],\n"
2442+
" PRIMEM[\"Greenwich\",0,\n"
2443+
" ANGLEUNIT[\"Degree\",0.0174532925199433]]],\n"
2444+
" CONVERSION[\"unnamed\",\n"
2445+
" METHOD[\"Krovak (North Orientated)\",\n"
2446+
" ID[\"EPSG\",1041]],\n"
2447+
" PARAMETER[\"Latitude of projection centre\",49.5,\n"
2448+
" ANGLEUNIT[\"Degree\",0.0174532925199433],\n"
2449+
" ID[\"EPSG\",8811]],\n"
2450+
" PARAMETER[\"Longitude of origin\",24.8333333333333,\n"
2451+
" ANGLEUNIT[\"Degree\",0.0174532925199433],\n"
2452+
" ID[\"EPSG\",8833]],\n"
2453+
" PARAMETER[\"Co-latitude of cone axis\",30.2881397527778,\n"
2454+
" ANGLEUNIT[\"Degree\",0.0174532925199433],\n"
2455+
" ID[\"EPSG\",1036]],\n"
2456+
" PARAMETER[\"Latitude of pseudo standard parallel\",78.5,\n"
2457+
" ANGLEUNIT[\"Degree\",0.0174532925199433],\n"
2458+
" ID[\"EPSG\",8818]],\n"
2459+
" PARAMETER[\"Scale factor on pseudo standard "
2460+
"parallel\",0.9999,\n"
2461+
" SCALEUNIT[\"unity\",1],\n"
2462+
" ID[\"EPSG\",8819]],\n"
2463+
" PARAMETER[\"False easting\",0,\n"
2464+
" LENGTHUNIT[\"metre\",1],\n"
2465+
" ID[\"EPSG\",8806]],\n"
2466+
" PARAMETER[\"False northing\",0,\n"
2467+
" LENGTHUNIT[\"metre\",1],\n"
2468+
" ID[\"EPSG\",8807]]],\n"
2469+
" CS[Cartesian,2],\n"
2470+
" AXIS[\"(E)\",east,\n"
2471+
" ORDER[1],\n"
2472+
" LENGTHUNIT[\"metre\",1,\n"
2473+
" ID[\"EPSG\",9001]]],\n"
2474+
" AXIS[\"(N)\",north,\n"
2475+
" ORDER[2],\n"
2476+
" LENGTHUNIT[\"metre\",1,\n"
2477+
" ID[\"EPSG\",9001]]]]";
2478+
2479+
EXPECT_EQ(
2480+
crs->exportToWKT(
2481+
WKTFormatter::create(WKTFormatter::Convention::WKT2_2019, dbContext)
2482+
.get()),
2483+
expected_wkt2);
2484+
2485+
EXPECT_EQ(
2486+
crs->exportToWKT(
2487+
WKTFormatter::create(WKTFormatter::Convention::WKT1_ESRI, dbContext)
2488+
.get()),
2489+
wkt);
2490+
}
2491+
2492+
// ---------------------------------------------------------------------------
2493+
2494+
TEST(crs, projectedCRS_from_EPSG_as_WKT1_ESRI_s_jtsk03_krovak_east_north) {
2495+
auto dbContext = DatabaseContext::create();
2496+
auto factoryEPSG = AuthorityFactory::create(dbContext, "EPSG");
2497+
auto crs = factoryEPSG->createProjectedCRS("8353");
2498+
2499+
auto wkt = "PROJCS[\"S-JTSK_[JTSK03]_Krovak_East_North\","
2500+
"GEOGCS[\"S-JTSK_[JTSK03]\",DATUM[\"S-JTSK_[JTSK03]\","
2501+
"SPHEROID[\"Bessel_1841\",6377397.155,299.1528128]],"
2502+
"PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],"
2503+
"PROJECTION[\"Krovak\"],"
2504+
"PARAMETER[\"False_Easting\",0.0],"
2505+
"PARAMETER[\"False_Northing\",0.0],"
2506+
"PARAMETER[\"Pseudo_Standard_Parallel_1\",78.5],"
2507+
"PARAMETER[\"Scale_Factor\",0.9999],"
2508+
"PARAMETER[\"Azimuth\",30.2881397527778],"
2509+
"PARAMETER[\"Longitude_Of_Center\",24.8333333333333],"
2510+
"PARAMETER[\"Latitude_Of_Center\",49.5],"
2511+
"PARAMETER[\"X_Scale\",-1.0],"
2512+
"PARAMETER[\"Y_Scale\",1.0],"
2513+
"PARAMETER[\"XY_Plane_Rotation\",90.0],"
2514+
"UNIT[\"Meter\",1.0]]";
2515+
2516+
EXPECT_EQ(
2517+
crs->exportToWKT(
2518+
WKTFormatter::create(WKTFormatter::Convention::WKT1_ESRI, dbContext)
2519+
.get()),
2520+
wkt);
2521+
}
2522+
2523+
// ---------------------------------------------------------------------------
2524+
24102525
TEST(crs, projectedCRS_as_PROJ_string) {
24112526
auto crs = createProjected();
24122527

0 commit comments

Comments
 (0)