From 419c3850211447b3a435442662f8fa12efd15cca Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 4 Dec 2018 23:32:19 +0100 Subject: Add proj_obj_create_vertical_crs() and proj_obj_create_compound_crs() --- src/c_api.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ src/proj_experimental.h | 11 +++++++ test/unit/test_c_api.cpp | 43 ++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) diff --git a/src/c_api.cpp b/src/c_api.cpp index 718d46bf..a5ed1509 100644 --- a/src/c_api.cpp +++ b/src/c_api.cpp @@ -2101,6 +2101,86 @@ PJ_OBJ *proj_obj_create_geocentric_crs_from_datum(PJ_CONTEXT *ctx, // --------------------------------------------------------------------------- +/** \brief Create a VerticalCRS + * + * The returned object must be unreferenced with proj_obj_unref() after + * use. + * It should be used by at most one thread at a time. + * + * @param ctx PROJ context, or NULL for default context + * @param crs_name Name of the GeographicCRS. Or NULL + * @param datum_name Name of the VerticalReferenceFrame. Or NULL + * @param linear_units Name of the linear units. Or NULL for Metre + * @param linear_units_conv Conversion factor from the linear unit to metre. Or + * 0 for Metre if linear_units == NULL. Otherwise should be not NULL + * + * @return Object of type VerticalCRS that must be unreferenced with + * proj_obj_unref(), or NULL in case of error. + */ +PJ_OBJ *proj_obj_create_vertical_crs(PJ_CONTEXT *ctx, const char *crs_name, + const char *datum_name, + const char *linear_units, + double linear_units_conv) { + + SANITIZE_CTX(ctx); + try { + const UnitOfMeasure linearUnit( + createLinearUnit(linear_units, linear_units_conv)); + auto datum = + VerticalReferenceFrame::create(createPropertyMapName(datum_name)); + auto vertCRS = VerticalCRS::create( + createPropertyMapName(crs_name), datum, + cs::VerticalCS::createGravityRelatedHeight(linearUnit)); + return PJ_OBJ::create(vertCRS); + } catch (const std::exception &e) { + proj_log_error(ctx, __FUNCTION__, e.what()); + } + return nullptr; +} + +// --------------------------------------------------------------------------- + +/** \brief Create a CompoundCRS + * + * The returned object must be unreferenced with proj_obj_unref() after + * use. + * It should be used by at most one thread at a time. + * + * @param ctx PROJ context, or NULL for default context + * @param crs_name Name of the GeographicCRS. Or NULL + * @param horiz_crs Horizontal CRS. must not be NULL. + * @param vert_crs Vertical CRS. must not be NULL. + * + * @return Object of type CompoundCRS that must be unreferenced with + * proj_obj_unref(), or NULL in case of error. + */ +PJ_OBJ *proj_obj_create_compound_crs(PJ_CONTEXT *ctx, const char *crs_name, + PJ_OBJ *horiz_crs, PJ_OBJ *vert_crs) { + + assert(horiz_crs); + assert(vert_crs); + SANITIZE_CTX(ctx); + auto l_horiz_crs = util::nn_dynamic_pointer_cast(horiz_crs->obj); + if (!l_horiz_crs) { + return nullptr; + } + auto l_vert_crs = util::nn_dynamic_pointer_cast(vert_crs->obj); + if (!l_vert_crs) { + return nullptr; + } + try { + auto compoundCRS = CompoundCRS::create( + createPropertyMapName(crs_name), + {NN_NO_CHECK(l_horiz_crs), NN_NO_CHECK(l_vert_crs)}); + return PJ_OBJ::create(compoundCRS); + } catch (const std::exception &e) { + proj_log_error(ctx, __FUNCTION__, e.what()); + } + return nullptr; +} + +// --------------------------------------------------------------------------- + /** \brief Return a copy of the object with its name changed * * Currently, only implemented on CRS objects. diff --git a/src/proj_experimental.h b/src/proj_experimental.h index 1dc16f99..19cde6fc 100644 --- a/src/proj_experimental.h +++ b/src/proj_experimental.h @@ -187,6 +187,17 @@ PJ_OBJ PROJ_DLL *proj_obj_crs_alter_parameters_linear_unit(PJ_CONTEXT *ctx, PJ_OBJ PROJ_DLL *proj_obj_create_engineering_crs(PJ_CONTEXT *ctx, const char *crsName); +PJ_OBJ PROJ_DLL *proj_obj_create_vertical_crs(PJ_CONTEXT *ctx, + const char *crs_name, + const char *datum_name, + const char *linear_units, + double linear_units_conv); + +PJ_OBJ PROJ_DLL *proj_obj_create_compound_crs(PJ_CONTEXT *ctx, + const char *crs_name, + PJ_OBJ* horiz_crs, + PJ_OBJ* vert_crs); + /** Description of a parameter value for a Conversion. */ typedef struct { diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index bec965ce..57ade07f 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -2432,4 +2432,47 @@ TEST_F(CApi, proj_obj_create_projected_crs) { ASSERT_NE(projCRS, nullptr); } +// --------------------------------------------------------------------------- + +TEST_F(CApi, proj_obj_create_compound_crs) { + + auto horiz_cs = proj_obj_create_ellipsoidal_2D_cs( + m_ctxt, PJ_ELLPS2D_LONGITUDE_LATITUDE, nullptr, 0); + ObjectKeeper keeper_horiz_cs(horiz_cs); + ASSERT_NE(horiz_cs, nullptr); + + auto horiz_crs = proj_obj_create_geographic_crs( + m_ctxt, "WGS 84", "World Geodetic System 1984", "WGS 84", 6378137, + 298.257223563, "Greenwich", 0.0, "Degree", 0.0174532925199433, + horiz_cs); + ObjectKeeper keeper_horiz_crs(horiz_crs); + ASSERT_NE(horiz_crs, nullptr); + + auto vert_crs = proj_obj_create_vertical_crs(m_ctxt, "myVertCRS", + "myVertDatum", nullptr, 0.0); + ObjectKeeper keeper_vert_crs(vert_crs); + ASSERT_NE(vert_crs, nullptr); + + EXPECT_EQ(proj_obj_get_name(vert_crs), std::string("myVertCRS")); + + auto compound_crs = proj_obj_create_compound_crs(m_ctxt, "myCompoundCRS", + horiz_crs, vert_crs); + ObjectKeeper keeper_compound_crss(compound_crs); + ASSERT_NE(compound_crs, nullptr); + + EXPECT_EQ(proj_obj_get_name(compound_crs), std::string("myCompoundCRS")); + + auto subcrs_horiz = proj_obj_crs_get_sub_crs(m_ctxt, compound_crs, 0); + ASSERT_NE(subcrs_horiz, nullptr); + ObjectKeeper keeper_subcrs_horiz(subcrs_horiz); + EXPECT_TRUE( + proj_obj_is_equivalent_to(subcrs_horiz, horiz_crs, PJ_COMP_STRICT)); + + auto subcrs_vert = proj_obj_crs_get_sub_crs(m_ctxt, compound_crs, 1); + ASSERT_NE(subcrs_vert, nullptr); + ObjectKeeper keeper_subcrs_vert(subcrs_vert); + EXPECT_TRUE( + proj_obj_is_equivalent_to(subcrs_vert, vert_crs, PJ_COMP_STRICT)); +} + } // namespace -- cgit v1.2.3