aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan D. Snow <alansnow21@gmail.com>2021-04-18 05:34:29 -0500
committerGitHub <noreply@github.com>2021-04-18 12:34:29 +0200
commite4e2991b174ea48b67e9b41c8f356a9cf1bba081 (patch)
treed523f7534caf2662f1b97d5e8e40b5d16886c998
parent3d1c573dc9d9f56ced597554ad9fa1643f0a0ae9 (diff)
downloadPROJ-e4e2991b174ea48b67e9b41c8f356a9cf1bba081.tar.gz
PROJ-e4e2991b174ea48b67e9b41c8f356a9cf1bba081.zip
Added proj_get_celestial_body_list_from_database (#2674)
Closes #2667
-rw-r--r--include/proj/io.hpp13
-rw-r--r--scripts/reference_exported_symbols.txt4
-rw-r--r--src/iso19111/c_api.cpp70
-rw-r--r--src/iso19111/factory.cpp37
-rw-r--r--src/proj.h23
-rw-r--r--test/unit/test_c_api.cpp31
-rw-r--r--test/unit/test_factory.cpp33
7 files changed, 211 insertions, 0 deletions
diff --git a/include/proj/io.hpp b/include/proj/io.hpp
index e4307d02..e51dd19a 100644
--- a/include/proj/io.hpp
+++ b/include/proj/io.hpp
@@ -1126,6 +1126,19 @@ class PROJ_GCC_DLL AuthorityFactory {
PROJ_DLL std::list<UnitInfo> getUnitList() const;
+ /** Celestial Body information */
+ struct CelestialBodyInfo {
+ /** Authority name */
+ std::string authName;
+ /** Name */
+ std::string name;
+ //! @cond Doxygen_Suppress
+ CelestialBodyInfo();
+ //! @endcond
+ };
+
+ PROJ_DLL std::list<CelestialBodyInfo> getCelestialBodyList() const;
+
PROJ_DLL static AuthorityFactoryNNPtr
create(const DatabaseContextNNPtr &context,
const std::string &authorityName);
diff --git a/scripts/reference_exported_symbols.txt b/scripts/reference_exported_symbols.txt
index ed49e0e5..d5aef65d 100644
--- a/scripts/reference_exported_symbols.txt
+++ b/scripts/reference_exported_symbols.txt
@@ -319,6 +319,7 @@ osgeo::proj::internal::split(std::string const&, std::string const&)
osgeo::proj::internal::tolower(std::string const&)
osgeo::proj::internal::toString(double, int)
osgeo::proj::io::AuthorityFactory::~AuthorityFactory()
+osgeo::proj::io::AuthorityFactory::CelestialBodyInfo::CelestialBodyInfo()
osgeo::proj::io::AuthorityFactory::createCompoundCRS(std::string const&) const
osgeo::proj::io::AuthorityFactory::createConversion(std::string const&) const
osgeo::proj::io::AuthorityFactory::createCoordinateOperation(std::string const&, bool) const
@@ -346,6 +347,7 @@ osgeo::proj::io::AuthorityFactory::CRSInfo::CRSInfo()
osgeo::proj::io::AuthorityFactory::databaseContext() const
osgeo::proj::io::AuthorityFactory::getAuthorityCodes(osgeo::proj::io::AuthorityFactory::ObjectType const&, bool) const
osgeo::proj::io::AuthorityFactory::getAuthority() const
+osgeo::proj::io::AuthorityFactory::getCelestialBodyList() const
osgeo::proj::io::AuthorityFactory::getCRSInfoList() const
osgeo::proj::io::AuthorityFactory::getDescriptionText(std::string const&) const
osgeo::proj::io::AuthorityFactory::getOfficialNameFromAlias(std::string const&, std::string const&, std::string const&, bool, std::string&, std::string&, std::string&) const
@@ -781,6 +783,7 @@ proj_as_projjson
proj_as_proj_string
proj_assign_context
proj_as_wkt
+proj_celestial_body_list_destroy
proj_cleanup
proj_clone
proj_concatoperation_get_step
@@ -959,6 +962,7 @@ proj_factors
proj_geod
proj_get_area_of_use
proj_get_authorities_from_database
+proj_get_celestial_body_list_from_database
proj_get_celestial_body_name
proj_get_codes_from_database
proj_get_crs_info_list_from_database
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp
index c9eaf46a..cb44151a 100644
--- a/src/iso19111/c_api.cpp
+++ b/src/iso19111/c_api.cpp
@@ -2674,6 +2674,76 @@ PROJ_STRING_LIST proj_get_codes_from_database(PJ_CONTEXT *ctx,
// ---------------------------------------------------------------------------
+/** \brief Enumerate celestial bodies from the database.
+ *
+ * The returned object is an array of PROJ_CELESTIAL_BODY_INFO* pointers, whose last
+ * entry is NULL. This array should be freed with proj_celestial_body_list_destroy()
+ *
+ * @param ctx PROJ context, or NULL for default context
+ * @param auth_name Authority name, used to restrict the search.
+ * Or NULL for all authorities.
+ * @param out_result_count Output parameter pointing to an integer to receive
+ * the size of the result list. Might be NULL
+ * @return an array of PROJ_CELESTIAL_BODY_INFO* pointers to be freed with
+ * proj_celestial_body_list_destroy(), or NULL in case of error.
+ * @since 8.1
+ */
+PROJ_CELESTIAL_BODY_INFO **proj_get_celestial_body_list_from_database(PJ_CONTEXT *ctx,
+ const char *auth_name,
+ int *out_result_count) {
+ SANITIZE_CTX(ctx);
+ PROJ_CELESTIAL_BODY_INFO **ret = nullptr;
+ int i = 0;
+ try {
+ auto factory = AuthorityFactory::create(getDBcontext(ctx),
+ auth_name ? auth_name : "");
+ auto list = factory->getCelestialBodyList();
+ ret = new PROJ_CELESTIAL_BODY_INFO *[list.size() + 1];
+ for (const auto &info : list) {
+ ret[i] = new PROJ_CELESTIAL_BODY_INFO;
+ ret[i]->auth_name = pj_strdup(info.authName.c_str());
+ ret[i]->name = pj_strdup(info.name.c_str());
+ i++;
+ }
+ ret[i] = nullptr;
+ if (out_result_count)
+ *out_result_count = i;
+ ctx->safeAutoCloseDbIfNeeded();
+ return ret;
+ } catch (const std::exception &e) {
+ proj_log_error(ctx, __FUNCTION__, e.what());
+ if (ret) {
+ ret[i + 1] = nullptr;
+ proj_celestial_body_list_destroy(ret);
+ }
+ if (out_result_count)
+ *out_result_count = 0;
+ }
+ ctx->safeAutoCloseDbIfNeeded();
+ return nullptr;
+}
+
+// ---------------------------------------------------------------------------
+
+/** \brief Destroy the result returned by
+ * proj_get_celestial_body_list_from_database().
+ *
+ * @since 8.1
+ */
+void proj_celestial_body_list_destroy(PROJ_CELESTIAL_BODY_INFO **list) {
+ if (list) {
+ for (int i = 0; list[i] != nullptr; i++) {
+ free(list[i]->auth_name);
+ free(list[i]->name);
+ delete list[i];
+ }
+ delete[] list;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+
/** Free a list of NULL terminated strings. */
void proj_string_list_destroy(PROJ_STRING_LIST list) {
if (list) {
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp
index 19db111b..088289c5 100644
--- a/src/iso19111/factory.cpp
+++ b/src/iso19111/factory.cpp
@@ -7465,6 +7465,14 @@ AuthorityFactory::UnitInfo::UnitInfo()
deprecated{} {}
//! @endcond
+
+// ---------------------------------------------------------------------------
+
+//! @cond Doxygen_Suppress
+AuthorityFactory::CelestialBodyInfo::CelestialBodyInfo() : authName{}, name{} {}
+//! @endcond
+
+
// ---------------------------------------------------------------------------
/** \brief Return the list of units.
@@ -7517,6 +7525,35 @@ std::list<AuthorityFactory::UnitInfo> AuthorityFactory::getUnitList() const {
// ---------------------------------------------------------------------------
+/** \brief Return the list of celestial bodies.
+ * @throw FactoryException
+ *
+ * @since 8.1
+ */
+std::list<AuthorityFactory::CelestialBodyInfo>
+AuthorityFactory::getCelestialBodyList() const {
+ std::string sql = "SELECT auth_name, name FROM celestial_body";
+ ListOfParams params;
+ if (d->hasAuthorityRestriction()) {
+ sql += " WHERE auth_name = ?";
+ params.emplace_back(d->authority());
+ }
+ sql += " ORDER BY auth_name, name";
+
+ auto sqlRes = d->run(sql, params);
+ std::list<AuthorityFactory::CelestialBodyInfo> res;
+ for (const auto &row : sqlRes) {
+ AuthorityFactory::CelestialBodyInfo info;
+ info.authName = row[0];
+ info.name = row[1];
+ res.emplace_back(info);
+ }
+ return res;
+}
+
+
+// ---------------------------------------------------------------------------
+
/** \brief Gets the official name from a possibly alias name.
*
* @param aliasedName Alias name.
diff --git a/src/proj.h b/src/proj.h
index f32e26b7..49bf991c 100644
--- a/src/proj.h
+++ b/src/proj.h
@@ -1028,6 +1028,22 @@ typedef struct
int deprecated;
} PROJ_UNIT_INFO;
+/** \brief Structure given description of a celestial body.
+ *
+ * This structure may grow over time, and should not be directly allocated by
+ * client code.
+ * @since 8.1
+ */
+typedef struct
+{
+ /** Authority name. */
+ char* auth_name;
+
+ /** Object name. For example "Earth" */
+ char* name;
+
+} PROJ_CELESTIAL_BODY_INFO;
+
/**@}*/
@@ -1183,6 +1199,13 @@ PROJ_STRING_LIST PROJ_DLL proj_get_codes_from_database(PJ_CONTEXT *ctx,
PJ_TYPE type,
int allow_deprecated);
+PROJ_CELESTIAL_BODY_INFO PROJ_DLL **proj_get_celestial_body_list_from_database(
+ PJ_CONTEXT *ctx,
+ const char *auth_name,
+ int *out_result_count);
+
+void PROJ_DLL proj_celestial_body_list_destroy(PROJ_CELESTIAL_BODY_INFO** list);
+
PROJ_CRS_LIST_PARAMETERS PROJ_DLL *proj_get_crs_list_parameters_create(void);
void PROJ_DLL proj_get_crs_list_parameters_destroy(
diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp
index ca41620e..964d25d9 100644
--- a/test/unit/test_c_api.cpp
+++ b/test/unit/test_c_api.cpp
@@ -3899,6 +3899,37 @@ TEST_F(CApi, proj_get_units_from_database) {
// ---------------------------------------------------------------------------
+TEST_F(CApi, proj_get_celestial_body_list_from_database) {
+ { proj_celestial_body_list_destroy(nullptr); }
+
+ {
+ auto list = proj_get_celestial_body_list_from_database(nullptr, nullptr, 0);
+ ASSERT_NE(list, nullptr);
+ ASSERT_NE(list[0], nullptr);
+ ASSERT_NE(list[0]->auth_name, nullptr);
+ ASSERT_NE(list[0]->name, nullptr);
+ proj_celestial_body_list_destroy(list);
+ }
+ {
+ int result_count = 0;
+ auto list = proj_get_celestial_body_list_from_database(nullptr, "ESRI", &result_count);
+ ASSERT_NE(list, nullptr);
+ EXPECT_GT(result_count, 1);
+ EXPECT_EQ(list[result_count], nullptr);
+ bool foundGanymede = false;
+ for (int i = 0; i < result_count; i++) {
+ EXPECT_EQ(std::string(list[i]->auth_name), "ESRI");
+ if (std::string(list[i]->name) == "Ganymede") {
+ foundGanymede = true;
+ }
+ }
+ EXPECT_TRUE(foundGanymede);
+ proj_celestial_body_list_destroy(list);
+ }
+}
+
+// ---------------------------------------------------------------------------
+
TEST_F(CApi, proj_normalize_for_visualization) {
{
diff --git a/test/unit/test_factory.cpp b/test/unit/test_factory.cpp
index edc8b190..02033a8a 100644
--- a/test/unit/test_factory.cpp
+++ b/test/unit/test_factory.cpp
@@ -3441,6 +3441,39 @@ TEST(factory, getUnitList) {
// ---------------------------------------------------------------------------
+TEST(factory, getCelestialBodyList) {
+ auto ctxt = DatabaseContext::create();
+ {
+ auto factory = AuthorityFactory::create(ctxt, std::string());
+ auto list = factory->getCelestialBodyList();
+ EXPECT_GT(list.size(), 1U);
+ bool foundPROJ = false;
+ bool foundESRI = false;
+ bool foundEarth = false;
+ for (const auto &info : list) {
+ foundESRI |= info.authName == "ESRI";
+ foundPROJ |= info.authName == "PROJ";
+ if (info.authName == "PROJ") {
+ EXPECT_EQ(info.name, "Earth");
+ foundEarth = true;
+ }
+ }
+ EXPECT_TRUE(foundESRI);
+ EXPECT_TRUE(foundPROJ);
+ EXPECT_TRUE(foundEarth);
+ }
+ {
+ auto factory = AuthorityFactory::create(ctxt, "ESRI");
+ auto list = factory->getCelestialBodyList();
+ EXPECT_GT(list.size(), 1U);
+ for (const auto &info : list) {
+ EXPECT_EQ(info.authName, "ESRI");
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------
+
TEST(factory, objectInsertion) {
// Cannot nest startInsertStatementsSession