function OSGridNumberToLatLong(E,N){var a=6377563.396;var b=6356256.910;var F0=0.9996012717;var lat0=49*Math.PI/180;var lon0=-2*Math.PI/180;var N0=-100000;var E0=400000;var e2=1-(b*b)/(a*a);var n=(a-b)/(a+b);var n2=n*n;var n3=n2*n;var lat=lat0;var M=0;do{lat=(N-N0-M)/(a*F0)+lat;var Ma=(1+n+(5.0/4.0)*n2+(5.0/4.0)*n3)*(lat-lat0);var Mb=(3*n+3*n2+(21.0/8.0)*n3)*Math.sin(lat-lat0)*Math.cos(lat+lat0);var Mc=((15.0/8.0)*n2+(15.0/8.0)*n3)*Math.sin(2.0*(lat-lat0))*Math.cos(2.0*(lat+lat0));var Md=(35.0/24.0)*n3*Math.sin(3.0*(lat-lat0))*Math.cos(3.0*(lat+lat0));M=b*F0*(Ma-Mb+Mc-Md)}while(N-N0-M>=0.00001);var cosLat=Math.cos(lat);var sinLat=Math.sin(lat);var nu=a*F0/Math.sqrt(1.0-e2*sinLat*sinLat);var rho=a*F0*(1.0-e2)/Math.pow(1.0-e2*sinLat*sinLat,1.5);var eta2=nu/rho-1.0;var tanLat=Math.tan(lat);var tan2lat=tanLat*tanLat;var tan4lat=tan2lat*tan2lat;var tan6lat=tan4lat*tan2lat;var secLat=1/cosLat;var nu3=nu*nu*nu;var nu5=nu3*nu*nu;var nu7=nu5*nu*nu;var VII=tanLat/(2*rho*nu);var VIII=tanLat/(24.0*rho*nu3)*(5.0+3.0*tan2lat+eta2-9.0*tan2lat*eta2);var IX=tanLat/(720.0*rho*nu5)*(61.0+90.0*tan2lat+45.0*tan4lat);var X=secLat/nu;var XI=secLat/(6.0*nu3)*(nu/rho+2*tan2lat);var XII=secLat/(120.0*nu5)*(5.0+28.0*tan2lat+24.0*tan4lat);var XIIA=secLat/(5040.0*nu7)*(61.0+662.0*tan2lat+1320.0*tan4lat+720.0*tan6lat);var dE=(E-E0);var dE2=dE*dE;var dE3=dE2*dE;var dE4=dE2*dE2;var dE5=dE3*dE2;var dE6=dE4*dE2;var dE7=dE5*dE2;lat=lat-VII*dE2+VIII*dE4-IX*dE6;var lon=lon0+X*dE-XI*dE3+XII*dE5-XIIA*dE7;return new LatLon(lat.toDeg()+0.0008,lon.toDeg()-0.0013)}function LatLongToOSGrid(p){var lat=p.lat.toRad(),lon=p.lon.toRad();var a=6377563.396,b=6356256.910;var F0=0.9996012717;var lat0=(49).toRad();var lon0=(-2).toRad();var N0=-100000;var E0=400000;var e2=1-(b*b)/(a*a);var n=(a-b)/(a+b);var n2=n*n;var n3=n2*n;var cosLat=Math.cos(lat);var sinLat=Math.sin(lat);var nu=a*F0/Math.sqrt(1.0-e2*sinLat*sinLat);var rho=a*F0*(1-e2)/Math.pow(1.0-e2*sinLat*sinLat,1.5);var eta2=nu/rho-1.0;var Ma=(1+n+(5.0/4.0)*n2+(5.0/4.0)*n3)*(lat-lat0);var Mb=(3*n+3*n2+(21.0/8.0)*n3)*Math.sin(lat-lat0)*Math.cos(lat+lat0);var Mc=((15.0/8.0)*n2+(15.0/8.0)*n3)*Math.sin(2.0*(lat-lat0))*Math.cos(2.0*(lat+lat0));var Md=(35.0/24.0)*n3*Math.sin(3.0*(lat-lat0))*Math.cos(3.0*(lat+lat0));var M=b*F0*(Ma-Mb+Mc-Md);var cos3lat=cosLat*cosLat*cosLat;var cos5lat=cos3lat*cosLat*cosLat;var tan2lat=Math.tan(lat)*Math.tan(lat);var tan4lat=tan2lat*tan2lat;var I=M+N0;var II=(nu/2.0)*sinLat*cosLat;var III=(nu/24.0)*sinLat*cos3lat*(5.0-tan2lat+9.0*eta2);var IIIA=(nu/720.0)*sinLat*cos5lat*(61.0-58.0*tan2lat+tan4lat);var IV=nu*cosLat;var V=(nu/6.0)*cos3lat*(nu/rho-tan2lat);var VI=(nu/120.0)*cos5lat*(5.0-18.0*tan2lat+tan4lat+14.0*eta2-58.0*tan2lat*eta2);var dLon=lon-lon0;var dLon2=dLon*dLon;var dLon3=dLon2*dLon;var dLon4=dLon3*dLon;var dLon5=dLon4*dLon;var dLon6=dLon5*dLon;var N=I+II*dLon2+III*dLon4+IIIA*dLon6;var E=E0+IV*dLon+V*dLon3+VI*dLon5;return gridrefNumToLet(E,N,8)}function gridrefLetToNum(gridref){var l1=gridref.toUpperCase().charCodeAt(0)-'A'.charCodeAt(0);var l2=gridref.toUpperCase().charCodeAt(1)-'A'.charCodeAt(0);if(l1>7){l1--}if(l2>7){l2--}var e=((l1-2)%5)*5+(l2%5);var n=(19-Math.floor(l1/5)*5)-Math.floor(l2/5);gridref=gridref.slice(2).replace(/ /g,'');e+=gridref.slice(0,gridref.length/2);n+=gridref.slice(gridref.length/2);switch(gridref.length){case 6:e+='50';n+='50';break;case 8:e+='5';n+='5';break}return[e,n]}function gridrefNumToLet(e,n,digits){var e100k=Math.floor(e/100000);var n100k=Math.floor(n/100000);if(e100k<0||e100k>6||n100k<0||n100k>12){return''}var l1=(19-n100k)-(19-n100k)%5+Math.floor((e100k+10)/5);var l2=(19-n100k)*5%25+e100k%5;if(l1>7){l1++}if(l2>7){l2++}var letPair=String.fromCharCode(l1+'A'.charCodeAt(0),l2+'A'.charCodeAt(0));e=Math.floor((e%100000)/Math.pow(10,5-digits/2));n=Math.floor((n%100000)/Math.pow(10,5-digits/2));var gridRef=letPair+e.padLZ(digits/2)+n.padLZ(digits/2);return gridRef}Number.prototype.padLZ=function(width){var num=this.toString(),len=num.length;for(var i=0;i<width-len;i++){num='0'+num}return num};var e={WGS84:{a:6378137,b:6356752.3142,f:1/298.257223563},Airy1830:{a:6377563.396,b:6356256.910,f:1/299.3249646}};var h={WGS84toOSGB36:{tx:-446.448,ty:125.157,tz:-542.060,rx:-0.1502,ry:-0.2470,rz:-0.8421,s:20.4894},OSGB36toWGS84:{tx:446.448,ty:-125.157,tz:542.060,rx:0.1502,ry:0.2470,rz:0.8421,s:-20.4894}};function convertOSGB36toWGS84(p1){var p2=convert(p1,e.Airy1830,h.OSGB36toWGS84,e.WGS84);return p2}function convertWGS84toOSGB36(p1){var p2=convert(p1,e.WGS84,h.WGS84toOSGB36,e.Airy1830);return p2}function convert(p,e1,t,e2){p1=new LatLon(p.lat,p.lon,p.height);p1.lat=p.lat.toRad();p1.lon=p.lon.toRad();var a=e1.a,b=e1.b;var sinPhi=Math.sin(p1.lat);var cosPhi=Math.cos(p1.lat);var sinLambda=Math.sin(p1.lon);var cosLambda=Math.cos(p1.lon);var H=p1.height;var eSq=(a*a-b*b)/(a*a);var nu=a/Math.sqrt(1-eSq*sinPhi*sinPhi);var x1=(nu+H)*cosPhi*cosLambda;var y1=(nu+H)*cosPhi*sinLambda;var z1=((1-eSq)*nu+H)*sinPhi;var tx=t.tx;var ty=t.ty;var tz=t.tz;var rx=t.rx/3600*Math.PI/180;var ry=t.ry/3600*Math.PI/180;var rz=t.rz/3600*Math.PI/180;var s1=t.s/1e6+1;var x2=tx+x1*s1-y1*rz+z1*ry;var y2=ty+x1*rz+y1*s1-z1*rx;var z2=tz-x1*ry+y1*rx+z1*s1;a=e2.a;b=e2.b;var precision=4/a;eSq=(a*a-b*b)/(a*a);p=Math.sqrt(x2*x2+y2*y2);var phi=Math.atan2(z2,p*(1-eSq)),phiP=2*Math.PI;while(Math.abs(phi-phiP)>precision){nu=a/Math.sqrt(1-eSq*Math.sin(phi)*Math.sin(phi));phiP=phi;phi=Math.atan2(z2+eSq*nu*Math.sin(phi),p)}var lambda=Math.atan2(y2,x2);H=p/Math.cos(phi)-nu;return new LatLon(phi.toDeg(),lambda.toDeg(),H)}function LatLon(lat,lon,height){if(arguments.length<3){height=0}this.lat=lat;this.lon=lon;this.height=height}String.prototype.parseDeg=function(){var deg;if(!isNaN(this)){return Number(this)}var degLL=this.replace(/^-/,'').replace(/[NSEW]/i,'');var dms=degLL.split(/[^0-9.]+/);for(var i in dms){if(dms[i]==''){dms.splice(i,1)}}switch(dms.length){case 3:deg=dms[0]/1+dms[1]/60+dms[2]/3600;break;case 2:deg=dms[0]/1+dms[1]/60;break;case 1:if(/[NS]/i.test(this)){degLL='0'+degLL}deg=dms[0].slice(0,3)/1+dms[0].slice(3,5)/60+dms[0].slice(5)/3600;break;default:return NaN}if(/^-/.test(this)||/[WS]/i.test(this)){deg=-deg}return deg};Number.prototype.toRad=function(){return this*Math.PI/180};Number.prototype.toDeg=function(){return this*180/Math.PI};Number.prototype.toDMS=function(dp){if(arguments.length<1){dp=0}var d=Math.abs(this);var deg=Math.floor(d);var min=Math.floor((d-deg)*60);var sec=((d-deg-min/60)*3600).toFixed(dp);if(sec==60){sec=(0).toFixed(dp);min++}if(min==60){min=0;deg++}if(deg==360){deg=0}if(deg<100){deg='0'+deg}if(deg<10){deg='0'+deg}if(min<10){min='0'+min}if(sec<10){sec='0'+sec}return deg+'\u00B0'+min+'\u2032'+sec+'\u2033'};Number.prototype.toDMS2=function(dp){if(arguments.length<1){dp=0}var d=Math.abs(this);var seconds=(d*3600).toFixed(dp);var deg=Math.floor(seconds/3600);var min=Math.floor(seconds/60)%60;var sec=(seconds%60).toFixed(dp);if(deg<100){deg='0'+deg}if(deg<10){deg='0'+deg}if(min<10){min='0'+min}if(sec<10){sec='0'+sec}return deg+'\u00B0'+min+'\u2032'+sec+'\u2033'};Number.prototype.toLat=function(dp){return this.toDMS(dp).slice(1)+(this<0?'S':'N')};Number.prototype.toLon=function(dp){return this.toDMS(dp)+(this>0?'E':'W')};LatLon.prototype.toString=function(){return this.lat.toLat()+', '+this.lon.toLon()};function OSGridToLatLong(gridRef){var gr=gridrefLetToNum(gridRef);var E=gr[0];var N=gr[1];var a=6377563.396;var b=6356256.910;var F0=0.9996012717;var lat0=49*Math.PI/180;var lon0=-2*Math.PI/180;var N0=-100000;var E0=400000;var e2=1-(b*b)/(a*a);var n=(a-b)/(a+b);var n2=n*n;var n3=n2*n;var lat=lat0;var M=0;do{lat=(N-N0-M)/(a*F0)+lat;var Ma=(1+n+(5.0/4.0)*n2+(5.0/4.0)*n3)*(lat-lat0);var Mb=(3*n+3*n2+(21.0/8.0)*n3)*Math.sin(lat-lat0)*Math.cos(lat+lat0);var Mc=((15.0/8.0)*n2+(15.0/8.0)*n3)*Math.sin(2.0*(lat-lat0))*Math.cos(2.0*(lat+lat0));var Md=(35.0/24.0)*n3*Math.sin(3.0*(lat-lat0))*Math.cos(3.0*(lat+lat0));M=b*F0*(Ma-Mb+Mc-Md)}while(N-N0-M>=0.00001);var cosLat=Math.cos(lat);var sinLat=Math.sin(lat);var nu=a*F0/Math.sqrt(1.0-e2*sinLat*sinLat);var rho=a*F0*(1.0-e2)/Math.pow(1.0-e2*sinLat*sinLat,1.5);var eta2=nu/rho-1.0;var tanLat=Math.tan(lat);var tan2lat=tanLat*tanLat;var tan4lat=tan2lat*tan2lat;var tan6lat=tan4lat*tan2lat;var secLat=1/cosLat;var nu3=nu*nu*nu;var nu5=nu3*nu*nu;var nu7=nu5*nu*nu;var VII=tanLat/(2*rho*nu);var VIII=tanLat/(24.0*rho*nu3)*(5.0+3.0*tan2lat+eta2-9.0*tan2lat*eta2);var IX=tanLat/(720.0*rho*nu5)*(61.0+90.0*tan2lat+45.0*tan4lat);var X=secLat/nu;var XI=secLat/(6.0*nu3)*(nu/rho+2*tan2lat);var XII=secLat/(120.0*nu5)*(5.0+28.0*tan2lat+24.0*tan4lat);var XIIA=secLat/(5040.0*nu7)*(61.0+662.0*tan2lat+1320.0*tan4lat+720.0*tan6lat);var dE=(E-E0);var dE2=dE*dE;var dE3=dE2*dE;var dE4=dE2*dE2;var dE5=dE3*dE2;var dE6=dE4*dE2;var dE7=dE5*dE2;lat=lat-VII*dE2+VIII*dE4-IX*dE6;var lon=lon0+X*dE-XI*dE3+XII*dE5-XIIA*dE7;return new LatLon(lat.toDeg()+0.0008,lon.toDeg()-0.0013)}
