diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2020-04-04 01:28:11 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-04-04 01:28:11 +0200 |
| commit | 670eab68f2345b2a77bfac8a109588770bceb740 (patch) | |
| tree | 4f0ecbe08d2ab975966d65f85e4485e4f4050324 /src | |
| parent | 1a8933942cf92d0724cc168d04302d8b78c3814f (diff) | |
| parent | bb770de3b7cb04aad8116ed84a5815b7f6f7a82c (diff) | |
| download | PROJ-670eab68f2345b2a77bfac8a109588770bceb740.tar.gz PROJ-670eab68f2345b2a77bfac8a109588770bceb740.zip | |
Merge pull request #2126 from rouault/createFromUserInput_compoundCRS_from_names
createFromUserInput(): allow compound CRS with the 2 parts given by names, e.g. 'WGS 84 + EGM96 height'
Diffstat (limited to 'src')
| -rw-r--r-- | src/iso19111/c_api.cpp | 4 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 107 |
2 files changed, 89 insertions, 22 deletions
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index 17fbd079..5a3f0374 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -427,7 +427,9 @@ PJ *proj_clone(PJ_CONTEXT *ctx, const PJ *obj) { /** \brief Instantiate an object from a WKT string, PROJ string, object code * (like "EPSG:4326", "urn:ogc:def:crs:EPSG::4326", - * "urn:ogc:def:coordinateOperation:EPSG::1671") or PROJJSON string. + * "urn:ogc:def:coordinateOperation:EPSG::1671"), a PROJJSON string, an object + * name (e.g "WGS 84") of a compound CRS build from object names + * (e.g "WGS 84 + EGM96 height") * * This function calls osgeo::proj::io::createFromUserInput() * diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 8bfb4395..dfc1aa27 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -6025,32 +6025,20 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text, if (dbContext) { auto factory = AuthorityFactory::create(NN_NO_CHECK(dbContext), std::string()); - // First pass: exact match on CRS objects - // Second pass: exact match on other objects - // Third pass: approximate match on CRS objects - // Fourth pass: approximate match on other objects - constexpr size_t limitResultCount = 10; - for (int pass = 0; pass <= 3; ++pass) { - const bool approximateMatch = (pass >= 2); + + const auto searchObject = [&factory]( + const std::string &objectName, bool approximateMatch, + const std::vector<AuthorityFactory::ObjectType> &objectTypes, + bool &goOn) { + constexpr size_t limitResultCount = 10; auto res = factory->createObjectsFromName( - text, - (pass == 0 || pass == 2) - ? std::vector< - AuthorityFactory::ObjectType>{AuthorityFactory:: - ObjectType::CRS} - : std::vector< - AuthorityFactory:: - ObjectType>{AuthorityFactory::ObjectType:: - ELLIPSOID, - AuthorityFactory::ObjectType::DATUM, - AuthorityFactory::ObjectType:: - COORDINATE_OPERATION}, - approximateMatch, limitResultCount); + objectName, objectTypes, approximateMatch, limitResultCount); if (res.size() == 1) { return res.front(); } if (res.size() > 1) { - if (pass == 0 || pass == 2) { + if (objectTypes.size() == 1 && + objectTypes[0] == AuthorityFactory::ObjectType::CRS) { for (size_t ndim = 2; ndim <= 3; ndim++) { for (const auto &obj : res) { auto crs = @@ -6079,6 +6067,79 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text, } throw ParsingException(msg); } + goOn = true; + throw ParsingException("dummy"); + }; + + const auto searchCRS = [&searchObject](const std::string &objectName) { + bool goOn = false; + const auto objectTypes = std::vector<AuthorityFactory::ObjectType>{ + AuthorityFactory::ObjectType::CRS}; + try { + constexpr bool approximateMatch = false; + return searchObject(objectName, approximateMatch, objectTypes, + goOn); + } catch (const std::exception &) { + if (!goOn) + throw; + } + constexpr bool approximateMatch = true; + return searchObject(objectName, approximateMatch, objectTypes, + goOn); + }; + + // strings like "WGS 84 + EGM96 height" + CompoundCRSPtr compoundCRS; + try { + const auto tokensCompound = split(text, " + "); + if (tokensCompound.size() == 2) { + auto obj1 = searchCRS(tokensCompound[0]); + auto obj2 = searchCRS(tokensCompound[1]); + auto crs1 = util::nn_dynamic_pointer_cast<CRS>(obj1); + auto crs2 = util::nn_dynamic_pointer_cast<CRS>(obj2); + if (crs1 && crs2) { + compoundCRS = + CompoundCRS::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + crs1->nameStr() + " + " + + crs2->nameStr()), + {NN_NO_CHECK(crs1), NN_NO_CHECK(crs2)}) + .as_nullable(); + } + } + } catch (const std::exception &) { + } + + // First pass: exact match on CRS objects + // Second pass: exact match on other objects + // Third pass: approximate match on CRS objects + // Fourth pass: approximate match on other objects + for (int pass = 0; pass <= 3; ++pass) { + const bool approximateMatch = (pass >= 2); + bool goOn = false; + try { + return searchObject( + text, approximateMatch, + (pass == 0 || pass == 2) + ? std::vector< + AuthorityFactory::ObjectType>{AuthorityFactory:: + ObjectType::CRS} + : std::vector< + AuthorityFactory:: + ObjectType>{AuthorityFactory::ObjectType:: + ELLIPSOID, + AuthorityFactory::ObjectType:: + DATUM, + AuthorityFactory::ObjectType:: + COORDINATE_OPERATION}, + goOn); + } catch (const std::exception &) { + if (!goOn) + throw; + } + if (compoundCRS) { + return NN_NO_CHECK(compoundCRS); + } } } @@ -6114,6 +6175,8 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text, * <li>an Object name. e.g "WGS 84", "WGS 84 / UTM zone 31N". In that case as * uniqueness is not guaranteed, the function may apply heuristics to * determine the appropriate best match.</li> + * <li>a compound CRS made from two object names separated with " + ". + * e.g. "WGS 84 + EGM96 height"</li> * <li>PROJJSON string</li> * </ul> * @@ -6163,6 +6226,8 @@ BaseObjectNNPtr createFromUserInput(const std::string &text, * <li>an Object name. e.g "WGS 84", "WGS 84 / UTM zone 31N". In that case as * uniqueness is not guaranteed, the function may apply heuristics to * determine the appropriate best match.</li> + * <li>a compound CRS made from two object names separated with " + ". + * e.g. "WGS 84 + EGM96 height"</li> * <li>PROJJSON string</li> * </ul> * |
