/src/com/google/maps/extras/arcgislink/LambertConformalConic.as
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}