package ca.bc.coordsys.impl; import ca.bc.coordsys.Geographic; import ca.bc.coordsys.Planar; import ca.bc.coordsys.Projection; /** * Implements the Polyconic projection. * * */ public class Polyconic extends Projection { // private: 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 int zone;// UTMzone MeridianArcLength S = new MeridianArcLength(); Geographic q = new Geographic(); public Polyconic() { super(); } public void setParameters(double originLatitude, double originLongitude) { // Polyconic projection L0 = originLongitude / 180.0 * Math.PI; phi0 = originLatitude / 180.0 * Math.PI; } 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; } public void forward(Geographic q, Planar p) { double M; double M0; S.compute(currentSpheroid, q.lat, 0); M = S.s; S.compute(currentSpheroid, phi0, 0); M0 = S.s; double a; double e; double e2; a = currentSpheroid.a; e = currentSpheroid.e; e2 = e * e; double N; double t; t = Math.sin(q.lat); N = a / Math.sqrt(1.0 - e2 * t * t); double E; E = (q.lon - L0) * Math.sin(q.lat); t = 1.0 / Math.tan(q.lat); p.x = N * t * Math.sin(E); p.y = M - M0 + N * t * (1.0 - Math.cos(E)); } public void inverse(Planar p, Geographic q) { double a; double e; double es; a = currentSpheroid.getA(); e = currentSpheroid.getE(); es = e * e; double A; double B; double M0; S.compute(currentSpheroid, phi0, 0); M0 = S.s; A = (M0 + p.y) / a; B = (p.x * p.x) / (a * a) + A * A; double C; double phiN; double M; double Mp; double Ma; double Ma2; double s2p; q.lat = A; int count = 0; do { phiN = q.lat; C = Math.sqrt(1.0 - es * Math.sin(phiN) * Math.sin(phiN)) * Math.tan(phiN); S.compute(currentSpheroid, phiN, 0); M = S.s; Ma = M / a; Ma2 = Ma * Ma; S.compute(currentSpheroid, phiN, 1); Mp = S.s; s2p = Math.sin(2.0 * phiN); q.lat = q.lat - (A * (C * Ma + 1.0) - Ma - 0.5 * (Ma2 + B) * C) / (es * s2p * (Ma2 + B - 2.0 * A * Ma) / 4.0 * C + (A - Ma) * (C * Mp - 2.0 / s2p) - Mp); } while (Math.abs(q.lat - phiN) > 1.0e-6 && count++ < 100);//1.0e-12); q.lon = Math.asin(p.x * C / a) / Math.sin(q.lat) + L0; } }