/src/proj/src/projections/labrd.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(labrd, "Laborde") "\n\tCyl, Sph\n\tSpecial for Madagascar\n\tlat_0="; |
10 | 0 | #define EPS 1.e-10 |
11 | | |
12 | | namespace { // anonymous namespace |
13 | | struct pj_opaque { |
14 | | double kRg, p0s, A, C, Ca, Cb, Cc, Cd; |
15 | | }; |
16 | | } // anonymous namespace |
17 | | |
18 | 0 | static PJ_XY labrd_e_forward(PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */ |
19 | 0 | PJ_XY xy = {0.0, 0.0}; |
20 | 0 | struct pj_opaque *Q = static_cast<struct pj_opaque *>(P->opaque); |
21 | 0 | double V1, V2, ps, sinps, cosps, sinps2, cosps2; |
22 | 0 | double I1, I2, I3, I4, I5, I6, x2, y2, t; |
23 | |
|
24 | 0 | V1 = Q->A * log(tan(M_FORTPI + .5 * lp.phi)); |
25 | 0 | t = P->e * sin(lp.phi); |
26 | 0 | V2 = .5 * P->e * Q->A * log((1. + t) / (1. - t)); |
27 | 0 | ps = 2. * (atan(exp(V1 - V2 + Q->C)) - M_FORTPI); |
28 | 0 | I1 = ps - Q->p0s; |
29 | 0 | cosps = cos(ps); |
30 | 0 | cosps2 = cosps * cosps; |
31 | 0 | sinps = sin(ps); |
32 | 0 | sinps2 = sinps * sinps; |
33 | 0 | I4 = Q->A * cosps; |
34 | 0 | I2 = .5 * Q->A * I4 * sinps; |
35 | 0 | I3 = I2 * Q->A * Q->A * (5. * cosps2 - sinps2) / 12.; |
36 | 0 | I6 = I4 * Q->A * Q->A; |
37 | 0 | I5 = I6 * (cosps2 - sinps2) / 6.; |
38 | 0 | I6 *= Q->A * Q->A * |
39 | 0 | (5. * cosps2 * cosps2 + sinps2 * (sinps2 - 18. * cosps2)) / 120.; |
40 | 0 | t = lp.lam * lp.lam; |
41 | 0 | xy.x = Q->kRg * lp.lam * (I4 + t * (I5 + t * I6)); |
42 | 0 | xy.y = Q->kRg * (I1 + t * (I2 + t * I3)); |
43 | 0 | x2 = xy.x * xy.x; |
44 | 0 | y2 = xy.y * xy.y; |
45 | 0 | V1 = 3. * xy.x * y2 - xy.x * x2; |
46 | 0 | V2 = xy.y * y2 - 3. * x2 * xy.y; |
47 | 0 | xy.x += Q->Ca * V1 + Q->Cb * V2; |
48 | 0 | xy.y += Q->Ca * V2 - Q->Cb * V1; |
49 | 0 | return xy; |
50 | 0 | } |
51 | | |
52 | 0 | static PJ_LP labrd_e_inverse(PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */ |
53 | 0 | PJ_LP lp = {0.0, 0.0}; |
54 | 0 | struct pj_opaque *Q = static_cast<struct pj_opaque *>(P->opaque); |
55 | | /* t = 0.0 optimization is to avoid a false positive cppcheck warning */ |
56 | | /* (cppcheck git beaf29c15867984aa3c2a15cf15bd7576ccde2b3). Might no */ |
57 | | /* longer be necessary with later versions. */ |
58 | 0 | double x2, y2, V1, V2, V3, V4, t = 0.0, t2, ps, pe, tpe, s; |
59 | 0 | double I7, I8, I9, I10, I11, d, Re; |
60 | 0 | int i; |
61 | |
|
62 | 0 | x2 = xy.x * xy.x; |
63 | 0 | y2 = xy.y * xy.y; |
64 | 0 | V1 = 3. * xy.x * y2 - xy.x * x2; |
65 | 0 | V2 = xy.y * y2 - 3. * x2 * xy.y; |
66 | 0 | V3 = xy.x * (5. * y2 * y2 + x2 * (-10. * y2 + x2)); |
67 | 0 | V4 = xy.y * (5. * x2 * x2 + y2 * (-10. * x2 + y2)); |
68 | 0 | xy.x += -Q->Ca * V1 - Q->Cb * V2 + Q->Cc * V3 + Q->Cd * V4; |
69 | 0 | xy.y += Q->Cb * V1 - Q->Ca * V2 - Q->Cd * V3 + Q->Cc * V4; |
70 | 0 | ps = Q->p0s + xy.y / Q->kRg; |
71 | 0 | pe = ps + P->phi0 - Q->p0s; |
72 | |
|
73 | 0 | for (i = 20; i; --i) { |
74 | 0 | V1 = Q->A * log(tan(M_FORTPI + .5 * pe)); |
75 | 0 | tpe = P->e * sin(pe); |
76 | 0 | V2 = .5 * P->e * Q->A * log((1. + tpe) / (1. - tpe)); |
77 | 0 | t = ps - 2. * (atan(exp(V1 - V2 + Q->C)) - M_FORTPI); |
78 | 0 | pe += t; |
79 | 0 | if (fabs(t) < EPS) |
80 | 0 | break; |
81 | 0 | } |
82 | |
|
83 | 0 | t = P->e * sin(pe); |
84 | 0 | t = 1. - t * t; |
85 | 0 | Re = P->one_es / (t * sqrt(t)); |
86 | 0 | t = tan(ps); |
87 | 0 | t2 = t * t; |
88 | 0 | s = Q->kRg * Q->kRg; |
89 | 0 | d = Re * P->k0 * Q->kRg; |
90 | 0 | I7 = t / (2. * d); |
91 | 0 | I8 = t * (5. + 3. * t2) / (24. * d * s); |
92 | 0 | d = cos(ps) * Q->kRg * Q->A; |
93 | 0 | I9 = 1. / d; |
94 | 0 | d *= s; |
95 | 0 | I10 = (1. + 2. * t2) / (6. * d); |
96 | 0 | I11 = (5. + t2 * (28. + 24. * t2)) / (120. * d * s); |
97 | 0 | x2 = xy.x * xy.x; |
98 | 0 | lp.phi = pe + x2 * (-I7 + I8 * x2); |
99 | 0 | lp.lam = xy.x * (I9 + x2 * (-I10 + x2 * I11)); |
100 | 0 | return lp; |
101 | 0 | } |
102 | | |
103 | 0 | PJ *PJ_PROJECTION(labrd) { |
104 | 0 | double Az, sinp, R, N, t; |
105 | 0 | struct pj_opaque *Q = |
106 | 0 | static_cast<struct pj_opaque *>(calloc(1, sizeof(struct pj_opaque))); |
107 | 0 | if (nullptr == Q) |
108 | 0 | return pj_default_destructor(P, PROJ_ERR_OTHER /*ENOMEM*/); |
109 | 0 | P->opaque = Q; |
110 | |
|
111 | 0 | if (P->phi0 == 0.) { |
112 | 0 | proj_log_error( |
113 | 0 | P, _("Invalid value for lat_0: lat_0 should be different from 0")); |
114 | 0 | return pj_default_destructor(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE); |
115 | 0 | } |
116 | | |
117 | 0 | Az = pj_param(P->ctx, P->params, "razi").f; |
118 | 0 | sinp = sin(P->phi0); |
119 | 0 | t = 1. - P->es * sinp * sinp; |
120 | 0 | N = 1. / sqrt(t); |
121 | 0 | R = P->one_es * N / t; |
122 | 0 | Q->kRg = P->k0 * sqrt(N * R); |
123 | 0 | Q->p0s = atan(sqrt(R / N) * tan(P->phi0)); |
124 | 0 | Q->A = sinp / sin(Q->p0s); |
125 | 0 | t = P->e * sinp; |
126 | 0 | Q->C = .5 * P->e * Q->A * log((1. + t) / (1. - t)) + |
127 | 0 | -Q->A * log(tan(M_FORTPI + .5 * P->phi0)) + |
128 | 0 | log(tan(M_FORTPI + .5 * Q->p0s)); |
129 | 0 | t = Az + Az; |
130 | 0 | Q->Cb = 1. / (12. * Q->kRg * Q->kRg); |
131 | 0 | Q->Ca = (1. - cos(t)) * Q->Cb; |
132 | 0 | Q->Cb *= sin(t); |
133 | 0 | Q->Cc = 3. * (Q->Ca * Q->Ca - Q->Cb * Q->Cb); |
134 | 0 | Q->Cd = 6. * Q->Ca * Q->Cb; |
135 | |
|
136 | 0 | P->inv = labrd_e_inverse; |
137 | 0 | P->fwd = labrd_e_forward; |
138 | |
|
139 | 0 | return P; |
140 | 0 | } |