/src/proj/src/projections/col_urban.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(col_urban, "Colombia Urban") |
10 | | "\n\tMisc\n\th_0="; |
11 | | |
12 | | // Notations and formulas taken from IOGP Publication 373-7-2 - |
13 | | // Geomatics Guidance Note number 7, part 2 - March 2020 |
14 | | |
15 | | namespace { // anonymous namespace |
16 | | |
17 | | struct pj_col_urban { |
18 | | double h0; // height of projection origin, divided by semi-major axis (a) |
19 | | double rho0; // adimensional value, contrary to Guidance note 7.2 |
20 | | double A; |
21 | | double B; // adimensional value, contrary to Guidance note 7.2 |
22 | | double C; |
23 | | double D; // adimensional value, contrary to Guidance note 7.2 |
24 | | }; |
25 | | } // anonymous namespace |
26 | | |
27 | 0 | static PJ_XY col_urban_forward(PJ_LP lp, PJ *P) { |
28 | 0 | PJ_XY xy; |
29 | 0 | struct pj_col_urban *Q = static_cast<struct pj_col_urban *>(P->opaque); |
30 | |
|
31 | 0 | const double cosphi = cos(lp.phi); |
32 | 0 | const double sinphi = sin(lp.phi); |
33 | 0 | const double nu = 1. / sqrt(1 - P->es * sinphi * sinphi); |
34 | 0 | const double lam_nu_cosphi = lp.lam * nu * cosphi; |
35 | 0 | xy.x = Q->A * lam_nu_cosphi; |
36 | 0 | const double sinphi_m = sin(0.5 * (lp.phi + P->phi0)); |
37 | 0 | const double rho_m = |
38 | 0 | (1 - P->es) / pow(1 - P->es * sinphi_m * sinphi_m, 1.5); |
39 | 0 | const double G = 1 + Q->h0 / rho_m; |
40 | 0 | xy.y = G * Q->rho0 * |
41 | 0 | ((lp.phi - P->phi0) + Q->B * lam_nu_cosphi * lam_nu_cosphi); |
42 | |
|
43 | 0 | return xy; |
44 | 0 | } |
45 | | |
46 | 0 | static PJ_LP col_urban_inverse(PJ_XY xy, PJ *P) { |
47 | 0 | PJ_LP lp; |
48 | 0 | struct pj_col_urban *Q = static_cast<struct pj_col_urban *>(P->opaque); |
49 | |
|
50 | 0 | lp.phi = P->phi0 + xy.y / Q->D - Q->B * (xy.x / Q->C) * (xy.x / Q->C); |
51 | 0 | const double sinphi = sin(lp.phi); |
52 | 0 | const double nu = 1. / sqrt(1 - P->es * sinphi * sinphi); |
53 | 0 | lp.lam = xy.x / (Q->C * nu * cos(lp.phi)); |
54 | |
|
55 | 0 | return lp; |
56 | 0 | } |
57 | | |
58 | 11 | PJ *PJ_PROJECTION(col_urban) { |
59 | 11 | struct pj_col_urban *Q = static_cast<struct pj_col_urban *>( |
60 | 11 | calloc(1, sizeof(struct pj_col_urban))); |
61 | 11 | if (nullptr == Q) |
62 | 0 | return pj_default_destructor(P, PROJ_ERR_OTHER /*ENOMEM*/); |
63 | 11 | P->opaque = Q; |
64 | | |
65 | 11 | const double h0_unscaled = pj_param(P->ctx, P->params, "dh_0").f; |
66 | 11 | Q->h0 = h0_unscaled / P->a; |
67 | 11 | const double sinphi0 = sin(P->phi0); |
68 | 11 | const double nu0 = 1. / sqrt(1 - P->es * sinphi0 * sinphi0); |
69 | 11 | Q->A = 1 + Q->h0 / nu0; |
70 | 11 | Q->rho0 = (1 - P->es) / pow(1 - P->es * sinphi0 * sinphi0, 1.5); |
71 | 11 | Q->B = tan(P->phi0) / (2 * Q->rho0 * nu0); |
72 | 11 | Q->C = 1 + Q->h0; |
73 | 11 | Q->D = Q->rho0 * (1 + Q->h0 / (1 - P->es)); |
74 | | |
75 | 11 | P->fwd = col_urban_forward; |
76 | 11 | P->inv = col_urban_inverse; |
77 | | |
78 | 11 | return P; |
79 | 11 | } |