// Cart_2_Proj.java
// This class performs one conversion and one map projection
// Cartesian coordinates ---(conversion)---> ellipsoidal coordinates
// ---(projection)---> grid coordinates.

public class Cart_2_Proj extends Cart_2_Geod
{
   protected double Lat0, Long0;   // origin of projection
   protected double N0, E0;   // grid coord. of origin
   protected double M0;   // scale factor along the central meridian
   protected double a0, a2, a4, a6;
   protected double BM0;   // meridian distance of the origin
   public double northing, easting;   // northing and easting of a point
   
   // constructor fetch the projection parameters
   public Cart_2_Proj(double aa, double e2, double lat, double long1,
                      double n, double e, double m)
   {
      super( aa, e2);
      Lat0 = lat;
      Long0 = long1;
      N0 = n;
      E0 = e;
      M0 = m;
      
      a0 = 1.0 - ee/4.0 - 3*ee*ee/64.0 - 5.0*ee*ee*ee/256.0;
      a2 = 3.0/8.0*(ee + ee*ee/4.0 + 15.0*ee*ee*ee/128.0);
      a4 = 15.0/256.0*(ee*ee + 3.0*ee*ee*ee/4.0);
      a6 = 35.0*ee*ee*ee/3072.0;
      BM0 = M_dist(Lat0);
   }
   
   protected double M_dist(double lat)
   {
      return a*(a0*lat - a2*Math.sin(2*lat) + a4*Math.sin(4*lat) - a6*Math.sin(6*lat));
   }
   
   public void compute_grid()
   {
      double dlong;   // longtitude measured from central meridian
      double p;   // radius of curvature in the meridian
      double phi;   // isometric latitude
      double t;   // tan(Lat)
      double BM;   // meridian distance
      double N;
      
      dlong = Math.abs(Long - Long0);
      N = curvature(Lat);
      p = a*(1.0-ee)/Math.exp(Math.log(1.0-ee*Math.pow(Math.sin(Lat),2))*3.0/2.0);
      phi = N/p;
      t = Math.tan(Lat);
      BM = M_dist(Lat);
      
      // begin computing the Northing
      northing = BM - BM0 + N*Math.sin(Lat)*Math.pow(dlong,2.0)/2.0*Math.cos(Lat);
      northing = northing + N*Math.sin(Lat)*Math.pow(dlong,4.0)/24.0*Math.pow(Math.cos(Lat),3.0)
                 *(4.0*phi*phi + phi - t*t);
      northing = northing + N*Math.sin(Lat)*Math.pow(dlong,6.0)/720.0*Math.pow(Math.cos(Lat),5.0)
                 *(8.0*Math.pow(phi,4.0)*(11.0 - 24.0*t*t) - 28*Math.pow(phi,3.0)*(1.0 - 6.0*t*t)
                 + phi*phi*(1.0 - 32.0*t*t) - 2.0*phi*t*t + Math.pow(t,4.0));
      northing = northing + N*Math.sin(Lat)*Math.pow(dlong,8)/40320.0*Math.pow(Math.cos(Lat),7.0)
                 *(1385.0 - 3111.0*t*t + 543.0*Math.pow(t,4.0) - Math.pow(t,6));
      northing = N0 + M0 * northing;
      
      // begin computing the Easting
      easting = N * dlong * Math.cos(Lat);
      easting = easting + N*Math.pow(dlong,3)/6.0*Math.pow(Math.cos(Lat),3)*(phi - t*t);
      easting = easting + N*Math.pow(dlong,5)/120*Math.pow(Math.cos(Lat),5)
                *(4*Math.pow(phi,3)*(1.0-6.0*t*t) + phi*phi*(1.0+8.0*t*t) - phi*2.0*t*t + Math.pow(t,4));
      easting = easting + N*Math.pow(dlong,7)/5040.0*Math.pow(Math.cos(Lat),7)
                *(61.0 - 479.0*t*t + 179.0*Math.pow(t,4) - Math.pow(t,6));
      easting = E0 + M0 * easting;
      // that's all...
      // ...far from over!!!
  }
}  // end of Cart_2_Proj.java
