diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2020-03-12 23:10:20 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2020-03-13 08:45:56 +0100 |
| commit | f0d6b64fee8b796ec038929187b7b725f62a5ba8 (patch) | |
| tree | b32badffae5470b2f318d4a0a98cc27443bbd75a /src/iso19111/c_api.cpp | |
| parent | ca3caf0e976e95a739963567057654cb8909bfb9 (diff) | |
| download | PROJ-f0d6b64fee8b796ec038929187b7b725f62a5ba8.tar.gz PROJ-f0d6b64fee8b796ec038929187b7b725f62a5ba8.zip | |
Add proj_get_suggested_operation()
Return the index of the operation that would be the most appropriate to
transform the specified coordinates.
This operation may use resources that are not locally available, depending
on the search criteria used by proj_create_operations().
This could be done by using proj_create_operations() with a punctual bounding
box, but this function is faster when one needs to evaluate on many points
with the same (source_crs, target_crs) tuple.
Diffstat (limited to 'src/iso19111/c_api.cpp')
| -rw-r--r-- | src/iso19111/c_api.cpp | 109 |
1 files changed, 106 insertions, 3 deletions
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index d5f299c2..d9def9d6 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -216,12 +216,17 @@ struct PJ_OBJ_LIST { explicit PJ_OBJ_LIST(std::vector<IdentifiedObjectNNPtr> &&objectsIn) : objects(std::move(objectsIn)) {} + virtual ~PJ_OBJ_LIST(); PJ_OBJ_LIST(const PJ_OBJ_LIST &) = delete; PJ_OBJ_LIST &operator=(const PJ_OBJ_LIST &) = delete; //! @endcond }; +//! @cond Doxygen_Suppress +PJ_OBJ_LIST::~PJ_OBJ_LIST() = default; +//! @endcond + // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress @@ -7406,6 +7411,62 @@ void PROJ_DLL proj_operation_factory_context_set_discard_superseded( // --------------------------------------------------------------------------- +//! @cond Doxygen_Suppress +/** \brief Opaque object representing a set of operation results. */ +struct PJ_OPERATION_LIST : PJ_OBJ_LIST { + + PJ *source_crs; + PJ *target_crs; + bool hasPreparedOperation = false; + std::vector<CoordOperation> preparedOperations{}; + + explicit PJ_OPERATION_LIST(PJ_CONTEXT *ctx, const PJ *source_crsIn, + const PJ *target_crsIn, + std::vector<IdentifiedObjectNNPtr> &&objectsIn); + ~PJ_OPERATION_LIST() override; + + PJ_OPERATION_LIST(const PJ_OPERATION_LIST &) = delete; + PJ_OPERATION_LIST &operator=(const PJ_OPERATION_LIST &) = delete; + + const std::vector<CoordOperation> &getPreparedOperations(PJ_CONTEXT *ctx); +}; + +// --------------------------------------------------------------------------- + +PJ_OPERATION_LIST::PJ_OPERATION_LIST( + PJ_CONTEXT *ctx, const PJ *source_crsIn, const PJ *target_crsIn, + std::vector<IdentifiedObjectNNPtr> &&objectsIn) + : PJ_OBJ_LIST(std::move(objectsIn)), + source_crs(proj_clone(ctx, source_crsIn)), + target_crs(proj_clone(ctx, target_crsIn)) {} + +// --------------------------------------------------------------------------- + +PJ_OPERATION_LIST::~PJ_OPERATION_LIST() { + auto tmpCtxt = proj_context_create(); + proj_assign_context(source_crs, tmpCtxt); + proj_assign_context(target_crs, tmpCtxt); + proj_destroy(source_crs); + proj_destroy(target_crs); + proj_context_destroy(tmpCtxt); +} + +// --------------------------------------------------------------------------- + +const std::vector<CoordOperation> & +PJ_OPERATION_LIST::getPreparedOperations(PJ_CONTEXT *ctx) { + if (!hasPreparedOperation) { + hasPreparedOperation = true; + preparedOperations = + pj_create_prepared_operations(ctx, source_crs, target_crs, this); + } + return preparedOperations; +} + +//! @endcond + +// --------------------------------------------------------------------------- + /** \brief Find a list of CoordinateOperation from source_crs to target_crs. * * The operations are sorted with the most relevant ones first: by @@ -7457,7 +7518,8 @@ proj_create_operations(PJ_CONTEXT *ctx, const PJ *source_crs, for (const auto &op : ops) { objects.emplace_back(op); } - return new PJ_OBJ_LIST(std::move(objects)); + return new PJ_OPERATION_LIST(ctx, source_crs, target_crs, + std::move(objects)); } catch (const std::exception &e) { proj_log_error(ctx, __FUNCTION__, e.what()); return nullptr; @@ -7466,6 +7528,47 @@ proj_create_operations(PJ_CONTEXT *ctx, const PJ *source_crs, // --------------------------------------------------------------------------- +/** Return the index of the operation that would be the most appropriate to + * transform the specified coordinates. + * + * This operation may use resources that are not locally available, depending + * on the search criteria used by proj_create_operations(). + * + * This could be done by using proj_create_operations() with a punctual bounding + * box, but this function is faster when one needs to evaluate on many points + * with the same (source_crs, target_crs) tuple. + * + * @param ctx PROJ context, or NULL for default context + * @param operations List of operations returned by proj_create_operations() + * @param direction Direction into which to transform the point. + * @param coord Coordinate to transform + * @return the index in operations that would be used to transform coord. Or -1 + * in case of error, or no match. + * + * @since 7.1 + */ +int proj_get_suggested_operation(PJ_CONTEXT *ctx, PJ_OBJ_LIST *operations, + PJ_DIRECTION direction, PJ_COORD coord) { + SANITIZE_CTX(ctx); + auto opList = dynamic_cast<PJ_OPERATION_LIST *>(operations); + if (opList == nullptr) { + proj_log_error(ctx, __FUNCTION__, + "operations is not a list of operations"); + return -1; + } + + int iExcluded[2] = {-1, -1}; + const auto &preparedOps = opList->getPreparedOperations(ctx); + int idx = pj_get_suggested_operation(ctx, preparedOps, iExcluded, direction, + coord); + if (idx >= 0) { + idx = preparedOps[idx].idxInOriginalList; + } + return idx; +} + +// --------------------------------------------------------------------------- + /** \brief Return the number of objects in the result set * * @param result Object of type PJ_OBJ_LIST (must not be NULL) @@ -7787,8 +7890,8 @@ PJ *proj_normalize_for_visualization(PJ_CONTEXT *ctx, const PJ *obj) { } } pjNew->alternativeCoordinateOperations.emplace_back( - minxSrc, minySrc, maxxSrc, maxySrc, minxDst, minyDst, - maxxDst, maxyDst, + alt.idxInOriginalList, minxSrc, minySrc, maxxSrc, + maxySrc, minxDst, minyDst, maxxDst, maxyDst, pj_obj_create(ctx, co->normalizeForVisualization()), co->nameStr(), alt.accuracy, alt.isOffshore); } |
