/src/proj/src/projections/airy.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * Project: PROJ.4 |
3 | | * Purpose: Implementation of the airy (Airy) projection. |
4 | | * Author: Gerald Evenden (1995) |
5 | | * Thomas Knudsen (2016) - revise/add regression tests |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 1995, Gerald Evenden |
9 | | * |
10 | | * Permission is hereby granted, free of charge, to any person obtaining a |
11 | | * copy of this software and associated documentation files (the "Software"), |
12 | | * to deal in the Software without restriction, including without limitation |
13 | | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
14 | | * and/or sell copies of the Software, and to permit persons to whom the |
15 | | * Software is furnished to do so, subject to the following conditions: |
16 | | * |
17 | | * The above copyright notice and this permission notice shall be included |
18 | | * in all copies or substantial portions of the Software. |
19 | | * |
20 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
21 | | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
22 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
23 | | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
24 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
25 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
26 | | * DEALINGS IN THE SOFTWARE. |
27 | | *****************************************************************************/ |
28 | | |
29 | | #include "proj.h" |
30 | | #include "proj_internal.h" |
31 | | #include <errno.h> |
32 | | |
33 | | PROJ_HEAD(airy, "Airy") "\n\tMisc Sph, no inv\n\tno_cut lat_b="; |
34 | | |
35 | | namespace { // anonymous namespace |
36 | | enum Mode { N_POLE = 0, S_POLE = 1, EQUIT = 2, OBLIQ = 3 }; |
37 | | } // anonymous namespace |
38 | | |
39 | | namespace { // anonymous namespace |
40 | | struct pj_airy { |
41 | | double p_halfpi; |
42 | | double sinph0; |
43 | | double cosph0; |
44 | | double Cb; |
45 | | enum Mode mode; |
46 | | int no_cut; /* do not cut at hemisphere limit */ |
47 | | }; |
48 | | } // anonymous namespace |
49 | | |
50 | 669 | #define EPS 1.e-10 |
51 | | |
52 | 0 | static PJ_XY airy_s_forward(PJ_LP lp, PJ *P) { /* Spheroidal, forward */ |
53 | 0 | PJ_XY xy = {0.0, 0.0}; |
54 | 0 | struct pj_airy *Q = static_cast<struct pj_airy *>(P->opaque); |
55 | 0 | double sinlam, coslam, cosphi, sinphi, t, s, Krho, cosz; |
56 | |
|
57 | 0 | sinlam = sin(lp.lam); |
58 | 0 | coslam = cos(lp.lam); |
59 | 0 | switch (Q->mode) { |
60 | 0 | case EQUIT: |
61 | 0 | case OBLIQ: |
62 | 0 | sinphi = sin(lp.phi); |
63 | 0 | cosphi = cos(lp.phi); |
64 | 0 | cosz = cosphi * coslam; |
65 | 0 | if (Q->mode == OBLIQ) |
66 | 0 | cosz = Q->sinph0 * sinphi + Q->cosph0 * cosz; |
67 | 0 | if (!Q->no_cut && cosz < -EPS) { |
68 | 0 | proj_errno_set(P, PROJ_ERR_COORD_TRANSFM_OUTSIDE_PROJECTION_DOMAIN); |
69 | 0 | return xy; |
70 | 0 | } |
71 | 0 | s = 1. - cosz; |
72 | 0 | if (fabs(s) > EPS) { |
73 | 0 | t = 0.5 * (1. + cosz); |
74 | 0 | if (t == 0) { |
75 | 0 | proj_errno_set( |
76 | 0 | P, PROJ_ERR_COORD_TRANSFM_OUTSIDE_PROJECTION_DOMAIN); |
77 | 0 | return xy; |
78 | 0 | } |
79 | 0 | Krho = -log(t) / s - Q->Cb / t; |
80 | 0 | } else |
81 | 0 | Krho = 0.5 - Q->Cb; |
82 | 0 | xy.x = Krho * cosphi * sinlam; |
83 | 0 | if (Q->mode == OBLIQ) |
84 | 0 | xy.y = Krho * (Q->cosph0 * sinphi - Q->sinph0 * cosphi * coslam); |
85 | 0 | else |
86 | 0 | xy.y = Krho * sinphi; |
87 | 0 | break; |
88 | 0 | case S_POLE: |
89 | 0 | case N_POLE: |
90 | 0 | lp.phi = fabs(Q->p_halfpi - lp.phi); |
91 | 0 | if (!Q->no_cut && (lp.phi - EPS) > M_HALFPI) { |
92 | 0 | proj_errno_set(P, PROJ_ERR_COORD_TRANSFM_OUTSIDE_PROJECTION_DOMAIN); |
93 | 0 | return xy; |
94 | 0 | } |
95 | 0 | lp.phi *= 0.5; |
96 | 0 | if (lp.phi > EPS) { |
97 | 0 | t = tan(lp.phi); |
98 | 0 | Krho = -2. * (log(cos(lp.phi)) / t + t * Q->Cb); |
99 | 0 | xy.x = Krho * sinlam; |
100 | 0 | xy.y = Krho * coslam; |
101 | 0 | if (Q->mode == N_POLE) |
102 | 0 | xy.y = -xy.y; |
103 | 0 | } else |
104 | 0 | xy.x = xy.y = 0.; |
105 | 0 | } |
106 | 0 | return xy; |
107 | 0 | } |
108 | | |
109 | 227 | PJ *PJ_PROJECTION(airy) { |
110 | 227 | double beta; |
111 | | |
112 | 227 | struct pj_airy *Q = |
113 | 227 | static_cast<struct pj_airy *>(calloc(1, sizeof(struct pj_airy))); |
114 | 227 | if (nullptr == Q) |
115 | 0 | return pj_default_destructor(P, PROJ_ERR_OTHER /*ENOMEM*/); |
116 | | |
117 | 227 | P->opaque = Q; |
118 | | |
119 | 227 | Q->no_cut = pj_param(P->ctx, P->params, "bno_cut").i; |
120 | 227 | beta = 0.5 * (M_HALFPI - pj_param(P->ctx, P->params, "rlat_b").f); |
121 | 227 | if (fabs(beta) < EPS) |
122 | 0 | Q->Cb = -0.5; |
123 | 227 | else { |
124 | 227 | Q->Cb = 1. / tan(beta); |
125 | 227 | Q->Cb *= Q->Cb * log(cos(beta)); |
126 | 227 | } |
127 | | |
128 | 227 | if (fabs(fabs(P->phi0) - M_HALFPI) < EPS) |
129 | 12 | if (P->phi0 < 0.) { |
130 | 6 | Q->p_halfpi = -M_HALFPI; |
131 | 6 | Q->mode = S_POLE; |
132 | 6 | } else { |
133 | 6 | Q->p_halfpi = M_HALFPI; |
134 | 6 | Q->mode = N_POLE; |
135 | 6 | } |
136 | 215 | else { |
137 | 215 | if (fabs(P->phi0) < EPS) |
138 | 197 | Q->mode = EQUIT; |
139 | 18 | else { |
140 | 18 | Q->mode = OBLIQ; |
141 | 18 | Q->sinph0 = sin(P->phi0); |
142 | 18 | Q->cosph0 = cos(P->phi0); |
143 | 18 | } |
144 | 215 | } |
145 | 227 | P->fwd = airy_s_forward; |
146 | 227 | P->es = 0.; |
147 | 227 | return P; |
148 | 227 | } |
149 | | |
150 | | #undef EPS |