diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2020-12-15 01:12:58 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2020-12-15 17:24:54 +0100 |
| commit | 1d803550e7059729cf2734fc6190993e8b8404bf (patch) | |
| tree | 9ead2265d639388da39ad52aa88cd9861b508831 | |
| parent | 2abc0aaf3a03493aaa3f940e1d420d8d9a7b804f (diff) | |
| download | PROJ-1d803550e7059729cf2734fc6190993e8b8404bf.tar.gz PROJ-1d803550e7059729cf2734fc6190993e8b8404bf.zip | |
proj_trans_array(): make it transform all coordinates even when an error occurs
| -rw-r--r-- | docs/source/development/reference/functions.rst | 11 | ||||
| -rw-r--r-- | src/4D_api.cpp | 35 | ||||
| -rw-r--r-- | test/unit/gie_self_tests.cpp | 33 |
3 files changed, 71 insertions, 8 deletions
diff --git a/docs/source/development/reference/functions.rst b/docs/source/development/reference/functions.rst index 5b559d55..08b3e669 100644 --- a/docs/source/development/reference/functions.rst +++ b/docs/source/development/reference/functions.rst @@ -368,13 +368,22 @@ Coordinate transformation Batch transform an array of :c:type:`PJ_COORD`. + Performs transformation on all points, even if errors occur on some points + (new to 8.0. Previous versions would exit early in case of failure on a given point) + + Individual points that fail to transform will have their components set to + ``HUGE_VAL`` + :param P: Transformation object :type P: :c:type:`PJ` * :param `direction`: Transformation direction. :type `direction`: PJ_DIRECTION :param n: Number of coordinates in :c:data:`coord` :type n: `size_t` - :returns: `int` 0 if all observations are transformed without error, otherwise returns error number + :returns: `int` 0 if all observations are transformed without error, otherwise returns error number. + This error number will be a precise error number if all coordinates that fail to transform + for the same reason, or a generic error code if they fail for different + reasons. Error reporting diff --git a/src/4D_api.cpp b/src/4D_api.cpp index 612be716..556a8c2d 100644 --- a/src/4D_api.cpp +++ b/src/4D_api.cpp @@ -377,18 +377,43 @@ int proj_trans_array (PJ *P, PJ_DIRECTION direction, size_t n, PJ_COORD *coord) /****************************************************************************** Batch transform an array of PJ_COORD. + Performs transformation on all points, even if errors occur on some points. + + Individual points that fail to transform will have their components set to + HUGE_VAL + Returns 0 if all coordinates are transformed without error, otherwise - returns error number. + returns a precise error number if all coordinates that fail to transform + for the same reason, or a generic error code if they fail for different + reasons. ******************************************************************************/ size_t i; + int retErrno = 0; + bool hasSetRetErrno = false; + bool sameRetErrno = true; for (i = 0; i < n; i++) { + proj_context_errno_set(P->ctx, 0); coord[i] = proj_trans (P, direction, coord[i]); - if (proj_errno(P)) - return proj_errno (P); - } + int thisErrno = proj_errno(P); + if( thisErrno != 0 ) + { + if( !hasSetRetErrno ) + { + retErrno = thisErrno; + hasSetRetErrno = true; + } + else if( sameRetErrno && retErrno != thisErrno ) + { + sameRetErrno = false; + retErrno = PROJ_ERR_COORD_TRANSFM; + } + } + } + + proj_context_errno_set(P->ctx, retErrno); - return 0; + return retErrno; } diff --git a/test/unit/gie_self_tests.cpp b/test/unit/gie_self_tests.cpp index 70e67dcc..4244766e 100644 --- a/test/unit/gie_self_tests.cpp +++ b/test/unit/gie_self_tests.cpp @@ -46,7 +46,7 @@ TEST(gie, cart_selftest) { PJ_CONTEXT *ctx; PJ *P; PJ_COORD a, b, obs[2]; - PJ_COORD coord[2]; + PJ_COORD coord[3]; size_t n, sz; double dist, h, t; @@ -200,7 +200,7 @@ TEST(gie, cart_selftest) { coord[0] = proj_coord(proj_torad(12), proj_torad(55), 45, 0); coord[1] = proj_coord(proj_torad(12), proj_torad(56), 50, 0); - ASSERT_FALSE(proj_trans_array(P, PJ_FWD, 2, coord)); + ASSERT_EQ(proj_trans_array(P, PJ_FWD, 2, coord), 0); ASSERT_EQ(a.lpz.lam, coord[0].lpz.lam); ASSERT_EQ(a.lpz.phi, coord[0].lpz.phi); @@ -209,6 +209,35 @@ TEST(gie, cart_selftest) { ASSERT_EQ(b.lpz.phi, coord[1].lpz.phi); ASSERT_EQ(b.lpz.z, coord[1].lpz.z); + /* test proj_trans_array () with two failed points for the same reason */ + + coord[0] = + proj_coord(proj_torad(12), proj_torad(95), 45, 0); // invalid latitude + coord[1] = proj_coord(proj_torad(12), proj_torad(56), 50, 0); + coord[2] = + proj_coord(proj_torad(12), proj_torad(95), 45, 0); // invalid latitude + ASSERT_EQ(proj_trans_array(P, PJ_FWD, 3, coord), + PROJ_ERR_COORD_TRANSFM_INVALID_COORD); + + ASSERT_EQ(HUGE_VAL, coord[0].lpz.lam); + ASSERT_EQ(HUGE_VAL, coord[0].lpz.phi); + ASSERT_EQ(HUGE_VAL, coord[0].lpz.z); + ASSERT_EQ(b.lpz.lam, coord[1].lpz.lam); + ASSERT_EQ(b.lpz.phi, coord[1].lpz.phi); + ASSERT_EQ(b.lpz.z, coord[1].lpz.z); + ASSERT_EQ(HUGE_VAL, coord[2].lpz.lam); + ASSERT_EQ(HUGE_VAL, coord[2].lpz.phi); + ASSERT_EQ(HUGE_VAL, coord[2].lpz.z); + + /* test proj_trans_array () with two failed points for different reasons */ + + coord[0] = + proj_coord(proj_torad(12), proj_torad(95), 45, 0); // invalid latitude + coord[1] = + proj_coord(proj_torad(105), proj_torad(0), 45, + 0); // in the equatorial axis, at 90° of the central meridian + ASSERT_EQ(proj_trans_array(P, PJ_FWD, 2, coord), PROJ_ERR_COORD_TRANSFM); + /* Clean up after proj_trans_* tests */ proj_destroy(P); } |
