diff options
| author | Alan D. Snow <alansnow21@gmail.com> | 2021-04-18 05:34:29 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-04-18 12:34:29 +0200 |
| commit | e4e2991b174ea48b67e9b41c8f356a9cf1bba081 (patch) | |
| tree | d523f7534caf2662f1b97d5e8e40b5d16886c998 | |
| parent | 3d1c573dc9d9f56ced597554ad9fa1643f0a0ae9 (diff) | |
| download | PROJ-e4e2991b174ea48b67e9b41c8f356a9cf1bba081.tar.gz PROJ-e4e2991b174ea48b67e9b41c8f356a9cf1bba081.zip | |
Added proj_get_celestial_body_list_from_database (#2674)
Closes #2667
| -rw-r--r-- | include/proj/io.hpp | 13 | ||||
| -rw-r--r-- | scripts/reference_exported_symbols.txt | 4 | ||||
| -rw-r--r-- | src/iso19111/c_api.cpp | 70 | ||||
| -rw-r--r-- | src/iso19111/factory.cpp | 37 | ||||
| -rw-r--r-- | src/proj.h | 23 | ||||
| -rw-r--r-- | test/unit/test_c_api.cpp | 31 | ||||
| -rw-r--r-- | test/unit/test_factory.cpp | 33 |
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. @@ -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 |
