From 5f6fac3afdb03aef5a26ce5f60c10ed612fa6fc2 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 17 Jun 2021 17:53:11 +0200 Subject: proj_trans/cs2cs: If two operations have the same accuracy, use the one that is contained within a larger one Relates to https://github.com/OSGeo/gdal/issues/3998 Before that change, cs2cs on a NAD83(HARN) to WGS84 transformation would use the "NAD83(HARN) to WGS 84 (1)" transformation (a null Helmert shift) that is valid for whole US, including non-CONUS areas, even when used on points located on CONUS that has a "NAD83(HARN) to WGS 84 (3)" transformation (non-null Helmert shift) with same accuracy (1m). But if doing EPSG:2874 "NAD83(HARN) / California zone 5 (ftUS)" to WGS84, we would use this later "NAD83(HARN) to WGS 84 (3)" transformation because the area of use of EPSG:2874 restricts to CONUS. This isn't consistant. With that change, we now have more consistent behavior, even if it can be argued which of the 2 transformations is the best... $ echo 34 -120 | src/cs2cs -d 8 EPSG:4326 "NAD83(HARN)" | src/cs2cs "NAD83(HARN)" EPSG:2874 5955507.74 1828410.98 0.00 $ echo 34 -120 | src/cs2cs EPSG:4326 EPSG:2874 5955507.74 1828410.98 0.00 --- src/4D_api.cpp | 10 +++++++++- test/cli/testvarious | 6 ++++++ test/cli/tv_out.dist | 3 +++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/4D_api.cpp b/src/4D_api.cpp index 8b676f9b..95582e48 100644 --- a/src/4D_api.cpp +++ b/src/4D_api.cpp @@ -243,7 +243,15 @@ int pj_get_suggested_operation(PJ_CONTEXT*, // onshore. So in a general way, prefer a onshore area to a // offshore one. if( iBest < 0 || - (alt.accuracy >= 0 && alt.accuracy < bestAccuracy && + (alt.accuracy >= 0 && + (alt.accuracy < bestAccuracy || + // If two operations have the same accuracy, use the one that + // is contained within a larger one + (alt.accuracy == bestAccuracy && + alt.minxSrc > opList[iBest].minxSrc && + alt.minySrc > opList[iBest].minySrc && + alt.maxxSrc < opList[iBest].maxxSrc && + alt.maxySrc < opList[iBest].maxySrc)) && !alt.isOffshore) ) { iBest = i; bestAccuracy = alt.accuracy; diff --git a/test/cli/testvarious b/test/cli/testvarious index e88cf68b..6e9cd43c 100755 --- a/test/cli/testvarious +++ b/test/cli/testvarious @@ -1047,6 +1047,12 @@ $EXE -E EPSG:2636 "WGS 84" >> ${OUT} <> ${OUT} +echo "Check that we select the operation that has the smallest area of use, when 2 have the same accuracy" >> ${OUT} +$EXE -E EPSG:4326 "NAD83(HARN)" >> ${OUT} < Date: Fri, 18 Jun 2021 13:04:23 +0200 Subject: operations_computation.rst: add note about proj_create_crs_to_crs not necessarily using the operation that appears as first --- docs/source/operations/operations_computation.rst | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/source/operations/operations_computation.rst b/docs/source/operations/operations_computation.rst index 0bc57ff0..5c2596e6 100644 --- a/docs/source/operations/operations_computation.rst +++ b/docs/source/operations/operations_computation.rst @@ -59,9 +59,9 @@ From a code point of view, the entry point of the algorithm is the C++ It combines several strategies: -- look up in the PROJ database for available operations -- consider the pair (source CRS, target CRS) to synthetize operations depending - on the nature of the source and target CRS. + - look up in the PROJ database for available operations + - consider the pair (source CRS, target CRS) to synthetize operations depending + on the nature of the source and target CRS. Geographic CRS to Geographic CRS, with known identifiers -------------------------------------------------------- @@ -156,6 +156,18 @@ performed in the order they are listed below: lexicographic order (e.g. "FOO to BAR (3)" will have higher precedence than "FOO to BAR (2)") +.. note:: + + :c:func:`proj_trans`, on the results returned by :c:func:`proj_create_crs_to_crs`, + will not necessarily use the operation that + is listed in first position due to the above algorithm. :c:func:`proj_trans` + has more context, since it has the coordinate to transform, so it can compare + this coordinate to the area of use of operations. Typically, the above criteria + will favor an operation that has a larger area of use over another one with a + smaller area, due to it being more generally applicable. But once coordinates are known, + :c:func:`proj_trans` can select an operation with a smaller + area of use that applies to the coordinate to transform. + Geodetic/geographic CRS to Geodetic/geographic CRS, without known identifiers ----------------------------------------------------------------------------- -- cgit v1.2.3