diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2019-10-04 01:13:43 +0200 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2019-10-04 01:13:43 +0200 |
| commit | ae779eaa8264914a401f585f747a0f87fd5350e9 (patch) | |
| tree | a82bfb05cf329f05fb2563389b9efe5f002595e9 /src | |
| parent | 109f75c74ee9e251b9507aeb5f3add109042bd5f (diff) | |
| download | PROJ-ae779eaa8264914a401f585f747a0f87fd5350e9.tar.gz PROJ-ae779eaa8264914a401f585f747a0f87fd5350e9.zip | |
Add a proj_crs_demote_to_2D(). Useful if forced to export a 3D CRS to a best approximate as WKT1 that doesn't support it
Diffstat (limited to 'src')
| -rw-r--r-- | src/iso19111/c_api.cpp | 42 | ||||
| -rw-r--r-- | src/iso19111/crs.cpp | 81 | ||||
| -rw-r--r-- | src/proj_experimental.h | 4 |
3 files changed, 127 insertions, 0 deletions
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index ac3a5f11..4fedbe05 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -3388,6 +3388,48 @@ PJ *proj_crs_create_projected_3D_crs_from_2D(PJ_CONTEXT *ctx, // --------------------------------------------------------------------------- +/** \brief Create a 2D CRS from an existing 3D CRS. + * + * See osgeo::proj::crs::CRS::demoteTo2D(). + * + * The returned object must be unreferenced with proj_destroy() 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_2D_name CRS name. Or NULL (in which case the name of crs_3D + * will be used) + * @param crs_3D 3D CRS to be "demoted" to 2D. Must not be NULL. + * + * @return Object that must be unreferenced with + * proj_destroy(), or NULL in case of error. + * @since 7.0 + */ +PJ *proj_crs_demote_to_2D(PJ_CONTEXT *ctx, const char *crs_2D_name, + const PJ *crs_3D) { + SANITIZE_CTX(ctx); + auto cpp_3D_crs = dynamic_cast<const CRS *>(crs_3D->iso_obj.get()); + if (!cpp_3D_crs) { + proj_log_error(ctx, __FUNCTION__, "crs_3D is not a CRS"); + return nullptr; + } + try { + auto dbContext = getDBcontextNoException(ctx, __FUNCTION__); + return pj_obj_create( + ctx, cpp_3D_crs->demoteTo2D(crs_2D_name ? std::string(crs_2D_name) + : cpp_3D_crs->nameStr(), + dbContext)); + } catch (const std::exception &e) { + proj_log_error(ctx, __FUNCTION__, e.what()); + if (ctx->cpp_context) { + ctx->cpp_context->autoCloseDbIfNeeded(); + } + return nullptr; + } +} + +// --------------------------------------------------------------------------- + /** \brief Instantiate a EngineeringCRS with just a name * * The returned object must be unreferenced with proj_destroy() after diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index d0e23f95..b98e5937 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -843,6 +843,49 @@ CRSNNPtr CRS::promoteTo3D(const std::string &newName, return NN_NO_CHECK( std::static_pointer_cast<CRS>(shared_from_this().as_nullable())); } +// --------------------------------------------------------------------------- + +/** \brief Return a variant of this CRS "demoted" to a 2D one, if not already + * the case. + * + * + * @param newName Name of the new CRS. If empty, nameStr() will be used. + * @param dbContext Database context to look for potentially already registered + * 2D CRS. May be nullptr. + * @return a new CRS demoted to 2D, or the current one if already 2D or not + * applicable. + * @since 7.0 + */ +CRSNNPtr CRS::demoteTo2D(const std::string &newName, + const io::DatabaseContextPtr &dbContext) const { + const auto geogCRS = dynamic_cast<const GeographicCRS *>(this); + if (geogCRS) { + return geogCRS->demoteTo2D(newName, dbContext); + } + + const auto projCRS = dynamic_cast<const ProjectedCRS *>(this); + if (projCRS) { + return projCRS->demoteTo2D(newName, dbContext); + } + + const auto boundCRS = dynamic_cast<const BoundCRS *>(this); + if (boundCRS) { + return BoundCRS::create( + boundCRS->baseCRS()->demoteTo2D(newName, dbContext), + boundCRS->hubCRS(), boundCRS->transformation()); + } + + const auto compoundCRS = dynamic_cast<const CompoundCRS *>(this); + if (compoundCRS) { + const auto &components = compoundCRS->componentReferenceSystems(); + if (components.size() >= 2) { + return components[0]; + } + } + + return NN_NO_CHECK( + std::static_pointer_cast<CRS>(shared_from_this().as_nullable())); +} // --------------------------------------------------------------------------- @@ -3650,6 +3693,44 @@ ProjectedCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const { // --------------------------------------------------------------------------- +/** \brief Return a variant of this CRS "demoted" to a 2D one, if not already + * the case. + * + * + * @param newName Name of the new CRS. If empty, nameStr() will be used. + * @param dbContext Database context to look for potentially already registered + * 2D CRS. May be nullptr. + * @return a new CRS demoted to 2D, or the current one if already 2D or not + * applicable. + * @since 7.0 + */ +ProjectedCRSNNPtr +ProjectedCRS::demoteTo2D(const std::string &newName, + const io::DatabaseContextPtr &dbContext) const { + + const auto &axisList = coordinateSystem()->axisList(); + if (axisList.size() == 3) { + auto cs = cs::CartesianCS::create(util::PropertyMap(), axisList[0], + axisList[1]); + const auto &l_baseCRS = baseCRS(); + const auto geogCRS = + dynamic_cast<const GeographicCRS *>(l_baseCRS.get()); + const auto newBaseCRS = + geogCRS ? util::nn_static_pointer_cast<GeodeticCRS>( + geogCRS->demoteTo2D(std::string(), dbContext)) + : l_baseCRS; + return ProjectedCRS::create( + util::PropertyMap().set(common::IdentifiedObject::NAME_KEY, + !newName.empty() ? newName : nameStr()), + newBaseCRS, derivingConversionRef(), cs); + } + + return NN_NO_CHECK(std::dynamic_pointer_cast<ProjectedCRS>( + shared_from_this().as_nullable())); +} + +// --------------------------------------------------------------------------- + //! @cond Doxygen_Suppress std::list<std::pair<CRSNNPtr, int>> diff --git a/src/proj_experimental.h b/src/proj_experimental.h index 9a1a6045..63b858d5 100644 --- a/src/proj_experimental.h +++ b/src/proj_experimental.h @@ -235,6 +235,10 @@ PJ PROJ_DLL *proj_crs_create_projected_3D_crs_from_2D(PJ_CONTEXT *ctx, const PJ* projected_2D_crs, const PJ* geog_3D_crs); +PJ PROJ_DLL *proj_crs_demote_to_2D(PJ_CONTEXT *ctx, + const char* crs_2D_name, + const PJ* crs_3D); + PJ PROJ_DLL *proj_create_engineering_crs(PJ_CONTEXT *ctx, const char *crsName); |
