aboutsummaryrefslogtreecommitdiff
path: root/src/PJ_sconics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/PJ_sconics.cpp')
-rw-r--r--src/PJ_sconics.cpp216
1 files changed, 216 insertions, 0 deletions
diff --git a/src/PJ_sconics.cpp b/src/PJ_sconics.cpp
new file mode 100644
index 00000000..4efec86f
--- /dev/null
+++ b/src/PJ_sconics.cpp
@@ -0,0 +1,216 @@
+#define PJ_LIB__
+#include <errno.h>
+#include "proj.h"
+#include "projects.h"
+#include "proj_math.h"
+
+
+enum Type {
+ EULER = 0,
+ MURD1 = 1,
+ MURD2 = 2,
+ MURD3 = 3,
+ PCONIC = 4,
+ TISSOT = 5,
+ VITK1 = 6
+};
+
+struct pj_opaque {
+ double n;
+ double rho_c;
+ double rho_0;
+ double sig;
+ double c1, c2;
+ enum Type type;
+};
+
+
+#define EPS10 1.e-10
+#define EPS 1e-10
+#define LINE2 "\n\tConic, Sph\n\tlat_1= and lat_2="
+
+PROJ_HEAD(euler, "Euler") LINE2;
+PROJ_HEAD(murd1, "Murdoch I") LINE2;
+PROJ_HEAD(murd2, "Murdoch II") LINE2;
+PROJ_HEAD(murd3, "Murdoch III") LINE2;
+PROJ_HEAD(pconic, "Perspective Conic") LINE2;
+PROJ_HEAD(tissot, "Tissot") LINE2;
+PROJ_HEAD(vitk1, "Vitkovsky I") LINE2;
+
+
+
+/* get common factors for simple conics */
+static int phi12(PJ *P, double *del) {
+ double p1, p2;
+ int err = 0;
+
+ if (!pj_param(P->ctx, P->params, "tlat_1").i ||
+ !pj_param(P->ctx, P->params, "tlat_2").i) {
+ err = -41;
+ } else {
+ p1 = pj_param(P->ctx, P->params, "rlat_1").f;
+ p2 = pj_param(P->ctx, P->params, "rlat_2").f;
+ *del = 0.5 * (p2 - p1);
+ static_cast<struct pj_opaque*>(P->opaque)->sig = 0.5 * (p2 + p1);
+ err = (fabs(*del) < EPS || fabs(static_cast<struct pj_opaque*>(P->opaque)->sig) < EPS) ? PJD_ERR_ABS_LAT1_EQ_ABS_LAT2 : 0;
+ }
+ return err;
+}
+
+
+static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
+ XY xy = {0.0, 0.0};
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
+ double rho;
+
+ switch (Q->type) {
+ case MURD2:
+ rho = Q->rho_c + tan (Q->sig - lp.phi);
+ break;
+ case PCONIC:
+ rho = Q->c2 * (Q->c1 - tan (lp.phi - Q->sig));
+ break;
+ default:
+ rho = Q->rho_c - lp.phi;
+ break;
+ }
+
+ xy.x = rho * sin ( lp.lam *= Q->n );
+ xy.y = Q->rho_0 - rho * cos (lp.lam);
+ return xy;
+}
+
+
+static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, (and ellipsoidal?) inverse */
+ LP lp = {0.0, 0.0};
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
+ double rho;
+
+ rho = hypot (xy.x, xy.y = Q->rho_0 - xy.y);
+ if (Q->n < 0.) {
+ rho = - rho;
+ xy.x = - xy.x;
+ xy.y = - xy.y;
+ }
+
+ lp.lam = atan2 (xy.x, xy.y) / Q->n;
+
+ switch (Q->type) {
+ case PCONIC:
+ lp.phi = atan (Q->c1 - rho / Q->c2) + Q->sig;
+ break;
+ case MURD2:
+ lp.phi = Q->sig - atan(rho - Q->rho_c);
+ break;
+ default:
+ lp.phi = Q->rho_c - rho;
+ }
+ return lp;
+}
+
+
+static PJ *setup(PJ *P, enum Type type) {
+ double del, cs;
+ int err;
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ if (0==Q)
+ return pj_default_destructor (P, ENOMEM);
+ P->opaque = Q;
+ Q->type = type;
+
+ err = phi12 (P, &del);
+ if(err)
+ return pj_default_destructor (P, err);
+
+ switch (Q->type) {
+
+ case TISSOT:
+ Q->n = sin (Q->sig);
+ cs = cos (del);
+ Q->rho_c = Q->n / cs + cs / Q->n;
+ Q->rho_0 = sqrt ((Q->rho_c - 2 * sin (P->phi0)) / Q->n);
+ break;
+
+ case MURD1:
+ Q->rho_c = sin(del)/(del * tan(Q->sig)) + Q->sig;
+ Q->rho_0 = Q->rho_c - P->phi0;
+ Q->n = sin(Q->sig);
+ break;
+
+ case MURD2:
+ Q->rho_c = (cs = sqrt (cos (del))) / tan (Q->sig);
+ Q->rho_0 = Q->rho_c + tan (Q->sig - P->phi0);
+ Q->n = sin (Q->sig) * cs;
+ break;
+
+ case MURD3:
+ Q->rho_c = del / (tan(Q->sig) * tan(del)) + Q->sig;
+ Q->rho_0 = Q->rho_c - P->phi0;
+ Q->n = sin (Q->sig) * sin (del) * tan (del) / (del * del);
+ break;
+
+ case EULER:
+ Q->n = sin (Q->sig) * sin (del) / del;
+ del *= 0.5;
+ Q->rho_c = del / (tan (del) * tan (Q->sig)) + Q->sig;
+ Q->rho_0 = Q->rho_c - P->phi0;
+ break;
+
+ case PCONIC:
+ Q->n = sin (Q->sig);
+ Q->c2 = cos (del);
+ Q->c1 = 1./tan (Q->sig);
+ if (fabs (del = P->phi0 - Q->sig) - EPS10 >= M_HALFPI)
+ return pj_default_destructor(P, PJD_ERR_LAT_0_HALF_PI_FROM_MEAN);
+
+ Q->rho_0 = Q->c2 * (Q->c1 - tan (del));
+ break;
+
+ case VITK1:
+ Q->n = (cs = tan (del)) * sin (Q->sig) / del;
+ Q->rho_c = del / (cs * tan (Q->sig)) + Q->sig;
+ Q->rho_0 = Q->rho_c - P->phi0;
+ break;
+ }
+
+ P->inv = s_inverse;
+ P->fwd = s_forward;
+ P->es = 0;
+ return (P);
+}
+
+
+PJ *PROJECTION(euler) {
+ return setup(P, EULER);
+}
+
+
+PJ *PROJECTION(tissot) {
+ return setup(P, TISSOT);
+}
+
+
+PJ *PROJECTION(murd1) {
+ return setup(P, MURD1);
+}
+
+
+PJ *PROJECTION(murd2) {
+ return setup(P, MURD2);
+}
+
+
+PJ *PROJECTION(murd3) {
+ return setup(P, MURD3);
+}
+
+
+PJ *PROJECTION(pconic) {
+ return setup(P, PCONIC);
+}
+
+
+PJ *PROJECTION(vitk1) {
+ return setup(P, VITK1);
+}
+