Solved

Convert this JS to VB

Posted on 2006-07-18
22
746 Views
Last Modified: 2008-01-09
Hi All,

I have this javascript that I would like to use in a vb app, but need a hand converting it to vb functions.

'Begin JS Code

//complex number functions from Javascript The Definitive Guide by David Flanagan

function Complex(real, imaginary) {
   this.x = real;
   this.y = imaginary;
}

// return magnitude of complex number
Complex.prototype.magnitude = function() {
  return Math.sqrt(this.x * this.x + this.y * this.y);
};

//return a complex number that is the negative of input
Complex.prototype.negative = function() {
  return new Complex(-this.x, -this.y);
};

//return the real portion of a complex number
Complex.prototype.valueOf = function() { return this.x; };

//add two complex numbers
Complex.add = function (a, b) {
  return new Complex(a.x + b.x, a.y + b.y);
};

//subtract two complex numbers
Complex.subtract = function (a, b) {
  return new Complex(a.x - b.x, a.y - b.y);
};
 
//multiply two complex numbers
Complex.multiply = function (a, b) {
  return new Complex(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
};
 
//divide two complex numbers
Complex.divide = function (a, b) {
  var cmod2 = b.x * b.x + b.y * b.y;
  var temp = new Complex(b.x / cmod2, -b.y / cmod2);
  return new Complex.multiply(a, temp);
};
 
//scale a complex number
Complex.scale = function (a, s) {
   return new Complex(a.x * s, a.y * s);
};

//power of a complex number
Complex.power = function(a, p) {
 if (p>0) {
   var ans = new Complex(a.x, a.y);
   for (il=1; il<p; il++) ans = Complex.multiply(ans, a);
 }
 else {
   var ans = new Complex(1, 1);
 }  
 return new Complex(ans.x,ans.y);
};    


Complex.prototype.toString = function() {
 return "{" + this.x + "," + this.y + "}";
};
   
var a =  6378388.0;
var n0 = 6023150.0;
var e0 = 2510000.0;
var lt0 = -41.0;
var ln0 = 173.0;

var cfi = new Array(0.6399175073,
                         -0.1358797613,
                           0.063294409,
                           -0.02526853,
                             0.0117879,
                            -0.0055161,
                             0.0026906,
                             -0.001333,
                               0.00067,
                              -0.00034);
                             
var cfl = new Array(1.5627014243,
                          0.5185406398,
                           -0.03333098,
                            -0.1052906,
                            -0.0368594,
                        0.007317,
                         0.01220,
                         0.00394,
                         -0.0013 );

var cfb1 = new Array(6);
cfb1[0] = new Complex(0.7557853228,           0.0);                                                       
cfb1[1] = new Complex(0.249204646,   0.003371507);
cfb1[2] = new Complex(-0.001541739,   0.041058560);
cfb1[3] = new Complex(-0.10162907,    0.01727609);
cfb1[4] = new Complex(-0.26623489,   -0.36249218);
cfb1[5] = new Complex(-0.6870983,    -1.1651967);

var cfb2 = new Array(6);
cfb2[0] = new Complex(1.3231270439,           0.0);
cfb2[1] = new Complex(-0.577245789,  -0.007809598);
cfb2[2] = new Complex(0.508307513,  -0.112208952);
cfb2[3] = new Complex(-0.15094762,    0.18200602);
cfb2[4] = new Complex(1.01418179,    1.64497696);
cfb2[5] = new Complex(1.9660549,     2.5127645);


     
function calcRandB(form, in1, in2, in3, in4) {             //calculate plane grid range and bearing
  // in1 - point 1 coordinates index
  // in2 - point 2 coordinates index
  // in3 - distance index
  // in4 - bearing index
  var de = parseFloat(form.east[in2].value) - parseFloat(form.east[in1].value);  //difference in eastings
  var dn = parseFloat(form.north[in2].value) - parseFloat(form.north[in1].value);  //difference in northings

  form.distvalue[in3].value = Math.sqrt(de * de + dn * dn);          //compute distance
  form.distvalue[in3].value = roundoff(form.distvalue[in3].value,distsize);  //round off distance
 
  var x = Math.atan2(de,dn);    //compute bearing, result in radians
  if (x < 0) {
     x += 2 * pi;             //if negative add 2*pi or 360 degrees
  }
  ddd2dms(form, in4, rad2deg(x));
return true;
}


function calcPoint(form, in1, in2, in3, in4) {           //calculate grid coordinates from plane grid range and bearing
  // in1 - point 1 coordinates index
  // in2 - point 2 coordinates index
  // in3 - distance index
  // in4 - bearing index

  var x = dms2ddd(form.degreevalue[in4].value, form.minutevalue[in4].value, form.secondvalue[in4].value);  //convert to decimal degrees
  x = deg2rad(x);             //convert to radians
  var dn = parseFloat(form.distvalue[in3].value) * Math.cos(x) ;  
  var de = parseFloat(form.distvalue[in3].value) * Math.sin(x) ;  
  form.north[in2].value = parseFloat(form.north[in1].value) + dn;
  form.east[in2].value = parseFloat(form.east[in1].value) + de;
  form.north[in2].value = roundoff(form.north[in2].value,distsize);
  form.east[in2].value = roundoff(form.east[in2].value,distsize);
return true;
}


function deg2rad(x){                //convert decimal degrees to radians
   
  x = x * pi / 180;
  return x;
}

function rad2deg(x){                //convert radians to decimal degrees
   
  x = x * 180 / pi;
  return x;
}

function roundoff(x,y){              //round off x to y decimal places
  x = parseFloat(x);
  y = parseFloat(y);
  x = Math.round(x * Math.pow(10,y))/Math.pow(10,y);
  return x;
}

function dms2ddd(d,m,s){

  if (isblank(d)) d = '0';
   else {
      var y = d.slice(0, 1);
      d = parseFloat(d);
   }
  if (isblank(m)) m = '0';
   else
      m = parseFloat(m);
  if (isblank(s)) s = '0';
   else
      s = parseFloat(s);
  var x = Math.abs(d) + (Math.abs(m) / 60) + (Math.abs(s) / 3600);  //convert to decimal degrees
  if ((y == "-") || (d < 0) || (m < 0) || (s < 0)) x = -x;
  return x;

}

function isblank(s)
{
  for(var i = 0; i < s.length; i++) {
      var c = s.charAt(i);
      if ((c != ' ') && (c != '\n') && (c != '\t')) return false;
  }
  return true;
}

function geo2grid(form, in1, in2, in3, in4, in5){
  // in1 - point latitude index
  // in2 - point longitude index
  // in3 - point grid coordinates
  // in4 - grid convergence index
  // in5 - point scale factor index
 
  var a =  6378388.0;
var n0 = 6023150.0;
var e0 = 2510000.0;
var lt0 = -41.0;
var ln0 = 173.0;


  var latddd = dms2ddd(form.degreevalue[in1].value, form.minutevalue[in1].value, form.secondvalue[in1].value);  // convert latitude of point to decimal degrees then radians
  var latrad = deg2rad(latddd);
  var londdd = dms2ddd(form.degreevalue[in2].value, form.minutevalue[in2].value, form.secondvalue[in2].value);  // likewise for longitude
  var lonrad = deg2rad(londdd);

var lt = (latddd - lt0) * 0.03600;
var sum = 0;
for (i=0; i < 10; i++) {
  sum = sum + cfi[i] * Math.pow(lt, i + 1);
}

var z1 = new Complex(sum, deg2rad(londdd - ln0));

var z0 = new Complex(0,0);
var z2 = new Complex(0,0);
var z3 = new Complex(0,0);

for (ij=0; ij<6; ij++) {
  z2 = Complex.power(z1, ij+1);
  z3 = Complex.multiply(cfb1[ij], z2);  
  z0 =  Complex.add(z0,z3);
}
form.north[in3].value = n0 + z0.x * a;
form.east[in3].value = e0 + z0.y * a;
}


function grid2geo(form, in1, in2, in3, in4, in5){
  // in1 - point latitude index
  // in2 - point longitude index
  // in3 - point grid coordinates
  // in4 - grid convergence index
  // in5 - point scale factor index

var a =  6378388.0;
var n0 = 6023150.0;
var e0 = 2510000.0;
var lt0 = -41.0;
var ln0 = 173.0;

var north = parseFloat(form.north[in3].value);
var east = parseFloat(form.east[in3].value);

var z = new Complex((north - n0)/a, (east - e0)/a);

var z1 = new Complex(0,0);
var z2 = new Complex(0,0);
var z3 = new Complex(0,0);
for (ij=0; ij<6; ij++) {
  z2 = Complex.power(z,ij+1);
  z3 = Complex.multiply(cfb2[ij],z2);
  z1 = Complex.add(z1, z3);
}
for (kk=0; kk<2; kk++) {
z2 = new Complex(0,0);
for (ij=2; ij<7; ij++) {
  z2 = Complex.add(z2,(Complex.multiply(Complex.power(z1,ij),Complex.scale(cfb1[ij-1],(ij-1)))));
}


 z3 = new Complex(cfb1[0].x, cfb1[0].y);
 z3 = Complex.add(z3, Complex.multiply(Complex.scale(cfb1[1],2),z1));
 z3 = Complex.add(z3, Complex.multiply(Complex.scale(cfb1[2],3),Complex.power(z1,2)));
 z3 = Complex.add(z3, Complex.multiply(Complex.scale(cfb1[3],4),Complex.power(z1,3)));
 z3 = Complex.add(z3, Complex.multiply(Complex.scale(cfb1[4],5),Complex.power(z1,4)));
 z3 = Complex.add(z3, Complex.multiply(Complex.scale(cfb1[5],6),Complex.power(z1,5)));

 z1 = Complex.divide(Complex.add(z,z2),z3);
}
var dphi = 0;
for (ij=1; ij<10; ij++) {
  dphi = dphi + cfl[ij-1] * Math.pow(z1.x,ij);
}

var latdeg = lt0 + (dphi * 100000 / 3600);
var londeg = ln0 + rad2deg(z1.y);

  ddd2dms(form, in1, latdeg);
  ddd2dms(form, in2, londeg);
}

function tttghg() {
// calclulate constants required for Redfern's formulae
  var k = parseFloat(form.k.value);  //scale factor
  var a = parseFloat(form.a.value);  //semi-major axis
  var f = 1 / parseFloat(form.invf.value);  //flattening
  var b = a * (1 - f);    //semi-minor axis
  var e2 = (a * a - b * b)/(a * a);  //eccentricity squared
  var e = Math.sqrt(e2);  //eccentricity
  var ei2 = (a * a - b * b)/(b * b); //second eccentricity squared
  var ei = Math.sqrt(ei2); //second eccentricity
  var n = (a - b)/(a + b);
  var G = a * (1 - n) * (1 - n * n) * (1 + (9 / 4) * n * n + (255 / 64) * Math.pow(n,4)) * (pi / 180);  //Mean length of an arc of one degree of the meridian
  var north = (parseFloat(form.north[in3].value) - parseFloat(form.falsenorth.value)) * units;  //northing from the equator
  var east = (parseFloat(form.east[in3].value) - parseFloat(form.falseeast.value)) * units; //easting from the CM
  var m = north / k;  //meridian distance
  var sigma = (m * pi) / (180 * G);

// calculate the foot point latitude and constants for that latitude
  var footlat = sigma + ((3 * n / 2) - (27 * Math.pow(n, 3) / 32)) * Math.sin(2 * sigma) + ((21 * n * n / 16) - (55 * Math.pow(n, 4) / 32)) * Math.sin(4 * sigma) + (151 * Math.pow(n, 3) / 96) * Math.sin(6 * sigma) + (1097 * Math.pow(n, 4) / 512) * Math.sin(8 * sigma);
  var rho = a * (1 - e2) / Math.pow(1 - (e2 * Math.sin(footlat) * Math.sin(footlat)),(3/2)); //radius of curvature in plane of meridian
  var nu = a / Math.sqrt(1 - (e2 * Math.sin(footlat) * Math.sin(footlat))); //radius of curvature in prime vertical
  var psi = nu / rho;
  var t = Math.tan(footlat);  //tan of latitude

// calculate latitude
  var x = east / (k * nu);
  var laterm1 = (t / (k * rho )) * ( east * x / 2);
  var laterm2 = (t / (k * rho )) * ( east * Math.pow(x, 3) / 24) * (-4 * psi * psi + 9 * psi * (1 - t * t) + 12 * t * t );
  var laterm3 = (t / (k * rho )) * ( east * Math.pow(x, 5) / 720) * (8 * Math.pow(psi, 4) * (11 - 24 * t * t) - 12 * Math.pow(psi, 3) * (21 - 71 * t * t) + 15 * psi * psi * (15 - 98 * t * t + 15 * Math.pow(t, 4)) + 180 * psi * (5 * t * t - 3 * Math.pow(t, 4)) + 360 * Math.pow(t, 4));
  var laterm4 = (t / (k * rho )) * ( east * Math.pow(x, 7) / 40320) * (1385 + 3633 * t * t + 4095 * Math.pow(t, 4) + 1575 * Math.pow(t, 6));
  var latrad = footlat - laterm1 + laterm2 - laterm3 + laterm4;

  ddd2dms(form, in1, rad2deg(latrad));
 
// calculate longitude
  var seclat = 1 / Math.cos(footlat);
  var loterm1 = x * seclat;
  var loterm2 = (Math.pow(x, 3) / 6) * seclat * (psi + 2 * t * t);
  var loterm3 = (Math.pow(x, 5) / 120) * seclat * (-4 * Math.pow(psi, 3) * (1 - 6 * t * t) + psi * psi * (9 -68 * t * t) + 72 * psi * t * t + 24 * Math.pow(t, 4));
  var loterm4 = (Math.pow(x, 7) / 5040) * seclat * (61 + 662 * t * t + 1320 * Math.pow(t, 4) + 720 * Math.pow(t, 6));
  var w = loterm1 - loterm2 + loterm3 - loterm4;
  var longrad = deg2rad(parseFloat(form.cmlong.value)) + w;

  ddd2dms(form, in2, rad2deg(longrad));

// calculate grid convergence
  var gterm1 = -t * x;
  var gterm2 = (t * Math.pow(x, 3) / 3) * (-2 * psi * psi + 3 * psi + t * t);
  var gterm3 = (-t * Math.pow(x, 5) / 15) * (Math.pow(psi, 4) * (11 - 24 * t * t) - 3 * Math.pow(psi, 3) * (8 - 23 * t * t) + 5 * psi * psi * (3 - 14 * t * t) + 30 * psi * t * t + 3 * Math.pow(t, 4));
  var gterm4 = (t * Math.pow(x, 7) / 315) * (17 +77 * t * t + 105 * Math.pow(t, 4) + 45 * Math.pow(t, 6));
  var gridconv = gterm1 + gterm2 + gterm3 + gterm4;

  ddd2dms(form, in4, rad2deg(gridconv));

// calculate point scale factor
  x = east * east / (k * k * rho * nu);
  var kterm1 = x / 2;
  var kterm2 = (x * x / 24) * (4 * psi * (1 - 6 * t * t) - 3 * (1 - 16 * t * t) - 24 * t * t / psi);
  var kterm3 = Math.pow(x, 3) / 720 ;
  var pointk = k * (1 + kterm1 + kterm2 + kterm3);
  form.pointk[in5].value = roundoff(pointk, bearsize);  
     
return true;
}

function calcRandBgeo(form, in1, in2, in3, in4, in5, in6){
  // in1 - point 1 latitude index
  // in2 - point 1 longitude index
  // in3 - point 2 latitude index
  // in4 - point 2 longitude index
  // in5 - distance index
  // in6 - bearing index

var j = form.units.selectedIndex;
var units = form.units.options[j].value;

// calclulate constants
//  var k = parseFloat(form.k.value);  //scale factor
  var a = parseFloat(form.a.value);  //semi-major axis
  var f = 1 / parseFloat(form.invf.value);  //flattening
  var b = a * (1 - f);    //semi-minor axis
 
  var latddd1 = dms2ddd(form.degreevalue[in1].value, form.minutevalue[in1].value, form.secondvalue[in1].value);  // convert latitude of point to decimal degrees then radians
  var latrad1 = deg2rad(latddd1);
  var londdd1 = dms2ddd(form.degreevalue[in2].value, form.minutevalue[in2].value, form.secondvalue[in2].value);  // likewise for longitude
  var lonrad1 = deg2rad(londdd1);
  var latddd2 = dms2ddd(form.degreevalue[in3].value, form.minutevalue[in3].value, form.secondvalue[in3].value);  // convert latitude of point to decimal degrees then radians
  var latrad2 = deg2rad(latddd2);
  var londdd2 = dms2ddd(form.degreevalue[in4].value, form.minutevalue[in4].value, form.secondvalue[in4].value);  // likewise for longitude
  var lonrad2 = deg2rad(londdd2);

  var w = lonrad2 - lonrad1;

  if (Math.abs(w) > 1.5707963268) {
     alert("Sorry this calculator isn't designed for such large distances.\nTry my Great Circle Calculator instead.");
  }
  var tanB1 = Math.tan(latrad1) * (1 - f);
  var tanB2 = Math.tan(latrad2) * (1 - f);
  var B1 = Math.atan(tanB1);
  var B2 = Math.atan(tanB2);

  var term1 = Math.sin(w) * Math.cos(B2);
  var term2 = Math.sin(B2) * Math.cos(B1) - Math.sin(B1) * Math.cos(B2) * Math.cos(w);
  var phi = Math.asin(Math.sqrt(term1 * term1 + term2 * term2));
  var c = (Math.cos(B1) * Math.cos(B2) * Math.sin(w)) / Math.sin(phi);
  var m = 1 - c * c;
 
  term1 = phi * (1 + f + f * f)
  term2 = Math.sin(B1) * Math.sin(B2) * ((f + f * f) * Math.sin(phi) - ((f * f / 2) * phi * phi / Math.sin(phi)));
  var term3 = m * (-1 * (phi * (f + f * f) / 2) - ((f + f * f) / 2) * Math.sin(phi) * Math.cos(phi) + ((f * f / 2) * phi * phi) / Math.tan(phi));
  var term4 = Math.sin(B1) * Math.sin(B2) * Math.sin(B1) * Math.sin(B2) * (-1 * (f * f /2) * Math.sin(phi) * Math.cos(phi));
  var term5 = m * m * ((f * f / 16 ) * phi + (f * f / 16) * Math.sin(phi) * Math.cos(phi) - (f * f / 2) * phi * phi / Math.tan(phi) - (f * f / 8) * Math.sin(phi) * Math.pow(Math.cos(phi), 3));
  var term6 = Math.sin(B1) * Math.sin(B2) * m * ((f * f / 2) * phi * phi / Math.sin(phi) + (f * f / 2) * Math.sin(phi) * Math.cos(phi) * Math.cos(phi));
  var s = b * (term1 + term2 + term3 + term4 + term5 + term6);
  form.distvalue[in5].value = roundoff((s / units), distsize);  //round off distance
 
  term1 = (f + f * f) * phi;
  term2 = Math.sin(B1) * Math.sin(B2) * ( -1 * (f * f / 2) * Math.sin(phi) - f * f * phi * phi / Math.sin(phi));
  term3 = m * (-1 * (5 * f * f / 4) * phi + (f * f /4) * Math.sin(phi) * Math.cos(phi) + f * f * phi * phi / Math.tan(phi));
  lamda = c * (term1 + term2 + term3) + w;
 
  var de = Math.sin(B2) * Math.cos(B1) - Math.cos(lamda) * Math.sin(B1) * Math.cos(B2);
  var dn = Math.sin(lamda) * Math.cos(B2);
  var x = Math.atan2(dn,de);    //compute bearing, result in radians
  if (x < 0) {
     x += 2 * pi;             //if negative add 2*pi or 360 degrees
  }

if (w == 0) {
   if (latddd2 < latddd1)
       x =  pi;
   else if (latddd2 > latddd1)
       x = 0;
   else if (latddd2 == latddd1) {
       x = 0;
       form.distvalue[in5].value = roundoff(0, distsize);  //round off distance
   }
}
  ddd2dms(form, in6, rad2deg(x));
   
return true;
}


function calcPointgeo(form, in1, in2, in3, in4, in5, in6){
  // in1 - point 1 latitude index
  // in2 - point 1 longitude index
  // in3 - point 2 latitude index
  // in4 - point 2 longitude index
  // in5 - distance index
  // in6 - bearing index

var j = form.units.selectedIndex;
var units = form.units.options[j].value;

// calclulate constants
//  var k = parseFloat(form.k.value);  //scale factor
  var a = parseFloat(form.a.value);  //semi-major axis
  var f = 1 / parseFloat(form.invf.value);  //flattening
  var b = a * (1 - f);    //semi-minor axis
  var e2 = (a * a - b * b)/(a * a);  //eccentricity squared
  var e = Math.sqrt(e2);  //eccentricity
  var ei2 = (a * a - b * b)/(b * b); //second eccentricity squared
  var ei = Math.sqrt(ei2); //second eccentricity
 
  var latddd1 = dms2ddd(form.degreevalue[in1].value, form.minutevalue[in1].value, form.secondvalue[in1].value);  // convert latitude of point to decimal degrees then radians
  var latrad1 = deg2rad(latddd1);
  var londdd1 = dms2ddd(form.degreevalue[in2].value, form.minutevalue[in2].value, form.secondvalue[in2].value);  // likewise for longitude
  var lonrad1 = deg2rad(londdd1);
  var x12 = dms2ddd(form.degreevalue[in6].value, form.minutevalue[in6].value, form.secondvalue[in6].value);  //convert to decimal degrees
  x12 = deg2rad(x12);             //convert to radians
  var s = (parseFloat(form.distvalue[in5].value) * units);  
 
  if (Math.abs(s) > 10019148.059) {
     alert("Sorry this calculator isn't designed for such large distances.\nTry my Great Circle Calculator instead.");
  }
  var tanB1 = Math.tan(latrad1) * (1 - f);
  var B1 = Math.atan(tanB1);
  var cosB0 = Math.cos(B1) * Math.sin(x12);
  var B0 = Math.acos(cosB0);
  var g = Math.cos(B1) * Math.cos(x12);
  var m = (1 + (ei2 / 2) * Math.sin(B1) * Math.sin(B1)) * (1 - Math.cos(B0) * Math.cos(B0));
  var phis = s / b;
  var a1 = (1 + (ei2 / 2) * Math.sin(B1) * Math.sin(B1)) * (Math.sin(B1) * Math.sin(B1) * Math.cos(phis) + g * Math.sin(B1) * Math.sin(phis));

  var term1 = a1 * (-1 * (ei2 / 2) * Math.sin(phis));
  var term2 = m * (-1 * (ei2 / 4) * phis + (ei2 / 4) * Math.sin(phis) * Math.cos(phis));
  var term3 = a1 * a1 * ((5 * ei2 * ei2 / 8) * Math.sin(phis) * Math.cos(phis));
  var term4 = m * m * (( 11 * ei2 * ei2 / 64) * phis - (13 * ei2 * ei2 / 64) * Math.sin(phis) * Math.cos(phis) - (ei2 * ei2 / 8) * phis * Math.cos(phis) * Math.cos(phis) + (5 * ei2 * ei2 / 32) * Math.sin(phis) * Math.pow(Math.cos(phis), 3));
  var term5 = a1 * m * ((3 * ei2 * ei2 / 8) * Math.sin(phis) + (ei2 * ei2 /4) * phis * Math.cos(phis) - (5 * ei2 * ei2 / 8) * Math.sin(phis) * Math.cos(phis) * Math.cos(phis));
  var phi0 = phis + term1 + term2 + term3 + term4 + term5;
 
  var cotlamda = (Math.cos(B1) * Math.cos(phi0) - Math.sin(B1) * Math.sin(phi0) * Math.cos(x12)) / (Math.sin(phi0) * Math.sin(x12));
  var lamda = Math.atan(1 / cotlamda);
 
  term1 = -1 * f * phis;
  term2 = a1 * ((3 * f * f / 2) * Math.sin(phis));
  term3 = m * ((3 * f * f / 4) * phis - (3 * f * f / 4) * Math.sin(phis) * Math.cos(phis));
  var w = (term1 + term2 + term3) * Math.cos(B0) + lamda;

  var lonrad2 = lonrad1 + w;
  ddd2dms(form, in4, rad2deg(lonrad2));

  var sinB2 = Math.sin(B1) * Math.cos(phi0) + g * Math.sin(phi0);
  var cosB2 = Math.sqrt((Math.cos(B0) * Math.cos(B0)) + Math.pow((g * Math.cos(phi0) - Math.sin(B1) * Math.sin(phi0)), 2));
  var tanB2 = sinB2 / cosB2;
  var tanlat2 = tanB2 / (1 - f);
  var latrad2 = Math.atan(tanlat2);
  ddd2dms(form, in3, rad2deg(latrad2));

return true;
}

function ddd2dms(form, ind, bearing){
  var y = Math.abs(parseFloat(bearing));
  form.degreevalue[ind].value = parseInt(y + 1) - 1;
  var x = y - form.degreevalue[ind].value;    
  form.minutevalue[ind].value = parseInt(x * 60 + 1) - 1;
  form.secondvalue[ind].value = ((x * 60) - form.minutevalue[ind].value) * 60;
  form.secondvalue[ind].value = roundoff(form.secondvalue[ind].value,secsize);
  if (form.secondvalue[ind].value == 60) {
      form.secondvalue[ind].value = "0";
      form.minutevalue[ind].value = form.minutevalue[ind].value * 1 + 1;
      if (form.minutevalue[ind].value == 60) {
        form.minutevalue[ind].value = "0";
        form.degreevalue[ind].value = form.degreevalue[ind].value * 1 + 1;
      }
  }
  if (bearing < 0) {
     if (form.degreevalue[ind].value != 0)
        form.degreevalue[ind].value = -form.degreevalue[ind].value;
     else if (form.minutevalue[ind].value != 0)
        form.minutevalue[ind].value = -form.minutevalue[ind].value;
     else
        form.secondvalue[ind].value = -form.secondvalue[ind].value;
  }  
  form.degreevalue[ind].value += "\260";                                        // add degrees symbol now we have finished with value
  form.minutevalue[ind].value += "\'";                                        //add minute symbol now we have finished with value
  form.secondvalue[ind].value += '\"';               //round off seconds and add symbol
return true;
}

function confirmSphChange(form){             //to only allow changes to spheroid parameters if in user defined mode

var i = form.spheroid.selectedIndex;
if (i != 22) {
  form.a.blur();
  form.invf.blur();
  alert("\n To override Spheroid Parameters\n use the User Defined option.");
}
return true;
}
 
 

function updateSpheroid(form){

var i = form.spheroid.selectedIndex;
switch(i) {
  case 0:
    form.a.value = 6378388.000;
    form.invf.value = 297.000;
    break;
}
return true;
}

function confirmProjChange(form){             //to only allow changes to projection parameters if in user defined mode

var i = form.projection.selectedIndex;
if (i != 2) {
  form.falsenorth.blur();
  form.falseeast.blur();
  form.k.blur();
  alert("\n To override Projection Parameters\n use the User Defined option.");
}
return true;
}

function updateProjection(form, x){

var i = form.projection.selectedIndex;
var j = form.units.selectedIndex;
var units = form.units.options[j].value;
switch(i) {
  case 0:
    form.falsenorth.value = 0;
    form.falseeast.value = 500000 / units;
    form.k.value = 0.9996;
    break;
  case 1:
    form.falsenorth.value = 10000000 / units;
    form.falseeast.value = 500000 / units;
    form.k.value = 0.9996;
    break;
  case 2:
    if (x == 1) {                  // only reset if called from projection selection not grid units
      form.falsenorth.value = '';
      form.falseeast.value = '';
      form.k.value = '';
    }
    break;
}
}

function swapgeos(form){
  var x = form.degreevalue[0].value;
  form.degreevalue[0].value = form.degreevalue[5].value;
  form.degreevalue[5].value = x;
  x = form.degreevalue[1].value;
  form.degreevalue[1].value = form.degreevalue[6].value;
  form.degreevalue[6].value = x;

  x = form.minutevalue[0].value;
  form.minutevalue[0].value = form.minutevalue[5].value;
  form.minutevalue[5].value = x;
  x = form.minutevalue[1].value;
  form.minutevalue[1].value = form.minutevalue[6].value;
  form.minutevalue[6].value = x;
 
  x = form.secondvalue[0].value;
  form.secondvalue[0].value = form.secondvalue[5].value;
  form.secondvalue[5].value = x;
  x = form.secondvalue[1].value;
  form.secondvalue[1].value = form.secondvalue[6].value;
  form.secondvalue[6].value = x;
return true;
}

function swapgrid(form){
  var x = form.north[0].value;
  form.north[0].value = form.north[1].value;
  form.north[1].value = x;
  x = form.east[0].value;
  form.east[0].value = form.east[1].value;
  form.east[1].value = x;
return true;
}

function updateCM(form){
  var zone = parseFloat(form.zone.value);
  if ((zone < 1) || (zone > 60) || isblank(form.zone.value)) {
     form.zone.value = "";
     alert("\n  Please enter a UTM Zone number\n between 1 and 60.");
     form.zone.focus();
  }
  else {
     form.cmlong.value =  zone * 6 - 183 + "\260";
  }
}

function updateZone(form){
  var cmlong = parseFloat(form.cmlong.value);
  if ((cmlong < -180) || (cmlong > 180) || isblank(form.cmlong.value)) {
     form.cmlong.value = "";
     alert("\n Please enter a Longitude of Central Meridian between +/- 180\260");
     form.cmlong.focus();
  }
  else {
     form.zone.value = roundoff(((cmlong + 183) / 6), 2);
  }
}


'End JS Code

0
Comment
Question by:nzfire
  • 12
  • 10
22 Comments
 
LVL 1

Author Comment

by:nzfire
Comment Utility
Alternatively, I have 'C' source code to the above...
0
 
LVL 15

Expert Comment

by:bpmurray
Comment Utility
It's easy enough to convert this,  as long as you give ALL the information. For example, many of the functions have a parameter "form" - what is this? Is it an HTML form or is it something else? What are its fields?

Just to give you an idea of how it can be done, the complex number functionality can be converted to:
Public Class Complex
    Public x As Integer, y As Integer

    Public Sub New(ByVal real As Integer, ByVal imaginary As Integer)
        x = real
        y = imaginary
    End Sub

    '  return magnitude of complex number
    Public Function magnitude() As Double
        Return Math.Sqrt(Me.x * Me.x + Me.y * Me.y)
    End Function

    ' return a complex number that is the negative of input
    Public Function negative() As Complex
        Return New Complex(-Me.x, -Me.y)
    End Function

    ' return the real portion of a complex number
    Public Function valueOf() As Integer
        Return Me.x
    End Function

    ' add two complex numbers
    Public Function add(ByVal b As Complex) As Complex
        Return New Complex(Me.x + b.x, Me.y + b.y)
    End Function

    ' subtract two complex numbers
    Public Function subtract(ByVal b As Complex) As Complex
        Return New Complex(Me.x - b.x, Me.y - b.y)
    End Function

    ' multiply two complex numbers
    Public Function multiply(ByVal b As Complex) As Complex
        Return New Complex(Me.x * b.x - Me.y * b.y, Me.x * b.y + Me.y * b.x)
    End Function

    ' divide two complex numbers
    Public Function divide(ByVal b As Complex) As Complex
        Dim cmod2 As Integer
        Dim temp As Complex

        cmod2 = b.x * b.x + b.y * b.y
        temp = New Complex(b.x / cmod2, -b.y / cmod2)
        Return Me.multiply(temp)
    End Function

    ' scale a complex number
    Public Function scale(ByVal s As Integer)
        Return New Complex((Me.x) * s, (Me.y) * s)
    End Function

    ' power of a complex number
    Public Function power(ByVal p As Integer)
        Dim ans As Complex
        Dim il As Integer
        If (p > 0) Then
            ans = New Complex(Me.x, Me.y)
            For il = 1 To p
                ans = ans.multiply(ans)
            Next
        Else
            ans = New Complex(1, 1))
        End If
        Return New Complex(ans.x, ans.y)
    End Function

    Public Overrides Function toString() As String
        Return "{" + Me.x + "," + Me.y + "}"
    End Function

