Coverage Report

Created: 2025-07-11 06:33

/src/PROJ/src/projections/somerc.cpp
Line
Count
Source (jump to first uncovered line)
1
2
3
#include <errno.h>
4
#include <math.h>
5
6
#include "proj.h"
7
#include "proj_internal.h"
8
9
PROJ_HEAD(somerc, "Swiss. Obl. Mercator") "\n\tCyl, Ell\n\tFor CH1903";
10
11
namespace { // anonymous namespace
12
struct pj_somerc {
13
    double K, c, hlf_e, kR, cosp0, sinp0;
14
};
15
} // anonymous namespace
16
17
0
#define EPS 1.e-10
18
0
#define NITER 6
19
20
1.00k
static PJ_XY somerc_e_forward(PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
21
1.00k
    PJ_XY xy = {0.0, 0.0};
22
1.00k
    double phip, lamp, phipp, lampp, sp, cp;
23
1.00k
    struct pj_somerc *Q = static_cast<struct pj_somerc *>(P->opaque);
24
25
1.00k
    sp = P->e * sin(lp.phi);
26
1.00k
    phip = 2. * atan(exp(Q->c * (log(tan(M_FORTPI + 0.5 * lp.phi)) -
27
1.00k
                                 Q->hlf_e * log((1. + sp) / (1. - sp))) +
28
1.00k
                         Q->K)) -
29
1.00k
           M_HALFPI;
30
1.00k
    lamp = Q->c * lp.lam;
31
1.00k
    cp = cos(phip);
32
1.00k
    phipp = aasin(P->ctx, Q->cosp0 * sin(phip) - Q->sinp0 * cp * cos(lamp));
33
1.00k
    lampp = aasin(P->ctx, cp * sin(lamp) / cos(phipp));
34
1.00k
    xy.x = Q->kR * lampp;
35
1.00k
    xy.y = Q->kR * log(tan(M_FORTPI + 0.5 * phipp));
36
1.00k
    return xy;
37
1.00k
}
38
39
0
static PJ_LP somerc_e_inverse(PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
40
0
    PJ_LP lp = {0.0, 0.0};
41
0
    struct pj_somerc *Q = static_cast<struct pj_somerc *>(P->opaque);
42
0
    double phip, lamp, phipp, lampp, cp, esp, con, delp;
43
0
    int i;
44
45
0
    phipp = 2. * (atan(exp(xy.y / Q->kR)) - M_FORTPI);
46
0
    lampp = xy.x / Q->kR;
47
0
    cp = cos(phipp);
48
0
    phip = aasin(P->ctx, Q->cosp0 * sin(phipp) + Q->sinp0 * cp * cos(lampp));
49
0
    lamp = aasin(P->ctx, cp * sin(lampp) / cos(phip));
50
0
    con = (Q->K - log(tan(M_FORTPI + 0.5 * phip))) / Q->c;
51
0
    for (i = NITER; i; --i) {
52
0
        esp = P->e * sin(phip);
53
0
        delp = (con + log(tan(M_FORTPI + 0.5 * phip)) -
54
0
                Q->hlf_e * log((1. + esp) / (1. - esp))) *
55
0
               (1. - esp * esp) * cos(phip) * P->rone_es;
56
0
        phip -= delp;
57
0
        if (fabs(delp) < EPS)
58
0
            break;
59
0
    }
60
0
    if (i) {
61
0
        lp.phi = phip;
62
0
        lp.lam = lamp / Q->c;
63
0
    } else {
64
0
        proj_errno_set(P, PROJ_ERR_COORD_TRANSFM_OUTSIDE_PROJECTION_DOMAIN);
65
0
        return lp;
66
0
    }
67
0
    return (lp);
68
0
}
69
70
97
PJ *PJ_PROJECTION(somerc) {
71
97
    double cp, phip0, sp;
72
97
    struct pj_somerc *Q =
73
97
        static_cast<struct pj_somerc *>(calloc(1, sizeof(struct pj_somerc)));
74
97
    if (nullptr == Q)
75
0
        return pj_default_destructor(P, PROJ_ERR_OTHER /*ENOMEM*/);
76
97
    P->opaque = Q;
77
78
97
    Q->hlf_e = 0.5 * P->e;
79
97
    cp = cos(P->phi0);
80
97
    cp *= cp;
81
97
    Q->c = sqrt(1 + P->es * cp * cp * P->rone_es);
82
97
    sp = sin(P->phi0);
83
97
    Q->sinp0 = sp / Q->c;
84
97
    phip0 = aasin(P->ctx, Q->sinp0);
85
97
    Q->cosp0 = cos(phip0);
86
97
    sp *= P->e;
87
97
    Q->K = log(tan(M_FORTPI + 0.5 * phip0)) -
88
97
           Q->c * (log(tan(M_FORTPI + 0.5 * P->phi0)) -
89
97
                   Q->hlf_e * log((1. + sp) / (1. - sp)));
90
97
    Q->kR = P->k0 * sqrt(P->one_es) / (1. - sp * sp);
91
97
    P->inv = somerc_e_inverse;
92
97
    P->fwd = somerc_e_forward;
93
97
    return P;
94
97
}
95
96
#undef EPS
97
#undef NITER