aboutsummaryrefslogtreecommitdiff
path: root/test/unit/test_metadata.cpp
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2018-11-14 17:40:42 +0100
committerEven Rouault <even.rouault@spatialys.com>2018-11-14 22:48:29 +0100
commitd928db15d53805d9b728b440079756081961c536 (patch)
treee862a961d26bedb34c58e4f28ef0bdeedb5f3225 /test/unit/test_metadata.cpp
parent330e8bf686f9c4524075ca1ff50cbca6c9e091da (diff)
downloadPROJ-d928db15d53805d9b728b440079756081961c536.tar.gz
PROJ-d928db15d53805d9b728b440079756081961c536.zip
Implement RFC 2: Initial integration of "GDAL SRS barn" work
This work mostly consists of: - a C++ implementation of the ISO-19111:2018 / OGC Topic 2 "Referencing by coordinates" classes to represent Datums, Coordinate systems, CRSs (Coordinate Reference Systems) and Coordinate Operations. - methods to convert between this C++ modeling and WKT1, WKT2 and PROJ string representations of those objects - management and query of a SQLite3 database of CRS and Coordinate Operation definition - a C API binding part of those capabilities This is all-in-one squashed commit of the work of https://github.com/OSGeo/proj.4/pull/1040
Diffstat (limited to 'test/unit/test_metadata.cpp')
-rw-r--r--test/unit/test_metadata.cpp388
1 files changed, 388 insertions, 0 deletions
diff --git a/test/unit/test_metadata.cpp b/test/unit/test_metadata.cpp
new file mode 100644
index 00000000..96b8cbff
--- /dev/null
+++ b/test/unit/test_metadata.cpp
@@ -0,0 +1,388 @@
+/******************************************************************************
+ *
+ * Project: PROJ
+ * Purpose: Test ISO19111:2018 implementation
+ * Author: Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gtest_include.h"
+
+#include "proj/io.hpp"
+#include "proj/metadata.hpp"
+#include "proj/util.hpp"
+
+using namespace osgeo::proj::io;
+using namespace osgeo::proj::metadata;
+using namespace osgeo::proj::util;
+
+// ---------------------------------------------------------------------------
+
+TEST(metadata, citation) {
+ Citation c("my citation");
+ Citation c2(c);
+ ASSERT_TRUE(c2.title().has_value());
+ ASSERT_EQ(*(c2.title()), "my citation");
+}
+
+// ---------------------------------------------------------------------------
+
+static bool equals(ExtentNNPtr extent1, ExtentNNPtr extent2) {
+ return extent1->contains(extent2) && extent2->contains(extent1);
+}
+
+static bool equals(GeographicExtentNNPtr extent1,
+ GeographicExtentNNPtr extent2) {
+ return extent1->contains(extent2) && extent2->contains(extent1);
+}
+
+static GeographicExtentNNPtr getBBox(ExtentNNPtr extent) {
+ assert(extent->geographicElements().size() == 1);
+ return extent->geographicElements()[0];
+}
+
+TEST(metadata, extent) {
+ Extent::create(
+ optional<std::string>(), std::vector<GeographicExtentNNPtr>(),
+ std::vector<VerticalExtentNNPtr>(), std::vector<TemporalExtentNNPtr>());
+
+ auto world = Extent::createFromBBOX(-180, -90, 180, 90);
+ EXPECT_TRUE(world->isEquivalentTo(world.get()));
+ EXPECT_TRUE(world->contains(world));
+
+ auto west_hemisphere = Extent::createFromBBOX(-180, -90, 0, 90);
+ EXPECT_TRUE(!world->isEquivalentTo(west_hemisphere.get()));
+ EXPECT_TRUE(world->contains(west_hemisphere));
+ EXPECT_TRUE(!west_hemisphere->contains(world));
+
+ auto world_inter_world = world->intersection(world);
+ ASSERT_TRUE(world_inter_world != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(world_inter_world), world));
+
+ auto france = Extent::createFromBBOX(-5, 40, 12, 51);
+ EXPECT_TRUE(france->contains(france));
+ EXPECT_TRUE(world->contains(france));
+ EXPECT_TRUE(!france->contains(
+ world)); // We are only speaking about geography here ;-)
+ EXPECT_TRUE(world->intersects(france));
+ EXPECT_TRUE(france->intersects(world));
+
+ auto france_inter_france = france->intersection(france);
+ ASSERT_TRUE(france_inter_france != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(france_inter_france), france));
+
+ auto france_inter_world = france->intersection(world);
+ ASSERT_TRUE(france_inter_world != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(france_inter_world), france));
+
+ auto world_inter_france = world->intersection(france);
+ ASSERT_TRUE(world_inter_france != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(world_inter_france), france));
+
+ auto france_shifted =
+ Extent::createFromBBOX(-5 + 5, 40 + 5, 12 + 5, 51 + 5);
+ EXPECT_TRUE(france->intersects(france_shifted));
+ EXPECT_TRUE(france_shifted->intersects(france));
+ EXPECT_TRUE(!france->contains(france_shifted));
+ EXPECT_TRUE(!france_shifted->contains(france));
+
+ auto europe = Extent::createFromBBOX(-30, 25, 30, 70);
+ EXPECT_TRUE(europe->contains(france));
+ EXPECT_TRUE(!france->contains(europe));
+
+ auto france_inter_europe = france->intersection(europe);
+ ASSERT_TRUE(france_inter_europe != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(france_inter_europe), france));
+
+ auto europe_intersects_france = europe->intersection(france);
+ ASSERT_TRUE(europe_intersects_france != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(europe_intersects_france), france));
+
+ auto nz = Extent::createFromBBOX(155.0, -60.0, -170.0, -25.0);
+ EXPECT_TRUE(nz->contains(nz));
+ EXPECT_TRUE(world->contains(nz));
+ EXPECT_TRUE(nz->intersects(world));
+ EXPECT_TRUE(world->intersects(nz));
+ EXPECT_TRUE(!nz->contains(world));
+ EXPECT_TRUE(!nz->contains(france));
+ EXPECT_TRUE(!france->contains(nz));
+ EXPECT_TRUE(!nz->intersects(france));
+ EXPECT_TRUE(!france->intersects(nz));
+
+ {
+ auto nz_inter_world = nz->intersection(world);
+ ASSERT_TRUE(nz_inter_world != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(nz_inter_world), nz));
+ }
+
+ {
+ auto nz_inter_world = getBBox(nz)->intersection(getBBox(world));
+ ASSERT_TRUE(nz_inter_world != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(nz_inter_world), getBBox(nz)));
+ }
+
+ {
+ auto world_inter_nz = world->intersection(nz);
+ ASSERT_TRUE(world_inter_nz != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(world_inter_nz), nz));
+ }
+
+ {
+ auto world_inter_nz = getBBox(world)->intersection(getBBox(nz));
+ ASSERT_TRUE(world_inter_nz != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(world_inter_nz), getBBox(nz)));
+ }
+
+ EXPECT_TRUE(nz->intersection(france) == nullptr);
+ EXPECT_TRUE(france->intersection(nz) == nullptr);
+
+ auto bbox_antimeridian_north =
+ Extent::createFromBBOX(155.0, 10.0, -170.0, 30.0);
+ EXPECT_TRUE(!nz->contains(bbox_antimeridian_north));
+ EXPECT_TRUE(!bbox_antimeridian_north->contains(nz));
+ EXPECT_TRUE(!nz->intersects(bbox_antimeridian_north));
+ EXPECT_TRUE(!bbox_antimeridian_north->intersects(nz));
+ EXPECT_TRUE(!nz->intersection(bbox_antimeridian_north));
+ EXPECT_TRUE(!bbox_antimeridian_north->intersection(nz));
+
+ auto nz_pos_long = Extent::createFromBBOX(155.0, -60.0, 180.0, -25.0);
+ EXPECT_TRUE(nz->contains(nz_pos_long));
+ EXPECT_TRUE(!nz_pos_long->contains(nz));
+ EXPECT_TRUE(nz->intersects(nz_pos_long));
+ EXPECT_TRUE(nz_pos_long->intersects(nz));
+ auto nz_inter_nz_pos_long = nz->intersection(nz_pos_long);
+ ASSERT_TRUE(nz_inter_nz_pos_long != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(nz_inter_nz_pos_long), nz_pos_long));
+ auto nz_pos_long_inter_nz = nz_pos_long->intersection(nz);
+ ASSERT_TRUE(nz_pos_long_inter_nz != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(nz_pos_long_inter_nz), nz_pos_long));
+
+ auto nz_neg_long = Extent::createFromBBOX(-180.0, -60.0, -170.0, -25.0);
+ EXPECT_TRUE(nz->contains(nz_neg_long));
+ EXPECT_TRUE(!nz_neg_long->contains(nz));
+ EXPECT_TRUE(nz->intersects(nz_neg_long));
+ EXPECT_TRUE(nz_neg_long->intersects(nz));
+ auto nz_inter_nz_neg_long = nz->intersection(nz_neg_long);
+ ASSERT_TRUE(nz_inter_nz_neg_long != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(nz_inter_nz_neg_long), nz_neg_long));
+ auto nz_neg_long_inter_nz = nz_neg_long->intersection(nz);
+ ASSERT_TRUE(nz_neg_long_inter_nz != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(nz_neg_long_inter_nz), nz_neg_long));
+
+ auto nz_smaller = Extent::createFromBBOX(160, -55.0, -175.0, -30.0);
+ EXPECT_TRUE(nz->contains(nz_smaller));
+ EXPECT_TRUE(!nz_smaller->contains(nz));
+
+ auto nz_pos_long_shifted_west =
+ Extent::createFromBBOX(150.0, -60.0, 175.0, -25.0);
+ EXPECT_TRUE(!nz->contains(nz_pos_long_shifted_west));
+ EXPECT_TRUE(!nz_pos_long_shifted_west->contains(nz));
+ EXPECT_TRUE(nz->intersects(nz_pos_long_shifted_west));
+ EXPECT_TRUE(nz_pos_long_shifted_west->intersects(nz));
+
+ auto nz_smaller_shifted = Extent::createFromBBOX(165, -60.0, -170.0, -25.0);
+ EXPECT_TRUE(!nz_smaller->contains(nz_smaller_shifted));
+ EXPECT_TRUE(!nz_smaller_shifted->contains(nz_smaller));
+ EXPECT_TRUE(nz_smaller->intersects(nz_smaller_shifted));
+ EXPECT_TRUE(nz_smaller_shifted->intersects(nz_smaller));
+
+ auto nz_shifted = Extent::createFromBBOX(165.0, -60.0, -160.0, -25.0);
+ auto nz_intersect_nz_shifted = nz->intersection(nz_shifted);
+ ASSERT_TRUE(nz_intersect_nz_shifted != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(nz_intersect_nz_shifted),
+ Extent::createFromBBOX(165, -60.0, -170.0, -25.0)));
+
+ auto nz_inter_nz_smaller = nz->intersection(nz_smaller);
+ ASSERT_TRUE(nz_inter_nz_smaller != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(nz_inter_nz_smaller), nz_smaller));
+
+ auto nz_smaller_inter_nz = nz_smaller->intersection(nz);
+ ASSERT_TRUE(nz_smaller_inter_nz != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(nz_smaller_inter_nz), nz_smaller));
+
+ auto world_smaller = Extent::createFromBBOX(-179, -90, 179, 90);
+ EXPECT_TRUE(!world_smaller->contains(nz));
+ EXPECT_TRUE(!nz->contains(world_smaller));
+
+ auto nz_inter_world_smaller = nz->intersection(world_smaller);
+ ASSERT_TRUE(nz_inter_world_smaller != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(nz_inter_world_smaller),
+ Extent::createFromBBOX(155, -60, 179, -25)));
+
+ auto world_smaller_inter_nz = world_smaller->intersection(nz);
+ ASSERT_TRUE(world_smaller_inter_nz != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(world_smaller_inter_nz),
+ Extent::createFromBBOX(155, -60, 179, -25)));
+
+ auto world_smaller_east = Extent::createFromBBOX(-179, -90, 150, 90);
+ EXPECT_TRUE(!world_smaller_east->contains(nz));
+ EXPECT_TRUE(!nz->contains(world_smaller_east));
+
+ auto nz_inter_world_smaller_east = nz->intersection(world_smaller_east);
+ ASSERT_TRUE(nz_inter_world_smaller_east != nullptr);
+ EXPECT_EQ(nn_dynamic_pointer_cast<GeographicBoundingBox>(
+ nz_inter_world_smaller_east->geographicElements()[0])
+ ->westBoundLongitude(),
+ -179);
+ EXPECT_EQ(nn_dynamic_pointer_cast<GeographicBoundingBox>(
+ nz_inter_world_smaller_east->geographicElements()[0])
+ ->eastBoundLongitude(),
+ -170);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(nz_inter_world_smaller_east),
+ Extent::createFromBBOX(-179, -60, -170, -25)));
+
+ auto world_smaller_east_inter_nz = world_smaller_east->intersection(nz);
+ ASSERT_TRUE(world_smaller_east_inter_nz != nullptr);
+ EXPECT_EQ(nn_dynamic_pointer_cast<GeographicBoundingBox>(
+ world_smaller_east_inter_nz->geographicElements()[0])
+ ->westBoundLongitude(),
+ -179);
+ EXPECT_EQ(nn_dynamic_pointer_cast<GeographicBoundingBox>(
+ world_smaller_east_inter_nz->geographicElements()[0])
+ ->eastBoundLongitude(),
+ -170);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(world_smaller_east_inter_nz),
+ Extent::createFromBBOX(-179, -60, -170, -25)));
+
+ auto east_hemisphere = Extent::createFromBBOX(0, -90, 180, 90);
+ auto east_hemisphere_inter_nz = east_hemisphere->intersection(nz);
+ ASSERT_TRUE(east_hemisphere_inter_nz != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(east_hemisphere_inter_nz),
+ Extent::createFromBBOX(155.0, -60.0, 180.0, -25.0)));
+
+ auto minus_180_to_156 = Extent::createFromBBOX(-180, -90, 156, 90);
+ auto minus_180_to_156_inter_nz = minus_180_to_156->intersection(nz);
+ ASSERT_TRUE(minus_180_to_156_inter_nz != nullptr);
+ EXPECT_TRUE(equals(NN_CHECK_ASSERT(minus_180_to_156_inter_nz),
+ Extent::createFromBBOX(-180.0, -60.0, -170.0, -25.0)));
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(metadata, identifier_empty) {
+ auto id(Identifier::create());
+ Identifier id2(*id);
+ ASSERT_TRUE(!id2.authority().has_value());
+ ASSERT_TRUE(id2.code().empty());
+ ASSERT_TRUE(!id2.codeSpace().has_value());
+ ASSERT_TRUE(!id2.version().has_value());
+ ASSERT_TRUE(!id2.description().has_value());
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(metadata, identifier_properties) {
+ PropertyMap properties;
+ properties.set(Identifier::AUTHORITY_KEY, "authority");
+ properties.set(Identifier::CODESPACE_KEY, "codespace");
+ properties.set(Identifier::VERSION_KEY, "version");
+ properties.set(Identifier::DESCRIPTION_KEY, "description");
+ auto id(Identifier::create("my code", properties));
+ Identifier id2(*id);
+ ASSERT_TRUE(id2.authority().has_value());
+ ASSERT_EQ(*(id2.authority()->title()), "authority");
+ ASSERT_EQ(id2.code(), "my code");
+ ASSERT_TRUE(id2.codeSpace().has_value());
+ ASSERT_EQ(*(id2.codeSpace()), "codespace");
+ ASSERT_TRUE(id2.version().has_value());
+ ASSERT_EQ(*(id2.version()), "version");
+ ASSERT_TRUE(id2.description().has_value());
+ ASSERT_EQ(*(id2.description()), "description");
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(metadata, identifier_code_integer) {
+ PropertyMap properties;
+ properties.set(Identifier::CODE_KEY, 1234);
+ auto id(Identifier::create(std::string(), properties));
+ ASSERT_EQ(id->code(), "1234");
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(metadata, identifier_code_string) {
+ PropertyMap properties;
+ properties.set(Identifier::CODE_KEY, "1234");
+ auto id(Identifier::create(std::string(), properties));
+ ASSERT_EQ(id->code(), "1234");
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(metadata, identifier_code_invalid_type) {
+ PropertyMap properties;
+ properties.set(Identifier::CODE_KEY, true);
+ ASSERT_THROW(Identifier::create(std::string(), properties),
+ InvalidValueTypeException);
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(metadata, identifier_authority_citation) {
+ PropertyMap properties;
+ properties.set(Identifier::AUTHORITY_KEY,
+ nn_make_shared<Citation>("authority"));
+ auto id(Identifier::create(std::string(), properties));
+ ASSERT_TRUE(id->authority().has_value());
+ ASSERT_EQ(*(id->authority()->title()), "authority");
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(metadata, identifier_authority_invalid_type) {
+ PropertyMap properties;
+ properties.set(Identifier::AUTHORITY_KEY, true);
+ ASSERT_THROW(Identifier::create(std::string(), properties),
+ InvalidValueTypeException);
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(metadata, id) {
+ auto in_wkt = "ID[\"EPSG\",4946,1.5,\n"
+ " CITATION[\"my citation\"],\n"
+ " URI[\"urn:ogc:def:crs:EPSG::4946\"]]";
+ auto id =
+ nn_dynamic_pointer_cast<Identifier>(WKTParser().createFromWKT(in_wkt));
+ ASSERT_TRUE(id != nullptr);
+
+ EXPECT_TRUE(id->authority().has_value());
+ EXPECT_EQ(*(id->authority()->title()), "my citation");
+ EXPECT_EQ(*(id->codeSpace()), "EPSG");
+ EXPECT_EQ(id->code(), "4946");
+ EXPECT_TRUE(id->version().has_value());
+ EXPECT_EQ(*(id->version()), "1.5");
+ EXPECT_TRUE(id->uri().has_value());
+ EXPECT_EQ(*(id->uri()), "urn:ogc:def:crs:EPSG::4946");
+
+ auto got_wkt = id->exportToWKT(WKTFormatter::create().get());
+ EXPECT_EQ(got_wkt, in_wkt);
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(metadata, Identifier_isEquivalentName) {
+ EXPECT_TRUE(Identifier::isEquivalentName("Central_Meridian",
+ "Central_- ()/Meridian"));
+}