Coverage Report

Created: 2025-06-13 06:29

/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
}