/src/PROJ/src/projections/loxim.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(loxim, "Loximuthal") "\n\tPCyl Sph"; |
10 | | |
11 | 25.3k | #define EPS 1e-8 |
12 | | |
13 | | namespace { // anonymous namespace |
14 | | struct pj_loxim_data { |
15 | | double phi1; |
16 | | double cosphi1; |
17 | | double tanphi1; |
18 | | }; |
19 | | } // anonymous namespace |
20 | | |
21 | 6.30k | static PJ_XY loxim_s_forward(PJ_LP lp, PJ *P) { /* Spheroidal, forward */ |
22 | 6.30k | PJ_XY xy = {0.0, 0.0}; |
23 | 6.30k | struct pj_loxim_data *Q = static_cast<struct pj_loxim_data *>(P->opaque); |
24 | | |
25 | 6.30k | xy.y = lp.phi - Q->phi1; |
26 | 6.30k | if (fabs(xy.y) < EPS) |
27 | 0 | xy.x = lp.lam * Q->cosphi1; |
28 | 6.30k | else { |
29 | 6.30k | xy.x = M_FORTPI + 0.5 * lp.phi; |
30 | 6.30k | if (fabs(xy.x) < EPS || fabs(fabs(xy.x) - M_HALFPI) < EPS) |
31 | 0 | xy.x = 0.; |
32 | 6.30k | else |
33 | 6.30k | xy.x = lp.lam * xy.y / log(tan(xy.x) / Q->tanphi1); |
34 | 6.30k | } |
35 | 6.30k | return xy; |
36 | 6.30k | } |
37 | | |
38 | 0 | static PJ_LP loxim_s_inverse(PJ_XY xy, PJ *P) { /* Spheroidal, inverse */ |
39 | 0 | PJ_LP lp = {0.0, 0.0}; |
40 | 0 | struct pj_loxim_data *Q = static_cast<struct pj_loxim_data *>(P->opaque); |
41 | |
|
42 | 0 | lp.phi = xy.y + Q->phi1; |
43 | 0 | if (fabs(xy.y) < EPS) { |
44 | 0 | lp.lam = xy.x / Q->cosphi1; |
45 | 0 | } else { |
46 | 0 | lp.lam = M_FORTPI + 0.5 * lp.phi; |
47 | 0 | if (fabs(lp.lam) < EPS || fabs(fabs(lp.lam) - M_HALFPI) < EPS) |
48 | 0 | lp.lam = 0.; |
49 | 0 | else |
50 | 0 | lp.lam = xy.x * log(tan(lp.lam) / Q->tanphi1) / xy.y; |
51 | 0 | } |
52 | 0 | return lp; |
53 | 0 | } |
54 | | |
55 | 117 | PJ *PJ_PROJECTION(loxim) { |
56 | 117 | struct pj_loxim_data *Q = static_cast<struct pj_loxim_data *>( |
57 | 117 | calloc(1, sizeof(struct pj_loxim_data))); |
58 | 117 | if (nullptr == Q) |
59 | 0 | return pj_default_destructor(P, PROJ_ERR_OTHER /*ENOMEM*/); |
60 | 117 | P->opaque = Q; |
61 | | |
62 | 117 | Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; |
63 | 117 | Q->cosphi1 = cos(Q->phi1); |
64 | 117 | if (Q->cosphi1 < EPS) { |
65 | 3 | proj_log_error(P, |
66 | 3 | _("Invalid value for lat_1: |lat_1| should be < 90°")); |
67 | 3 | return pj_default_destructor(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE); |
68 | 3 | } |
69 | | |
70 | 114 | Q->tanphi1 = tan(M_FORTPI + 0.5 * Q->phi1); |
71 | | |
72 | 114 | P->inv = loxim_s_inverse; |
73 | 114 | P->fwd = loxim_s_forward; |
74 | 114 | P->es = 0.; |
75 | | |
76 | 114 | return P; |
77 | 117 | } |
78 | | |
79 | | #undef EPS |