/src/PROJ/src/projections/fouc_s.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(fouc_s, "Foucaut Sinusoidal") "\n\tPCyl, Sph"; |
10 | | |
11 | 0 | #define MAX_ITER 10 |
12 | 0 | #define LOOP_TOL 1e-7 |
13 | | |
14 | | namespace { // anonymous namespace |
15 | | struct pj_fouc_s_data { |
16 | | double n, n1; |
17 | | }; |
18 | | } // anonymous namespace |
19 | | |
20 | 0 | static PJ_XY fouc_s_s_forward(PJ_LP lp, PJ *P) { /* Spheroidal, forward */ |
21 | 0 | PJ_XY xy = {0.0, 0.0}; |
22 | 0 | struct pj_fouc_s_data *Q = static_cast<struct pj_fouc_s_data *>(P->opaque); |
23 | 0 | double t; |
24 | |
|
25 | 0 | t = cos(lp.phi); |
26 | 0 | xy.x = lp.lam * t / (Q->n + Q->n1 * t); |
27 | 0 | xy.y = Q->n * lp.phi + Q->n1 * sin(lp.phi); |
28 | 0 | return xy; |
29 | 0 | } |
30 | | |
31 | 0 | static PJ_LP fouc_s_s_inverse(PJ_XY xy, PJ *P) { /* Spheroidal, inverse */ |
32 | 0 | PJ_LP lp = {0.0, 0.0}; |
33 | 0 | struct pj_fouc_s_data *Q = static_cast<struct pj_fouc_s_data *>(P->opaque); |
34 | 0 | int i; |
35 | |
|
36 | 0 | if (Q->n != 0.0) { |
37 | 0 | lp.phi = xy.y; |
38 | 0 | for (i = MAX_ITER; i; --i) { |
39 | 0 | const double V = (Q->n * lp.phi + Q->n1 * sin(lp.phi) - xy.y) / |
40 | 0 | (Q->n + Q->n1 * cos(lp.phi)); |
41 | 0 | lp.phi -= V; |
42 | 0 | if (fabs(V) < LOOP_TOL) |
43 | 0 | break; |
44 | 0 | } |
45 | 0 | if (!i) |
46 | 0 | lp.phi = xy.y < 0. ? -M_HALFPI : M_HALFPI; |
47 | 0 | } else |
48 | 0 | lp.phi = aasin(P->ctx, xy.y); |
49 | 0 | const double V = cos(lp.phi); |
50 | 0 | lp.lam = xy.x * (Q->n + Q->n1 * V) / V; |
51 | 0 | return lp; |
52 | 0 | } |
53 | | |
54 | 41 | PJ *PJ_PROJECTION(fouc_s) { |
55 | 41 | struct pj_fouc_s_data *Q = static_cast<struct pj_fouc_s_data *>( |
56 | 41 | calloc(1, sizeof(struct pj_fouc_s_data))); |
57 | 41 | if (nullptr == Q) |
58 | 0 | return pj_default_destructor(P, PROJ_ERR_OTHER /*ENOMEM*/); |
59 | 41 | P->opaque = Q; |
60 | | |
61 | 41 | Q->n = pj_param(P->ctx, P->params, "dn").f; |
62 | 41 | if (Q->n < 0. || Q->n > 1.) { |
63 | 6 | proj_log_error(P, |
64 | 6 | _("Invalid value for n: it should be in [0,1] range.")); |
65 | 6 | return pj_default_destructor(P, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE); |
66 | 6 | } |
67 | | |
68 | 35 | Q->n1 = 1. - Q->n; |
69 | 35 | P->es = 0; |
70 | 35 | P->inv = fouc_s_s_inverse; |
71 | 35 | P->fwd = fouc_s_s_forward; |
72 | 35 | return P; |
73 | 41 | } |
74 | | |
75 | | #undef MAX_ITER |
76 | | #undef LOOP_TOL |