Coverage Report

Created: 2025-06-13 06:18

/src/proj/src/projections/natearth2.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
The Natural Earth II projection was designed by Tom Patterson, US National
3
Park Service, in 2012, using Flex Projector. The polynomial equation was
4
developed by Bojan Savric and Bernhard Jenny, College of Earth, Ocean,
5
and Atmospheric Sciences, Oregon State University.
6
Port to PROJ.4 by Bojan Savric, 4 April 2016
7
*/
8
9
#include <math.h>
10
11
#include "proj.h"
12
#include "proj_internal.h"
13
14
PROJ_HEAD(natearth2, "Natural Earth 2") "\n\tPCyl, Sph";
15
16
0
#define A0 0.84719
17
0
#define A1 -0.13063
18
0
#define A2 -0.04515
19
0
#define A3 0.05494
20
0
#define A4 -0.02326
21
0
#define A5 0.00331
22
0
#define B0 1.01183
23
0
#define B1 -0.02625
24
0
#define B2 0.01926
25
0
#define B3 -0.00396
26
0
#define C0 B0
27
0
#define C1 (9 * B1)
28
0
#define C2 (11 * B2)
29
0
#define C3 (13 * B3)
30
0
#define EPS 1e-11
31
0
#define MAX_Y (0.84719 * 0.535117535153096 * M_PI)
32
/* Not sure at all of the appropriate number for MAX_ITER... */
33
0
#define MAX_ITER 100
34
35
0
static PJ_XY natearth2_s_forward(PJ_LP lp, PJ *P) { /* Spheroidal, forward */
36
0
    PJ_XY xy = {0.0, 0.0};
37
0
    double phi2, phi4, phi6;
38
0
    (void)P;
39
40
0
    phi2 = lp.phi * lp.phi;
41
0
    phi4 = phi2 * phi2;
42
0
    phi6 = phi2 * phi4;
43
44
0
    xy.x = lp.lam * (A0 + A1 * phi2 +
45
0
                     phi6 * phi6 * (A2 + A3 * phi2 + A4 * phi4 + A5 * phi6));
46
0
    xy.y = lp.phi * (B0 + phi4 * phi4 * (B1 + B2 * phi2 + B3 * phi4));
47
0
    return xy;
48
0
}
49
50
0
static PJ_LP natearth2_s_inverse(PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
51
0
    PJ_LP lp = {0.0, 0.0};
52
0
    double yc, y2, y4, y6, f, fder;
53
0
    int i;
54
0
    (void)P;
55
56
    /* make sure y is inside valid range */
57
0
    if (xy.y > MAX_Y) {
58
0
        xy.y = MAX_Y;
59
0
    } else if (xy.y < -MAX_Y) {
60
0
        xy.y = -MAX_Y;
61
0
    }
62
63
    /* latitude */
64
0
    yc = xy.y;
65
0
    for (i = MAX_ITER; i; --i) { /* Newton-Raphson */
66
0
        y2 = yc * yc;
67
0
        y4 = y2 * y2;
68
0
        f = (yc * (B0 + y4 * y4 * (B1 + B2 * y2 + B3 * y4))) - xy.y;
69
0
        fder = C0 + y4 * y4 * (C1 + C2 * y2 + C3 * y4);
70
0
        const double tol = f / fder;
71
0
        yc -= tol;
72
0
        if (fabs(tol) < EPS) {
73
0
            break;
74
0
        }
75
0
    }
76
0
    if (i == 0)
77
0
        proj_context_errno_set(
78
0
            P->ctx, PROJ_ERR_COORD_TRANSFM_OUTSIDE_PROJECTION_DOMAIN);
79
0
    lp.phi = yc;
80
81
    /* longitude */
82
0
    y2 = yc * yc;
83
0
    y4 = y2 * y2;
84
0
    y6 = y2 * y4;
85
86
0
    lp.lam =
87
0
        xy.x / (A0 + A1 * y2 + y6 * y6 * (A2 + A3 * y2 + A4 * y4 + A5 * y6));
88
89
0
    return lp;
90
0
}
91
92
0
PJ *PJ_PROJECTION(natearth2) {
93
0
    P->es = 0;
94
0
    P->inv = natearth2_s_inverse;
95
0
    P->fwd = natearth2_s_forward;
96
97
0
    return P;
98
0
}
99
100
#undef A0
101
#undef A1
102
#undef A2
103
#undef A3
104
#undef A4
105
#undef A5
106
#undef B0
107
#undef B1
108
#undef B2
109
#undef B3
110
#undef C0
111
#undef C1
112
#undef C2
113
#undef C3
114
#undef EPS
115
#undef MAX_Y
116
#undef MAX_ITER