From 5078ce353450fc8746f508e1285d047d0ed6c31e Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 14 Apr 2020 23:58:51 +0200 Subject: createOperations(): do not remove ballpark transformation if there are only grid based operations, even if they cover the whole area of use (fixes #2143) --- src/iso19111/coordinateoperation.cpp | 55 +++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 24e82f7c..d038b5f9 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -10462,6 +10462,7 @@ struct CoordinateOperationContext::Private { std::vector> intermediateCRSAuthCodes_{}; bool discardSuperseded_ = true; + bool allowBallpark_ = true; }; //! @endcond @@ -10516,6 +10517,20 @@ void CoordinateOperationContext::setDesiredAccuracy(double accuracy) { // --------------------------------------------------------------------------- +/** \brief Return whether ballpark transformations are allowed */ +bool CoordinateOperationContext::getAllowBallparkTransformations() const { + return d->allowBallpark_; +} + +// --------------------------------------------------------------------------- + +/** \brief Set whether ballpark transformations are allowed */ +void CoordinateOperationContext::setAllowBallparkTransformations(bool allow) { + d->allowBallpark_ = allow; +} + +// --------------------------------------------------------------------------- + /** \brief Set how source and target CRS extent should be used * when considering if a transformation can be used (only takes effect if * no area of interest is explicitly defined). @@ -11185,7 +11200,7 @@ struct FilterResults { const CoordinateOperationContext::SourceTargetCRSExtentUse sourceAndTargetCRSExtentUse; - bool hasOpThatContainsAreaOfInterest = false; + bool hasOpThatContainsAreaOfInterestAndNoGrid = false; std::vector res{}; // ---------------------------------------------------------------------- @@ -11231,6 +11246,7 @@ struct FilterResults { STRICT_CONTAINMENT : context->getSpatialCriterion(); bool hasFoundOpWithExtent = false; + const bool allowBallpark = context->getAllowBallparkTransformations(); for (const auto &op : sourceList) { if (desiredAccuracy != 0) { const double accuracy = getAccuracy(op); @@ -11238,6 +11254,9 @@ struct FilterResults { continue; } } + if (!allowBallpark && op->hasBallparkTransformation()) { + continue; + } if (areaOfInterest) { bool emptyIntersection = false; auto extent = getExtent(op, true, emptyIntersection); @@ -11246,9 +11265,11 @@ struct FilterResults { hasFoundOpWithExtent = true; bool extentContains = extent->contains(NN_NO_CHECK(areaOfInterest)); - if (extentContains) { - if (!op->hasBallparkTransformation()) { - hasOpThatContainsAreaOfInterest = true; + if (!hasOpThatContainsAreaOfInterestAndNoGrid && + extentContains) { + if (!op->hasBallparkTransformation() && + op->gridsNeeded(nullptr, true).empty()) { + hasOpThatContainsAreaOfInterestAndNoGrid = true; } } if (spatialCriterion == @@ -11275,9 +11296,11 @@ struct FilterResults { !extent1 || extent->contains(NN_NO_CHECK(extent1)); bool extentContainsExtent2 = !extent2 || extent->contains(NN_NO_CHECK(extent2)); - if (extentContainsExtent1 && extentContainsExtent2) { - if (!op->hasBallparkTransformation()) { - hasOpThatContainsAreaOfInterest = true; + if (!hasOpThatContainsAreaOfInterestAndNoGrid && + extentContainsExtent1 && extentContainsExtent2) { + if (!op->hasBallparkTransformation() && + op->gridsNeeded(nullptr, true).empty()) { + hasOpThatContainsAreaOfInterestAndNoGrid = true; } } if (spatialCriterion == @@ -11311,6 +11334,9 @@ struct FilterResults { continue; } } + if (!allowBallpark && op->hasBallparkTransformation()) { + continue; + } res.emplace_back(op); } } @@ -11444,12 +11470,13 @@ struct FilterResults { // If we have more than one result, and than the last result is the // default "Ballpark geographic offset" or "Ballpark geocentric - // translation" - // operations we have synthetized, and that at least one operation - // has the desired area of interest, remove it as - // all previous results are necessarily better - if (hasOpThatContainsAreaOfInterest && res.size() > 1) { - const std::string &name = res.back()->nameStr(); + // translation" operations we have synthetized, and that at least one + // operation has the desired area of interest and does not require the + // use of grids, remove it as all previous results are necessarily + // better + if (hasOpThatContainsAreaOfInterestAndNoGrid && res.size() > 1) { + const auto &opLast = res.back(); + const std::string &name = opLast->nameStr(); if (name.find(BALLPARK_GEOGRAPHIC_OFFSET) != std::string::npos || name.find(NULL_GEOGRAPHIC_OFFSET) != std::string::npos || name.find(NULL_GEOCENTRIC_TRANSLATION) != std::string::npos || @@ -14770,7 +14797,7 @@ void CoordinateOperationFactory::Private::createOperationsCompoundToCompound( } } - // If we didn't find a non-ballbark transformation between + // If we didn't find a non-ballpark transformation between // the 2 vertical CRS, then try through intermediate geographic CRS // For example // WGS 84 + EGM96 --> ETRS89 + Belfast height where -- cgit v1.2.3 From 953ff68cbd444046f2aa2f8b305c1d7cb258cc8a Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 14 Apr 2020 23:59:26 +0200 Subject: lookForGridAlternative(): fix bug with Dutch 2008 grids --- src/iso19111/factory.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index b60ce9f9..f6650055 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -926,7 +926,8 @@ bool DatabaseContext::lookForGridAlternative(const std::string &officialName, bool &inverse) const { auto res = d->run( "SELECT proj_grid_name, proj_grid_format, inverse_direction FROM " - "grid_alternatives WHERE original_grid_name = ?", + "grid_alternatives WHERE original_grid_name = ? AND " + "proj_grid_name <> ''", {officialName}); if (res.empty()) { return false; -- cgit v1.2.3