/*
Author: Mike Adair madairATdmsolutions.ca
Richard Greenwood rich@greenwoodmap.com
License: LGPL as per: http://www.gnu.org/copyleft/lesser.html
$Id: Proj.js 2956 2007-07-09 12:17:52Z steven $
*/
/**
* Namespace: Proj4js
*
* Proj4js is a JavaScript library to transform point coordinates from one
* coordinate system to another, including datum transformations.
*
* This library is a port of both the Proj.4 and GCTCP C libraries to JavaScript.
* Enabling these transformations in the browser allows geographic data stored
* in different projections to be combined in browser-based web mapping
* applications.
*
* Proj4js must have access to coordinate system initialization strings (which
* are the same as for PROJ.4 command line). Thes can be included in your
* application using a
def is a CS definition in PROJ.4 WKT format, for example:
+proj="tmerc" //longlat, etc.
+a=majorRadius
+b=minorRadius
+lat0=somenumber
+long=somenumber
*/
Proj4js.defs = {
// These are so widely used, we'll go ahead and throw them in
// without requiring a separate .js file
'WGS84': "+title=long/lat:WGS84 +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees",
'EPSG:4326': "+title=long/lat:WGS84 +proj=longlat +a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84 +units=degrees",
'EPSG:4269': "+title=long/lat:NAD83 +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees",
'EPSG:3785': "+title= Google Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs"
};
Proj4js.defs['GOOGLE'] = Proj4js.defs['EPSG:3785'];
Proj4js.defs['EPSG:900913'] = Proj4js.defs['EPSG:3785'];
Proj4js.defs['EPSG:102113'] = Proj4js.defs['EPSG:3785'];
Proj4js.common = {
PI : 3.141592653589793238, //Math.PI,
HALF_PI : 1.570796326794896619, //Math.PI*0.5,
TWO_PI : 6.283185307179586477, //Math.PI*2,
FORTPI : 0.78539816339744833,
R2D : 57.29577951308232088,
D2R : 0.01745329251994329577,
SEC_TO_RAD : 4.84813681109535993589914102357e-6, /* SEC_TO_RAD = Pi/180/3600 */
EPSLN : 1.0e-10,
MAX_ITER : 20,
// following constants from geocent.c
COS_67P5 : 0.38268343236508977, /* cosine of 67.5 degrees */
AD_C : 1.0026000, /* Toms region 1 constant */
/* datum_type values */
PJD_UNKNOWN : 0,
PJD_3PARAM : 1,
PJD_7PARAM : 2,
PJD_GRIDSHIFT: 3,
PJD_WGS84 : 4, // WGS84 or equivalent
PJD_NODATUM : 5, // WGS84 or equivalent
SRS_WGS84_SEMIMAJOR : 6378137.0, // only used in grid shift transforms
// ellipoid pj_set_ell.c
SIXTH : .1666666666666666667, /* 1/6 */
RA4 : .04722222222222222222, /* 17/360 */
RA6 : .02215608465608465608, /* 67/3024 */
RV4 : .06944444444444444444, /* 5/72 */
RV6 : .04243827160493827160, /* 55/1296 */
// Function to compute the constant small m which is the radius of
// a parallel of latitude, phi, divided by the semimajor axis.
// -----------------------------------------------------------------
msfnz : function(eccent, sinphi, cosphi) {
var con = eccent * sinphi;
return cosphi/(Math.sqrt(1.0 - con * con));
},
// Function to compute the constant small t for use in the forward
// computations in the Lambert Conformal Conic and the Polar
// Stereographic projections.
// -----------------------------------------------------------------
tsfnz : function(eccent, phi, sinphi) {
var con = eccent * sinphi;
var com = .5 * eccent;
con = Math.pow(((1.0 - con) / (1.0 + con)), com);
return (Math.tan(.5 * (this.HALF_PI - phi))/con);
},
// Function to compute the latitude angle, phi2, for the inverse of the
// Lambert Conformal Conic and Polar Stereographic projections.
// ----------------------------------------------------------------
phi2z : function(eccent, ts) {
var eccnth = .5 * eccent;
var con, dphi;
var phi = this.HALF_PI - 2 * Math.atan(ts);
for (var i = 0; i <= 15; i++) {
con = eccent * Math.sin(phi);
dphi = this.HALF_PI - 2 * Math.atan(ts *(Math.pow(((1.0 - con)/(1.0 + con)),eccnth))) - phi;
phi += dphi;
if (Math.abs(dphi) <= .0000000001) return phi;
}
alert("phi2z has NoConvergence");
return (-9999);
},
/* Function to compute constant small q which is the radius of a
parallel of latitude, phi, divided by the semimajor axis.
------------------------------------------------------------*/
qsfnz : function(eccent,sinphi) {
var con;
if (eccent > 1.0e-7) {
con = eccent * sinphi;
return (( 1.0- eccent * eccent) * (sinphi /(1.0 - con * con) - (.5/eccent)*Math.log((1.0 - con)/(1.0 + con))));
} else {
return(2.0 * sinphi);
}
},
/* Function to eliminate roundoff errors in asin
----------------------------------------------*/
asinz : function(x) {
if (Math.abs(x)>1.0) {
x=(x>1.0)?1.0:-1.0;
}
return Math.asin(x);
},
// following functions from gctpc cproj.c for transverse mercator projections
e0fn : function(x) {return(1.0-0.25*x*(1.0+x/16.0*(3.0+1.25*x)));},
e1fn : function(x) {return(0.375*x*(1.0+0.25*x*(1.0+0.46875*x)));},
e2fn : function(x) {return(0.05859375*x*x*(1.0+0.75*x));},
e3fn : function(x) {return(x*x*x*(35.0/3072.0));},
mlfn : function(e0,e1,e2,e3,phi) {return(e0*phi-e1*Math.sin(2.0*phi)+e2*Math.sin(4.0*phi)-e3*Math.sin(6.0*phi));},
srat : function(esinp, exp) {
return(Math.pow((1.0-esinp)/(1.0+esinp), exp));
},
// Function to return the sign of an argument
sign : function(x) { if (x < 0.0) return(-1); else return(1);},
// Function to adjust longitude to -180 to 180; input in radians
adjust_lon : function(x) {
x = (Math.abs(x) < this.PI) ? x: (x - (this.sign(x)*this.TWO_PI) );
return x;
},
// IGNF - DGR : algorithms used by IGN France
// Function to adjust latitude to -90 to 90; input in radians
adjust_lat : function(x) {
x= (Math.abs(x) < this.HALF_PI) ? x: (x - (this.sign(x)*this.PI) );
return x;
},
// Latitude Isometrique - close to tsfnz ...
latiso : function(eccent, phi, sinphi) {
if (Math.abs(phi) > this.HALF_PI) return +Number.NaN;
if (phi==this.HALF_PI) return Number.POSITIVE_INFINITY;
if (phi==-1.0*this.HALF_PI) return -1.0*Number.POSITIVE_INFINITY;
var con= eccent*sinphi;
return Math.log(Math.tan((this.HALF_PI+phi)/2.0))+eccent*Math.log((1.0-con)/(1.0+con))/2.0;
},
fL : function(x,L) {
return 2.0*Math.atan(x*Math.exp(L)) - this.HALF_PI;
},
// Inverse Latitude Isometrique - close to ph2z
invlatiso : function(eccent, ts) {
var phi= this.fL(1.0,ts);
var Iphi= 0.0;
var con= 0.0;
do {
Iphi= phi;
con= eccent*Math.sin(Iphi);
phi= this.fL(Math.exp(eccent*Math.log((1.0+con)/(1.0-con))/2.0),ts)
} while (Math.abs(phi-Iphi)>1.0e-12);
return phi;
},
// Needed for Gauss Schreiber
// Original: Denis Makarov (info@binarythings.com)
// Web Site: http://www.binarythings.com
sinh : function(x)
{
var r= Math.exp(x);
r= (r-1.0/r)/2.0;
return r;
},
cosh : function(x)
{
var r= Math.exp(x);
r= (r+1.0/r)/2.0;
return r;
},
tanh : function(x)
{
var r= Math.exp(x);
r= (r-1.0/r)/(r+1.0/r);
return r;
},
asinh : function(x)
{
var s= (x>= 0? 1.0:-1.0);
return s*(Math.log( Math.abs(x) + Math.sqrt(x*x+1.0) ));
},
acosh : function(x)
{
return 2.0*Math.log(Math.sqrt((x+1.0)/2.0) + Math.sqrt((x-1.0)/2.0));
},
atanh : function(x)
{
return Math.log((x-1.0)/(x+1.0))/2.0;
},
// Grande Normale
gN : function(a,e,sinphi)
{
var temp= e*sinphi;
return a/Math.sqrt(1.0 - temp*temp);
}
};
/** datum object
*/
Proj4js.datum = Proj4js.Class({
initialize : function(proj) {
this.datum_type = Proj4js.common.PJD_WGS84; //default setting
if (proj.datumCode && proj.datumCode == 'none') {
this.datum_type = Proj4js.common.PJD_NODATUM;
}
if (proj && proj.datum_params) {
for (var i=0; i 3) {
if (proj.datum_params[3] != 0 || proj.datum_params[4] != 0 ||
proj.datum_params[5] != 0 || proj.datum_params[6] != 0 ) {
this.datum_type = Proj4js.common.PJD_7PARAM;
proj.datum_params[3] *= Proj4js.common.SEC_TO_RAD;
proj.datum_params[4] *= Proj4js.common.SEC_TO_RAD;
proj.datum_params[5] *= Proj4js.common.SEC_TO_RAD;
proj.datum_params[6] = (proj.datum_params[6]/1000000.0) + 1.0;
}
}
}
if (proj) {
this.a = proj.a; //datum object also uses these values
this.b = proj.b;
this.es = proj.es;
this.ep2 = proj.ep2;
this.datum_params = proj.datum_params;
}
},
/****************************************************************/
// cs_compare_datums()
// Returns 1 (TRUE) if the two datums match, otherwise 0 (FALSE).
compare_datums : function( dest ) {
if( this.datum_type != dest.datum_type ) {
return false; // false, datums are not equal
} else if( this.a != dest.a || Math.abs(this.es-dest.es) > 0.000000000050 ) {
// the tolerence for es is to ensure that GRS80 and WGS84
// are considered identical
return false;
} else if( this.datum_type == Proj4js.common.PJD_3PARAM ) {
return (this.datum_params[0] == dest.datum_params[0]
&& this.datum_params[1] == dest.datum_params[1]
&& this.datum_params[2] == dest.datum_params[2]);
} else if( this.datum_type == Proj4js.common.PJD_7PARAM ) {
return (this.datum_params[0] == dest.datum_params[0]
&& this.datum_params[1] == dest.datum_params[1]
&& this.datum_params[2] == dest.datum_params[2]
&& this.datum_params[3] == dest.datum_params[3]
&& this.datum_params[4] == dest.datum_params[4]
&& this.datum_params[5] == dest.datum_params[5]
&& this.datum_params[6] == dest.datum_params[6]);
} else if( this.datum_type == Proj4js.common.PJD_GRIDSHIFT ) {
return strcmp( pj_param(this.params,"snadgrids").s,
pj_param(dest.params,"snadgrids").s ) == 0;
} else {
return true; // datums are equal
}
}, // cs_compare_datums()
/*
* The function Convert_Geodetic_To_Geocentric converts geodetic coordinates
* (latitude, longitude, and height) to geocentric coordinates (X, Y, Z),
* according to the current ellipsoid parameters.
*
* Latitude : Geodetic latitude in radians (input)
* Longitude : Geodetic longitude in radians (input)
* Height : Geodetic height, in meters (input)
* X : Calculated Geocentric X coordinate, in meters (output)
* Y : Calculated Geocentric Y coordinate, in meters (output)
* Z : Calculated Geocentric Z coordinate, in meters (output)
*
*/
geodetic_to_geocentric : function(p) {
var Longitude = p.x;
var Latitude = p.y;
var Height = p.z ? p.z : 0; //Z value not always supplied
var X; // output
var Y;
var Z;
var Error_Code=0; // GEOCENT_NO_ERROR;
var Rn; /* Earth radius at location */
var Sin_Lat; /* Math.sin(Latitude) */
var Sin2_Lat; /* Square of Math.sin(Latitude) */
var Cos_Lat; /* Math.cos(Latitude) */
/*
** Don't blow up if Latitude is just a little out of the value
** range as it may just be a rounding issue. Also removed longitude
** test, it should be wrapped by Math.cos() and Math.sin(). NFW for PROJ.4, Sep/2001.
*/
if( Latitude < -Proj4js.common.HALF_PI && Latitude > -1.001 * Proj4js.common.HALF_PI ) {
Latitude = -Proj4js.common.HALF_PI;
} else if( Latitude > Proj4js.common.HALF_PI && Latitude < 1.001 * Proj4js.common.HALF_PI ) {
Latitude = Proj4js.common.HALF_PI;
} else if ((Latitude < -Proj4js.common.HALF_PI) || (Latitude > Proj4js.common.HALF_PI)) {
/* Latitude out of range */
Proj4js.reportError('geocent:lat out of range:'+Latitude);
return null;
}
if (Longitude > Proj4js.common.PI) Longitude -= (2*Proj4js.common.PI);
Sin_Lat = Math.sin(Latitude);
Cos_Lat = Math.cos(Latitude);
Sin2_Lat = Sin_Lat * Sin_Lat;
Rn = this.a / (Math.sqrt(1.0e0 - this.es * Sin2_Lat));
X = (Rn + Height) * Cos_Lat * Math.cos(Longitude);
Y = (Rn + Height) * Cos_Lat * Math.sin(Longitude);
Z = ((Rn * (1 - this.es)) + Height) * Sin_Lat;
p.x = X;
p.y = Y;
p.z = Z;
return Error_Code;
}, // cs_geodetic_to_geocentric()
geocentric_to_geodetic : function (p) {
/* local defintions and variables */
/* end-criterium of loop, accuracy of sin(Latitude) */
var genau = 1.E-12;
var genau2 = (genau*genau);
var maxiter = 30;
var P; /* distance between semi-minor axis and location */
var RR; /* distance between center and location */
var CT; /* sin of geocentric latitude */
var ST; /* cos of geocentric latitude */
var RX;
var RK;
var RN; /* Earth radius at location */
var CPHI0; /* cos of start or old geodetic latitude in iterations */
var SPHI0; /* sin of start or old geodetic latitude in iterations */
var CPHI; /* cos of searched geodetic latitude */
var SPHI; /* sin of searched geodetic latitude */
var SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */
var At_Pole; /* indicates location is in polar region */
var iter; /* # of continous iteration, max. 30 is always enough (s.a.) */
var X = p.x;
var Y = p.y;
var Z = p.z ? p.z : 0.0; //Z value not always supplied
var Longitude;
var Latitude;
var Height;
At_Pole = false;
P = Math.sqrt(X*X+Y*Y);
RR = Math.sqrt(X*X+Y*Y+Z*Z);
/* special cases for latitude and longitude */
if (P/this.a < genau) {
/* special case, if P=0. (X=0., Y=0.) */
At_Pole = true;
Longitude = 0.0;
/* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis
* of ellipsoid (=center of mass), Latitude becomes PI/2 */
if (RR/this.a < genau) {
Latitude = Proj4js.common.HALF_PI;
Height = -this.b;
return;
}
} else {
/* ellipsoidal (geodetic) longitude
* interval: -PI < Longitude <= +PI */
Longitude=Math.atan2(Y,X);
}
/* --------------------------------------------------------------
* Following iterative algorithm was developped by
* "Institut f�r Erdmessung", University of Hannover, July 1988.
* Internet: www.ife.uni-hannover.de
* Iterative computation of CPHI,SPHI and Height.
* Iteration of CPHI and SPHI to 10**-12 radian resp.
* 2*10**-7 arcsec.
* --------------------------------------------------------------
*/
CT = Z/RR;
ST = P/RR;
RX = 1.0/Math.sqrt(1.0-this.es*(2.0-this.es)*ST*ST);
CPHI0 = ST*(1.0-this.es)*RX;
SPHI0 = CT*RX;
iter = 0;
/* loop to find sin(Latitude) resp. Latitude
* until |sin(Latitude(iter)-Latitude(iter-1))| < genau */
do
{
iter++;
RN = this.a/Math.sqrt(1.0-this.es*SPHI0*SPHI0);
/* ellipsoidal (geodetic) height */
Height = P*CPHI0+Z*SPHI0-RN*(1.0-this.es*SPHI0*SPHI0);
RK = this.es*RN/(RN+Height);
RX = 1.0/Math.sqrt(1.0-RK*(2.0-RK)*ST*ST);
CPHI = ST*(1.0-RK)*RX;
SPHI = CT*RX;
SDPHI = SPHI*CPHI0-CPHI*SPHI0;
CPHI0 = CPHI;
SPHI0 = SPHI;
}
while (SDPHI*SDPHI > genau2 && iter < maxiter);
/* ellipsoidal (geodetic) latitude */
Latitude=Math.atan(SPHI/Math.abs(CPHI));
p.x = Longitude;
p.y = Latitude;
p.z = Height;
return p;
}, // cs_geocentric_to_geodetic()
/** Convert_Geocentric_To_Geodetic
* The method used here is derived from 'An Improved Algorithm for
* Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996
*/
geocentric_to_geodetic_noniter : function (p) {
var X = p.x;
var Y = p.y;
var Z = p.z ? p.z : 0; //Z value not always supplied
var Longitude;
var Latitude;
var Height;
var W; /* distance from Z axis */
var W2; /* square of distance from Z axis */
var T0; /* initial estimate of vertical component */
var T1; /* corrected estimate of vertical component */
var S0; /* initial estimate of horizontal component */
var S1; /* corrected estimate of horizontal component */
var Sin_B0; /* Math.sin(B0), B0 is estimate of Bowring aux variable */
var Sin3_B0; /* cube of Math.sin(B0) */
var Cos_B0; /* Math.cos(B0) */
var Sin_p1; /* Math.sin(phi1), phi1 is estimated latitude */
var Cos_p1; /* Math.cos(phi1) */
var Rn; /* Earth radius at location */
var Sum; /* numerator of Math.cos(phi1) */
var At_Pole; /* indicates location is in polar region */
X = parseFloat(X); // cast from string to float
Y = parseFloat(Y);
Z = parseFloat(Z);
At_Pole = false;
if (X != 0.0)
{
Longitude = Math.atan2(Y,X);
}
else
{
if (Y > 0)
{
Longitude = Proj4js.common.HALF_PI;
}
else if (Y < 0)
{
Longitude = -Proj4js.common.HALF_PI;
}
else
{
At_Pole = true;
Longitude = 0.0;
if (Z > 0.0)
{ /* north pole */
Latitude = Proj4js.common.HALF_PI;
}
else if (Z < 0.0)
{ /* south pole */
Latitude = -Proj4js.common.HALF_PI;
}
else
{ /* center of earth */
Latitude = Proj4js.common.HALF_PI;
Height = -this.b;
return;
}
}
}
W2 = X*X + Y*Y;
W = Math.sqrt(W2);
T0 = Z * Proj4js.common.AD_C;
S0 = Math.sqrt(T0 * T0 + W2);
Sin_B0 = T0 / S0;
Cos_B0 = W / S0;
Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
T1 = Z + this.b * this.ep2 * Sin3_B0;
Sum = W - this.a * this.es * Cos_B0 * Cos_B0 * Cos_B0;
S1 = Math.sqrt(T1*T1 + Sum * Sum);
Sin_p1 = T1 / S1;
Cos_p1 = Sum / S1;
Rn = this.a / Math.sqrt(1.0 - this.es * Sin_p1 * Sin_p1);
if (Cos_p1 >= Proj4js.common.COS_67P5)
{
Height = W / Cos_p1 - Rn;
}
else if (Cos_p1 <= -Proj4js.common.COS_67P5)
{
Height = W / -Cos_p1 - Rn;
}
else
{
Height = Z / Sin_p1 + Rn * (this.es - 1.0);
}
if (At_Pole == false)
{
Latitude = Math.atan(Sin_p1 / Cos_p1);
}
p.x = Longitude;
p.y = Latitude;
p.z = Height;
return p;
}, // geocentric_to_geodetic_noniter()
/****************************************************************/
// pj_geocentic_to_wgs84( p )
// p = point to transform in geocentric coordinates (x,y,z)
geocentric_to_wgs84 : function ( p ) {
if( this.datum_type == Proj4js.common.PJD_3PARAM )
{
// if( x[io] == HUGE_VAL )
// continue;
p.x += this.datum_params[0];
p.y += this.datum_params[1];
p.z += this.datum_params[2];
}
else if (this.datum_type == Proj4js.common.PJD_7PARAM)
{
var Dx_BF =this.datum_params[0];
var Dy_BF =this.datum_params[1];
var Dz_BF =this.datum_params[2];
var Rx_BF =this.datum_params[3];
var Ry_BF =this.datum_params[4];
var Rz_BF =this.datum_params[5];
var M_BF =this.datum_params[6];
// if( x[io] == HUGE_VAL )
// continue;
var x_out = M_BF*( p.x - Rz_BF*p.y + Ry_BF*p.z) + Dx_BF;
var y_out = M_BF*( Rz_BF*p.x + p.y - Rx_BF*p.z) + Dy_BF;
var z_out = M_BF*(-Ry_BF*p.x + Rx_BF*p.y + p.z) + Dz_BF;
p.x = x_out;
p.y = y_out;
p.z = z_out;
}
}, // cs_geocentric_to_wgs84
/****************************************************************/
// pj_geocentic_from_wgs84()
// coordinate system definition,
// point to transform in geocentric coordinates (x,y,z)
geocentric_from_wgs84 : function( p ) {
if( this.datum_type == Proj4js.common.PJD_3PARAM )
{
//if( x[io] == HUGE_VAL )
// continue;
p.x -= this.datum_params[0];
p.y -= this.datum_params[1];
p.z -= this.datum_params[2];
}
else if (this.datum_type == Proj4js.common.PJD_7PARAM)
{
var Dx_BF =this.datum_params[0];
var Dy_BF =this.datum_params[1];
var Dz_BF =this.datum_params[2];
var Rx_BF =this.datum_params[3];
var Ry_BF =this.datum_params[4];
var Rz_BF =this.datum_params[5];
var M_BF =this.datum_params[6];
var x_tmp = (p.x - Dx_BF) / M_BF;
var y_tmp = (p.y - Dy_BF) / M_BF;
var z_tmp = (p.z - Dz_BF) / M_BF;
//if( x[io] == HUGE_VAL )
// continue;
p.x = x_tmp + Rz_BF*y_tmp - Ry_BF*z_tmp;
p.y = -Rz_BF*x_tmp + y_tmp + Rx_BF*z_tmp;
p.z = Ry_BF*x_tmp - Rx_BF*y_tmp + z_tmp;
} //cs_geocentric_from_wgs84()
}
});
/** point object, nothing fancy, just allows values to be
passed back and forth by reference rather than by value.
Other point classes may be used as long as they have
x and y properties, which will get modified in the transform method.
*/
Proj4js.Point = Proj4js.Class({
/**
* Constructor: Proj4js.Point
*
* Parameters:
* - x {float} or {Array} either the first coordinates component or
* the full coordinates
* - y {float} the second component
* - z {float} the third component, optional.
*/
initialize : function(x,y,z) {
if (typeof x == 'object') {
this.x = x[0];
this.y = x[1];
this.z = x[2] || 0.0;
} else if (typeof x == 'string' && typeof y == 'undefined') {
var coords = x.split(',');
this.x = parseFloat(coords[0]);
this.y = parseFloat(coords[1]);
this.z = parseFloat(coords[2]) || 0.0;
} else {
this.x = x;
this.y = y;
this.z = z || 0.0;
}
},
/**
* APIMethod: clone
* Build a copy of a Proj4js.Point object.
*
* Return:
* {Proj4js}.Point the cloned point.
*/
clone : function() {
return new Proj4js.Point(this.x, this.y, this.z);
},
/**
* APIMethod: toString
* Return a readable string version of the point
*
* Return:
* {String} String representation of Proj4js.Point object.
* (ex. "x=5,y=42")
*/
toString : function() {
return ("x=" + this.x + ",y=" + this.y);
},
/**
* APIMethod: toShortString
* Return a short string version of the point.
*
* Return:
* {String} Shortened String representation of Proj4js.Point object.
* (ex. "5, 42")
*/
toShortString : function() {
return (this.x + ", " + this.y);
}
});
Proj4js.PrimeMeridian = {
"greenwich": 0.0, //"0dE",
"lisbon": -9.131906111111, //"9d07'54.862\"W",
"paris": 2.337229166667, //"2d20'14.025\"E",
"bogota": -74.080916666667, //"74d04'51.3\"W",
"madrid": -3.687938888889, //"3d41'16.58\"W",
"rome": 12.452333333333, //"12d27'8.4\"E",
"bern": 7.439583333333, //"7d26'22.5\"E",
"jakarta": 106.807719444444, //"106d48'27.79\"E",
"ferro": -17.666666666667, //"17d40'W",
"brussels": 4.367975, //"4d22'4.71\"E",
"stockholm": 18.058277777778, //"18d3'29.8\"E",
"athens": 23.7163375, //"23d42'58.815\"E",
"oslo": 10.722916666667 //"10d43'22.5\"E"
};
Proj4js.Ellipsoid = {
"MERIT": {a:6378137.0, rf:298.257, ellipseName:"MERIT 1983"},
"SGS85": {a:6378136.0, rf:298.257, ellipseName:"Soviet Geodetic System 85"},
"GRS80": {a:6378137.0, rf:298.257222101, ellipseName:"GRS 1980(IUGG, 1980)"},
"IAU76": {a:6378140.0, rf:298.257, ellipseName:"IAU 1976"},
"airy": {a:6377563.396, b:6356256.910, ellipseName:"Airy 1830"},
"APL4.": {a:6378137, rf:298.25, ellipseName:"Appl. Physics. 1965"},
"NWL9D": {a:6378145.0, rf:298.25, ellipseName:"Naval Weapons Lab., 1965"},
"mod_airy": {a:6377340.189, b:6356034.446, ellipseName:"Modified Airy"},
"andrae": {a:6377104.43, rf:300.0, ellipseName:"Andrae 1876 (Den., Iclnd.)"},
"aust_SA": {a:6378160.0, rf:298.25, ellipseName:"Australian Natl & S. Amer. 1969"},
"GRS67": {a:6378160.0, rf:298.2471674270, ellipseName:"GRS 67(IUGG 1967)"},
"bessel": {a:6377397.155, rf:299.1528128, ellipseName:"Bessel 1841"},
"bess_nam": {a:6377483.865, rf:299.1528128, ellipseName:"Bessel 1841 (Namibia)"},
"clrk66": {a:6378206.4, b:6356583.8, ellipseName:"Clarke 1866"},
"clrk80": {a:6378249.145, rf:293.4663, ellipseName:"Clarke 1880 mod."},
"CPM": {a:6375738.7, rf:334.29, ellipseName:"Comm. des Poids et Mesures 1799"},
"delmbr": {a:6376428.0, rf:311.5, ellipseName:"Delambre 1810 (Belgium)"},
"engelis": {a:6378136.05, rf:298.2566, ellipseName:"Engelis 1985"},
"evrst30": {a:6377276.345, rf:300.8017, ellipseName:"Everest 1830"},
"evrst48": {a:6377304.063, rf:300.8017, ellipseName:"Everest 1948"},
"evrst56": {a:6377301.243, rf:300.8017, ellipseName:"Everest 1956"},
"evrst69": {a:6377295.664, rf:300.8017, ellipseName:"Everest 1969"},
"evrstSS": {a:6377298.556, rf:300.8017, ellipseName:"Everest (Sabah & Sarawak)"},
"fschr60": {a:6378166.0, rf:298.3, ellipseName:"Fischer (Mercury Datum) 1960"},
"fschr60m": {a:6378155.0, rf:298.3, ellipseName:"Fischer 1960"},
"fschr68": {a:6378150.0, rf:298.3, ellipseName:"Fischer 1968"},
"helmert": {a:6378200.0, rf:298.3, ellipseName:"Helmert 1906"},
"hough": {a:6378270.0, rf:297.0, ellipseName:"Hough"},
"intl": {a:6378388.0, rf:297.0, ellipseName:"International 1909 (Hayford)"},
"kaula": {a:6378163.0, rf:298.24, ellipseName:"Kaula 1961"},
"lerch": {a:6378139.0, rf:298.257, ellipseName:"Lerch 1979"},
"mprts": {a:6397300.0, rf:191.0, ellipseName:"Maupertius 1738"},
"new_intl": {a:6378157.5, b:6356772.2, ellipseName:"New International 1967"},
"plessis": {a:6376523.0, rf:6355863.0, ellipseName:"Plessis 1817 (France)"},
"krass": {a:6378245.0, rf:298.3, ellipseName:"Krassovsky, 1942"},
"SEasia": {a:6378155.0, b:6356773.3205, ellipseName:"Southeast Asia"},
"walbeck": {a:6376896.0, b:6355834.8467, ellipseName:"Walbeck"},
"WGS60": {a:6378165.0, rf:298.3, ellipseName:"WGS 60"},
"WGS66": {a:6378145.0, rf:298.25, ellipseName:"WGS 66"},
"WGS72": {a:6378135.0, rf:298.26, ellipseName:"WGS 72"},
"WGS84": {a:6378137.0, rf:298.257223563, ellipseName:"WGS 84"},
"sphere": {a:6370997.0, b:6370997.0, ellipseName:"Normal Sphere (r=6370997)"}
};
Proj4js.Datum = {
"WGS84": {towgs84: "0,0,0", ellipse: "WGS84", datumName: "WGS84"},
"GGRS87": {towgs84: "-199.87,74.79,246.62", ellipse: "GRS80", datumName: "Greek_Geodetic_Reference_System_1987"},
"NAD83": {towgs84: "0,0,0", ellipse: "GRS80", datumName: "North_American_Datum_1983"},
"NAD27": {nadgrids: "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat", ellipse: "clrk66", datumName: "North_American_Datum_1927"},
"potsdam": {towgs84: "606.0,23.0,413.0", ellipse: "bessel", datumName: "Potsdam Rauenberg 1950 DHDN"},
"carthage": {towgs84: "-263.0,6.0,431.0", ellipse: "clark80", datumName: "Carthage 1934 Tunisia"},
"hermannskogel": {towgs84: "653.0,-212.0,449.0", ellipse: "bessel", datumName: "Hermannskogel"},
"ire65": {towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15", ellipse: "mod_airy", datumName: "Ireland 1965"},
"nzgd49": {towgs84: "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993", ellipse: "intl", datumName: "New Zealand Geodetic Datum 1949"},
"OSGB36": {towgs84: "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894", ellipse: "airy", datumName: "Airy 1830"}
};
Proj4js.WGS84 = new Proj4js.Proj('WGS84');
Proj4js.Datum['OSB36'] = Proj4js.Datum['OSGB36']; //as returned from spatialreference.org
//lookup table to go from the projection name in WKT to the Proj4js projection name
//build this out as required
Proj4js.wktProjections = {
"Lambert Tangential Conformal Conic Projection": "lcc",
"Mercator": "merc",
"Popular Visualisation Pseudo Mercator": "merc",
"Transverse_Mercator": "tmerc",
"Transverse Mercator": "tmerc",
"Lambert Azimuthal Equal Area": "laea",
"Universal Transverse Mercator System": "utm"
};