Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a new peer-reviewed authority #4190

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion data/sql/commit.sql
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ FOR EACH ROW BEGIN
-- check that the auth_name of all objects in object_view is recorded in builtin_authorities
SELECT RAISE(ABORT, 'One or several authorities referenced in object_view are missing in builtin_authorities')
WHERE EXISTS (
SELECT DISTINCT o.auth_name FROM object_view o WHERE NOT EXISTS (
SELECT DISTINCT o.auth_name FROM object_view o WHERE o.auth_name != 'IDNK' AND NOT EXISTS (
SELECT 1 FROM builtin_authorities b WHERE o.auth_name = b.auth_name)
);

Expand Down
59 changes: 59 additions & 0 deletions data/sql/idnk.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
-- Self-appointed authority, originating from https://talks.osgeo.org/media/foss4g-europe-2024/submissions/B8CETX/resources/WGS_84_I_dont_know_I_dont_care_pTbpl9n.pdf

-- Geodetic CRS

INSERT INTO "geodetic_datum" VALUES('IDNK','DATUM','Unknown geodetic datum','Datum to be used when the actual datum is unknown, instead of misusing WGS84','EPSG','7019','EPSG','8901',NULL,NULL,NULL,NULL,NULL,0);
INSERT INTO "usage" VALUES('IDNK','DATUM_USAGE','geodetic_datum','IDNK','DATUM','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');

INSERT INTO "geodetic_crs" VALUES('IDNK','GEOGRAPHIC','Unknown geographic 2D CRS','Geographic CRS to be used when the actual datum is unknown, instead of misusing WGS84','geographic 2D','EPSG','6424','IDNK','DATUM',NULL,0);
INSERT INTO "usage" VALUES(
'IDNK',
'GEOGRAPHIC_USAGE',
'geodetic_crs',
'IDNK',
'GEOGRAPHIC',
'PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');

INSERT INTO "geodetic_crs" VALUES('IDNK','GEOGRAPHIC_3D','Unknown geographic 3D CRS','Geographic 3D CRS to be used when the actual datum is unknown, instead of misusing WGS84','geographic 3D','EPSG','6423','IDNK','DATUM',NULL,0);
INSERT INTO "usage" VALUES(
'IDNK',
'GEOGRAPHIC_3D_USAGE',
'geodetic_crs',
'IDNK',
'GEOGRAPHIC_3D',
'PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');

INSERT INTO "geodetic_crs" VALUES('IDNK','GEOCENTRIC','Unknown geocentric CRS','Geocentric CRS to be used when the actual datum is unknown, instead of misusing WGS84','geocentric','EPSG','6500','IDNK','DATUM',NULL,0);
INSERT INTO "usage" VALUES(
'IDNK',
'GEOCENTRIC_USAGE',
'geodetic_crs',
'IDNK',
'GEOCENTRIC',
'PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');

-- UTM zones

WITH RECURSIVE zone_counter (zone)
AS (SELECT 1 UNION ALL SELECT zone+1 AS new_zone FROM zone_counter WHERE new_zone <= 60)
INSERT INTO "projected_crs" SELECT 'IDNK','UTM_' || zone || 'N','Unknown / UTM zone ' || zone || 'N','UTM based CRS to be used when the actual datum is unknown, instead of misusing WGS84','EPSG','4400','IDNK','GEOGRAPHIC','EPSG',16000+zone,NULL,0 FROM zone_counter;

WITH RECURSIVE zone_counter (zone)
AS (SELECT 1 UNION ALL SELECT zone+1 AS new_zone FROM zone_counter WHERE new_zone <= 60)
INSERT INTO "usage" SELECT 'IDNK','UTM_' || zone || 'N_USAGE','projected_crs','IDNK','UTM_' || zone || 'N','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN' FROM zone_counter;

WITH RECURSIVE zone_counter (zone)
AS (SELECT 1 UNION ALL SELECT zone+1 AS new_zone FROM zone_counter WHERE new_zone <= 60)
INSERT INTO "projected_crs" SELECT 'IDNK','UTM_' || zone || 'S','Unknown / UTM zone ' || zone || 'S','UTM based CRS to be used when the actual datum is unknown, instead of misusing WGS84','EPSG','4400','IDNK','GEOGRAPHIC','EPSG',16100+zone,NULL,0 FROM zone_counter;

WITH RECURSIVE zone_counter (zone)
AS (SELECT 1 UNION ALL SELECT zone+1 AS new_zone FROM zone_counter WHERE new_zone <= 60)
INSERT INTO "usage" SELECT 'IDNK','UTM_' || zone || 'S_USAGE','projected_crs','IDNK','UTM_' || zone || 'S','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN' FROM zone_counter;

-- Vertical CRS

INSERT INTO "vertical_datum" VALUES('IDNK','VERTICAL_DATUM','Unknown vertical datum',NULL,NULL,NULL,NULL,NULL,NULL,0);
INSERT INTO "usage" VALUES('IDNK','VERTICAL_DATUM_USAGE','vertical_datum','IDNK','VERTICAL_DATUM','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');

INSERT INTO "vertical_crs" VALUES('IDNK','VERTICAL','Unknown vertical CRS',NULL,'EPSG','6499','IDNK','VERTICAL_DATUM',0);
INSERT INTO "usage" VALUES('IDNK','VERTICAL','vertical_crs','IDNK','VERTICAL','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');
1 change: 1 addition & 0 deletions data/sql_filelist.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ set(SQL_FILES
"${SQL_DIR}/supersession.sql"
"${SQL_DIR}/deprecation.sql"
"${SQL_DIR}/esri.sql"
"${SQL_DIR}/idnk.sql"
"${SQL_DIR}/ignf.sql"
"${SQL_DIR}/nkg.sql"
"${SQL_DIR}/iau.sql"
Expand Down
39 changes: 22 additions & 17 deletions src/iso19111/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2927,7 +2927,8 @@ DatabaseContext::create(const std::string &databasePath,
/** \brief Return the list of authorities used in the database.
*/
std::set<std::string> DatabaseContext::getAuthorities() const {
auto res = d->run("SELECT auth_name FROM authority_list");
auto res = d->run("SELECT auth_name FROM authority_list "
"WHERE auth_name != 'IDNK'");
std::set<std::string> list;
for (const auto &row : res) {
list.insert(row[0]);
Expand Down Expand Up @@ -8399,10 +8400,17 @@ std::list<AuthorityFactory::CRSInfo> AuthorityFactory::getCRSInfoList() const {
sql += getSqlArea("geodetic_crs");
sql += getJoinCelestialBody("c");
ListOfParams params;
if (d->hasAuthorityRestriction()) {
sql += "WHERE c.auth_name = ? ";
params.emplace_back(d->authority());
}

const auto addAuthorityRestriction = [this, &params, &sql]() {
if (d->hasAuthorityRestriction()) {
sql += "WHERE c.auth_name = ? ";
params.emplace_back(d->authority());
} else {
sql += "WHERE c.auth_name != 'IDNK' ";
}
};
addAuthorityRestriction();

sql += "UNION ALL SELECT c.auth_name, c.code, c.name, 'projected', "
"c.deprecated, "
"a.west_lon, a.south_lat, a.east_lon, a.north_lat, "
Expand All @@ -8419,30 +8427,21 @@ std::list<AuthorityFactory::CRSInfo> AuthorityFactory::getCRSInfoList() const {
"AND gcrs.code = c.geodetic_crs_code ";
sql += getSqlArea("projected_crs");
sql += getJoinCelestialBody("gcrs");
if (d->hasAuthorityRestriction()) {
sql += "WHERE c.auth_name = ? ";
params.emplace_back(d->authority());
}
addAuthorityRestriction();
// FIXME: we can't handle non-EARTH vertical CRS for now
sql += "UNION ALL SELECT c.auth_name, c.code, c.name, 'vertical', "
"c.deprecated, "
"a.west_lon, a.south_lat, a.east_lon, a.north_lat, "
"a.description, NULL, 'Earth' FROM vertical_crs c ";
sql += getSqlArea("vertical_crs");
if (d->hasAuthorityRestriction()) {
sql += "WHERE c.auth_name = ? ";
params.emplace_back(d->authority());
}
addAuthorityRestriction();
// FIXME: we can't handle non-EARTH compound CRS for now
sql += "UNION ALL SELECT c.auth_name, c.code, c.name, 'compound', "
"c.deprecated, "
"a.west_lon, a.south_lat, a.east_lon, a.north_lat, "
"a.description, NULL, 'Earth' FROM compound_crs c ";
sql += getSqlArea("compound_crs");
if (d->hasAuthorityRestriction()) {
sql += "WHERE c.auth_name = ? ";
params.emplace_back(d->authority());
}
addAuthorityRestriction();
sql += ") r ORDER BY auth_name, code";
auto sqlRes = d->run(sql, params);
std::list<AuthorityFactory::CRSInfo> res;
Expand Down Expand Up @@ -9412,6 +9411,8 @@ AuthorityFactory::createGeodeticCRSFromEllipsoid(
if (d->hasAuthorityRestriction()) {
sql += " AND geodetic_crs.auth_name = ?";
params.emplace_back(d->authority());
} else {
sql += " AND geodetic_crs.auth_name != 'IDNK'";
}
if (!geodetic_crs_type.empty()) {
sql += " AND geodetic_crs.type = ?";
Expand Down Expand Up @@ -9537,6 +9538,8 @@ AuthorityFactory::createProjectedCRSFromExisting(
if (d->hasAuthorityRestriction()) {
sql += " AND projected_crs.auth_name = ?";
params.emplace_back(d->authority());
} else {
sql += " AND projected_crs.auth_name!= 'IDNK'";
}

int iParam = 0;
Expand Down Expand Up @@ -9768,6 +9771,8 @@ AuthorityFactory::createProjectedCRSFromExisting(
if (d->hasAuthorityRestriction()) {
sql += " AND auth_name = ?";
params.emplace_back(d->authority());
} else {
sql += " AND auth_name != 'IDNK'";
}

auto sqlRes2 = d->run(sql, params);
Expand Down
3 changes: 3 additions & 0 deletions test/unit/test_c_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4008,6 +4008,9 @@ TEST_F(CApi, proj_get_crs_info_list_from_database) {
EXPECT_NE(list[0]->auth_name, nullptr);
EXPECT_NE(list[0]->code, nullptr);
EXPECT_NE(list[0]->name, nullptr);
for (int i = 0; list[i] != nullptr; i++) {
EXPECT_TRUE(std::string(list[i]->auth_name) != "IDNK");
}
proj_crs_info_list_destroy(list);
}

Expand Down
34 changes: 34 additions & 0 deletions test/unit/test_crs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1998,6 +1998,23 @@ TEST(crs, geodeticcrs_identify_db) {
EXPECT_EQ(res.front().first->getEPSGCode(), 4326);
EXPECT_EQ(res.front().second, 70.0);
}
{
// Test that IDNK authority doesn't popup in results
auto obj = PROJStringParser()
.attachDatabaseContext(dbContext)
.createFromPROJString(
"+proj=longlat +ellps=GRS80 +no_defs +type=crs");
auto crs = nn_dynamic_pointer_cast<GeodeticCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto allFactory = AuthorityFactory::create(dbContext, std::string());
auto res = crs->identify(allFactory);
EXPECT_GE(res.size(), 1U);
for (const auto &match : res) {
const auto &ids = match.first->identifiers();
ASSERT_TRUE(!ids.empty());
EXPECT_TRUE(*(ids[0]->codeSpace()) != "IDNK");
}
}
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -3468,6 +3485,23 @@ TEST(crs, projectedCRS_identify_db) {
"IAU_2015");
EXPECT_EQ(res.front().second, 90);
}
{
// Test that IDNK authority doesn't popup in results
auto obj = PROJStringParser()
.attachDatabaseContext(dbContext)
.createFromPROJString("+proj=utm +zone=31 +ellps=GRS80 "
"+units=m +no_defs +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto allFactory = AuthorityFactory::create(dbContext, std::string());
auto res = crs->identify(allFactory);
EXPECT_GE(res.size(), 1U);
for (const auto &match : res) {
const auto &ids = match.first->identifiers();
ASSERT_TRUE(!ids.empty());
EXPECT_TRUE(*(ids[0]->codeSpace()) != "IDNK");
}
}
}

// ---------------------------------------------------------------------------
Expand Down