aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2020-12-15 01:12:58 +0100
committerEven Rouault <even.rouault@spatialys.com>2020-12-15 17:24:54 +0100
commit1d803550e7059729cf2734fc6190993e8b8404bf (patch)
tree9ead2265d639388da39ad52aa88cd9861b508831
parent2abc0aaf3a03493aaa3f940e1d420d8d9a7b804f (diff)
downloadPROJ-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.rst11
-rw-r--r--src/4D_api.cpp35
-rw-r--r--test/unit/gie_self_tests.cpp33
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);
}