Coverage Report

Created: 2025-08-03 06:36

/src/PROJ/src/ell_set.cpp
Line
Count
Source (jump to first uncovered line)
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
362k
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
362k
    int err = proj_errno_reset(P);
81
362k
    const char *empty = {""};
82
83
362k
    free(P->def_size);
84
362k
    P->def_size = nullptr;
85
362k
    free(P->def_shape);
86
362k
    P->def_shape = nullptr;
87
362k
    free(P->def_spherification);
88
362k
    P->def_spherification = nullptr;
89
362k
    free(P->def_ellps);
90
362k
    P->def_ellps = nullptr;
91
92
    /* Specifying R overrules everything */
93
362k
    if (pj_get_param(P->params, "R")) {
94
709
        if (0 != ellps_size(P))
95
272
            return 1;
96
437
        pj_calc_ellipsoid_params(P, P->a, 0);
97
437
        if (proj_errno(P))
98
0
            return 1;
99
437
        return proj_errno_restore(P, err);
100
437
    }
101
102
    /* If an ellps argument is specified, start by using that */
103
361k
    if (0 != ellps_ellps(P))
104
212
        return 1;
105
106
    /* We may overwrite the size */
107
361k
    if (0 != ellps_size(P))
108
5.08k
        return 2;
109
110
    /* We may also overwrite the shape */
111
356k
    if (0 != ellps_shape(P))
112
185
        return 3;
113
114
    /* When we're done with it, we compute all related ellipsoid parameters */
115
356k
    pj_calc_ellipsoid_params(P, P->a, P->es);
116
117
    /* And finally, we may turn it into a sphere */
118
356k
    if (0 != ellps_spherification(P))
119
15
        return 4;
120
121
356k
    proj_log_trace(P, "pj_ellipsoid - final: a=%.3f f=1/%7.3f, errno=%d", P->a,
122
356k
                   P->f != 0 ? 1 / P->f : 0, proj_errno(P));
123
356k
    proj_log_trace(P, "pj_ellipsoid - final: %s %s %s %s",
124
356k
                   P->def_size ? P->def_size : empty,
125
356k
                   P->def_shape ? P->def_shape : empty,
126
356k
                   P->def_spherification ? P->def_spherification : empty,
127
356k
                   P->def_ellps ? P->def_ellps : empty);
128
129
356k
    if (proj_errno(P))
130
99
        return 5;
131
132
    /* success */
133
356k
    return proj_errno_restore(P, err);
