aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/cli/testvarious2
-rw-r--r--test/fuzzers/README.TXT2
-rw-r--r--test/gie/more_builtins.gie2
-rw-r--r--test/unit/test_c_api.cpp6
-rw-r--r--test/unit/test_crs.cpp80
-rw-r--r--test/unit/test_factory.cpp7
-rw-r--r--test/unit/test_io.cpp170
-rw-r--r--test/unit/test_operation.cpp340
8 files changed, 586 insertions, 23 deletions
diff --git a/test/cli/testvarious b/test/cli/testvarious
index 6d773c4c..6a77729e 100755
--- a/test/cli/testvarious
+++ b/test/cli/testvarious
@@ -959,7 +959,7 @@ echo "Test EPSG:4896 to EPSG:7930" >> ${OUT}
# compatibility, the t-component is not written to STDOUT as part of the
# coordinate data, but rather as part of the string that follows the xyz
# components. This is only seen by users when the -E option is used. Which
-# means that this test also experience that behaviour.
+# means that this test also experience that behavior.
$EXE -f %.4f EPSG:4896 EPSG:7930 -E >> ${OUT} <<EOF
3496737.2679 743254.4507 5264462.9620 2019.0
3496737.2679 743254.4507 5264462.9620 2029.0
diff --git a/test/fuzzers/README.TXT b/test/fuzzers/README.TXT
index a43e089f..3482e5cd 100644
--- a/test/fuzzers/README.TXT
+++ b/test/fuzzers/README.TXT
@@ -1,4 +1,4 @@
-This directory contain fuzzer main funtions and scripts for the
+This directory contain fuzzer main functions and scripts for the
Google OSS Fuzz project: https://github.com/google/oss-fuzz/
The main build scripts are in:
diff --git a/test/gie/more_builtins.gie b/test/gie/more_builtins.gie
index 3847c87e..610c6c3f 100644
--- a/test/gie/more_builtins.gie
+++ b/test/gie/more_builtins.gie
@@ -429,7 +429,7 @@ expect failure errno invalid_arg
operation proj=helmert rx=1 convention=1
expect failure errno invalid_arg
-# towgs84 in helmert context should alwas be position_vector
+# towgs84 in helmert context should always be position_vector
operation proj=helmert towgs84=1,2,3,4,5,6,7 convention=coordinate_frame
expect failure errno invalid_arg
diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp
index e56fb39c..e0473d4f 100644
--- a/test/unit/test_c_api.cpp
+++ b/test/unit/test_c_api.cpp
@@ -1497,7 +1497,7 @@ TEST_F(CApi, proj_create_operations_with_pivot) {
// There is no direct transformations between both
- // Default behaviour: allow any pivot
+ // Default behavior: allow any pivot
{
auto ctxt = proj_create_operation_factory_context(m_ctxt, nullptr);
ASSERT_NE(ctxt, nullptr);
@@ -1621,7 +1621,7 @@ TEST_F(CApi, proj_create_operations_allow_ballpark_transformations) {
proj_operation_factory_context_set_grid_availability_use(
m_ctxt, ctxt, PROJ_GRID_AVAILABILITY_IGNORED);
- // Default: allowed implictly
+ // Default: allowed implicitly
{
auto res = proj_create_operations(m_ctxt, source_crs, target_crs, ctxt);
ASSERT_NE(res, nullptr);
@@ -4350,7 +4350,7 @@ TEST_F(
// In this particular case, PROJ computes a transformation from NAD83(2011)
// (EPSG:6318) to WGS84 (EPSG:4979) for the initial horizontal adjustment
// before the geoidgrids application. There are 6 candidate transformations
- // for that in subzones of the US and one last no-op tranformation flagged
+ // for that in subzones of the US and one last no-op transformation flagged
// as ballpark. That one used to be eliminated because by
// proj_create_crs_to_crs() because there were non Ballpark transformations
// available. This resulted thus in an error when transforming outside of
diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp
index 270e7f95..cf285b0a 100644
--- a/test/unit/test_crs.cpp
+++ b/test/unit/test_crs.cpp
@@ -2303,7 +2303,7 @@ TEST(crs, projectedCRS_identify_db) {
auto res = crs->identify(factoryEPSG);
ASSERT_EQ(res.size(), 1U);
EXPECT_EQ(res.front().first->getEPSGCode(), 3044);
- EXPECT_EQ(res.front().second, 25);
+ EXPECT_EQ(res.front().second, 50);
}
{
// Identify from a WKT1 string, without explicit axis
@@ -2397,7 +2397,7 @@ TEST(crs, projectedCRS_identify_db) {
auto res = crs->identify(factoryEPSG);
EXPECT_EQ(res.size(), 1U);
EXPECT_EQ(res.front().first->getEPSGCode(), 2327);
- EXPECT_EQ(res.front().second, 50);
+ EXPECT_EQ(res.front().second, 70);
}
{
// EPSG:6646 as PROJ.4 string, using clrk80 which is pretty generic
@@ -2439,7 +2439,7 @@ TEST(crs, projectedCRS_identify_db) {
for (const auto &pair : res) {
if (pair.first->identifiers()[0]->code() == "102039") {
found = true;
- EXPECT_EQ(pair.second, 25);
+ EXPECT_EQ(pair.second, 50);
break;
}
}
@@ -2574,6 +2574,48 @@ TEST(crs, projectedCRS_identify_db) {
EXPECT_EQ(res.front().first->getEPSGCode(), 2154);
EXPECT_EQ(res.front().second, 70);
}
+ {
+ // Test identification of LKS92_Latvia_TM (#2214)
+ auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(
+ "PROJCS[\"LKS92_Latvia_TM\",GEOGCS[\"GCS_LKS92\","
+ "DATUM[\"D_Latvia_1992\","
+ "SPHEROID[\"GRS_1980\",6378137,298.257222101]],"
+ "PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.017453292519943295]],"
+ "PROJECTION[\"Transverse_Mercator\"],"
+ "PARAMETER[\"latitude_of_origin\",0],"
+ "PARAMETER[\"central_meridian\",24],"
+ "PARAMETER[\"scale_factor\",0.9996],"
+ "PARAMETER[\"false_easting\",500000],"
+ "PARAMETER[\"false_northing\",-6000000],"
+ "UNIT[\"Meter\",1]]");
+ auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+ auto res = crs->identify(factoryEPSG);
+ ASSERT_EQ(res.size(), 1U);
+ EXPECT_EQ(res.front().first->getEPSGCode(), 3059);
+ EXPECT_EQ(res.front().second, 90);
+ }
+ {
+ // Test identification of CRS where everything but datum names matches
+ auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(
+ "PROJCS[\"WGS_1984_UTM_Zone_31N\",GEOGCS[\"GCS_WGS_1984\","
+ "DATUM[\"wrong_datum_name\","
+ "SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],"
+ "PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],"
+ "PROJECTION[\"Transverse_Mercator\"],"
+ "PARAMETER[\"False_Easting\",500000.0],"
+ "PARAMETER[\"False_Northing\",0.0],"
+ "PARAMETER[\"Central_Meridian\",3.0],"
+ "PARAMETER[\"Scale_Factor\",0.9996],"
+ "PARAMETER[\"Latitude_Of_Origin\",0.0],"
+ "UNIT[\"Meter\",1.0]]");
+ auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+ auto res = crs->identify(factoryEPSG);
+ ASSERT_EQ(res.size(), 1U);
+ EXPECT_EQ(res.front().first->getEPSGCode(), 32631);
+ EXPECT_EQ(res.front().second, 60);
+ }
}
// ---------------------------------------------------------------------------
@@ -4121,7 +4163,7 @@ TEST(crs, boundCRS_identify_db) {
EXPECT_EQ(boundCRS->baseCRS()->getEPSGCode(), 2106);
EXPECT_EQ(boundCRS->transformation()->nameStr(),
"NZGD2000 to WGS 84 (1)");
- EXPECT_EQ(res.front().second, 50);
+ EXPECT_EQ(res.front().second, 70);
}
{
@@ -5752,6 +5794,21 @@ TEST(crs, promoteTo3D_and_demoteTo2D) {
nn_dynamic_pointer_cast<ProjectedCRS>(crs3DAsBound->baseCRS());
ASSERT_TRUE(baseCRS != nullptr);
EXPECT_EQ(baseCRS->coordinateSystem()->axisList().size(), 3U);
+
+ auto hubCRS =
+ nn_dynamic_pointer_cast<GeographicCRS>(crs3DAsBound->hubCRS());
+ ASSERT_TRUE(hubCRS != nullptr);
+ EXPECT_EQ(hubCRS->coordinateSystem()->axisList().size(), 3U);
+
+ auto transfSrcCRS = nn_dynamic_pointer_cast<GeographicCRS>(
+ crs3DAsBound->transformation()->sourceCRS());
+ ASSERT_TRUE(transfSrcCRS != nullptr);
+ EXPECT_EQ(transfSrcCRS->coordinateSystem()->axisList().size(), 3U);
+
+ auto transfDstCRS = nn_dynamic_pointer_cast<GeographicCRS>(
+ crs3DAsBound->transformation()->targetCRS());
+ ASSERT_TRUE(transfDstCRS != nullptr);
+ EXPECT_EQ(transfDstCRS->coordinateSystem()->axisList().size(), 3U);
}
auto demoted = crs3DAsBound->demoteTo2D(std::string(), nullptr);
@@ -5762,6 +5819,21 @@ TEST(crs, promoteTo3D_and_demoteTo2D) {
nn_dynamic_pointer_cast<ProjectedCRS>(crs2DAsBound->baseCRS());
ASSERT_TRUE(baseCRS != nullptr);
EXPECT_EQ(baseCRS->coordinateSystem()->axisList().size(), 2U);
+
+ auto hubCRS =
+ nn_dynamic_pointer_cast<GeographicCRS>(crs2DAsBound->hubCRS());
+ ASSERT_TRUE(hubCRS != nullptr);
+ EXPECT_EQ(hubCRS->coordinateSystem()->axisList().size(), 2U);
+
+ auto transfSrcCRS = nn_dynamic_pointer_cast<GeographicCRS>(
+ crs2DAsBound->transformation()->sourceCRS());
+ ASSERT_TRUE(transfSrcCRS != nullptr);
+ EXPECT_EQ(transfSrcCRS->coordinateSystem()->axisList().size(), 2U);
+
+ auto transfDstCRS = nn_dynamic_pointer_cast<GeographicCRS>(
+ crs2DAsBound->transformation()->targetCRS());
+ ASSERT_TRUE(transfDstCRS != nullptr);
+ EXPECT_EQ(transfDstCRS->coordinateSystem()->axisList().size(), 2U);
}
}
diff --git a/test/unit/test_factory.cpp b/test/unit/test_factory.cpp
index aee2f572..e6cfa72b 100644
--- a/test/unit/test_factory.cpp
+++ b/test/unit/test_factory.cpp
@@ -2763,6 +2763,13 @@ TEST(factory, createObjectsFromName) {
.size(),
3U);
+ EXPECT_EQ(
+ factory
+ ->createObjectsFromName(
+ "WGS 84", {AuthorityFactory::ObjectType::GEOCENTRIC_CRS}, false)
+ .size(),
+ 1U);
+
{
auto res = factoryEPSG->createObjectsFromName(
"WGS84", {AuthorityFactory::ObjectType::GEOGRAPHIC_2D_CRS}, true);
diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp
index 0570bb7e..d62e5c59 100644
--- a/test/unit/test_io.cpp
+++ b/test/unit/test_io.cpp
@@ -2484,6 +2484,136 @@ TEST(wkt_parse, COMPD_CS_non_conformant_horizontal_plus_horizontal_as_in_LAS) {
// ---------------------------------------------------------------------------
+TEST(wkt_parse,
+ COMPD_CS_non_conformant_horizontal_TOWGS84_plus_horizontal_as_in_LAS) {
+
+ const auto wkt = "COMPD_CS[\"WGS 84 + WGS 84\",\n"
+ " GEOGCS[\"WGS 84\",\n"
+ " DATUM[\"WGS_1984\",\n"
+ " SPHEROID[\"WGS 84\",6378137,298.257223563,\n"
+ " AUTHORITY[\"EPSG\",\"7030\"]],\n"
+ " TOWGS84[0,0,0,0,0,0,0],\n"
+ " AUTHORITY[\"EPSG\",\"6326\"]],\n"
+ " PRIMEM[\"Greenwich\",0,\n"
+ " AUTHORITY[\"EPSG\",\"8901\"]],\n"
+ " UNIT[\"degree\",0.0174532925199433,\n"
+ " AUTHORITY[\"EPSG\",\"9122\"]],\n"
+ " AUTHORITY[\"EPSG\",\"4326\"]],\n"
+ " GEOGCS[\"WGS 84\",\n"
+ " DATUM[\"WGS_1984\",\n"
+ " SPHEROID[\"WGS 84\",6378137,298.257223563,\n"
+ " AUTHORITY[\"EPSG\",\"7030\"]],\n"
+ " AUTHORITY[\"EPSG\",\"6326\"]],\n"
+ " PRIMEM[\"Greenwich\",0,\n"
+ " AUTHORITY[\"EPSG\",\"8901\"]],\n"
+ " UNIT[\"degree\",0.0174532925199433,\n"
+ " AUTHORITY[\"EPSG\",\"9122\"]],\n"
+ " AUTHORITY[\"EPSG\",\"4326\"]]]";
+ auto dbContext = DatabaseContext::create();
+ auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt);
+ auto crs = nn_dynamic_pointer_cast<BoundCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+ auto baseCRS = nn_dynamic_pointer_cast<GeographicCRS>(crs->baseCRS());
+ ASSERT_TRUE(baseCRS != nullptr);
+ EXPECT_EQ(baseCRS->nameStr(), "WGS 84");
+ EXPECT_EQ(baseCRS->coordinateSystem()->axisList().size(), 3U);
+
+ EXPECT_EQ(
+ crs->exportToWKT(
+ WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL, dbContext)
+ .get()),
+ wkt);
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(wkt_parse,
+ COMPD_CS_horizontal_bound_geog_plus_vertical_ellipsoidal_height) {
+ // See https://github.com/OSGeo/PROJ/issues/2228
+ const char *wkt =
+ "COMPD_CS[\"NAD83 + Ellipsoid (Meters)\",\n"
+ " GEOGCS[\"NAD83\",\n"
+ " DATUM[\"North_American_Datum_1983\",\n"
+ " SPHEROID[\"GRS 1980\",6378137,298.257222101,\n"
+ " AUTHORITY[\"EPSG\",\"7019\"]],\n"
+ " TOWGS84[0,0,0,0,0,0,0],\n"
+ " AUTHORITY[\"EPSG\",\"6269\"]],\n"
+ " PRIMEM[\"Greenwich\",0,\n"
+ " AUTHORITY[\"EPSG\",\"8901\"]],\n"
+ " UNIT[\"degree\",0.0174532925199433,\n"
+ " AUTHORITY[\"EPSG\",\"9122\"]],\n"
+ " AUTHORITY[\"EPSG\",\"4269\"]],\n"
+ " VERT_CS[\"Ellipsoid (Meters)\",\n"
+ " VERT_DATUM[\"Ellipsoid\",2002],\n"
+ " UNIT[\"metre\",1,\n"
+ " AUTHORITY[\"EPSG\",\"9001\"]],\n"
+ " AXIS[\"Up\",UP]]]";
+ auto dbContext = DatabaseContext::create();
+ auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt);
+ auto crs = nn_dynamic_pointer_cast<BoundCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+ auto baseCRS = nn_dynamic_pointer_cast<GeographicCRS>(crs->baseCRS());
+ ASSERT_TRUE(baseCRS != nullptr);
+ EXPECT_EQ(baseCRS->nameStr(), "NAD83");
+ EXPECT_EQ(baseCRS->coordinateSystem()->axisList().size(), 3U);
+
+ EXPECT_EQ(
+ crs->exportToWKT(
+ WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL, dbContext)
+ .get()),
+ wkt);
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(wkt_parse,
+ COMPD_CS_horizontal_projected_plus_vertical_ellipsoidal_height) {
+ // Variant of above
+ const char *wkt =
+ "COMPD_CS[\"WGS 84 / UTM zone 31N + Ellipsoid (Meters)\",\n"
+ " PROJCS[\"WGS 84 / UTM zone 31N\",\n"
+ " GEOGCS[\"WGS 84\",\n"
+ " DATUM[\"WGS_1984\",\n"
+ " SPHEROID[\"WGS 84\",6378137,298.257223563,\n"
+ " AUTHORITY[\"EPSG\",\"7030\"]],\n"
+ " AUTHORITY[\"EPSG\",\"6326\"]],\n"
+ " PRIMEM[\"Greenwich\",0,\n"
+ " AUTHORITY[\"EPSG\",\"8901\"]],\n"
+ " UNIT[\"degree\",0.0174532925199433,\n"
+ " AUTHORITY[\"EPSG\",\"9122\"]],\n"
+ " AUTHORITY[\"EPSG\",\"4326\"]],\n"
+ " PROJECTION[\"Transverse_Mercator\"],\n"
+ " PARAMETER[\"latitude_of_origin\",0],\n"
+ " PARAMETER[\"central_meridian\",3],\n"
+ " PARAMETER[\"scale_factor\",0.9996],\n"
+ " PARAMETER[\"false_easting\",500000],\n"
+ " PARAMETER[\"false_northing\",0],\n"
+ " UNIT[\"metre\",1,\n"
+ " AUTHORITY[\"EPSG\",\"9001\"]],\n"
+ " AXIS[\"Easting\",EAST],\n"
+ " AXIS[\"Northing\",NORTH],\n"
+ " AUTHORITY[\"EPSG\",\"32631\"]],\n"
+ " VERT_CS[\"Ellipsoid (Meters)\",\n"
+ " VERT_DATUM[\"Ellipsoid\",2002],\n"
+ " UNIT[\"metre\",1,\n"
+ " AUTHORITY[\"EPSG\",\"9001\"]],\n"
+ " AXIS[\"Up\",UP]]]";
+ auto dbContext = DatabaseContext::create();
+ auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt);
+ auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+ EXPECT_EQ(crs->nameStr(), "WGS 84 / UTM zone 31N");
+ EXPECT_EQ(crs->coordinateSystem()->axisList().size(), 3U);
+
+ EXPECT_EQ(
+ crs->exportToWKT(
+ WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL, dbContext)
+ .get()),
+ wkt);
+}
+
+// ---------------------------------------------------------------------------
+
TEST(wkt_parse, COORDINATEOPERATION) {
std::string src_wkt;
@@ -3442,6 +3572,32 @@ TEST(wkt_parse, WKT1_VERT_DATUM_EXTENSION) {
// ---------------------------------------------------------------------------
+TEST(wkt_parse, WKT1_VERT_DATUM_EXTENSION_units_ftUS) {
+ auto wkt = "VERT_CS[\"NAVD88 height (ftUS)\","
+ " VERT_DATUM[\"North American Vertical Datum 1988\",2005,"
+ " EXTENSION[\"PROJ4_GRIDS\",\"foo.gtx\"],"
+ " AUTHORITY[\"EPSG\",\"5103\"]],"
+ " UNIT[\"US survey foot\",0.304800609601219,"
+ " AUTHORITY[\"EPSG\",\"9003\"]],"
+ " AXIS[\"Gravity-related height\",UP],"
+ " AUTHORITY[\"EPSG\",\"6360\"]]";
+
+ auto obj = WKTParser().createFromWKT(wkt);
+ auto crs = nn_dynamic_pointer_cast<BoundCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+
+ EXPECT_EQ(crs->transformation()->nameStr(),
+ "NAVD88 height to WGS84 ellipsoidal height"); // no (ftUS)
+ auto sourceTransformationCRS = crs->transformation()->sourceCRS();
+ auto sourceTransformationVertCRS =
+ nn_dynamic_pointer_cast<VerticalCRS>(sourceTransformationCRS);
+ EXPECT_EQ(
+ sourceTransformationVertCRS->coordinateSystem()->axisList()[0]->unit(),
+ UnitOfMeasure::METRE);
+}
+
+// ---------------------------------------------------------------------------
+
TEST(wkt_parse, WKT1_DATUM_EXTENSION) {
auto wkt =
"PROJCS[\"unnamed\",\n"
@@ -9854,8 +10010,18 @@ TEST(io, createFromUserInput) {
// Search names in the database
EXPECT_THROW(createFromUserInput("foobar", dbContext), ParsingException);
- EXPECT_NO_THROW(createFromUserInput("WGS 84", dbContext));
- EXPECT_NO_THROW(createFromUserInput("WGS84", dbContext));
+ {
+ // Official name
+ auto obj = createFromUserInput("WGS 84", dbContext);
+ auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
+ EXPECT_TRUE(crs != nullptr);
+ }
+ {
+ // PROJ alias
+ auto obj = createFromUserInput("WGS84", dbContext);
+ auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
+ EXPECT_TRUE(crs != nullptr);
+ }
EXPECT_NO_THROW(createFromUserInput("UTM zone 31N", dbContext));
EXPECT_THROW(createFromUserInput("UTM zone 31", dbContext),
ParsingException);
diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp
index a655aff0..92b5f923 100644
--- a/test/unit/test_operation.cpp
+++ b/test/unit/test_operation.cpp
@@ -2904,7 +2904,7 @@ TEST(operation, wkt1_import_mercator_variant_A) {
// ---------------------------------------------------------------------------
TEST(operation, wkt1_import_mercator_variant_A_that_is_variant_B) {
- // Adresses https://trac.osgeo.org/gdal/ticket/3026
+ // Addresses https://trac.osgeo.org/gdal/ticket/3026
auto wkt = "PROJCS[\"test\",\n"
" GEOGCS[\"WGS 84\",\n"
" DATUM[\"WGS 1984\",\n"
@@ -4648,7 +4648,7 @@ TEST(operation, geogCRS_to_geogCRS_context_NAD27_to_WGS84_G1762) {
// ---------------------------------------------------------------------------
TEST(operation, geogCRS_to_geogCRS_context_WGS84_G1674_to_WGS84_G1762) {
- // Check that particular behaviour with WGS 84 (Gxxx) related to
+ // Check that particular behavior with WGS 84 (Gxxx) related to
// 'geodetic_datum_preferred_hub' table and custom no-op transformations
// between WGS 84 and WGS 84 (Gxxx) doesn't affect direct transformations
// to those realizations.
@@ -7003,13 +7003,17 @@ TEST(operation, compoundCRS_with_boundGeogCRS_to_geogCRS) {
compound, GeographicCRS::EPSG_4979);
ASSERT_TRUE(op != nullptr);
EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=pipeline +step +proj=axisswap +order=2,1 +step "
- "+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=push +v_3 "
- "+step +proj=cart +ellps=WGS84 +step +proj=helmert +x=1 +y=2 "
- "+z=3 +rx=4 +ry=5 +rz=6 +s=7 +convention=position_vector +step "
- "+inv +proj=cart +ellps=WGS84 +step +proj=pop +v_3 +step "
- "+proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap "
- "+order=2,1");
+ "+proj=pipeline "
+ "+step +proj=axisswap +order=2,1 "
+ "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+step +proj=push +v_3 "
+ "+step +proj=cart +ellps=WGS84 "
+ "+step +proj=helmert +x=1 +y=2 +z=3 +rx=4 +ry=5 +rz=6 +s=7 "
+ "+convention=position_vector "
+ "+step +inv +proj=cart +ellps=WGS84 "
+ "+step +proj=pop +v_3 "
+ "+step +proj=unitconvert +xy_in=rad +xy_out=deg "
+ "+step +proj=axisswap +order=2,1");
}
// ---------------------------------------------------------------------------
@@ -7136,6 +7140,61 @@ TEST(operation,
// ---------------------------------------------------------------------------
+TEST(operation,
+ compoundCRS_with_boundProjCRS_with_ftus_and_boundVerticalCRS_to_geogCRS) {
+
+ auto wkt =
+ "COMPD_CS[\"NAD_1983_StatePlane_Alabama_West_FIPS_0102_Feet + "
+ "NAVD88 height - Geoid12B (US Feet)\",\n"
+ " PROJCS[\"NAD_1983_StatePlane_Alabama_West_FIPS_0102_Feet\",\n"
+ " GEOGCS[\"NAD83\",\n"
+ " DATUM[\"North_American_Datum_1983\",\n"
+ " SPHEROID[\"GRS 1980\",6378137,298.257222101,\n"
+ " AUTHORITY[\"EPSG\",\"7019\"]],\n"
+ " TOWGS84[0,0,0,0,0,0,0],\n"
+ " AUTHORITY[\"EPSG\",\"6269\"]],\n"
+ " PRIMEM[\"Greenwich\",0],\n"
+ " UNIT[\"Degree\",0.0174532925199433]],\n"
+ " PROJECTION[\"Transverse_Mercator\"],\n"
+ " PARAMETER[\"latitude_of_origin\",30],\n"
+ " PARAMETER[\"central_meridian\",-87.5],\n"
+ " PARAMETER[\"scale_factor\",0.999933333333333],\n"
+ " PARAMETER[\"false_easting\",1968500],\n"
+ " PARAMETER[\"false_northing\",0],\n"
+ " UNIT[\"US survey foot\",0.304800609601219,\n"
+ " AUTHORITY[\"EPSG\",\"9003\"]],\n"
+ " AXIS[\"Easting\",EAST],\n"
+ " AXIS[\"Northing\",NORTH],\n"
+ " AUTHORITY[\"ESRI\",\"102630\"]],\n"
+ " VERT_CS[\"NAVD88 height (ftUS)\",\n"
+ " VERT_DATUM[\"North American Vertical Datum 1988\",2005,\n"
+ " EXTENSION[\"PROJ4_GRIDS\",\"foo.gtx\"],\n"
+ " AUTHORITY[\"EPSG\",\"5103\"]],\n"
+ " UNIT[\"US survey foot\",0.304800609601219,\n"
+ " AUTHORITY[\"EPSG\",\"9003\"]],\n"
+ " AXIS[\"Gravity-related height\",UP],\n"
+ " AUTHORITY[\"EPSG\",\"6360\"]]]";
+
+ auto obj = WKTParser().createFromWKT(wkt);
+ auto crs = nn_dynamic_pointer_cast<CompoundCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+ auto op = CoordinateOperationFactory::create()->createOperation(
+ NN_NO_CHECK(crs), GeographicCRS::EPSG_4979);
+ ASSERT_TRUE(op != nullptr);
+
+ EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=pipeline "
+ "+step +proj=unitconvert +xy_in=us-ft +xy_out=m "
+ "+step +inv +proj=tmerc +lat_0=30 +lon_0=-87.5 "
+ "+k=0.999933333333333 +x_0=600000 +y_0=0 +ellps=GRS80 "
+ "+step +proj=unitconvert +z_in=us-ft +z_out=m "
+ "+step +proj=vgridshift +grids=foo.gtx +multiplier=1 "
+ "+step +proj=unitconvert +xy_in=rad +xy_out=deg "
+ "+step +proj=axisswap +order=2,1");
+}
+
+// ---------------------------------------------------------------------------
+
TEST(operation, geocent_to_compoundCRS) {
auto objSrc = PROJStringParser().createFromPROJString(
"+proj=geocent +datum=WGS84 +units=m +type=crs");
@@ -7296,6 +7355,217 @@ TEST(operation, compoundCRS_to_compoundCRS_with_bound_crs_in_horiz_and_vert) {
// ---------------------------------------------------------------------------
+TEST(
+ operation,
+ compoundCRS_to_compoundCRS_with_bound_crs_in_horiz_and_vert_same_geoidgrids) {
+ auto objSrc = PROJStringParser().createFromPROJString(
+ "+proj=longlat +ellps=GRS67 +nadgrids=@foo.gsb +geoidgrids=@foo.gtx "
+ "+type=crs");
+ auto src = nn_dynamic_pointer_cast<CRS>(objSrc);
+ ASSERT_TRUE(src != nullptr);
+ auto objDst = PROJStringParser().createFromPROJString(
+ "+proj=longlat +ellps=GRS80 +nadgrids=@bar.gsb +geoidgrids=@foo.gtx "
+ "+type=crs");
+ auto dst = nn_dynamic_pointer_cast<CRS>(objDst);
+ ASSERT_TRUE(dst != nullptr);
+ auto op = CoordinateOperationFactory::create()->createOperation(
+ NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dst));
+ ASSERT_TRUE(op != nullptr);
+ EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=pipeline "
+ "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+step +proj=hgridshift +grids=@foo.gsb "
+ "+step +inv +proj=hgridshift +grids=@bar.gsb "
+ "+step +proj=unitconvert +xy_in=rad +xy_out=deg");
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(
+ operation,
+ compoundCRS_to_compoundCRS_with_bound_crs_in_horiz_and_vert_same_geoidgrids_different_vunits) {
+ auto objSrc = PROJStringParser().createFromPROJString(
+ "+proj=longlat +ellps=GRS67 +nadgrids=@foo.gsb +geoidgrids=@foo.gtx "
+ "+type=crs");
+ auto src = nn_dynamic_pointer_cast<CRS>(objSrc);
+ ASSERT_TRUE(src != nullptr);
+ auto objDst = PROJStringParser().createFromPROJString(
+ "+proj=longlat +ellps=GRS80 +nadgrids=@bar.gsb +geoidgrids=@foo.gtx "
+ "+vunits=us-ft +type=crs");
+ auto dst = nn_dynamic_pointer_cast<CRS>(objDst);
+ ASSERT_TRUE(dst != nullptr);
+ auto op = CoordinateOperationFactory::create()->createOperation(
+ NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dst));
+ ASSERT_TRUE(op != nullptr);
+ EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=pipeline "
+ "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+step +proj=hgridshift +grids=@foo.gsb "
+ "+step +proj=unitconvert +z_in=m +z_out=us-ft "
+ "+step +inv +proj=hgridshift +grids=@bar.gsb "
+ "+step +proj=unitconvert +xy_in=rad +xy_out=deg");
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(
+ operation,
+ compoundCRS_to_compoundCRS_with_bound_crs_in_horiz_and_vert_same_nadgrids_same_geoidgrids) {
+ auto objSrc = PROJStringParser().createFromPROJString(
+ "+proj=longlat +ellps=GRS67 +nadgrids=@foo.gsb +geoidgrids=@foo.gtx "
+ "+type=crs");
+ auto src = nn_dynamic_pointer_cast<CRS>(objSrc);
+ ASSERT_TRUE(src != nullptr);
+ auto objDst = PROJStringParser().createFromPROJString(
+ "+proj=longlat +ellps=GRS80 +nadgrids=@foo.gsb +geoidgrids=@foo.gtx "
+ "+type=crs");
+ auto dst = nn_dynamic_pointer_cast<CRS>(objDst);
+ ASSERT_TRUE(dst != nullptr);
+ auto op = CoordinateOperationFactory::create()->createOperation(
+ NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dst));
+ ASSERT_TRUE(op != nullptr);
+ EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=noop");
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(
+ operation,
+ compoundCRS_to_compoundCRS_with_bound_crs_in_horiz_and_vert_same_towgs84_same_geoidgrids) {
+ auto objSrc = PROJStringParser().createFromPROJString(
+ "+proj=longlat +ellps=GRS67 +towgs84=0,0,0 +geoidgrids=@foo.gtx "
+ "+type=crs");
+ auto src = nn_dynamic_pointer_cast<CRS>(objSrc);
+ ASSERT_TRUE(src != nullptr);
+ auto objDst = PROJStringParser().createFromPROJString(
+ "+proj=longlat +ellps=GRS80 +towgs84=0,0,0 +geoidgrids=@foo.gtx "
+ "+type=crs");
+ auto dst = nn_dynamic_pointer_cast<CRS>(objDst);
+ ASSERT_TRUE(dst != nullptr);
+ auto op = CoordinateOperationFactory::create()->createOperation(
+ NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dst));
+ ASSERT_TRUE(op != nullptr);
+ EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=pipeline "
+ "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+step +proj=push +v_3 "
+ "+step +proj=cart +ellps=GRS67 "
+ "+step +inv +proj=cart +ellps=GRS80 "
+ "+step +proj=pop +v_3 "
+ "+step +proj=unitconvert +xy_in=rad +xy_out=deg");
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(
+ operation,
+ compoundCRS_to_compoundCRS_with_bound_crs_in_horiz_and_vert_WKT1_same_geoidgrids_context) {
+ auto objSrc = WKTParser().createFromWKT(
+ "COMPD_CS[\"NAD83 / Alabama West + NAVD88 height - Geoid12B "
+ "(Meters)\",\n"
+ " PROJCS[\"NAD83 / Alabama West\",\n"
+ " GEOGCS[\"NAD83\",\n"
+ " DATUM[\"North_American_Datum_1983\",\n"
+ " SPHEROID[\"GRS 1980\",6378137,298.257222101,\n"
+ " AUTHORITY[\"EPSG\",\"7019\"]],\n"
+ " TOWGS84[0,0,0,0,0,0,0],\n"
+ " AUTHORITY[\"EPSG\",\"6269\"]],\n"
+ " PRIMEM[\"Greenwich\",0,\n"
+ " AUTHORITY[\"EPSG\",\"8901\"]],\n"
+ " UNIT[\"degree\",0.0174532925199433,\n"
+ " AUTHORITY[\"EPSG\",\"9122\"]],\n"
+ " AUTHORITY[\"EPSG\",\"4269\"]],\n"
+ " PROJECTION[\"Transverse_Mercator\"],\n"
+ " PARAMETER[\"latitude_of_origin\",30],\n"
+ " PARAMETER[\"central_meridian\",-87.5],\n"
+ " PARAMETER[\"scale_factor\",0.999933333],\n"
+ " PARAMETER[\"false_easting\",600000],\n"
+ " PARAMETER[\"false_northing\",0],\n"
+ " UNIT[\"metre\",1,\n"
+ " AUTHORITY[\"EPSG\",\"9001\"]],\n"
+ " AXIS[\"X\",EAST],\n"
+ " AXIS[\"Y\",NORTH],\n"
+ " AUTHORITY[\"EPSG\",\"26930\"]],\n"
+ " VERT_CS[\"NAVD88 height\",\n"
+ " VERT_DATUM[\"North American Vertical Datum 1988\",2005,\n"
+ " "
+ "EXTENSION[\"PROJ4_GRIDS\",\"g2012a_alaska.gtx,g2012a_hawaii.gtx,"
+ "g2012a_conus.gtx\"],\n"
+ " AUTHORITY[\"EPSG\",\"5103\"]],\n"
+ " UNIT[\"metre\",1,\n"
+ " AUTHORITY[\"EPSG\",\"9001\"]],\n"
+ " AXIS[\"Gravity-related height\",UP],\n"
+ " AUTHORITY[\"EPSG\",\"5703\"]]]");
+ auto src = nn_dynamic_pointer_cast<CRS>(objSrc);
+ ASSERT_TRUE(src != nullptr);
+ auto objDst = WKTParser().createFromWKT(
+ "COMPD_CS[\"NAD_1983_StatePlane_Alabama_West_FIPS_0102_Feet + NAVD88 "
+ "height - Geoid12B (US Feet)\",\n"
+ " PROJCS[\"NAD_1983_StatePlane_Alabama_West_FIPS_0102_Feet\",\n"
+ " GEOGCS[\"NAD83\",\n"
+ " DATUM[\"North_American_Datum_1983\",\n"
+ " SPHEROID[\"GRS 1980\",6378137,298.257222101,\n"
+ " AUTHORITY[\"EPSG\",\"7019\"]],\n"
+ " TOWGS84[0,0,0,0,0,0,0],\n"
+ " AUTHORITY[\"EPSG\",\"6269\"]],\n"
+ " PRIMEM[\"Greenwich\",0],\n"
+ " UNIT[\"Degree\",0.0174532925199433]],\n"
+ " PROJECTION[\"Transverse_Mercator\"],\n"
+ " PARAMETER[\"latitude_of_origin\",30],\n"
+ " PARAMETER[\"central_meridian\",-87.5],\n"
+ " PARAMETER[\"scale_factor\",0.999933333333333],\n"
+ " PARAMETER[\"false_easting\",1968500],\n"
+ " PARAMETER[\"false_northing\",0],\n"
+ " UNIT[\"US survey foot\",0.304800609601219,\n"
+ " AUTHORITY[\"EPSG\",\"9003\"]],\n"
+ " AXIS[\"Easting\",EAST],\n"
+ " AXIS[\"Northing\",NORTH],\n"
+ " AUTHORITY[\"ESRI\",\"102630\"]],\n"
+ " VERT_CS[\"NAVD88 height (ftUS)\",\n"
+ " VERT_DATUM[\"North American Vertical Datum 1988\",2005,\n"
+ " "
+ "EXTENSION[\"PROJ4_GRIDS\",\"g2012a_alaska.gtx,g2012a_hawaii.gtx,"
+ "g2012a_conus.gtx\"],\n"
+ " AUTHORITY[\"EPSG\",\"5103\"]],\n"
+ " UNIT[\"US survey foot\",0.304800609601219,\n"
+ " AUTHORITY[\"EPSG\",\"9003\"]],\n"
+ " AXIS[\"Gravity-related height\",UP],\n"
+ " AUTHORITY[\"EPSG\",\"6360\"]]]");
+ auto dst = nn_dynamic_pointer_cast<CRS>(objDst);
+ ASSERT_TRUE(dst != nullptr);
+
+ auto dbContext = DatabaseContext::create();
+ auto authFactory = AuthorityFactory::create(dbContext, "EPSG");
+ auto ctxt = CoordinateOperationContext::create(authFactory, nullptr, 0.0);
+ ctxt->setGridAvailabilityUse(
+ CoordinateOperationContext::GridAvailabilityUse::
+ IGNORE_GRID_AVAILABILITY);
+ ctxt->setSpatialCriterion(
+ CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION);
+ auto list = CoordinateOperationFactory::create()->createOperations(
+ NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dst), ctxt);
+ ASSERT_GE(list.size(), 1U);
+ EXPECT_EQ(list[0]->nameStr(),
+ "Inverse of unnamed + "
+ "Transformation from NAD83 to WGS84 + "
+ "NAVD88 height to NAVD88 height (ftUS) + "
+ "Inverse of Transformation from NAD83 to WGS84 + "
+ "unnamed");
+ auto grids = list[0]->gridsNeeded(dbContext, false);
+ EXPECT_TRUE(grids.empty());
+ EXPECT_EQ(list[0]->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=pipeline "
+ "+step +inv +proj=tmerc +lat_0=30 +lon_0=-87.5 +k=0.999933333 "
+ "+x_0=600000 +y_0=0 +ellps=GRS80 "
+ "+step +proj=unitconvert +z_in=m +z_out=us-ft "
+ "+step +proj=tmerc +lat_0=30 +lon_0=-87.5 +k=0.999933333333333 "
+ "+x_0=600000 +y_0=0 +ellps=GRS80 "
+ "+step +proj=unitconvert +xy_in=m +xy_out=us-ft");
+}
+
+// ---------------------------------------------------------------------------
+
TEST(operation, compoundCRS_to_compoundCRS_context) {
auto authFactory =
AuthorityFactory::create(DatabaseContext::create(), "EPSG");
@@ -7800,6 +8070,49 @@ TEST(operation, compoundCRS_to_geogCRS_3D_context) {
// ---------------------------------------------------------------------------
+TEST(operation, compoundCRS_to_geogCRS_3D_with_3D_helmert_context) {
+ // Use case of https://github.com/OSGeo/PROJ/issues/2225
+ auto dbContext = DatabaseContext::create();
+ auto authFactory = AuthorityFactory::create(dbContext, "EPSG");
+ auto ctxt = CoordinateOperationContext::create(authFactory, nullptr, 0.0);
+ ctxt->setSpatialCriterion(
+ CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION);
+ ctxt->setGridAvailabilityUse(
+ CoordinateOperationContext::GridAvailabilityUse::
+ IGNORE_GRID_AVAILABILITY);
+ // WGS84 + EGM96 height
+ auto srcObj = createFromUserInput("EPSG:4326+5773", dbContext, false);
+ auto src = nn_dynamic_pointer_cast<CRS>(srcObj);
+ ASSERT_TRUE(src != nullptr);
+ auto list = CoordinateOperationFactory::create()->createOperations(
+ NN_NO_CHECK(src),
+ // CH1903+
+ authFactory->createCoordinateReferenceSystem("4150")->promoteTo3D(
+ std::string(), dbContext),
+ ctxt);
+ ASSERT_GE(list.size(), 1U);
+ EXPECT_EQ(list[0]->nameStr(), "Inverse of WGS 84 to EGM96 height (1) + "
+ "Inverse of CH1903+ to WGS 84 (1)");
+ // Check that there is no push v_3 / pop v_3
+ const char *expected_proj =
+ "+proj=pipeline "
+ "+step +proj=axisswap +order=2,1 "
+ "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+step +proj=vgridshift +grids=us_nga_egm96_15.tif +multiplier=1 "
+ "+step +proj=cart +ellps=WGS84 "
+ "+step +proj=helmert +x=-674.374 +y=-15.056 +z=-405.346 "
+ "+step +inv +proj=cart +ellps=bessel "
+ "+step +proj=unitconvert +xy_in=rad +xy_out=deg "
+ "+step +proj=axisswap +order=2,1";
+ EXPECT_EQ(list[0]->exportToPROJString(
+ PROJStringFormatter::create(
+ PROJStringFormatter::Convention::PROJ_5, dbContext)
+ .get()),
+ expected_proj);
+}
+
+// ---------------------------------------------------------------------------
+
TEST(operation, compoundCRS_to_geogCRS_2D_promote_to_3D_context) {
auto authFactory =
AuthorityFactory::create(DatabaseContext::create(), "EPSG");
@@ -8425,13 +8738,18 @@ TEST(operation, compoundCRS_from_WKT2_no_id_to_geogCRS_3D_context) {
" VDATUM[\"Normaal Amsterdams Peil\"],\n"
" CS[vertical,1],\n"
" AXIS[\"gravity-related height (H)\",up,\n"
- " LENGTHUNIT[\"metre\",1]]]]";
+ " LENGTHUNIT[\"metre\",1]]],\n"
+ " USAGE[\n"
+ " SCOPE[\"unknown\"],\n"
+ " AREA[\"Netherlands - onshore\"],\n"
+ " BBOX[50.75,3.2,53.7,7.22]]]";
+
auto obj = WKTParser().createFromWKT(wkt2);
auto src_from_wkt2 = nn_dynamic_pointer_cast<CRS>(obj);
ASSERT_TRUE(src_from_wkt2 != nullptr);
auto list2 = CoordinateOperationFactory::create()->createOperations(
NN_NO_CHECK(src_from_wkt2), dst, ctxt);
- ASSERT_GE(list.size(), list2.size() - 1);
+ ASSERT_EQ(list.size(), list2.size());
for (size_t i = 0; i < list.size(); i++) {
const auto &op = list[i];
const auto &op2 = list2[i];