Coverage Report

Created: 2026-10-13 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PROJ/src/projections/bertin1953.cpp
Line
Count
Source
1
/*
2
  Created by Jacques Bertin in 1953, this projection was the go-to choice
3
  of the French cartographic school when they wished to represent phenomena
4
  on a global scale.
5
6
  Formula designed by Philippe Rivière, 2017.
7
  https://visionscarto.net/bertin-projection-1953
8
9
  Port to PROJ by Philippe Rivière, 21 September 2018
10
*/
11
12
#include <errno.h>
13
#include <math.h>
14
15
#include "proj.h"
16
#include "proj_internal.h"
17
18
PROJ_HEAD(bertin1953, "Bertin 1953")
19
"\n\tMisc Sph no inv.";
20
21
namespace { // anonymous namespace
22
struct pj_bertin1953 {
23
    double cos_delta_phi, sin_delta_phi, cos_delta_gamma, sin_delta_gamma,
24
        deltaLambda;
25
};
26
} // anonymous namespace
27
28
0
static PJ_XY bertin1953_s_forward(PJ_LP lp, PJ *P) {
29
0
    PJ_XY xy = {0.0, 0.0};
30
0
    struct pj_bertin1953 *Q = static_cast<struct pj_bertin1953 *>(P->opaque);
31
32
0
    double fu = 1.4, k = 12., w = 1.68, d;
33
34
    /* Rotate */
35
0
    double cosphi, x, y, z, z0;
36
0
    lp.lam += PJ_TORAD(-16.5);
37
0
    cosphi = cos(lp.phi);
38
0
    x = cos(lp.lam) * cosphi;
39
0
    y = sin(lp.lam) * cosphi;
40
0
    z = sin(lp.phi);
41
0
    z0 = z * Q->cos_delta_phi + x * Q->sin_delta_phi;
42
0
    lp.lam = atan2(y * Q->cos_delta_gamma - z0 * Q->sin_delta_gamma,
43
0
                   x * Q->cos_delta_phi - z * Q->sin_delta_phi);
44
0
    z0 = z0 * Q->cos_delta_gamma + y * Q->sin_delta_gamma;
45
0
    lp.phi = asin(z0);
46
47
0
    lp.lam = adjlon(lp.lam);
48
49
    /* Adjust pre-projection */
50
0
    if (lp.lam + lp.phi < -fu) {
51
0
        d = (lp.lam - lp.phi + 1.6) * (lp.lam + lp.phi + fu) / 8.;
52
0
        lp.lam += d;
53
0
        lp.phi -= 0.8 * d * sin(lp.phi + M_PI / 2.);
54
0
    }
55
56
    /* Project with Hammer (1.68,2) */
57
0
    cosphi = cos(lp.phi);
58
0
    d = sqrt(2. / (1. + cosphi * cos(lp.lam / 2.)));
59
0
    xy.x = w * d * cosphi * sin(lp.lam / 2.);
60
0
    xy.y = d * sin(lp.phi);
61
62
    /* Adjust post-projection */
63
0
    d = (1. - cos(lp.lam * lp.phi)) / k;
64
0
    if (xy.y < 0.) {
65
0
        xy.x *= 1. + d;
66
0
    }
67
0
    if (xy.y > 0.) {
68
0
        xy.y *= 1. + d / 1.5 * xy.x * xy.x;
69
0
    }
70
71
0
    return xy;
72
0
}
73
74
0
PJ *PJ_PROJECTION(bertin1953) {
75
0
    struct pj_bertin1953 *Q = static_cast<struct pj_bertin1953 *>(
76
0
        calloc(1, sizeof(struct pj_bertin1953)));
77
0
    if (nullptr == Q)
78
0
        return pj_default_destructor(P, PROJ_ERR_OTHER /*ENOMEM*/);
79
0
    P->opaque = Q;
80
81
0
    P->lam0 = 0;
82
0
    P->phi0 = PJ_TORAD(-42.);
83
84
0
    Q->cos_delta_phi = cos(P->phi0);
85
0
    Q->sin_delta_phi = sin(P->phi0);
86
0
    Q->cos_delta_gamma = 1.;
87
0
    Q->sin_delta_gamma = 0.;
88
89
0
    P->es = 0.;
90
0
    P->fwd = bertin1953_s_forward;
91
92
0
    return P;
93
0
}