134
356k
}
135
136
/***************************************************************************************/
137
361k
static int ellps_ellps(PJ *P) {
138
    /***************************************************************************************/
139
361k
    const PJ_ELLPS *ellps;
140
361k
    paralist *par = nullptr;
141
361k
    char *name;
142
361k
    int err;
143
144
    /* Sail home if ellps=xxx is not specified */
145
361k
    par = pj_get_param(P->params, "ellps");
146
361k
    if (nullptr == par)
147
75.9k
        return 0;
148
149
    /* Then look up the right size and shape parameters from the builtin list */
150
285k
    if (strlen(par->param) < 7) {
151
29
        proj_log_error(P, _("Invalid value for +ellps"));
152
29
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
153
29
    }
154
285k
    name = par->param + 6;
155
285k
    ellps = pj_find_ellps(name);
156
285k
    if (nullptr == ellps) {
157
183
        proj_log_error(P, _("Unrecognized value for +ellps"));
158
183
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
159
183
    }
160
161
    /* Now, get things ready for ellps_size/ellps_shape, make them do their
162
     * thing
163
     */
164
285k
    err = proj_errno_reset(P);
165
166
285k
    paralist *new_params = pj_mkparam(ellps->major);
167
285k
    if (nullptr == new_params)
168
0
        return proj_errno_set(P, PROJ_ERR_OTHER /*ENOMEM*/);
169
285k
    new_params->next = pj_mkparam(ellps->ell);
170
285k
    if (nullptr == new_params->next) {
171
0
        free(new_params);
172
0
        return proj_errno_set(P, PROJ_ERR_OTHER /*ENOMEM*/);
173
0
    }
174
285k
    paralist *old_params = P->params;
175
285k
    P->params = new_params;
176
177
285k
    {
178
285k
        PJ empty_PJ;
179
285k
        pj_inherit_ellipsoid_def(&empty_PJ, P);
180
285k
    }
181
285k
    const bool errorOnSizeOrShape = (ellps_size(P) || ellps_shape(P));
182
285k
    P->params = old_params;
183
285k
    free(new_params->next);
184
285k
    free(new_params);
185
285k
    if (errorOnSizeOrShape)
186
0
        return proj_errno_set(P, PROJ_ERR_OTHER /*ENOMEM*/);
187
285k
    if (proj_errno(P))
188
0
        return proj_errno(P);
189
190
    /* Finally update P and sail home */
191
285k
    P->def_ellps = pj_strdup(par->param);
192
285k
    par->used = 1;
193
194
285k
    return proj_errno_restore(P, err);
195
285k
}
196
197
/***************************************************************************************/
198
648k
static int ellps_size(PJ *P) {
199
    /***************************************************************************************/
200
648k
    paralist *par = nullptr;
201
648k
    int a_was_set = 0;
202
203
648k
    free(P->def_size);
204
648k
    P->def_size = nullptr;
205
206
    /* A size parameter *must* be given, but may have been given as ellps prior
207
     */
208
648k
    if (P->a != 0)
209
316k
        a_was_set = 1;
210
211
    /* Check which size key is specified */
212
648k
    par = pj_get_param(P->params, "R");
213
648k
    if (nullptr == par)
214
647k
        par = pj_get_param(P->params, "a");
215
648k
    if (nullptr == par) {
216
320k
        if (a_was_set)
217
315k
            return 0;
218
4.85k
        if (P->need_ellps)
219
180
            proj_log_error(P, _("Major axis not given"));
220
4.85k
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_MISSING_ARG);
221
320k
    }
222
223
327k
    P->def_size = pj_strdup(par->param);
224
327k
    par->used = 1;
225
327k
    P->a = pj_atof(pj_param_value(par));
226
327k
    if (P->a <= 0) {
227
464
        proj_log_error(P, _("Invalid value for major axis"));
228
464
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
229
464
    }
230
326k
    if (HUGE_VAL == P->a) {
231
35
        proj_log_error(P, _("Invalid value for major axis"));
232
35
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
233
35
    }
234
235
326k
    if ('R' == par->param[0]) {
236
437
        P->es = P->f = P->e = P->rf = 0;
237
437
        P->b = P->a;
238
437
    }
239
326k
    return 0;
