Exemple #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);
}
Exemple #2
0
static PJ_COORD fwd_finalize (PJ *P, PJ_COORD coo) {

    switch (OUTPUT_UNITS) {

    /* Handle false eastings/northings and non-metric linear units */
    case PJ_IO_UNITS_CARTESIAN:

        if (P->is_geocent) {
            coo = proj_trans (P->cart, PJ_FWD, coo);
        }
        coo.xyz.x *= P->fr_meter;
        coo.xyz.y *= P->fr_meter;
        coo.xyz.z *= P->fr_meter;

        break;

    /* Classic proj.4 functions return plane coordinates in units of the semimajor axis */
    case PJ_IO_UNITS_CLASSIC:
        coo.xy.x *= P->a;
        coo.xy.y *= P->a;

    /* Falls through */ /* (<-- GCC warning silencer) */
    /* to continue processing in common with PJ_IO_UNITS_PROJECTED */
    case PJ_IO_UNITS_PROJECTED:
        coo.xyz.x = P->fr_meter  * (coo.xyz.x + P->x0);
        coo.xyz.y = P->fr_meter  * (coo.xyz.y + P->y0);
        coo.xyz.z = P->vfr_meter * (coo.xyz.z + P->z0);
        break;

    case PJ_IO_UNITS_WHATEVER:
        break;

    case PJ_IO_UNITS_RADIANS:
        coo.lpz.z = P->vfr_meter * (coo.lpz.z + P->z0);

        if( P->is_long_wrap_set ) {
            if( coo.lpz.lam != HUGE_VAL ) {
                coo.lpz.lam  = P->long_wrap_center +
                               adjlon(coo.lpz.lam - P->long_wrap_center);
            }
        }

        break;
    }

    if (P->axisswap)
        coo = proj_trans (P->axisswap, PJ_FWD, coo);

    return coo;
}
Exemple #3
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
}
Exemple #4
0
bool
GeoConvHelper::x2cartesian_const(Position& from) const {
    double x2 = from.x() * myGeoScale;
    double y2 = from.y() * myGeoScale;
    double x = x2 * myCos - y2 * mySin;
    double y = x2 * mySin + y2 * myCos;
    if (myProjectionMethod == NONE) {
        from.add(myOffset);
    } else if (myUseInverseProjection) {
        cartesian2geo(from);
    } else {
        if (x > 180.1 || x < -180.1) {
            WRITE_WARNING("Invalid longitude " + toString(x));
            return false;
        }
        if (y > 90.1 || y < -90.1) {
            WRITE_WARNING("Invalid latitude " + toString(y));
            return false;
        }
#ifdef PROJ_API_FILE
        if (myProjection != nullptr) {
#ifdef PROJ_VERSION_MAJOR
            PJ_COORD c;
            c.lp.lam = proj_torad(x);
            c.lp.phi = proj_torad(y);
            c = proj_trans(myProjection, PJ_FWD, c);
            //!!! check pj_errno
            x = c.xy.x;
            y = c.xy.y;
#else
            projUV p;
            p.u = x * DEG_TO_RAD;
            p.v = y * DEG_TO_RAD;
            p = pj_fwd(p, myProjection);
            //!!! check pj_errno
            x = p.u;
            y = p.v;
#endif
        }
#endif
        if (myProjectionMethod == SIMPLE) {
            x *= 111320. * cos(DEG2RAD(y));
            y *= 111136.;
            //!!! recheck whether the axes are mirrored
        }
    }
    if (x > std::numeric_limits<double>::max() ||
            y > std::numeric_limits<double>::max()) {
        return false;
    }
    from.set(x, y);
    from.add(myOffset);
    if (myFlatten) {
        from.setz(0);
    }
    return true;
}
Exemple #5
0
/* dimensionality as the number of dimensions given in accept */
static PJ_COORD expect_trans_n_dim (PJ_COORD ci) {
    if (4==T.dimensions_given_at_last_accept)
        return proj_trans (T.P, T.dir, ci);

    if (3==T.dimensions_given_at_last_accept)
        return pj_approx_3D_trans (T.P, T.dir, ci);

    return pj_approx_2D_trans (T.P, T.dir, ci);
}
Exemple #6
0
static PJ_COORD pipeline_reverse_4d (PJ_COORD point, PJ *P) {
    int i, first_step, last_step;

    first_step = static_cast<struct pj_opaque*>(P->opaque)->steps;
    last_step  =  0;

    for (i = first_step;  i != last_step;  i--)
        point = proj_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_INV, point);

    return point;
}
Exemple #7
0
static PJ_COORD pipeline_forward_4d (PJ_COORD point, PJ *P) {
    int i, first_step, last_step;

    first_step = 1;
    last_step  = static_cast<struct pj_opaque*>(P->opaque)->steps + 1;

    for (i = first_step;  i != last_step;  i++)
        point = proj_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_FWD, point);

    return point;
}
Exemple #8
0
int proj_trans_array (PJ *P, PJ_DIRECTION direction, size_t n, PJ_COORD *coord) {
/******************************************************************************
    Batch transform an array of PJ_COORD.

    Returns 0 if all coordinates are transformed without error, otherwise
    returns error number.
******************************************************************************/
    size_t i;

    for (i = 0;  i < n;  i++) {
        coord[i] = proj_trans (P, direction, coord[i]);
        if (proj_errno(P))
            return proj_errno (P);
    }

   return 0;
}
Exemple #9
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;
}
bool reproject(T & geom, projection const& source, projection const& dest)
{
    proj_transform proj_trans(source, dest);
    detail::geom_reproj_visitor visit(proj_trans);
    return visit(geom);
}
T reproject_copy(T const& geom, projection const& source, projection const& dest, unsigned int & n_err)
{
    proj_transform proj_trans(source, dest);
    return reproject_copy(geom, proj_trans, n_err);
}
Exemple #12
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;
}
Exemple #13
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;
}