Пример #1
0
static PJ_LP e_inverse (PJ_XY xy, PJ *P) {          /* Ellipsoidal, inverse */
    PJ_LP lp = {0.0,0.0};
    struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
    PJ_XY t;
    double yc = 0.0;
    int i = 0;
    const int N_MAX_ITER = 1000; /* Arbitrarily chosen number... */

    lp.phi = Q->phi_2;
    lp.lam = xy.x / cos(lp.phi);
    do {
        t = loc_for(lp, P, &yc);
        const double denom = t.y - yc;
        if( denom != 0 || fabs(t.y - xy.y) > TOL )
        {
            if( denom == 0 ) {
                proj_errno_set(P, PJD_ERR_NON_CONVERGENT);
                return proj_coord_error().lp;
            }
            lp.phi = ((lp.phi - Q->phi_1) * (xy.y - yc) / denom) + Q->phi_1;
        }
        if( t.x != 0 || fabs(t.x - xy.x) > TOL )
            lp.lam = lp.lam * xy.x / t.x;
        i ++;
    } while (i < N_MAX_ITER &&
             (fabs(t.x - xy.x) > TOL || fabs(t.y - xy.y) > TOL));

    if( i == N_MAX_ITER )
    {
        proj_errno_set(P, PJD_ERR_NON_CONVERGENT);
        return proj_coord_error().lp;
    }

    return lp;
}
Пример #2
0
PJ_COORD pj_fwd4d (PJ_COORD coo, PJ *P) {
    int last_errno = proj_errno_reset(P);

    if (!P->skip_fwd_prepare)
        coo = fwd_prepare (P, coo);
    if (HUGE_VAL==coo.v[0])
        return proj_coord_error ();

    /* Call the highest dimensional converter available */
    if (P->fwd4d)
        coo = P->fwd4d (coo, P);
    else if (P->fwd3d)
        coo.xyz  =  P->fwd3d (coo.lpz, P);
    else if (P->fwd)
        coo.xy  =  P->fwd (coo.lp, P);
    else {
        proj_errno_set (P, EINVAL);
        return proj_coord_error ();
    }
    if (HUGE_VAL==coo.v[0])
        return proj_coord_error ();

    if (!P->skip_fwd_finalize)
        coo = fwd_finalize (P, coo);

    return error_or_coord(P, coo, last_errno);
}
Пример #3
0
PJ_XYZ pj_fwd3d(PJ_LPZ lpz, PJ *P) {
    int last_errno;
    PJ_COORD coo = {{0,0,0,0}};
    coo.lpz = lpz;

    last_errno = proj_errno_reset(P);

    if (!P->skip_fwd_prepare)
        coo = fwd_prepare (P, coo);
    if (HUGE_VAL==coo.v[0])
        return proj_coord_error ().xyz;

    /* Do the transformation, using the lowest dimensional transformer feasible */
    if (P->fwd3d)
        coo.xyz = P->fwd3d(coo.lpz, P);
    else if (P->fwd4d)
        coo = P->fwd4d (coo, P);
    else if (P->fwd)
        coo.xy = P->fwd (coo.lp, P);
    else {
        proj_errno_set (P, EINVAL);
        return proj_coord_error ().xyz;
    }
    if (HUGE_VAL==coo.v[0])
        return proj_coord_error ().xyz;

    if (!P->skip_fwd_finalize)
        coo = fwd_finalize (P, coo);

    return error_or_coord(P, coo, last_errno).xyz;
}
Пример #4
0
PJ_COORD proj_trans (PJ *P, PJ_DIRECTION direction, PJ_COORD coord) {
/***************************************************************************************
Apply the transformation P to the coordinate coord, preferring the 4D interfaces if
available.

See also pj_approx_2D_trans and pj_approx_3D_trans in pj_internal.c, which work
similarly, but prefers the 2D resp. 3D interfaces if available.
***************************************************************************************/
    if (0==P)
        return coord;
    if (P->inverted)
        direction = -direction;

    switch (direction) {
        case PJ_FWD:
            return pj_fwd4d (coord, P);
        case PJ_INV:
            return  pj_inv4d (coord, P);
        case PJ_IDENT:
            return coord;
        default:
            break;
    }

    proj_errno_set (P, EINVAL);
    return proj_coord_error ();
}
Пример #5
0
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;
}
Пример #6
0
static PJ_COORD reverse_4d(PJ_COORD coo, PJ *P) {
    struct pj_opaque *Q = (struct pj_opaque *) P->opaque;
    unsigned int i;
    PJ_COORD out;

    out = proj_coord_error();

    for (i=0; i<4; i++)
        out.v[Q->axis[i]] = coo.v[i] * Q->sign[i];

    return out;
}
Пример #7
0
static LP reverse_2d(XY xy, PJ *P) {
    struct pj_opaque *Q = (struct pj_opaque *) P->opaque;
    unsigned int i;
    PJ_COORD out, in;

    in.xy = xy;
    out = proj_coord_error();

    for (i=0; i<2; i++)
        out.v[Q->axis[i]] = in.v[i] * Q->sign[i];

    return out.lp;
}
Пример #8
0
static XY forward_2d(LP lp, PJ *P) {
    struct pj_opaque *Q = (struct pj_opaque *) P->opaque;
    unsigned int i;
    PJ_COORD out, in;

    in.lp = lp;
    out = proj_coord_error();

    for (i=0; i<2; i++)
        out.v[i] = in.v[Q->axis[i]] * Q->sign[i];

    return out.xy;
}
Пример #9
0
static LPZ reverse_3d(XYZ xyz, PJ *P) {
    struct pj_opaque *Q = (struct pj_opaque *) P->opaque;
    unsigned int i;
    PJ_COORD in, out;

    out = proj_coord_error();
    in.xyz = xyz;

    for (i=0; i<3; i++)
        out.v[Q->axis[i]] = in.v[i] * Q->sign[i];

    return out.lpz;
}
Пример #10
0
static XYZ forward_3d(LPZ lpz, PJ *P) {
    struct pj_opaque *Q = (struct pj_opaque *) P->opaque;
    unsigned int i;
    PJ_COORD out, in;

    in.lpz = lpz;
    out = proj_coord_error();

    for (i=0; i<3; i++)
        out.v[i] = in.v[Q->axis[i]] * Q->sign[i];

    return out.xyz;
}
Пример #11
0
static PJ_LPZ reverse_3d(PJ_XYZ in, PJ *P) {
    struct pj_opaque *Q = (struct pj_opaque *) P->opaque;
    PJ_COORD out;
    double dt = 0.0;
    out.xyz = in;

    if (Q->t_obs != HUGE_VAL) {
        dt = Q->t_epoch - Q->t_obs;
    } else {
        out = proj_coord_error(); /* in the 3D case +t_obs must be specified */
        proj_log_debug(P, "deformation: +t_obs must be specified");
        return out.lpz;
    }

    out.xyz = reverse_shift(P, in, dt);

    return out.lpz;
}
Пример #12
0
static PJ_LP vandg_s_inverse (PJ_XY xy, PJ *P) {           /* Spheroidal, inverse */
    PJ_LP lp = {0.0,0.0};
    double t, c0, c1, c2, c3, al, r2, r, m, d, ay, x2, y2;

    x2 = xy.x * xy.x;
    if ((ay = fabs(xy.y)) < TOL) {
        lp.phi = 0.;
        t = x2 * x2 + TPISQ * (x2 + HPISQ);
        lp.lam = fabs(xy.x) <= TOL ? 0. :
           .5 * (x2 - PISQ + sqrt(t)) / xy.x;
        return (lp);
    }
    y2 = xy.y * xy.y;
    r = x2 + y2;    r2 = r * r;
    c1 = - M_PI * ay * (r + PISQ);
    c3 = r2 + M_TWOPI * (ay * r + M_PI * (y2 + M_PI * (ay + M_HALFPI)));
    c2 = c1 + PISQ * (r - 3. *  y2);
    c0 = M_PI * ay;
    c2 /= c3;
    al = c1 / c3 - THIRD * c2 * c2;
    m = 2. * sqrt(-THIRD * al);
    d = C2_27 * c2 * c2 * c2 + (c0 * c0 - THIRD * c2 * c1) / c3;
    const double al_mul_m = al * m;
    if( al_mul_m == 0 ) {
        proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
        return proj_coord_error().lp;
    }
    d = 3. * d /al_mul_m;
    t = fabs(d);
    if ((t - TOL) <= 1.) {
        d = t > 1. ? (d > 0. ? 0. : M_PI) : acos(d);
        lp.phi = M_PI * (m * cos(d * THIRD + PI4_3) - THIRD * c2);
        if (xy.y < 0.) lp.phi = -lp.phi;
        t = r2 + TPISQ * (x2 - y2 + HPISQ);
        lp.lam = fabs(xy.x) <= TOL ? 0. :
           .5 * (r - PISQ + (t <= 0. ? 0. : sqrt(t))) / xy.x;
    } else {
        proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
        return lp;
    }

    return lp;
}
Пример #13
0
static PJ_XY sterea_e_forward (PJ_LP lp, PJ *P) {          /* Ellipsoidal, forward */
    PJ_XY xy = {0.0,0.0};
    struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
    double cosc, sinc, cosl, k;

    lp = pj_gauss(P->ctx, lp, Q->en);
    sinc = sin(lp.phi);
    cosc = cos(lp.phi);
    cosl = cos(lp.lam);
    const double denom = 1. + Q->sinc0 * sinc + Q->cosc0 * cosc * cosl;
    if( denom == 0.0 ) {
        proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
        return proj_coord_error().xy;
    }
    k = P->k0 * Q->R2 / denom;
    xy.x = k * cosc * sin(lp.lam);
    xy.y = k * (Q->cosc0 * sinc - Q->sinc0 * cosc * cosl);
    return xy;
}
Пример #14
0
static PJ_COORD parse_coord (const char *args) {
/*****************************************************************************
Attempt to interpret args as a PJ_COORD.
******************************************************************************/
    int i;
    const char *endp;
    const char *dmsendp;
    const char *prev = args;
    PJ_COORD a = proj_coord (0,0,0,0);

    T.dimensions_given = 0;
    for (i = 0;   i < 4;   i++) {
        /* proj_strtod doesn't read values like 123d45'678W so we need a bit */
        /* of help from proj_dmstor. proj_strtod effectively ignores what    */
        /* comes after "d", so we use that fact that when dms is larger than */
        /* d the value was stated in "dms" form.                             */
        /* This could be avoided if proj_dmstor used the same proj_strtod()  */
        /* as gie, but that is not the case (yet). When we remove projects.h */
        /* from the public API we can change that.                           */
        double d = proj_strtod(prev,  (char **) &endp);
        double dms = PJ_TODEG(proj_dmstor (prev, (char **) &dmsendp));
       /* TODO: When projects.h is removed, call proj_dmstor() in all cases */
        if (d != dms && fabs(d) < fabs(dms) && fabs(dms) < fabs(d) + 1) {
            d = dms;
            endp = dmsendp;
        }
        /* A number like -81d00'00.000 will be parsed correctly by both */
        /* proj_strtod and proj_dmstor but only the latter will return  */
        /* the correct end-pointer.                                     */
        if (d == dms && endp != dmsendp)
            endp = dmsendp;

        /* Break out if there were no more numerals */
        if (prev==endp)
            return i > 1? a: proj_coord_error ();

        a.v[i] = d;
        prev = endp;
        T.dimensions_given++;
    }

    return a;
}
Пример #15
0
static PJ_XYZ forward_3d(PJ_LPZ lpz, PJ *P) {
    struct pj_opaque *Q = (struct pj_opaque *) P->opaque;
    PJ_COORD out, in;
    PJ_XYZ shift;
    double dt = 0.0;
    in.lpz = lpz;
    out = in;

    if (Q->t_obs != HUGE_VAL) {
        dt = Q->t_epoch - Q->t_obs;
    } else {
        out = proj_coord_error(); /* in the 3D case +t_obs must be specified */
        proj_log_debug(P, "deformation: +t_obs must be specified");
        return out.xyz;
    }

    shift = get_grid_shift(P, in.xyz);

    out.xyz.x += dt * shift.x;
    out.xyz.y += dt * shift.y;
    out.xyz.z += dt * shift.z;

    return out.xyz;
}
Пример #16
0
static PJ_COORD fwd_prepare (PJ *P, PJ_COORD coo) {
    if (HUGE_VAL==coo.v[0] || HUGE_VAL==coo.v[1] || HUGE_VAL==coo.v[2])
        return proj_coord_error ();

    /* The helmert datum shift will choke unless it gets a sensible 4D coordinate */
    if (HUGE_VAL==coo.v[2] && P->helmert) coo.v[2] = 0.0;
    if (HUGE_VAL==coo.v[3] && P->helmert) coo.v[3] = 0.0;

    /* Check validity of angular input coordinates */
    if (INPUT_UNITS==PJ_IO_UNITS_RADIANS) {
        double t;

        /* check for latitude or longitude over-range */
        t = (coo.lp.phi < 0  ?  -coo.lp.phi  :  coo.lp.phi) - M_HALFPI;
        if (t > PJ_EPS_LAT  ||  coo.lp.lam > 10  ||  coo.lp.lam < -10) {
            proj_errno_set (P, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT);
            return proj_coord_error ();
        }

        /* Clamp latitude to -90..90 degree range */
        if (coo.lp.phi > M_HALFPI)
            coo.lp.phi = M_HALFPI;
        if (coo.lp.phi < -M_HALFPI)
            coo.lp.phi = -M_HALFPI;

        /* If input latitude is geocentrical, convert to geographical */
        if (P->geoc)
            coo = pj_geocentric_latitude (P, PJ_INV, coo);

        /* Ensure longitude is in the -pi:pi range */
        if (0==P->over)
            coo.lp.lam = adjlon(coo.lp.lam);

        if (P->hgridshift)
            coo = proj_trans (P->hgridshift, PJ_INV, coo);
        else if (P->helmert || (P->cart_wgs84 != nullptr && P->cart != nullptr)) {
            coo = proj_trans (P->cart_wgs84, PJ_FWD, coo); /* Go cartesian in WGS84 frame */
            if( P->helmert )
                coo = proj_trans (P->helmert,    PJ_INV, coo); /* Step into local frame */
            coo = proj_trans (P->cart,       PJ_INV, coo); /* Go back to angular using local ellps */
        }
        if (coo.lp.lam==HUGE_VAL)
            return coo;
        if (P->vgridshift)
            coo = proj_trans (P->vgridshift, PJ_FWD, coo); /* Go orthometric from geometric */

        /* Distance from central meridian, taking system zero meridian into account */
        coo.lp.lam = (coo.lp.lam - P->from_greenwich) - P->lam0;

        /* Ensure longitude is in the -pi:pi range */
        if (0==P->over)
            coo.lp.lam = adjlon(coo.lp.lam);

        return coo;
    }


    /* We do not support gridshifts on cartesian input */
    if (INPUT_UNITS==PJ_IO_UNITS_CARTESIAN && P->helmert)
            return proj_trans (P->helmert, PJ_INV, coo);
    return coo;
}