240
326k
}
241
242
/***************************************************************************************/
243
642k
static int ellps_shape(PJ *P) {
244
    /***************************************************************************************/
245
642k
    const char *keys[] = {"rf", "f", "es", "e", "b"};
246
642k
    paralist *par = nullptr;
247
642k
    size_t i, len;
248
249
642k
    par = nullptr;
250
642k
    len = sizeof(keys) / sizeof(char *);
251
252
642k
    free(P->def_shape);
253
642k
    P->def_shape = nullptr;
254
255
    /* Check which shape key is specified */
256
2.45M
    for (i = 0; i < len; i++) {
257
2.14M
        par = pj_get_param(P->params, keys[i]);
258
2.14M
        if (par)
259
330k
            break;
260
2.14M
    }
261
262
    /* Not giving a shape parameter means selecting a sphere, unless shape */
263
    /* has been selected previously via ellps=xxx */
264
642k
    if (nullptr == par && P->es != 0)
265
308k
        return 0;
266
333k
    if (nullptr == par && P->es == 0) {
267
2.98k
        P->es = P->f = 0;
268
2.98k
        P->b = P->a;
269
2.98k
        return 0;
270
2.98k
    }
271
272
330k
    P->def_shape = pj_strdup(par->param);
273
330k
    par->used = 1;
274
330k
    P->es = P->f = P->b = P->e = P->rf = 0;
275
276
330k
    switch (i) {
277
278
    /* reverse flattening, rf */
279
245k
    case 0:
280
245k
        P->rf = pj_atof(pj_param_value(par));
281
245k
        if (HUGE_VAL == P->rf || P->rf <= 0) {
282
15
            proj_log_error(P, _("Invalid value for rf. Should be > 0"));
283
15
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
284
15
        }
285
245k
        P->f = 1 / P->rf;
286
245k
        P->es = 2 * P->f - P->f * P->f;
287
245k
        break;
288
289
    /* flattening, f */
290
1.60k
    case 1:
291
1.60k
        P->f = pj_atof(pj_param_value(par));
292
1.60k
        if (HUGE_VAL == P->f || P->f < 0) {
293
11
            proj_log_error(P, _("Invalid value for f. Should be >= 0"));
294
11
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
295
11
        }
296
297
1.59k
        P->rf = P->f != 0.0 ? 1.0 / P->f : HUGE_VAL;
298
1.59k
        P->es = 2 * P->f - P->f * P->f;
299
1.59k
        break;
300
301
    /* eccentricity squared, es */
302
36.5k
    case 2:
303
36.5k
        P->es = pj_atof(pj_param_value(par));
304
36.5k
        if (HUGE_VAL == P->es || P->es < 0 || P->es >= 1) {
305
13
            proj_log_error(P,
306
13
                           _("Invalid value for es. Should be in [0,1[ range"));
307
13
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
308
13
        }
309
36.4k
        break;
310
311
    /* eccentricity, e */
312
36.4k
    case 3:
313
3.82k
        P->e = pj_atof(pj_param_value(par));
314
3.82k
        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.80k
        P->es = P->e * P->e;
320
3.80k
        break;
321
322
    /* semiminor axis, b */
323
42.9k
    case 4:
324
42.9k
        P->b = pj_atof(pj_param_value(par));
325
42.9k
        if (HUGE_VAL == P->b || P->b <= 0) {
326
78
            proj_log_error(P, _("Invalid value for b. Should be > 0"));
327
78
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
328
78
        }
329
42.8k
        if (P->b == P->a)
330
324
            break;
331
        // coverity[division_by_zero]
332
42.5k
        P->f = (P->a - P->b) / P->a;
333
42.5k
        P->es = 2 * P->f - P->f * P->f;
334
42.5k
        break;
335
0
    default:
336
        // shouldn't happen
337
0
        return PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE;
338
330k
    }
339
340
    // Written that way to catch NaN
341
330k
    if (!(P->es >= 0)) {
342
41
        proj_log_error(P, _("Invalid eccentricity"));
343
41
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
344
41
    }
345
330k
    return 0;
346
330k
}
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
356k
static int ellps_spherification(PJ *P) {
357
    /***************************************************************************************/
358
356k
    const char *keys[] = {"R_A", "R_V",     "R_a",     "R_g",
359
356k
                          "R_h", "R_lat_a", "R_lat_g", "R_C"};
360
356k
    size_t len, i;
361
356k
    paralist *par = nullptr;
362
363
356k
    double t;
364
356k
    char *v, *endp;
365
366
356k
    len = sizeof(keys) / sizeof(char *);
367
368
    /* Check which spherification key is specified */
369
3.20M
    for (i = 0; i < len; i++) {
370
2.84M
        par = pj_get_param(P->params, keys[i]);
371
2.84M
        if (par)
372
1.37k
            break;
373
2.84M
    }
374
375
    /* No spherification specified? Then we're done */
376
356k
    if (i == len)
377
354k
        return 0;
378
379
    /* Store definition */
380
1.37k
    P->def_spherification = pj_strdup(par->param);
381
1.37k
    par->used = 1;
382
383
1.37k
    switch (i) {
384
385
    /* R_A - a sphere with same area as ellipsoid */
386
318
    case 0:
387
318
        P->a *= 1. - P->es * (SIXTH + P->es * (RA4 + P->es * RA6));
388
318
        break;
389
390
    /* R_V - a sphere with same volume as ellipsoid */
391
39
    case 1:
392
39
        P->a *= 1. - P->es * (SIXTH + P->es * (RV4 + P->es * RV6));
393
39
        break;
394
395
    /* R_a - a sphere with R = the arithmetic mean of the ellipsoid */
396
91
    case 2:
397
91
        P->a = (P->a + P->b) / 2;
398
91
        break;
399
400
    /* R_g - a sphere with R = the geometric mean of the ellipsoid */
401
158
    case 3:
402
158
        P->a = sqrt(P->a * P->b);
403
158
        break;
404
405
    /* R_h - a sphere with R = the harmonic mean of the ellipsoid */
406
421
    case 4:
407
421
        if (P->a + P->b == 0)
408
0
            return proj_errno_set(
409
0
                P, PROJ_ERR_COORD_TRANSFM_OUTSIDE_PROJECTION_DOMAIN);
410
421
        P->a = (2 * P->a * P->b) / (P->a + P->b);
411
421
        break;
412
413
    /* R_lat_a - a sphere with R = the arithmetic mean of the ellipsoid at given
414
     * latitude */
415
60
    case 5:
416
    /* R_lat_g - a sphere with R = the geometric  mean of the ellipsoid at given
417
     * latitude */
418
135
    case 6:
419
135
        v = pj_param_value(par);
420
135
        t = proj_dmstor(v, &endp);
421
135
        if (fabs(t) > M_HALFPI) {
422
4
            proj_log_error(
423
4
                P, _("Invalid value for lat_g. |lat_g| should be <= 90°"));
424
4
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
425
4
        }
426
131
        t = sin(t);
427
131
        t = 1 - P->es * t * t;
428
131
        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
131
        if (i == 5) /* arithmetic */
433
60
            P->a *= (1. - P->es + t) / (2 * t * sqrt(t));
434
71
        else /* geometric */
435
71
            P->a *= sqrt(1 - P->es) / t;
436
131
        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
213
    case 7:
445
213
        t = sin(P->phi0);
446
213
        t = 1 - P->es * t * t;
447
213
        if (t == 0.) {
448
1
            proj_log_error(P, _("Invalid eccentricity"));
449
1
            return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
450
1
        }
451
212
        P->a *= sqrt(1 - P->es) / t;
452
212
        break;
453
1.37k
    }
454
455
1.37k
    if (P->a <= 0.) {
456
10
        proj_log_error(P, _("Invalid or missing major axis"));
457
10
        return proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
458
10
    }
459
460
    /* Clean up the ellipsoidal parameters to reflect the sphere */
461
1.36k
    P->es = P->e = P->f = 0;
462
1.36k
    P->rf = HUGE_VAL;
463
1.36k
    P->b = P->a;
464
1.36k
    pj_calc_ellipsoid_params(P, P->a, 0);
465
466
1.36k
    return 0;
467
1.37k
}
468
469
/* locate parameter in list */
470
7.01M
static paralist *pj_get_param(paralist *list, const char *key) {
471
7.01M
    size_t l = strlen(key);
472
73.4M
    while (list && !(0 == strncmp(list->param, key, l) &&
473
67.3M
                     (0 == list->param[l] || list->param[l] == '=')))
474
66.4M
        list = list->next;
475
7.01M
    return list;
476
7.01M
}
477
478
658k
static char *pj_param_value(paralist *list) {
479
658k
    char *key, *value;
480
658k
    if (nullptr == list)
481
0
        return nullptr;
482
483
658k
    key = list->param;
484
658k
    value = strchr(key, '=');
485
486
    /* a flag (i.e. a key without value) has its own name (key) as value */
487
658k
    return value ? value + 1 : key;
488
658k
}
489
490
285k
static const PJ_ELLPS *pj_find_ellps(const char *name) {
491
285k
    int i;
492
285k
    const char *s;
493
285k
    const PJ_ELLPS *ellps;
494
495
285k
    if (nullptr == name)
496
0
        return nullptr;
497
498
285k
    ellps = proj_list_ellps();
499
500
    /* Search through internal ellipsoid list for name */
501
4.52M
    for (i = 0; (s = ellps[i].id) && strcmp(name, s); ++i)
502
4.23M
        ;
503
285k
    if (nullptr == s)
504
183
        return nullptr;
505
285k
    return ellps + i;
506
285k
}
507
508
/**************************************************************************************/
509
319k
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
319k
    dst->a = src->a;
