PageRenderTime 25ms CodeModel.GetById 15ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://gmaps-utility-library-flash.googlecode.com/
ActionScript | 114 lines | 65 code | 8 blank | 41 comment | 1 complexity | dc09b59c63071a21e89b329d61250e44 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
 14   * <a target  = wiki href  = 'http://en.wikipedia.org/wiki/Transverse_Mercator_projection'>Transverse Mercator Projection</a>
 15   */
 16  public class TransverseMercator extends SpatialReference {
 17    private var a_:Number;
 18    private var k0_:Number;
 19    private var lamdaF_:Number;
 20    private var FE_:Number;
 21    private var FN_:Number;
 22    private var es_:Number;
 23    private var ep4_:Number;
 24    private var ep6_:Number;
 25    private var eas_:Number;
 26    private var M0_:Number;
 27
 28    /**
 29     * Create a Transverse Mercator Projection. The <code>params</code> passed in constructor should contain the
 30     * following properties: <br/>
 31     * <code>
 32     * <br/>-wkid: well-known id
 33     * <br/>-semi_major:  ellipsoidal semi-major axis in meters
 34     * <br/>-unit: meters per unit
 35     * <br/>-inverse_flattening: inverse of flattening of the ellipsoid where 1/f  =  a/(a - b)
 36     * <br/>-Scale Factor: scale factor at origin
 37     * <br/>-latitude_of_origin: phiF, latitude of the false origin
 38     * <br/>-central_meridian: lamdaF, longitude of the false origin  (with respect to the prime meridian)
 39     * <br/>-false_easting: FE, false easting, the Eastings value assigned to the natural origin
 40     * <br/>-false_northing: FN, false northing, the Northings value assigned to the natural origin
 41     * </code>
 42     * <br/>e.g. Georgia West State Plane NAD83 Feet:
 43     * <br/><code> var gawsp83  = new ArcGISTransverseMercator({wkid: 102667, semi_major:6378137.0,
 44     *  inverse_flattening:298.257222101,central_meridian:-84.16666666666667, latitude_of_origin: 30.0,
 45     *  scale_factor:0.9999,'false_easting':2296583.333333333, 'false_northing':0, unit: 0.3048006096012192});
 46     *  </code>
 47     * @param {Object} params
 48     * @name ArcGISTransverseMercator
 49     * @extends ArcGISSpatialReference
 50     */
 51    public function TransverseMercator(params:Object) {
 52      params=params || {};
 53      super(params);
 54      //GLatLng(33.74561,-84.454308)<  === >  GPoint(2209149.07977075, 1362617.71496891);
 55      this.a_=params.semi_major / params.unit; //this.
 56      var f_i:Number=params.inverse_flattening;
 57      this.k0_=params.scale_factor;
 58      var phiF:Number=params.latitude_of_origin * RAD_DEG; //(Math.PI / 180);
 59      this.lamdaF_=params.central_meridian * RAD_DEG;
 60      this.FE_=params.false_easting; //this.
 61      this.FN_=params.false_northing; //this.
 62      var f:Number=1.0 / f_i; //this.
 63      /*e: eccentricity of the ellipsoid where e^2  =  2f - f^2 */
 64      this.es_=2 * f - f * f;
 65      //var _e  =  Math.sqrt(this.es_);
 66      /* e^4 */
 67      this.ep4_=this.es_ * this.es_;
 68      /* e^6 */
 69      this.ep6_=this.ep4_ * this.es_;
 70      /* e'  second eccentricity where e'^2  =  e^2 / (1-e^2) */
 71      this.eas_=this.es_ / (1 - this.es_);
 72      this.M0_=this.calc_m_(phiF, this.a_, this.es_, this.ep4_, this.ep6_);
 73    }
 74
 75    private function calc_m_(phi:Number, a:Number, es:Number, ep4:Number, ep6:Number):Number {
 76      return a * ((1 - es / 4 - 3 * ep4 / 64 - 5 * ep6 / 256) * phi - (3 * es / 8 + 3 * ep4 / 32 + 45 * ep6 / 1024) * Math.sin(2 * phi) + (15 * ep4 / 256 + 45 * ep6 / 1024) * Math.sin(4 * phi) - (35 * ep6 / 3072) * Math.sin(6 * phi));
 77    }
 78
 79    override public function forward(lnglat:Array):Array {
 80      var phi:Number=lnglat[1] * RAD_DEG; // (Math.PI / 180);
 81      var lamda:Number=lnglat[0] * RAD_DEG; //(Math.PI / 180);
 82      var nu:Number=this.a_ / Math.sqrt(1 - this.es_ * Math.pow(Math.sin(phi), 2));
 83      var T:Number=Math.pow(Math.tan(phi), 2);
 84      var C:Number=this.eas_ * Math.pow(Math.cos(phi), 2);
 85      var A:Number=(lamda - this.lamdaF_) * Math.cos(phi);
 86      var M:Number=this.calc_m_(phi, this.a_, this.es_, this.ep4_, this.ep6_);
 87      var E:Number=this.FE_ + this.k0_ * nu * (A + (1 - T + C) * Math.pow(A, 3) / 6 + (5 - 18 * T + T * T + 72 * C - 58 * this.eas_) * Math.pow(A, 5) / 120);
 88      var N:Number=this.FN_ + this.k0_ * (M - this.M0_) + nu * Math.tan(phi) * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * Math.pow(A, 4) / 120 + (61 - 58 * T + T * T + 600 * C - 330 * this.eas_) * Math.pow(A, 6) / 720);
 89      return [E, N];
 90    }
 91
 92    override public function reverse(coords:Array):Array {
 93      var E:Number=coords[0];
 94      var N:Number=coords[1];
 95      var e1:Number=(1 - Math.sqrt(1 - this.es_)) / (1 + Math.sqrt(1 - this.es_));
 96      var M1:Number=this.M0_ + (N - this.FN_) / this.k0_;
 97      var mu1:Number=M1 / (this.a_ * (1 - this.es_ / 4 - 3 * this.ep4_ / 64 - 5 * this.ep6_ / 256));
 98      var phi1:Number=mu1 + (3 * e1 / 2 - 27 * Math.pow(e1, 3) / 32) * Math.sin(2 * mu1) + (21 * e1 * e1 / 16 - 55 * Math.pow(e1, 4) / 32) * Math.sin(4 * mu1) + (151 * Math.pow(e1, 3) / 6) * Math.sin(6 * mu1) + (1097 * Math.pow(e1, 4) / 512) * Math.sin(8 * mu1);
 99      var C1:Number=this.eas_ * Math.pow(Math.cos(phi1), 2);
100      var T1:Number=Math.pow(Math.tan(phi1), 2);
101      var N1:Number=this.a_ / Math.sqrt(1 - this.es_ * Math.pow(Math.sin(phi1), 2));
102      var R1:Number=this.a_ * (1 - this.es_) / Math.pow((1 - this.es_ * Math.pow(Math.sin(phi1), 2)), 3 / 2);
103      var D:Number=(E - this.FE_) / (N1 * this.k0_);
104      var phi:Number=phi1 - (N1 * Math.tan(phi1) / R1) * (D * D / 2 - (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1 - 9 * this.eas_) * Math.pow(D, 4) / 24 + (61 + 90 * T1 + 28 * C1 + 45 * T1 * T1 - 252 * this.eas_ - 3 * C1 * C1) * Math.pow(D, 6) / 720);
105      var lamda:Number=this.lamdaF_ + (D - (1 + 2 * T1 + C1) * Math.pow(D, 3) / 6 + (5 - 2 * C1 + 28 * T1 - 3 * C1 * C1 + 8 * this.eas_ + 24 * T1 * T1) * Math.pow(D, 5) / 120) / Math.cos(phi1);
106      return [lamda / RAD_DEG, phi / RAD_DEG];
107    }
108
109    override public function getCircumference():Number {
110      return Math.PI * 2 * this.a_;
111    }
112
113  }
114}