Coverage Report

Created: 2026-07-14 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PROJ/src/ell_set.cpp
Line
Count
Source
1
/* set ellipsoid parameters a and es */
2
3
#include <math.h>
4
#include <stddef.h>
5
#include <string.h>
6
7
#include "proj.h"
8
#include "proj_internal.h"
9
10
/* Prototypes of the pj_ellipsoid helper functions */
11
static int ellps_ellps(PJ *P);
12
static int ellps_size(PJ *P);
13
static int ellps_shape(PJ *P);
14
static int ellps_spherification(PJ *P);
15
16
static paralist *pj_get_param(paralist *list, const char *key);
17
static char *pj_param_value(paralist *list);
18
static const PJ_ELLPS *pj_find_ellps(const char *name);
19
20
/***************************************************************************************/
21
496k
int pj_ellipsoid(PJ *P) {
22
    /****************************************************************************************
23
        This is a replacement for the classic PROJ pj_ell_set function. The main
24
    difference is that pj_ellipsoid augments the PJ object with a copy of the
25
    exact tags used to define its related ellipsoid.
26
27
        This makes it possible to let a new PJ object inherit the geometrical
28
    properties of an existing one.
29
30
        A complete ellipsoid definition comprises a size (primary) and a shape
31
    (secondary) parameter.
32
33
        Size parameters supported are:
34
            R, defining the radius of a spherical planet
35
            a, defining the semimajor axis of an ellipsoidal planet
36
37
        Shape parameters supported are:
38
            rf, the reverse flattening of the ellipsoid
39
            f,  the flattening of the ellipsoid
40
            es, the eccentricity squared
41
            e,  the eccentricity
42
            b,  the semiminor axis
43
44
        The ellps=xxx parameter provides both size and shape for a number of
45
    built in ellipsoid definitions.
46
47
        The ellipsoid definition may be augmented with a spherification flag,
48
    turning the ellipsoid into a sphere with features defined by the ellipsoid.
49
50
        Spherification parameters supported are:
51
            R_A, which gives a sphere with the same surface area as the
52
            ellipsoid R_V, which gives a sphere with the same volume as the
53
    ellipsoid
54
55
            R_a, which gives a sphere with R = (a + b)/2   (arithmetic mean)
56
            R_g, which gives a sphere with R = sqrt(a*b)   (geometric mean)
57
            R_h, which gives a sphere with R = 2*a*b/(a+b) (harmonic mean)
58
59
            R_lat_a=phi, which gives a sphere with R being the arithmetic mean
60
            of of the corresponding ellipsoid at latitude phi.
61
            R_lat_g=phi, which gives
62
            a sphere with R being the geometric mean of of the corresponding
63
    ellipsoid at latitude phi.
64
65
            R_C, which gives a sphere with the radius of the conformal sphere
66
            at phi0.
67
68
        If R is given as size parameter, any shape and spherification parameters
69
        given are ignored.
70
71
        If size and shape are given as ellps=xxx, later shape and size
72
    parameters are are taken into account as modifiers for the built in
73
    ellipsoid definition.
74
75
        While this may seem strange, it is in accordance with historical PROJ
76
        behavior. It can e.g. be used to define coordinates on the ellipsoid
77
        scaled to unit semimajor axis by specifying "+ellps=xxx +a=1"
78
79
    ****************************************************************************************/
80
496k
    int err = proj_errno_reset(P);
81
496k
    const char *empty = {""};
82
83
496k
    free(P->def_size);
84
496k
    P->def_size = nullptr;
85
496k
    free(P->def_shape);
86
496k
    P->def_shape = nullptr;
87
496k
    free(P->def_spherification);
88
496k
    P->def_spherification = nullptr;
89
496k
    free(P->def_ellps);
90
496k
    P->def_ellps = nullptr;
91
92
    /* Specifying R overrules everything */
93
496k
    if (pj_get_param(P->params, "R")) {
94
2.29k
        if (0 != ellps_size(P))
95
681
            return 1;
96
1.61k
        pj_calc_ellipsoid_params(P, P->a, 0);
97
1.61k
        if (proj_errno(P))
98
0
            return 1;
99
1.61k
        return proj_errno_restore(P, err);
100
1.61k
    }
101
102
    /* If an ellps argument is specified, start by using that */
103
494k
    if (0 != ellps_ellps(P))
104
400
        return 1;
105
106
    /* We may overwrite the size */
107
494k
    if (0 != ellps_size(P))
108
5.46k
        return 2;
109
110
    /* We may also overwrite the shape */
111
488k
    if (0 != ellps_shape(P))
112
308
        return 3;
113
114
    /* When we're done with it, we compute all related ellipsoid parameters */
115
488k
    pj_calc_ellipsoid_params(P, P->a, P->es);
116
117
    /* And finally, we may turn it into a sphere */
118
488k
    if (0 != ellps_spherification(P))
119
6
        return 4;
120
121
488k
    proj_log_trace(P, "pj_ellipsoid - final: a=%.3f f=1/%7.3f, errno=%d", P->a,
122
488k
                   P->f != 0 ? 1 / P->f : 0, proj_errno(P));
123
488k
    proj_log_trace(P, "pj_ellipsoid - final: %s %s %s %s",
124
488k
                   P->def_size ? P->def_size : empty,
125
488k
                   P->def_shape ? P->def_shape : empty,
126
488k
                   P->def_spherification ? P->def_spherification : empty,
127
488k
                   P->def_ellps ? P->def_ellps : empty);
128
129
488k
    if (proj_errno(P))
130
194
        return 5;
131
132
    /* success */
133
488k
    return proj_errno_restore(P, err);
134
488k
}
135
136
/***************************************************************************************/
137
494k
static int ellps_ellps(PJ *P) {
138
    /***************************************************************************************/
139
494k
    const PJ_ELLPS *ellps;
140
494k
    paralist *par = nullptr;
141
494k
    char *name;
142
494k
    int err;
143
144
    /* Sail home if ellps=xxx is not specified */
145
494k
    par = pj_get_param(P->params, "ellps");
146
494k
    if (nullptr == par)
147
102k
        return 0;
148
149
    /* Then look up the right size and shape parameters from the builtin list */
150
392k
    if (strlen(par->param) < 7) {
151
39
        proj_log_error(P, _("Invalid value for +ellps"));
152
39
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
153
39
    }
154
392k
    name = par->param + 6;
155
392k
    ellps = pj_find_ellps(name);
156
392k
    if (nullptr == ellps) {
157
361
        proj_log_error(P, _("Unrecognized value for +ellps"));
158
361
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
159
361
    }
160
161
    /* Now, get things ready for ellps_size/ellps_shape, make them do their
162
     * thing
163
     */
164
392k
    err = proj_errno_reset(P);
165
166
392k
    paralist *new_params = pj_mkparam(ellps->major);
167
392k
    if (nullptr == new_params)
168
0
        return proj_errno_set(P, PROJ_ERR_OTHER /*ENOMEM*/);
169
392k
    new_params->next = pj_mkparam(ellps->ell);
170
392k
    if (nullptr == new_params->next) {
171
0
        free(new_params);
172
0
        return proj_errno_set(P, PROJ_ERR_OTHER /*ENOMEM*/);
173
0
    }
174
392k
    paralist *old_params = P->params;
175
392k
    P->params = new_params;
176
177
392k
    {
178
392k
        PJ empty_PJ;
179
392k
        pj_inherit_ellipsoid_def(&empty_PJ, P);
180
392k
    }
181
392k
    const bool errorOnSizeOrShape = (ellps_size(P) || ellps_shape(P));
182
392k
    P->params = old_params;
183
392k
    free(new_params->next);
184
392k
    free(new_params);
185
392k
    if (errorOnSizeOrShape)
186
0
        return proj_errno_set(P, PROJ_ERR_OTHER /*ENOMEM*/);
187
392k
    if (proj_errno(P))
188
0
        return proj_errno(P);
189
190
    /* Finally update P and sail home */
191
392k
    P->def_ellps = pj_strdup(par->param);
192
392k
    par->used = 1;
193
194
392k
    return proj_errno_restore(P, err);
195
392k
}
196
197
/***************************************************************************************/
198
888k
static int ellps_size(PJ *P) {
199
    /***************************************************************************************/
200
888k
    paralist *par = nullptr;
201
888k
    int a_was_set = 0;
202
203
888k
    free(P->def_size);
204
888k
    P->def_size = nullptr;
205
206
    /* A size parameter *must* be given, but may have been given as ellps prior
207
     */
208
888k
    if (P->a != 0)
209
431k
        a_was_set = 1;
210
211
    /* Check which size key is specified */
212
888k
    par = pj_get_param(P->params, "R");
213
888k
    if (nullptr == par)
214
886k
        par = pj_get_param(P->params, "a");
215
888k
    if (nullptr == par) {
216
435k
        if (a_was_set)
217
429k
            return 0;
218
5.37k
        if (P->need_ellps)
219
214
            proj_log_error(P, _("Major axis not given"));
220
5.37k
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_MISSING_ARG);
221
435k
    }
