
function GSComplex(real,imag){this.real=new Number(real);this.imag=new Number(imag);};GSComplex.prototype.add=function(c){return new GSComplex(this.real+c.real,this.imag+c.imag);};GSComplex.prototype.sub=function(c){return new GSComplex(this.real-c.real,this.imag-c.imag);};GSComplex.prototype.mul=function(c){return new GSComplex(this.real*c.real-this.imag*c.imag,this.real*c.imag+this.imag*c.real);};GSComplex.prototype.pow=function(power){if(power==0)
return new GSComplex(1,0);var c=this;for(var i=1;i<power;i++)
c=c.mul(this);return c;};GSComplex.prototype.div=function(c){var cmod2=c.real*c.real+c.imag*c.imag;return this.mul(new GSComplex(c.real/cmod2,-c.imag/cmod2));};GSComplex.prototype.scale=function(factor){return new GSComplex(this.real*factor,this.imag*factor);};GSComplex.prototype.equals=function(c){return this.real.toPrecision(15)==c.real.toPrecision(15)&&this.imag.toPrecision(15)==c.imag.toPrecision(15);};GSComplex.prototype.toString=function(){return this.real+"+"+this.imag+"i";};GSComplex.zero=new GSComplex(0,0);function GSGeodeticDatum(semiMajor,semiMinor,flatteningReciprocal,eccentricity1Squared,eccentricity2Squared){this.semiMajor=semiMajor;this.semiMinor=semiMinor;this.flatteningReciprocal=flatteningReciprocal;this.eccentricity1Squared=eccentricity1Squared;this.eccentricity2Squared=eccentricity2Squared;};GSGeodeticDatum.nzgd2000=new GSGeodeticDatum(6378137.0,6356752.314,298.257223563,6.694380067*Math.pow(10,-3),6.73949682*Math.pow(10,-3));GSGeodeticDatum.nzgd49=new GSGeodeticDatum(6378388.0,6356911.946,297.0,6.722670062*Math.pow(10,-3),6.768170238*Math.pow(10,-3));function GSCoordinateUtil(){};GSCoordinateUtil.A=[null,0.6399175073,-0.1358797613,0.063294409,-0.02526853,0.0117879,-0.0055161,0.0026906,-0.001333,0.00067,-0.00034];GSCoordinateUtil.B=[null,new GSComplex(0.7557853228,0.0),new GSComplex(0.249204646,0.003371507),new GSComplex(-0.001541739,0.041058560),new GSComplex(-0.10162907,0.01727609),new GSComplex(-0.26623489,-0.36249218),new GSComplex(-0.6870983,-1.1651967)];GSCoordinateUtil.C=[null,new GSComplex(1.3231270439,0.0),new GSComplex(-0.577245789,-0.007809598),new GSComplex(0.508307513,-0.112208952),new GSComplex(-0.15094762,0.18200602),new GSComplex(1.01418179,1.64497696),new GSComplex(1.9660549,2.5127645)];GSCoordinateUtil.D=[null,1.5627014243,0.5185406398,-0.03333098,-0.1052906,-0.0368594,0.007317,0.01220,0.00394,-0.0013];GSCoordinateUtil.nzmgToWgs84=function(coordinate){var g49=GSCoordinateUtil.nzmgToGeodeticNzgd49(coordinate);var p49=GSCoordinateUtil.geodeticNzgd49ToCartesianNzgd49(g49);var p2000=GSCoordinateUtil.cartesianNzgd49ToCartesianNzgd2000(p49);return GSCoordinateUtil.cartesianNzgd2000ToGeodeticNzgd2000(p2000);};GSCoordinateUtil.wgs84ToNzmg=function(latitude,longitude){var p2000=GSCoordinateUtil.geodeticNzgd2000ToCartesianNzgd2000({latitude:latitude,longitude:longitude});var p49=GSCoordinateUtil.cartesianNzgd2000ToCartesianNzgd49(p2000);var g49=GSCoordinateUtil.cartesianNzgd49ToGeodeticNzgd49(p49);return GSCoordinateUtil.geodeticNzgd49ToNzmg(g49);};GSCoordinateUtil.decimalToSexagesimal=function(decimalDegree){var sgn=decimalDegree>0?"":"-";var d=Math.abs(decimalDegree);var degrees=Math.floor(d);d=(d-degrees)*60;var minutes=Math.floor(d);d=(d-minutes)*60;var seconds=d.toFixed(3);return sgn+degrees+" "+minutes+" "+seconds;};GSCoordinateUtil.normalizeAngle=function(angle){angle=new String(angle);if(angle.indexOf(".")==5&&angle.substr(0,1)!="-"){var degreesLength=3;}else if(angle.indexOf(".")==6&&angle.substr(0,1)=="-"){var degreesLength=4;}else{alert(angle);throw new Error("Illegal argument: angle must be in format DDDMM.d+ (with an optional minus prefix)");return;}
var degrees=new Number(angle.substr(0,degreesLength));var minutes=new Number(angle.substr(degreesLength));if(degreesLength==3){return degrees+minutes/60;}else{return degrees-minutes/60;}};GSCoordinateUtil.nzmgToGeodeticNzgd49=function(c){var z=new GSComplex((c.y-6023150.0)/GSGeodeticDatum.nzgd49.semiMajor,(c.x-2510000.0)/GSGeodeticDatum.nzgd49.semiMajor);var theta=[];theta[0]=GSComplex.zero;for(var n=1;n<=6;n++)
theta[0]=theta[0].add(GSCoordinateUtil.C[n].mul(z.pow(n)));for(var i=0;i<=1;i++){var a=GSComplex.zero;var b=GSComplex.zero;for(var n=2;n<=6;n++)
a=a.add(GSCoordinateUtil.B[n].mul(theta[i].pow(n)).scale(n-1));for(var n=1;n<=6;n++)
b=b.add(GSCoordinateUtil.B[n].mul(theta[i].pow(n-1)).scale(n));theta[i+1]=(z.add(a)).div(b);}
var deltaPhi=0;for(var n=1;n<=9;n++)
deltaPhi+=GSCoordinateUtil.D[n]*Math.pow(theta[2].real,n);var deltaLambda=theta[2].imag;var coordinate={};coordinate.latitude=-41.0+deltaPhi*100000/3600;coordinate.longitude=173.0+deltaLambda*180/Math.PI;return coordinate;};GSCoordinateUtil.e0=2510000;GSCoordinateUtil.n0=6023150;GSCoordinateUtil.phi0=-41.0;GSCoordinateUtil.lambda0=173.0;GSCoordinateUtil.geodeticNzgd49ToNzmg=function(g49){var phi=g49.latitude;var lambda=g49.longitude;var deltaPhi=(phi-GSCoordinateUtil.phi0)*0.03600;var deltaPsi=0;for(var n=1;n<=10;n++){deltaPsi+=GSCoordinateUtil.A[n]*Math.pow(deltaPhi,n);}
deltaLambda=(lambda-GSCoordinateUtil.lambda0)*Math.PI/180;var theta=new GSComplex(deltaPsi,deltaLambda);var z=new GSComplex(0,0);for(var n=1;n<=6;n++){z=z.add(GSCoordinateUtil.B[n].mul(theta.pow(n)));}
var x=z.real;var y=z.imag;var easting=y*GSGeodeticDatum.nzgd49.semiMajor+GSCoordinateUtil.e0;var northing=x*GSGeodeticDatum.nzgd49.semiMajor+GSCoordinateUtil.n0;return new GSPoint(easting,northing);};GSCoordinateUtil.geodeticNzgd49ToCartesianNzgd49=function(g49){var theta=g49.latitude*Math.PI/180;var lambda=g49.longitude*Math.PI/180;var aSquared=Math.pow(GSGeodeticDatum.nzgd49.semiMajor,2);var bSquared=Math.pow(GSGeodeticDatum.nzgd49.semiMinor,2);var N=aSquared/Math.sqrt(aSquared*Math.pow(Math.cos(theta),2)+bSquared*Math.pow(Math.sin(theta),2));var point={};point.x=N*Math.cos(theta)*Math.cos(lambda);point.y=N*Math.cos(theta)*Math.sin(lambda);point.z=bSquared/aSquared*N*Math.sin(theta);return point;};GSCoordinateUtil.geodeticNzgd2000ToCartesianNzgd2000=function(g2000){var theta=g2000.latitude*Math.PI/180;var lambda=g2000.longitude*Math.PI/180;var aSquared=Math.pow(GSGeodeticDatum.nzgd2000.semiMajor,2);var bSquared=Math.pow(GSGeodeticDatum.nzgd2000.semiMinor,2);var N=aSquared/Math.sqrt(aSquared*Math.pow(Math.cos(theta),2)+bSquared*Math.pow(Math.sin(theta),2));var point={};point.x=N*Math.cos(theta)*Math.cos(lambda);point.y=N*Math.cos(theta)*Math.sin(lambda);point.z=bSquared/aSquared*N*Math.sin(theta);return point;};GSCoordinateUtil.cartesianNzgd49ToGeodeticNzgd49=function(p49){var a=GSGeodeticDatum.nzgd49.semiMajor;var b=GSGeodeticDatum.nzgd49.semiMinor;var e1=GSGeodeticDatum.nzgd49.eccentricity1Squared;var e2=GSGeodeticDatum.nzgd49.eccentricity2Squared;var p=Math.sqrt(p49.x*p49.x+p49.y*p49.y);var theta=Math.atan(p49.z*a/(p*b));var g49={};g49.latitude=Math.atan((p49.z+e2*b*Math.pow(Math.sin(theta),3))/(p-e1*a*Math.pow(Math.cos(theta),3)))*180/Math.PI;g49.longitude=Math.atan2(p49.y,p49.x)*180/Math.PI;return g49;};GSCoordinateUtil.cartesianNzgd2000ToGeodeticNzgd2000=function(p2000){var a=GSGeodeticDatum.nzgd2000.semiMajor;var b=GSGeodeticDatum.nzgd2000.semiMinor;var e1=GSGeodeticDatum.nzgd2000.eccentricity1Squared;var e2=GSGeodeticDatum.nzgd2000.eccentricity2Squared;var p=Math.sqrt(p2000.x*p2000.x+p2000.y*p2000.y);var theta=Math.atan(p2000.z*a/(p*b));var g2000={};g2000.latitude=Math.atan((p2000.z+e2*b*Math.pow(Math.sin(theta),3))/(p-e1*a*Math.pow(Math.cos(theta),3)))*180/Math.PI;g2000.longitude=Math.atan2(p2000.y,p2000.x)*180/Math.PI;return g2000;};GSCoordinateUtil.cartesianNzgd49ToCartesianNzgd2000=function(c49){var k=0.000004848137;var t={x:59.47,y:-5.04,z:187.44};var r={x:-0.47*k,y:0.10*k,z:-1.024*k};var scale=1+-4.5993*Math.pow(10,-6);return{x:t.x+scale*((1*c49.x)+(r.z*c49.y)+(-r.y*c49.z)),y:t.y+scale*((-r.z*c49.x)+(1*c49.y)+(r.x*c49.z)),z:t.z+scale*((r.y*c49.x)+(-r.x*c49.y)+(1*c49.z))};};GSCoordinateUtil.cartesianNzgd2000ToCartesianNzgd49=function(c49){var k=0.000004848137;var t={x:-59.47,y:5.04,z:-187.44};var r={x:0.47*k,y:-0.10*k,z:1.024*k};var scale=1+4.5993*Math.pow(10,-6);return{x:t.x+scale*((1*c49.x)+(r.z*c49.y)+(-r.y*c49.z)),y:t.y+scale*((-r.z*c49.x)+(1*c49.y)+(r.x*c49.z)),z:t.z+scale*((r.y*c49.x)+(-r.x*c49.y)+(1*c49.z))};};