518
319k
    dst->b = src->b;
519
319k
    dst->ra = src->ra;
520
319k
    dst->rb = src->rb;
521
522
    /* The eccentricities */
523
319k
    dst->alpha = src->alpha;
524
319k
    dst->e = src->e;
525
319k
    dst->es = src->es;
526
319k
    dst->e2 = src->e2;
527
319k
    dst->e2s = src->e2s;
528
319k
    dst->e3 = src->e3;
529
319k
    dst->e3s = src->e3s;
530
319k
    dst->one_es = src->one_es;
531
319k
    dst->rone_es = src->rone_es;
532
533
    /* The flattenings */
534
319k
    dst->f = src->f;
535
319k
    dst->f2 = src->f2;
536
319k
    dst->n = src->n;
537
319k
    dst->rf = src->rf;
538
319k
    dst->rf2 = src->rf2;
539
319k
    dst->rn = src->rn;
540
541
    /* This one's for GRS80 */
542
319k
    dst->J = src->J;
543
544
    /* es and a before any +proj related adjustment */
545
319k
    dst->es_orig = src->es_orig;
546
319k
    dst->a_orig = src->a_orig;
547
319k
}
548
549
/***************************************************************************************/
550
774k
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
774k
    P->a = a;
579
774k
    P->es = es;
