Example #1
0
void
GeoConvHelper::cartesian2geo(Position& cartesian) const {
    cartesian.sub(getOffsetBase());
    if (myProjectionMethod == NONE) {
        return;
    }
    if (myProjectionMethod == SIMPLE) {
        const double y = cartesian.y() / 111136.;
        const double x = cartesian.x() / 111320. / cos(DEG2RAD(y));
        cartesian.set(x, y);
        return;
    }
#ifdef PROJ_API_FILE
#ifdef PROJ_VERSION_MAJOR
    PJ_COORD c;
    c.xy.x = cartesian.x();
    c.xy.y = cartesian.y();
    c = proj_trans(myProjection, PJ_INV, c);
    cartesian.set(proj_todeg(c.lp.lam), proj_todeg(c.lp.phi));
#else
    projUV p;
    p.u = cartesian.x();
    p.v = cartesian.y();
    p = pj_inv(p, myProjection);
    //!!! check pj_errno
    p.u *= RAD_TO_DEG;
    p.v *= RAD_TO_DEG;
    cartesian.set((double) p.u, (double) p.v);
#endif
#endif
}
Example #2
0
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;
}
Example #3
0
static PJ_COORD todeg_coord (PJ *P, PJ_DIRECTION dir, PJ_COORD a) {
    size_t i, n;
    const char *axis = "enut";
    paralist *l = pj_param_exists (P->params, "axis");
    if (l && dir==PJ_FWD)
        axis = l->param + strlen ("axis=");
    n = strlen (axis);
    for (i = 0;  i < n;  i++)
        if (strchr ("news", axis[i]))
            a.v[i] = proj_todeg (a.v[i]);
    return a;
}
Example #4
0
static double strtod_scaled (const char *args, double default_scale) {
/*****************************************************************************
Interpret <args> as a numeric followed by a linear decadal prefix.
Return the properly scaled numeric
******************************************************************************/
    double s;
    const double GRS80_DEG = 111319.4908; /* deg-to-m at equator of GRS80 */
    const char *endp = args;
    s = proj_strtod (args, (char **) &endp);
    if (args==endp)
        return HUGE_VAL;

    endp = column (args, 2);

    if (0==strcmp(endp, "km"))
        s *= 1000;
    else if (0==strcmp(endp, "m"))
        s *= 1;
    else if (0==strcmp(endp, "dm"))
        s /= 10;
    else if (0==strcmp(endp, "cm"))
        s /= 100;
    else if (0==strcmp(endp, "mm"))
        s /= 1000;
    else if (0==strcmp(endp, "um"))
        s /= 1e6;
    else if (0==strcmp(endp, "nm"))
        s /= 1e9;
    else if (0==strcmp(endp, "rad"))
        s = GRS80_DEG * proj_todeg (s);
    else if (0==strcmp(endp, "deg"))
        s = GRS80_DEG * s;
    else
        s *= default_scale;
    return s;
}
Example #5
0
bool
GeoConvHelper::x2cartesian(Position& from, bool includeInBoundary) {
    if (includeInBoundary) {
        myOrigBoundary.add(from);
    }
    // init projection parameter on first use
#ifdef PROJ_API_FILE
    if (myProjection == nullptr) {
        double x = from.x() * myGeoScale;
        switch (myProjectionMethod) {
            case DHDN_UTM: {
                int zone = (int)((x - 500000.) / 1000000.);
                if (zone < 1 || zone > 5) {
                    WRITE_WARNING("Attempt to initialize DHDN_UTM-projection on invalid longitude " + toString(x));
                    return false;
                }
                myProjString = "+proj=tmerc +lat_0=0 +lon_0=" + toString(3 * zone) +
                               " +k=1 +x_0=" + toString(zone * 1000000 + 500000) +
                               " +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs";
#ifdef PROJ_VERSION_MAJOR
                myInverseProjection = proj_create(PJ_DEFAULT_CTX, myProjString.c_str());
                myGeoProjection = proj_create(PJ_DEFAULT_CTX, "+proj=latlong +datum=WGS84");
#else
                myInverseProjection = pj_init_plus(myProjString.c_str());
                myGeoProjection = pj_init_plus("+proj=latlong +datum=WGS84");
#endif
                //!!! check pj_errno
                x = ((x - 500000.) / 1000000.) * 3; // continues with UTM
            }
            FALLTHROUGH;
            case UTM: {
                int zone = (int)(x + 180) / 6 + 1;
                myProjString = "+proj=utm +zone=" + toString(zone) +
                               " +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
#ifdef PROJ_VERSION_MAJOR
                myProjection = proj_create(PJ_DEFAULT_CTX, myProjString.c_str());
#else
                myProjection = pj_init_plus(myProjString.c_str());
#endif
                //!!! check pj_errno
            }
            break;
            case DHDN: {
                int zone = (int)(x / 3);
                if (zone < 1 || zone > 5) {
                    WRITE_WARNING("Attempt to initialize DHDN-projection on invalid longitude " + toString(x));
                    return false;
                }
                myProjString = "+proj=tmerc +lat_0=0 +lon_0=" + toString(3 * zone) +
                               " +k=1 +x_0=" + toString(zone * 1000000 + 500000) +
                               " +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs";
#ifdef PROJ_VERSION_MAJOR
                myProjection = proj_create(PJ_DEFAULT_CTX, myProjString.c_str());
#else
                myProjection = pj_init_plus(myProjString.c_str());
#endif
                //!!! check pj_errno
            }
            break;
            default:
                break;
        }
    }
    if (myInverseProjection != nullptr) {
#ifdef PROJ_VERSION_MAJOR
        PJ_COORD c;
        c.xy.x = from.x();
        c.xy.y = from.y();
        c = proj_trans(myInverseProjection, PJ_INV, c);
        from.set(proj_todeg(c.lp.lam), proj_todeg(c.lp.phi));
#else
        double x = from.x();
        double y = from.y();
        if (pj_transform(myInverseProjection, myGeoProjection, 1, 1, &x, &y, nullptr)) {
            WRITE_WARNING("Could not transform (" + toString(x) + "," + toString(y) + ")");
        }
        from.set(double(x * RAD_TO_DEG), double(y * RAD_TO_DEG));
#endif
    }
#endif
    // perform conversion
    bool ok = x2cartesian_const(from);
    if (ok) {
        if (includeInBoundary) {
            myConvBoundary.add(from);
        }
    }
    return ok;
}