From a9ef3a229c6fef5ef8a05ba521a0237f2ffa6aa6 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 6 Dec 2018 16:23:07 +0100 Subject: Coordinate operation search: add a authority_to_authority_preference table to restrict and prioritize searches --- src/coordinateoperation.cpp | 100 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 21 deletions(-) (limited to 'src/coordinateoperation.cpp') diff --git a/src/coordinateoperation.cpp b/src/coordinateoperation.cpp index 04f9bc9a..d187f2cc 100644 --- a/src/coordinateoperation.cpp +++ b/src/coordinateoperation.cpp @@ -8937,6 +8937,14 @@ CoordinateOperationContext::getIntermediateCRS() const { * If a non null authorityFactory is provided, the resulting context should * not be used simultaneously by more than one thread. * + * If authorityFactory->getAuthority() is the empty string, then coordinate + * operations from any authority will be searched, with the restrictions set + * in the authority_to_authority_preference database table. + * If authorityFactory->getAuthority() is set to "any", then coordinate + * operations from any authority will be searched + * If authorityFactory->getAuthority() is a non-empty string different of "any", + * then coordinate operatiosn will be searched only in that authority namespace. + * * @param authorityFactory Authority factory, or null if no database lookup * is allowed. * Use io::authorityFactory::create(context, std::string()) to allow all @@ -9663,6 +9671,8 @@ findOpsInRegistryDirect(const crs::CRSNNPtr &sourceCRS, const CoordinateOperationContextNNPtr &context) { const auto &authFactory = context->getAuthorityFactory(); assert(authFactory); + const auto &authFactoryName = authFactory->getAuthority(); + for (const auto &idSrc : sourceCRS->identifiers()) { const auto &srcAuthName = *(idSrc->codeSpace()); const auto &srcCode = idSrc->code(); @@ -9671,17 +9681,39 @@ findOpsInRegistryDirect(const crs::CRSNNPtr &sourceCRS, const auto &targetAuthName = *(idTarget->codeSpace()); const auto &targetCode = idTarget->code(); if (!targetAuthName.empty()) { - auto res = - authFactory->createFromCoordinateReferenceSystemCodes( - srcAuthName, srcCode, targetAuthName, targetCode, - context->getUsePROJAlternativeGridNames(), - context->getGridAvailabilityUse() == - CoordinateOperationContext:: - GridAvailabilityUse:: - DISCARD_OPERATION_IF_MISSING_GRID, - context->getDiscardSuperseded()); - if (!res.empty()) { - return res; + std::vector authorities; + if (authFactoryName == "any") { + authorities.emplace_back(); + } + if (authFactoryName.empty()) { + authorities = authFactory->databaseContext() + ->getAllowedAuthorities( + srcAuthName, targetAuthName); + if (authorities.empty()) { + authorities.emplace_back(); + } + } else { + authorities.emplace_back(authFactoryName); + } + for (const auto &authority : authorities) { + const auto tmpAuthFactory = + io::AuthorityFactory::create( + authFactory->databaseContext(), + authority == "any" ? std::string() : authority); + auto res = + tmpAuthFactory + ->createFromCoordinateReferenceSystemCodes( + srcAuthName, srcCode, targetAuthName, + targetCode, + context->getUsePROJAlternativeGridNames(), + context->getGridAvailabilityUse() == + CoordinateOperationContext:: + GridAvailabilityUse:: + DISCARD_OPERATION_IF_MISSING_GRID, + context->getDiscardSuperseded()); + if (!res.empty()) { + return res; + } } } } @@ -9706,6 +9738,8 @@ static std::vector findsOpsInRegistryWithIntermediate( const auto &authFactory = context->getAuthorityFactory(); assert(authFactory); + const auto &authFactoryName = authFactory->getAuthority(); + for (const auto &idSrc : sourceCRS->identifiers()) { const auto &srcAuthName = *(idSrc->codeSpace()); const auto &srcCode = idSrc->code(); @@ -9714,16 +9748,40 @@ static std::vector findsOpsInRegistryWithIntermediate( const auto &targetAuthName = *(idTarget->codeSpace()); const auto &targetCode = idTarget->code(); if (!targetAuthName.empty()) { - auto res = authFactory->createFromCRSCodesWithIntermediates( - srcAuthName, srcCode, targetAuthName, targetCode, - context->getUsePROJAlternativeGridNames(), - context->getGridAvailabilityUse() == - CoordinateOperationContext::GridAvailabilityUse:: - DISCARD_OPERATION_IF_MISSING_GRID, - context->getDiscardSuperseded(), - context->getIntermediateCRS()); - if (!res.empty()) { - return res; + std::vector authorities; + if (authFactoryName == "any") { + authorities.emplace_back(); + } + if (authFactoryName.empty()) { + authorities = authFactory->databaseContext() + ->getAllowedAuthorities( + srcAuthName, targetAuthName); + if (authorities.empty()) { + authorities.emplace_back(); + } + } else { + authorities.emplace_back(authFactoryName); + } + for (const auto &authority : authorities) { + const auto tmpAuthFactory = + io::AuthorityFactory::create( + authFactory->databaseContext(), + authority == "any" ? std::string() : authority); + + auto res = + tmpAuthFactory->createFromCRSCodesWithIntermediates( + srcAuthName, srcCode, targetAuthName, + targetCode, + context->getUsePROJAlternativeGridNames(), + context->getGridAvailabilityUse() == + CoordinateOperationContext:: + GridAvailabilityUse:: + DISCARD_OPERATION_IF_MISSING_GRID, + context->getDiscardSuperseded(), + context->getIntermediateCRS()); + if (!res.empty()) { + return res; + } } } } -- cgit v1.2.3 From 4022e2093a6773458c2453e42089c987da6efbf9 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 6 Dec 2018 19:40:13 +0100 Subject: Fix special handling of Azimuth parameter of Krovak --- src/coordinateoperation.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/coordinateoperation.cpp') diff --git a/src/coordinateoperation.cpp b/src/coordinateoperation.cpp index d187f2cc..ced0ab9f 100644 --- a/src/coordinateoperation.cpp +++ b/src/coordinateoperation.cpp @@ -5177,7 +5177,9 @@ void Conversion::_exportToPROJString( double latitudePseudoStandardParallel = parameterValueNumeric( EPSG_CODE_PARAMETER_LATITUDE_PSEUDO_STANDARD_PARALLEL, common::UnitOfMeasure::DEGREE); - if (std::fabs(colatitude - 30.28813972222222) > 1e-8) { + // 30deg 17' 17.30311'' = 30.28813975277777776 + // 30deg 17' 17.303'' = 30.288139722222223 as used in GDAL WKT1 + if (std::fabs(colatitude - 30.2881397) > 1e-7) { throw io::FormattingException( std::string("Unsupported value for ") + EPSG_NAME_PARAMETER_COLATITUDE_CONE_AXIS); -- cgit v1.2.3 From 263b259b276edd075b0abcd6aad0e923230c2d15 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 7 Dec 2018 02:22:20 +0100 Subject: Various speed optimizations --- src/coordinateoperation.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/coordinateoperation.cpp') diff --git a/src/coordinateoperation.cpp b/src/coordinateoperation.cpp index ced0ab9f..8f75864e 100644 --- a/src/coordinateoperation.cpp +++ b/src/coordinateoperation.cpp @@ -2055,8 +2055,7 @@ static util::PropertyMap createMethodMapNameEPSGCode(int code) { static util::PropertyMap getUTMConversionProperty(const util::PropertyMap &properties, int zone, bool north) { - if (properties.find(common::IdentifiedObject::NAME_KEY) == - properties.end()) { + if (!properties.get(common::IdentifiedObject::NAME_KEY)) { std::string conversionName("UTM zone "); conversionName += toString(zone); conversionName += (north ? 'N' : 'S'); @@ -2073,8 +2072,7 @@ getUTMConversionProperty(const util::PropertyMap &properties, int zone, static util::PropertyMap addDefaultNameIfNeeded(const util::PropertyMap &properties, const std::string &defaultName) { - if (properties.find(common::IdentifiedObject::NAME_KEY) == - properties.end()) { + if (!properties.get(common::IdentifiedObject::NAME_KEY)) { return util::PropertyMap(properties) .set(common::IdentifiedObject::NAME_KEY, defaultName); } else { @@ -9579,6 +9577,10 @@ struct FilterAndSort { // cppcheck-suppress functionStatic void removeDuplicateOps() { + if (res.size() <= 1) { + return; + } + // When going from EPSG:4807 (NTF Paris) to EPSG:4171 (RGC93), we get // EPSG:7811, NTF (Paris) to RGF93 (2), 1 m // and unknown id, NTF (Paris) to NTF (1) + Inverse of RGF93 to NTF (2), -- cgit v1.2.3