diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2018-12-06 00:20:30 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2018-12-06 00:20:30 +0100 |
| commit | e699ae83eada3aa706e06215f5370dafc3235f7b (patch) | |
| tree | 654b2fa264cce5be734673d06f11407388467e55 | |
| parent | 095d44a4a6dd4244bd8c42b28ee1a3bb521fe4b9 (diff) | |
| parent | dccf4658ac4cf9194682350ec292a086a2bb24a1 (diff) | |
| download | PROJ-e699ae83eada3aa706e06215f5370dafc3235f7b.tar.gz PROJ-e699ae83eada3aa706e06215f5370dafc3235f7b.zip | |
Merge remote-tracking branch 'rouault/gdalbarn'
| -rw-r--r-- | src/c_api.cpp | 67 | ||||
| -rw-r--r-- | src/proj_experimental.h | 5 | ||||
| -rw-r--r-- | test/unit/test_c_api.cpp | 77 |
3 files changed, 149 insertions, 0 deletions
diff --git a/src/c_api.cpp b/src/c_api.cpp index a5ed1509..fed91750 100644 --- a/src/c_api.cpp +++ b/src/c_api.cpp @@ -55,6 +55,7 @@ #include "proj_experimental.h" #include "projects.h" // clang-format on +#include "proj_constants.h" using namespace NS_PROJ::common; using namespace NS_PROJ::crs; @@ -2526,6 +2527,72 @@ PJ_OBJ *proj_obj_create_conversion(PJ_CONTEXT *ctx, const char *name, // --------------------------------------------------------------------------- +/** + * \brief Return an equivalent projection. + * + * Currently implemented: + * <ul> + * <li>EPSG_CODE_METHOD_MERCATOR_VARIANT_A (1SP) to + * EPSG_CODE_METHOD_MERCATOR_VARIANT_B (2SP)</li> + * <li>EPSG_CODE_METHOD_MERCATOR_VARIANT_B (2SP) to + * EPSG_CODE_METHOD_MERCATOR_VARIANT_A (1SP)</li> + * <li>EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP to + * EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP</li> + * <li>EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP to + * EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP</li> + * </ul> + * + * @param ctx PROJ context, or NULL for default context + * @param conversion Object of type Conversion. Must not be NULL. + * @param new_method_epsg_code EPSG code of the target method. Or 0 (in which + * case new_method_name must be specified). + * @param new_method_name EPSG or PROJ target method name. Or nullptr (in which + * case new_method_epsg_code must be specified). + * @return new conversion that must be unreferenced with + * proj_obj_unref(), or NULL in case of error. + */ +PJ_OBJ *proj_obj_convert_conversion_to_other_method( + PJ_CONTEXT *ctx, const PJ_OBJ *conversion, int new_method_epsg_code, + const char *new_method_name) { + SANITIZE_CTX(ctx); + auto conv = dynamic_cast<const Conversion *>(conversion->obj.get()); + if (!conv) { + proj_log_error(ctx, __FUNCTION__, "not a Conversion"); + return nullptr; + } + if (new_method_epsg_code == 0) { + if (!new_method_name) { + return nullptr; + } + if (metadata::Identifier::isEquivalentName( + new_method_name, EPSG_NAME_METHOD_MERCATOR_VARIANT_A)) { + new_method_epsg_code = EPSG_CODE_METHOD_MERCATOR_VARIANT_A; + } else if (metadata::Identifier::isEquivalentName( + new_method_name, EPSG_NAME_METHOD_MERCATOR_VARIANT_B)) { + new_method_epsg_code = EPSG_CODE_METHOD_MERCATOR_VARIANT_B; + } else if (metadata::Identifier::isEquivalentName( + new_method_name, + EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_1SP)) { + new_method_epsg_code = EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP; + } else if (metadata::Identifier::isEquivalentName( + new_method_name, + EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_2SP)) { + new_method_epsg_code = EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP; + } + } + try { + auto new_conv = conv->convertToOtherMethod(new_method_epsg_code); + if (!new_conv) + return nullptr; + return PJ_OBJ::create(NN_NO_CHECK(new_conv)); + } catch (const std::exception &e) { + proj_log_error(ctx, __FUNCTION__, e.what()); + return nullptr; + } +} + +// --------------------------------------------------------------------------- + //! @cond Doxygen_Suppress static CoordinateSystemAxisNNPtr createAxis(const PJ_AXIS_DESCRIPTION &axis) { diff --git a/src/proj_experimental.h b/src/proj_experimental.h index 19cde6fc..b8c37054 100644 --- a/src/proj_experimental.h +++ b/src/proj_experimental.h @@ -227,6 +227,11 @@ PJ_OBJ PROJ_DLL *proj_obj_create_conversion(PJ_CONTEXT *ctx, int param_count, const PJ_PARAM_DESCRIPTION* params); +PJ_OBJ PROJ_DLL *proj_obj_convert_conversion_to_other_method(PJ_CONTEXT *ctx, + const PJ_OBJ *conversion, + int new_method_epsg_code, + const char *new_method_name); + PJ_OBJ PROJ_DLL *proj_obj_create_projected_crs(PJ_CONTEXT *ctx, const char* crs_name, const PJ_OBJ* geodetic_crs, diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index 57ade07f..42d00fa6 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -29,6 +29,7 @@ #include "gtest_include.h" #include "proj.h" +#include "proj_constants.h" #include "proj_experimental.h" #include "proj/common.hpp" @@ -2475,4 +2476,80 @@ TEST_F(CApi, proj_obj_create_compound_crs) { proj_obj_is_equivalent_to(subcrs_vert, vert_crs, PJ_COMP_STRICT)); } +// --------------------------------------------------------------------------- + +TEST_F(CApi, proj_obj_convert_conversion_to_other_method) { + { + auto geog_cs = proj_obj_create_ellipsoidal_2D_cs( + m_ctxt, PJ_ELLPS2D_LONGITUDE_LATITUDE, nullptr, 0); + ObjectKeeper keeper_geog_cs(geog_cs); + ASSERT_NE(geog_cs, nullptr); + + auto geogCRS = proj_obj_create_geographic_crs( + m_ctxt, "WGS 84", "World Geodetic System 1984", "WGS 84", 6378137, + 298.257223563, "Greenwich", 0.0, "Degree", 0.0174532925199433, + geog_cs); + ObjectKeeper keeper_geogCRS(geogCRS); + ASSERT_NE(geogCRS, nullptr); + + auto cs = proj_obj_create_cartesian_2D_cs( + m_ctxt, PJ_CART2D_EASTING_NORTHING, nullptr, 0); + ObjectKeeper keeper_cs(cs); + ASSERT_NE(cs, nullptr); + + auto conv = proj_obj_create_conversion_mercator_variant_a( + m_ctxt, 0, 1, 0.99, 2, 3, "Degree", 0.0174532925199433, "Metre", + 1.0); + ObjectKeeper keeper_conv(conv); + ASSERT_NE(conv, nullptr); + + auto projCRS = + proj_obj_create_projected_crs(m_ctxt, "my CRS", geogCRS, conv, cs); + ObjectKeeper keeper_projCRS(projCRS); + ASSERT_NE(projCRS, nullptr); + + // Wrong object type + EXPECT_EQ( + proj_obj_convert_conversion_to_other_method( + m_ctxt, projCRS, EPSG_CODE_METHOD_MERCATOR_VARIANT_B, nullptr), + nullptr); + + auto conv_in_proj = proj_obj_crs_get_coordoperation( + m_ctxt, projCRS, nullptr, nullptr, nullptr); + ObjectKeeper keeper_conv_in_proj(conv_in_proj); + ASSERT_NE(conv_in_proj, nullptr); + + // 3rd and 4th argument both 0/null + EXPECT_EQ(proj_obj_convert_conversion_to_other_method( + m_ctxt, conv_in_proj, 0, nullptr), + nullptr); + + auto new_conv = proj_obj_convert_conversion_to_other_method( + m_ctxt, conv_in_proj, EPSG_CODE_METHOD_MERCATOR_VARIANT_B, nullptr); + ObjectKeeper keeper_new_conv(new_conv); + ASSERT_NE(new_conv, nullptr); + + EXPECT_FALSE( + proj_obj_is_equivalent_to(new_conv, conv_in_proj, PJ_COMP_STRICT)); + EXPECT_TRUE(proj_obj_is_equivalent_to(new_conv, conv_in_proj, + PJ_COMP_EQUIVALENT)); + + auto new_conv_from_name = proj_obj_convert_conversion_to_other_method( + m_ctxt, conv_in_proj, 0, EPSG_NAME_METHOD_MERCATOR_VARIANT_B); + ObjectKeeper keeper_new_conv_from_name(new_conv_from_name); + ASSERT_NE(new_conv_from_name, nullptr); + + EXPECT_TRUE(proj_obj_is_equivalent_to(new_conv, new_conv_from_name, + PJ_COMP_STRICT)); + + auto new_conv_back = proj_obj_convert_conversion_to_other_method( + m_ctxt, conv_in_proj, 0, EPSG_NAME_METHOD_MERCATOR_VARIANT_A); + ObjectKeeper keeper_new_conv_back(new_conv_back); + ASSERT_NE(new_conv_back, nullptr); + + EXPECT_TRUE(proj_obj_is_equivalent_to(conv_in_proj, new_conv_back, + PJ_COMP_STRICT)); + } +} + } // namespace |