222
223
453k
    P->def_size = pj_strdup(par->param);
224
453k
    par->used = 1;
225
453k
    P->a = pj_atof(pj_param_value(par));
226
453k
    if (P->a <= 0) {
227
754
        proj_log_error(P, _("Invalid value for major axis"));
228
754
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
229
754
    }
230
452k
    if (HUGE_VAL == P->a) {
231
15
        proj_log_error(P, _("Invalid value for major axis"));
232
15
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
233
15
    }
234
235
452k
    if ('R' == par->param[0]) {
236
1.61k
        P->es = P->f = P->e = P->rf = 0;
237
1.61k
        P->b = P->a;
238
1.61k
    }
239
452k
    return 0;
240
452k
}
241
242
/***************************************************************************************/
243
880k
static int ellps_shape(PJ *P) {
244
    /***************************************************************************************/
245
880k
    const char *keys[] = {"rf", "f", "es", "e", "b"};
246
880k
    paralist *par = nullptr;
247
880k
    size_t i, len;
248
249
880k
    par = nullptr;
250
880k
    len = sizeof(keys) / sizeof(char *);
251
252
880k
    free(P->def_shape);
253
880k
    P->def_shape = nullptr;
254
255
    /* Check which shape key is specified */
256
3.33M
    for (i = 0; i < len; i++) {
257
2.90M
        par = pj_get_param(P->params, keys[i]);
258
2.90M
        if (par)
259
454k
            break;
260
2.90M
    }
261
262
    /* Not giving a shape parameter means selecting a sphere, unless shape */
263
    /* has been selected previously via ellps=xxx */
264
880k
    if (nullptr == par && P->es != 0)
265
422k
        return 0;
266
458k
    if (nullptr == par && P->es == 0) {
267
3.89k
        P->es = P->f = 0;
268
3.89k
        P->b = P->a;
269
3.89k
        return 0;
270
3.89k
    }
271
272
454k
    P->def_shape = pj_strdup(par->param);
273
454k
    par->used = 1;
274
454k
    P->es = P->f = P->b = P->e = P->rf = 0;
275
276
454k
    switch (i) {
277
278
    /* reverse flattening, rf */
279
345k
    case 0:
280
345k
        P->rf = pj_atof(pj_param_value(par));
281
345k
        if (HUGE_VAL == P->rf || P->rf <= 0) {
282
12
            proj_log_error(P, _("Invalid value for rf. Should be > 0"));
283
12
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
284
12
        }
285
345k
        P->f = 1 / P->rf;
286
345k
        P->es = 2 * P->f - P->f * P->f;
287
345k
        break;
288
289
    /* flattening, f */
290
1.18k
    case 1:
291
1.18k
        P->f = pj_atof(pj_param_value(par));
292
1.18k
        if (HUGE_VAL == P->f || P->f < 0) {
293
4
            proj_log_error(P, _("Invalid value for f. Should be >= 0"));
294
4
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
295
4
        }
296
297
1.18k
        P->rf = P->f != 0.0 ? 1.0 / P->f : HUGE_VAL;
298
1.18k
        P->es = 2 * P->f - P->f * P->f;
299
1.18k
        break;
300
301
    /* eccentricity squared, es */
302
51.7k
    case 2:
303
51.7k
        P->es = pj_atof(pj_param_value(par));
304
51.7k
        if (HUGE_VAL == P->es || P->es < 0 || P->es >= 1) {
305
11
            proj_log_error(P,
306
11
                           _("Invalid value for es. Should be in [0,1[ range"));
307
11
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
308
11
        }
309
51.7k
        break;
310
311
    /* eccentricity, e */
312
51.7k
    case 3:
313
3.62k
        P->e = pj_atof(pj_param_value(par));
314
3.62k
        if (HUGE_VAL == P->e || P->e < 0 || P->e >= 1) {
315
27
            proj_log_error(P,
316
27
                           _("Invalid value for e. Should be in [0,1[ range"));
317
27
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
318
27
        }
319
3.60k
        P->es = P->e * P->e;
320
3.60k
        break;
321
322
    /* semiminor axis, b */
323
51.9k
    case 4:
324
51.9k
        P->b = pj_atof(pj_param_value(par));
325
51.9k
        if (HUGE_VAL == P->b || P->b <= 0) {
326
157
            proj_log_error(P, _("Invalid value for b. Should be > 0"));
327
157
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
328
157
        }
329
51.7k
        if (P->b == P->a)
330
290
            break;
331
        // coverity[division_by_zero]
332
51.4k
        P->f = (P->a - P->b) / P->a;
333
51.4k
        P->es = 2 * P->f - P->f * P->f;
334
51.4k
        break;
335
0
    default:
336
        // shouldn't happen
337
0
        return PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE;
338
454k
    }
339
340
    // Written that way to catch NaN
341
454k
    if (!(P->es >= 0)) {
342
97
        proj_log_error(P, _("Invalid eccentricity"));
343
97
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
344
97
    }
345
454k
    return 0;
346
454k
}
347
348
/* series coefficients for calculating ellipsoid-equivalent spheres */
349
static const double SIXTH = 1 / 6.;
350
static const double RA4 = 17 / 360.;
351
static const double RA6 = 67 / 3024.;
352
static const double RV4 = 5 / 72.;
353
static const double RV6 = 55 / 1296.;
354
355
/***************************************************************************************/
356
488k
static int ellps_spherification(PJ *P) {
357
    /***************************************************************************************/
358
488k
    const char *keys[] = {"R_A", "R_V",     "R_a",     "R_g",
359
488k
                          "R_h", "R_lat_a", "R_lat_g", "R_C"};
360
488k
    size_t len, i;
361
488k
    paralist *par = nullptr;
362
363
488k
    double t;
364
488k
    char *v, *endp;
365
366
488k
    len = sizeof(keys) / sizeof(char *);
367
368
    /* Check which spherification key is specified */
369
4.38M
    for (i = 0; i < len; i++) {
370
3.89M
        par = pj_get_param(P->params, keys[i]);
371
3.89M
        if (par)
372
1.77k
            break;
373
3.89M
    }
374
375
    /* No spherification specified? Then we're done */
376
488k
    if (i == len)
377
486k
        return 0;
378
379
    /* Store definition */
380
1.77k
    P->def_spherification = pj_strdup(par->param);
381
1.77k
    par->used = 1;
382
383
1.77k
    switch (i) {
384
385
    /* R_A - a sphere with same area as ellipsoid */
386
516
    case 0:
387
516
        P->a *= 1. - P->es * (SIXTH + P->es * (RA4 + P->es * RA6));
388
516
        break;
389
390
    /* R_V - a sphere with same volume as ellipsoid */
391
22
    case 1:
392
22
        P->a *= 1. - P->es * (SIXTH + P->es * (RV4 + P->es * RV6));
393
22
        break;
394
395
    /* R_a - a sphere with R = the arithmetic mean of the ellipsoid */
396
475
    case 2:
397
475
        P->a = (P->a + P->b) / 2;
398
475
        break;
399
400
    /* R_g - a sphere with R = the geometric mean of the ellipsoid */
401
122
    case 3:
402
122
        P->a = sqrt(P->a * P->b);
403
122
        break;
404
405
    /* R_h - a sphere with R = the harmonic mean of the ellipsoid */
406
158
    case 4:
407
158
        if (P->a + P->b == 0)
408
0
            return proj_errno_set(
409
0
                P, PROJ_ERR_COORD_TRANSFM_OUTSIDE_PROJECTION_DOMAIN);
410
158
        P->a = (2 * P->a * P->b) / (P->a + P->b);
411
158
        break;
412
413
    /* R_lat_a - a sphere with R = the arithmetic mean of the ellipsoid at given
414
     * latitude */
415
52
    case 5:
416
    /* R_lat_g - a sphere with R = the geometric  mean of the ellipsoid at given
417
     * latitude */
418
136
    case 6:
419
136
        v = pj_param_value(par);
420
136
        t = proj_dmstor(v, &endp);
421
136
        if (fabs(t) > M_HALFPI) {
422
0
            proj_log_error(
423
0
                P, _("Invalid value for lat_g. |lat_g| should be <= 90°"));
424
0
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
425
0
        }
426
136
        t = sin(t);
427
136
        t = 1 - P->es * t * t;
428
136
        if (t == 0.) {
429
0
            proj_log_error(P, _("Invalid eccentricity"));
430
0
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
431
0
        }
432
136
        if (i == 5) /* arithmetic */
433
52
            P->a *= (1. - P->es + t) / (2 * t * sqrt(t));
434
84
        else /* geometric */
435
84
            P->a *= sqrt(1 - P->es) / t;
436
136
        break;
437
438
    /* R_C - a sphere with R = radius of conformal sphere, taken at a
439
     * latitude that is phi0 (note: at least for mercator. for other
440
     * projection methods, this could be phi1)
441
     * Formula from IOGP Publication 373-7-2 – Geomatics Guidance Note number 7,
442
     * part 2 1.1 Ellipsoid parameters
443
     */
444
341
    case 7:
445
341
        t = sin(P->phi0);
446
341
        t = 1 - P->es * t * t;
447
341
        if (t == 0.) {
448
0
            proj_log_error(P, _("Invalid eccentricity"));
449
0
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
450
0
        }
451
341
        P->a *= sqrt(1 - P->es) / t;
452
341
        break;
453
1.77k
    }
454
455
1.77k
    if (P->a <= 0.) {
456
6
        proj_log_error(P, _("Invalid or missing major axis"));
457
6
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
458
6
    }
459
460
    /* Clean up the ellipsoidal parameters to reflect the sphere */
461
1.76k
    P->es = P->e = P->f = 0;
462
1.76k
    P->rf = HUGE_VAL;
463
1.76k
    P->b = P->a;
464
1.76k
    pj_calc_ellipsoid_params(P, P->a, 0);
465
466
1.76k
    return 0;
467
1.77k
}
468
469
/* locate parameter in list */
470
9.57M
static paralist *pj_get_param(paralist *list, const char *key) {
471
9.57M
    size_t l = strlen(key);
472
108M
    while (list && !(0 == strncmp(list->param, key, l) &&
473
2.07M
                     (0 == list->param[l] || list->param[l] == '=')))
474
99.3M
        list = list->next;
475
9.57M
    return list;
476
9.57M
}
477
478
907k
static char *pj_param_value(paralist *list) {
479
907k
    char *key, *value;
480
907k
    if (nullptr == list)
481
0
        return nullptr;
482
483
907k
    key = list->param;
484
907k
    value = strchr(key, '=');
485
486
    /* a flag (i.e. a key without value) has its own name (key) as value */
487
907k
    return value ? value + 1 : key;
488
907k
}
489
490
392k
static const PJ_ELLPS *pj_find_ellps(const char *name) {
491
392k
    int i;
492
392k
    const char *s;
493
392k
    const PJ_ELLPS *ellps;
494
495
392k
    if (nullptr == name)
496
0
        return nullptr;
497
498
392k
    ellps = proj_list_ellps();
499
500
    /* Search through internal ellipsoid list for name */
501
6.14M
    for (i = 0; (s = ellps[i].id) && strcmp(name, s); ++i)
502
5.74M
        ;
503
392k
    if (nullptr == s)
504
361
        return nullptr;
505
392k
    return ellps + i;
506
392k
}
507
508
/**************************************************************************************/
509
440k
void pj_inherit_ellipsoid_def(const PJ *src, PJ *dst) {
510
    /***************************************************************************************
511
        Brute force copy the ellipsoidal parameters from src to dst.  This code
512
    was written before the actual ellipsoid setup parameters were kept available
513
    in the PJ->def_xxx elements.
514
    ***************************************************************************************/
515
516
    /* The linear parameters */
517
440k
    dst->a = src->a;
518
440k
    dst->b = src->b;
519
440k
    dst->ra = src->ra;
520
440k
    dst->rb = src->rb;
521
522
    /* The eccentricities */
523
440k
    dst->alpha = src->alpha;
524
440k
    dst->e = src->e;
525
440k
    dst->es = src->es;
526
440k
    dst->e2 = src->e2;
527
440k
    dst->e2s = src->e2s;
528
440k
    dst->e3 = src->e3;
529
440k
    dst->e3s = src->e3s;
530
440k
    dst->one_es = src->one_es;
531
440k
    dst->rone_es = src->rone_es;
532
533
    /* The flattenings */
534
440k
    dst->f = src->f;
535
440k
    dst->f2 = src->f2;
536
440k
    dst->n = src->n;
537
440k
    dst->rf = src->rf;
538
440k
    dst->rf2 = src->rf2;
539
440k
    dst->rn = src->rn;
540
541
    /* This one's for GRS80 */
542
440k
    dst->J = src->J;
543
544
    /* es and a before any +proj related adjustment */
545
440k
    dst->es_orig = src->es_orig;
546
440k
    dst->a_orig = src->a_orig;
547
440k
}
548
549
/***************************************************************************************/
550
1.05M
int pj_calc_ellipsoid_params(PJ *P, double a, double es) {
551
    /****************************************************************************************
552
        Calculate a large number of ancillary ellipsoidal parameters, in
553
    addition to the two traditional PROJ defining parameters: Semimajor axis, a,
554
    and the eccentricity squared, es.
555
556
        Most of these parameters are fairly cheap to compute in comparison to
557
    the overall effort involved in initializing a PJ object. They may, however,
558
    take a substantial part of the time taken in computing an individual point
559
    transformation.
560
561
        So by providing them up front, we can amortize the (already modest) cost
562
    over all transformations carried out over the entire lifetime of a PJ
563
    object, rather than incur that cost for every single transformation.
564
565
        Most of the parameter calculations here are based on the "angular
566
    eccentricity", i.e. the angle, measured from the semiminor axis, of a line
567
    going from the north pole to one of the foci of the ellipsoid - or in other
568
    words: The arc sine of the eccentricity.
569
570
        The formulae used are mostly taken from:
571
572
        Richard H. Rapp: Geometric Geodesy, Part I, (178 pp, 1991).
573
        Columbus, Ohio:  Dept. of Geodetic Science
574
        and Surveying, Ohio State University.
575
576
    ****************************************************************************************/
577
578
1.05M
    P->a = a;
579
1.05M
    P->es = es;
580
581
    /* Compute some ancillary ellipsoidal parameters */
582
1.05M
    if (P->e == 0)
583
546k
        P->e = sqrt(P->es); /* eccentricity */
584
1.05M
    P->alpha = asin(P->e);  /* angular eccentricity */
585
586
    /* second eccentricity */
587
1.05M
    P->e2 = tan(P->alpha);
588
1.05M
    P->e2s = P->e2 * P->e2;
589
590
    /* third eccentricity */
591
1.05M
    P->e3 = (0 != P->alpha)
592
1.05M
                ? sin(P->alpha) / sqrt(2 - sin(P->alpha) * sin(P->alpha))
593
1.05M
                : 0;
594
1.05M
    P->e3s = P->e3 * P->e3;
595
596
    /* flattening */
597
1.05M
    if (0 == P->f)
598
149k
        P->f = 1 - cos(P->alpha); /* = 1 - sqrt (1 - PIN->es); */
599
1.05M
    if (!(P->f >= 0.0 && P->f < 1.0)) {
600
57
        proj_log_error(P, _("Invalid eccentricity"));
601
57
        proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
602
57
        return PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE;
603
57
    }
604
1.05M
    P->rf = P->f != 0.0 ? 1.0 / P->f : HUGE_VAL;
605
606
    /* second flattening */
607
1.05M
    P->f2 = (cos(P->alpha) != 0) ? 1 / cos(P->alpha) - 1 : 0;
608
1.05M
    P->rf2 = P->f2 != 0.0 ? 1 / P->f2 : HUGE_VAL;
609
610
    /* third flattening */
611
1.05M
    P->n = pow(tan(P->alpha / 2), 2);
612
1.05M
    P->rn = P->n != 0.0 ? 1 / P->n : HUGE_VAL;
613
614
    /* ...and a few more */
615
1.05M
    if (0 == P->b)
616
475k
        P->b = (1 - P->f) * P->a;
617
1.05M
    P->rb = 1. / P->b;
618
1.05M
    P->ra = 1. / P->a;
619
620
1.05M
    P->one_es = 1. - P->es;
621
1.05M
    if (P->one_es == 0.) {
622
143
        proj_log_error(P, _("Invalid eccentricity"));
623
143
        proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
624
143
        return PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE;
625
143
    }
626
627
1.05M
    P->rone_es = 1. / P->one_es;
628
629
1.05M
    return 0;
630
1.05M
}
631
632
/**************************************************************************************/
633
0
int pj_ell_set(PJ_CONTEXT *ctx, paralist *pl, double *a, double *es) {
634
    /***************************************************************************************
635
        Initialize ellipsoidal parameters by emulating the original ellipsoid
636
    setup function by Gerald Evenden, through a call to pj_ellipsoid
637
    ***************************************************************************************/
638
0
    PJ B;
639
0
    int ret;
640
641
0
    B.ctx = ctx;
642
0
    B.params = pl;
643
644
0
    ret = pj_ellipsoid(&B);
645
646
0
    free(B.def_size);
647
0
    free(B.def_shape);
648
0
    free(B.def_spherification);
649
0
    free(B.def_ellps);
650
651
0
    if (ret)
652
0
        return ret;
653
654
0
    *a = B.a;
655
0
    *es = B.es;
656
0
    return 0;
657
0
}