aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Knudsen <lastname DOT firstname AT gmail DOT com>2016-04-12 21:55:29 +0200
committerThomas Knudsen <lastname DOT firstname AT gmail DOT com>2016-04-12 21:55:29 +0200
commitc8f040f1d6b52f89825c9a1060545a97bf799487 (patch)
tree65cc06d0ba2bed9f84d3c5f676182ced243cbdf9
parent86a3221bdc26ea2cdbe85fcf270263ce02fef0e6 (diff)
downloadPROJ-c8f040f1d6b52f89825c9a1060545a97bf799487.tar.gz
PROJ-c8f040f1d6b52f89825c9a1060545a97bf799487.zip
refactoring + added selftest for 7 more projections
tcc, tcea, tmerc, tpeqd, urm5, urmfps, wag1
-rw-r--r--src/PJ_aea.c7
-rw-r--r--src/PJ_tcc.c76
-rw-r--r--src/PJ_tcea.c104
-rw-r--r--src/PJ_tmerc.c373
-rw-r--r--src/PJ_tpeqd.c193
-rw-r--r--src/PJ_urm5.c103
-rw-r--r--src/PJ_urmfps.c176
-rw-r--r--src/pj_generic_selftest.c20
8 files changed, 767 insertions, 285 deletions
diff --git a/src/PJ_aea.c b/src/PJ_aea.c
index 6de8f00d..7a507460 100644
--- a/src/PJ_aea.c
+++ b/src/PJ_aea.c
@@ -457,22 +457,15 @@ int pj_somerc_selftest (void) {return 10000;}
int pj_stere_selftest (void) {return 10000;}
int pj_sterea_selftest (void) {return 10000;}
int pj_gstmerc_selftest (void) {return 10000;}
-int pj_tcc_selftest (void) {return 10000;}
-int pj_tcea_selftest (void) {return 10000;}
int pj_tissot_selftest (void) {return 10000;}
-int pj_tmerc_selftest (void) {return 10000;}
-int pj_tpeqd_selftest (void) {return 10000;}
int pj_tpers_selftest (void) {return 10000;}
int pj_ups_selftest (void) {return 10000;}
-int pj_urm5_selftest (void) {return 10000;}
-int pj_urmfps_selftest (void) {return 10000;}
int pj_utm_selftest (void) {return 10000;}
int pj_vandg_selftest (void) {return 10000;}
int pj_vandg2_selftest (void) {return 10000;}
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_wag4_selftest (void) {return 10000;}
int pj_wag5_selftest (void) {return 10000;}
int pj_wag6_selftest (void) {return 10000;}
diff --git a/src/PJ_tcc.c b/src/PJ_tcc.c
index 00cdb556..457924c0 100644
--- a/src/PJ_tcc.c
+++ b/src/PJ_tcc.c
@@ -1,17 +1,65 @@
-#define PROJ_PARMS__ \
- double ap;
-#define EPS10 1.e-10
#define PJ_LIB__
-#include <projects.h>
+#include <projects.h>
+
PROJ_HEAD(tcc, "Transverse Central Cylindrical") "\n\tCyl, Sph, no inv.";
-FORWARD(s_forward); /* spheroid */
- double b, bt;
-
- b = cos(lp.phi) * sin(lp.lam);
- if ((bt = 1. - b * b) < EPS10) F_ERROR;
- xy.x = b / sqrt(bt);
- xy.y = atan2(tan(lp.phi) , cos(lp.lam));
- return (xy);
+
+#define EPS10 1.e-10
+
+
+static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
+ XY xy = {0.0, 0.0};
+ double b, bt;
+
+ b = cos (lp.phi) * sin (lp.lam);
+ if ((bt = 1. - b * b) < EPS10) F_ERROR;
+ xy.x = b / sqrt(bt);
+ xy.y = atan2 (tan (lp.phi) , cos (lp.lam));
+ return xy;
+}
+
+
+static void *freeup_new (PJ *P) { /* Destructor */
+ return pj_dealloc(P);
+}
+
+static void freeup (PJ *P) {
+ freeup_new (P);
+ return;
+}
+
+
+PJ *PROJECTION(tcc) {
+ P->es = 0.;
+ P->fwd = s_forward;
+ P->inv = 0;
+
+ return P;
+}
+
+
+#ifdef PJ_OMIT_SELFTEST
+int pj_tcc_selftest (void) {return 0;}
+#else
+int pj_tcc_selftest (void) {
+ double tolerance_lp = 1e-10;
+ double tolerance_xy = 1e-7;
+
+ char s_args[] = {"+proj=tcc +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"};
+
+ LP fwd_in[] = {
+ { 2, 1},
+ { 2,-1},
+ {-2, 1},
+ {-2,-1}
+ };
+
+ XY s_fwd_expect[] = {
+ {223458.84419245756, 111769.14504058579},
+ {223458.84419245756, -111769.14504058579},
+ {-223458.84419245756, 111769.14504058579},
+ {-223458.84419245756, -111769.14504058579},
+ };
+
+ 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(tcc) P->es = 0.; P->fwd = s_forward; ENDENTRY(P)
+#endif
diff --git a/src/PJ_tcea.c b/src/PJ_tcea.c
index 3626fa17..7b469d0e 100644
--- a/src/PJ_tcea.c
+++ b/src/PJ_tcea.c
@@ -1,27 +1,85 @@
-#define PROJ_PARMS__ \
- double rk0;
#define PJ_LIB__
-#include <projects.h>
+#include <projects.h>
+
PROJ_HEAD(tcea, "Transverse Cylindrical Equal Area") "\n\tCyl, Sph";
-FORWARD(s_forward); /* spheroid */
- xy.x = P->rk0 * cos(lp.phi) * sin(lp.lam);
- xy.y = P->k0 * (atan2(tan(lp.phi), cos(lp.lam)) - P->phi0);
- return (xy);
+
+
+static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
+ XY xy = {0.0,0.0};
+ xy.x = cos (lp.phi) * sin (lp.lam) / P->k0;
+ xy.y = P->k0 * (atan2 (tan (lp.phi), cos (lp.lam)) - P->phi0);
+ return xy;
+}
+
+
+static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
+ LP lp = {0.0, 0.0};
+ double t;
+
+ xy.y = xy.y / P->k0 + P->phi0;
+ xy.x *= P->k0;
+ t = sqrt (1. - xy.x * xy.x);
+ lp.phi = asin (t * sin (xy.y));
+ lp.lam = atan2 (xy.x, t * cos (xy.y));
+ return lp;
+}
+
+
+static void *freeup_new (PJ *P) { /* Destructor */
+ return pj_dealloc(P);
+}
+
+static void freeup (PJ *P) {
+ freeup_new (P);
+ return;
}
-INVERSE(s_inverse); /* spheroid */
- double t;
-
- xy.y = xy.y * P->rk0 + P->phi0;
- xy.x *= P->k0;
- t = sqrt(1. - xy.x * xy.x);
- lp.phi = asin(t * sin(xy.y));
- lp.lam = atan2(xy.x, t * cos(xy.y));
- return (lp);
+
+
+PJ *PROJECTION(tcea) {
+ P->inv = s_inverse;
+ P->fwd = s_forward;
+ P->es = 0.;
+ return P;
+}
+
+
+#ifdef PJ_OMIT_SELFTEST
+int pj_tcea_selftest (void) {return 0;}
+#else
+int pj_tcea_selftest (void) {
+ double tolerance_lp = 1e-10;
+ double tolerance_xy = 1e-7;
+
+ char s_args[] = {"+proj=tcea +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"};
+
+ LP fwd_in[] = {
+ { 2, 1},
+ { 2,-1},
+ {-2, 1},
+ {-2,-1}
+ };
+
+ XY s_fwd_expect[] = {
+ { 223322.76057672748, 111769.14504058579},
+ { 223322.76057672748, -111769.14504058579},
+ {-223322.76057672748, 111769.14504058579},
+ {-223322.76057672748, -111769.14504058579},
+ };
+
+ XY inv_in[] = {
+ { 200, 100},
+ { 200,-100},
+ {-200, 100},
+ {-200,-100}
+ };
+
+ LP s_inv_expect[] = {
+ { 0.0017904931102938101, 0.00089524655445477922},
+ { 0.0017904931102938101, -0.00089524655445477922},
+ {-0.0017904931102938101, 0.00089524655445477922},
+ {-0.0017904931102938101, -0.00089524655445477922},
+ };
+
+ 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);
}
-FREEUP; if (P) pj_dalloc(P); }
-ENTRY0(tcea)
- P->rk0 = 1 / P->k0;
- P->inv = s_inverse;
- P->fwd = s_forward;
- P->es = 0.;
-ENDENTRY(P)
+#endif
diff --git a/src/PJ_tmerc.c b/src/PJ_tmerc.c
index 70e8e72f..35203261 100644
--- a/src/PJ_tmerc.c
+++ b/src/PJ_tmerc.c
@@ -1,13 +1,16 @@
-#define PROJ_PARMS__ \
- double esp; \
- double ml0; \
- double *en;
#define PJ_LIB__
-#include <projects.h>
+#include <projects.h>
+
PROJ_HEAD(tmerc, "Transverse Mercator") "\n\tCyl, Sph&Ell";
-#define EPS10 1.e-10
-#define aks0 P->esp
-#define aks5 P->ml0
+
+
+struct pj_opaque {
+ double esp; \
+ double ml0; \
+ double *en;
+};
+
+#define EPS10 1.e-10
#define FC1 1.
#define FC2 .5
#define FC3 .16666666666666666666
@@ -16,138 +19,234 @@ PROJ_HEAD(tmerc, "Transverse Mercator") "\n\tCyl, Sph&Ell";
#define FC6 .03333333333333333333
#define FC7 .02380952380952380952
#define FC8 .01785714285714285714
-FORWARD(e_forward); /* ellipse */
- double al, als, n, cosphi, sinphi, t;
-
- /*
- * Fail if our longitude is more than 90 degrees from the
- * central meridian since the results are essentially garbage.
- * Is error -20 really an appropriate return value?
- *
- * http://trac.osgeo.org/proj/ticket/5
- */
- if( lp.lam < -HALFPI || lp.lam > HALFPI )
- {
- xy.x = HUGE_VAL;
- xy.y = HUGE_VAL;
- pj_ctx_set_errno( P->ctx, -14 );
- return xy;
- }
-
- sinphi = sin(lp.phi); cosphi = cos(lp.phi);
- t = fabs(cosphi) > 1e-10 ? sinphi/cosphi : 0.;
- t *= t;
- al = cosphi * lp.lam;
- als = al * al;
- al /= sqrt(1. - P->es * sinphi * sinphi);
- n = P->esp * cosphi * cosphi;
- xy.x = P->k0 * al * (FC1 +
- FC3 * als * (1. - t + n +
- FC5 * als * (5. + t * (t - 18.) + n * (14. - 58. * t)
- + FC7 * als * (61. + t * ( t * (179. - t) - 479. ) )
- )));
- xy.y = P->k0 * (pj_mlfn(lp.phi, sinphi, cosphi, P->en) - P->ml0 +
- sinphi * al * lp.lam * FC2 * ( 1. +
- FC4 * als * (5. - t + n * (9. + 4. * n) +
- FC6 * als * (61. + t * (t - 58.) + n * (270. - 330 * t)
- + FC8 * als * (1385. + t * ( t * (543. - t) - 3111.) )
- ))));
- return (xy);
+
+
+static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */
+ XY xy = {0.0, 0.0};
+ struct pj_opaque *Q = P->opaque;
+ double al, als, n, cosphi, sinphi, t;
+
+ /*
+ * Fail if our longitude is more than 90 degrees from the
+ * central meridian since the results are essentially garbage.
+ * Is error -20 really an appropriate return value?
+ *
+ * http://trac.osgeo.org/proj/ticket/5
+ */
+ if( lp.lam < -HALFPI || lp.lam > HALFPI ) {
+ xy.x = HUGE_VAL;
+ xy.y = HUGE_VAL;
+ pj_ctx_set_errno( P->ctx, -14 );
+ return xy;
+ }
+
+ sinphi = sin (lp.phi);
+ cosphi = cos (lp.phi);
+ t = fabs (cosphi) > 1e-10 ? sinphi/cosphi : 0.;
+ t *= t;
+ al = cosphi * lp.lam;
+ als = al * al;
+ al /= sqrt (1. - P->es * sinphi * sinphi);
+ n = Q->esp * cosphi * cosphi;
+ xy.x = P->k0 * al * (FC1 +
+ FC3 * als * (1. - t + n +
+ FC5 * als * (5. + t * (t - 18.) + n * (14. - 58. * t)
+ + FC7 * als * (61. + t * ( t * (179. - t) - 479. ) )
+ )));
+ xy.y = P->k0 * (pj_mlfn(lp.phi, sinphi, cosphi, Q->en) - Q->ml0 +
+ sinphi * al * lp.lam * FC2 * ( 1. +
+ FC4 * als * (5. - t + n * (9. + 4. * n) +
+ FC6 * als * (61. + t * (t - 58.) + n * (270. - 330 * t)
+ + FC8 * als * (1385. + t * ( t * (543. - t) - 3111.) )
+ ))));
+ return (xy);
+}
+
+
+static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
+ XY xy = {0.0,0.0};
+ double b, cosphi;
+
+ /*
+ * Fail if our longitude is more than 90 degrees from the
+ * central meridian since the results are essentially garbage.
+ * Is error -20 really an appropriate return value?
+ *
+ * http://trac.osgeo.org/proj/ticket/5
+ */
+ if( lp.lam < -HALFPI || lp.lam > HALFPI ) {
+ xy.x = HUGE_VAL;
+ xy.y = HUGE_VAL;
+ pj_ctx_set_errno( P->ctx, -14 );
+ return xy;
+ }
+
+ cosphi = cos(lp.phi);
+ b = cosphi * sin (lp.lam);
+ if (fabs (fabs (b) - 1.) <= EPS10)
+ F_ERROR;
+
+ xy.x = P->opaque->ml0 * log ((1. + b) / (1. - b));
+ xy.y = cosphi * cos (lp.lam) / sqrt (1. - b * b);
+
+ b = fabs ( xy.y );
+ if (b >= 1.) {
+ if ((b - 1.) > EPS10)
+ F_ERROR
+ else xy.y = 0.;
+ } else
+ xy.y = acos (xy.y);
+
+ if (lp.phi < 0.)
+ xy.y = -xy.y;
+ xy.y = P->opaque->esp * (xy.y - P->phi0);
+ return xy;
+}
+
+
+static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
+ LP lp = {0.0,0.0};
+ struct pj_opaque *Q = P->opaque;
+ double n, con, cosphi, d, ds, sinphi, t;
+
+ lp.phi = pj_inv_mlfn(P->ctx, Q->ml0 + xy.y / P->k0, P->es, Q->en);
+ if (fabs(lp.phi) >= HALFPI) {
+ lp.phi = xy.y < 0. ? -HALFPI : HALFPI;
+ lp.lam = 0.;
+ } else {
+ sinphi = sin(lp.phi);
+ cosphi = cos(lp.phi);
+ t = fabs (cosphi) > 1e-10 ? sinphi/cosphi : 0.;
+ n = Q->esp * cosphi * cosphi;
+ d = xy.x * sqrt (con = 1. - P->es * sinphi * sinphi) / P->k0;
+ con *= t;
+ t *= t;
+ ds = d * d;
+ lp.phi -= (con * ds / (1.-P->es)) * FC2 * (1. -
+ ds * FC4 * (5. + t * (3. - 9. * n) + n * (1. - 4 * n) -
+ ds * FC6 * (61. + t * (90. - 252. * n +
+ 45. * t) + 46. * n
+ - ds * FC8 * (1385. + t * (3633. + t * (4095. + 1574. * t)) )
+ )));
+ lp.lam = d*(FC1 -
+ ds*FC3*( 1. + 2.*t + n -
+ ds*FC5*(5. + t*(28. + 24.*t + 8.*n) + 6.*n
+ - ds * FC7 * (61. + t * (662. + t * (1320. + 720. * t)) )
+ ))) / cosphi;
+ }
+ return lp;
}
-FORWARD(s_forward); /* sphere */
- double b, cosphi;
-
- /*
- * Fail if our longitude is more than 90 degrees from the
- * central meridian since the results are essentially garbage.
- * Is error -20 really an appropriate return value?
- *
- * http://trac.osgeo.org/proj/ticket/5
- */
- if( lp.lam < -HALFPI || lp.lam > HALFPI )
- {
- xy.x = HUGE_VAL;
- xy.y = HUGE_VAL;
- pj_ctx_set_errno( P->ctx, -14 );
- return xy;
- }
-
- b = (cosphi = cos(lp.phi)) * sin(lp.lam);
- if (fabs(fabs(b) - 1.) <= EPS10) F_ERROR;
- xy.x = aks5 * log((1. + b) / (1. - b));
- if ((b = fabs( xy.y = cosphi * cos(lp.lam) / sqrt(1. - b * b) )) >= 1.) {
- if ((b - 1.) > EPS10) F_ERROR
- else xy.y = 0.;
- } else
- xy.y = acos(xy.y);
- if (lp.phi < 0.) xy.y = -xy.y;
- xy.y = aks0 * (xy.y - P->phi0);
- return (xy);
+
+
+static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
+ LP lp = {0.0, 0.0};
+ double h, g;
+
+ h = exp(xy.x / P->opaque->esp);
+ g = .5 * (h - 1. / h);
+ h = cos (P->phi0 + xy.y / P->opaque->esp);
+ lp.phi = asin(sqrt((1. - h * h) / (1. + g * g)));
+ if (xy.y < 0.) lp.phi = -lp.phi;
+ lp.lam = (g || h) ? atan2 (g, h) : 0.;
+ return lp;
+}
+
+
+static void *freeup_new (PJ *P) { /* Destructor */
+ if (0==P)
+ return 0;
+ if (0==P->opaque)
+ return pj_dealloc (P);
+ pj_dealloc (P->opaque->en);
+ pj_dealloc (P->opaque);
+ return pj_dealloc(P);
}
-INVERSE(e_inverse); /* ellipsoid */
- double n, con, cosphi, d, ds, sinphi, t;
-
- lp.phi = pj_inv_mlfn(P->ctx, P->ml0 + xy.y / P->k0, P->es, P->en);
- if (fabs(lp.phi) >= HALFPI) {
- lp.phi = xy.y < 0. ? -HALFPI : HALFPI;
- lp.lam = 0.;
- } else {
- sinphi = sin(lp.phi);
- cosphi = cos(lp.phi);
- t = fabs(cosphi) > 1e-10 ? sinphi/cosphi : 0.;
- n = P->esp * cosphi * cosphi;
- d = xy.x * sqrt(con = 1. - P->es * sinphi * sinphi) / P->k0;
- con *= t;
- t *= t;
- ds = d * d;
- lp.phi -= (con * ds / (1.-P->es)) * FC2 * (1. -
- ds * FC4 * (5. + t * (3. - 9. * n) + n * (1. - 4 * n) -
- ds * FC6 * (61. + t * (90. - 252. * n +
- 45. * t) + 46. * n
- - ds * FC8 * (1385. + t * (3633. + t * (4095. + 1574. * t)) )
- )));
- lp.lam = d*(FC1 -
- ds*FC3*( 1. + 2.*t + n -
- ds*FC5*(5. + t*(28. + 24.*t + 8.*n) + 6.*n
- - ds * FC7 * (61. + t * (662. + t * (1320. + 720. * t)) )
- ))) / cosphi;
- }
- return (lp);
+
+static void freeup (PJ *P) {
+ freeup_new (P);
+ return;
}
-INVERSE(s_inverse); /* sphere */
- double h, g;
-
- h = exp(xy.x / aks0);
- g = .5 * (h - 1. / h);
- h = cos(P->phi0 + xy.y / aks0);
- lp.phi = asin(sqrt((1. - h * h) / (1. + g * g)));
- if (xy.y < 0.) lp.phi = -lp.phi;
- lp.lam = (g || h) ? atan2(g, h) : 0.;
- return (lp);
+
+static PJ *setup(PJ *P) { /* general initialization */
+ struct pj_opaque *Q = P->opaque;
+ if (P->es) {
+ if (!(Q->en = pj_enfn(P->es)))
+ E_ERROR_0;
+ Q->ml0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), Q->en);
+ Q->esp = P->es / (1. - P->es);
+ P->inv = e_inverse;
+ P->fwd = e_forward;
+ } else {
+ Q->esp = P->k0;
+ Q->ml0 = .5 * Q->esp;
+ P->inv = s_inverse;
+ P->fwd = s_forward;
+ }
+ return P;
}
-FREEUP;
- if (P) {
- if (P->en)
- pj_dalloc(P->en);
- pj_dalloc(P);
- }
+
+
+PJ *PROJECTION(tmerc) {
+ struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
+ if (0==Q)
+ return freeup_new (P);
+ P->opaque = Q;
+ return setup(P);
}
- static PJ *
-setup(PJ *P) { /* general initialization */
- if (P->es) {
- if (!(P->en = pj_enfn(P->es)))
- E_ERROR_0;
- P->ml0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), P->en);
- P->esp = P->es / (1. - P->es);
- P->inv = e_inverse;
- P->fwd = e_forward;
- } else {
- aks0 = P->k0;
- aks5 = .5 * aks0;
- P->inv = s_inverse;
- P->fwd = s_forward;
- }
- return P;
+
+
+#ifdef PJ_OMIT_SELFTEST
+int pj_tmerc_selftest (void) {return 0;}
+#else
+int pj_tmerc_selftest (void) {
+ double tolerance_lp = 1e-10;
+ double tolerance_xy = 1e-7;
+
+ char e_args[] = {"+proj=tmerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"};
+ char s_args[] = {"+proj=tmerc +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"};
+
+ LP fwd_in[] = {
+ { 2, 1},
+ { 2,-1},
+ {-2, 1},
+ {-2,-1}
+ };
+
+ XY e_fwd_expect[] = {
+ { 222650.79679577847, 110642.22941192707},
+ { 222650.79679577847, -110642.22941192707},
+ {-222650.79679577847, 110642.22941192707},
+ {-222650.79679577847, -110642.22941192707},
+ };
+
+ XY s_fwd_expect[] = {
+ { 223413.46640632232, 111769.14504059685},
+ { 223413.46640632232, -111769.14504059685},
+ {-223413.46640632208, 111769.14504059685},
+ {-223413.46640632208, -111769.14504059685},
+ };
+
+ XY inv_in[] = {
+ { 200, 100},
+ { 200,-100},
+ {-200, 100},
+ {-200,-100}
+ };
+
+ LP e_inv_expect[] = {
+ { 0.0017966305681649396, 0.00090436947663183841},
+ { 0.0017966305681649396, -0.00090436947663183841},
+ {-0.0017966305681649396, 0.00090436947663183841},
+ {-0.0017966305681649396, -0.00090436947663183841},
+ };
+
+ LP s_inv_expect[] = {
+ { 0.0017904931097048034, 0.00089524670602767842},
+ { 0.0017904931097048034, -0.00089524670602767842},
+ {-0.001790493109714345, 0.00089524670602767842},
+ {-0.001790493109714345, -0.00089524670602767842},
+ };
+
+ 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);
}
-ENTRY1(tmerc, en)
-ENDENTRY(setup(P))
+#endif
diff --git a/src/PJ_tpeqd.c b/src/PJ_tpeqd.c
index 4ab5cf4e..182f23a5 100644
--- a/src/PJ_tpeqd.c
+++ b/src/PJ_tpeqd.c
@@ -1,76 +1,177 @@
-#define PROJ_PARMS__ \
- double cp1, sp1, cp2, sp2, ccs, cs, sc, r2z0, z02, dlam2; \
- double hz0, thz0, rhshz0, ca, sa, lp, lamc;
#define PJ_LIB__
#include <projects.h>
+
+
PROJ_HEAD(tpeqd, "Two Point Equidistant")
"\n\tMisc Sph\n\tlat_1= lon_1= lat_2= lon_2=";
-FORWARD(s_forward); /* sphere */
+
+struct pj_opaque {
+ double cp1, sp1, cp2, sp2, ccs, cs, sc, r2z0, z02, dlam2; \
+ double hz0, thz0, rhshz0, ca, sa, lp, lamc;
+};
+
+
+static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
+ XY xy = {0.0, 0.0};
+ struct pj_opaque *Q = P->opaque;
double t, z1, z2, dl1, dl2, sp, cp;
sp = sin(lp.phi);
cp = cos(lp.phi);
- z1 = aacos(P->ctx,P->sp1 * sp + P->cp1 * cp * cos(dl1 = lp.lam + P->dlam2));
- z2 = aacos(P->ctx,P->sp2 * sp + P->cp2 * cp * cos(dl2 = lp.lam - P->dlam2));
+ z1 = aacos(P->ctx, Q->sp1 * sp + Q->cp1 * cp * cos (dl1 = lp.lam + Q->dlam2));
+ z2 = aacos(P->ctx, Q->sp2 * sp + Q->cp2 * cp * cos (dl2 = lp.lam - Q->dlam2));
z1 *= z1;
z2 *= z2;
- xy.x = P->r2z0 * (t = z1 - z2);
- t = P->z02 - t;
- xy.y = P->r2z0 * asqrt(4. * P->z02 * z2 - t * t);
- if ((P->ccs * sp - cp * (P->cs * sin(dl1) - P->sc * sin(dl2))) < 0.)
+
+ xy.x = Q->r2z0 * (t = z1 - z2);
+ t = Q->z02 - t;
+ xy.y = Q->r2z0 * asqrt (4. * Q->z02 * z2 - t * t);
+ if ((Q->ccs * sp - cp * (Q->cs * sin(dl1) - Q->sc * sin(dl2))) < 0.)
xy.y = -xy.y;
return xy;
}
-INVERSE(s_inverse); /* sphere */
+
+
+static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
+ LP lp = {0.0,0.0};
+ struct pj_opaque *Q = P->opaque;
double cz1, cz2, s, d, cp, sp;
- cz1 = cos(hypot(xy.y, xy.x + P->hz0));
- cz2 = cos(hypot(xy.y, xy.x - P->hz0));
+ cz1 = cos (hypot(xy.y, xy.x + Q->hz0));
+ cz2 = cos (hypot(xy.y, xy.x - Q->hz0));
s = cz1 + cz2;
d = cz1 - cz2;
- lp.lam = - atan2(d, (s * P->thz0));
- lp.phi = aacos(P->ctx,hypot(P->thz0 * s, d) * P->rhshz0);
+ lp.lam = - atan2(d, (s * Q->thz0));
+ lp.phi = aacos(P->ctx, hypot (Q->thz0 * s, d) * Q->rhshz0);
if ( xy.y < 0. )
lp.phi = - lp.phi;
/* lam--phi now in system relative to P1--P2 base equator */
- sp = sin(lp.phi);
- cp = cos(lp.phi);
- lp.phi = aasin(P->ctx,P->sa * sp + P->ca * cp * (s = cos(lp.lam -= P->lp)));
- lp.lam = atan2(cp * sin(lp.lam), P->sa * cp * s - P->ca * sp) + P->lamc;
+ sp = sin (lp.phi);
+ cp = cos (lp.phi);
+ lp.phi = aasin (P->ctx, Q->sa * sp + Q->ca * cp * (s = cos(lp.lam -= Q->lp)));
+ lp.lam = atan2 (cp * sin(lp.lam), Q->sa * cp * s - Q->ca * sp) + Q->lamc;
return lp;
}
-FREEUP; if (P) pj_dalloc(P); }
-ENTRY0(tpeqd)
+
+
+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(tpeqd) {
double lam_1, lam_2, phi_1, phi_2, A12, pp;
+ struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
+ if (0==Q)
+ return freeup_new (P);
+ P->opaque = Q;
+
/* get control point locations */
phi_1 = pj_param(P->ctx, P->params, "rlat_1").f;
lam_1 = pj_param(P->ctx, P->params, "rlon_1").f;
phi_2 = pj_param(P->ctx, P->params, "rlat_2").f;
lam_2 = pj_param(P->ctx, P->params, "rlon_2").f;
- if (phi_1 == phi_2 && lam_1 == lam_2) E_ERROR(-25);
- P->lam0 = adjlon(0.5 * (lam_1 + lam_2));
- P->dlam2 = adjlon(lam_2 - lam_1);
- P->cp1 = cos(phi_1);
- P->cp2 = cos(phi_2);
- P->sp1 = sin(phi_1);
- P->sp2 = sin(phi_2);
- P->cs = P->cp1 * P->sp2;
- P->sc = P->sp1 * P->cp2;
- P->ccs = P->cp1 * P->cp2 * sin(P->dlam2);
- P->z02 = aacos(P->ctx,P->sp1 * P->sp2 + P->cp1 * P->cp2 * cos(P->dlam2));
- P->hz0 = .5 * P->z02;
- A12 = atan2(P->cp2 * sin(P->dlam2),
- P->cp1 * P->sp2 - P->sp1 * P->cp2 * cos(P->dlam2));
- P->ca = cos(pp = aasin(P->ctx,P->cp1 * sin(A12)));
- P->sa = sin(pp);
- P->lp = adjlon(atan2(P->cp1 * cos(A12), P->sp1) - P->hz0);
- P->dlam2 *= .5;
- P->lamc = HALFPI - atan2(sin(A12) * P->sp1, cos(A12)) - P->dlam2;
- P->thz0 = tan(P->hz0);
- P->rhshz0 = .5 / sin(P->hz0);
- P->r2z0 = 0.5 / P->z02;
- P->z02 *= P->z02;
- P->inv = s_inverse; P->fwd = s_forward;
+
+ if (phi_1 == phi_2 && lam_1 == lam_2)
+ E_ERROR(-25);
+ P->lam0 = adjlon (0.5 * (lam_1 + lam_2));
+ Q->dlam2 = adjlon (lam_2 - lam_1);
+
+ Q->cp1 = cos (phi_1);
+ Q->cp2 = cos (phi_2);
+ Q->sp1 = sin (phi_1);
+ Q->sp2 = sin (phi_2);
+ Q->cs = Q->cp1 * Q->sp2;
+ Q->sc = Q->sp1 * Q->cp2;
+ Q->ccs = Q->cp1 * Q->cp2 * sin(Q->dlam2);
+ Q->z02 = aacos(P->ctx, Q->sp1 * Q->sp2 + Q->cp1 * Q->cp2 * cos (Q->dlam2));
+ Q->hz0 = .5 * Q->z02;
+ A12 = atan2(Q->cp2 * sin (Q->dlam2),
+ Q->cp1 * Q->sp2 - Q->sp1 * Q->cp2 * cos (Q->dlam2));
+ Q->ca = cos(pp = aasin(P->ctx, Q->cp1 * sin(A12)));
+ Q->sa = sin(pp);
+ Q->lp = adjlon ( atan2 (Q->cp1 * cos(A12), Q->sp1) - Q->hz0);
+ Q->dlam2 *= .5;
+ Q->lamc = HALFPI - atan2(sin(A12) * Q->sp1, cos(A12)) - Q->dlam2;
+ Q->thz0 = tan (Q->hz0);
+ Q->rhshz0 = .5 / sin (Q->hz0);
+ Q->r2z0 = 0.5 / Q->z02;
+ Q->z02 *= Q->z02;
+
+ P->inv = s_inverse;
+ P->fwd = s_forward;
P->es = 0.;
-ENDENTRY(P)
+
+ return P;
+}
+
+
+#ifdef PJ_OMIT_SELFTEST
+int pj_tpeqd_selftest (void) {return 0;}
+#else
+
+int pj_tpeqd_selftest (void) {
+ double tolerance_lp = 1e-10;
+ double tolerance_xy = 1e-7;
+
+ char e_args[] = {"+proj=tpeqd +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"};
+ char s_args[] = {"+proj=tpeqd +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"};
+
+ LP fwd_in[] = {
+ { 2, 1},
+ { 2,-1},
+ {-2, 1},
+ {-2,-1}
+ };
+
+ XY e_fwd_expect[] = {
+ {-27750.758831679042, -222599.40369177726},
+ {-250434.93702403645, -222655.93819326628},
+ {-27750.758831679042, 222599.40369177726},
+ {-250434.93702403645, 222655.93819326628},
+ };
+
+ XY s_fwd_expect[] = {
+ {-27845.882978485075, -223362.43069526015},
+ {-251293.37876465076, -223419.15898590829},
+ {-27845.882978485075, 223362.43069526015},
+ {-251293.37876465076, 223419.15898590829},
+ };
+
+ XY inv_in[] = {
+ { 200, 100},
+ { 200,-100},
+ {-200, 100},
+ {-200,-100}
+ };
+
+ LP e_inv_expect[] = {
+ {-0.00089855554821257374, 1.2517966304145272},
+ {0.0008985555481998515, 1.2517966304145272},
+ {-0.00089855431859741167, 1.2482033692781642},
+ {0.00089855431859741167, 1.2482033692781642},
+ };
+
+ LP s_inv_expect[] = {
+ {-0.00089548606640108474, 1.2517904929571837},
+ {0.0008954860663883625, 1.2517904929571837},
+ {-0.000895484845182587, 1.248209506737604},
+ {0.00089548484516986475, 1.248209506737604},
+ };
+
+ 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_urm5.c b/src/PJ_urm5.c
index 9159df65..7a759b07 100644
--- a/src/PJ_urm5.c
+++ b/src/PJ_urm5.c
@@ -1,28 +1,81 @@
-#define PROJ_PARMS__ \
- double m, rmn, q3, n;
#define PJ_LIB__
-# include <projects.h>
+#include <projects.h>
+
PROJ_HEAD(urm5, "Urmaev V") "\n\tPCyl., Sph., no inv.\n\tn= q= alpha=";
-FORWARD(s_forward); /* spheroid */
- double t;
-
- t = lp.phi = aasin(P->ctx,P->n * sin(lp.phi));
- xy.x = P->m * lp.lam * cos(lp.phi);
- t *= t;
- xy.y = lp.phi * (1. + t * P->q3) * P->rmn;
- return xy;
+
+struct pj_opaque {
+ double m, rmn, q3, n;
+};
+
+
+static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
+ XY xy = {0.0, 0.0};
+ struct pj_opaque *Q = P->opaque;
+ double t;
+
+ t = lp.phi = aasin (P->ctx, Q->n * sin (lp.phi));
+ xy.x = Q->m * lp.lam * cos (lp.phi);
+ t *= t;
+ xy.y = lp.phi * (1. + t * Q->q3) * Q->rmn;
+ return xy;
+}
+
+
+static void *freeup_new (PJ *P) { /* Destructor */
+ return pj_dealloc(P);
+}
+
+static void freeup (PJ *P) {
+ freeup_new (P);
+ return;
+}
+
+
+PJ *PROJECTION(urm5) {
+ double alpha, t;
+ struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
+ if (0==Q)
+ return freeup_new (P);
+ P->opaque = Q;
+
+ Q->n = pj_param(P->ctx, P->params, "dn").f;
+ Q->q3 = pj_param(P->ctx, P->params, "dq").f / 3.;
+ alpha = pj_param(P->ctx, P->params, "ralpha").f;
+ t = Q->n * sin (alpha);
+ Q->m = cos (alpha) / sqrt (1. - t * t);
+ Q->rmn = 1. / (Q->m * Q->n);
+
+ P->es = 0.;
+ P->inv = 0;
+ P->fwd = s_forward;
+
+ return P;
+}
+
+
+#ifdef PJ_OMIT_SELFTEST
+int pj_urm5_selftest (void) {return 0;}
+#else
+int pj_urm5_selftest (void) {
+ double tolerance_lp = 1e-10;
+ double tolerance_xy = 1e-7;
+
+ char s_args[] = {"+proj=urm5 +a=6400000 +lat_1=0.5 +lat_2=2"};
+
+ LP fwd_in[] = {
+ { 2, 1},
+ { 2,-1},
+ {-2, 1},
+ {-2,-1}
+ };
+
+ XY s_fwd_expect[] = {
+ { 223393.6384339639, 111696.81878511712},
+ { 223393.6384339639, -111696.81878511712},
+ {-223393.6384339639, 111696.81878511712},
+ {-223393.6384339639, -111696.81878511712},
+ };
+
+ 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(urm5)
- double alpha, t;
-
- P->n = pj_param(P->ctx, P->params, "dn").f;
- P->q3 = pj_param(P->ctx, P->params, "dq").f / 3.;
- alpha = pj_param(P->ctx, P->params, "ralpha").f;
- t = P->n * sin(alpha);
- P->m = cos(alpha) / sqrt(1. - t * t);
- P->rmn = 1. / (P->m * P->n);
- P->es = 0.;
- P->inv = 0;
- P->fwd = s_forward;
-ENDENTRY(P)
+#endif
diff --git a/src/PJ_urmfps.c b/src/PJ_urmfps.c
index 5c5918ae..2322aa04 100644
--- a/src/PJ_urmfps.c
+++ b/src/PJ_urmfps.c
@@ -1,40 +1,166 @@
-#define PROJ_PARMS__ \
- double n, C_y;
#define PJ_LIB__
#include <projects.h>
+
PROJ_HEAD(urmfps, "Urmaev Flat-Polar Sinusoidal") "\n\tPCyl, Sph.\n\tn=";
PROJ_HEAD(wag1, "Wagner I (Kavraisky VI)") "\n\tPCyl, Sph.";
+
+struct pj_opaque {
+ double n, C_y;
+};
+
#define C_x 0.8773826753
#define Cy 1.139753528477
-FORWARD(s_forward); /* sphere */
- lp.phi = aasin(P->ctx,P->n * sin(lp.phi));
- xy.x = C_x * lp.lam * cos(lp.phi);
- xy.y = P->C_y * lp.phi;
- return (xy);
-}
-INVERSE(s_inverse); /* sphere */
- xy.y /= P->C_y;
- lp.phi = aasin(P->ctx,sin(xy.y) / P->n);
- lp.lam = xy.x / (C_x * cos(xy.y));
- return (lp);
-}
-FREEUP; if (P) pj_dalloc(P); }
- static PJ *
-setup(PJ *P) {
- P->C_y = Cy / P->n;
+
+
+static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
+ XY xy = {0.0, 0.0};
+ lp.phi = aasin (P->ctx,P->opaque->n * sin (lp.phi));
+ xy.x = C_x * lp.lam * cos (lp.phi);
+ xy.y = P->opaque->C_y * lp.phi;
+ return xy;
+}
+
+
+static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
+ LP lp = {0.0, 0.0};
+ xy.y /= P->opaque->C_y;
+ lp.phi = aasin(P->ctx, sin (xy.y) / P->opaque->n);
+ lp.lam = xy.x / (C_x * cos (xy.y));
+ return lp;
+}
+
+
+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;
+}
+
+static PJ *setup(PJ *P) {
+ P->opaque->C_y = Cy / P->opaque->n;
P->es = 0.;
P->inv = s_inverse;
P->fwd = s_forward;
return P;
}
-ENTRY0(urmfps)
+
+
+PJ *PROJECTION(urmfps) {
+ struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
+ if (0==Q)
+ return freeup_new (P);
+ P->opaque = Q;
+
if (pj_param(P->ctx, P->params, "tn").i) {
- P->n = pj_param(P->ctx, P->params, "dn").f;
- if (P->n <= 0. || P->n > 1.)
+ P->opaque->n = pj_param(P->ctx, P->params, "dn").f;
+ if (P->opaque->n <= 0. || P->opaque->n > 1.)
E_ERROR(-40)
} else
E_ERROR(-40)
-ENDENTRY(setup(P))
-ENTRY0(wag1)
- P->n = 0.8660254037844386467637231707;
-ENDENTRY(setup(P))
+
+ return setup(P);
+}
+
+
+PJ *PROJECTION(wag1) {
+ struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
+ if (0==Q)
+ return freeup_new (P);
+ P->opaque = Q;
+
+ P->opaque->n = 0.8660254037844386467637231707;
+ return setup(P);
+}
+
+
+#ifdef PJ_OMIT_SELFTEST
+int pj_urmfps_selftest (void) {return 0;}
+#else
+int pj_urmfps_selftest (void) {
+ double tolerance_lp = 1e-10;
+ double tolerance_xy = 1e-7;
+
+ char s_args[] = {"+proj=urmfps +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"};
+
+ LP fwd_in[] = {
+ { 2, 1},
+ { 2,-1},
+ {-2, 1},
+ {-2,-1}
+ };
+
+ XY s_fwd_expect[] = {
+ { 196001.70813419219, 127306.84332999329},
+ { 196001.70813419219, -127306.84332999329},
+ {-196001.70813419219, 127306.84332999329},
+ {-196001.70813419219, -127306.84332999329},
+ };
+
+ XY inv_in[] = {
+ { 200, 100},
+ { 200,-100},
+ {-200, 100},
+ {-200,-100}
+ };
+
+ LP s_inv_expect[] = {
+ { 0.002040720839642371, 0.00078547381740438178},
+ { 0.002040720839642371, -0.00078547381740438178},
+ {-0.002040720839642371, 0.00078547381740438178},
+ {-0.002040720839642371, -0.00078547381740438178},
+ };
+
+ 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
+
+
+#ifdef PJ_OMIT_SELFTEST
+int pj_wag1_selftest (void) {return 0;}
+#else
+int pj_wag1_selftest (void) {
+ double tolerance_lp = 1e-10;
+ double tolerance_xy = 1e-7;
+
+ char s_args[] = {"+proj=wag1 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"};
+
+ LP fwd_in[] = {
+ { 2, 1},
+ { 2,-1},
+ {-2, 1},
+ {-2,-1}
+ };
+
+ XY s_fwd_expect[] = {
+ { 195986.78156115755, 127310.07506065986},
+ { 195986.78156115755, -127310.07506065986},
+ {-195986.78156115755, 127310.07506065986},
+ {-195986.78156115755, -127310.07506065986},
+ };
+
+ XY inv_in[] = {
+ { 200, 100},
+ { 200,-100},
+ {-200, 100},
+ {-200,-100}
+ };
+
+ LP s_inv_expect[] = {
+ { 0.002040720839738254, 0.00078547381739207999},
+ { 0.002040720839738254, -0.00078547381739207999},
+ {-0.002040720839738254, 0.00078547381739207999},
+ {-0.002040720839738254, -0.00078547381739207999},
+ };
+
+ 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_generic_selftest.c b/src/pj_generic_selftest.c
index 5ac239e2..2af3f3b9 100644
--- a/src/pj_generic_selftest.c
+++ b/src/pj_generic_selftest.c
@@ -145,11 +145,15 @@ static int deviates_xy (XY expected, XY got, double tolerance) {
Determine whether two XYs deviate by more than <tolerance>.
+ The test material ("expected" values) may contain coordinates that
+ are indeterminate. For those cases, we test the other coordinate
+ only by forcing expected and actual ("got") coordinates to 0.
+
***********************************************************************/
- if (HUGE_VAL== expected.x)
- return 0;
- if (HUGE_VAL== expected.y)
- return 0;
+ if ((HUGE_VAL== expected.x) || (isnan (expected.x)))
+ expected.x = got.x = 0;
+ if ((HUGE_VAL== expected.y) || (isnan (expected.y)))
+ expected.y = got.y = 0;
if (hypot ( expected.x - got.x, expected.y - got.y ) > tolerance)
return 1;
return 0;
@@ -169,10 +173,10 @@ static int deviates_lp (LP expected, LP got, double tolerance) {
output from pj_inv)
***********************************************************************/
- if (HUGE_VAL== expected.lam)
- return 0;
- if (HUGE_VAL== expected.phi)
- return 0;
+ if ((HUGE_VAL== expected.lam) || (isnan (expected.lam)))
+ expected.lam = got.lam = 0;
+ if ((HUGE_VAL== expected.phi) || (isnan (expected.phi)))
+ expected.phi = got.phi = 0;
if (hypot ( DEG_TO_RAD * expected.lam - got.lam, DEG_TO_RAD * expected.phi - got.phi ) > tolerance)
return 1;
return 0;