コード例 #1
0
ファイル: fwd.cpp プロジェクト: QuLogic/proj.4
static PJ_COORD error_or_coord(PJ *P, PJ_COORD coord, int last_errno) {
    if (proj_errno(P))
        return proj_coord_error();

    proj_errno_restore(P, last_errno);
    return coord;
}
コード例 #2
0
ファイル: deformation.cpp プロジェクト: kbevers/proj.4
static PJ_XYZ get_grid_shift(PJ* P, PJ_XYZ cartesian) {
/********************************************************************************
    Read correction values from grid. The cartesian input coordinates are
    converted to geodetic coordinates in order look up the correction values
    in the grid. Once the grid corrections are read we need to convert them
    from ENU-space to cartesian PJ_XYZ-space. ENU -> PJ_XYZ formula described in:

    Nørbech, T., et al, 2003(?), "Transformation from a Common Nordic Reference
    Frame to ETRS89 in Denmark, Finland, Norway, and Sweden – status report"

********************************************************************************/
    PJ_COORD geodetic, shift, temp;
    double sp, cp, sl, cl;
    int previous_errno = proj_errno_reset(P);

    /* cartesian to geodetic */
    geodetic.lpz = pj_inv3d(cartesian, static_cast<struct pj_opaque*>(P->opaque)->cart);

    /* look up correction values in grids */
    shift.lp    = proj_hgrid_value(P, geodetic.lp);
    shift.enu.u = proj_vgrid_value(P, geodetic.lp);

    if (proj_errno(P) == PJD_ERR_GRID_AREA)
        proj_log_debug(P, "deformation: coordinate (%.3f, %.3f) outside deformation model",
                       proj_todeg(geodetic.lp.lam), proj_todeg(geodetic.lp.phi));

    /* grid values are stored as mm/yr, we need m/yr */
    shift.xyz.x /= 1000;
    shift.xyz.y /= 1000;
    shift.xyz.z /= 1000;

    /* pre-calc cosines and sines */
    sp = sin(geodetic.lp.phi);
    cp = cos(geodetic.lp.phi);
    sl = sin(geodetic.lp.lam);
    cl = cos(geodetic.lp.lam);

    /* ENU -> PJ_XYZ */
    temp.xyz.x = -sp*cl*shift.enu.n - sl*shift.enu.e + cp*cl*shift.enu.u;
    temp.xyz.y = -sp*sl*shift.enu.n + cl*shift.enu.e + cp*sl*shift.enu.u;
    temp.xyz.z =     cp*shift.enu.n +                     sp*shift.enu.u;

    shift.xyz = temp.xyz;

    proj_errno_restore(P, previous_errno);

    return shift.xyz;
}
コード例 #3
0
ファイル: pipeline.cpp プロジェクト: QuLogic/proj.4
/* re-initialize P->geod.                                                    */
static void set_ellipsoid(PJ *P) {
    paralist *cur, *attachment;
    int err = proj_errno_reset (P);

    /* Break the linked list after the global args */
    attachment = nullptr;
    for (cur = P->params; cur != nullptr; cur = cur->next)
        /* cur->next will always be non 0 given argv_sentinel presence, */
        /* but this is far from being obvious for a static analyzer */
        if (cur->next != nullptr && strcmp(argv_sentinel, cur->next->param) == 0) {
            attachment = cur->next;
            cur->next = nullptr;
            break;
        }

    /* Check if there's any ellipsoid specification in the global params. */
    /* If not, use GRS80 as default                                       */
    if (0 != pj_ellipsoid (P)) {
        P->a  = 6378137.0;
        P->f = 1.0 / 298.257222101;
        P->es = 2*P->f - P->f*P->f;

        /* reset an "unerror": In this special use case, the errno is    */
        /* not an error signal, but just a reply from pj_ellipsoid,      */
        /* telling us that "No - there was no ellipsoid definition in    */
        /* the PJ you provided".                                         */
        proj_errno_reset (P);
    }
    P->a_orig = P->a;
    P->es_orig = P->es;

    pj_calc_ellipsoid_params (P, P->a, P->es);

    geod_init(P->geod, P->a,  (1 - sqrt (1 - P->es)));

    /* Re-attach the dangling list */
    /* Note: cur will always be non 0 given argv_sentinel presence, */
    /* but this is far from being obvious for a static analyzer */
    if( cur != nullptr )
        cur->next = attachment;
    proj_errno_restore (P, err);
}
コード例 #4
0
ファイル: pj_init.c プロジェクト: ampimis/RtkGps
PJ *
pj_init_ctx(projCtx ctx, int argc, char **argv) {
    char *s, *name;
    PJ_CONSTRUCTOR proj;
    paralist *curr, *init, *start;
    int i;
    int err;
    PJ *PIN = 0;
    int n_pipelines = 0;
    int n_inits = 0;

    if (0==ctx)
        ctx = pj_get_default_ctx ();

    ctx->last_errno = 0;

    if (argc <= 0) {
        pj_ctx_set_errno (ctx, PJD_ERR_NO_ARGS);
        return 0;
    }

    /* count occurrences of pipelines and inits */
    for (i = 0; i < argc; ++i) {
        if (!strcmp (argv[i], "+proj=pipeline") || !strcmp(argv[i], "proj=pipeline") )
                n_pipelines++;
        if (!strncmp (argv[i], "+init=", 6) || !strncmp(argv[i], "init=", 5))
            n_inits++;
    }

    /* can't have nested pipelines directly */
    if (n_pipelines > 1) {
        pj_ctx_set_errno (ctx, PJD_ERR_MALFORMED_PIPELINE);
        return 0;
    }

    /* don't allow more than one +init in non-pipeline operations */
    if (n_pipelines == 0 && n_inits > 1) {
        pj_ctx_set_errno (ctx, PJD_ERR_TOO_MANY_INITS);
        return 0;
    }


    /* put arguments into internal linked list */
    start = curr = pj_mkparam(argv[0]);
    if (!curr)
        return pj_dealloc_params (ctx, start, ENOMEM);

    for (i = 1; i < argc; ++i) {
        curr->next = pj_mkparam(argv[i]);
        if (!curr->next)
            return pj_dealloc_params (ctx, start, ENOMEM);
        curr = curr->next;
    }


    /* Only expand '+init's in non-pipeline operations. '+init's in pipelines are */
    /* expanded in the individual pipeline steps during pipeline initialization.  */
    /* Potentially this leads to many nested pipelines, which shouldn't be a      */
    /* problem when '+init's are expanded as late as possible.                    */
    init = pj_param_exists (start, "init");
    if (init && n_pipelines == 0) {
        init = pj_expand_init (ctx, init);
        if (!init)
            return pj_dealloc_params (ctx, start, PJD_ERR_NO_ARGS);
    }
    if (ctx->last_errno)
        return pj_dealloc_params (ctx, start, ctx->last_errno);

    /* Find projection selection */
    curr = pj_param_exists (start, "proj");
    if (0==curr)
        return pj_dealloc_params (ctx, start, PJD_ERR_PROJ_NOT_NAMED);
    name =  curr->param;
    if (strlen (name) < 6)
        return pj_dealloc_params (ctx, start, PJD_ERR_PROJ_NOT_NAMED);
    name += 5;

    proj = locate_constructor (name);
    if (0==proj)
        return pj_dealloc_params (ctx, start, PJD_ERR_UNKNOWN_PROJECTION_ID);


    /* Append general and projection specific defaults to the definition list */
    append_defaults_to_paralist (ctx, start, "general");
    append_defaults_to_paralist (ctx, start, name);


    /* Allocate projection structure */
    PIN = proj(0);
    if (0==PIN)
        return pj_dealloc_params (ctx, start, ENOMEM);


    PIN->ctx = ctx;
    PIN->params = start;
    PIN->is_latlong = 0;
    PIN->is_geocent = 0;
    PIN->is_long_wrap_set = 0;
    PIN->long_wrap_center = 0.0;
    strcpy( PIN->axis, "enu" );

    PIN->gridlist = NULL;
    PIN->gridlist_count = 0;

    PIN->vgridlist_geoid = NULL;
    PIN->vgridlist_geoid_count = 0;

    /* Set datum parameters. Similarly to +init parameters we want to expand    */
    /* +datum parameters as late as possible when dealing with pipelines.       */
    /* otherwise only the first occurrence of +datum will be expanded and that */
    if (n_pipelines == 0) {
        if (pj_datum_set(ctx, start, PIN))
            return pj_default_destructor (PIN, proj_errno(PIN));
    }

    err = pj_ellipsoid (PIN);

    if (err) {
        /* Didn't get an ellps, but doesn't need one: Get a free WGS84 */
        if (PIN->need_ellps) {
            pj_log (ctx, PJ_LOG_DEBUG_MINOR, "pj_init_ctx: Must specify ellipsoid or sphere");
            return pj_default_destructor (PIN, proj_errno(PIN));
        }
        else {
            if (PJD_ERR_MAJOR_AXIS_NOT_GIVEN==proj_errno (PIN))
                proj_errno_reset (PIN);
            PIN->f = 1.0/298.257223563;
            PIN->a_orig  = PIN->a  = 6378137.0;
            PIN->es_orig = PIN->es = PIN->f*(2-PIN->f);
        }
    }
    PIN->a_orig = PIN->a;
    PIN->es_orig = PIN->es;
    if (pj_calc_ellipsoid_params (PIN, PIN->a, PIN->es))
        return pj_default_destructor (PIN, PJD_ERR_ECCENTRICITY_IS_ONE);

    /* Now that we have ellipse information check for WGS84 datum */
    if( PIN->datum_type == PJD_3PARAM
        && PIN->datum_params[0] == 0.0
        && PIN->datum_params[1] == 0.0
        && PIN->datum_params[2] == 0.0
        && PIN->a == 6378137.0
        && ABS(PIN->es - 0.006694379990) < 0.000000000050 )/*WGS84/GRS80*/
    {
        PIN->datum_type = PJD_WGS84;
    }

    /* Set PIN->geoc coordinate system */
    PIN->geoc = (PIN->es != 0.0 && pj_param(ctx, start, "bgeoc").i);

    /* Over-ranging flag */
    PIN->over = pj_param(ctx, start, "bover").i;

    /* Vertical datum geoid grids */
    PIN->has_geoid_vgrids = pj_param(ctx, start, "tgeoidgrids").i;
    if( PIN->has_geoid_vgrids ) /* we need to mark it as used. */
        pj_param(ctx, start, "sgeoidgrids");

    /* Longitude center for wrapping */
    PIN->is_long_wrap_set = pj_param(ctx, start, "tlon_wrap").i;
    if (PIN->is_long_wrap_set) {
        PIN->long_wrap_center = pj_param(ctx, start, "rlon_wrap").f;
        /* Don't accept excessive values otherwise we might perform badly */
        /* when correcting longitudes around it */
        /* The test is written this way to error on long_wrap_center "=" NaN */
        if( !(fabs(PIN->long_wrap_center) < 10 * M_TWOPI) )
            return pj_default_destructor (PIN, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT);
    }

    /* Axis orientation */
    if( (pj_param(ctx, start,"saxis").s) != NULL )
    {
        const char *axis_legal = "ewnsud";
        const char *axis_arg = pj_param(ctx, start,"saxis").s;
        if( strlen(axis_arg) != 3 )
            return pj_default_destructor (PIN, PJD_ERR_AXIS);

        if( strchr( axis_legal, axis_arg[0] ) == NULL
            || strchr( axis_legal, axis_arg[1] ) == NULL
            || strchr( axis_legal, axis_arg[2] ) == NULL)
            return pj_default_destructor (PIN, PJD_ERR_AXIS);

        /* TODO: it would be nice to validate we don't have on axis repeated */
        strcpy( PIN->axis, axis_arg );
    }

    /* Central meridian */
    PIN->lam0=pj_param(ctx, start, "rlon_0").f;

    /* Central latitude */
    PIN->phi0 = pj_param(ctx, start, "rlat_0").f;

    /* False easting and northing */
    PIN->x0 = pj_param(ctx, start, "dx_0").f;
    PIN->y0 = pj_param(ctx, start, "dy_0").f;
    PIN->z0 = pj_param(ctx, start, "dz_0").f;
    PIN->t0 = pj_param(ctx, start, "dt_0").f;

    /* General scaling factor */
    if (pj_param(ctx, start, "tk_0").i)
        PIN->k0 = pj_param(ctx, start, "dk_0").f;
    else if (pj_param(ctx, start, "tk").i)
        PIN->k0 = pj_param(ctx, start, "dk").f;
    else
        PIN->k0 = 1.;
    if (PIN->k0 <= 0.)
        return pj_default_destructor (PIN, PJD_ERR_K_LESS_THAN_ZERO);

    /* Set units */
    s = 0;
    if ((name = pj_param(ctx, start, "sunits").s) != NULL) {
        for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i) ;
        if (!s)
            return pj_default_destructor (PIN, PJD_ERR_UNKNOWN_UNIT_ID);
        s = pj_units[i].to_meter;
    }
    if (s || (s = pj_param(ctx, start, "sto_meter").s)) {
        double factor;
        int ratio = 0;

        /* ratio number? */
        if (strlen (s) > 1 && s[0] == '1' && s[1]=='/') {
            ratio = 1;
            s += 2;
        }

        factor = pj_strtod(s, &s);
        if ((factor <= 0.0) || (1/factor==0))
            return pj_default_destructor (PIN, PJD_ERR_UNIT_FACTOR_LESS_THAN_0);

        PIN->to_meter = ratio?  1 / factor: factor;
        PIN->fr_meter = 1 / PIN->to_meter;

    } else
        PIN->to_meter = PIN->fr_meter = 1.;

    /* Set vertical units */
    s = 0;
    if ((name = pj_param(ctx, start, "svunits").s) != NULL) {
        for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i) ;
        if (!s)
            return pj_default_destructor (PIN, PJD_ERR_UNKNOWN_UNIT_ID);
        s = pj_units[i].to_meter;
    }
    if (s || (s = pj_param(ctx, start, "svto_meter").s)) {
        PIN->vto_meter = pj_strtod(s, &s);
        if (*s == '/') /* ratio number */
            PIN->vto_meter /= pj_strtod(++s, 0);
        if (PIN->vto_meter <= 0.0)
            return pj_default_destructor (PIN, PJD_ERR_UNIT_FACTOR_LESS_THAN_0);
        PIN->vfr_meter = 1. / PIN->vto_meter;
    } else {
        PIN->vto_meter = PIN->to_meter;
        PIN->vfr_meter = PIN->fr_meter;
    }

    /* Prime meridian */
    s = 0;
    if ((name = pj_param(ctx, start, "spm").s) != NULL) {
        const char *value = NULL;
        char *next_str = NULL;

        for (i = 0; pj_prime_meridians[i].id != NULL; ++i )
        {
            if( strcmp(name,pj_prime_meridians[i].id) == 0 )
            {
                value = pj_prime_meridians[i].defn;
                break;
            }
        }

        if( value == NULL
            && (dmstor_ctx(ctx,name,&next_str) != 0.0  || *name == '0')
            && *next_str == '\0' )
            value = name;

        if (!value)
            return pj_default_destructor (PIN, PJD_ERR_UNKNOWN_PRIME_MERIDIAN);
        PIN->from_greenwich = dmstor_ctx(ctx,value,NULL);
    }
    else
        PIN->from_greenwich = 0.0;

    /* Private object for the geodesic functions */
    PIN->geod = pj_calloc (1, sizeof (struct geod_geodesic));
    if (0==PIN->geod)
        return pj_default_destructor (PIN, ENOMEM);
    geod_init(PIN->geod, PIN->a,  (1 - sqrt (1 - PIN->es)));

    /* Projection specific initialization */
    err = proj_errno_reset (PIN);
    PIN = proj(PIN);
    if (proj_errno (PIN)) {
        pj_free(PIN);
        return 0;
    }
    proj_errno_restore (PIN, err);
    return PIN;
}
コード例 #5
0
ファイル: pj_factors.c プロジェクト: ampimis/RtkGps
int pj_factors(LP lp, const PJ *P, double h, struct FACTORS *fac) {
    double cosphi, t, n, r;
    int err;
    PJ_COORD coo = {{0, 0, 0, 0}};
    coo.lp = lp;

    /* Failing the 3 initial checks will most likely be due to */
    /* earlier errors, so we leave errno alone */
    if (0==fac)
        return 1;

    if (0==P)
        return 1;

    if (HUGE_VAL==lp.lam)
        return 1;

    /* But from here, we're ready to make our own mistakes */
    err = proj_errno_reset (P);

    /* Indicate that all factors are numerical approximations */
    fac->code = 0;

    /* Check for latitude or longitude overange */
    if ((fabs (lp.phi)-M_HALFPI) > EPS || fabs (lp.lam) > 10.) {
        proj_errno_set (P, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT);
        return 1;
    }

    /* Set a reasonable step size for the numerical derivatives */
    h = fabs (h);
    if (h < EPS)
        h = DEFAULT_H;

    /* If input latitudes are geocentric, convert to geographic */
    if (P->geoc)
        lp = proj_geocentric_latitude (P, PJ_INV, coo).lp;

    /* If latitude + one step overshoots the pole, move it slightly inside, */
    /* so the numerical derivative still exists */
    if (fabs (lp.phi) > (M_HALFPI - h))
        lp.phi = lp.phi < 0. ? -(M_HALFPI-h) : (M_HALFPI-h);

    /* Longitudinal distance from central meridian */
    lp.lam -= P->lam0;
    if (!P->over)
        lp.lam = adjlon(lp.lam);

    /* Derivatives */
    if (pj_deriv (lp, h, P, &(fac->der))) {
        proj_errno_set (P, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT);
        return 1;
    }

    /* Scale factors */
    cosphi = cos (lp.phi);
    fac->h = hypot (fac->der.x_p, fac->der.y_p);
    fac->k = hypot (fac->der.x_l, fac->der.y_l) / cosphi;

    if (P->es != 0.0) {
        t = sin(lp.phi);
        t = 1. - P->es * t * t;
        n = sqrt(t);
        fac->h *= t * n / P->one_es;
        fac->k *= n;
        r = t * t / P->one_es;
    } else
        r = 1.;

    /* Convergence */
    fac->conv = -atan2 (fac->der.x_p, fac->der.y_p);

    /* Areal scale factor */
    fac->s = (fac->der.y_p * fac->der.x_l - fac->der.x_p * fac->der.y_l) * r / cosphi;

    /* Meridian-parallel angle (theta prime) */
    fac->thetap = aasin(P->ctx,fac->s / (fac->h * fac->k));

    /* Tissot ellipse axis */
    t = fac->k * fac->k + fac->h * fac->h;
    fac->a = sqrt(t + 2. * fac->s);
    t = t - 2. * fac->s;
    t = t > 0? sqrt(t): 0;
    fac->b = 0.5 * (fac->a - t);
    fac->a = 0.5 * (fac->a + t);

    /* Angular distortion */
    fac->omega = 2. * aasin(P->ctx, (fac->a - fac->b) / (fac->a + fac->b) );

    proj_errno_restore (P, err);
    return 0;
}