diff options
| -rw-r--r-- | src/PJ_aea.c | 8 | ||||
| -rw-r--r-- | src/PJ_calcofi.c | 154 | ||||
| -rw-r--r-- | src/PJ_cass.c | 196 | ||||
| -rw-r--r-- | src/PJ_cc.c | 87 | ||||
| -rw-r--r-- | src/PJ_wag2.c | 81 | ||||
| -rw-r--r-- | src/PJ_wag3.c | 103 | ||||
| -rw-r--r-- | src/PJ_wag7.c | 66 | ||||
| -rw-r--r-- | src/PJ_wink1.c | 104 | ||||
| -rw-r--r-- | src/PJ_wink2.c | 89 | ||||
| -rw-r--r-- | src/projects.h | 2 |
10 files changed, 712 insertions, 178 deletions
diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 59f3e7bd..6de8f00d 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -356,9 +356,6 @@ source files int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} -int pj_calcofi_selftest (void) {return 10000;} -int pj_cass_selftest (void) {return 10000;} -int pj_cc_selftest (void) {return 10000;} int pj_cea_selftest (void) {return 10000;} int pj_chamb_selftest (void) {return 10000;} int pj_collg_selftest (void) {return 10000;} @@ -476,13 +473,8 @@ int pj_vandg3_selftest (void) {return 10000;} int pj_vandg4_selftest (void) {return 10000;} int pj_vitk1_selftest (void) {return 10000;} int pj_wag1_selftest (void) {return 10000;} -int pj_wag2_selftest (void) {return 10000;} -int pj_wag3_selftest (void) {return 10000;} int pj_wag4_selftest (void) {return 10000;} int pj_wag5_selftest (void) {return 10000;} int pj_wag6_selftest (void) {return 10000;} -int pj_wag7_selftest (void) {return 10000;} int pj_weren_selftest (void) {return 10000;} -int pj_wink1_selftest (void) {return 10000;} -int pj_wink2_selftest (void) {return 10000;} #endif diff --git a/src/PJ_calcofi.c b/src/PJ_calcofi.c index 2d142938..62749a93 100644 --- a/src/PJ_calcofi.c +++ b/src/PJ_calcofi.c @@ -1,25 +1,27 @@ #define PJ_LIB__ #include <projects.h> + +PROJ_HEAD(calcofi, + "Cal Coop Ocean Fish Invest Lines/Stations") "\n\tCyl, Sph&Ell"; + #include <string.h> #include <stdio.h> #include <math.h> #include <proj_api.h> #include <errno.h> -/* Conversions for the California Cooperative Oceanic Fisheries Investigations +/* Conversions for the California Cooperative Oceanic Fisheries Investigations Line/Station coordinate system following the algorithm of: -Eber, L.E., and R.P. Hewitt. 1979. Conversion algorithms for the CALCOFI -station grid. California Cooperative Oceanic Fisheries Investigations Reports -20:135-137. (corrected for typographical errors). +Eber, L.E., and R.P. Hewitt. 1979. Conversion algorithms for the CALCOFI +station grid. California Cooperative Oceanic Fisheries Investigations Reports +20:135-137. (corrected for typographical errors). http://www.calcofi.org/publications/calcofireports/v20/Vol_20_Eber___Hewitt.pdf -They assume 1 unit of CalCOFI Line == 1/5 degree in longitude or -meridional units at reference point O, and similarly 1 unit of CalCOFI -Station == 1/15 of a degree at O. -By convention, CalCOFI Line/Station conversions use Clarke 1866 but we use +They assume 1 unit of CalCOFI Line == 1/5 degree in longitude or +meridional units at reference point O, and similarly 1 unit of CalCOFI +Station == 1/15 of a degree at O. +By convention, CalCOFI Line/Station conversions use Clarke 1866 but we use whatever ellipsoid is provided. */ -PROJ_HEAD(calcofi, - "Cal Coop Ocean Fish Invest Lines/Stations") "\n\tCyl, Sph&Ell"; #define EPS10 1.e-10 #define DEG_TO_LINE 5 @@ -31,14 +33,17 @@ PROJ_HEAD(calcofi, #define PT_O_LAMBDA -2.1144663887911301 /* lon -121.15 and */ #define PT_O_PHI 0.59602993955606354 /* lat 34.15 */ #define ROTATION_ANGLE 0.52359877559829882 /*CalCOFI angle of 30 deg in rad */ -FORWARD(e_forward); /* ellipsoid */ + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; double oy; /* pt O y value in Mercator */ double l1; /* l1 and l2 are distances calculated using trig that sum to the east/west distance between point O and point xy */ double l2; - double ry; /* r is the point on the same station as o (60) and the same + double ry; /* r is the point on the same station as o (60) and the same line as xy xy, r, o form a right triangle */ - /* if the user has specified +lon_0 or +k0 for some reason, + /* if the user has specified +lon_0 or +k0 for some reason, we're going to ignore it so that xy is consistent with point O */ lp.lam = lp.lam + P->lam0; if (fabs(fabs(lp.phi) - HALFPI) <= EPS10) F_ERROR; @@ -49,18 +54,21 @@ FORWARD(e_forward); /* ellipsoid */ l2 = -xy.x - l1 + PT_O_LAMBDA; ry = l2 * cos(ROTATION_ANGLE) * sin(ROTATION_ANGLE) + xy.y; ry = pj_phi2(P->ctx, exp(-ry), P->e); /*inverse Mercator*/ - xy.x = PT_O_LINE - RAD_TO_DEG * - (ry - PT_O_PHI) * DEG_TO_LINE / cos(ROTATION_ANGLE); - xy.y = PT_O_STATION + RAD_TO_DEG * + xy.x = PT_O_LINE - RAD_TO_DEG * + (ry - PT_O_PHI) * DEG_TO_LINE / cos(ROTATION_ANGLE); + xy.y = PT_O_STATION + RAD_TO_DEG * (ry - lp.phi) * DEG_TO_STATION / sin(ROTATION_ANGLE); /* set a = 1, x0 = 0, and y0 = 0 so that no further unit adjustments are done */ P->a = 1; P->x0 = 0; P->y0 = 0; - return (xy); + return xy; } -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; double oy; double l1; double l2; @@ -73,17 +81,20 @@ FORWARD(s_forward); /* spheroid */ l1 = (xy.y - oy) * tan(ROTATION_ANGLE); l2 = -xy.x - l1 + PT_O_LAMBDA; ry = l2 * cos(ROTATION_ANGLE) * sin(ROTATION_ANGLE) + xy.y; - ry = HALFPI - 2. * atan(exp(-ry)); - xy.x = PT_O_LINE - RAD_TO_DEG * - (ry - PT_O_PHI) * DEG_TO_LINE / cos(ROTATION_ANGLE); - xy.y = PT_O_STATION + RAD_TO_DEG * + ry = HALFPI - 2. * atan(exp(-ry)); + xy.x = PT_O_LINE - RAD_TO_DEG * + (ry - PT_O_PHI) * DEG_TO_LINE / cos(ROTATION_ANGLE); + xy.y = PT_O_STATION + RAD_TO_DEG * (ry - lp.phi) * DEG_TO_STATION / sin(ROTATION_ANGLE); P->a = 1; P->x0 = 0; P->y0 = 0; - return (xy); + return xy; } -INVERSE(e_inverse); /* ellipsoid */ + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; double ry; /* y value of point r */ double oymctr; /* Mercator-transformed y value of point O */ double rymctr; /* Mercator-transformed ry */ @@ -93,7 +104,7 @@ INVERSE(e_inverse); /* ellipsoid */ /* turn x and y back into Line/Station */ xy.x /= P->ra; xy.y /= P->ra; - ry = PT_O_PHI - LINE_TO_RAD * (xy.x - PT_O_LINE) * + ry = PT_O_PHI - LINE_TO_RAD * (xy.x - PT_O_LINE) * cos(ROTATION_ANGLE); lp.phi = ry - STATION_TO_RAD * (xy.y - PT_O_STATION) * sin(ROTATION_ANGLE); oymctr = -log(pj_tsfn(PT_O_PHI, sin(PT_O_PHI), P->e)); @@ -103,9 +114,12 @@ INVERSE(e_inverse); /* ellipsoid */ l2 = (rymctr - xymctr) / (cos(ROTATION_ANGLE) * sin(ROTATION_ANGLE)); lp.lam = PT_O_LAMBDA - (l1 + l2); P->over = 1; - return (lp); + return lp; } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; double ry; double oymctr; double rymctr; @@ -114,7 +128,7 @@ INVERSE(s_inverse); /* spheroid */ double l2; xy.x /= P->ra; xy.y /= P->ra; - ry = PT_O_PHI - LINE_TO_RAD * (xy.x - PT_O_LINE) * + ry = PT_O_PHI - LINE_TO_RAD * (xy.x - PT_O_LINE) * cos(ROTATION_ANGLE); lp.phi = ry - STATION_TO_RAD * (xy.y - PT_O_STATION) * sin(ROTATION_ANGLE); oymctr = log(tan(FORTPI + .5 * PT_O_PHI)); @@ -124,10 +138,25 @@ INVERSE(s_inverse); /* spheroid */ l2 = (rymctr - xymctr) / (cos(ROTATION_ANGLE) * sin(ROTATION_ANGLE)); lp.lam = PT_O_LAMBDA - (l1 + l2); P->over = 1; - return (lp); + return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(calcofi) + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc (P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(calcofi) { + P->opaque = 0; + + P->pfree = freeup; + P->descr = des_calcofi; if (P->es) { /* ellipsoid */ P->inv = e_inverse; P->fwd = e_forward; @@ -135,4 +164,65 @@ ENTRY0(calcofi) P->inv = s_inverse; P->fwd = s_forward; } -ENDENTRY(P) + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_calcofi_selftest (void) {return 0;} +#else + +int pj_calcofi_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=calcofi +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=calcofi +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {508.44487214981905, -1171.7648604175156}, + {514.99916815188112, -1145.8219814677668}, + {500.68538412539851, -1131.4453779204598}, + {507.36971913666355, -1106.1782014834275}, + }; + + XY s_fwd_expect[] = { + {507.09050748781806, -1164.7273751978314}, + {513.68613637462886, -1138.9992682173072}, + {499.33626147591531, -1124.4351309968195}, + {506.0605703929898, -1099.3756650673038}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {-110.36330792469906, 12.032056975840137}, + {-98.455008863288782, 18.698723642506803}, + {-207.4470245036909, 81.314089278595247}, + {-62.486322854481287, 87.980755945261919}, + }; + + LP s_inv_expect[] = { + {-110.30519040955151, 12.032056975840137}, + {-98.322360950234085, 18.698723642506803}, + {-207.54490681381429, 81.314089278595247}, + {-62.576950371885275, 87.980755945261919}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif diff --git a/src/PJ_cass.c b/src/PJ_cass.c index 5f885376..28d35b91 100644 --- a/src/PJ_cass.c +++ b/src/PJ_cass.c @@ -1,96 +1,90 @@ #define PJ_LIB__ -# include <projects.h> +# include <projects.h> PROJ_HEAD(cass, "Cassini") "\n\tCyl, Sph&Ell"; -# define EPS10 1e-10 -# define C1 .16666666666666666666 -# define C2 .00833333333333333333 -# define C3 .04166666666666666666 -# define C4 .33333333333333333333 -# define C5 .06666666666666666666 +# define EPS10 1e-10 +# define C1 .16666666666666666666 +# define C2 .00833333333333333333 +# define C3 .04166666666666666666 +# define C4 .33333333333333333333 +# define C5 .06666666666666666666 struct pj_opaque { - /* These are the only opaque members actually initialized */ - double *en; - double m0; - - /* Apparently this group of opaque members should be demoted to local variables in e_forward and e_inverse */ - double n; - double t; - double a1; - double c; - double r; - double dd; - double d2; - double a2; - double tn; + double *en; + double m0; }; static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ - XY xy = {0.0,0.0}; + double n, t, a1, c, a2, tn; + XY xy = {0.0, 0.0}; struct pj_opaque *Q = P->opaque; - xy.y = pj_mlfn(lp.phi, Q->n = sin(lp.phi), Q->c = cos(lp.phi), Q->en); - Q->n = 1./sqrt(1. - P->es * Q->n * Q->n); - Q->tn = tan(lp.phi); Q->t = Q->tn * Q->tn; - Q->a1 = lp.lam * Q->c; - Q->c *= P->es * Q->c / (1 - P->es); - Q->a2 = Q->a1 * Q->a1; - xy.x = Q->n * Q->a1 * (1. - Q->a2 * Q->t * - (C1 - (8. - Q->t + 8. * Q->c) * Q->a2 * C2)); - xy.y -= Q->m0 - Q->n * Q->tn * Q->a2 * - (.5 + (5. - Q->t + 6. * Q->c) * Q->a2 * C3); - return xy; + + xy.y = pj_mlfn (lp.phi, n = sin (lp.phi), c = cos (lp.phi), Q->en); + + n = 1./sqrt(1. - P->es * n*n); + tn = tan(lp.phi); t = tn * tn; + a1 = lp.lam * c; + c *= P->es * c / (1 - P->es); + a2 = a1 * a1; + + xy.x = n * a1 * (1. - a2 * t * + (C1 - (8. - t + 8. * c) * a2 * C2)); + xy.y -= Q->m0 - n * tn * a2 * + (.5 + (5. - t + 6. * c) * a2 * C3); + + return xy; } static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ - XY xy = {0.0,0.0}; - xy.x = asin(cos(lp.phi) * sin(lp.lam)); - xy.y = atan2(tan(lp.phi) , cos(lp.lam)) - P->phi0; - return xy; + XY xy = {0.0, 0.0}; + xy.x = asin (cos (lp.phi) * sin (lp.lam)); + xy.y = atan2 (tan (lp.phi), cos (lp.lam)) - P->phi0; + return xy; } static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ - LP lp = {0.0,0.0}; + double n, t, r, dd, d2, tn, ph1; + LP lp = {0.0, 0.0}; struct pj_opaque *Q = P->opaque; - double ph1; - - ph1 = pj_inv_mlfn(P->ctx, Q->m0 + xy.y, P->es, Q->en); - Q->tn = tan(ph1); Q->t = Q->tn * Q->tn; - Q->n = sin(ph1); - Q->r = 1. / (1. - P->es * Q->n * Q->n); - Q->n = sqrt(Q->r); - Q->r *= (1. - P->es) * Q->n; - Q->dd = xy.x / Q->n; - Q->d2 = Q->dd * Q->dd; - lp.phi = ph1 - (Q->n * Q->tn / Q->r) * Q->d2 * - (.5 - (1. + 3. * Q->t) * Q->d2 * C3); - lp.lam = Q->dd * (1. + Q->t * Q->d2 * - (-C4 + (1. + 3. * Q->t) * Q->d2 * C5)) / cos(ph1); - return lp; + + ph1 = pj_inv_mlfn (P->ctx, Q->m0 + xy.y, P->es, Q->en); + tn = tan (ph1); t = tn*tn; + n = sin (ph1); + r = 1. / (1. - P->es * n * n); + n = sqrt (r); + r *= (1. - P->es) * n; + dd = xy.x / n; + d2 = dd * dd; + lp.phi = ph1 - (n * tn / r) * d2 * + (.5 - (1. + 3. * t) * d2 * C3); + lp.lam = dd * (1. + t * d2 * + (-C4 + (1. + 3. * t) * d2 * C5)) / cos (ph1); + return lp; } static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ LP lp = {0.0,0.0}; - lp.phi = asin(sin(P->opaque->dd = xy.y + P->phi0) * cos(xy.x)); - lp.lam = atan2(tan(xy.x), cos(P->opaque->dd)); - return lp; + double dd; + lp.phi = asin(sin(dd = xy.y + P->phi0) * cos(xy.x)); + lp.lam = atan2(tan(xy.x), cos(dd)); + return lp; } static void *freeup_new(PJ *P) { /* Destructor */ - if (0==P) + if (0==P) return 0; if (0==P->opaque) return pj_dealloc (P); - pj_dealloc(P->opaque->en); + pj_dealloc(P->opaque->en); pj_dealloc(P->opaque); return pj_dealloc(P); } @@ -103,28 +97,82 @@ static void freeup(PJ *P) { /* Destructor */ PJ *PROJECTION(cass) { /* Spheroidal? */ - if (0==P->es) { - P->inv = s_inverse; - P->fwd = s_forward; + if (0==P->es) { + P->inv = s_inverse; + P->fwd = s_forward; return P; } - /* Otherwise it's ellipsoidal */ + /* otherwise it's ellipsoidal */ P->opaque = pj_calloc (1, sizeof (struct pj_opaque)); - if (0==P->opaque) { - freeup (P); - return 0; - } + if (0==P->opaque) + return freeup_new (P); - P->opaque->en = pj_enfn(P->es); - if (0==P->opaque->en) { - freeup (P); - return 0; - } + P->opaque->en = pj_enfn (P->es); + if (0==P->opaque->en) + return freeup_new (P); - P->opaque->m0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), P->opaque->en); - P->inv = e_inverse; - P->fwd = e_forward; + P->opaque->m0 = pj_mlfn (P->phi0, sin (P->phi0), cos (P->phi0), P->opaque->en); + P->inv = e_inverse; + P->fwd = e_forward; return P; } + + +#ifdef PJ_OMIT_SELFTEST +int pj_cass_selftest (void) {return 0;} +#else + +int pj_cass_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=cass +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=cass +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222605.28577699114, 110642.22925399939}, + { 222605.28577699114, -110642.22925399939}, + {-222605.28577699114, 110642.22925399939}, + {-222605.28577699114, -110642.22925399939}, + }; + + XY s_fwd_expect[] = { + { 223368.10520348375, 111769.14504058579}, + { 223368.10520348375, -111769.14504058579}, + {-223368.10520348375, 111769.14504058579}, + {-223368.10520348375, -111769.14504058579}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.0017966305684613522, 0.00090436947663183841}, + { 0.0017966305684613522, -0.00090436947663183841}, + {-0.0017966305684613522, 0.00090436947663183841}, + {-0.0017966305684613522, -0.00090436947663183841}, + }; + + LP s_inv_expect[] = { + { 0.0017904931100023887, 0.00089524655445477922}, + { 0.0017904931100023887, -0.00089524655445477922}, + {-0.0017904931100023887, 0.00089524655445477922}, + {-0.0017904931100023887, -0.00089524655445477922}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} +#endif diff --git a/src/PJ_cc.c b/src/PJ_cc.c index 0f573929..475fbae4 100644 --- a/src/PJ_cc.c +++ b/src/PJ_cc.c @@ -1,20 +1,89 @@ -#define PROJ_PARMS__ \ - double ap; #define PJ_LIB__ #include <projects.h> + PROJ_HEAD(cc, "Central Cylindrical") "\n\tCyl, Sph"; #define EPS10 1.e-10 -FORWARD(s_forward); /* spheroid */ - if (fabs(fabs(lp.phi) - HALFPI) <= EPS10) F_ERROR; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + if (fabs (fabs(lp.phi) - HALFPI) <= EPS10) F_ERROR; xy.x = lp.lam; xy.y = tan(lp.phi); - return (xy); + return xy; } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; (void) P; lp.phi = atan(xy.y); lp.lam = xy.x; - return (lp); + return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(cc) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(cc) { + P->es = 0.; + + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_cc_selftest (void) {return 0;} +#else + +int pj_cc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=cc +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {223402.14425527418, 111712.41554059254}, + {223402.14425527418, -111712.41554059254}, + {-223402.14425527418, 111712.41554059254}, + {-223402.14425527418, -111712.41554059254}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {0.0017904931097838226, 0.00089524655481905597}, + {0.0017904931097838226, -0.00089524655481905597}, + {-0.0017904931097838226, 0.00089524655481905597}, + {-0.0017904931097838226, -0.00089524655481905597}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif diff --git a/src/PJ_wag2.c b/src/PJ_wag2.c index f4942bb2..b70dcd4f 100644 --- a/src/PJ_wag2.c +++ b/src/PJ_wag2.c @@ -5,17 +5,84 @@ PROJ_HEAD(wag2, "Wagner II") "\n\tPCyl., Sph."; #define C_y 1.38725 #define C_p1 0.88022 #define C_p2 0.88550 -FORWARD(s_forward); /* spheroid */ - lp.phi = aasin(P->ctx,C_p1 * sin(C_p2 * lp.phi)); - xy.x = C_x * lp.lam * cos(lp.phi); + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + lp.phi = aasin (P->ctx,C_p1 * sin (C_p2 * lp.phi)); + xy.x = C_x * lp.lam * cos (lp.phi); xy.y = C_y * lp.phi; return (xy); } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; lp.phi = xy.y / C_y; lp.lam = xy.x / (C_x * cos(lp.phi)); - lp.phi = aasin(P->ctx,sin(lp.phi) / C_p1) / C_p2; + lp.phi = aasin (P->ctx,sin(lp.phi) / C_p1) / C_p2; return (lp); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(wag2) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(wag2) { + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_wag2_selftest (void) {return 0;} +#else + +int pj_wag2_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wag2 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 206589.88809996162, 120778.04035754716}, + { 206589.88809996162, -120778.04035754716}, + {-206589.88809996162, 120778.04035754716}, + {-206589.88809996162, -120778.04035754716}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0019360240367390709, 0.00082795765763814082}, + { 0.0019360240367390709, -0.00082795765763814082}, + {-0.0019360240367390709, 0.00082795765763814082}, + {-0.0019360240367390709, -0.00082795765763814082}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif diff --git a/src/PJ_wag3.c b/src/PJ_wag3.c index 482e389c..0539f4a1 100644 --- a/src/PJ_wag3.c +++ b/src/PJ_wag3.c @@ -1,24 +1,101 @@ -#define PROJ_PARMS__ \ - double C_x; #define PJ_LIB__ # include <projects.h> PROJ_HEAD(wag3, "Wagner III") "\n\tPCyl., Sph.\n\tlat_ts="; #define TWOTHIRD 0.6666666666666666666667 -FORWARD(s_forward); /* spheroid */ - xy.x = P->C_x * lp.lam * cos(TWOTHIRD * lp.phi); + +struct pj_opaque { + double C_x; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + xy.x = P->opaque->C_x * lp.lam * cos(TWOTHIRD * lp.phi); xy.y = lp.phi; - return (xy); + return xy; } + + +#if 0 INVERSE(s_inverse); /* spheroid */ +#endif + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; lp.phi = xy.y; - lp.lam = xy.x / (P->C_x * cos(TWOTHIRD * lp.phi)); - return (lp); + lp.lam = xy.x / (P->opaque->C_x * cos(TWOTHIRD * lp.phi)); + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(wag3) + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(wag3) { double ts; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + ts = pj_param (P->ctx, P->params, "rlat_ts").f; + P->opaque->C_x = cos (ts) / cos (2.*ts/3.); + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_wag3_selftest (void) {return 0;} +#else + +int pj_wag3_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wag3 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {223387.02171816575, 111701.07212763709}, + {223387.02171816575, -111701.07212763709}, + {-223387.02171816575, 111701.07212763709}, + {-223387.02171816575, -111701.07212763709}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {0.001790493109880963, 0.00089524655489191132}, + {0.001790493109880963, -0.00089524655489191132}, + {-0.001790493109880963, 0.00089524655489191132}, + {-0.001790493109880963, -0.00089524655489191132}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + - ts = pj_param(P->ctx, P->params, "rlat_ts").f; - P->C_x = cos(ts) / cos(2.*ts/3.); - P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; -ENDENTRY(P) +#endif diff --git a/src/PJ_wag7.c b/src/PJ_wag7.c index db29ffb1..847566d8 100644 --- a/src/PJ_wag7.c +++ b/src/PJ_wag7.c @@ -1,15 +1,67 @@ #define PJ_LIB__ #include <projects.h> + PROJ_HEAD(wag7, "Wagner VII") "\n\tMisc Sph, no inv."; -FORWARD(s_forward); /* sphere */ + + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0, 0.0}; double theta, ct, D; - (void) P; - theta = asin(xy.y = 0.90630778703664996 * sin(lp.phi)); - xy.x = 2.66723 * (ct = cos(theta)) * sin(lp.lam /= 3.); - xy.y *= 1.24104 * (D = 1/(sqrt(0.5 * (1 + ct * cos(lp.lam))))); + (void) P; /* Shut up compiler warnnings about unused P */ + + theta = asin (xy.y = 0.90630778703664996 * sin(lp.phi)); + xy.x = 2.66723 * (ct = cos (theta)) * sin (lp.lam /= 3.); + xy.y *= 1.24104 * (D = 1/(sqrt (0.5 * (1 + ct * cos (lp.lam))))); xy.x *= D; return (xy); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(wag7) P->fwd = s_forward; P->inv = 0; P->es = 0.; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + + +PJ *PROJECTION(wag7) { + P->fwd = s_forward; + P->inv = 0; + P->es = 0.; + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_wag7_selftest (void) {return 0;} +#else + +int pj_wag7_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wag7 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 198601.87695731167, 125637.0457141714}, + { 198601.87695731167, -125637.0457141714}, + {-198601.87695731167, 125637.0457141714}, + {-198601.87695731167, -125637.0457141714}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} +#endif diff --git a/src/PJ_wink1.c b/src/PJ_wink1.c index dfb455e0..f9d127c0 100644 --- a/src/PJ_wink1.c +++ b/src/PJ_wink1.c @@ -1,20 +1,100 @@ -#define PROJ_PARMS__ \ - double cosphi1; #define PJ_LIB__ -# include <projects.h> +#include <projects.h> PROJ_HEAD(wink1, "Winkel I") "\n\tPCyl., Sph.\n\tlat_ts="; -FORWARD(s_forward); /* spheroid */ - xy.x = .5 * lp.lam * (P->cosphi1 + cos(lp.phi)); + + +struct pj_opaque { + double cosphi1; +}; + + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + xy.x = .5 * lp.lam * (P->opaque->cosphi1 + cos(lp.phi)); xy.y = lp.phi; return (xy); } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; lp.phi = xy.y; - lp.lam = 2. * xy.x / (P->cosphi1 + cos(lp.phi)); + lp.lam = 2. * xy.x / (P->opaque->cosphi1 + cos(lp.phi)); return (lp); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(wink1) - P->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_ts").f); - P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; -ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(wink1) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->opaque->cosphi1 = cos (pj_param(P->ctx, P->params, "rlat_ts").f); + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_wink1_selftest (void) {return 0;} +#else + +int pj_wink1_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wink1 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223385.13164095284, 111701.07212763709}, + { 223385.13164095284, -111701.07212763709}, + {-223385.13164095284, 111701.07212763709}, + {-223385.13164095284, -111701.07212763709}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0017904931098931057, 0.00089524655489191132}, + { 0.0017904931098931057, -0.00089524655489191132}, + {-0.0017904931098931057, 0.00089524655489191132}, + {-0.0017904931098931057, -0.00089524655489191132}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif diff --git a/src/PJ_wink2.c b/src/PJ_wink2.c index 388c790a..f31ba5a5 100644 --- a/src/PJ_wink2.c +++ b/src/PJ_wink2.c @@ -1,34 +1,93 @@ -#define PROJ_PARMS__ \ - double cosphi1; #define PJ_LIB__ # include <projects.h> + PROJ_HEAD(wink2, "Winkel II") "\n\tPCyl., Sph., no inv.\n\tlat_1="; + +struct pj_opaque { double cosphi1; }; + #define MAX_ITER 10 #define LOOP_TOL 1e-7 #define TWO_D_PI 0.636619772367581343 -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0, 0.0}; double k, V; int i; xy.y = lp.phi * TWO_D_PI; - k = PI * sin(lp.phi); + k = PI * sin (lp.phi); lp.phi *= 1.8; for (i = MAX_ITER; i ; --i) { - lp.phi -= V = (lp.phi + sin(lp.phi) - k) / - (1. + cos(lp.phi)); - if (fabs(V) < LOOP_TOL) + lp.phi -= V = (lp.phi + sin (lp.phi) - k) / + (1. + cos (lp.phi)); + if (fabs (V) < LOOP_TOL) break; } if (!i) lp.phi = (lp.phi < 0.) ? -HALFPI : HALFPI; else lp.phi *= 0.5; - xy.x = 0.5 * lp.lam * (cos(lp.phi) + P->cosphi1); - xy.y = FORTPI * (sin(lp.phi) + xy.y); - return (xy); + xy.x = 0.5 * lp.lam * (cos (lp.phi) + P->opaque->cosphi1); + xy.y = FORTPI * (sin (lp.phi) + xy.y); + return xy; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(wink2) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->opaque->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_1").f); + P->es = 0.; + P->inv = 0; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_wink2_selftest (void) {return 0;} +#else + +int pj_wink2_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wink2 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223387.39643378611, 124752.03279744535}, + { 223387.39643378611, -124752.03279744535}, + {-223387.39643378611, 124752.03279744535}, + {-223387.39643378611, -124752.03279744535}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(wink2) - P->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_1").f); - P->es = 0.; P->inv = 0; P->fwd = s_forward; -ENDENTRY(P) +#endif diff --git a/src/projects.h b/src/projects.h index 307b69bd..2957f848 100644 --- a/src/projects.h +++ b/src/projects.h @@ -359,7 +359,7 @@ extern struct PJ_PRIME_MERIDIANS pj_prime_meridians[]; #define INVERSE3D(name) static LPZ name(XYZ xyz, PJ *P) {LPZ lpz = {0.0, 0.0, 0.0} #define FREEUP static void freeup(PJ *P) { #define SPECIAL(name) static void name(LP lp, PJ *P, struct FACTORS *fac) - +#define ELLIPSOIDAL(P) ((P->es==0)? (FALSE): (TRUE)) /* cleaned up alternative to most of the "repetitive projection code" macros */ #define PROJECTION(name) \ |
