/src/proj/src/proj_mdist.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | ** libproj -- library of cartographic projections |
3 | | ** |
4 | | ** Copyright (c) 2003, 2006 Gerald I. Evenden |
5 | | */ |
6 | | /* |
7 | | ** Permission is hereby granted, free of charge, to any person obtaining |
8 | | ** a copy of this software and associated documentation files (the |
9 | | ** "Software"), to deal in the Software without restriction, including |
10 | | ** without limitation the rights to use, copy, modify, merge, publish, |
11 | | ** distribute, sublicense, and/or sell copies of the Software, and to |
12 | | ** permit persons to whom the Software is furnished to do so, subject to |
13 | | ** the following conditions: |
14 | | ** |
15 | | ** The above copyright notice and this permission notice shall be |
16 | | ** included in all copies or substantial portions of the Software. |
17 | | ** |
18 | | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
19 | | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
20 | | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
21 | | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
22 | | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
23 | | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
24 | | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
25 | | */ |
26 | | /* Computes distance from equator along the meridian to latitude phi |
27 | | ** and inverse on unit ellipsoid. |
28 | | ** Precision commensurate with double precision. |
29 | | */ |
30 | | |
31 | | #include <math.h> |
32 | | #include <stdlib.h> |
33 | | |
34 | | #include "proj.h" |
35 | | #include "proj_internal.h" |
36 | | |
37 | 3.13k | #define MAX_ITER 20 |
38 | 0 | #define TOL 1e-14 |
39 | | |
40 | | namespace { // anonymous namespace |
41 | | struct MDIST { |
42 | | int nb; |
43 | | double es; |
44 | | double E; |
45 | | double b[1]; |
46 | | }; |
47 | | } // anonymous namespace |
48 | 307 | void *proj_mdist_ini(double es) { |
49 | 307 | double numf, numfi, twon1, denf, denfi, ens, T, twon; |
50 | 307 | double den, El = 1., Es = 1.; |
51 | 307 | double E[MAX_ITER] = {1.}; |
52 | 307 | struct MDIST *b; |
53 | 307 | int i, j; |
54 | | |
55 | | /* generate E(e^2) and its terms E[] */ |
56 | 307 | ens = es; |
57 | 307 | numf = twon1 = denfi = 1.; |
58 | 307 | denf = 1.; |
59 | 307 | twon = 4.; |
60 | 3.13k | for (i = 1; i < MAX_ITER; ++i) { |
61 | 3.01k | numf *= (twon1 * twon1); |
62 | 3.01k | den = twon * denf * denf * twon1; |
63 | 3.01k | T = numf / den; |
64 | 3.01k | Es -= (E[i] = T * ens); |
65 | 3.01k | ens *= es; |
66 | 3.01k | twon *= 4.; |
67 | 3.01k | denf *= ++denfi; |
68 | 3.01k | twon1 += 2.; |
69 | 3.01k | if (Es == El) /* jump out if no change */ |
70 | 189 | break; |
71 | 2.82k | El = Es; |
72 | 2.82k | } |
73 | 307 | if ((b = (struct MDIST *)malloc(sizeof(struct MDIST) + |
74 | 307 | (i * sizeof(double)))) == nullptr) |
75 | 0 | return (nullptr); |
76 | 307 | b->nb = i - 1; |
77 | 307 | b->es = es; |
78 | 307 | b->E = Es; |
79 | | /* generate b_n coefficients--note: collapse with prefix ratios */ |
80 | 307 | b->b[0] = Es = 1. - Es; |
81 | 307 | numf = denf = 1.; |
82 | 307 | numfi = 2.; |
83 | 307 | denfi = 3.; |
84 | 3.13k | for (j = 1; j < i; ++j) { |
85 | 2.82k | Es -= E[j]; |
86 | 2.82k | numf *= numfi; |
87 | 2.82k | denf *= denfi; |
88 | 2.82k | b->b[j] = Es * numf / denf; |
89 | 2.82k | numfi += 2.; |
90 | 2.82k | denfi += 2.; |
91 | 2.82k | } |
92 | 307 | return (b); |
93 | 307 | } |
94 | 307 | double proj_mdist(double phi, double sphi, double cphi, const void *data) { |
95 | 307 | const struct MDIST *b = (const struct MDIST *)data; |
96 | 307 | double sc, sum, sphi2, D; |
97 | 307 | int i; |
98 | | |
99 | 307 | sc = sphi * cphi; |
100 | 307 | sphi2 = sphi * sphi; |
101 | 307 | D = phi * b->E - b->es * sc / sqrt(1. - b->es * sphi2); |
102 | 307 | sum = b->b[i = b->nb]; |
103 | 3.13k | while (i) |
104 | 2.82k | sum = b->b[--i] + sphi2 * sum; |
105 | 307 | return (D + sc * sum); |
106 | 307 | } |
107 | 0 | double proj_inv_mdist(PJ_CONTEXT *ctx, double dist, const void *data) { |
108 | 0 | const struct MDIST *b = (const struct MDIST *)data; |
109 | 0 | double s, t, phi, k; |
110 | 0 | int i; |
111 | |
|
112 | 0 | k = 1. / (1. - b->es); |
113 | 0 | i = MAX_ITER; |
114 | 0 | phi = dist; |
115 | 0 | while (i--) { |
116 | 0 | s = sin(phi); |
117 | 0 | t = 1. - b->es * s * s; |
118 | 0 | phi -= t = (proj_mdist(phi, s, cos(phi), b) - dist) * (t * sqrt(t)) * k; |
119 | 0 | if (fabs(t) < TOL) /* that is no change */ |
120 | 0 | return phi; |
121 | 0 | } |
122 | | /* convergence failed */ |
123 | 0 | proj_context_errno_set(ctx, |
124 | 0 | PROJ_ERR_COORD_TRANSFM_OUTSIDE_PROJECTION_DOMAIN); |
125 | 0 | return phi; |
126 | 0 | } |