diff options
Diffstat (limited to 'src/iso19111/c_api.cpp')
| -rw-r--r-- | src/iso19111/c_api.cpp | 112 |
1 files changed, 92 insertions, 20 deletions
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index 5df4c513..4c98af3d 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -1146,15 +1146,9 @@ PJ_OBJ_LIST *proj_get_non_deprecated(PJ_CONTEXT *ctx, const PJ *obj) { // --------------------------------------------------------------------------- -/** \brief Return whether two objects are equivalent. - * - * @param obj Object (must not be NULL) - * @param other Other object (must not be NULL) - * @param criterion Comparison criterion - * @return TRUE if they are equivalent - */ -int proj_is_equivalent_to(const PJ *obj, const PJ *other, - PJ_COMPARISON_CRITERION criterion) { +static int proj_is_equivalent_to_internal(PJ_CONTEXT *ctx, const PJ *obj, + const PJ *other, + PJ_COMPARISON_CRITERION criterion) { assert(obj); assert(other); if (!obj->iso_obj) { @@ -1176,7 +1170,50 @@ int proj_is_equivalent_to(const PJ *obj, const PJ *other, return IComparable::Criterion::EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS; })(criterion); - return obj->iso_obj->isEquivalentTo(other->iso_obj.get(), cppCriterion); + int res = obj->iso_obj->isEquivalentTo( + other->iso_obj.get(), cppCriterion, + ctx ? getDBcontextNoException(ctx, "proj_is_equivalent_to_with_ctx") + : nullptr); + if (ctx && ctx->cpp_context) { + ctx->cpp_context->autoCloseDbIfNeeded(); + } + return res; +} + +// --------------------------------------------------------------------------- + +/** \brief Return whether two objects are equivalent. + * + * Use proj_is_equivalent_to_with_ctx() to be able to use database information. + * + * @param obj Object (must not be NULL) + * @param other Other object (must not be NULL) + * @param criterion Comparison criterion + * @return TRUE if they are equivalent + */ +int proj_is_equivalent_to(const PJ *obj, const PJ *other, + PJ_COMPARISON_CRITERION criterion) { + return proj_is_equivalent_to_internal(nullptr, obj, other, criterion); +} + +// --------------------------------------------------------------------------- + +/** \brief Return whether two objects are equivalent + * + * Possibly using database to check for name aliases. + * + * @param ctx PROJ context, or NULL for default context + * @param obj Object (must not be NULL) + * @param other Other object (must not be NULL) + * @param criterion Comparison criterion + * @return TRUE if they are equivalent + * @since 6.3 + */ +int proj_is_equivalent_to_with_ctx(PJ_CONTEXT *ctx, const PJ *obj, + const PJ *other, + PJ_COMPARISON_CRITERION criterion) { + SANITIZE_CTX(ctx); + return proj_is_equivalent_to_internal(ctx, obj, other, criterion); } // --------------------------------------------------------------------------- @@ -2159,6 +2196,10 @@ PJ *proj_get_target_crs(PJ_CONTEXT *ctx, const PJ *obj) { * The candidate CRSs are either hard-coded, or looked in the database when * it is available. * + * Note that the implementation uses a set of heuristics to have a good + * compromise of successful identifications over execution time. It might miss + * legitimate matches in some circumstances. + * * The method returns a list of matching reference CRS, and the percentage * (0-100) of confidence in the match. The list is sorted by decreasing * confidence. @@ -2727,16 +2768,19 @@ static GeodeticReferenceFrameNNPtr createGeodeticReferenceFrame( if (metadata::Identifier::isEquivalentName( datumName.c_str(), refDatum->nameStr().c_str())) { datumName = refDatum->nameStr(); - } - } else { - std::string outTableName; - std::string authNameFromAlias; - std::string codeFromAlias; - auto officialName = authFactory->getOfficialNameFromAlias( - datumName, "geodetic_datum", std::string(), true, - outTableName, authNameFromAlias, codeFromAlias); - if (!officialName.empty()) { - datumName = officialName; + } else if (refDatum->identifiers().size() == 1) { + const auto &id = refDatum->identifiers()[0]; + const auto aliases = + authFactory->databaseContext()->getAliases( + *id->codeSpace(), id->code(), refDatum->nameStr(), + "geodetic_datum", std::string()); + for (const auto &alias : aliases) { + if (metadata::Identifier::isEquivalentName( + datumName.c_str(), alias.c_str())) { + datumName = refDatum->nameStr(); + break; + } + } } } } @@ -7783,6 +7827,34 @@ PJ *proj_normalize_for_visualization(PJ_CONTEXT *ctx, const PJ *obj) { // --------------------------------------------------------------------------- +/** \brief Returns a PJ* coordinate operation object which represents the + * inverse operation of the specified coordinate operation. + * + * @param ctx PROJ context, or NULL for default context + * @param obj Object of type CoordinateOperation (must not be NULL) + * @return a new PJ* object to free with proj_destroy() in case of success, or + * nullptr in case of error + * @since 6.3 + */ +PJ *proj_coordoperation_create_inverse(PJ_CONTEXT *ctx, const PJ *obj) { + + SANITIZE_CTX(ctx); + auto co = dynamic_cast<const CoordinateOperation *>(obj->iso_obj.get()); + if (!co) { + proj_log_error(ctx, __FUNCTION__, + "Object is not a CoordinateOperation"); + return nullptr; + } + try { + return pj_obj_create(ctx, co->inverse()); + } catch (const std::exception &e) { + proj_log_debug(ctx, __FUNCTION__, e.what()); + return nullptr; + } +} + +// --------------------------------------------------------------------------- + /** \brief Returns the number of steps of a concatenated operation. * * The input object must be a concatenated operation. |