End Class
0
 
LVL 1

Author Comment

by:nzfire
Comment Utility
Hi bpmurray,

Thanks so much for doing it this far. Sorry about the lack of information. Yes, it is an HTML form.

The 2 functions that I require are: geo2grid and grid to geo. I will post the HTML here if that helps.

If you view the page, the calculations that are performed in the "Point 1" area are all I require.

Thanks once again.

'/Begin code

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Untitled Document</title>
<SCRIPT language=JavaScript type=text/javascript>
<!--

   var pi = Math.PI;
   var secsize = 4;       // round second display to
   var distsize = 3;      // round distance display to
   var bearsize = 8;      // round bearing display to
   
   

//complex number functions from Javascript The Definitive Guide by David Flanagan

function Complex(real, imaginary) {
   this.x = real;
   this.y = imaginary;
}

// return magnitude of complex number
Complex.prototype.magnitude = function() {
  return Math.sqrt(this.x * this.x + this.y * this.y);
};

//return a complex number that is the negative of input
Complex.prototype.negative = function() {
  return new Complex(-this.x, -this.y);
};

//return the real portion of a complex number
Complex.prototype.valueOf = function() { return this.x; };

//add two complex numbers
Complex.add = function (a, b) {
  return new Complex(a.x + b.x, a.y + b.y);
};

