Skip to content

Commit 78d563c

Browse files
committed
proj_create_crs_to_crs(): restore behaviour of PROJ 9.1
Fixes https://lists.osgeo.org/pipermail/proj/2023-April/011003.html that is ``cs2cs EPSG:4326+5773 EPSG:4326+5782`` without grids available. Fixes situations where getting operations in PROJ_GRID_AVAILABILITY_KNOWN_AVAILABLE mode returns one single gridded operations where the grid isn't available or a ballpark operation. We retry in PROJ_GRID_AVAILABILITY_DISCARD_OPERATION_IF_MISSING_GRID mode to get a potential ballpark operation. Follow-up to similar fix of OSGeo#3614
1 parent b214363 commit 78d563c

File tree

3 files changed

+124
-36
lines changed

3 files changed

+124
-36
lines changed

src/4D_api.cpp

Lines changed: 79 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,25 +1878,29 @@ pj_create_prepared_operations(PJ_CONTEXT *ctx, const PJ *source_crs,
18781878
double north_lat = 0.0;
18791879

18801880
const char *areaName = nullptr;
1881-
if (proj_get_area_of_use(ctx, op, &west_lon, &south_lat, &east_lon,
1882-
&north_lat, &areaName)) {
1883-
const bool isOffshore =
1884-
areaName && strstr(areaName, "- offshore");
1885-
if (west_lon <= east_lon) {
1886-
op = add_coord_op_to_list(
1887-
i, op, west_lon, south_lat, east_lon, north_lat,
1888-
pjGeogToSrc, pjGeogToDst, isOffshore, preparedOpList);
1889-
} else {
1890-
auto op_clone = proj_clone(ctx, op);
1891-
1892-
op = add_coord_op_to_list(
1893-
i, op, west_lon, south_lat, 180, north_lat, pjGeogToSrc,
1894-
pjGeogToDst, isOffshore, preparedOpList);
1895-
op_clone = add_coord_op_to_list(
1896-
i, op_clone, -180, south_lat, east_lon, north_lat,
1897-
pjGeogToSrc, pjGeogToDst, isOffshore, preparedOpList);
1898-
proj_destroy(op_clone);
1899-
}
1881+
if (!proj_get_area_of_use(ctx, op, &west_lon, &south_lat, &east_lon,
1882+
&north_lat, &areaName)) {
1883+
west_lon = -180;
1884+
south_lat = -90;
1885+
east_lon = 180;
1886+
north_lat = 90;
1887+
}
1888+
1889+
const bool isOffshore = areaName && strstr(areaName, "- offshore");
1890+
if (west_lon <= east_lon) {
1891+
op = add_coord_op_to_list(i, op, west_lon, south_lat, east_lon,
1892+
north_lat, pjGeogToSrc, pjGeogToDst,
1893+
isOffshore, preparedOpList);
1894+
} else {
1895+
auto op_clone = proj_clone(ctx, op);
1896+
1897+
op = add_coord_op_to_list(i, op, west_lon, south_lat, 180,
1898+
north_lat, pjGeogToSrc, pjGeogToDst,
1899+
isOffshore, preparedOpList);
1900+
op_clone = add_coord_op_to_list(
1901+
i, op_clone, -180, south_lat, east_lon, north_lat,
1902+
pjGeogToSrc, pjGeogToDst, isOffshore, preparedOpList);
1903+
proj_destroy(op_clone);
19001904
}
19011905

19021906
proj_destroy(op);
@@ -2056,27 +2060,48 @@ PJ *proj_create_crs_to_crs_from_pj(PJ_CONTEXT *ctx, const PJ *source_crs,
20562060
P->skipNonInstantiable = warnIfBestTransformationNotAvailable;
20572061
}
20582062

2059-
if (P == nullptr || op_count == 1 ||
2060-
proj_get_type(source_crs) == PJ_TYPE_GEOCENTRIC_CRS ||
2061-
proj_get_type(target_crs) == PJ_TYPE_GEOCENTRIC_CRS) {
2063+
const bool mayNeedToReRunWithDiscardMissing =
2064+
(errorIfBestTransformationNotAvailable ||
2065+
warnIfBestTransformationNotAvailable) &&
2066+
!proj_context_is_network_enabled(ctx);
2067+
int singleOpIsInstanciable = -1;
2068+
if (P != nullptr && op_count == 1 && mayNeedToReRunWithDiscardMissing) {
2069+
singleOpIsInstanciable = proj_coordoperation_is_instantiable(ctx, P);
2070+
}
2071+
2072+
const auto backup_errno = proj_context_errno(ctx);
2073+
if ((P == nullptr ||
2074+
(op_count == 1 &&
2075+
(!mayNeedToReRunWithDiscardMissing ||
2076+
errorIfBestTransformationNotAvailable ||
2077+
singleOpIsInstanciable == static_cast<int>(true))) ||
2078+
proj_get_type(source_crs) == PJ_TYPE_GEOCENTRIC_CRS ||
2079+
proj_get_type(target_crs) == PJ_TYPE_GEOCENTRIC_CRS)) {
20622080
proj_list_destroy(op_list);
20632081
ctx->forceOver = false;
20642082

2065-
if (P != nullptr &&
2066-
(errorIfBestTransformationNotAvailable ||
2067-
warnIfBestTransformationNotAvailable) &&
2068-
!proj_coordoperation_is_instantiable(ctx, P)) {
2069-
warnAboutMissingGrid(P);
2070-
if (errorIfBestTransformationNotAvailable) {
2071-
proj_destroy(P);
2072-
return nullptr;
2083+
if (P != nullptr && (errorIfBestTransformationNotAvailable ||
2084+
warnIfBestTransformationNotAvailable)) {
2085+
if (singleOpIsInstanciable < 0) {
2086+
singleOpIsInstanciable =
2087+
proj_coordoperation_is_instantiable(ctx, P);
2088+
}
2089+
if (!singleOpIsInstanciable) {
2090+
warnAboutMissingGrid(P);
2091+
if (errorIfBestTransformationNotAvailable) {
2092+
proj_destroy(P);
2093+
return nullptr;
2094+
}
20732095
}
20742096
}
20752097

20762098
if (P != nullptr) {
20772099
P->over = forceOver;
20782100
}
20792101
return P;
2102+
} else if (op_count == 1 && mayNeedToReRunWithDiscardMissing &&
2103+
!singleOpIsInstanciable) {
2104+
warnAboutMissingGrid(P);
20802105
}
20812106

20822107
if (errorIfBestTransformationNotAvailable ||
@@ -2094,10 +2119,6 @@ PJ *proj_create_crs_to_crs_from_pj(PJ_CONTEXT *ctx, const PJ *source_crs,
20942119
return nullptr;
20952120
}
20962121

2097-
const bool mayNeedToReRunWithDiscardMissing =
2098-
(errorIfBestTransformationNotAvailable ||
2099-
warnIfBestTransformationNotAvailable) &&
2100-
!proj_context_is_network_enabled(ctx);
21012122
bool foundInstanciableAndNonBallpark = false;
21022123

21032124
for (auto &op : preparedOpList) {
@@ -2152,6 +2173,8 @@ PJ *proj_create_crs_to_crs_from_pj(PJ_CONTEXT *ctx, const PJ *source_crs,
21522173

21532174
op_list = proj_create_operations(ctx, source_crs, target_crs,
21542175
operation_ctx);
2176+
proj_operation_factory_context_destroy(operation_ctx);
2177+
21552178
if (op_list) {
21562179
ctx->forceOver = forceOver;
21572180
ctx->debug_level = PJ_LOG_NONE;
@@ -2179,10 +2202,30 @@ PJ *proj_create_crs_to_crs_from_pj(PJ_CONTEXT *ctx, const PJ *source_crs,
21792202
newOpList.emplace_back(std::move(op));
21802203
}
21812204
preparedOpList = std::move(newOpList);
2205+
} else {
2206+
// We get there in "cs2cs --only-best --no-ballpark
2207+
// EPSG:4326+3855 EPSG:4979" use case, where the initial
2208+
// create_operations returned 1 operation, and the retry
2209+
// with
2210+
// PROJ_GRID_AVAILABILITY_DISCARD_OPERATION_IF_MISSING_GRID
2211+
// returned 0.
2212+
if (op_count == 1 &&
2213+
(errorIfBestTransformationNotAvailable ||
2214+
warnIfBestTransformationNotAvailable)) {
2215+
if (singleOpIsInstanciable < 0) {
2216+
singleOpIsInstanciable =
2217+
proj_coordoperation_is_instantiable(ctx, P);
2218+
}
2219+
if (!singleOpIsInstanciable) {
2220+
if (errorIfBestTransformationNotAvailable) {
2221+
proj_destroy(P);
2222+
proj_context_errno_set(ctx, backup_errno);
2223+
return nullptr;
2224+
}
2225+
}
2226+
}
21822227
}
21832228
}
2184-
2185-
proj_operation_factory_context_destroy(operation_ctx);
21862229
}
21872230
}
21882231

test/cli/testvarious

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,36 @@ EOF
12171217

12181218
rm -rf tmp_dir
12191219

1220+
echo "##############################################################" >> ${OUT}
1221+
echo "Test cs2cs (grid missing) with scenario of https://lists.osgeo.org/pipermail/proj/2023-April/011003.html" >> ${OUT}
1222+
1223+
mkdir tmp_dir
1224+
cp $PROJ_DATA/proj.db tmp_dir
1225+
1226+
echo 39 -3 0 | PROJ_DATA=tmp_dir PROJ_DEBUG=2 $EXE EPSG:4326+5773 EPSG:4326+5782 -E 2>&1|grep -v pj_open_lib >> ${OUT}
1227+
1228+
rm -rf tmp_dir
1229+
1230+
echo "##############################################################" >> ${OUT}
1231+
echo "Test cs2cs (grid missing) --only-best=no with scenario of https://lists.osgeo.org/pipermail/proj/2023-April/011003.html" >> ${OUT}
1232+
1233+
mkdir tmp_dir
1234+
cp $PROJ_DATA/proj.db tmp_dir
1235+
1236+
echo 39 -3 0 | PROJ_DATA=tmp_dir PROJ_DEBUG=2 $EXE --only-best=no EPSG:4326+5773 EPSG:4326+5782 -E 2>&1|grep -v pj_open_lib >> ${OUT}
1237+
1238+
rm -rf tmp_dir
1239+
1240+
echo "##############################################################" >> ${OUT}
1241+
echo "Test cs2cs (grid missing) --only-best with scenario of https://lists.osgeo.org/pipermail/proj/2023-April/011003.html" >> ${OUT}
1242+
1243+
mkdir tmp_dir
1244+
cp $PROJ_DATA/proj.db tmp_dir
1245+
1246+
echo 39 -3 0 | PROJ_DISPLAY_PROGRAM_NAME=NO PROJ_DATA=tmp_dir PROJ_DEBUG=2 $EXE --only-best EPSG:4326+5773 EPSG:4326+5782 -E 2>&1|grep -v pj_open_lib >> ${OUT}
1247+
1248+
rm -rf tmp_dir
1249+
12201250
echo "##############################################################" >> ${OUT}
12211251
echo "Test Similarity Transformation (example from EPSG Guidance Note 7.2)" >> ${OUT}
12221252
#

test/cli/tv_out.dist

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,21 @@ Test cs2cs (grid missing) with scenario of https://github.com/OSGeo/PROJ/issues/
592592
569704.5660295591 4269024.671083651 569720.46 4268813.88 0.00
593593
569704.5660295591 4269024.671083651 569720.46 4268813.88 0.00
594594
##############################################################
595+
Test cs2cs (grid missing) with scenario of https://lists.osgeo.org/pipermail/proj/2023-April/011003.html
596+
Attempt to use coordinate operation Inverse of WGS 84 to EGM96 height (1) + ETRS89 to Alicante height (1) using ETRS89 to WGS 84 (1) failed. Grid es_ign_egm08-rednap.tif is not available. Consult https://proj.org/resource_files.html for guidance. Grid us_nga_egm96_15.tif is not available. Consult https://proj.org/resource_files.html for guidance. This might become an error in a future PROJ major release. Set the ONLY_BEST option to YES or NO. This warning will no longer be emitted (for the current transformation instance).
597+
Using coordinate operation Transformation from EGM96 height to Alicante height (ballpark vertical transformation)
598+
39 -3 0 39.00 -3.00 0.00
599+
##############################################################
600+
Test cs2cs (grid missing) --only-best=no with scenario of https://lists.osgeo.org/pipermail/proj/2023-April/011003.html
601+
39 -3 0 39.00 -3.00 0.00
602+
##############################################################
603+
Test cs2cs (grid missing) --only-best with scenario of https://lists.osgeo.org/pipermail/proj/2023-April/011003.html
604+
Attempt to use coordinate operation Inverse of WGS 84 to EGM96 height (1) + ETRS89 to Alicante height (1) using ETRS89 to WGS 84 (1) failed. Grid es_ign_egm08-rednap.tif is not available. Consult https://proj.org/resource_files.html for guidance. Grid us_nga_egm96_15.tif is not available. Consult https://proj.org/resource_files.html for guidance.
605+
606+
cannot initialize transformation
607+
cause: File not found or invalid
608+
program abnormally terminated
609+
##############################################################
595610
Test Similarity Transformation (example from EPSG Guidance Note 7.2)
596611
300000 4500000 299905.060 4499796.515 0.000
597612
##############################################################

0 commit comments

Comments
 (0)