/src/PROJ/src/projections/hammer.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(hammer, "Hammer & Eckert-Greifendorff") |
10 | | "\n\tMisc Sph, \n\tW= M="; |
11 | | |
12 | 0 | #define EPS 1.0e-10 |
13 | | |
14 | | namespace { // anonymous namespace |
15 | | struct pq_hammer { |
16 | | double w; |
17 | | double m, rm; |
18 | | }; |
19 | | } // anonymous namespace |
20 | | |
21 | 2.52k | static PJ_XY hammer_s_forward(PJ_LP lp, PJ *P) { /* Spheroidal, forward */ |
22 | 2.52k | PJ_XY xy = {0.0, 0.0}; |
23 | 2.52k | struct pq_hammer *Q = static_cast<struct pq_hammer *>(P->opaque); |
24 | 2.52k | double cosphi, d; |
25 | | |
26 | 2.52k | cosphi = cos(lp.phi); |
27 | 2.52k | lp.lam *= Q->w; |
28 | 2.52k | double denom = 1. + cosphi * cos(lp.lam); |
29 | 2.52k | if (denom == 0.0) { |
30 | 0 | proj_errno_set(P, PROJ_ERR_COORD_TRANSFM_OUTSIDE_PROJECTION_DOMAIN); |
31 | 0 | return proj_coord_error().xy; |
32 | 0 | } |
33 | 2.52k | d = sqrt(2. / denom); |
34 | 2.52k | xy.x = Q->m * d * cosphi * sin(lp.lam); |
35 | 2.52k | xy.y = Q->rm * d * sin(lp.phi); |
36 | 2.52k | return xy; |
37 | 2.52k | } |
38 | | |
39 | 0 | static PJ_LP hammer_s_inverse(PJ_XY xy, PJ *P) { /* Spheroidal, inverse */ |
40 | 0 | PJ_LP lp = {0.0, 0.0}; |
41 | 0 | struct pq_hammer *Q = static_cast<struct pq_hammer *>(P->opaque); |
42 | 0 | double z; |
43 | |
|
44 | 0 | z = sqrt(1. - 0.25 * Q->w * Q->w * xy.x * xy.x - 0.25 * xy.y * xy.y); |
45 | 0 | if (fabs(2. * z * z - 1.) < EPS) { |
46 | 0 | lp.lam = HUGE_VAL; |
47 | 0 | lp.phi = HUGE_VAL; |
48 | 0 | proj_errno_set(P, PROJ_ERR_COORD_TRANSFM_OUTSIDE_PROJECTION_DOMAIN); |
49 | 0 | } else { |
50 | 0 | lp.lam = aatan2(Q->w * xy.x * z, 2. * z * z - 1) / Q->w; |
51 | 0 | lp.phi = aasin(P->ctx, z * xy.y); |
52 | 0 | } |
53 | 0 | return lp; |
54 | 0 | } |
55 | | |
56 | 57 | PJ *PJ_PROJECTION(hammer) { |
57 | 57 | struct pq_hammer *Q = |
58 | 57 | static_cast<struct pq_hammer *>(calloc(1, sizeof(struct pq_hammer))); |
59 | 57 | if (nullptr == Q) |
60 | 0 | return pj_default_destructor(P, PROJ_ERR_OTHER /*ENOMEM*/); |
61 | 57 | P->opaque = Q; |
62 | | |
63 | 57 | if (pj_param(P->ctx, P->params, "tW").i) { |
64 | 8 | Q->w = fabs(pj_param(P->ctx, P->params, "dW").f); |
65 | 8 | if (Q->w <= 0.) { |
66 | 3 | proj_log_error(P, _("Invalid value for W: it should be > 0")); |
67 | 3 | return pj_default_destructor(P, |
68 | 3 | PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE); |
69 | 3 | } |
70 | 8 | } else |
71 | 49 | Q->w = .5; |
72 | 54 | if (pj_param(P->ctx, P->params, "tM").i) { |
73 | 8 | Q->m = fabs(pj_param(P->ctx, P->params, "dM").f); |
74 | 8 | if (Q->m <= 0.) { |
75 | 1 | proj_log_error(P, _("Invalid value for M: it should be > 0")); |
76 | 1 | return pj_default_destructor(P, |
77 | 1 | PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE); |
78 | 1 | } |
79 | 8 | } else |
80 | 46 | Q->m = 1.; |
81 | | |
82 | 53 | Q->rm = 1. / Q->m; |
83 | 53 | Q->m /= Q->w; |
84 | | |
85 | 53 | P->es = 0.; |
86 | 53 | P->fwd = hammer_s_forward; |
87 | 53 | P->inv = hammer_s_inverse; |
88 | | |
89 | 53 | return P; |
90 | 54 | } |
91 | | |
92 | | #undef EPS |