//subtract two complex numbers
Complex.subtract = function (a, b) {
  return new Complex(a.x - b.x, a.y - b.y);
};
 
//multiply two complex numbers
Complex.multiply = function (a, b) {
  return new Complex(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
};
 
//divide two complex numbers
Complex.divide = function (a, b) {
  var cmod2 = b.x * b.x + b.y * b.y;
  var temp = new Complex(b.x / cmod2, -b.y / cmod2);
  return new Complex.multiply(a, temp);
};
 
//scale a complex number
Complex.scale = function (a, s) {
   return new Complex(a.x * s, a.y * s);
};

//power of a complex number
Complex.power = function(a, p) {
 if (p>0) {
   var ans = new Complex(a.x, a.y);
   for (il=1; il<p; il++) ans = Complex.multiply(ans, a);
 }
 else {
   var ans = new Complex(1, 1);
 }  
 return new Complex(ans.x,ans.y);
};    


Complex.prototype.toString = function() {
 return "{" + this.x + "," + this.y + "}";
};
   
var a =  6378388.0;
var n0 = 6023150.0;
var e0 = 2510000.0;
var lt0 = -41.0;
var ln0 = 173.0;

var cfi = new Array(0.6399175073,
                         -0.1358797613,
                           0.063294409,
                           -0.02526853,
                             0.0117879,
                            -0.0055161,
                             0.0026906,
                             -0.001333,
                               0.00067,
                              -0.00034);
                             
var cfl = new Array(1.5627014243,
                          0.5185406398,
                           -0.03333098,
                            -0.1052906,
                            -0.0368594,
                        0.007317,
                         0.01220,
                         0.00394,
                         -0.0013 );

var cfb1 = new Array(6);
cfb1[0] = new Complex(0.7557853228,           0.0);                                                       
cfb1[1] = new Complex(0.249204646,   0.003371507);
cfb1[2] = new Complex(-0.001541739,   0.041058560);
cfb1[3] = new Complex(-0.10162907,    0.01727609);
cfb1[4] = new Complex(-0.26623489,   -0.36249218);
cfb1[5] = new Complex(-0.6870983,    -1.1651967);

var cfb2 = new Array(6);
cfb2[0] = new Complex(1.3231270439,           0.0);
cfb2[1] = new Complex(-0.577245789,  -0.007809598);
cfb2[2] = new Complex(0.508307513,  -0.112208952);
cfb2[3] = new Complex(-0.15094762,    0.18200602);
cfb2[4] = new Complex(1.01418179,    1.64497696);
cfb2[5] = new Complex(1.9660549,     2.5127645);


     
function calcRandB(form, in1, in2, in3, in4) {             //calculate plane grid range and bearing
  // in1 - point 1 coordinates index
  // in2 - point 2 coordinates index
  // in3 - distance index
  // in4 - bearing index
  var de = parseFloat(form.east[in2].value) - parseFloat(form.east[in1].value);  //difference in eastings
  var dn = parseFloat(form.north[in2].value) - parseFloat(form.north[in1].value);  //difference in northings

  form.distvalue[in3].value = Math.sqrt(de * de + dn * dn);          //compute distance
  form.distvalue[in3].value = roundoff(form.distvalue[in3].value,distsize);  //round off distance
 
  var x = Math.atan2(de,dn);    //compute bearing, result in radians
  if (x < 0) {
     x += 2 * pi;             //if negative add 2*pi or 360 degrees
  }
  ddd2dms(form, in4, rad2deg(x));
return true;
}


function calcPoint(form, in1, in2, in3, in4) {           //calculate grid coordinates from plane grid range and bearing
  // in1 - point 1 coordinates index
  // in2 - point 2 coordinates index
  // in3 - distance index
  // in4 - bearing index

  var x = dms2ddd(form.degreevalue[in4].value, form.minutevalue[in4].value, form.secondvalue[in4].value);  //convert to decimal degrees
  x = deg2rad(x);             //convert to radians
  var dn = parseFloat(form.distvalue[in3].value) * Math.cos(x) ;  
  var de = parseFloat(form.distvalue[in3].value) * Math.sin(x) ;  
  form.north[in2].value = parseFloat(form.north[in1].value) + dn;
  form.east[in2].value = parseFloat(form.east[in1].value) + de;
  form.north[in2].value = roundoff(form.north[in2].value,distsize);
  form.east[in2].value = roundoff(form.east[in2].value,distsize);
return true;
}


function deg2rad(x){                //convert decimal degrees to radians
   
  x = x * pi / 180;
  return x;
}

function rad2deg(x){                //convert radians to decimal degrees
   
  x = x * 180 / pi;
  return x;
}

function roundoff(x,y){              //round off x to y decimal places
  x = parseFloat(x);
  y = parseFloat(y);
  x = Math.round(x * Math.pow(10,y))/Math.pow(10,y);
  return x;
}

function dms2ddd(d,m,s){

  if (isblank(d)) d = '0';
   else {
      var y = d.slice(0, 1);
      d = parseFloat(d);
   }
  if (isblank(m)) m = '0';
   else
      m = parseFloat(m);
  if (isblank(s)) s = '0';
   else
      s = parseFloat(s);
  var x = Math.abs(d) + (Math.abs(m) / 60) + (Math.abs(s) / 3600);  //convert to decimal degrees
  if ((y == "-") || (d < 0) || (m < 0) || (s < 0)) x = -x;
  return x;

}

function isblank(s)
{
  for(var i = 0; i < s.length; i++) {
      var c = s.charAt(i);
      if ((c != ' ') && (c != '\n') && (c != '\t')) return false;
  }
  return true;
}

function geo2grid(form, in1, in2, in3, in4, in5){
  // in1 - point latitude index
  // in2 - point longitude index
  // in3 - point grid coordinates
  // in4 - grid convergence index
  // in5 - point scale factor index
 
  var a =  6378388.0;
var n0 = 6023150.0;
var e0 = 2510000.0;
var lt0 = -41.0;
var ln0 = 173.0;


  var latddd = dms2ddd(form.degreevalue[in1].value, form.minutevalue[in1].value, form.secondvalue[in1].value);  // convert latitude of point to decimal degrees then radians
  var latrad = deg2rad(latddd);
  var londdd = dms2ddd(form.degreevalue[in2].value, form.minutevalue[in2].value, form.secondvalue[in2].value);  // likewise for longitude
  var lonrad = deg2rad(londdd);

var lt = (latddd - lt0) * 0.03600;
var sum = 0;
for (i=0; i < 10; i++) {
  sum = sum + cfi[i] * Math.pow(lt, i + 1);
}

var z1 = new Complex(sum, deg2rad(londdd - ln0));

var z0 = new Complex(0,0);
var z2 = new Complex(0,0);
var z3 = new Complex(0,0);

for (ij=0; ij<6; ij++) {
  z2 = Complex.power(z1, ij+1);
  z3 = Complex.multiply(cfb1[ij], z2);  
  z0 =  Complex.add(z0,z3);
}
form.north[in3].value = n0 + z0.x * a;
form.east[in3].value = e0 + z0.y * a;
}


function grid2geo(form, in1, in2, in3, in4, in5){
  // in1 - point latitude index
  // in2 - point longitude index
  // in3 - point grid coordinates
  // in4 - grid convergence index
  // in5 - point scale factor index

var a =  6378388.0;
var n0 = 6023150.0;
var e0 = 2510000.0;
var lt0 = -41.0;
var ln0 = 173.0;

var north = parseFloat(form.north[in3].value);
var east = parseFloat(form.east[in3].value);

var z = new Complex((north - n0)/a, (east - e0)/a);

var z1 = new Complex(0,0);
var z2 = new Complex(0,0);
var z3 = new Complex(0,0);
for (ij=0; ij<6; ij++) {
  z2 = Complex.power(z,ij+1);
  z3 = Complex.multiply(cfb2[ij],z2);
  z1 = Complex.add(z1, z3);
}
for (kk=0; kk<2; kk++) {
z2 = new Complex(0,0);
for (ij=2; ij<7; ij++) {
  z2 = Complex.add(z2,(Complex.multiply(Complex.power(z1,ij),Complex.scale(cfb1[ij-1],(ij-1)))));
}


 z3 = new Complex(cfb1[0].x, cfb1[0].y);
 z3 = Complex.add(z3, Complex.multiply(Complex.scale(cfb1[1],2),z1));
 z3 = Complex.add(z3, Complex.multiply(Complex.scale(cfb1[2],3),Complex.power(z1,2)));
 z3 = Complex.add(z3, Complex.multiply(Complex.scale(cfb1[3],4),Complex.power(z1,3)));
 z3 = Complex.add(z3, Complex.multiply(Complex.scale(cfb1[4],5),Complex.power(z1,4)));
 z3 = Complex.add(z3, Complex.multiply(Complex.scale(cfb1[5],6),Complex.power(z1,5)));

 z1 = Complex.divide(Complex.add(z,z2),z3);
}
var dphi = 0;
for (ij=1; ij<10; ij++) {
  dphi = dphi + cfl[ij-1] * Math.pow(z1.x,ij);
}

var latdeg = lt0 + (dphi * 100000 / 3600);
var londeg = ln0 + rad2deg(z1.y);

  ddd2dms(form, in1, latdeg);
  ddd2dms(form, in2, londeg);
}

function tttghg() {
// calclulate constants required for Redfern's formulae
  var k = parseFloat(form.k.value);  //scale factor
  var a = parseFloat(form.a.value);  //semi-major axis
  var f = 1 / parseFloat(form.invf.value);  //flattening
  var b = a * (1 - f);    //semi-minor axis
  var e2 = (a * a - b * b)/(a * a);  //eccentricity squared
  var e = Math.sqrt(e2);  //eccentricity
  var ei2 = (a * a - b * b)/(b * b); //second eccentricity squared
  var ei = Math.sqrt(ei2); //second eccentricity
  var n = (a - b)/(a + b);
  var G = a * (1 - n) * (1 - n * n) * (1 + (9 / 4) * n * n + (255 / 64) * Math.pow(n,4)) * (pi / 180);  //Mean length of an arc of one degree of the meridian
  var north = (parseFloat(form.north[in3].value) - parseFloat(form.falsenorth.value)) * units;  //northing from the equator
  var east = (parseFloat(form.east[in3].value) - parseFloat(form.falseeast.value)) * units; //easting from the CM
  var m = north / k;  //meridian distance
  var sigma = (m * pi) / (180 * G);

// calculate the foot point latitude and constants for that latitude
  var footlat = sigma + ((3 * n / 2) - (27 * Math.pow(n, 3) / 32)) * Math.sin(2 * sigma) + ((21 * n * n / 16) - (55 * Math.pow(n, 4) / 32)) * Math.sin(4 * sigma) + (151 * Math.pow(n, 3) / 96) * Math.sin(6 * sigma) + (1097 * Math.pow(n, 4) / 512) * Math.sin(8 * sigma);
  var rho = a * (1 - e2) / Math.pow(1 - (e2 * Math.sin(footlat) * Math.sin(footlat)),(3/2)); //radius of curvature in plane of meridian
  var nu = a / Math.sqrt(1 - (e2 * Math.sin(footlat) * Math.sin(footlat))); //radius of curvature in prime vertical
  var psi = nu / rho;
  var t = Math.tan(footlat);  //tan of latitude

// calculate latitude
  var x = east / (k * nu);
  var laterm1 = (t / (k * rho )) * ( east * x / 2);
  var laterm2 = (t / (k * rho )) * ( east * Math.pow(x, 3) / 24) * (-4 * psi * psi + 9 * psi * (1 - t * t) + 12 * t * t );
  var laterm3 = (t / (k * rho )) * ( east * Math.pow(x, 5) / 720) * (8 * Math.pow(psi, 4) * (11 - 24 * t * t) - 12 * Math.pow(psi, 3) * (21 - 71 * t * t) + 15 * psi * psi * (15 - 98 * t * t + 15 * Math.pow(t, 4)) + 180 * psi * (5 * t * t - 3 * Math.pow(t, 4)) + 360 * Math.pow(t, 4));
  var laterm4 = (t / (k * rho )) * ( east * Math.pow(x, 7) / 40320) * (1385 + 3633 * t * t + 4095 * Math.pow(t, 4) + 1575 * Math.pow(t, 6));
  var latrad = footlat - laterm1 + laterm2 - laterm3 + laterm4;

  ddd2dms(form, in1, rad2deg(latrad));
 
// calculate longitude
  var seclat = 1 / Math.cos(footlat);
  var loterm1 = x * seclat;
  var loterm2 = (Math.pow(x, 3) / 6) * seclat * (psi + 2 * t * t);
  var loterm3 = (Math.pow(x, 5) / 120) * seclat * (-4 * Math.pow(psi, 3) * (1 - 6 * t * t) + psi * psi * (9 -68 * t * t) + 72 * psi * t * t + 24 * Math.pow(t, 4));
  var loterm4 = (Math.pow(x, 7) / 5040) * seclat * (61 + 662 * t * t + 1320 * Math.pow(t, 4) + 720 * Math.pow(t, 6));
  var w = loterm1 - loterm2 + loterm3 - loterm4;
  var longrad = deg2rad(parseFloat(form.cmlong.value)) + w;

  ddd2dms(form, in2, rad2deg(longrad));

// calculate grid convergence
  var gterm1 = -t * x;
  var gterm2 = (t * Math.pow(x, 3) / 3) * (-2 * psi * psi + 3 * psi + t * t);
  var gterm3 = (-t * Math.pow(x, 5) / 15) * (Math.pow(psi, 4) * (11 - 24 * t * t) - 3 * Math.pow(psi, 3) * (8 - 23 * t * t) + 5 * psi * psi * (3 - 14 * t * t) + 30 * psi * t * t + 3 * Math.pow(t, 4));
  var gterm4 = (t * Math.pow(x, 7) / 315) * (17 +77 * t * t + 105 * Math.pow(t, 4) + 45 * Math.pow(t, 6));
  var gridconv = gterm1 + gterm2 + gterm3 + gterm4;

  ddd2dms(form, in4, rad2deg(gridconv));

// calculate point scale factor
  x = east * east / (k * k * rho * nu);
  var kterm1 = x / 2;
  var kterm2 = (x * x / 24) * (4 * psi * (1 - 6 * t * t) - 3 * (1 - 16 * t * t) - 24 * t * t / psi);
  var kterm3 = Math.pow(x, 3) / 720 ;
  var pointk = k * (1 + kterm1 + kterm2 + kterm3);
  form.pointk[in5].value = roundoff(pointk, bearsize);  
     
return true;
}

function calcRandBgeo(form, in1, in2, in3, in4, in5, in6){
  // in1 - point 1 latitude index
  // in2 - point 1 longitude index
  // in3 - point 2 latitude index
  // in4 - point 2 longitude index
  // in5 - distance index
  // in6 - bearing index

var j = form.units.selectedIndex;
var units = form.units.options[j].value;

// calclulate constants
//  var k = parseFloat(form.k.value);  //scale factor
  var a = parseFloat(form.a.value);  //semi-major axis
  var f = 1 / parseFloat(form.invf.value);  //flattening
  var b = a * (1 - f);    //semi-minor axis
 
  var latddd1 = dms2ddd(form.degreevalue[in1].value, form.minutevalue[in1].value, form.secondvalue[in1].value);  // convert latitude of point to decimal degrees then radians
  var latrad1 = deg2rad(latddd1);
  var londdd1 = dms2ddd(form.degreevalue[in2].value, form.minutevalue[in2].value, form.secondvalue[in2].value);  // likewise for longitude
  var lonrad1 = deg2rad(londdd1);
  var latddd2 = dms2ddd(form.degreevalue[in3].value, form.minutevalue[in3].value, form.secondvalue[in3].value);  // convert latitude of point to decimal degrees then radians
  var latrad2 = deg2rad(latddd2);
  var londdd2 = dms2ddd(form.degreevalue[in4].value, form.minutevalue[in4].value, form.secondvalue[in4].value);  // likewise for longitude
  var lonrad2 = deg2rad(londdd2);

  var w = lonrad2 - lonrad1;

  if (Math.abs(w) > 1.5707963268) {
     alert("Sorry this calculator isn't designed for such large distances.\nTry my Great Circle Calculator instead.");
  }
  var tanB1 = Math.tan(latrad1) * (1 - f);
  var tanB2 = Math.tan(latrad2) * (1 - f);
  var B1 = Math.atan(tanB1);
  var B2 = Math.atan(tanB2);

  var term1 = Math.sin(w) * Math.cos(B2);
  var term2 = Math.sin(B2) * Math.cos(B1) - Math.sin(B1) * Math.cos(B2) * Math.cos(w);
  var phi = Math.asin(Math.sqrt(term1 * term1 + term2 * term2));
  var c = (Math.cos(B1) * Math.cos(B2) * Math.sin(w)) / Math.sin(phi);
  var m = 1 - c * c;
 
  term1 = phi * (1 + f + f * f)
  term2 = Math.sin(B1) * Math.sin(B2) * ((f + f * f) * Math.sin(phi) - ((f * f / 2) * phi * phi / Math.sin(phi)));
  var term3 = m * (-1 * (phi * (f + f * f) / 2) - ((f + f * f) / 2) * Math.sin(phi) * Math.cos(phi) + ((f * f / 2) * phi * phi) / Math.tan(phi));
  var term4 = Math.sin(B1) * Math.sin(B2) * Math.sin(B1) * Math.sin(B2) * (-1 * (f * f /2) * Math.sin(phi) * Math.cos(phi));
  var term5 = m * m * ((f * f / 16 ) * phi + (f * f / 16) * Math.sin(phi) * Math.cos(phi) - (f * f / 2) * phi * phi / Math.tan(phi) - (f * f / 8) * Math.sin(phi) * Math.pow(Math.cos(phi), 3));
  var term6 = Math.sin(B1) * Math.sin(B2) * m * ((f * f / 2) * phi * phi / Math.sin(phi) + (f * f / 2) * Math.sin(phi) * Math.cos(phi) * Math.cos(phi));
  var s = b * (term1 + term2 + term3 + term4 + term5 + term6);
  form.distvalue[in5].value = roundoff((s / units), distsize);  //round off distance
 
  term1 = (f + f * f) * phi;
  term2 = Math.sin(B1) * Math.sin(B2) * ( -1 * (f * f / 2) * Math.sin(phi) - f * f * phi * phi / Math.sin(phi));
  term3 = m * (-1 * (5 * f * f / 4) * phi + (f * f /4) * Math.sin(phi) * Math.cos(phi) + f * f * phi * phi / Math.tan(phi));
  lamda = c * (term1 + term2 + term3) + w;
 
  var de = Math.sin(B2) * Math.cos(B1) - Math.cos(lamda) * Math.sin(B1) * Math.cos(B2);
  var dn = Math.sin(lamda) * Math.cos(B2);
  var x = Math.atan2(dn,de);    //compute bearing, result in radians
  if (x < 0) {
     x += 2 * pi;             //if negative add 2*pi or 360 degrees
  }

if (w == 0) {
   if (latddd2 < latddd1)
       x =  pi;
   else if (latddd2 > latddd1)
       x = 0;
   else if (latddd2 == latddd1) {
       x = 0;
       form.distvalue[in5].value = roundoff(0, distsize);  //round off distance
   }
}
  ddd2dms(form, in6, rad2deg(x));
   
return true;
}


function calcPointgeo(form, in1, in2, in3, in4, in5, in6){
  // in1 - point 1 latitude index
  // in2 - point 1 longitude index
  // in3 - point 2 latitude index
  // in4 - point 2 longitude index
  // in5 - distance index
  // in6 - bearing index

var j = form.units.selectedIndex;
var units = form.units.options[j].value;

// calclulate constants
//  var k = parseFloat(form.k.value);  //scale factor
  var a = parseFloat(form.a.value);  //semi-major axis
  var f = 1 / parseFloat(form.invf.value);  //flattening
  var b = a * (1 - f);    //semi-minor axis
  var e2 = (a * a - b * b)/(a * a);  //eccentricity squared
  var e = Math.sqrt(e2);  //eccentricity
  var ei2 = (a * a - b * b)/(b * b); //second eccentricity squared
  var ei = Math.sqrt(ei2); //second eccentricity
 
  var latddd1 = dms2ddd(form.degreevalue[in1].value, form.minutevalue[in1].value, form.secondvalue[in1].value);  // convert latitude of point to decimal degrees then radians
  var latrad1 = deg2rad(latddd1);
  var londdd1 = dms2ddd(form.degreevalue[in2].value, form.minutevalue[in2].value, form.secondvalue[in2].value);  // likewise for longitude
  var lonrad1 = deg2rad(londdd1);
  var x12 = dms2ddd(form.degreevalue[in6].value, form.minutevalue[in6].value, form.secondvalue[in6].value);  //convert to decimal degrees
  x12 = deg2rad(x12);             //convert to radians
  var s = (parseFloat(form.distvalue[in5].value) * units);  
 
  if (Math.abs(s) > 10019148.059) {
     alert("Sorry this calculator isn't designed for such large distances.\nTry my Great Circle Calculator instead.");
  }
  var tanB1 = Math.tan(latrad1) * (1 - f);
  var B1 = Math.atan(tanB1);
  var cosB0 = Math.cos(B1) * Math.sin(x12);
  var B0 = Math.acos(cosB0);
  var g = Math.cos(B1) * Math.cos(x12);
  var m = (1 + (ei2 / 2) * Math.sin(B1) * Math.sin(B1)) * (1 - Math.cos(B0) * Math.cos(B0));
  var phis = s / b;
  var a1 = (1 + (ei2 / 2) * Math.sin(B1) * Math.sin(B1)) * (Math.sin(B1) * Math.sin(B1) * Math.cos(phis) + g * Math.sin(B1) * Math.sin(phis));

  var term1 = a1 * (-1 * (ei2 / 2) * Math.sin(phis));
  var term2 = m * (-1 * (ei2 / 4) * phis + (ei2 / 4) * Math.sin(phis) * Math.cos(phis));
  var term3 = a1 * a1 * ((5 * ei2 * ei2 / 8) * Math.sin(phis) * Math.cos(phis));
  var term4 = m * m * (( 11 * ei2 * ei2 / 64) * phis - (13 * ei2 * ei2 / 64) * Math.sin(phis) * Math.cos(phis) - (ei2 * ei2 / 8) * phis * Math.cos(phis) * Math.cos(phis) + (5 * ei2 * ei2 / 32) * Math.sin(phis) * Math.pow(Math.cos(phis), 3));
  var term5 = a1 * m * ((3 * ei2 * ei2 / 8) * Math.sin(phis) + (ei2 * ei2 /4) * phis * Math.cos(phis) - (5 * ei2 * ei2 / 8) * Math.sin(phis) * Math.cos(phis) * Math.cos(phis));
  var phi0 = phis + term1 + term2 + term3 + term4 + term5;
 
  var cotlamda = (Math.cos(B1) * Math.cos(phi0) - Math.sin(B1) * Math.sin(phi0) * Math.cos(x12)) / (Math.sin(phi0) * Math.sin(x12));
  var lamda = Math.atan(1 / cotlamda);
 
  term1 = -1 * f * phis;
  term2 = a1 * ((3 * f * f / 2) * Math.sin(phis));
  term3 = m * ((3 * f * f / 4) * phis - (3 * f * f / 4) * Math.sin(phis) * Math.cos(phis));
  var w = (term1 + term2 + term3) * Math.cos(B0) + lamda;

  var lonrad2 = lonrad1 + w;
  ddd2dms(form, in4, rad2deg(lonrad2));

  var sinB2 = Math.sin(B1) * Math.cos(phi0) + g * Math.sin(phi0);
  var cosB2 = Math.sqrt((Math.cos(B0) * Math.cos(B0)) + Math.pow((g * Math.cos(phi0) - Math.sin(B1) * Math.sin(phi0)), 2));
  var tanB2 = sinB2 / cosB2;
  var tanlat2 = tanB2 / (1 - f);
  var latrad2 = Math.atan(tanlat2);
  ddd2dms(form, in3, rad2deg(latrad2));

return true;
}

function ddd2dms(form, ind, bearing){
  var y = Math.abs(parseFloat(bearing));
  form.degreevalue[ind].value = parseInt(y + 1) - 1;
  var x = y - form.degreevalue[ind].value;    
  form.minutevalue[ind].value = parseInt(x * 60 + 1) - 1;
  form.secondvalue[ind].value = ((x * 60) - form.minutevalue[ind].value) * 60;
  form.secondvalue[ind].value = roundoff(form.secondvalue[ind].value,secsize);
  if (form.secondvalue[ind].value == 60) {
      form.secondvalue[ind].value = "0";
      form.minutevalue[ind].value = form.minutevalue[ind].value * 1 + 1;
      if (form.minutevalue[ind].value == 60) {
        form.minutevalue[ind].value = "0";
        form.degreevalue[ind].value = form.degreevalue[ind].value * 1 + 1;
      }
  }
  if (bearing < 0) {
     if (form.degreevalue[ind].value != 0)
        form.degreevalue[ind].value = -form.degreevalue[ind].value;
     else if (form.minutevalue[ind].value != 0)
        form.minutevalue[ind].value = -form.minutevalue[ind].value;
     else
        form.secondvalue[ind].value = -form.secondvalue[ind].value;
  }  
  form.degreevalue[ind].value += "\260";                                        // add degrees symbol now we have finished with value
  form.minutevalue[ind].value += "\'";                                        //add minute symbol now we have finished with value
  form.secondvalue[ind].value += '\"';               //round off seconds and add symbol
return true;
}

function confirmSphChange(form){             //to only allow changes to spheroid parameters if in user defined mode

var i = form.spheroid.selectedIndex;
if (i != 22) {
  form.a.blur();
  form.invf.blur();
  alert("\n To override Spheroid Parameters\n use the User Defined option.");
}
return true;
}
 
 

function updateSpheroid(form){

var i = form.spheroid.selectedIndex;
switch(i) {
  case 0:
    form.a.value = 6378388.000;
    form.invf.value = 297.000;
    break;
}
return true;
}

function confirmProjChange(form){             //to only allow changes to projection parameters if in user defined mode

var i = form.projection.selectedIndex;
if (i != 2) {
  form.falsenorth.blur();
  form.falseeast.blur();
  form.k.blur();
  alert("\n To override Projection Parameters\n use the User Defined option.");
}
return true;
}

function updateProjection(form, x){

var i = form.projection.selectedIndex;
var j = form.units.selectedIndex;
var units = form.units.options[j].value;
switch(i) {
  case 0:
    form.falsenorth.value = 0;
    form.falseeast.value = 500000 / units;
    form.k.value = 0.9996;
    break;
  case 1:
    form.falsenorth.value = 10000000 / units;
    form.falseeast.value = 500000 / units;
    form.k.value = 0.9996;
    break;
  case 2:
    if (x == 1) {                  // only reset if called from projection selection not grid units
      form.falsenorth.value = '';
      form.falseeast.value = '';
      form.k.value = '';
    }
    break;
}
}

function swapgeos(form){
  var x = form.degreevalue[0].value;
  form.degreevalue[0].value = form.degreevalue[5].value;
  form.degreevalue[5].value = x;
  x = form.degreevalue[1].value;
  form.degreevalue[1].value = form.degreevalue[6].value;
  form.degreevalue[6].value = x;

  x = form.minutevalue[0].value;
  form.minutevalue[0].value = form.minutevalue[5].value;
  form.minutevalue[5].value = x;
  x = form.minutevalue[1].value;
  form.minutevalue[1].value = form.minutevalue[6].value;
  form.minutevalue[6].value = x;
 
  x = form.secondvalue[0].value;
  form.secondvalue[0].value = form.secondvalue[5].value;
  form.secondvalue[5].value = x;
  x = form.secondvalue[1].value;
  form.secondvalue[1].value = form.secondvalue[6].value;
  form.secondvalue[6].value = x;
return true;
}

function swapgrid(form){
  var x = form.north[0].value;
  form.north[0].value = form.north[1].value;
  form.north[1].value = x;
  x = form.east[0].value;
  form.east[0].value = form.east[1].value;
  form.east[1].value = x;
return true;
}

function updateCM(form){
  var zone = parseFloat(form.zone.value);
  if ((zone < 1) || (zone > 60) || isblank(form.zone.value)) {
     form.zone.value = "";
     alert("\n  Please enter a UTM Zone number\n between 1 and 60.");
     form.zone.focus();
  }
  else {
     form.cmlong.value =  zone * 6 - 183 + "\260";
  }
}

function updateZone(form){
  var cmlong = parseFloat(form.cmlong.value);
  if ((cmlong < -180) || (cmlong > 180) || isblank(form.cmlong.value)) {
     form.cmlong.value = "";
     alert("\n Please enter a Longitude of Central Meridian between +/- 180\260");
     form.cmlong.focus();
  }
  else {
     form.zone.value = roundoff(((cmlong + 183) / 6), 2);
  }
}


//-->
</SCRIPT>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

<body>

<FORM name=geodetics onreset="return confirm('Erase ALL data and start over?')">
  <TABLE width="100%">
    <TBODY>
      <TR>
        <TD> <TABLE width="100%" border=1>
            <TBODY>
              <TR>
                <TD> <TABLE cellPadding=0 width="100%" border=0>
                    <TBODY>
                      <TR> </TR>
                    </TBODY>
                  </TABLE>
                  <table>
                    <tbody>
                      <tr>
                        <td>Spheroid:</td>
                        <td colspan=2><select name=spheroid>
                            <option
                    selected>International 1924</option>
                          </select> </td>
                        <td>Projection:</td>
                        <td><select onChange="updateProjection(this.form, 1)"
                  name=projection>
                            <option selected>NZMG</option>
                          </select> </td>
                      </tr>
                      <tr>
                        <td>Semi-Major Axis:</td>
                        <td><input readonly size=12 value=6378388.0 name=a></td>
                      </tr>
                      <tr>
                        <td>Inverse Flattening:</td>
                        <td><input readonly size=12 value=297 name=invf></td>
                      </tr>
                      <tr>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td>Grid Units:</td>
                        <td colspan=2><select name=units>
                            <option value=1
                    selected>Metres</option>
                          </select> </td>
                      </tr>
                      <tr>
                        <td colspan=9> <hr noshade> </td>
                      </tr>
                      <tr>
                        <td>Latitude <br>
                          ( - south): </td>
                        <td><input size=12 value=0° name=degreevalue></td>
                        <td><input size=4 value="0'" name=minutevalue></td>
                        <td><input size=6 value='0"' name=secondvalue></td>
                        <td><input name="button" type=button onClick="geo2grid(this.form, 0, 1, 0, 2, 0)" value=" Lat/Lon to N/E "></td>
                        <td>Northing:</td>
                        <td><input size=12 value=0 name=north></td>
                      </tr>
                      <tr>
                        <td>Longitude <br>
                          ( - west): </td>
                        <td><input size=12 value=0° name=degreevalue></td>
                        <td><input size=4 value="0'" name=minutevalue></td>
                        <td><input size=6 value='0"' name=secondvalue></td>
                        <td><input name="button" type=button onClick="grid2geo(this.form, 0, 1, 0, 2, 0)" value=" N/E to Lat/Lon "></td>
                        <td>Easting:</td>
                        <td><input size=12 value=0 name=east></td>
                      </tr>
                      <tr>
                        <td></td>
                        <td><input type=hidden size=12 value=0° name=degreevalue></td>
                        <td><input type=hidden size=4 value="0'" name=minutevalue></td>
                        <td><input type=hidden size=6 value='0"' name=secondvalue></td>
                        <td> <h3>
                            <center>
                              Point 1
                            </center>
                          </h3></td>
                        <td></td>
                        <td><input type=hidden size=12 value=0 name=pointk></td>
                      </tr>
                      <tr>
                        <td colspan=9> <hr noshade> </td>
                      </tr>
                      <tr>
                        <td>Ellipsoidal Distance:</td>
                        <td><input size=12 value=0 name=distvalue></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td>Grid Distance:</td>
                        <td><input size=12 value=0 name=distvalue></td>
                      </tr>
                      <tr>
                      <tr>
                        <td>True Bearing: </td>
                        <td><input size=12 value=0° name=degreevalue></td>
                        <td><input size=4 value="0'" name=minutevalue></td>
                        <td><input size=6 value='0"' name=secondvalue></td>
                        <td></td>
                        <td>Grid Bearing: </td>
                        <td><input size=12 value=0° name=degreevalue></td>
                        <td><input size=4 value="0'" name=minutevalue></td>
                        <td><input size=6 value='0"' name=secondvalue></td>
                      </tr>
                      <tr>
                        <td></td>
                        <td><input name="button" type=button onClick="calcRandBgeo(this.form, 0, 1, 5, 6, 0, 3)" value="Calc R &amp; B"></td>
                        <td colspan=2><input name="button" type=button onClick="calcPointgeo(this.form, 0, 1, 5, 6, 0, 3)" value="Calc Point 2"></td>
                        <td></td>
                        <td></td>
                        <td><input name="button" type=button onClick="calcRandB(this.form, 0, 1, 1, 4)" value="Calc R &amp; B"></td>
                        <td colspan=2><input name="button" type=button onClick="calcPoint(this.form, 0, 1, 1, 4)" value="Calc Point 2"></td>
                      </tr>
                      <tr>
                        <td colspan=9> <hr> </td>
                      </tr>
                      <tr>
                        <td>Latitude <br>
                          ( - south): </td>
                        <td><input size=12 value=0° name=degreevalue></td>
                        <td><input size=4 value="0'" name=minutevalue></td>
                        <td><input size=6 value='0"' name=secondvalue></td>
                        <td><input name="button" type=button onClick="geo2grid(this.form, 5, 6, 1, 7, 1)" value=" Lat/Lon to N/E "></td>
                        <td>Northing:</td>
                        <td><input size=12 value=0 name=north></td>
                      </tr>
                      <tr>
                        <td>Longitude <br>
                          ( - west): </td>
                        <td><input size=12 value=0° name=degreevalue></td>
                        <td><input size=4 value="0'" name=minutevalue></td>
                        <td><input size=6 value='0"' name=secondvalue></td>
                        <td><input name="button" type=button onClick="grid2geo(this.form, 5, 6, 1, 7, 1)" value=" N/E to Lat/Lon "></td>
                        <td>Easting:</td>
                        <td><input size=12 value=0 name=east></td>
                      </tr>
                      <tr>
                        <td></td>
                        <td><input type=hidden size=12 value=0° name=degreevalue></td>
                        <td><input type=hidden size=4 value="0'" name=minutevalue></td>
                        <td><input type=hidden size=6 value='0"' name=secondvalue></td>
                        <td> <h3>
                            <center>
                              Point 2
                            </center>
                          </h3></td>
                        <td></td>
                        <td><input type=hidden size=12 value=0 name=pointk></td>
                      </tr>
                      <tr>
                        <td></td>
                        <td><input name="button" type=button onClick=swapgeos(form) value="Swap 1 &amp; 2"></td>
                        <td></td>
                        <td></td>
                        <td><input name="reset" type=reset value="Reset Fields"></td>
                        <td></td>
                        <td><input name="button" type=button onClick=swapgrid(form) value="Swap 1 &amp; 2"></td>
                      </tr>
                    </tbody>
                  </table></TD>
              </TR>
            </TBODY>
          </TABLE></TD>
      </TR>
    </TBODY>
  </TABLE>
</FORM>
<p></P>
</body>
</html>


'/End code
0
 
LVL 15

Accepted Solution

by:
bpmurray earned 500 total points
Comment Utility
OK, here's the functionality. I'll assume that you know how to handle the form stuff - if not, please say so. It requires the complex class from my response above, and here is the module that consumes that class. Note that this is VB.Net. Anyway, here's the main module:

Module Geolib
    Dim pi = Math.PI
    Dim secsize As Integer = 4      ' round second display to
    Dim distsize As Integer = 3      ' round distance display to
    Dim bearsize As Integer = 8
    Dim a As Double = 6378388.0
    Dim n0 As Double = 6023150.0
    Dim e0 As Double = 2510000.0
    Dim lt0 As Double = -41.0
    Dim ln0 As Double = 173.0


    Dim cfi() As Double = {0.6399175073, -0.1358797613, 0.063294409, -0.02526853, 0.0117879, _
                           -0.0055161, 0.0026906, -0.001333, 0.00067, -0.00034}

    Dim cfl() As Double = {0.5627014243, 0.5185406398, -0.03333098, -0.1052906, -0.0368594, _
                            0.007317, 0.0122, 0.00394, -0.0013}

    Dim cfb1() As Complex = {New Complex(0.7557853228, 0.0), New Complex(0.249204646, 0.003371507), _
                              New Complex(-0.001541739, 0.04105856), New Complex(-0.10162907, 0.01727609), _
                              New Complex(-0.26623489, -0.36249218), New Complex(-0.6870983, -1.1651967)}


    Dim cfb2() As Complex = {New Complex(1.3231270439, 0.0), New Complex(-0.577245789, -0.007809598), _
                             New Complex(0.508307513, -0.112208952), New Complex(-0.15094762, 0.18200602), _
                             New Complex(1.01418179, 1.64497696), New Complex(1.9660549, 2.5127645)}



    Function calcRandB(ByVal form As FormType, ByVal in1 As Integer, ByVal in2 As Integer, ByVal in3 As Integer, ByVal in4 As Integer) As Boolean             ' calculate plane grid range and bearing
        '  in1 - point 1 coordinates index
        '  in2 - point 2 coordinates index
        '  in3 - distance index
        '  in4 - bearing index
        Dim de As Double = CDbl(form.east(in2).value) - CDbl(form.east(in1).value)  ' difference in eastings
        Dim dn As Double = CDbl(form.north(in2).value) - CDbl(form.north(in1).value)  ' difference in northings

        form.distvalue(in3).value = Math.Sqrt(de * de + dn * dn)          ' compute distance
        form.distvalue(in3).value = roundoff(form.distvalue(in3).value, distsize)  ' round off distance

        Dim x As Double = Math.Atan2(de, dn)    ' compute bearing, result in radians
        If (x < 0) Then
            x += 2 * pi             ' If negative add 2*pi or 360 degrees
        End If
        ddd2dms(form, in4, rad2deg(x))
        Return True
    End Function


    Function calcPoint(ByVal form As FormType, ByVal in1 As Integer, ByVal in2 As Integer, ByVal in3 As Integer, ByVal in4 As Integer) As Boolean           ' calculate grid coordinates from plane grid range and bearing
        '  in1 - point 1 coordinates index
        '  in2 - point 2 coordinates index
        '  in3 - distance index
        '  in4 - bearing index

        Dim x As Double = dms2ddd(form.degreevalue(in4).value, form.minutevalue(in4).value, form.secondvalue(in4).value)  ' convert to decimal degrees
        x = deg2rad(x)             ' convert to radians
        Dim dn As Double = CDbl(form.distvalue(in3).value) * Math.Cos(x)
        Dim de As Double = CDbl(form.distvalue(in3).value) * Math.Sin(x)
        form.north(in2).value = CDbl(form.north(in1).value) + dn
        form.east(in2).value = CDbl(form.east(in1).value) + de
        form.north(in2).value = roundoff(form.north(in2).value, distsize)
        form.east(in2).value = roundoff(form.east(in2).value, distsize)
        Return True
    End Function


    Function deg2rad(ByVal x) As Integer                ' convert decimal degrees to radians
        x = x * pi / 180
        Return x
    End Function

    Function rad2deg(ByVal x) As Double                ' convert radians to decimal degrees
        x = x * 180 / pi
        Return x
    End Function

    Function roundoff(ByVal x, ByVal y) As Double              ' round off x to y decimal places
        x = CDbl(x)
        y = CDbl(y)
        x = Math.Round(x * Math.Pow(10, y)) / Math.Pow(10, y)
        Return x
    End Function

    Function dms2ddd(ByVal ds As String, ByVal ms As String, ByVal ss As String) As Double
        Dim d As Double
        Dim m As Double
        Dim y As String = ""
        Dim s As Double
        If (isblank(ds)) Then
            d = 0
        Else
            y = Left(d, 1)
            d = CDbl(d)
        End If
        If (isblank(ms)) Then
            m = 0
        Else
            m = CDbl(m)
        End If
        If (isblank(ss)) Then
            s = 0
        Else
            s = CDbl(s)
        End If
        Dim x As Double = Math.Abs(d) + (Math.Abs(m) / 60) + (Math.Abs(s) / 3600)  ' convert to decimal degrees
        If ((y = "-") Or (d < 0) Or (m < 0) Or (s < 0)) Then
            x = -x
        End If
        Return x
    End Function

    Function isblank(ByVal s As String) As Boolean
        Dim temp As String = s.Trim()
        If temp.Length = 0 Then
            Return True
        Else
            Return False
        End If
    End Function

    Sub geo2grid(ByVal form As FormType, ByVal in1 As Integer, ByVal in2 As Integer, ByVal in3 As Integer, ByVal in4 As Integer, ByVal in5 As Integer)
        '  in1 - point latitude index
        '  in2 - point longitude index
        '  in3 - point grid coordinates
        '  in4 - grid convergence index
        '  in5 - point scale factor index

        Dim a As Double = 6378388.0
        Dim n0 As Double = 6023150.0
        Dim e0 As Double = 2510000.0
        Dim lt0 As Double = -41.0
        Dim ln0 As Double = 173.0


        Dim latddd As Double = dms2ddd(form.degreevalue(in1).value, form.minutevalue(in1).value, form.secondvalue(in1).value)  '  convert latitude of point to decimal degrees then radians
        Dim latrad As Double = deg2rad(latddd)
        Dim londdd As Double = dms2ddd(form.degreevalue(in2).value, form.minutevalue(in2).value, form.secondvalue(in2).value)  '  likewise for longitude
        Dim lonrad As Double = deg2rad(londdd)

        Dim lt As Double = (latddd - lt0) * 0.036
        Dim sum As Double = 0
        Dim i As Integer
        For i = 0 To 10
            sum = sum + cfi(i) * Math.Pow(lt, i + 1)
        Next i

        Dim z1 As Complex = New Complex(sum, deg2rad(londdd - ln0))

        Dim z0 As Complex = New Complex(0, 0)
        Dim z2 As Complex = New Complex(0, 0)
        Dim z3 As Complex = New Complex(0, 0)

        Dim ij As Integer
        For ij = 0 To 6
            z2 = z1.power(ij + 1)
            z3 = z2.multiply(cfb1(ij))
            z0 = z3.add(z0)
        Next ij
        form.north(in3).value = n0 + z0.x * a
        form.east(in3).value = e0 + z0.y * a
    End Sub


    Sub grid2geo(ByVal form, ByVal in1, ByVal in2, ByVal in3, ByVal in4, ByVal in5)
        '  in1 - point latitude index
        '  in2 - point longitude index
        '  in3 - point grid coordinates
        '  in4 - grid convergence index
        '  in5 - point scale factor index

        Dim a As Double = 6378388.0
        Dim n0 As Double = 6023150.0
        Dim e0 As Double = 2510000.0
        Dim lt0 As Double = -41.0
        Dim ln0 As Double = 173.0

        Dim north As Double = CDbl(form.north(in3).value)
        Dim east As Double = CDbl(form.east(in3).value)

        Dim z As Complex = New Complex((north - n0) / a, (east - e0) / a)

        Dim z1 As Complex = New Complex(0, 0)
        Dim z2 As Complex = New Complex(0, 0)
        Dim z3 As Complex = New Complex(0, 0)
        Dim ij As Integer
        For ij = 0 To 6
            z2 = z.power(ij + 1)
            z3 = z2.multiply(cfb2(ij))
            z1 = z3.add(z1)
        Next ij
        Dim kk As Integer
        For kk = 0 To 2
            z2 = New Complex(0, 0)
            For ij = 2 To 7
                z2 = z2.add(z1.power(ij).multiply(cfb1(ij - 1).scale(ij - 1)))
            Next ij


            z3 = New Complex(cfb1(0).x, cfb1(0).y)
            z3 = z3.add(cfb1(1).scale(2).multiply(z1))
            z3 = z3.add(cfb1(2).scale(3).multiply(z1.power(2)))
            z3 = z3.add(cfb1(3).scale(4).multiply(z1.power(3)))
            z3 = z3.add(cfb1(4).scale(5).multiply(z1.power(4)))
            z3 = z3.add(cfb1(5).scale(6).multiply(z1.power(5)))

            z1 = z.add(z2).divide(z3)
        Next kk
        Dim dphi As Double = 0
        For ij = 1 To 10
            dphi = dphi + cfl(ij - 1) * Math.Pow(z1.x, ij)
        Next ij

        Dim latdeg As Double = lt0 + (dphi * 100000 / 3600)
        Dim londeg As Double = ln0 + rad2deg(z1.y)

        ddd2dms(form, in1, latdeg)
        ddd2dms(form, in2, londeg)
    End Sub

    Function tttghg() As Boolean
        '  calclulate constants required for Redfern's formulae
        Dim k As Double = CDbl(form.k.value)  ' scale factor
        Dim a As Double = CDbl(form.a.value)  ' semi-major axis
        Dim f As Double = 1 / CDbl(form.invf.value)  ' flattening
        Dim b As Double = a * (1 - f)    ' semi-minor axis
        Dim e2 As Double = (a * a - b * b) / (a * a)  ' eccentricity squared
        Dim e As Double = Math.Sqrt(e2)  ' eccentricity
        Dim ei2 As Double = (a * a - b * b) / (b * b) ' second eccentricity squared
        Dim ei As Double = Math.Sqrt(ei2) ' second eccentricity
        Dim n As Double = (a - b) / (a + b)
        Dim G As Double = a * (1 - n) * (1 - n * n) * (1 + (9 / 4) * n * n + (255 / 64) * Math.Pow(n, 4)) * (pi / 180)  ' Mean length of an arc of one degree of the meridian
        Dim north As Double = (CDbl(form.north(in3).value) - CDbl(form.falsenorth.value)) * units  ' northing from the equator
        Dim east As Double = (CDbl(form.east(in3).value) - CDbl(form.falseeast.value)) * units ' easting from the CM
        Dim m As Double = north / k  ' meridian distance
        Dim sigma As Double = (m * pi) / (180 * G)

        '  calculate the foot point latitude and constants for that latitude
        Dim footlat As Double = sigma + ((3 * n / 2) - (27 * Math.Pow(n, 3) / 32)) * Math.Sin(2 * sigma) + ((21 * n * n / 16) - (55 * Math.Pow(n, 4) / 32)) * Math.Sin(4 * sigma) + (151 * Math.Pow(n, 3) / 96) * Math.Sin(6 * sigma) + (1097 * Math.Pow(n, 4) / 512) * Math.Sin(8 * sigma)
        Dim rho As Double = a * (1 - e2) / Math.Pow(1 - (e2 * Math.Sin(footlat) * Math.Sin(footlat)), (3 / 2)) ' radius of curvature in plane of meridian
        Dim nu As Double = a / Math.Sqrt(1 - (e2 * Math.Sin(footlat) * Math.Sin(footlat))) ' radius of curvature in prime vertical
        Dim psi As Double = nu / rho
        Dim t As Double = Math.Tan(footlat)  ' tan of latitude

        '  calculate latitude
        Dim x As Double = east / (k * nu)
        Dim laterm1 As Double = (t / (k * rho)) * (east * x / 2)
        Dim laterm2 As Double = (t / (k * rho)) * (east * Math.Pow(x, 3) / 24) * (-4 * psi * psi + 9 * psi * (1 - t * t) + 12 * t * t)
        Dim laterm3 As Double = (t / (k * rho)) * (east * Math.Pow(x, 5) / 720) * (8 * Math.Pow(psi, 4) * (11 - 24 * t * t) - 12 * Math.Pow(psi, 3) * (21 - 71 * t * t) + 15 * psi * psi * (15 - 98 * t * t + 15 * Math.Pow(t, 4)) + 180 * psi * (5 * t * t - 3 * Math.Pow(t, 4)) + 360 * Math.Pow(t, 4))
        Dim laterm4 As Double = (t / (k * rho)) * (east * Math.Pow(x, 7) / 40320) * (1385 + 3633 * t * t + 4095 * Math.Pow(t, 4) + 1575 * Math.Pow(t, 6))
        Dim latrad As Double = footlat - laterm1 + laterm2 - laterm3 + laterm4

        ddd2dms(form, in1, rad2deg(latrad))

        '  calculate longitude
        Dim seclat As Double = 1 / Math.Cos(footlat)
        Dim loterm1 As Double = x * seclat
        Dim loterm2 As Double = (Math.Pow(x, 3) / 6) * seclat * (psi + 2 * t * t)
        Dim loterm3 As Double = (Math.Pow(x, 5) / 120) * seclat * (-4 * Math.Pow(psi, 3) * (1 - 6 * t * t) + psi * psi * (9 - 68 * t * t) + 72 * psi * t * t + 24 * Math.Pow(t, 4))
        Dim loterm4 As Double = (Math.Pow(x, 7) / 5040) * seclat * (61 + 662 * t * t + 1320 * Math.Pow(t, 4) + 720 * Math.Pow(t, 6))
        Dim w As Double = loterm1 - loterm2 + loterm3 - loterm4
        Dim longrad As Double = deg2rad(CDbl(form.cmlong.value)) + w

        ddd2dms(form, in2, rad2deg(longrad))

        '  calculate grid convergence
        Dim gterm1 As Double = -t * x
        Dim gterm2 As Double = (t * Math.Pow(x, 3) / 3) * (-2 * psi * psi + 3 * psi + t * t)
        Dim gterm3 As Double = (-t * Math.Pow(x, 5) / 15) * (Math.Pow(psi, 4) * (11 - 24 * t * t) - 3 * Math.Pow(psi, 3) * (8 - 23 * t * t) + 5 * psi * psi * (3 - 14 * t * t) + 30 * psi * t * t + 3 * Math.Pow(t, 4))
        Dim gterm4 As Double = (t * Math.Pow(x, 7) / 315) * (17 + 77 * t * t + 105 * Math.Pow(t, 4) + 45 * Math.Pow(t, 6))
        Dim gridconv As Double = gterm1 + gterm2 + gterm3 + gterm4

        ddd2dms(form, in4, rad2deg(gridconv))

        '  calculate point scale factor
        x = east * east / (k * k * rho * nu)
        Dim kterm1 = x / 2
        Dim kterm2 = (x * x / 24) * (4 * psi * (1 - 6 * t * t) - 3 * (1 - 16 * t * t) - 24 * t * t / psi)
        Dim kterm3 As Double = Math.Pow(x, 3) / 720
        Dim pointk = k * (1 + kterm1 + kterm2 + kterm3)
        form.pointk(in5).value = roundoff(pointk, bearsize)

        Return True
    End Function

    Function calcRandBgeo(ByVal form, ByVal in1, ByVal in2, ByVal in3, ByVal in4, ByVal in5, ByVal in6) As Boolean
        '  in1 - point 1 latitude index
        '  in2 - point 1 longitude index
        '  in3 - point 2 latitude index
        '  in4 - point 2 longitude index
        '  in5 - distance index
        '  in6 - bearing index

        Dim j As Double = form.units.selectedIndex
        Dim units = form.units.options(j).value

        '  calclulate constants
        '   Dim k  As Double = CDbl(form.k.value)  ' scale factor
        Dim a As Double = CDbl(form.a.value)  ' semi-major axis
        Dim f As Double = 1 / CDbl(form.invf.value)  ' flattening
        Dim b As Double = a * (1 - f)    ' semi-minor axis

        Dim latddd1 = dms2ddd(form.degreevalue(in1).value, form.minutevalue(in1).value, form.secondvalue(in1).value)  '  convert latitude of point to decimal degrees then radians
        Dim latrad1 = deg2rad(latddd1)
        Dim londdd1 = dms2ddd(form.degreevalue(in2).value, form.minutevalue(in2).value, form.secondvalue(in2).value)  '  likewise for longitude
        Dim lonrad1 = deg2rad(londdd1)
        Dim latddd2 = dms2ddd(form.degreevalue(in3).value, form.minutevalue(in3).value, form.secondvalue(in3).value)  '  convert latitude of point to decimal degrees then radians
        Dim latrad2 = deg2rad(latddd2)
        Dim londdd2 = dms2ddd(form.degreevalue(in4).value, form.minutevalue(in4).value, form.secondvalue(in4).value)  '  likewise for longitude
        Dim lonrad2 = deg2rad(londdd2)

        Dim w As Double = lonrad2 - lonrad1

        If (Math.Abs(w) > 1.5707963268) Then
            MsgBox("Sorry this calculator isn't designed for such large distances.\nTry my Great Circle Calculator instead.")
        End If
        Dim tanB1 As Double = Math.Tan(latrad1) * (1 - f)
        Dim tanB2 As Double = Math.Tan(latrad2) * (1 - f)
        Dim B1 As Double = Math.Atan(tanB1)
        Dim B2 As Double = Math.Atan(tanB2)

        Dim term1 As Double = Math.Sin(w) * Math.Cos(B2)
        Dim term2 As Double = Math.Sin(B2) * Math.Cos(B1) - Math.Sin(B1) * Math.Cos(B2) * Math.Cos(w)
        Dim phi As Double = Math.Asin(Math.Sqrt(term1 * term1 + term2 * term2))
        Dim c As Double = (Math.Cos(B1) * Math.Cos(B2) * Math.Sin(w)) / Math.Sin(phi)
        Dim m As Double = 1 - c * c

        term1 = phi * (1 + f + f * f)
        term2 = Math.Sin(B1) * Math.Sin(B2) * ((f + f * f) * Math.Sin(phi) - ((f * f / 2) * phi * phi / Math.Sin(phi)))
        Dim term3 As Double = m * (-1 * (phi * (f + f * f) / 2) - ((f + f * f) / 2) * Math.Sin(phi) * Math.Cos(phi) + ((f * f / 2) * phi * phi) / Math.Tan(phi))
        Dim term4 As Double = Math.Sin(B1) * Math.Sin(B2) * Math.Sin(B1) * Math.Sin(B2) * (-1 * (f * f / 2) * Math.Sin(phi) * Math.Cos(phi))
        Dim term5 As Double = m * m * ((f * f / 16) * phi + (f * f / 16) * Math.Sin(phi) * Math.Cos(phi) - (f * f / 2) * phi * phi / Math.Tan(phi) - (f * f / 8) * Math.Sin(phi) * Math.Pow(Math.Cos(phi), 3))
        Dim term6 As Double = Math.Sin(B1) * Math.Sin(B2) * m * ((f * f / 2) * phi * phi / Math.Sin(phi) + (f * f / 2) * Math.Sin(phi) * Math.Cos(phi) * Math.Cos(phi))
        Dim s As Double = b * (term1 + term2 + term3 + term4 + term5 + term6)
        form.distvalue(in5).value = roundoff((s / units), distsize)  ' round off distance

        term1 = (f + f * f) * phi
        term2 = Math.Sin(B1) * Math.Sin(B2) * (-1 * (f * f / 2) * Math.Sin(phi) - f * f * phi * phi / Math.Sin(phi))
        term3 = m * (-1 * (5 * f * f / 4) * phi + (f * f / 4) * Math.Sin(phi) * Math.Cos(phi) + f * f * phi * phi / Math.Tan(phi))
        lamda = c * (term1 + term2 + term3) + w

        Dim de As Double = Math.Sin(B2) * Math.Cos(B1) - Math.Cos(lamda) * Math.Sin(B1) * Math.Cos(B2)
        Dim dn As Double = Math.Sin(lamda) * Math.Cos(B2)
        Dim x As Double = Math.Atan2(dn, de)    ' compute bearing, result in radians
        If (x < 0) Then
            x += 2 * pi             ' If negative add 2*pi or 360 degrees
        End If

        If (w = 0) Then
            If (latddd2 < latddd1) Then
                x = pi
            ElseIf (latddd2 > latddd1) Then
                x = 0
            ElseIf (latddd2 = latddd1) Then
                x = 0
                form.distvalue(in5).value = roundoff(0, distsize)  ' round off distance
            End If
        End If
        ddd2dms(form, in6, rad2deg(x))
        Return True
    End Function


    Function calcPointgeo(ByVal form As FormType, ByVal in1 As Integer, ByVal in2 As Integer, ByVal in3 As Integer, ByVal in4 As Integer, ByVal in5 As Integer, ByVal in6 As Integer) As Boolean
        '  in1 - point 1 latitude index
        '  in2 - point 1 longitude index
        '  in3 - point 2 latitude index
        '  in4 - point 2 longitude index
        '  in5 - distance index
        '  in6 - bearing index

        Dim j As Double = form.units.selectedIndex
        Dim units = form.units.options(j).value

        '  calclulate constants
        '   Dim k  As Double = CDbl(form.k.value)  ' scale factor
        Dim a As Double = CDbl(form.a.value)  ' semi-major axis
        Dim f As Double = 1 / CDbl(form.invf.value)  ' flattening
        Dim b As Double = a * (1 - f)    ' semi-minor axis
        Dim e2 = (a * a - b * b) / (a * a)  ' eccentricity squared
        Dim e As Double = Math.Sqrt(e2)  ' eccentricity
        Dim ei2 = (a * a - b * b) / (b * b) ' second eccentricity squared
        Dim ei As Double = Math.Sqrt(ei2) ' second eccentricity

        Dim latddd1 = dms2ddd(form.degreevalue(in1).value, form.minutevalue(in1).value, form.secondvalue(in1).value)  '  convert latitude of point to decimal degrees then radians
        Dim latrad1 = deg2rad(latddd1)
        Dim londdd1 = dms2ddd(form.degreevalue(in2).value, form.minutevalue(in2).value, form.secondvalue(in2).value)  '  likewise for longitude
        Dim lonrad1 = deg2rad(londdd1)
        Dim x12 = dms2ddd(form.degreevalue(in6).value, form.minutevalue(in6).value, form.secondvalue(in6).value)  ' convert to decimal degrees
        x12 = deg2rad(x12)             ' convert to radians
        Dim s As Double = (CDbl(form.distvalue(in5).value) * units)

        If (Math.Abs(s) > 10019148.059) Then
            MsgBox("Sorry this calculator isn't designed for such large distances.\nTry my Great Circle Calculator instead.")
        End If
        Dim tanB1 As Double = Math.Tan(latrad1) * (1 - f)
        Dim B1 As Double = Math.Atan(tanB1)
        Dim cosB0 As Double = Math.Cos(B1) * Math.Sin(x12)
        Dim B0 As Double = Math.Acos(cosB0)
        Dim g As Double = Math.Cos(B1) * Math.Cos(x12)
        Dim m As Double = (1 + (ei2 / 2) * Math.Sin(B1) * Math.Sin(B1)) * (1 - Math.Cos(B0) * Math.Cos(B0))
        Dim phis = s / b
        Dim a1 As Double = (1 + (ei2 / 2) * Math.Sin(B1) * Math.Sin(B1)) * (Math.Sin(B1) * Math.Sin(B1) * Math.Cos(phis) + g * Math.Sin(B1) * Math.Sin(phis))

        Dim term1 As Double = a1 * (-1 * (ei2 / 2) * Math.Sin(phis))
        Dim term2 As Double = m * (-1 * (ei2 / 4) * phis + (ei2 / 4) * Math.Sin(phis) * Math.Cos(phis))
        Dim term3 As Double = a1 * a1 * ((5 * ei2 * ei2 / 8) * Math.Sin(phis) * Math.Cos(phis))
        Dim term4 As Double = m * m * ((11 * ei2 * ei2 / 64) * phis - (13 * ei2 * ei2 / 64) * Math.Sin(phis) * Math.Cos(phis) - (ei2 * ei2 / 8) * phis * Math.Cos(phis) * Math.Cos(phis) + (5 * ei2 * ei2 / 32) * Math.Sin(phis) * Math.Pow(Math.Cos(phis), 3))
        Dim term5 As Double = a1 * m * ((3 * ei2 * ei2 / 8) * Math.Sin(phis) + (ei2 * ei2 / 4) * phis * Math.Cos(phis) - (5 * ei2 * ei2 / 8) * Math.Sin(phis) * Math.Cos(phis) * Math.Cos(phis))
        Dim phi0 = phis + term1 + term2 + term3 + term4 + term5

        Dim cotlamda As Double = (Math.Cos(B1) * Math.Cos(phi0) - Math.Sin(B1) * Math.Sin(phi0) * Math.Cos(x12)) / (Math.Sin(phi0) * Math.Sin(x12))
        Dim lamda As Double = Math.Atan(1 / cotlamda)

        term1 = -1 * f * phis
        term2 = a1 * ((3 * f * f / 2) * Math.Sin(phis))
        term3 = m * ((3 * f * f / 4) * phis - (3 * f * f / 4) * Math.Sin(phis) * Math.Cos(phis))
        Dim w As Double = (term1 + term2 + term3) * Math.Cos(B0) + lamda

        Dim lonrad2 = lonrad1 + w
        ddd2dms(form, in4, rad2deg(lonrad2))

        Dim sinB2 As Double = Math.Sin(B1) * Math.Cos(phi0) + g * Math.Sin(phi0)
        Dim cosB2 As Double = Math.Sqrt((Math.Cos(B0) * Math.Cos(B0)) + Math.Pow((g * Math.Cos(phi0) - Math.Sin(B1) * Math.Sin(phi0)), 2))
        Dim tanB2 = sinB2 / cosB2
        Dim tanlat2 = tanB2 / (1 - f)
        Dim latrad2 As Double = Math.Atan(tanlat2)
        ddd2dms(form, in3, rad2deg(latrad2))

        Return True
    End Function

    Function ddd2dms(ByVal form As FormType, ByVal ind As Integer, ByVal bearing) As Boolean
        Dim y As Double = Math.Abs(CDbl(bearing))
        form.degreevalue(ind).value = CInt(y + 1) - 1
        Dim x As Double = y - form.degreevalue(ind).value
        form.minutevalue(ind).value = CInt(x * 60 + 1) - 1
        form.secondvalue(ind).value = ((x * 60) - form.minutevalue(ind).value) * 60
        form.secondvalue(ind).value = roundoff(form.secondvalue(ind).value, secsize)
        If (form.secondvalue(ind).value = 60) Then
            form.secondvalue(ind).value = "0"
            form.minutevalue(ind).value = form.minutevalue(ind).value * 1 + 1
            If (form.minutevalue(ind).value = 60) Then
                form.minutevalue(ind).value = "0"
                form.degreevalue(ind).value = form.degreevalue(ind).value * 1 + 1
            End If
        End If
        If (bearing < 0) Then
            If (form.degreevalue(ind).value <> 0) Then
                form.degreevalue(ind).value = -form.degreevalue(ind).value
            ElseIf (form.minutevalue(ind).value <> 0) Then
                form.minutevalue(ind).value = -form.minutevalue(ind).value
            Else
                form.secondvalue(ind).value = -form.secondvalue(ind).value
            End If
        End If
        form.degreevalue(ind).value += "\260"                                        '  add degrees symbol now we have finished with value
        form.minutevalue(ind).value += "\'"                                        ' add minute symbol now we have finished with value
        With form.secondvalue(ind)
             value = value + '\"'               ' round off seconds and add symbol
        End With
        Return True
    End Function

    Function confirmSphChange(ByVal form) As Boolean             ' to only allow changes to spheroid parameters If in user defined mode

        Dim i As Double = form.spheroid.selectedIndex
        If (i <> 22) Then
            form.a.blur()
            form.invf.blur()
            MsgBox("\n To override Spheroid Parameters\n use the User Defined option.")
        End If
        Return True
    End Function



    Function updateSpheroid(ByVal form) As Boolean

        Dim i As Double = form.spheroid.selectedIndex
        Select Case i
            Case 0
                form.a.value = 6378388.0
                form.invf.value = 297.0
        End Select
        Return True
    End Function

    Function confirmProjChange(ByVal form) As Boolean             ' to only allow changes to projection parameters If in user defined mode

        Dim i As Double = form.projection.selectedIndex
        If (i <> 2) Then
            form.falsenorth.blur()
            form.falseeast.blur()
            form.k.blur()
            MsgBox("\n To override Projection Parameters\n use the User Defined option.")
        End If
        Return True
    End Function

    Sub updateProjection(ByVal form, ByVal x As Integer)

        Dim i As Double = form.projection.selectedIndex
        Dim j As Double = form.units.selectedIndex
        Dim units = form.units.options(j).value
        Select Case i
            Case 0
                form.falsenorth.value = 0
                form.falseeast.value = 500000 / units
                form.k.value = 0.9996

            Case 1
                form.falsenorth.value = 10000000 / units
                form.falseeast.value = 500000 / units
                form.k.value = 0.9996

            Case 2
                If (x = 1) Then                  '  only reset If called from projection selection not grid units
      form.falsenorth.value = ''
      form.falseeast.value = ''
      form.k.value = ''
                End If

        End Select
    End Sub

    Function swapgeos(ByVal form) As Boolean
        Dim x As Double = form.degreevalue(0).value
        form.degreevalue(0).value = form.degreevalue(5).value
        form.degreevalue(5).value = x
        x = form.degreevalue(1).value
        form.degreevalue(1).value = form.degreevalue(6).value
        form.degreevalue(6).value = x

        x = form.minutevalue(0).value
        form.minutevalue(0).value = form.minutevalue(5).value
        form.minutevalue(5).value = x
        x = form.minutevalue(1).value
        form.minutevalue(1).value = form.minutevalue(6).value
        form.minutevalue(6).value = x

        x = form.secondvalue(0).value
        form.secondvalue(0).value = form.secondvalue(5).value
        form.secondvalue(5).value = x
        x = form.secondvalue(1).value
        form.secondvalue(1).value = form.secondvalue(6).value
        form.secondvalue(6).value = x
        Return True
    End Function

    Function swapgrid(ByVal form) As Boolean
        Dim x As Double = form.north(0).value
        form.north(0).value = form.north(1).value
        form.north(1).value = x
        x = form.east(0).value
        form.east(0).value = form.east(1).value
        form.east(1).value = x
        Return True
    End Function

    Sub updateCM(ByVal form)
        Dim zone As Double = CDbl(form.zone.value)
        If ((zone < 1) Or (zone > 60) Or isblank(form.zone.value)) Then
            form.zone.value = ""
            MsgBox("\n  Please enter a UTM Zone number\n between 1 and 60.")
            form.zone.focus()
        Else
            form.cmlong.value = zone * 6 - 183 + "\260"
        End If
    End Sub

    Sub updateZone(ByVal form)
        Dim cmlong As Double = CDbl(form.cmlong.value)
        If ((cmlong < -180) Or (cmlong > 180) Or isblank(form.cmlong.value)) Then
            form.cmlong.value = ""
            MsgBox("\n Please enter a Longitude of Central Meridian between +/- 180\260")
            form.cmlong.focus()
        Else
            form.zone.value = roundoff(((cmlong + 183) / 6), 2)
        End If
    End Sub

End Module
0
 
LVL 1

Author Comment

by:nzfire
Comment Utility
Hi Again bpmurray,

Could you give me a quick rundown of the form stuff...

For instance form.east(in2).value

In the case of the field "east" how does the in2 work? How can i pass variables to the function?
0
 
LVL 1

Author Comment

by:nzfire
Comment Utility
I found out how i can get it to work, however, I get an error in the for loop:

Index was outside the bounds of the array

This is the code from the Geo2Grid function



        Dim a As Double = 6378388.0
        Dim n0 As Double = 6023150.0
        Dim e0 As Double = 2510000.0
        Dim lt0 As Double = -41.0
        Dim ln0 As Double = 173.0


        Dim latddd As Double = dms2ddd(Val(Me.latDeg.Text), Val(Me.latMin.Text), Val(Me.latSec.Text))  '  convert latitude of point to decimal degrees then radians
        Dim latrad As Double = deg2rad(latddd)
        Dim londdd As Double = dms2ddd(Val(Me.lonDeg.Text), Val(Me.lonMin.Text), Val(Me.lonSec.Text))  '  likewise for longitude
        Dim lonrad As Double = deg2rad(londdd)

        Debug.Print(latddd)
        Debug.Print(londdd)

        Dim lt As Double = (latddd - lt0) * 0.036
        Dim sum As Double = 0
        Dim i As Integer
        For i = 0 To 10
            sum = sum + cfi(i) * Math.Pow(lt, i + 1)    '<--index was outside the bounds of the array
        Next i

        Dim z1 As Complex = New Complex(sum, deg2rad(londdd - ln0))

        Dim z0 As Complex = New Complex(0, 0)
        Dim z2 As Complex = New Complex(0, 0)
        Dim z3 As Complex = New Complex(0, 0)

        Dim ij As Integer
        For ij = 0 To 6
            z2 = z1.power(ij + 1)
            z3 = z2.multiply(cfb1(ij))
            z0 = z3.add(z0)
        Next ij
        Me.North.Text = n0 + z0.x * a
        Me.East.Text = e0 + z0.y * a
0
 
LVL 15

Expert Comment

by:bpmurray
Comment Utility
Oops! You're dead right: that's an error. In fact, all the FOR-loops are incorrect; the to-value should be 1 less. So this particular example should be:

        For i = 0 To 9  ' <============== reduce by 1 from 10
            sum = sum + cfi(i) * Math.Pow(lt, i + 1)    '<--index was outside the bounds of the array
        Next i

        Dim z1 As Complex = New Complex(sum, deg2rad(londdd - ln0))

        Dim z0 As Complex = New Complex(0, 0)
        Dim z2 As Complex = New Complex(0, 0)
        Dim z3 As Complex = New Complex(0, 0)

        Dim ij As Integer
        For ij = 0 To 5 ' <============== reduce by 1 from 6
            z2 = z1.power(ij + 1)

There are a few more (actually 8 altogether) that need to be adjusted.
0
 
LVL 1

Author Comment

by:nzfire
Comment Utility
Ok, here's the update - you're really going to hate me now! I am starting to work with just that function for now and have reduced the to-value to 1 less than what it was.

Now the error I get is: "Arithmetic operation resulted in an overflow."
the location of the error is:    

Public Function multiply(ByVal b As Complex) As Complex
        Return New Complex(Me.x * b.x - Me.y * b.y, Me.x * b.y + Me.y * b.x)
    End Function

Just for your info, my test data is -34 degrees, 24 minutes, 2 seconds and 174 degrees east, 34 minutes and 1 second.

0
 
LVL 15

Expert Comment

by:bpmurray
Comment Utility
Can you display what the Me.x & y and b.x & y values are, please. That may tell what the problem is.
0
 
LVL 1

Author Comment

by:nzfire
Comment Utility
Here is what the values are when it breaks,


+            Me      {NZMGCalc.Complex}      NZMGCalc.Complex
            Me.x      &H283E100      Integer
            Me.y      &HFA98A000      Integer
+            b      {NZMGCalc.Complex}      NZMGCalc.Complex
            b.x      &H283E100      Integer
            b.y      &HFA98A000      Integer
            multiply      Nothing      NZMGCalc.Complex
0
 
LVL 15

Expert Comment

by:bpmurray
Comment Utility
Wow! They are biiiiiiiiiiig! No wonder there's an overflow. The multiply method itself should be OK, so the problem is where it's called from. Which method are you testing?
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 1

Author Comment

by:nzfire
Comment Utility
Yep, it sure is!!

Here is the sub, which is the code from the Geo2Grid function, with the variables hardcoded, well, not really hard coded, but taken from a textbox.

The values for example are:
latDeg = -34 latMin = 22 latSec = 2
lonDeg = 174 lonMin = 32 lonSec = 0


'/Begin Code
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim a As Double = 6378388.0
        Dim n0 As Double = 6023150.0
        Dim e0 As Double = 2510000.0
        Dim lt0 As Double = -41.0
        Dim ln0 As Double = 173.0


        Dim latddd As Double = dms2ddd(Val(Me.latDeg.Text), Val(Me.latMin.Text), Val(Me.latSec.Text))  '  convert latitude of point to decimal degrees then radians
        Dim latrad As Double = deg2rad(latddd)
        Dim londdd As Double = dms2ddd(Val(Me.lonDeg.Text), Val(Me.lonMin.Text), Val(Me.lonSec.Text))  '  likewise for longitude
        Dim lonrad As Double = deg2rad(londdd)

        Debug.Print(latddd)
        Debug.Print(londdd)

        Dim lt As Double = (latddd - lt0) * 0.036
        Dim sum As Double = 0
        Dim i As Integer
        For i = 0 To 9 'was 10
            sum = sum + cfi(i) * Math.Pow(lt, i + 1)
        Next i

        Dim z1 As Complex = New Complex(sum, deg2rad(londdd - ln0))

        Dim z0 As Complex = New Complex(0, 0)
        Dim z2 As Complex = New Complex(0, 0)
        Dim z3 As Complex = New Complex(0, 0)

        Dim ij As Integer
        For ij = 0 To 5 'was 6
            z2 = z1.power(ij + 1)
            z3 = z2.multiply(cfb1(ij))
            z0 = z3.add(z0)
        Next ij
        Me.North.Text = n0 + z0.x * a
        Me.East.Text = e0 + z0.y * a
    End Sub

'/End code
0
 
LVL 15

Expert Comment

by:bpmurray
Comment Utility
It seems to work OK for me - can you check your implementations of these:

    Function dms2ddd(ByVal d As Double, ByVal m As Double, ByVal s As Double) As Double
        Dim x As Double = Math.Abs(d) + (Math.Abs(m) / 60) + (Math.Abs(s) / 3600)  ' convert to decimal degrees
        If ((d < 0) Or (m < 0) Or (s < 0)) Then
            x = -x
        End If
        Return x
    End Function

    Function deg2rad(ByVal x As Double) As Double                ' convert decimal degrees to radians
        x = x * pi / 180
        Return x
    End Function
0
 
LVL 15

Expert Comment

by:bpmurray
Comment Utility
Oh, the Debug.print statements output this:
-34.3672222222222
104.533333333333
-34.3672222222222
104.533333333333
0
 
LVL 1

Author Comment

by:nzfire
Comment Utility
i changed that function to the code you supplied above and the answers now give:

North 6023150
East 2510000

Even if I change the latitude/longitude within reason ie a few degrees, I get the same answer!!

In the web page I get the following, (Using the above lat long)

The answer should be North = 6758066.224704542 and East = 2652129.2868528683

Sorry that this is such a hassle Brendan. I really appreciate your help.

Sean
0
 
LVL 15

Expert Comment

by:bpmurray
Comment Utility
Since the results are integral, it looks like some value has been converted to an integer and lost its precision. The results are within a few percent of the expected values, so this seems very likely. Perhaps the best solution is to go through the classes and change any integer to a double. The Complex types seem OK to me, so it's really only the other calculations that need to be tweaked.
0
 
LVL 1

Author Comment

by:nzfire
Comment Utility
Okie dokie, Here is an update.

I have changed the offending Ints and get better results with using doubles, but still a bit off...

I've been comparing what I should get with the js version and about 500 odd metres off, so maybe again a precision thing.

Cheers,
Sean
0
 
LVL 1

Author Comment

by:nzfire
Comment Utility
Second update: Changing the types in the complex class changes it. I found that changing the ints in the following gave more of the right answer.

    Public Sub New(ByVal real As Double, ByVal imaginary As Double) 'both int
        x = real
        y = imaginary
    End Sub
0
 
LVL 15

Expert Comment

by:bpmurray
Comment Utility
That's interesting: it shouldn't really be an issue, although division would result in rounded results, which may be where the error occurs. If this is the case, you should also update all Integers in that class file to Double.
0
 
LVL 1

Author Comment

by:nzfire
Comment Utility
Yep, tried that and still get a small error when I compare the values I get back from this code against the js version.

Any suggestions on how to debug it....well I should say "tweak" :)
0
 
LVL 15

Expert Comment

by:bpmurray
Comment Utility
UNfortunately, I don't know what you actually have as code any more :-)

Perhaps this small difference is in the UI to internal value conversion? That's a common place to lose accuracy. Try a debug display of some of the calculations, and compare these with the equivalents in the web page - use alert() calls there.
0
 
LVL 1

Author Comment

by:nzfire
Comment Utility
Thats exactly what I will do...

I'm going to accept this now anyway and if I still have any queries I might have to post back. :)

Thanks a million
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Adobe Customization Wizard XI issues 26 163
VBA color chart bars 12 64
countHi challenge 25 84
Scripting vs. Programming languages 25 109
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
Although it can be difficult to imagine, someday your child will have a career of his or her own. He or she will likely start a family, buy a home and start having their own children. So, while being a kid is still extremely important, it’s also …
An introduction to basic programming syntax in Java by creating a simple program. Viewers can follow the tutorial as they create their first class in Java. Definitions and explanations about each element are given to help prepare viewers for future …
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now