580
581
    /* Compute some ancillary ellipsoidal parameters */
582
774k
    if (P->e == 0)
583
401k
        P->e = sqrt(P->es); /* eccentricity */
584
774k
    P->alpha = asin(P->e);  /* angular eccentricity */
585
586
    /* second eccentricity */
587
774k
    P->e2 = tan(P->alpha);
588
774k
    P->e2s = P->e2 * P->e2;
589
590
    /* third eccentricity */
591
774k
    P->e3 = (0 != P->alpha)
592
774k
                ? sin(P->alpha) / sqrt(2 - sin(P->alpha) * sin(P->alpha))
593
774k
                : 0;
594
774k
    P->e3s = P->e3 * P->e3;
595
596
    /* flattening */
597
774k
    if (0 == P->f)
598
114k
        P->f = 1 - cos(P->alpha); /* = 1 - sqrt (1 - PIN->es); */
599
774k
    if (!(P->f >= 0.0 && P->f < 1.0)) {
600
29
        proj_log_error(P, _("Invalid eccentricity"));
601
29
        proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
602
29
        return PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE;
603
29
    }
604
774k
    P->rf = P->f != 0.0 ? 1.0 / P->f : HUGE_VAL;
605
606
    /* second flattening */
607
774k
    P->f2 = (cos(P->alpha) != 0) ? 1 / cos(P->alpha) - 1 : 0;
608
774k
    P->rf2 = P->f2 != 0.0 ? 1 / P->f2 : HUGE_VAL;
609
610
    /* third flattening */
611
774k
    P->n = pow(tan(P->alpha / 2), 2);
612
774k
    P->rn = P->n != 0.0 ? 1 / P->n : HUGE_VAL;
613
614
    /* ...and a few more */
615
774k
    if (0 == P->b)
616
342k
        P->b = (1 - P->f) * P->a;
617
774k
    P->rb = 1. / P->b;
618
774k
    P->ra = 1. / P->a;
619
620
774k
    P->one_es = 1. - P->es;
621
774k
    if (P->one_es == 0.) {
622
81
        proj_log_error(P, _("Invalid eccentricity"));
623
81
        proj_errno_set(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE);
624
81
        return PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE;
625
81
    }
626
627
774k
    P->rone_es = 1. / P->one_es;
628
629
774k
    return 0;
630
774k
}
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
}