Beispiel #1
0
/* Measure numerical deviation after n roundtrips fwd-inv (or inv-fwd) */
double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD *coord) {
    int i;
    PJ_COORD t, org;

    if (0==P)
        return HUGE_VAL;

    if (n < 1) {
        proj_errno_set (P, EINVAL);
        return HUGE_VAL;
    }

    /* in the first half-step, we generate the output value */
    org  = *coord;
    *coord = proj_trans (P, direction, org);
    t = *coord;

    /* now we take n-1 full steps in inverse direction: We are */
    /* out of phase due to the half step already taken */
    for (i = 0;  i < n - 1;  i++)
        t = proj_trans (P,  direction,  proj_trans (P, -direction, t) );

    /* finally, we take the last half-step */
    t = proj_trans (P, -direction, t);

    /* checking for angular *input* since we do a roundtrip, and end where we begin */
    if (proj_angular_input (P, direction))
        return proj_lpz_dist (P, org, t);

    return proj_xyz_dist (org, t);
}
Beispiel #2
0
int proj_angular_output (PJ *P, enum PJ_DIRECTION dir) {
/******************************************************************************
    Returns 1 if the operator P provides angular output coordinates when
    operating in direction dir, 0 otherwise.
    dir: {PJ_FWD, PJ_INV}
******************************************************************************/
    return proj_angular_input (P, -dir);
}
Beispiel #3
0
/* file processing function */
static void process(FILE *fid) {
    char line[MAX_LINE+3], *s = nullptr, pline[40];
    PJ_COORD data;

    for (;;) {
        int facs_bad = 0;
        ++emess_dat.File_line;

        if (bin_in) {   /* binary input */
            if (fread(&data, sizeof(PJ_UV), 1, fid) != 1)
                break;
        } else {    /* ascii input */
            if (!(s = fgets(line, MAX_LINE, fid)))
                break;

            if (!strchr(s, '\n')) { /* overlong line */
                int c;
                (void)strcat(s, "\n");
                /* gobble up to newline */
                while ((c = fgetc(fid)) != EOF && c != '\n') ;
            }

            if (*s == tag) {
                if (!bin_out)
                    (void)fputs(line, stdout);
                continue;
            }

            if (reversein) {
                data.uv.v = (*informat)(s, &s);
                data.uv.u = (*informat)(s, &s);
            } else {
                data.uv.u = (*informat)(s, &s);
                data.uv.v = (*informat)(s, &s);
            }

            if (data.uv.v == HUGE_VAL)
                data.uv.u = HUGE_VAL;

            if (!*s && (s > line)) --s; /* assumed we gobbled \n */
            if (!bin_out && echoin) {
                char t;
                t = *s;
                *s = '\0';
                (void)fputs(line, stdout);
                *s = t;
                putchar('\t');
            }
        }

        if (data.uv.u != HUGE_VAL) {
            PJ_COORD coord;
            coord.lp = data.lp;
            if (prescale) { data.uv.u *= fscale; data.uv.v *= fscale; }
            if (dofactors && !inverse) {
                facs = proj_factors(Proj, coord);
                facs_bad = proj_errno(Proj);
            }

            data.xy = (*proj.fwd)(data.lp, Proj);

            if (dofactors && inverse) {
                facs = proj_factors(Proj, coord);
                facs_bad = proj_errno(Proj);
            }

            if (postscale && data.uv.u != HUGE_VAL)
                { data.uv.u *= fscale; data.uv.v *= fscale; }
        }

        if (bin_out) { /* binary output */
            (void)fwrite(&data, sizeof(PJ_UV), 1, stdout);
            continue;
        } else if (data.uv.u == HUGE_VAL) /* error output */
            (void)fputs(oterr, stdout);
        else if (inverse && !oform) {   /*ascii DMS output */
            if (reverseout) {
                (void)fputs(rtodms(pline, data.uv.v, 'N', 'S'), stdout);
                putchar('\t');
                (void)fputs(rtodms(pline, data.uv.u, 'E', 'W'), stdout);
            } else {
                (void)fputs(rtodms(pline, data.uv.u, 'E', 'W'), stdout);
                putchar('\t');
                (void)fputs(rtodms(pline, data.uv.v, 'N', 'S'), stdout);
            }
        } else {    /* x-y or decimal degree ascii output, scale if warranted by output units */
            if (inverse) {
                if (proj_angular_input(Proj, PJ_FWD)) {
                    data.uv.v *= RAD_TO_DEG;
                    data.uv.u *= RAD_TO_DEG;
                }
            } else {
                if (proj_angular_output(Proj, PJ_FWD)) {
                    data.uv.v *= RAD_TO_DEG;
                    data.uv.u *= RAD_TO_DEG;
                }
            }

            if (reverseout) {
                (void)printf(oform, data.uv.v); putchar('\t');
                (void)printf(oform, data.uv.u);
            } else {
                (void)printf(oform, data.uv.u); putchar('\t');
                (void)printf(oform, data.uv.v);
            }
        }

        /* print scale factor data */
        if (dofactors) {
            if (!facs_bad)
                (void)printf("\t<%g %g %g %g %g %g>",
                    facs.meridional_scale, facs.parallel_scale, facs.areal_scale,
                    facs.angular_distortion * RAD_TO_DEG, facs.tissot_semimajor, facs.tissot_semiminor);
            else
                (void)fputs("\t<* * * * * *>", stdout);
        }
        (void)fputs(bin_in ? "\n" : s, stdout);
    }
}
Beispiel #4
0
int main(int argc, char **argv) {
    char *arg, *pargv[MAX_PARGS];
    char **eargv = argv;
    FILE *fid;
    int pargc = 0, eargc = 0, mon = 0;

    if ( (emess_dat.Prog_name = strrchr(*argv,DIR_CHAR)) != nullptr)
        ++emess_dat.Prog_name;
    else emess_dat.Prog_name = *argv;
    inverse = ! strncmp(emess_dat.Prog_name, "inv", 3);
    if (argc <= 1 ) {
        (void)fprintf(stderr, usage, pj_get_release(), emess_dat.Prog_name);
        exit (0);
    }

    /* process run line arguments */
    while (--argc > 0) { /* collect run line arguments */
        if(**++argv == '-') for(arg = *argv;;) {
            switch(*++arg) {
              case '\0': /* position of "stdin" */
                if (arg[-1] == '-') eargv[eargc++] = const_cast<char*>("-");
                break;
              case 'b': /* binary I/O */
                bin_in = bin_out = 1;
                continue;
              case 'v': /* monitor dump of initialization */
                mon = 1;
                continue;
              case 'i': /* input binary */
                bin_in = 1;
                continue;
              case 'o': /* output binary */
                bin_out = 1;
                continue;
              case 'I': /* alt. method to spec inverse */
                inverse = 1;
                continue;
              case 'E': /* echo ascii input to ascii output */
                echoin = 1;
                continue;
              case 'V': /* very verbose processing mode */
                very_verby = 1;
                mon = 1;
                continue;
              case 'S': /* compute scale factors */
                dofactors = 1;
                continue;
              case 't': /* set col. one char */
                if (arg[1]) tag = *++arg;
                else emess(1,"missing -t col. 1 tag");
                continue;
              case 'l': /* list projections, ellipses or units */
                if (!arg[1] || arg[1] == 'p' || arg[1] == 'P') {
                    /* list projections */
                    const struct PJ_LIST *lp;
                    int do_long = arg[1] == 'P', c;
                    const char *str;

                    for (lp = proj_list_operations() ; lp->id ; ++lp) {
                        if( strcmp(lp->id,"latlong") == 0
                            || strcmp(lp->id,"longlat") == 0
                            || strcmp(lp->id,"geocent") == 0 )
                            continue;

                        (void)printf("%s : ", lp->id);
                        if (do_long)  /* possibly multiline description */
                            (void)puts(*lp->descr);
                        else { /* first line, only */
                            str = *lp->descr;
                            while ((c = *str++) && c != '\n')
                                putchar(c);
                            putchar('\n');
                        }
                    }
                } else if (arg[1] == '=') { /* list projection 'descr' */
                    const struct PJ_LIST *lp;

                    arg += 2;
                    for (lp = proj_list_operations(); lp->id ; ++lp)
                        if (!strcmp(lp->id, arg)) {
                            (void)printf("%9s : %s\n", lp->id, *lp->descr);
                            break;
                        }
                } else if (arg[1] == 'e') { /* list ellipses */
                    const struct PJ_ELLPS *le;

                    for (le = proj_list_ellps(); le->id ; ++le)
                        (void)printf("%9s %-16s %-16s %s\n",
                                     le->id, le->major, le->ell, le->name);
                } else if (arg[1] == 'u') { /* list units */
                    const struct PJ_UNITS *lu;

                    for (lu = proj_list_units(); lu->id ; ++lu)
                        (void)printf("%12s %-20s %s\n",
                                     lu->id, lu->to_meter, lu->name);
                } else if (arg[1] == 'd') { /* list datums */
                    const struct PJ_DATUMS *ld;

                    printf("__datum_id__ __ellipse___ __definition/comments______________________________\n" );
                    for (ld = pj_get_datums_ref(); ld->id ; ++ld)
                    {
                        printf("%12s %-12s %-30s\n",
                               ld->id, ld->ellipse_id, ld->defn);
                        if( ld->comments != nullptr && strlen(ld->comments) > 0 )
                            printf( "%25s %s\n", " ", ld->comments );
                    }
                } else
                    emess(1,"invalid list option: l%c",arg[1]);
                exit(0);
                /* cppcheck-suppress duplicateBreak */
                continue; /* artificial */
              case 'e': /* error line alternative */
                if (--argc <= 0)
                    noargument:
                emess(1,"missing argument for -%c",*arg);
                oterr = *++argv;
                continue;
              case 'm': /* cartesian multiplier */
                if (--argc <= 0) goto noargument;
                postscale = 1;
                if (!strncmp("1/",*++argv,2) ||
                    !strncmp("1:",*argv,2)) {
                    if((fscale = atof((*argv)+2)) == 0.)
                        goto badscale;
                    fscale = 1. / fscale;
                } else
                    if ((fscale = atof(*argv)) == 0.) {
                      badscale:
                        emess(1,"invalid scale argument");
                    }
                continue;
              case 'W': /* specify seconds precision */
              case 'w': /* -W for constant field width */
              {
                int c = arg[1];
                if (c != 0 && isdigit(c)) {
                    set_rtodms(c - '0', *arg == 'W');
                    ++arg;
                } else
                    emess(1,"-W argument missing or non-digit");
                continue;
              }
              case 'f': /* alternate output format degrees or xy */
                if (--argc <= 0) goto noargument;
                oform = *++argv;
                continue;
              case 'd':
                if (--argc <= 0) goto noargument;
                sprintf(oform_buffer, "%%.%df", atoi(*++argv));
                oform = oform_buffer;
                break;
              case 'r': /* reverse input */
                reversein = 1;
                continue;
              case 's': /* reverse output */
                reverseout = 1;
                continue;
              default:
                emess(1, "invalid option: -%c",*arg);
                break;
            }
            break;
        } else if (**argv == '+') { /* + argument */
            if (pargc < MAX_PARGS)
                pargv[pargc++] = *argv + 1;
            else
                emess(1,"overflowed + argument table");
        } else /* assumed to be input file name(s) */
            eargv[eargc++] = *argv;
    }
    if (eargc == 0) /* if no specific files force sysin */
        eargv[eargc++] = const_cast<char*>("-");

    /* done with parameter and control input */
    if (inverse && postscale) {
        prescale = 1;
        postscale = 0;
        fscale = 1./fscale;
    }
    if (!(Proj = pj_init(pargc, pargv)))
        emess(3,"projection initialization failure\ncause: %s",
              pj_strerrno(pj_errno));

    if (!proj_angular_input(Proj, PJ_FWD)) {
        emess(3, "can't initialize operations that take non-angular input coordinates");
        exit(0);
    }

    if (proj_angular_output(Proj, PJ_FWD)) {
        emess(3, "can't initialize operations that produce angular output coordinates");
        exit(0);
    }

    if (inverse) {
        if (!Proj->inv)
            emess(3,"inverse projection not available");
        proj.inv = pj_inv;
    } else
        proj.fwd = pj_fwd;

    /* set input formatting control */
    if (mon) {
        pj_pr_list(Proj);
        if (very_verby) {
            (void)printf("#Final Earth figure: ");
            if (Proj->es != 0.0) {
                (void)printf("ellipsoid\n#  Major axis (a): ");
                (void)printf(oform ? oform : "%.3f", Proj->a);
                (void)printf("\n#  1/flattening: %.6f\n",
                             1./(1. - sqrt(1. - Proj->es)));
                (void)printf("#  squared eccentricity: %.12f\n", Proj->es);
            } else {
                (void)printf("sphere\n#  Radius: ");
                (void)printf(oform ? oform : "%.3f", Proj->a);
                (void)putchar('\n');
            }
        }
    }

    if (inverse)
        informat = strtod;
    else {
        informat = proj_dmstor;
        if (!oform)
            oform = "%.2f";
    }

    if (bin_out) {
        SET_BINARY_MODE(stdout);
    }

    /* process input file list */
    for ( ; eargc-- ; ++eargv) {
        if (**eargv == '-') {
            fid = stdin;
            emess_dat.File_name = const_cast<char*>("<stdin>");

            if (bin_in)
            {
                SET_BINARY_MODE(stdin);
            }

        } else {
            if ((fid = fopen(*eargv, "rb")) == nullptr) {
                emess(-2, *eargv, "input file");
                continue;
            }
            emess_dat.File_name = *eargv;
        }
        emess_dat.File_line = 0;
        if (very_verby)
            vprocess(fid);
        else
            process(fid);
        (void)fclose(fid);
        emess_dat.File_name = nullptr;
    }

    if( Proj )
        pj_free(Proj);

    exit(0); /* normal completion */
}
Beispiel #5
0
static int expect (const char *args) {
/*****************************************************************************
Tell GIE what to expect, when transforming the ACCEPTed input
******************************************************************************/
    PJ_COORD ci, co, ce;
    double d;
    int expect_failure = 0;
    int expect_failure_with_errno = 0;

    if (0==strncmp (args, "failure", 7)) {
        expect_failure = 1;

        /* Option: Fail with an expected errno (syntax: expect failure errno -33) */
        if (0==strncmp (column (args, 2), "errno", 5))
            expect_failure_with_errno = errno_from_err_const (column (args, 3));
    }

    if (T.ignore==proj_errno(T.P))
        return another_skip ();

    if (nullptr==T.P) {
        /* If we expect failure, and fail, then it's a success... */
        if (expect_failure) {
            /* Failed to fail correctly? */
            if (expect_failure_with_errno && proj_errno (T.P)!=expect_failure_with_errno)
                return expect_failure_with_errno_message (expect_failure_with_errno, proj_errno(T.P));

            return another_succeeding_failure ();
        }

        /* Otherwise, it's a true failure */
        banner (T.operation);
        errmsg (3, "%sInvalid operation definition in line no. %d:\n       %s (errno=%s/%d)\n",
            delim, (int) T.operation_lineno, pj_strerrno(proj_errno(T.P)),
            err_const_from_errno (proj_errno(T.P)), proj_errno(T.P)
        );
        return another_failing_failure ();
    }

    /* We may still successfully fail even if the proj_create succeeded */
    if (expect_failure) {
        proj_errno_reset (T.P);

        /* Try to carry out the operation - and expect failure */
        ci = proj_angular_input (T.P, T.dir)? torad_coord (T.P, T.dir, T.a): T.a;
        co = expect_trans_n_dim (ci);

        if (expect_failure_with_errno) {
            if (proj_errno (T.P)==expect_failure_with_errno)
                return another_succeeding_failure ();
            fprintf (T.fout, "errno=%d, expected=%d\n", proj_errno (T.P), expect_failure_with_errno);
            return another_failing_failure ();
        }


        /* Succeeded in failing? - that's a success */
        if (co.xyz.x==HUGE_VAL)
            return another_succeeding_failure ();

        /* Failed to fail? - that's a failure */
        banner (T.operation);
        errmsg (3, "%sFailed to fail. Operation definition in line no. %d\n",
            delim, (int) T.operation_lineno
        );
        return another_failing_failure ();
    }


    if (T.verbosity > 3) {
        fprintf (T.fout, "%s\n", T.P->inverted? "INVERTED": "NOT INVERTED");
        fprintf (T.fout, "%s\n", T.dir== 1? "forward": "reverse");
        fprintf (T.fout, "%s\n", proj_angular_input (T.P, T.dir)?  "angular in":  "linear in");
        fprintf (T.fout, "%s\n", proj_angular_output (T.P, T.dir)? "angular out": "linear out");
        fprintf (T.fout, "left: %d   right:  %d\n", T.P->left, T.P->right);
    }

    tests++;
    T.e  =  parse_coord (args);
    if (HUGE_VAL==T.e.v[0])
        return expect_message_cannot_parse (args);


    /* expected angular values, probably in degrees */
    ce = proj_angular_output (T.P, T.dir)? torad_coord (T.P, T.dir, T.e): T.e;
    if (T.verbosity > 3)
        fprintf (T.fout, "EXPECTS  %.12f  %.12f  %.12f  %.12f\n",
                 ce.v[0],ce.v[1],ce.v[2],ce.v[3]);

    /* input ("accepted") values, also probably in degrees */
    ci = proj_angular_input (T.P, T.dir)? torad_coord (T.P, T.dir, T.a): T.a;
    if (T.verbosity > 3)
        fprintf (T.fout, "ACCEPTS  %.12f  %.12f  %.12f  %.12f\n",
                 ci.v[0],ci.v[1],ci.v[2],ci.v[3]);

    /* do the transformation, but mask off dimensions not given in expect-ation */
    co = expect_trans_n_dim (ci);
    if (T.dimensions_given < 4)
        co.v[3] = 0;
    if (T.dimensions_given < 3)
        co.v[2] = 0;

    /* angular output from proj_trans comes in radians */
    T.b = proj_angular_output (T.P, T.dir)? todeg_coord (T.P, T.dir, co): co;
    if (T.verbosity > 3)
        fprintf (T.fout, "GOT      %.12f  %.12f  %.12f  %.12f\n",
                 co.v[0],co.v[1],co.v[2],co.v[3]);

#if 0
    /* We need to handle unusual axis orders - that'll be an item for version 5.1 */
    if (T.P->axisswap) {
        ce = proj_trans (T.P->axisswap, T.dir, ce);
        co = proj_trans (T.P->axisswap, T.dir, co);
    }
#endif
    if (proj_angular_output (T.P, T.dir))
        d = proj_lpz_dist (T.P, ce, co);
    else
        d = proj_xyz_dist (co, ce);

    if (d > T.tolerance)
        return expect_message (d, args);
    succs++;

    another_success ();
    return 0;
}
Beispiel #6
0
static int roundtrip (const char *args) {
/*****************************************************************************
Check how far we go from the ACCEPTed point when doing successive
back/forward transformation pairs.

Without args, roundtrip defaults to 100 iterations:

  roundtrip

With one arg, roundtrip will default to a tolerance of T.tolerance:

  roundtrip ntrips

With two args:

  roundtrip ntrips tolerance

Always returns 0.
******************************************************************************/
    int ntrips;
    double d, r, ans;
    char *endp;
    PJ_COORD coo;

    if (nullptr==T.P) {
        if (T.ignore == proj_errno(T.P))
            return another_skip();

        return another_failure ();
    }

    ans = proj_strtod (args, &endp);
    if (endp==args) {
        /* Default to 100 iterations if not args. */
        ntrips = 100;
    } else {
        if (ans < 1.0 || ans > 1000000.0) {
            errmsg (2, "Invalid number of roundtrips: %lf\n", ans);
            return another_failing_roundtrip ();
        }
        ntrips = (int)ans;
    }

    d = strtod_scaled (endp, 1);
    d = d==HUGE_VAL?  T.tolerance:  d;

    /* input ("accepted") values - probably in degrees */
    coo = proj_angular_input  (T.P, T.dir)? torad_coord (T.P, T.dir, T.a):  T.a;

    r = proj_roundtrip (T.P, T.dir, ntrips, &coo);
    if (r <= d)
        return another_succeeding_roundtrip ();

    if (T.verbosity > -1) {
        if (0==T.op_ko && T.verbosity < 2)
            banner (T.operation);
        fprintf (T.fout, "%s", T.op_ko? "     -----\n": delim);
        fprintf (T.fout, "     FAILURE in %s(%d):\n", opt_strip_path (T.curr_file), (int) F->lineno);
        fprintf (T.fout, "     roundtrip deviation: %.6f mm, expected: %.6f mm\n", 1000*r, 1000*d);
    }
    return another_failing_roundtrip ();
}