diff options
Diffstat (limited to 'test')
| -rwxr-xr-x | test/cli/testvarious | 2 | ||||
| -rw-r--r-- | test/fuzzers/README.TXT | 2 | ||||
| -rw-r--r-- | test/gie/more_builtins.gie | 2 | ||||
| -rw-r--r-- | test/unit/test_c_api.cpp | 6 | ||||
| -rw-r--r-- | test/unit/test_crs.cpp | 80 | ||||
| -rw-r--r-- | test/unit/test_factory.cpp | 7 | ||||
| -rw-r--r-- | test/unit/test_io.cpp | 170 | ||||
| -rw-r--r-- | test/unit/test_operation.cpp | 340 |
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]; |
