aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2020-02-06 19:42:04 +0100
committerGitHub <noreply@github.com>2020-02-06 19:42:04 +0100
commit20e9bdea538efea120e4aa48ba4847c28679dc99 (patch)
tree9168a76717b3012b8a17c2d808eea0df6bd2fa97 /src
parent4d0b2e91c52e4ddae04741931dead86cc52492f5 (diff)
parent7fb3ebbf3724050787653afd3f6010760c280a32 (diff)
downloadPROJ-20e9bdea538efea120e4aa48ba4847c28679dc99.tar.gz
PROJ-20e9bdea538efea120e4aa48ba4847c28679dc99.zip
Merge pull request #1916 from rouault/backport_1884_1914_1915
[Backport 6.3] PR #1884 #1914 #1915
Diffstat (limited to 'src')
-rw-r--r--src/iso19111/factory.cpp319
-rw-r--r--src/iso19111/io.cpp173
2 files changed, 320 insertions, 172 deletions
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp
index 9ed9dc25..2fe12fb3 100644
--- a/src/iso19111/factory.cpp
+++ b/src/iso19111/factory.cpp
@@ -4331,56 +4331,29 @@ AuthorityFactory::createBetweenGeodeticCRSWithDatumBasedIntermediates(
// For some reason, filtering on v1.deprecated and v2.deprecated kills
// performance
- std::string sqlProlog("SELECT v1.table_name as table1, "
- "v1.auth_name AS auth_name1, v1.code AS code1, "
- "v1.deprecated AS deprecated1, "
- "v2.table_name as table2, "
- "v2.auth_name AS auth_name2, v2.code AS code2, "
- "v2.deprecated AS deprecated2, "
- "a1.south_lat AS south_lat1, "
- "a1.west_lon AS west_lon1, "
- "a1.north_lat AS north_lat1, "
- "a1.east_lon AS east_lon1, "
- "a2.south_lat AS south_lat2, "
- "a2.west_lon AS west_lon2, "
- "a2.north_lat AS north_lat2, "
- "a2.east_lon AS east_lon2 ");
- if (discardSuperseded) {
- sqlProlog += ", ss1.replacement_auth_name AS replacement_auth_name1, "
- "ss1.replacement_code AS replacement_code1, "
- "ss2.replacement_auth_name AS replacement_auth_name2, "
- "ss2.replacement_code AS replacement_code2 ";
- }
- sqlProlog += "FROM coordinate_operation_view v1 "
- "JOIN coordinate_operation_view v2 "
- "JOIN geodetic_crs g_source "
- "JOIN geodetic_crs g_v1s "
- "JOIN geodetic_crs g_v1t "
- "JOIN geodetic_crs g_v2s "
- "JOIN geodetic_crs g_v2t "
- "JOIN geodetic_crs g_target "
- "ON g_v1s.auth_name = v1.source_crs_auth_name "
- "AND g_v1s.code = v1.source_crs_code "
- "AND g_v1t.auth_name = v1.target_crs_auth_name "
- "AND g_v1t.code = v1.target_crs_code "
- "AND g_v2s.auth_name = v2.source_crs_auth_name "
- "AND g_v2s.code = v2.source_crs_code "
- "AND g_v2t.auth_name = v2.target_crs_auth_name "
- "AND g_v2t.code = v2.target_crs_code ";
-
- const std::string joinSupersession(
- "LEFT JOIN supersession ss1 ON "
- "ss1.superseded_table_name = v1.table_name AND "
- "ss1.superseded_auth_name = v1.auth_name AND "
- "ss1.superseded_code = v1.code AND "
- "ss1.superseded_table_name = ss1.replacement_table_name "
- "LEFT JOIN supersession ss2 ON "
- "ss2.superseded_table_name = v2.table_name AND "
- "ss2.superseded_auth_name = v2.auth_name AND "
- "ss2.superseded_code = v2.code AND "
- "ss2.superseded_table_name = ss2.replacement_table_name ");
+ const std::string sqlProlog("SELECT v1.table_name as table1, "
+ "v1.auth_name AS auth_name1, v1.code AS code1, "
+ "v1.deprecated AS deprecated1, "
+ "v2.table_name as table2, "
+ "v2.auth_name AS auth_name2, v2.code AS code2, "
+ "v2.deprecated AS deprecated2 "
+ "FROM coordinate_operation_view v1 "
+ "JOIN coordinate_operation_view v2 "
+ "JOIN geodetic_crs g_source "
+ "JOIN geodetic_crs g_v1s "
+ "JOIN geodetic_crs g_v1t "
+ "JOIN geodetic_crs g_v2s "
+ "JOIN geodetic_crs g_v2t "
+ "JOIN geodetic_crs g_target "
+ "ON g_v1s.auth_name = v1.source_crs_auth_name "
+ "AND g_v1s.code = v1.source_crs_code "
+ "AND g_v1t.auth_name = v1.target_crs_auth_name "
+ "AND g_v1t.code = v1.target_crs_code "
+ "AND g_v2s.auth_name = v2.source_crs_auth_name "
+ "AND g_v2s.code = v2.source_crs_code "
+ "AND g_v2t.auth_name = v2.target_crs_auth_name "
+ "AND g_v2t.code = v2.target_crs_code ");
const std::string joinArea(
- (discardSuperseded ? joinSupersession : std::string()) +
"JOIN area a1 ON v1.area_of_use_auth_name = a1.auth_name "
"AND v1.area_of_use_code = a1.code "
"JOIN area a2 ON v2.area_of_use_auth_name = a2.auth_name "
@@ -4393,8 +4366,13 @@ AuthorityFactory::createBetweenGeodeticCRSWithDatumBasedIntermediates(
additionalWhere +=
"WHERE g_source.auth_name = ? AND g_source.code = ? "
"AND g_target.auth_name = ? AND g_target.code = ? "
- "AND intersects_bbox(south_lat1, west_lon1, north_lat1, east_lon1, "
- "south_lat2, west_lon2, north_lat2, east_lon2) = 1 ";
+ "AND intersects_bbox("
+ "a1.south_lat, a1.west_lon, a1.north_lat, a1.east_lon, "
+ "a2.south_lat, a2.west_lon, a2.north_lat, a2.east_lon) = 1 ";
+
+#if 0
+ // While those additonal constraints are correct, they are found to
+ // kill performance. So enforce them as post-processing
if (!allowedAuthorities.empty()) {
additionalWhere += "AND v1.auth_name IN (";
@@ -4409,7 +4387,7 @@ AuthorityFactory::createBetweenGeodeticCRSWithDatumBasedIntermediates(
additionalWhere += ',';
additionalWhere += '?';
}
- additionalWhere += ')';
+ additionalWhere += ") ";
for (const auto &allowedAuthority : allowedAuthorities) {
params.emplace_back(allowedAuthority);
}
@@ -4422,6 +4400,8 @@ AuthorityFactory::createBetweenGeodeticCRSWithDatumBasedIntermediates(
params.emplace_back(d->authority());
params.emplace_back(d->authority());
}
+#endif
+
for (const auto &extent : {intersectingExtent1, intersectingExtent2}) {
if (extent) {
const auto &geogExtent = extent->geographicElements();
@@ -4437,10 +4417,10 @@ AuthorityFactory::createBetweenGeodeticCRSWithDatumBasedIntermediates(
if (south_lat != -90.0 || west_lon != -180.0 ||
north_lat != 90.0 || east_lon != 180.0) {
additionalWhere +=
- "AND intersects_bbox(south_lat1, "
- "west_lon1, north_lat1, east_lon1, ?, ?, ?, ?) AND "
- "intersects_bbox(south_lat2, west_lon2, "
- "north_lat2, east_lon2, ?, ?, ?, ?) ";
+ "AND intersects_bbox(a1.south_lat, a1.west_lon, "
+ "a1.north_lat, a1.east_lon, ?, ?, ?, ?) AND "
+ "intersects_bbox(a2.south_lat, a2.west_lon, "
+ "a2.north_lat, a2.east_lon, ?, ?, ?, ?) ";
params.emplace_back(south_lat);
params.emplace_back(west_lon);
params.emplace_back(north_lat);
@@ -4478,53 +4458,192 @@ AuthorityFactory::createBetweenGeodeticCRSWithDatumBasedIntermediates(
auto res = d->run(sql + additionalWhere, params);
// fprintf(stderr, "after\n");
- const auto filterOutSuperseded = [](SQLResultSet &&resultSet) {
- std::set<std::pair<std::string, std::string>> setTransf1;
- std::set<std::pair<std::string, std::string>> setTransf2;
+ const auto filterDeprecatedAndNotMatchingAuth =
+ [&](SQLResultSet &&resultSet) {
+
+ SQLResultSet filteredResultSet;
+ for (const auto &row : resultSet) {
+ const auto &deprecated1 = row[3];
+ const auto &deprecated2 = row[7];
+ if (deprecated1 == "1" || deprecated2 == "1") {
+ continue;
+ }
+ const auto &auth_name1 = row[1];
+ const auto &auth_name2 = row[5];
+ if (d->hasAuthorityRestriction()) {
+ if (auth_name1 != d->authority() ||
+ auth_name2 != d->authority()) {
+ continue;
+ }
+ }
+ if (!allowedAuthorities.empty()) {
+ {
+ bool found = false;
+ for (const auto &auth : allowedAuthorities) {
+ if (auth_name1 == auth) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ continue;
+ }
+ }
+ {
+ bool found = false;
+ for (const auto &auth : allowedAuthorities) {
+ if (auth_name2 == auth) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ continue;
+ }
+ }
+ }
+
+ filteredResultSet.emplace_back(row);
+ }
+ return filteredResultSet;
+ };
+
+ const auto filterOutSuperseded = [&](SQLResultSet &&resultSet) {
+ std::set<std::pair<std::string, std::string>> setTransf;
+ std::string findSupersededSql("SELECT superseded_table_name, "
+ "superseded_auth_name, superseded_code, "
+ "replacement_auth_name, replacement_code "
+ "FROM supersession WHERE ");
+ bool findSupersededFirstWhere = true;
+ ListOfParams findSupersededParams;
+
+ std::set<std::string> setAlreadyAsked;
+ const auto keyMapSupersession = [](
+ const std::string &table_name, const std::string &auth_name,
+ const std::string &code) { return table_name + auth_name + code; };
+
for (const auto &row : resultSet) {
- // table1
+ const auto &table1 = row[0];
const auto &auth_name1 = row[1];
const auto &code1 = row[2];
- const auto &deprecated1 = row[3];
- // table2
+ const auto key1 = keyMapSupersession(table1, auth_name1, code1);
+ if (setAlreadyAsked.find(key1) == setAlreadyAsked.end()) {
+ setAlreadyAsked.insert(key1);
+ if (!findSupersededFirstWhere)
+ findSupersededSql += " OR ";
+ findSupersededFirstWhere = false;
+ findSupersededSql +=
+ "(superseded_table_name = ? AND replacement_table_name = "
+ "superseded_table_name AND superseded_auth_name = ? AND "
+ "superseded_code = ?)";
+ findSupersededParams.push_back(table1);
+ findSupersededParams.push_back(auth_name1);
+ findSupersededParams.push_back(code1);
+ }
+
+ const auto &table2 = row[4];
const auto &auth_name2 = row[5];
const auto &code2 = row[6];
- const auto &deprecated2 = row[7];
- if (deprecated1 == "1" || deprecated2 == "1") {
- continue;
+ const auto key2 = keyMapSupersession(table2, auth_name2, code2);
+ if (setAlreadyAsked.find(key2) == setAlreadyAsked.end()) {
+ setAlreadyAsked.insert(key2);
+ if (!findSupersededFirstWhere)
+ findSupersededSql += " OR ";
+ findSupersededFirstWhere = false;
+ findSupersededSql +=
+ "(superseded_table_name = ? AND replacement_table_name = "
+ "superseded_table_name AND superseded_auth_name = ? AND "
+ "superseded_code = ?)";
+ findSupersededParams.push_back(table2);
+ findSupersededParams.push_back(auth_name2);
+ findSupersededParams.push_back(code2);
}
- setTransf1.insert(
+
+ setTransf.insert(
std::pair<std::string, std::string>(auth_name1, code1));
- setTransf2.insert(
+ setTransf.insert(
std::pair<std::string, std::string>(auth_name2, code2));
}
+
+ std::map<std::string, std::vector<std::pair<std::string, std::string>>>
+ mapSupersession;
+
+ if (!findSupersededParams.empty()) {
+ const auto resSuperseded =
+ d->run(findSupersededSql, findSupersededParams);
+ for (const auto &row : resSuperseded) {
+ const auto &superseded_table_name = row[0];
+ const auto &superseded_auth_name = row[1];
+ const auto &superseded_code = row[2];
+ const auto &replacement_auth_name = row[3];
+ const auto &replacement_code = row[4];
+ mapSupersession[keyMapSupersession(superseded_table_name,
+ superseded_auth_name,
+ superseded_code)]
+ .push_back(std::pair<std::string, std::string>(
+ replacement_auth_name, replacement_code));
+ }
+ }
+
SQLResultSet filteredResultSet;
for (const auto &row : resultSet) {
- const auto &replacement_auth_name1 = row[16];
- const auto &replacement_code1 = row[17];
- const auto &replacement_auth_name2 = row[18];
- const auto &replacement_code2 = row[19];
- if (!replacement_auth_name1.empty() &&
- setTransf1.find(std::pair<std::string, std::string>(
- replacement_auth_name1, replacement_code1)) !=
- setTransf1.end()) {
- // Skip transformations that are superseded by others that got
- // returned in the result set.
- continue;
+ const auto &table1 = row[0];
+ const auto &auth_name1 = row[1];
+ const auto &code1 = row[2];
+ const auto &table2 = row[4];
+ const auto &auth_name2 = row[5];
+ const auto &code2 = row[6];
+
+ auto iter1 = mapSupersession.find(
+ keyMapSupersession(table1, auth_name1, code1));
+ if (iter1 != mapSupersession.end()) {
+ bool foundReplacement = false;
+ for (const auto &replacement : iter1->second) {
+ const auto &replacement_auth_name = replacement.first;
+ const auto &replacement_code = replacement.second;
+ if (setTransf.find(std::pair<std::string, std::string>(
+ replacement_auth_name, replacement_code)) !=
+ setTransf.end()) {
+ // Skip transformations that are superseded by others
+ // that got
+ // returned in the result set.
+ foundReplacement = true;
+ break;
+ }
+ }
+ if (foundReplacement) {
+ continue;
+ }
}
- if (!replacement_auth_name2.empty() &&
- setTransf2.find(std::pair<std::string, std::string>(
- replacement_auth_name2, replacement_code2)) !=
- setTransf2.end()) {
- // Skip transformations that are superseded by others that got
- // returned in the result set.
- continue;
+
+ auto iter2 = mapSupersession.find(
+ keyMapSupersession(table2, auth_name2, code2));
+ if (iter2 != mapSupersession.end()) {
+ bool foundReplacement = false;
+ for (const auto &replacement : iter2->second) {
+ const auto &replacement_auth_name = replacement.first;
+ const auto &replacement_code = replacement.second;
+ if (setTransf.find(std::pair<std::string, std::string>(
+ replacement_auth_name, replacement_code)) !=
+ setTransf.end()) {
+ // Skip transformations that are superseded by others
+ // that got
+ // returned in the result set.
+ foundReplacement = true;
+ break;
+ }
+ }
+ if (foundReplacement) {
+ continue;
+ }
}
+
filteredResultSet.emplace_back(row);
}
return filteredResultSet;
};
+ res = filterDeprecatedAndNotMatchingAuth(std::move(res));
if (discardSuperseded) {
res = filterOutSuperseded(std::move(res));
}
@@ -4535,14 +4654,10 @@ AuthorityFactory::createBetweenGeodeticCRSWithDatumBasedIntermediates(
const auto &table1 = row[0];
const auto &auth_name1 = row[1];
const auto &code1 = row[2];
- const auto &deprecated1 = row[3];
const auto &table2 = row[4];
const auto &auth_name2 = row[5];
const auto &code2 = row[6];
- const auto &deprecated2 = row[7];
- if (deprecated1 == "1" || deprecated2 == "1") {
- continue;
- }
+
auto op1 = d->createFactory(auth_name1)
->createCoordinateOperation(
code1, true, usePROJAlternativeGridNames, table1);
@@ -4623,6 +4738,8 @@ AuthorityFactory::createBetweenGeodeticCRSWithDatumBasedIntermediates(
// fprintf(stderr, "before %s\n", (sql + additionalWhere).c_str());
res = d->run(sql + additionalWhere, params);
// fprintf(stderr, "after\n");
+
+ res = filterDeprecatedAndNotMatchingAuth(std::move(res));
if (discardSuperseded) {
res = filterOutSuperseded(std::move(res));
}
@@ -4630,14 +4747,10 @@ AuthorityFactory::createBetweenGeodeticCRSWithDatumBasedIntermediates(
const auto &table1 = row[0];
const auto &auth_name1 = row[1];
const auto &code1 = row[2];
- const auto &deprecated1 = row[3];
const auto &table2 = row[4];
const auto &auth_name2 = row[5];
const auto &code2 = row[6];
- const auto &deprecated2 = row[7];
- if (deprecated1 == "1" || deprecated2 == "1") {
- continue;
- }
+
auto op1 = d->createFactory(auth_name1)
->createCoordinateOperation(
code1, true, usePROJAlternativeGridNames, table1);
@@ -4718,6 +4831,8 @@ AuthorityFactory::createBetweenGeodeticCRSWithDatumBasedIntermediates(
// fprintf(stderr, "before %s\n", (sql + additionalWhere).c_str());
res = d->run(sql + additionalWhere, params);
// fprintf(stderr, "after\n");
+
+ res = filterDeprecatedAndNotMatchingAuth(std::move(res));
if (discardSuperseded) {
res = filterOutSuperseded(std::move(res));
}
@@ -4725,14 +4840,10 @@ AuthorityFactory::createBetweenGeodeticCRSWithDatumBasedIntermediates(
const auto &table1 = row[0];
const auto &auth_name1 = row[1];
const auto &code1 = row[2];
- const auto &deprecated1 = row[3];
const auto &table2 = row[4];
const auto &auth_name2 = row[5];
const auto &code2 = row[6];
- const auto &deprecated2 = row[7];
- if (deprecated1 == "1" || deprecated2 == "1") {
- continue;
- }
+
auto op1 = d->createFactory(auth_name1)
->createCoordinateOperation(
code1, true, usePROJAlternativeGridNames, table1);
@@ -4813,6 +4924,8 @@ AuthorityFactory::createBetweenGeodeticCRSWithDatumBasedIntermediates(
// fprintf(stderr, "before %s\n", (sql + additionalWhere).c_str());
res = d->run(sql + additionalWhere, params);
// fprintf(stderr, "after\n");
+
+ res = filterDeprecatedAndNotMatchingAuth(std::move(res));
if (discardSuperseded) {
res = filterOutSuperseded(std::move(res));
}
@@ -4820,14 +4933,10 @@ AuthorityFactory::createBetweenGeodeticCRSWithDatumBasedIntermediates(
const auto &table1 = row[0];
const auto &auth_name1 = row[1];
const auto &code1 = row[2];
- const auto &deprecated1 = row[3];
const auto &table2 = row[4];
const auto &auth_name2 = row[5];
const auto &code2 = row[6];
- const auto &deprecated2 = row[7];
- if (deprecated1 == "1" || deprecated2 == "1") {
- continue;
- }
+
auto op1 = d->createFactory(auth_name1)
->createCoordinateOperation(
code1, true, usePROJAlternativeGridNames, table1);
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index 7a3cba6b..9d463091 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -1997,65 +1997,20 @@ GeodeticReferenceFrameNNPtr WKTParser::Private::buildGeodeticReferenceFrame(
// do that before buildEllipsoid() so that esriStyle_ can be set
auto name = stripQuotes(nodeP->children()[0]);
- if (name == "WGS_1984") {
- properties.set(IdentifiedObject::NAME_KEY,
- GeodeticReferenceFrame::EPSG_6326->nameStr());
- } else if (starts_with(name, "D_")) {
- esriStyle_ = true;
- const char *tableNameForAlias = nullptr;
- std::string authNameFromAlias;
- std::string codeFromAlias;
- if (name == "D_WGS_1984") {
- name = "World Geodetic System 1984";
- authNameFromAlias = Identifier::EPSG;
- codeFromAlias = "6326";
- } else {
- tableNameForAlias = "geodetic_datum";
- }
-
- if (dbContext_ && tableNameForAlias) {
- std::string outTableName;
- auto authFactory = AuthorityFactory::create(NN_NO_CHECK(dbContext_),
- std::string());
- auto officialName = authFactory->getOfficialNameFromAlias(
- name, tableNameForAlias, "ESRI", false, outTableName,
- authNameFromAlias, codeFromAlias);
- if (!officialName.empty()) {
- if (primeMeridian->nameStr() !=
- PrimeMeridian::GREENWICH->nameStr()) {
- auto nameWithPM =
- officialName + " (" + primeMeridian->nameStr() + ")";
- if (dbContext_->isKnownName(nameWithPM, "geodetic_datum")) {
- officialName = nameWithPM;
- }
- }
- name = officialName;
- }
- }
- properties.set(IdentifiedObject::NAME_KEY, name);
- if (!authNameFromAlias.empty()) {
- auto identifiers = ArrayOfBaseObject::create();
- identifiers->add(Identifier::create(
- codeFromAlias,
- PropertyMap()
- .set(Identifier::CODESPACE_KEY, authNameFromAlias)
- .set(Identifier::AUTHORITY_KEY, authNameFromAlias)));
- properties.set(IdentifiedObject::IDENTIFIERS_KEY, identifiers);
- }
- } else if (name.find('_') != std::string::npos) {
- // Likely coming from WKT1
+ const auto identifyFromName = [&](const std::string &l_name) {
+ bool foundDatumName = false;
if (dbContext_) {
auto authFactory = AuthorityFactory::create(NN_NO_CHECK(dbContext_),
std::string());
auto res = authFactory->createObjectsFromName(
- name, {AuthorityFactory::ObjectType::GEODETIC_REFERENCE_FRAME},
- true, 1);
- bool foundDatumName = false;
+ l_name,
+ {AuthorityFactory::ObjectType::GEODETIC_REFERENCE_FRAME}, true,
+ 1);
if (!res.empty()) {
const auto &refDatum = res.front();
if (metadata::Identifier::isEquivalentName(
- name.c_str(), refDatum->nameStr().c_str())) {
+ l_name.c_str(), refDatum->nameStr().c_str())) {
foundDatumName = true;
properties.set(IdentifiedObject::NAME_KEY,
refDatum->nameStr());
@@ -2096,13 +2051,76 @@ GeodeticReferenceFrameNNPtr WKTParser::Private::buildGeodeticReferenceFrame(
std::string authNameFromAlias;
std::string codeFromAlias;
auto officialName = authFactory->getOfficialNameFromAlias(
- name, "geodetic_datum", std::string(), true, outTableName,
+ l_name, "geodetic_datum", std::string(), true, outTableName,
authNameFromAlias, codeFromAlias);
if (!officialName.empty()) {
+ foundDatumName = true;
properties.set(IdentifiedObject::NAME_KEY, officialName);
}
}
}
+ return foundDatumName;
+ };
+
+ if (name == "WGS_1984") {
+ properties.set(IdentifiedObject::NAME_KEY,
+ GeodeticReferenceFrame::EPSG_6326->nameStr());
+ } else if (starts_with(name, "D_")) {
+ esriStyle_ = true;
+ const char *tableNameForAlias = nullptr;
+ std::string authNameFromAlias;
+ std::string codeFromAlias;
+ if (name == "D_WGS_1984") {
+ name = "World Geodetic System 1984";
+ authNameFromAlias = Identifier::EPSG;
+ codeFromAlias = "6326";
+ } else {
+ tableNameForAlias = "geodetic_datum";
+ }
+
+ bool setNameAndId = true;
+ if (dbContext_ && tableNameForAlias) {
+ std::string outTableName;
+ auto authFactory = AuthorityFactory::create(NN_NO_CHECK(dbContext_),
+ std::string());
+ auto officialName = authFactory->getOfficialNameFromAlias(
+ name, tableNameForAlias, "ESRI", false, outTableName,
+ authNameFromAlias, codeFromAlias);
+ if (officialName.empty()) {
+ // For the case of "D_GDA2020" where there is no D_GDA2020 ESRI
+ // alias, so just try without the D_ prefix.
+ const auto nameWithoutDPrefix = name.substr(2);
+ if (identifyFromName(nameWithoutDPrefix)) {
+ setNameAndId = false; // already done in identifyFromName()
+ }
+ } else {
+ if (primeMeridian->nameStr() !=
+ PrimeMeridian::GREENWICH->nameStr()) {
+ auto nameWithPM =
+ officialName + " (" + primeMeridian->nameStr() + ")";
+ if (dbContext_->isKnownName(nameWithPM, "geodetic_datum")) {
+ officialName = nameWithPM;
+ }
+ }
+ name = officialName;
+ }
+ }
+
+ if (setNameAndId) {
+ properties.set(IdentifiedObject::NAME_KEY, name);
+ if (!authNameFromAlias.empty()) {
+ auto identifiers = ArrayOfBaseObject::create();
+ identifiers->add(Identifier::create(
+ codeFromAlias,
+ PropertyMap()
+ .set(Identifier::CODESPACE_KEY, authNameFromAlias)
+ .set(Identifier::AUTHORITY_KEY, authNameFromAlias)));
+ properties.set(IdentifiedObject::IDENTIFIERS_KEY, identifiers);
+ }
+ }
+ } else if (name.find('_') != std::string::npos) {
+ // Likely coming from WKT1
+ identifyFromName(name);
}
auto ellipsoid = buildEllipsoid(ellipsoidNode);
@@ -8734,22 +8752,43 @@ CRSNNPtr PROJStringParser::Private::buildProjectedCRS(
} else if (param->unit_type == UnitOfMeasure::Type::SCALE) {
value = 1;
- } else {
- // For omerc, if gamma is missing, the default value is
- // alpha
- if (step.name == "omerc" && proj_name == "gamma") {
- paramValue = &getParamValue(step, "alpha");
- if (!paramValue->empty()) {
- value = getAngularValue(*paramValue);
+ }
+ // For omerc, if gamma is missing, the default value is
+ // alpha
+ else if (step.name == "omerc" && proj_name == "gamma") {
+ paramValue = &getParamValue(step, "alpha");
+ if (!paramValue->empty()) {
+ value = getAngularValue(*paramValue);
+ }
+ } else if (step.name == "krovak") {
+ if (param->epsg_code ==
+ EPSG_CODE_PARAMETER_COLATITUDE_CONE_AXIS) {
+ value = 30.28813975277777776;
+ } else if (
+ param->epsg_code ==
+ EPSG_CODE_PARAMETER_LATITUDE_PSEUDO_STANDARD_PARALLEL) {
+ value = 78.5;
+ }
+ } else if (step.name == "cea" && proj_name == "lat_ts") {
+ paramValue = &getParamValueK(step);
+ if (!paramValue->empty()) {
+ bool hasError = false;
+ const double k = getNumericValue(*paramValue, &hasError);
+ if (hasError) {
+ throw ParsingException("invalid value for k/k_0");
}
- } else if (step.name == "krovak") {
- if (param->epsg_code ==
- EPSG_CODE_PARAMETER_COLATITUDE_CONE_AXIS) {
- value = 30.28813975277777776;
- } else if (
- param->epsg_code ==
- EPSG_CODE_PARAMETER_LATITUDE_PSEUDO_STANDARD_PARALLEL) {
- value = 78.5;
+ if (k >= 0 && k <= 1) {
+ const double es =
+ geogCRS->ellipsoid()->squaredEccentricity();
+ if (es < 0) {
+ throw ParsingException("Invalid flattening");
+ }
+ value =
+ Angle(acos(k * sqrt((1 - es) / (1 - k * k * es))),
+ UnitOfMeasure::RADIAN)
+ .convertToUnit(UnitOfMeasure::DEGREE);
+ } else {
+ throw ParsingException("k/k_0 should be in [0,1]");
}
}
}