PageRenderTime 15ms CodeModel.GetById 2ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/src/com/google/maps/extras/arcgislink/LambertConformalConic.as

http://gmaps-utility-library-flash.googlecode.com/
ActionScript | 128 lines | 87 code | 3 blank | 38 comment | 3 complexity | 37cd3273f0e36bda54853c737c72ce59 MD5 | raw file
  1/*
  2 * ArcGIS for Google Maps Flash API
  3 *
  4 * License http://www.apache.org/licenses/LICENSE-2.0
  5 */
  6 /**
  7 * @author nianwei at gmail dot com
  8 */ 
  9
 10package com.google.maps.extras.arcgislink
 11{
 12  /**
 13  * This class represents a Spatial Reference System based on <a target  = wiki href  = 'http://en.wikipedia.org/wiki/Lambert_conformal_conic_projection'>Lambert Conformal Conic Projection</a>. */
 14  public class LambertConformalConic extends SpatialReference
 15  {
 16    private var a_:Number;
 17    private var e_:Number;
 18    private var F_:Number;
 19    private var FE_:Number;
 20    private var lamdaF_:Number;
 21    private var n_:Number;
 22    private var rF_:Number;
 23    private var FN_:Number;
 24    
 25    /**
 26 * Create a Lambert Conformal Conic Projection based Spatial Reference. The <code>params</code> passed in construction should
 27 * include the following properties:<code>
 28 * <br/>-wkid: well-known id
 29 * <br/>-semi_major:  ellipsoidal semi-major axis in meter
 30 * <br/>-unit: meters per unit
 31 * <br/>-inverse_flattening: inverse of flattening of the ellipsoid where 1/f  =  a/(a - b)
 32 * <br/>-standard_parallel_1: phi1, latitude of the first standard parallel
 33 * <br/>-standard_parallel_2: phi2, latitude of the second standard parallel
 34 * <br/>-latitude_of_origin: phiF, latitude of the false origin
 35 * <br/>-central_meridian: lamdaF, longitude of the false origin  (with respect to the prime meridian)
 36 * <br/>-false_easting: FE, false easting, the Eastings value assigned to the natural origin
 37 * <br/>-false_northing: FN, false northing, the Northings value assigned to the natural origin
 38 * </code>
 39 * <br/> e.g. North Carolina State Plane NAD83 Feet: <br/>
 40 * <code> var ncsp82  = new ArcGISLambertConformalConic({wkid:2264, semi_major: 6378137.0,inverse_flattening: 298.257222101,
 41 *   standard_parallel_1: 34.33333333333334, standard_parallel_2: 36.16666666666666,
 42 *   central_meridian: -79.0, latitude_of_origin: 33.75,'false_easting': 2000000.002616666,
 43 *   'false_northing': 0, unit: 0.3048006096012192 }); </code>
 44 * @name ArcGISLambertConformalConic
 45 * @extends ArcGISSpatialReference
 46 * @constructor
 47 * @param {Object} params
 48 */
 49    public function LambertConformalConic(params:Object)
 50    {
 51     //http://pubs.er.usgs.gov/djvu/PP/PP_1395.pdf
 52     // http://www.posc.org/Epicentre.2_2/DataModel/ExamplesofUsage/eu_cs34.html
 53     //for NCSP83: GLatLng(35.102363,-80.5666)<  === > GPoint(1531463.95, 495879.744);
 54      params = params || {};
 55      super(params);
 56      var f_i:Number = params.inverse_flattening;
 57      var phi1:Number = params.standard_parallel_1 * RAD_DEG;
 58      var phi2:Number = params.standard_parallel_2 * RAD_DEG;
 59      var phiF:Number = params.latitude_of_origin * RAD_DEG;
 60      this.a_ = params.semi_major / params.unit;
 61      this.lamdaF_ = params.central_meridian * RAD_DEG;
 62      this.FE_ = params.false_easting;
 63      this.FN_ = params.false_northing;
 64      
 65      var f:Number = 1.0 / f_i; //e: eccentricity of the ellipsoid where e^2  =  2f - f^2 
 66      var es:Number = 2 * f - f * f;
 67      this.e_ = Math.sqrt(es);
 68      var m1:Number = this.calc_m_(phi1, es);
 69      var m2:Number = this.calc_m_(phi2, es);
 70      var tF:Number = this.calc_t_(phiF, this.e_);
 71      var t1:Number = this.calc_t_(phi1, this.e_);
 72      var t2:Number = this.calc_t_(phi2, this.e_);
 73      this.n_ = Math.log(m1 / m2) / Math.log(t1 / t2);
 74      this.F_ = m1 / (this.n_ * Math.pow(t1, this.n_));
 75      this.rF_ = this.calc_r_(this.a_, this.F_, tF, this.n_);
 76    }
 77    private function calc_m_(phi:Number, es:Number):Number{
 78      var sinphi:Number = Math.sin(phi);
 79      return Math.cos(phi) / Math.sqrt(1 - es * sinphi * sinphi);
 80    }
 81    private function calc_t_(phi:Number, e:Number):Number{
 82      var esinphi:Number = e * Math.sin(phi);
 83      return Math.tan(Math.PI / 4 - phi / 2) / Math.pow((1 - esinphi) / (1 + esinphi), e / 2);
 84    }
 85    private function calc_r_ (a:Number, F:Number, t:Number, n:Number):Number {
 86      return a * F * Math.pow(t, n);
 87    };
 88    private function calc_phi_(t_i:Number, e:Number, phi:Number):Number{
 89      var esinphi:Number = e * Math.sin(phi);
 90      return Math.PI / 2 - 2 * Math.atan(t_i * Math.pow((1 - esinphi) / (1 + esinphi), e / 2));
 91    }
 92    private function solve_phi_(t_i:Number, e:Number, init:Number):Number{
 93      // iteration
 94      var i:int = 0;
 95      var phi:Number = init;
 96      var newphi:Number = this.calc_phi_(t_i, e, phi);//this.
 97      while (Math.abs(newphi - phi) > 0.000000001 && i < 10) {
 98        i++;
 99        phi = newphi;
100        newphi = this.calc_phi_(t_i, e, phi);//this.
101      }
102      return newphi;
103    }
104    override public function forward(lnglat:Array):Array{
105      var phi:Number = lnglat[1] * RAD_DEG;// (Math.PI / 180);
106      var lamda:Number = lnglat[0] * RAD_DEG;
107      var t:Number = this.calc_t_(phi, this.e_);
108      var r:Number = this.calc_r_(this.a_, this.F_, t, this.n_);
109      var theta:Number = this.n_ * (lamda - this.lamdaF_);
110      var E:Number = this.FE_ + r * Math.sin(theta);
111      var N:Number = this.FN_ + this.rF_ - r * Math.cos(theta);
112      return [E, N];
113    } 
114    override public function reverse(coords:Array):Array{
115      var E:Number = coords[0];
116      var N:Number = coords[1];
117      var theta_i:Number = Math.atan((E - this.FE_) / (this.rF_ - (N - this.FN_)));
118      var r_i:Number = (this.n_ > 0 ? 1 : -1) * Math.sqrt((E - this.FE_) * (E - this.FE_) + (this.rF_ - (N - this.FN_)) * (this.rF_ - (N - this.FN_)));
119      var t_i:Number = Math.pow((r_i / (this.a_ * this.F_)), 1 / this.n_);
120      var phi:Number = this.solve_phi_(t_i, this.e_, 0);
121      var lamda:Number = theta_i / this.n_ + this.lamdaF_;
122      return [lamda / RAD_DEG, phi / RAD_DEG];
123    }
124    override public function getCircumference():Number{
125      return Math.PI * 2 * this.a_;
126    }
127  }
128}