aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/c_api.cpp80
-rw-r--r--src/proj_experimental.h11
-rw-r--r--test/unit/test_c_api.cpp43
3 files changed, 134 insertions, 0 deletions
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<CRS>(horiz_crs->obj);
+ if (!l_horiz_crs) {
+ return nullptr;
+ }
+ auto l_vert_crs = util::nn_dynamic_pointer_cast<CRS>(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