package ca.bc.coordsys.impl;
import ca.bc.coordsys.Geographic;
import ca.bc.coordsys.Planar;
import ca.bc.coordsys.Projection;
/**
* Implements the Albers projection.
*
*/
public class Albers extends Projection {
double L0;// central meridian
double k0;// scale factor
double phi1;// 1st standard parallel
double phi2;// 2nd standard parallel
double phi0;// Latitude of projection
double X0;// false Easting
double Y0;// false Northing
double A_n, A_C, A_p0;// variables for Albers, see constructor
Geographic q = new Geographic();
public Albers() {
super();
}
public void setParameters(double centralMeridian,
double firstStandardParallel,
double secondStandardParallel,
double latitudeOfProjection,
double falseEasting,
double falseNorthing) {
L0 = centralMeridian * Math.PI / 180.0;
phi1 = firstStandardParallel * Math.PI / 180.0;
phi2 = secondStandardParallel * Math.PI / 180.0;
phi0 = latitudeOfProjection * Math.PI / 180.0;
X0 = falseEasting;
Y0 = falseNorthing;
double m1;
double m2;
double q1;
double q2;
double q0;
m1 = albersM(phi1);
m2 = albersM(phi2);
q1 = albersQ(phi1);
q2 = albersQ(phi2);
q0 = albersQ(phi0);
A_n = (m1 * m1 - m2 * m2) / (q2 - q1);
A_C = m1 * m1 + A_n * q1;
double a;
a = currentSpheroid.getA();
A_p0 = (a * Math.sqrt(A_C - A_n * q0)) / A_n;
}// END - constructor for Albers projection plane
public Planar asPlanar(Geographic q0, Planar p) {
q.lat = q0.lat / 180.0 * Math.PI;
q.lon = q0.lon / 180.0 * Math.PI;
forward(q, p);
return p;
}
public Geographic asGeographic(Planar p, Geographic q) {
inverse(p, q);
q.lat = q.lat * 180.0 / Math.PI;
q.lon = q.lon * 180.0 / Math.PI;
return q;
}
void forward(Geographic q, Planar p) {
double que;
double theta;
double pee;
double a;
a = currentSpheroid.getA();
que = albersQ(q.lat);
theta = A_n * (q.lon - L0);
pee = (a * Math.sqrt(A_C - A_n * que)) / A_n;
p.x = pee * Math.sin(theta) + X0;
p.y = A_p0 - pee * Math.cos(theta) + Y0;
}
void inverse(Planar p, Geographic q) {
double es;
double x;
double y;
double theta;
double pee;
double que;
double a;
double e;
a = currentSpheroid.getA();
e = currentSpheroid.getE();
es = e * e;
x = p.x - X0;
y = p.y - Y0;
theta = Math.atan2(x, A_p0 - y);
pee = Math.sqrt(x * x + Math.pow((A_p0 - y), 2.0));
que = (A_C - (pee * pee * A_n * A_n) / (a * a)) / A_n;
q.lon = L0 + theta / A_n;
double li;
double delta;
double j1;
double k1;
double k2;
double k3;
double lip1;
//li = Math.sin(que / 2.0); -- transcription error
li = Math.asin(que / 2.0);
delta = 10e010;
do {
j1 = Math.pow((1.0 - es * Math.pow(Math.sin(li), 2.0)), 2.0) / (2.0 * Math.cos(li));
k1 = que / (1.0 - es);
k2 = Math.sin(li) / (1.0 - es * Math.pow(Math.sin(li), 2.0));
k3 = (1.0 / (2.0 * e)) * Math.log((1.0 - e * Math.sin(li)) / (1.0 + e * Math.sin(li)));
lip1 = li + j1 * (k1 - k2 + k3);
delta = Math.abs(lip1 - li);
li = lip1;
} while (delta > 1.0e-012);
q.lat = li;
}
double albersQ(double lat) {
double q;
double e;
e = currentSpheroid.getE();
q = (1.0 - e * e) * (Math.sin(lat) / (1.0 - e * e * Math.pow(Math.sin(lat), 2.0))
- (1.0 / (2.0 * e)) * Math.log((1.0 - e * Math.sin(lat)) / (1.0 + e * Math.sin(lat))));
return q;
}
double albersM(double lat) {
double m;
double e;
e = currentSpheroid.getE();
m = Math.cos(lat) / Math.sqrt(1.0 - e * e * Math.pow(Math.sin(lat), 2.0));
return m;
}
}