diff options
Diffstat (limited to 'src/gie.c')
| -rw-r--r-- | src/gie.c | 735 |
1 files changed, 729 insertions, 6 deletions
@@ -435,8 +435,25 @@ static int operation (char *args) { an operation is the general term describing something that can be either a conversion or a transformation) ******************************************************************************/ + int i, j, n; T.op_id++; + + /* compactify the args, so we can fit more info on a line in verbose mode */ + n = (int) strlen (args); + for (i = j = 0; i < n; ) { + /* skip prefix whitespace */ + while (isspace (args[i])) + i++; + /* move a whitespace delimited text string to the left, skipping over superfluous whitespace */ + while ((0!=args[i]) && (!isspace (args[i]))) + args[j++] = args[i++]; + if (args[j+1]!=0) + args[j++] = ' '; + i++; + } + args[j++] = 0; strcpy (&(T.operation[0]), args); + if (T.verbosity > 1) { finish_previous_operation (args); banner (args); @@ -448,15 +465,67 @@ static int operation (char *args) { direction ("forward"); tolerance ("0.5 mm"); + if (T.P) proj_destroy (T.P); T.P = proj_create (0, args); - if (0==T.P) - errmsg(3, "Invalid operation definition!\n %s\n", args); + return 0; } + + +static int pj_unitconvert_selftest (void); +static int pj_cart_selftest (void); +static int pj_horner_selftest (void); +/*****************************************************************************/ +static int builtins (char *args) { +/***************************************************************************** + There are still a few tests that cannot be described using gie + primitives. Instead, they are implemented as builtins, and invoked + using the "builtins" command verb. +******************************************************************************/ + int i; + if (T.verbosity > 1) { + finish_previous_operation (args); + banner ("builtins: unitconvert, horner, cart"); + } + T.op_ok = 0; + T.op_ko = 0; + + i = pj_unitconvert_selftest (); + if (i!=0) { + printf ("pj_unitconvert_selftest fails with %d\n", i); + another_failure(); + } + else + another_success (); + + + i = pj_cart_selftest (); + if (i!=0) { + printf ("pj_cart_selftest fails with %d\n", i); + another_failure(); + } + else + another_success (); + + i = pj_horner_selftest (); + if (i!=0) { + printf ("pj_horner_selftest fails with %d\n", i); + another_failure(); + } + else + another_success (); + + return 0; +} + + + + + static PJ_COORD torad_coord (PJ_COORD a) { PJ_COORD c = a; c.lpz.lam = proj_torad (a.lpz.lam); @@ -496,7 +565,7 @@ static int accept (char *args) { ******************************************************************************/ T.a = parse_coord (args); if (T.verbosity > 3) - printf ("# %s", args); + printf ("# %s\n", args); return 0; } @@ -583,22 +652,58 @@ static int expect (char *args) { ******************************************************************************/ PJ_COORD ci, co, ce; double d; - if (0==T.P) + int expect_failure = 0; + + if (0==strcmp (args, "failure")) + expect_failure = 1; + + if (0==T.P && !expect_failure) { + errmsg(3, "Invalid operation definition!\n %s\n", args); + return another_failure (); + } + + + if (expect_failure) { + /* If we expect failure, and fail, then it's a success... */ + if (0==T.P) + return another_success (); + /* We may still successfully fail even if the proj_create succeeded */ + ci = proj_angular_input (T.P, T.dir)? torad_coord (T.a): T.a; + co = proj_trans (T.P, T.dir, ci); + if (co.xyz.x==HUGE_VAL) + return another_success (); + /* no - we didn't manage to purportedly fail */ return another_failure (); + } + + + if (T.verbosity > 3) { + puts (T.P->inverted? "INVERTED": "NOT INVERTED"); + puts (T.dir== 1? "forward": "reverse"); + puts (proj_angular_input (T.P, T.dir)? "angular in": "linear in"); + puts (proj_angular_output (T.P, T.dir)? "angular out": "linear out"); + } T.e = parse_coord (args); if (HUGE_VAL==T.e.v[0]) return expect_message_cannot_parse (args); - /* expected angular values probably in degrees */ + /* expected angular values, probably in degrees */ ce = proj_angular_output (T.P, T.dir)? torad_coord (T.e): T.e; + if (T.verbosity > 3) + printf ("EXPECTS %.4f %.4f %.4f %.4f\n", ce.v[0],ce.v[1],ce.v[2],ce.v[3]); - /* input ("accepted") values also probably in degrees */ + /* input ("accepted") values, also probably in degrees */ ci = proj_angular_input (T.P, T.dir)? torad_coord (T.a): T.a; + if (T.verbosity > 3) + printf ("ACCEPTS %.4f %.4f %.4f %.4f\n", ci.v[0],ci.v[1],ci.v[2],ci.v[3]); + /* angular output from proj_trans comes in radians */ co = proj_trans (T.P, T.dir, ci); T.b = proj_angular_output (T.P, T.dir)? todeg_coord (co): co; + if (T.verbosity > 3) + printf ("GOT %.4f %.4f %.4f %.4f\n", ci.v[0],ci.v[1],ci.v[2],ci.v[3]); /* but there are a few more possible input conventions... */ if (proj_angular_output (T.P, T.dir)) { @@ -693,6 +798,8 @@ static int dispatch (char *cmnd, char *args) { if (0==strcmp (cmnd, "direction")) return direction (args); if (0==strcmp (cmnd, "TOLERANCE")) return tolerance (args); if (0==strcmp (cmnd, "tolerance")) return tolerance (args); + if (0==strcmp (cmnd, "BUILTINS")) return builtins (args); + if (0==strcmp (cmnd, "builtins")) return builtins (args); if (0==strcmp (cmnd, "ECHO")) return echo (args); if (0==strcmp (cmnd, "echo")) return echo (args); if (0==strcmp (cmnd, "END")) return finish_previous_operation (args), level++, 0; @@ -806,3 +913,619 @@ static char *get_args (char *inp) { return args; return --args; } + + + + + + + + + + + + + + + + + + + +char tc32_utm32[] = { + " +proj=horner" + " +ellps=intl" + " +range=500000" + " +fwd_origin=877605.269066,6125810.306769" + " +inv_origin=877605.760036,6125811.281773" + " +deg=4" + " +fwd_v=6.1258112678e+06,9.9999971567e-01,1.5372750011e-10,5.9300860915e-15,2.2609497633e-19,4.3188227445e-05,2.8225130416e-10,7.8740007114e-16,-1.7453997279e-19,1.6877465415e-10,-1.1234649773e-14,-1.7042333358e-18,-7.9303467953e-15,-5.2906832535e-19,3.9984284847e-19" + " +fwd_u=8.7760574982e+05,9.9999752475e-01,2.8817299305e-10,5.5641310680e-15,-1.5544700949e-18,-4.1357045890e-05,4.2106213519e-11,2.8525551629e-14,-1.9107771273e-18,3.3615590093e-10,2.4380247154e-14,-2.0241230315e-18,1.2429019719e-15,5.3886155968e-19,-1.0167505000e-18" + " +inv_v=6.1258103208e+06,1.0000002826e+00,-1.5372762184e-10,-5.9304261011e-15,-2.2612705361e-19,-4.3188331419e-05,-2.8225549995e-10,-7.8529116371e-16,1.7476576773e-19,-1.6875687989e-10,1.1236475299e-14,1.7042518057e-18,7.9300735257e-15,5.2881862699e-19,-3.9990736798e-19" + " +inv_u=8.7760527928e+05,1.0000024735e+00,-2.8817540032e-10,-5.5627059451e-15,1.5543637570e-18,4.1357152105e-05,-4.2114813612e-11,-2.8523713454e-14,1.9109017837e-18,-3.3616407783e-10,-2.4382678126e-14,2.0245020199e-18,-1.2441377565e-15,-5.3885232238e-19,1.0167203661e-18" +}; + + +char sb_utm32[] = { + " +proj=horner" + " +ellps=intl" + " +range=500000" + " +tolerance=0.0005" + " +fwd_origin=4.94690026817276e+05,6.13342113183056e+06" + " +inv_origin=6.19480258923588e+05,6.13258568148837e+06" + " +deg=3" + " +fwd_c=6.13258562111350e+06,6.19480105709997e+05,9.99378966275206e-01,-2.82153291753490e-02,-2.27089979140026e-10,-1.77019590701470e-09,1.08522286274070e-14,2.11430298751604e-15" + " +inv_c=6.13342118787027e+06,4.94690181709311e+05,9.99824464710368e-01,2.82279070814774e-02,7.66123542220864e-11,1.78425334628927e-09,-1.05584823306400e-14,-3.32554258683744e-15" +}; + +static int pj_horner_selftest (void) { + PJ *P; + PJ_COORD a, b, c; + double dist; + + /* Real polynonia relating the technical coordinate system TC32 to "System 45 Bornholm" */ + P = proj_create (PJ_DEFAULT_CTX, tc32_utm32); + if (0==P) + return 10; + + a = b = proj_coord (0,0,0,0); + a.uv.v = 6125305.4245; + a.uv.u = 878354.8539; + c = a; + + /* Check roundtrip precision for 1 iteration each way, starting in forward direction */ + dist = proj_roundtrip (P, PJ_FWD, 1, &c); + if (dist > 0.01) + return 1; + + /* The complex polynomial transformation between the "System Storebaelt" and utm32/ed50 */ + P = proj_create (PJ_DEFAULT_CTX, sb_utm32); + if (0==P) + return 11; + + /* Test value: utm32_ed50(620000, 6130000) = sb_ed50(495136.8544, 6130821.2945) */ + a = b = c = proj_coord (0,0,0,0); + a.uv.v = 6130821.2945; + a.uv.u = 495136.8544; + c.uv.v = 6130000.0000; + c.uv.u = 620000.0000; + + /* Forward projection */ + b = proj_trans (P, PJ_FWD, a); + dist = proj_xy_dist (b.xy, c.xy); + if (dist > 0.001) + return 2; + + /* Inverse projection */ + b = proj_trans (P, PJ_INV, c); + dist = proj_xy_dist (b.xy, a.xy); + if (dist > 0.001) + return 3; + + /* Check roundtrip precision for 1 iteration each way */ + dist = proj_roundtrip (P, PJ_FWD, 1, &a); + if (dist > 0.01) + return 4; + + proj_destroy(P); + return 0; +} + + + + + + + + + + + + +/* Testing quite a bit of the pj_obs_api as a side effect (inspired by pj_obs_api_test.c) */ +static int pj_cart_selftest (void) { + PJ_CONTEXT *ctx; + PJ *P; + PJ_COORD a, b, obs[2]; + PJ_COORD coord[2]; + + PJ_INFO info; + PJ_PROJ_INFO pj_info; + PJ_GRID_INFO grid_info; + PJ_INIT_INFO init_info; + + PJ_DERIVS derivs; + PJ_FACTORS factors; + + const PJ_OPERATIONS *oper_list; + const PJ_ELLPS *ellps_list; + const PJ_UNITS *unit_list; + const PJ_PRIME_MERIDIANS *pm_list; + + int err; + size_t n, sz; + double dist, h, t; + char *args[3] = {"proj=utm", "zone=32", "ellps=GRS80"}; + char *arg = {"+proj=utm +zone=32 +ellps=GRS80"}; + char buf[40]; + + /* An utm projection on the GRS80 ellipsoid */ + P = proj_create (PJ_DEFAULT_CTX, arg); + if (0==P) + return 1; + + + /* Clean up */ + proj_destroy (P); + + /* Same projection, now using argc/argv style initialization */ + P = proj_create_argv (PJ_DEFAULT_CTX, 3, args); + if (0==P) + return 2; + + /* zero initialize everything, then set (longitude, latitude) to (12, 55) */ + a = proj_coord (0,0,0,0); + /* a.lp: The coordinate part of a, interpreted as a classic LP pair */ + a.lp.lam = PJ_TORAD(12); + a.lp.phi = PJ_TORAD(55); + + /* Forward projection */ + b = proj_trans (P, PJ_FWD, a); + + /* Inverse projection */ + a = proj_trans (P, PJ_INV, b); + + /* Null projection */ + a = proj_trans (P, PJ_IDENT, a); + + /* Forward again, to get two linear items for comparison */ + a = proj_trans (P, PJ_FWD, a); + + dist = proj_xy_dist (a.xy, b.xy); + if (dist > 2e-9) + return 3; + + /* Clear any previous error */ + proj_errno_set (P, 0); + + /* Invalid projection */ + a = proj_trans (P, 42, a); + if (a.lpz.lam!=HUGE_VAL) + return 4; + err = proj_errno (P); + if (0==err) + return 5; + + /* Clear error again */ + proj_errno_set (P, 0); + + /* Clean up */ + proj_destroy (P); + + /* Now do some 3D transformations */ + P = proj_create (PJ_DEFAULT_CTX, "+proj=cart +ellps=GRS80"); + if (0==P) + return 6; + + /* zero initialize everything, then set (longitude, latitude, height) to (12, 55, 100) */ + a = b = proj_coord (0,0,0,0); + a.lpz.lam = PJ_TORAD(12); + a.lpz.phi = PJ_TORAD(55); + a.lpz.z = 100; + + /* Forward projection: 3D-Cartesian-to-Ellipsoidal */ + b = proj_trans (P, PJ_FWD, a); + + /* Check roundtrip precision for 10000 iterations each way */ + dist = proj_roundtrip (P, PJ_FWD, 10000, &a); + dist = proj_roundtrip (P, PJ_INV, 10000, &b); + if (dist > 2e-9) + return 7; + + + /* Test at the North Pole */ + a = b = proj_coord (0,0,0,0); + a.lpz.lam = PJ_TORAD(0); + a.lpz.phi = PJ_TORAD(90); + a.lpz.z = 100; + + /* Forward projection: Ellipsoidal-to-3D-Cartesian */ + dist = proj_roundtrip (P, PJ_FWD, 1, &a); + if (dist > 1e-12) + return 8; + + /* Test at the South Pole */ + a = b = proj_coord (0,0,0,0); + a.lpz.lam = PJ_TORAD(0); + a.lpz.phi = PJ_TORAD(-90); + a.lpz.z = 100; + b = a; + + /* Forward projection: Ellipsoidal-to-3D-Cartesian */ + dist = proj_roundtrip (P, PJ_FWD, 1, &a); + if (dist > 1e-12) + return 9; + + + /* Inverse projection: 3D-Cartesian-to-Ellipsoidal */ + b = proj_trans (P, PJ_INV, b); + + /* Move p to another context */ + ctx = proj_context_create (); + if (ctx==pj_get_default_ctx()) + return 10; + proj_context_set (P, ctx); + if (ctx != P->ctx) + return 11; + b = proj_trans (P, PJ_FWD, b); + + /* Move it back to the default context */ + proj_context_set (P, 0); + if (pj_get_default_ctx() != P->ctx) + return 12; + proj_context_destroy (ctx); + + /* We go on with the work - now back on the default context */ + b = proj_trans (P, PJ_INV, b); + proj_destroy (P); + + + /* Testing proj_trans_generic () */ + + /* An utm projection on the GRS80 ellipsoid */ + P = proj_create (PJ_DEFAULT_CTX, "+proj=utm +zone=32 +ellps=GRS80"); + if (0==P) + return 13; + + obs[0] = proj_coord (PJ_TORAD(12), PJ_TORAD(55), 45, 0); + obs[1] = proj_coord (PJ_TORAD(12), PJ_TORAD(56), 50, 0); + sz = sizeof (PJ_COORD); + + /* Forward projection */ + a = proj_trans (P, PJ_FWD, obs[0]); + b = proj_trans (P, PJ_FWD, obs[1]); + + n = proj_trans_generic ( + P, PJ_FWD, + &(obs[0].lpz.lam), sz, 2, + &(obs[0].lpz.phi), sz, 2, + &(obs[0].lpz.z), sz, 2, + 0, sz, 0 + ); + if (2!=n) + return 14; + if (a.lpz.lam != obs[0].lpz.lam) return 15; + if (a.lpz.phi != obs[0].lpz.phi) return 16; + if (a.lpz.z != obs[0].lpz.z) return 17; + if (b.lpz.lam != obs[1].lpz.lam) return 18; + if (b.lpz.phi != obs[1].lpz.phi) return 19; + if (b.lpz.z != obs[1].lpz.z) return 20; + + /* now test the case of constant z */ + obs[0] = proj_coord (PJ_TORAD(12), PJ_TORAD(55), 45, 0); + obs[1] = proj_coord (PJ_TORAD(12), PJ_TORAD(56), 50, 0); + h = 27; + t = 33; + n = proj_trans_generic ( + P, PJ_FWD, + &(obs[0].lpz.lam), sz, 2, + &(obs[0].lpz.phi), sz, 2, + &h, 0, 1, + &t, 0, 1 + ); + if (2!=n) + return 21; + if (a.lpz.lam != obs[0].lpz.lam) return 22; + if (a.lpz.phi != obs[0].lpz.phi) return 23; + if (45 != obs[0].lpz.z) return 24; + if (b.lpz.lam != obs[1].lpz.lam) return 25; + if (b.lpz.phi != obs[1].lpz.phi) return 26; + if (50 != obs[1].lpz.z) return 27; /* NOTE: unchanged */ + if (50==h) return 28; + + /* test proj_trans_array () */ + + coord[0] = proj_coord (PJ_TORAD(12), PJ_TORAD(55), 45, 0); + coord[1] = proj_coord (PJ_TORAD(12), PJ_TORAD(56), 50, 0); + if (proj_trans_array (P, PJ_FWD, 2, coord)) + return 40; + + if (a.lpz.lam != coord[0].lpz.lam) return 41; + if (a.lpz.phi != coord[0].lpz.phi) return 42; + if (a.lpz.z != coord[0].lpz.z) return 43; + if (b.lpz.lam != coord[1].lpz.lam) return 44; + if (b.lpz.phi != coord[1].lpz.phi) return 45; + if (b.lpz.z != coord[1].lpz.z) return 46; + + /* Clean up after proj_trans_* tests */ + proj_destroy (P); + + /* test proj_create_crs_to_crs() */ + P = proj_create_crs_to_crs(PJ_DEFAULT_CTX, "epsg:25832", "epsg:25833", NULL); + if (P==0) + return 50; + + a.xy.x = 700000.0; + a.xy.y = 6000000.0; + b.xy.x = 307788.8761171057; + b.xy.y = 5999669.3036037628; + + a = proj_trans(P, PJ_FWD, a); + if (dist > 1e-7) + return 51; + proj_destroy(P); + + /* let's make sure that only entries in init-files results in a usable PJ */ + P = proj_create_crs_to_crs(PJ_DEFAULT_CTX, "proj=utm +zone=32 +datum=WGS84", "proj=utm +zone=33 +datum=WGS84", NULL); + if (P != 0) { + proj_destroy(P); + return 52; + } + proj_destroy(P); + + /* ********************************************************************** */ + /* Test info functions */ + /* ********************************************************************** */ + + /* proj_info() */ + /* this one is difficult to test, since the output changes with the setup */ + info = proj_info(); + if (info.version[0] != '\0' ) { + char tmpstr[64]; + sprintf(tmpstr, "%d.%d.%d", info.major, info.minor, info.patch); + if (strcmp(info.version, tmpstr)) return 55; + } + if (info.release[0] == '\0') return 56; + if (info.searchpath[0] == '\0') return 57; + + /* proj_pj_info() */ + P = proj_create(PJ_DEFAULT_CTX, "+proj=august"); /* august has no inverse */ + if (proj_pj_info(P).has_inverse) { proj_destroy(P); return 60; } + proj_destroy(P); + + P = proj_create(PJ_DEFAULT_CTX, arg); + pj_info = proj_pj_info(P); + if ( !pj_info.has_inverse ) { proj_destroy(P); return 61; } + if ( strcmp(pj_info.definition, arg) ) { proj_destroy(P); return 62; } + if ( strcmp(pj_info.id, "utm") ) { proj_destroy(P); return 63; } + proj_destroy(P); + + /* proj_grid_info() */ + grid_info = proj_grid_info("egm96_15.gtx"); + if ( strlen(grid_info.filename) == 0 ) return 64; + if ( strcmp(grid_info.gridname, "egm96_15.gtx") ) return 65; + grid_info = proj_grid_info("nonexistinggrid"); + if ( strlen(grid_info.filename) > 0 ) return 66; + + /* proj_init_info() */ + init_info = proj_init_info("unknowninit"); + if ( strlen(init_info.filename) != 0 ) return 67; + + init_info = proj_init_info("epsg"); + /* Need to allow for "Unknown" until all commonly distributed EPSG-files comes with a metadata section */ + if ( strcmp(init_info.origin, "EPSG") && strcmp(init_info.origin, "Unknown") ) return 69; + if ( strcmp(init_info.name, "epsg") ) return 68; + + + + /* test proj_rtodms() and proj_dmstor() */ + if (strcmp("180dN", proj_rtodms(buf, M_PI, 'N', 'S'))) + return 70; + + if (proj_dmstor(&buf[0], NULL) != M_PI) + return 71; + + if (strcmp("114d35'29.612\"S", proj_rtodms(buf, -2.0, 'N', 'S'))) + return 72; + + /* we can't expect perfect numerical accuracy so testing with a tolerance */ + if (fabs(-2.0 - proj_dmstor(&buf[0], NULL)) > 1e-7) + return 73; + + + /* test proj_derivatives_retrieve() and proj_factors_retrieve() */ + P = proj_create(PJ_DEFAULT_CTX, "+proj=merc"); + a = proj_coord (0,0,0,0); + a.lp.lam = PJ_TORAD(12); + a.lp.phi = PJ_TORAD(55); + + derivs = proj_derivatives(P, a.lp); + if (proj_errno(P)) + return 80; /* derivs not created correctly */ + + if ( fabs(derivs.x_l - 1.0) > 1e-5 ) return 81; + if ( fabs(derivs.x_p - 0.0) > 1e-5 ) return 82; + if ( fabs(derivs.y_l - 0.0) > 1e-5 ) return 83; + if ( fabs(derivs.y_p - 1.73959) > 1e-5 ) return 84; + + + factors = proj_factors(P, a.lp); + if (proj_errno(P)) + return 85; /* factors not created correctly */ + + /* check a few key characteristics of the Mercator projection */ + if (factors.omega != 0.0) return 86; /* angular distortion should be 0 */ + if (factors.thetap != M_PI_2) return 87; /* Meridian/parallel angle should be 90 deg */ + if (factors.conv != 0.0) return 88; /* meridian convergence should be 0 */ + + + proj_destroy(P); + + /* Check that proj_list_* functions work by looping through them */ + n = 0; + for (oper_list = proj_list_operations(); oper_list->id; ++oper_list) n++; + if (n == 0) return 90; + + n = 0; + for (ellps_list = proj_list_ellps(); ellps_list->id; ++ellps_list) n++; + if (n == 0) return 91; + + n = 0; + for (unit_list = proj_list_units(); unit_list->id; ++unit_list) n++; + if (n == 0) return 92; + + n = 0; + for (pm_list = proj_list_prime_meridians(); pm_list->id; ++pm_list) n++; + if (n == 0) return 93; + + + /* check io-predicates */ + + /* angular in on fwd, linear out */ + P = proj_create (PJ_DEFAULT_CTX, "+proj=cart +ellps=GRS80"); + if (0==P) return 0; + if (!proj_angular_input (P, PJ_FWD)) return 100; + if ( proj_angular_input (P, PJ_INV)) return 101; + if ( proj_angular_output (P, PJ_FWD)) return 102; + if (!proj_angular_output (P, PJ_INV)) return 103; + P->inverted = 1; + if ( proj_angular_input (P, PJ_FWD)) return 104; + if (!proj_angular_input (P, PJ_INV)) return 105; + if (!proj_angular_output (P, PJ_FWD)) return 106; + if ( proj_angular_output (P, PJ_INV)) return 107; + proj_destroy(P); + + /* angular in and out */ + P = proj_create(PJ_DEFAULT_CTX, + "+proj=molodensky +a=6378160 +rf=298.25 " + "+da=-23 +df=-8.120449e-8 +dx=-134 +dy=-48 +dz=149 " + "+abridged " + ); + if (0==P) return 0; + if (!proj_angular_input (P, PJ_FWD)) return 108; + if (!proj_angular_input (P, PJ_INV)) return 109; + if (!proj_angular_output (P, PJ_FWD)) return 110; + if (!proj_angular_output (P, PJ_INV)) return 111; + P->inverted = 1; + if (!proj_angular_input (P, PJ_FWD)) return 112; + if (!proj_angular_input (P, PJ_INV)) return 113; + if (!proj_angular_output (P, PJ_FWD)) return 114; + if (!proj_angular_output (P, PJ_INV)) return 115; + proj_destroy(P); + + /* linear in and out */ + P = proj_create(PJ_DEFAULT_CTX, + " +proj=helmert +ellps=GRS80" + " +x=0.0127 +y=0.0065 +z=-0.0209 +s=0.00195" + " +rx=-0.00039 +ry=0.00080 +rz=-0.00114" + " +dx=-0.0029 +dy=-0.0002 +dz=-0.0006 +ds=0.00001" + " +drx=-0.00011 +dry=-0.00019 +drz=0.00007" + " +epoch=1988.0 +transpose" + ); + if (0==P) return 0; + if (proj_angular_input (P, PJ_FWD)) return 116; + if (proj_angular_input (P, PJ_INV)) return 117; + if (proj_angular_output (P, PJ_FWD)) return 118; + if (proj_angular_output (P, PJ_INV)) return 119; + P->inverted = 1; + if (proj_angular_input (P, PJ_FWD)) return 120; + if (proj_angular_input (P, PJ_INV)) return 121; + if (proj_angular_output (P, PJ_FWD)) return 122; + if (proj_angular_output (P, PJ_INV)) return 123; + proj_destroy(P); + + + return 0; +} + + + + + + + + + + + + + + + +static int test_time(char* args, double tol, double t_in, double t_exp) { + PJ_COORD in, out; + PJ *P = proj_create(PJ_DEFAULT_CTX, args); + int ret = 0; + + if (P == 0) + return 5; + + in.xyzt.t = t_in; + + out = proj_trans(P, PJ_FWD, in); + if (fabs(out.xyzt.t - t_exp) > tol) { + proj_log_error(P, "out: %10.10g, expect: %10.10g", out.xyzt.t, t_exp); + ret = 1; + } + out = proj_trans(P, PJ_INV, out); + if (fabs(out.xyzt.t - t_in) > tol) { + proj_log_error(P, "out: %10.10g, expect: %10.10g", out.xyzt.t, t_in); + ret = 2; + } + pj_free(P); + + proj_log_level(NULL, 0); + return ret; +} + +static int test_xyz(char* args, double tol, PJ_TRIPLET in, PJ_TRIPLET exp) { + PJ_COORD out, obs_in; + PJ *P = proj_create(PJ_DEFAULT_CTX, args); + int ret = 0; + + if (P == 0) + return 5; + + obs_in.xyz = in.xyz; + out = proj_trans(P, PJ_FWD, obs_in); + if (proj_xyz_dist(out.xyz, exp.xyz) > tol) { + printf("exp: %10.10g, %10.10g, %10.10g\n", exp.xyz.x, exp.xyz.y, exp.xyz.z); + printf("out: %10.10g, %10.10g, %10.10g\n", out.xyz.x, out.xyz.y, out.xyz.z); + ret = 1; + } + + out = proj_trans(P, PJ_INV, out); + if (proj_xyz_dist(out.xyz, in.xyz) > tol) { + printf("exp: %g, %g, %g\n", in.xyz.x, in.xyz.y, in.xyz.z); + printf("out: %g, %g, %g\n", out.xyz.x, out.xyz.y, out.xyz.z); + ret += 2; + } + proj_destroy(P); + proj_log_level(NULL, 0); + return ret; +} + + +static int pj_unitconvert_selftest (void) { + int ret = 0; + char args1[] = "+proj=unitconvert +t_in=decimalyear +t_out=decimalyear"; + double in1 = 2004.25; + + char args2[] = "+proj=unitconvert +t_in=gps_week +t_out=gps_week"; + double in2 = 1782.0; + + char args3[] = "+proj=unitconvert +t_in=mjd +t_out=mjd"; + double in3 = 57390.0; + + char args4[] = "+proj=unitconvert +t_in=gps_week +t_out=decimalyear"; + double in4 = 1877.71428, exp4 = 2016.0; + + char args5[] = "+proj=unitconvert +xy_in=m +xy_out=dm +z_in=cm +z_out=mm"; + PJ_TRIPLET in5 = {{55.25, 23.23, 45.5}}, exp5 = {{552.5, 232.3, 455.0}}; + + char args6[] = "+proj=unitconvert +xy_in=m +xy_out=m +z_in=m +z_out=m"; + PJ_TRIPLET in6 = {{12.3, 45.6, 7.89}}; + + ret = test_time(args1, 1e-6, in1, in1); if (ret) return ret + 10; + ret = test_time(args2, 1e-6, in2, in2); if (ret) return ret + 20; + ret = test_time(args3, 1e-6, in3, in3); if (ret) return ret + 30; + ret = test_time(args4, 1e-6, in4, exp4); if (ret) return ret + 40; + ret = test_xyz (args5, 1e-10, in5, exp5); if (ret) return ret + 50; + ret = test_xyz (args6, 1e-10, in6, in6); if (ret) return ret + 50; + + return 0; + +} + + + |
