/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 | 0 | static PJ_XY merc_e_forward(PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */ |
14 | 0 | PJ_XY xy = {0.0, 0.0}; |
15 | 0 | 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 | 0 | double sphi = sin(lp.phi); |
19 | 0 | double cphi = cos(lp.phi); |
20 | 0 | xy.y = P->k0 * (asinh(sphi / cphi) - P->e * atanh(P->e * sphi)); |
21 | 0 | return xy; |
22 | 0 | } |
23 | | |
24 | 0 | static PJ_XY merc_s_forward(PJ_LP lp, PJ *P) { /* Spheroidal, forward */ |
25 | 0 | PJ_XY xy = {0.0, 0.0}; |
26 | 0 | xy.x = P->k0 * lp.lam; |
27 | 0 | xy.y = P->k0 * asinh(tan(lp.phi)); |
28 | 0 | return xy; |
29 | 0 | } |
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 | 1.59k | PJ *PJ_PROJECTION(merc) { |
46 | 1.59k | double phits = 0.0; |
47 | 1.59k | int is_phits; |
48 | | |
49 | 1.59k | if ((is_phits = pj_param(P->ctx, P->params, "tlat_ts").i)) { |
50 | 685 | phits = fabs(pj_param(P->ctx, P->params, "rlat_ts").f); |
51 | 685 | 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 | 685 | } |
58 | | |
59 | 1.58k | if (P->es != 0.0) { /* ellipsoid */ |
60 | 415 | if (is_phits) |
61 | 90 | P->k0 = pj_msfn(sin(phits), cos(phits), P->es); |
62 | 415 | P->inv = merc_e_inverse; |
63 | 415 | P->fwd = merc_e_forward; |
64 | 415 | } |
65 | | |
66 | 1.17k | else { /* sphere */ |
67 | 1.17k | if (is_phits) |
68 | 594 | P->k0 = cos(phits); |
69 | 1.17k | P->inv = merc_s_inverse; |
70 | 1.17k | P->fwd = merc_s_forward; |
71 | 1.17k | } |
72 | | |
73 | 1.58k | return P; |
74 | 1.59k | } |
75 | | |
76 | 862 | PJ *PJ_PROJECTION(webmerc) { |
77 | | |
78 | | /* Overriding k_0 with fixed parameter */ |
79 | 862 | P->k0 = 1.0; |
80 | | |
81 | 862 | P->inv = merc_s_inverse; |
82 | 862 | P->fwd = merc_s_forward; |
83 | 862 | return P; |
84 | 862 | } |