/src/PROJ/src/projections/merc.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | |
3 | | #include <float.h> |
4 | | #include <math.h> |
5 | | |
6 | | #include "proj.h" |
7 | | #include "proj_internal.h" |
8 | | #include <math.h> |
9 | | |
10 | | PROJ_HEAD(merc, "Mercator") "\n\tCyl, Sph&Ell\n\tlat_ts="; |
11 | | PROJ_HEAD(webmerc, "Web Mercator / Pseudo Mercator") "\n\tCyl, Ell\n\t"; |
12 | | |
13 | 7.30k | static PJ_XY merc_e_forward(PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */ |
14 | 7.30k | PJ_XY xy = {0.0, 0.0}; |
15 | 7.30k | xy.x = P->k0 * lp.lam; |
16 | | // Instead of calling tan and sin, call sin and cos which the compiler |
17 | | // optimizes to a single call to sincos. |
18 | 7.30k | double sphi = sin(lp.phi); |
19 | 7.30k | double cphi = cos(lp.phi); |
20 | 7.30k | xy.y = P->k0 * (asinh(sphi / cphi) - P->e * atanh(P->e * sphi)); |
21 | 7.30k | return xy; |
22 | 7.30k | } |
23 | | |
24 | 1.17k | static PJ_XY merc_s_forward(PJ_LP lp, PJ *P) { /* Spheroidal, forward */ |
25 | 1.17k | PJ_XY xy = {0.0, 0.0}; |
26 | 1.17k | xy.x = P->k0 * lp.lam; |
27 | 1.17k | xy.y = P->k0 * asinh(tan(lp.phi)); |
28 | 1.17k | return xy; |
29 | 1.17k | } |
30 | | |
31 | 0 | static PJ_LP merc_e_inverse(PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */ |
32 | 0 | PJ_LP lp = {0.0, 0.0}; |
33 | 0 | lp.phi = atan(pj_sinhpsi2tanphi(P->ctx, sinh(xy.y / P->k0), P->e)); |
34 | 0 | lp.lam = xy.x / P->k0; |
35 | 0 | return lp; |
36 | 0 | } |
37 | | |
38 | 0 | static PJ_LP merc_s_inverse(PJ_XY xy, PJ *P) { /* Spheroidal, inverse */ |
39 | 0 | PJ_LP lp = {0.0, 0.0}; |
40 | 0 | lp.phi = atan(sinh(xy.y / P->k0)); |
41 | 0 | lp.lam = xy.x / P->k0; |
42 | 0 | return lp; |
43 | 0 | } |
44 | | |
45 | 418 | PJ *PJ_PROJECTION(merc) { |
46 | 418 | double phits = 0.0; |
47 | 418 | int is_phits; |
48 | | |
49 | 418 | if ((is_phits = pj_param(P->ctx, P->params, "tlat_ts").i)) { |
50 | 146 | phits = fabs(pj_param(P->ctx, P->params, "rlat_ts").f); |
51 | 146 | if (phits >= M_HALFPI) { |
52 | 1 | proj_log_error( |
53 | 1 | P, _("Invalid value for lat_ts: |lat_ts| should be <= 90°")); |
54 | 1 | return pj_default_destructor(P, |
55 | 1 | PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE); |
56 | 1 | } |
57 | 146 | } |
58 | | |
59 | 417 | if (P->es != 0.0) { /* ellipsoid */ |
60 | 314 | if (is_phits) |
61 | 78 | P->k0 = pj_msfn(sin(phits), cos(phits), P->es); |
62 | 314 | P->inv = merc_e_inverse; |
63 | 314 | P->fwd = merc_e_forward; |
64 | 314 | } |
65 | | |
66 | 103 | else { /* sphere */ |
67 | 103 | if (is_phits) |
68 | 67 | P->k0 = cos(phits); |
69 | 103 | P->inv = merc_s_inverse; |
70 | 103 | P->fwd = merc_s_forward; |
71 | 103 | } |
72 | | |
73 | 417 | return P; |
74 | 418 | } |
75 | | |
76 | 30 | PJ *PJ_PROJECTION(webmerc) { |
77 | | |
78 | | /* Overriding k_0 with fixed parameter */ |
79 | 30 | P->k0 = 1.0; |
80 | | |
81 | 30 | P->inv = merc_s_inverse; |
82 | 30 | P->fwd = merc_s_forward; |
83 | 30 | return P; |
84 | 30 | } |