var GEOCENT_LAT_ERROR=0x0001;var COS_67P5=0.38268343236508977;var AD_C=1.0026000;function cs_geodetic_to_geocentric(cs,p){var Longitude=p.x;var Latitude=p.y;var Height=p.z;var X;var Y;var Z;var Error_Code=0;var Rn;var Sin_Lat;var Sin2_Lat;var Cos_Lat;if(Latitude<-HALF_PI&&Latitude>-1.001*HALF_PI)
Latitude=-HALF_PI;else if(Latitude>HALF_PI&&Latitude<1.001*HALF_PI)
Latitude=HALF_PI;else if((Latitude<-HALF_PI)||(Latitude>HALF_PI))
{Error_Code|=GEOCENT_LAT_ERROR;}
if(!Error_Code)
{if(Longitude>PI)
Longitude-=(2*PI);Sin_Lat=Math.sin(Latitude);Cos_Lat=Math.cos(Latitude);Sin2_Lat=Sin_Lat*Sin_Lat;Rn=cs.a/(Math.sqrt(1.0e0-cs.es*Sin2_Lat));X=(Rn+Height)*Cos_Lat*Math.cos(Longitude);Y=(Rn+Height)*Cos_Lat*Math.sin(Longitude);Z=((Rn*(1-cs.es))+Height)*Sin_Lat;}
p.x=X;p.y=Y;p.z=Z;return Error_Code;}
function cs_geocentric_to_geodetic(cs,p){var X=p.x;var Y=p.y;var Z=p.z;var Longitude;var Latitude;var Height;var W;var W2;var T0;var T1;var S0;var S1;var Sin_B0;var Sin3_B0;var Cos_B0;var Sin_p1;var Cos_p1;var Rn;var Sum;var At_Pole;X=parseFloat(X);Y=parseFloat(Y);Z=parseFloat(Z);At_Pole=false;if(X!=0.0)
{Longitude=Math.atan2(Y,X);}
else
{if(Y>0)
{Longitude=HALF_PI;}
else if(Y<0)
{Longitude=-HALF_PI;}
else
{At_Pole=true;Longitude=0.0;if(Z>0.0)
{Latitude=HALF_PI;}
else if(Z<0.0)
{Latitude=-HALF_PI;}
else
{Latitude=HALF_PI;Height=-cs.b;return;}}}
W2=X*X+Y*Y;W=Math.sqrt(W2);T0=Z*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+cs.b*cs.ep2*Sin3_B0;Sum=W-cs.a*cs.es*Cos_B0*Cos_B0*Cos_B0;S1=Math.sqrt(T1*T1+Sum*Sum);Sin_p1=T1/S1;Cos_p1=Sum/S1;Rn=cs.a/Math.sqrt(1.0-cs.es*Sin_p1*Sin_p1);if(Cos_p1>=COS_67P5)
{Height=W/Cos_p1-Rn;}
else if(Cos_p1<=-COS_67P5)
{Height=W/-Cos_p1-Rn;}
else
{Height=Z/Sin_p1+Rn*(cs.es-1.0);}
if(At_Pole==false)
{Latitude=Math.atan(Sin_p1/Cos_p1);}
p.x=Longitude;p.y=Latitude;p.z=Height;return 0;}
function cs_geocentric_to_wgs84(defn,p){if(defn.datum_type==PJD_3PARAM)
{p.x+=defn.datum_params[0];p.y+=defn.datum_params[1];p.z+=defn.datum_params[2];}
else
{var Dx_BF=defn.datum_params[0];var Dy_BF=defn.datum_params[1];var Dz_BF=defn.datum_params[2];var Rx_BF=defn.datum_params[3];var Ry_BF=defn.datum_params[4];var Rz_BF=defn.datum_params[5];var M_BF=defn.datum_params[6];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;}}
function cs_geocentric_from_wgs84(defn,p){if(defn.datum_type==PJD_3PARAM)
{p.x-=defn.datum_params[0];p.y-=defn.datum_params[1];p.z-=defn.datum_params[2];}
else
{var Dx_BF=defn.datum_params[0];var Dy_BF=defn.datum_params[1];var Dz_BF=defn.datum_params[2];var Rx_BF=defn.datum_params[3];var Ry_BF=defn.datum_params[4];var Rz_BF=defn.datum_params[5];var M_BF=defn.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;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;}}
function e0fn(x){return(1.0-0.25*x*(1.0+x/16.0*(3.0+1.25*x)));}
function e1fn(x){return(0.375*x*(1.0+0.25*x*(1.0+0.46875*x)));}
function e2fn(x){return(0.05859375*x*x*(1.0+0.75*x));}
function e3fn(x){return(x*x*x*(35.0/3072.0));}
function mlfn(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));}
function adjust_lon(x){x=(Math.abs(x)<PI)?x:(x-(sign(x)*TWO_PI));return(x);}
function sign(x){if(x<0.0)return(-1);else return(1);}
function tmercInit(def){def.e0=e0fn(def.es);def.e1=e1fn(def.es);def.e2=e2fn(def.es);def.e3=e3fn(def.es);def.ml0=def.a*mlfn(def.e0,def.e1,def.e2,def.e3,def.lat0);def.ind=(def.es<.00001)?1:0;}
function utmInit(def){def.lat0=0.0;def.long0=((6*Math.abs(def.zone))-183)*D2R;def.x0=500000.0;def.y0=(def.zone<0)?10000000.0:0.0;if(!def.k0)
def.k0=0.9996;tmercInit(def);}
function tmercFwd(p){var delta_lon=adjust_lon(p.x-this.long0);var con;var x,y;var sin_phi=Math.sin(p.y);var cos_phi=Math.cos(p.y);if(this.ind!=0){var b=cos_phi*Math.sin(delta_lon);if((Math.abs(Math.abs(b)-1.0))<.0000000001){alert("Error in ll2tm(): Point projects into infinity"); 
return(93);}else{x=.5*this.a*this.k0*Math.log((1.0+b)/(1.0-b));con=Math.acos(cos_phi*Math.cos(delta_lon)/Math.sqrt(1.0-b*b));if(p.y<0)
con=-con;y=this.a*this.k0*(con-this.lat0);}}else{var al=cos_phi*delta_lon;var als=Math.pow(al,2);var c=this.ep2*Math.pow(cos_phi,2);var tq=Math.tan(p.y);var t=Math.pow(tq,2);con=1.0-this.es*Math.pow(sin_phi,2);var n=this.a/Math.sqrt(con);var ml=this.a*mlfn(this.e0,this.e1,this.e2,this.e3,p.y);x=this.k0*n*al*(1.0+als/6.0*(1.0-t+c+als/20.0*(5.0-18.0*t+Math.pow(t,2)+72.0*c-58.0*this.ep2)))+this.x0;y=this.k0*(ml-this.ml0+n*tq*(als*(0.5+als/24.0*(5.0-t+9.0*c+4.0*Math.pow(c,2)+als/30.0*(61.0-58.0*t+Math.pow(t,2)+600.0*c-330.0*this.ep2)))))+this.y0;}
p.x=x;p.y=y;}
var utmFwd=tmercFwd;function tmercInv(p){var con,phi;var delta_phi;var i;var max_iter=6;var lat,lon;if(this.ind!=0){var f=exp(p.x/(this.a*this.k0));var g=.5*(f-1/f);var temp=this.lat0+p.y/(this.a*this.k0);var h=cos(temp);con=sqrt((1.0-h*h)/(1.0+g*g));lat=asinz(con);if(temp<0)
lat=-lat;if((g==0)&&(h==0)){lon=this.long0;}else{lon=adjust_lon(atan2(g,h)+this.long0);}}else{p.x-=this.x0;p.y-=this.y0;con=(this.ml0+p.y/this.k0)/this.a;phi=con;for(i=0;;i++){delta_phi=((con+this.e1*Math.sin(2.0*phi)-this.e2*Math.sin(4.0*phi)+this.e3*Math.sin(6.0*phi))/this.e0)-phi;phi+=delta_phi;if(Math.abs(delta_phi)<=EPSLN)break;if(i>=max_iter){alert("Error in tm2ll(): Latitude failed to converge"); 
return(95);}}
if(Math.abs(phi)<HALF_PI){var sin_phi=Math.sin(phi);var cos_phi=Math.cos(phi);var tan_phi=Math.tan(phi);var c=this.ep2*Math.pow(cos_phi,2);var cs=Math.pow(c,2);var t=Math.pow(tan_phi,2);var ts=Math.pow(t,2);con=1.0-this.es*Math.pow(sin_phi,2);var n=this.a/Math.sqrt(con);var r=n*(1.0-this.es)/con;var d=p.x/(n*this.k0);var ds=Math.pow(d,2);lat=phi-(n*tan_phi*ds/r)*(0.5-ds/24.0*(5.0+3.0*t+10.0*c-4.0*cs-9.0*this.ep2-ds/30.0*(61.0+90.0*t+298.0*c+45.0*ts-252.0*this.ep2-3.0*cs)));lon=adjust_lon(this.long0+(d*(1.0-ds/6.0*(1.0+2.0*t+c-ds/20.0*(5.0-2.0*c+28.0*t-3.0*cs+8.0*this.ep2+24.0*ts)))/cos_phi));}else{lat=HALF_PI*sign(p.y);lon=this.long0;}}
p.x=lon;p.y=lat;}
var utmInv=tmercInv;var PI=Math.PI;var HALF_PI=PI*0.5;var TWO_PI=PI*2;var R2D=57.2957795131;var D2R=0.0174532925199;var EPSLN=1.0e-10;var SRS_WGS84_SEMIMAJOR=6378137.0;var SEC_TO_RAD=4.84813681109535993589914102357e-6
var PJD_UNKNOWN=0;var PJD_3PARAM=1;var PJD_7PARAM=2;var PJD_GRIDSHIFT=3;var PJD_WGS84=4;var csErrorMessage=""; 
function PT(x,y){this.x=x;this.y=y;this.z=0.0;}
var csList=new Object();csList.EPSG4326="+title=long / lat WGS84 +proj=longlat";  // +a=6378137.0 +b=6356752.31424518"; //  +ellps=WGS84 +datum=WGS84"; 
csList.EPSG4269="+title=long / lat NAD83 +proj=longlat";  // +a=6378137.0 +b=6356752.31414036"; //  +ellps=GRS80 +datum=NAD83"; 
function CS(def){if(!def){var def=csList.EPSG4326;csErrorMessage+="No coordinate system definition provided, assuming longlat WGS83"; }
var paramName,paramVal;var paramArray=def.split("+"); 
for(var prop=0;prop<paramArray.length;prop++)
{property=paramArray[prop].split("="); 
paramName=property[0].toLowerCase();paramVal=property[1];switch(paramName.replace(/\s/gi,""))   // trim out spaces 
{case "": break;   // throw away nameless parameter 
case "title": this.title =paramVal; break; 
case "proj":  this.proj =  paramVal.replace(/\s/gi,""); break; 
case "a":     this.a =  parseFloat(paramVal);  break; // semi-major radius 
case "b":     this.b =  parseFloat(paramVal);  break; // semi-minor radius 
case "lon_0": this.long0= paramVal*D2R; break;        // lam0, central longitude 
case "lat_0": this.lat0 = paramVal*D2R; break;        // phi0, central latitude 
case "x_0":   this.x0 = parseFloat(paramVal); break;  // false easting 
case "y_0":   this.y0 = parseFloat(paramVal); break;  // false northing 
case "k":     this.k0 = parseFloat(paramVal); break;  // projection scale factor 
case "to_meter": this.to_meter = eval(paramVal); break; // cartesian scaling 
case "zone":     this.zone =  parseInt(paramVal); break;      // UTM Zone 
case "towgs84":  this.datum_params = paramVal.split(","); break; 
case "from_greenwich": this.from_greenwich = paramVal*D2R; break; 
default:csErrorMessage+="\nUnrecognized parameter: " + paramName; }}
if(this.datum_params){for(var i=0;i<this.datum_params.length;i++)
this.datum_params[i]=parseFloat(this.datum_params[i]);if(this.datum_params[0]!=0||this.datum_params[1]!=0||this.datum_params[2]!=0)
this.datum_type=PJD_3PARAM;if(this.datum_params.length>3)
{if(this.datum_params[3]!=0||this.datum_params[4]!=0||this.datum_params[5]!=0||this.datum_params[6]!=0)
{this.datum_type=PJD_7PARAM;this.datum_params[3]*=SEC_TO_RAD;this.datum_params[4]*=SEC_TO_RAD;this.datum_params[5]*=SEC_TO_RAD;this.datum_params[6]=(this.datum_params[6]/1000000.0)+1.0;}}}
if(!this.datum_type)
this.datum_type=PJD_WGS84;if(!this.a){this.a=6378137.0;this.b=6356752.31424518;csErrorMessage+="\nEllipsoid parameters not provided, assuming WGS84"; }
this.a2=this.a*this.a;this.b2=this.b*this.b;this.es=(this.a2-this.b2)/this.a2;this.e=Math.sqrt(this.es);this.ep2=(this.a2-this.b2)/this.b2;if(this.proj!="longlat") {    // The Forward, Inverse, and Initilization functions are derived from the projection name. 
this.Forward=eval(this.proj+"Fwd"); 
this.Inverse=eval(this.proj+"Inv"); // name of inverse function (x/y to long/lat) 
this.Init=eval(this.proj+"Init"); // initilization function 
this.Init(this);}}
function cs_transform(srcdefn,dstdefn,point){pj_errno=0;if(srcdefn.proj=="longlat") { 
point.x*=D2R;point.y*=D2R;}else{if(srcdefn.to_meter){point.x*=srcdefn.to_meter;point.y*=srcdefn.to_meter;}
srcdefn.Inverse(point);}
if(srcdefn.from_greenwich){point.x+=srcdefn.from_greenwich;}
if(cs_datum_transform(srcdefn,dstdefn,point)!=0)
return pj_errno;if(dstdefn.from_greenwich){point.x-=dstdefn.from_greenwich;}
if(dstdefn.proj=="longlat" ) 
{point.x*=R2D;point.y*=R2D;}else{dstdefn.Forward(point);if(dstdefn.to_meter){point.x/=dstdefn.to_meter;point.y/=dstdefn.to_meter;}}}
function cs_datum_transform(srcdefn,dstdefn,point)
{if(cs_compare_datums(srcdefn,dstdefn))
return 0;if(srcdefn.datum_type==PJD_GRIDSHIFT)
{alert("ERROR: Grid shift transformations are not implemented yet."); }
if(dstdefn.datum_type==PJD_GRIDSHIFT)
{alert("ERROR: Grid shift transformations are not implemented yet."); }
if(srcdefn.datum_type==PJD_3PARAM||srcdefn.datum_type==PJD_7PARAM||dstdefn.datum_type==PJD_3PARAM||dstdefn.datum_type==PJD_7PARAM)
{cs_geodetic_to_geocentric(srcdefn,point);if(srcdefn.datum_type==PJD_3PARAM||srcdefn.datum_type==PJD_7PARAM)
{cs_geocentric_to_wgs84(srcdefn,point);}
if(dstdefn.datum_type==PJD_3PARAM||dstdefn.datum_type==PJD_7PARAM)
{cs_geocentric_from_wgs84(dstdefn,point);}
cs_geocentric_to_geodetic(dstdefn,point);}
if(dstdefn.datum_type==PJD_GRIDSHIFT)
{alert("ERROR: Grid shift transformations are not implemented yet."); }
return 0;}
function cs_compare_datums(srcdefn,dstdefn)
{if(srcdefn.datum_type!=dstdefn.datum_type)
{return 0;}
else if(srcdefn.datum_type==PJD_3PARAM)
{return(srcdefn.datum_params[0]==dstdefn.datum_params[0]&&srcdefn.datum_params[1]==dstdefn.datum_params[1]&&srcdefn.datum_params[2]==dstdefn.datum_params[2]);}
else if(srcdefn.datum_type==PJD_7PARAM)
{return(srcdefn.datum_params[0]==dstdefn.datum_params[0]&&srcdefn.datum_params[1]==dstdefn.datum_params[1]&&srcdefn.datum_params[2]==dstdefn.datum_params[2]&&srcdefn.datum_params[3]==dstdefn.datum_params[3]&&srcdefn.datum_params[4]==dstdefn.datum_params[4]&&srcdefn.datum_params[5]==dstdefn.datum_params[5]&&srcdefn.datum_params[6]==dstdefn.datum_params[6]);}
else if(srcdefn.datum_type==PJD_GRIDSHIFT)
{return strcmp(pj_param(srcdefn.params,"snadgrids").s, 
pj_param(dstdefn.params,"snadgrids").s ) == 0; }
else
return 1;}
csList.GOOGLE_WGS84="+title=GOOGLE MAP&EARTH / WGS84 +proj=longlat +a=6378137.0 +b=6356752.3146581478 +datum=WGS84"; 
csList.TM128_katech_3param="+title=TM128_katech (3 param datum shift) +proj=tmerc +lat_0=38.0 +lon_0=128.0 +x_0=400000.0 +y_0=600000.0 +k=0.9999 +a=6377397.155 +b=6356078.9633422494 +towgs84=-146.43,507.89,681.46,0,0,0,0 ";