diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2020-09-18 13:31:36 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-09-18 13:31:36 +0200 |
| commit | 81aaa47b4e1f7799ad59f07d738823184f20a9cf (patch) | |
| tree | 448fb1ab3c3152224450b6a07f723ba14623b727 /src | |
| parent | 1e11bf646d2cf9b731b02f2260c68fe2a5a21cf4 (diff) | |
| parent | 75074ce863e36299ec39b39decdd435eed15ad63 (diff) | |
| download | PROJ-81aaa47b4e1f7799ad59f07d738823184f20a9cf.tar.gz PROJ-81aaa47b4e1f7799ad59f07d738823184f20a9cf.zip | |
Merge pull request #2357 from rouault/fix_2356
Adjust createBoundCRSToWGS84IfPossible() and operation filtering (for POSGAR 2007 to WGS84 issues) (fixes #2356)
Diffstat (limited to 'src')
| -rw-r--r-- | src/iso19111/coordinateoperation.cpp | 133 | ||||
| -rw-r--r-- | src/iso19111/crs.cpp | 25 |
2 files changed, 69 insertions, 89 deletions
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 10b1baf4..65ef2b77 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -11380,8 +11380,31 @@ struct SortFunction { return false; } - // Arbitrary final criterion - return a_name < b_name; + // Arbitrary final criterion. We actually return the greater element + // first, so that "Amersfoort to WGS 84 (4)" is presented before + // "Amersfoort to WGS 84 (3)", which is probably a better guess. + + // Except for French NTF (Paris) to NTF, where the (1) conversion + // should be preferred because in the remarks of (2), it is mentionned + // OGP prefers value from IGN Paris (code 1467)... + if (a_name.find("NTF (Paris) to NTF (1)") != std::string::npos && + b_name.find("NTF (Paris) to NTF (2)") != std::string::npos) { + return true; + } + if (a_name.find("NTF (Paris) to NTF (2)") != std::string::npos && + b_name.find("NTF (Paris) to NTF (1)") != std::string::npos) { + return false; + } + if (a_name.find("NTF (Paris) to RGF93 (1)") != std::string::npos && + b_name.find("NTF (Paris) to RGF93 (2)") != std::string::npos) { + return true; + } + if (a_name.find("NTF (Paris) to RGF93 (2)") != std::string::npos && + b_name.find("NTF (Paris) to RGF93 (1)") != std::string::npos) { + return false; + } + + return a_name > b_name; } bool operator()(const CoordinateOperationNNPtr &a, @@ -11407,6 +11430,23 @@ static size_t getStepCount(const CoordinateOperationNNPtr &op) { // --------------------------------------------------------------------------- +// Return number of steps that are transformations (and not conversions) +static size_t getTransformationStepCount(const CoordinateOperationNNPtr &op) { + auto concat = dynamic_cast<const ConcatenatedOperation *>(op.get()); + size_t stepCount = 1; + if (concat) { + stepCount = 0; + for (const auto &subOp : concat->operations()) { + if (dynamic_cast<const Conversion *>(subOp.get()) == nullptr) { + stepCount++; + } + } + } + return stepCount; +} + +// --------------------------------------------------------------------------- + static bool isNullTransformation(const std::string &name) { if (name.find(" + ") != std::string::npos) return false; @@ -11442,8 +11482,7 @@ struct FilterResults { // results // ... removeSyntheticNullTransforms(); - if (context->getDiscardSuperseded()) - removeUninterestingOps(); + removeUninterestingOps(); removeDuplicateOps(); removeSyntheticNullTransforms(); return *this; @@ -11758,50 +11797,23 @@ struct FilterResults { void removeUninterestingOps() { // Eliminate operations that bring nothing, ie for a given area of use, - // do not keep operations that have greater accuracy. Actually we must - // be a bit more subtle than that, and take into account grid - // availability + // do not keep operations that have similar or worse accuracy, but + // involve more (non conversion) steps std::vector<CoordinateOperationNNPtr> resTemp; metadata::ExtentPtr lastExtent; double lastAccuracy = -1; - bool lastHasGrids = false; - bool lastGridsAvailable = true; - std::set<std::set<std::string>> setOfSetOfGrids; size_t lastStepCount = 0; CoordinateOperationPtr lastOp; bool first = true; - const auto gridAvailabilityUse = context->getGridAvailabilityUse(); for (const auto &op : res) { const auto curAccuracy = getAccuracy(op); bool dummy = false; const auto curExtent = getExtent(op, true, dummy); - bool curHasGrids = false; - bool curGridsAvailable = true; - std::set<std::string> curSetOfGrids; - - const auto curStepCount = getStepCount(op); - - if (context->getAuthorityFactory()) { - const auto gridsNeeded = op->gridsNeeded( - context->getAuthorityFactory()->databaseContext(), - gridAvailabilityUse == - CoordinateOperationContext::GridAvailabilityUse:: - KNOWN_AVAILABLE); - for (const auto &gridDesc : gridsNeeded) { - curHasGrids = true; - curSetOfGrids.insert(gridDesc.shortName); - if (!gridDesc.available) { - curGridsAvailable = false; - } - } - } + const auto curStepCount = getTransformationStepCount(op); if (first) { resTemp.emplace_back(op); - - lastHasGrids = curHasGrids; - lastGridsAvailable = curGridsAvailable; first = false; } else { if (lastOp->_isEquivalentTo(op.get())) { @@ -11812,66 +11824,19 @@ struct FilterResults { (curExtent && lastExtent && curExtent->contains(NN_NO_CHECK(lastExtent)) && lastExtent->contains(NN_NO_CHECK(curExtent)))); - if (((curAccuracy > lastAccuracy && lastAccuracy >= 0) || + if (((curAccuracy >= lastAccuracy && lastAccuracy >= 0) || (curAccuracy < 0 && lastAccuracy >= 0)) && - sameExtent) { - // If that set of grids has always been used for that - // extent, - // no need to add them again - if (setOfSetOfGrids.find(curSetOfGrids) != - setOfSetOfGrids.end()) { - continue; - } - - const bool sameNameOrEmptyName = - ((!curExtent && !lastExtent) || - (curExtent && lastExtent && - !curExtent->description()->empty() && - *(curExtent->description()) == - *(lastExtent->description()))); - - // If we have already found a operation without grids for - // that extent, no need to add any lower accuracy operation - if (!lastHasGrids && sameNameOrEmptyName) { - continue; - } - // If we had only operations involving grids, but one - // past operation had available grids, no need to add - // the new one. - if (curHasGrids && curGridsAvailable && - lastGridsAvailable) { - continue; - } - } else if (curAccuracy == lastAccuracy && sameExtent) { - if (curStepCount > lastStepCount) { - continue; - } + sameExtent && curStepCount > lastStepCount) { + continue; } resTemp.emplace_back(op); - - if (sameExtent) { - if (!curHasGrids) { - lastHasGrids = false; - } - if (curGridsAvailable) { - lastGridsAvailable = true; - } - } else { - setOfSetOfGrids.clear(); - - lastHasGrids = curHasGrids; - lastGridsAvailable = curGridsAvailable; - } } lastOp = op.as_nullable(); lastStepCount = curStepCount; lastExtent = curExtent; lastAccuracy = curAccuracy; - if (!curSetOfGrids.empty()) { - setOfSetOfGrids.insert(curSetOfGrids); - } } res = std::move(resTemp); } diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 88420c8a..e96b3cc9 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -378,7 +378,8 @@ VerticalCRSPtr CRS::extractVerticalCRS() const { * a +towgs84 parameter or a WKT1:GDAL string with a TOWGS node. * * This method will fetch the GeographicCRS of this CRS and find a - * transformation to EPSG:4326 using the domain of the validity of the main CRS. + * transformation to EPSG:4326 using the domain of the validity of the main CRS, + * and there's only one Helmert transformation. * * @return a CRS. */ @@ -456,6 +457,7 @@ CRSNNPtr CRS::createBoundCRSToWGS84IfPossible( auto list = operation::CoordinateOperationFactory::create() ->createOperations(NN_NO_CHECK(geodCRS), hubCRS, ctxt); + CRSPtr candidateBoundCRS; for (const auto &op : list) { auto transf = util::nn_dynamic_pointer_cast<operation::Transformation>( @@ -466,8 +468,13 @@ CRSNNPtr CRS::createBoundCRSToWGS84IfPossible( } catch (const std::exception &) { continue; } - return util::nn_static_pointer_cast<CRS>(BoundCRS::create( - thisAsCRS, hubCRS, NN_NO_CHECK(transf))); + if (candidateBoundCRS) { + candidateBoundCRS = nullptr; + break; + } + candidateBoundCRS = + BoundCRS::create(thisAsCRS, hubCRS, NN_NO_CHECK(transf)) + .as_nullable(); } else { auto concatenated = dynamic_cast<const operation::ConcatenatedOperation *>( @@ -499,15 +506,23 @@ CRSNNPtr CRS::createBoundCRSToWGS84IfPossible( } catch (const std::exception &) { continue; } - return util::nn_static_pointer_cast<CRS>( + if (candidateBoundCRS) { + candidateBoundCRS = nullptr; + break; + } + candidateBoundCRS = BoundCRS::create(thisAsCRS, hubCRS, - NN_NO_CHECK(transf))); + NN_NO_CHECK(transf)) + .as_nullable(); } } } } } } + if (candidateBoundCRS) { + return NN_NO_CHECK(candidateBoundCRS); + } } catch (const std::exception &) { } } |
