aboutsummaryrefslogtreecommitdiff
path: root/examples/pj_obs_api_mini_demo.c
blob: 5cd5efe4d30eca5821ec8e7ce81ab0d0cf97a172 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/*******************************************************************************
    Simple example code demonstrating use of the proj.h API for 2D coordinate
    transformations.

    The main transformation setup object is PJ, well known from the two
    former proj APIs (projects.h and proj_api.h)

    The main data objects PJ_COORD and PJ_OBS are new, but encapsulate
    the older LP, XY etc. objects in a framework for storing a 3D
    observation taken at a 4D point in space-time, and including some
    additional metadata (e.g. a serial number or an epsg code).

    PJ_OBS and PJ_COORD use unions to enforce explicit statement of what
    kind of coordinates are expected at a given spot in the code, where
    the old API uses type punning, implicitly assuming that "you know what
    you do". For backward compatibility, the new API is not really type
    safe in the sense that you cannot use a cartesian coordinate where a
    geographic is expected - but it makes it possible to explicitly state
    in the code whet the programmer expected and intended.

    The proj thread contexts have not seen widespread use, so one of the
    intentions with this new API is to make them less visible on the API
    surface.

    A series of experiments have, however, shown that they, for (mostly)
    historical reasons, are very hard to eliminate totally. But we have
    reduced their API surface presence to a constructor and a destructor,
    plus an extra argument to the PJ constructor, pj_create().

    For single threaded programs, the calls to the context constructor
    and destructor may be left out, and the default context selected
    by passing a null-pointer to pj_create.

    Note: This file is in-lined in the documentation. Any changes must be
    reflected in docs/source/development/quickstart.rst

    Thomas Knudsen, 2016-10-30/2017-07-06
*******************************************************************************/
#include <stdio.h>
#include <proj.h>

int main (void) {
    PJ_CONTEXT *C;
    PJ *P;
    PJ *norm;
    PJ_COORD a, b;

    /* or you may set C=PJ_DEFAULT_CTX if you are sure you will     */
    /* use PJ objects from only one thread                          */
    C = proj_context_create();

    P = proj_create_crs_to_crs (C,
                                "EPSG:4326",
                                "+proj=utm +zone=32 +datum=WGS84", /* or EPSG:32632 */
                                NULL);

    if (0 == P) {
        fprintf(stderr, "Failed to create transformation object.\n");
        return 1;
    }

    /* This will ensure that the order of coordinates for the input CRS */
    /* will be longitude, latitude, whereas EPSG:4326 mandates latitude, */
    /* longitude */
    norm = proj_normalize_for_visualization(C, P);
    if (0 == norm) {
        fprintf(stderr, "Failed to normalize transformation object.\n");
        return 1;
    }
    proj_destroy(P);
    P = norm;

    /* a coordinate union representing Copenhagen: 55d N, 12d E    */
    /* Given that we have used proj_normalize_for_visualization(), the order of
    /* coordinates is longitude, latitude, and values are expressed in degrees. */
    a = proj_coord(12, 55, 0, 0);

    /* transform to UTM zone 32, then back to geographical */
    b = proj_trans(P, PJ_FWD, a);
    printf("easting: %.3f, northing: %.3f\n", b.enu.e, b.enu.n);

    b = proj_trans(P, PJ_INV, b);
    printf("longitude: %g, latitude: %g\n", b.lp.lam, b.lp.phi);

    /* Clean up */
    proj_destroy(P);
    proj_context_destroy(C); /* may be omitted in the single threaded case */
    return 0;
}