From eeea65526dfd0301a7759a978a5b8fcbcf5baecd Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Tue, 5 Apr 2016 19:05:06 +0200 Subject: Some initial work on internal regression tests Need these to reduce the chance I'm screwing up something during this rather intrusive code surgery --- src/pj_generic_selftest.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 src/pj_generic_selftest.c (limited to 'src/pj_generic_selftest.c') diff --git a/src/pj_generic_selftest.c b/src/pj_generic_selftest.c new file mode 100644 index 00000000..e2d24baf --- /dev/null +++ b/src/pj_generic_selftest.c @@ -0,0 +1,200 @@ +/****************************************************************************** + * Project: PROJ.4 + * Purpose: Generic regression test for PROJ.4 projection algorithms. + * Author: Thomas Knudsen + * + ****************************************************************************** + * Copyright (c) 2016, Thomas Knudsen + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + *****************************************************************************/ + + +#include +#define PJ_LIB__ +#include + + +static int deviates_xy (XY expected, XY got, double tolerance); +static int deviates_lp (LP expected, LP got, double tolerance); +static XY pj_fwd_deg (LP in, PJ *P); + + +/**********************************************************************/ +int pj_generic_selftest ( +/**********************************************************************/ + char *e_args, + char *s_args, + double tolerance_xy, + double tolerance_lp, + int n_fwd, + int n_inv, + LP *fwd_in, + XY *e_fwd_expect, + XY *s_fwd_expect, + XY *inv_in, + LP *e_inv_expect, + LP *s_inv_expect +) { +/*********************************************************************** + +Generic regression test for PROJ.4 projection algorithms, testing both +ellipsoidal ("e_") and spheroidal ("s_") versions of the projection +algorithms in both forward ("_fwd_") and inverse ("_inv_") mode. + +Compares the "known good" results in and +with the actual results obtained by transforming the forward input data +set in with pj_fwd() using setup arguments and +, respectively. + +Then + +Compares the "known good" results in and +with the actual results obtained by transforming the inverse input data +set in with pj_inv() using setup arguments and +, respectively. + +Any of the pointers passed may be set to 0, indicating "don't test this +part". + +Returns 0 if all data agree to within the accuracy specified in + and . Non-zero otherwise. + +***********************************************************************/ + int i; + + PJ *P; + +puts ("testing"); + if (e_args) { + + puts ("e_args"); + puts (e_args); + + P = pj_init_plus(e_args); + if (0==P) + return 2; + + /* Test forward ellipsoidal */ + if (e_fwd_expect) { puts ("e_fwd"); + for (i = 0; i < n_fwd; i++) + if (deviates_xy (e_fwd_expect[i], pj_fwd_deg ( fwd_in[i], P ), tolerance_xy)) + break; + if ( i != n_fwd ) + return 100 + i; + } + + /* Test inverse ellipsoidal */ + if (e_inv_expect) { puts ("e_inv"); + for (i = 0; i < n_inv; i++) + if (deviates_lp (e_inv_expect[i], pj_inv ( inv_in[i], P ), tolerance_lp)) + break; + if ( i != n_inv ) + return 200 + i; + } + + pj_free (P); + } + + + if (s_args) { + puts ("s_args"); + puts (s_args); + P = pj_init_plus(s_args); + if (0==P) + return 3; + + /* Test forward spherical */ + if (s_fwd_expect) { puts ("s_fwd"); + for (i = 0; i < n_fwd; i++) + if (deviates_xy (s_fwd_expect[i], pj_fwd_deg ( fwd_in[i], P ), tolerance_xy)) + break; + if ( i != n_fwd ) + return 300 + i; + } + + /* Test inverse spherical */ + if (s_inv_expect) { puts ("s_inv"); + for (i = 0; i < n_inv; i++) + if (deviates_lp (s_inv_expect[i], pj_inv ( inv_in[i], P ), tolerance_lp)) + break; + if ( i != n_inv ) + return 400 + i; + } + + pj_free (P); + } + + return 0; +} + + + +/**********************************************************************/ +static int deviates_xy (XY expected, XY got, double tolerance) { +/*********************************************************************** + + Determine whether two XYs deviate by more than . + +***********************************************************************/ + if (HUGE_VAL== expected.x) + return 0; + if (HUGE_VAL== expected.y) + return 0; + if (hypot ( expected.x - got.x, expected.y - got.y ) > tolerance) + return 1; + return 0; +} + + +/**********************************************************************/ +static int deviates_lp (LP expected, LP got, double tolerance) { +/*********************************************************************** + + Determine whether two LPs deviate by more than . + + This one is slightly tricky, since the LP is + supposed to be represented as degrees (since it was at some + time written down by a real human), whereas the LP is + represented in radians (since it is supposed to be the result + output from pj_inv) + +***********************************************************************/ + if (HUGE_VAL== expected.lam) + return 0; + if (HUGE_VAL== expected.phi) + return 0; + if (hypot ( DEG_TO_RAD * expected.lam - got.lam, DEG_TO_RAD * expected.phi - got.phi ) > tolerance) + return 1; + return 0; +} + + +/**********************************************************************/ +static XY pj_fwd_deg (LP in, PJ *P) { +/*********************************************************************** + + Wrapper for pj_fwd, accepting input in degrees. + +***********************************************************************/ + LP in_rad; + in_rad.lam = DEG_TO_RAD * in.lam; + in_rad.phi = DEG_TO_RAD * in.phi; + return pj_fwd (in_rad, P); +} -- cgit v1.2.3