Commit 7bc9d2b7 authored by Calvin Metcalf's avatar Calvin Metcalf
Browse files

common.js just points to the modules in the common directory

parent e8572d7f
Loading
Loading
Loading
Loading
+33 −359
Original line number Diff line number Diff line
@@ -39,424 +39,98 @@ exports.RV6 = 0.04243827160493827160;
// Function to compute the constant small m which is the radius of
//   a parallel of latitude; phi; divided by the semimajor axis.
// -----------------------------------------------------------------
exports.msfnz = function(eccent, sinphi, cosphi) {
  var con = eccent * sinphi;
  return cosphi / (Math.sqrt(1 - con * con));
};
exports.msfnz = require('./common/msfnz');

// Function to compute the constant small t for use in the forward
//   computations in the Lambert Conformal Conic and the Polar
//   Stereographic projections.
// -----------------------------------------------------------------
exports.tsfnz = function(eccent, phi, sinphi) {
  var con = eccent * sinphi;
  var com = 0.5 * eccent;
  con = Math.pow(((1 - con) / (1 + con)), com);
  return (Math.tan(0.5 * (this.HALF_PI - phi)) / con);
};
exports.tsfnz = require('./common/tsfnz');

// Function to compute the latitude angle; phi2; for the inverse of the
//   Lambert Conformal Conic and Polar Stereographic projections.
// ----------------------------------------------------------------
exports.phi2z = function(eccent, ts) {
  var eccnth = 0.5 * eccent;
  var con, dphi;
  var phi = this.HALF_PI - 2 * Math.atan(ts);
  for (var i = 0; i <= 15; i++) {
    con = eccent * Math.sin(phi);
    dphi = this.HALF_PI - 2 * Math.atan(ts * (Math.pow(((1 - con) / (1 + con)), eccnth))) - phi;
    phi += dphi;
    if (Math.abs(dphi) <= 0.0000000001) {
      return phi;
    }
  }
  //console.log("phi2z has NoConvergence");
  return -9999;
};
exports.phi2z = require('./common/phi2z');

/* Function to compute constant small q which is the radius of a 
   parallel of latitude, phi, divided by the semimajor axis. 
------------------------------------------------------------*/
exports.qsfnz = function(eccent, sinphi) {
  var con;
  if (eccent > 1.0e-7) {
    con = eccent * sinphi;
    return ((1 - eccent * eccent) * (sinphi / (1 - con * con) - (0.5 / eccent) * Math.log((1 - con) / (1 + con))));
  }
  else {
    return (2 * sinphi);
  }
};
exports.qsfnz = require('./common/qsfnz');

/* Function to compute the inverse of qsfnz
------------------------------------------------------------*/
exports.iqsfnz = function(eccent, q) {
  var temp = 1 - (1 - eccent * eccent) / (2 * eccent) * Math.log((1 - eccent) / (1 + eccent));
  if (Math.abs(Math.abs(q) - temp) < 1.0E-6) {
    if (q < 0) {
      return (-1 * exports.HALF_PI);
    }
    else {
      return exports.HALF_PI;
    }
  }
  //var phi = 0.5* q/(1-eccent*eccent);
  var phi = Math.asin(0.5 * q);
  var dphi;
  var sin_phi;
  var cos_phi;
  var con;
  for (var i = 0; i < 30; i++) {
    sin_phi = Math.sin(phi);
    cos_phi = Math.cos(phi);
    con = eccent * sin_phi;
    dphi = Math.pow(1 - con * con, 2) / (2 * cos_phi) * (q / (1 - eccent * eccent) - sin_phi / (1 - con * con) + 0.5 / eccent * Math.log((1 - con) / (1 + con)));
    phi += dphi;
    if (Math.abs(dphi) <= 0.0000000001) {
      return phi;
    }
  }

  //console.log("IQSFN-CONV:Latitude failed to converge after 30 iterations");
  return NaN;
};
exports.iqsfnz = require('./common/iqsfnz');

/* Function to eliminate roundoff errors in asin
----------------------------------------------*/
exports.asinz = function(x) {
  if (Math.abs(x) > 1) {
    x = (x > 1) ? 1 : -1;
  }
  return Math.asin(x);
};
exports.asinz = require('./common/asinz');

// following functions from gctpc cproj.c for transverse mercator projections
exports.e0fn = function(x) {
  return (1 - 0.25 * x * (1 + x / 16 * (3 + 1.25 * x)));
};
exports.e1fn = function(x) {
  return (0.375 * x * (1 + 0.25 * x * (1 + 0.46875 * x)));
};
exports.e2fn = function(x) {
  return (0.05859375 * x * x * (1 + 0.75 * x));
};
exports.e3fn = function(x) {
  return (x * x * x * (35 / 3072));
};
exports.mlfn = function(e0, e1, e2, e3, phi) {
  return (e0 * phi - e1 * Math.sin(2 * phi) + e2 * Math.sin(4 * phi) - e3 * Math.sin(6 * phi));
};
exports.imlfn = function(ml, e0, e1, e2, e3) {
  var phi;
  var dphi;

  phi = ml / e0;
  for (var i = 0; i < 15; i++) {
    dphi = (ml - (e0 * phi - e1 * Math.sin(2 * phi) + e2 * Math.sin(4 * phi) - e3 * Math.sin(6 * phi))) / (e0 - 2 * e1 * Math.cos(2 * phi) + 4 * e2 * Math.cos(4 * phi) - 6 * e3 * Math.cos(6 * phi));
    phi += dphi;
    if (Math.abs(dphi) <= 0.0000000001) {
      return phi;
    }
  }

  //..reportError("IMLFN-CONV:Latitude failed to converge after 15 iterations");
  return NaN;
};
exports.e0fn = require('./common/e0fn');
exports.e1fn = require('./common/e1fn');
exports.e2fn = require('./common/e2fn');
exports.e3fn = require('./common/e3fn');
exports.mlfn = require('./common/mlfn');
exports.imlfn = require('./common/imlfn');

exports.srat = function(esinp, exp) {
  return (Math.pow((1 - esinp) / (1 + esinp), exp));
};
exports.srat = require('./common/srat');

// Function to return the sign of an argument
exports.sign = function(x) {
  if (x < 0) {
    return (-1);
  }
  else {
    return (1);
  }
};
exports.sign = require('./common/sign');

// Function to adjust longitude to -180 to 180; input in radians
exports.adjust_lon = function(x) {
  x = (Math.abs(x) < this.PI) ? x : (x - (this.sign(x) * this.TWO_PI));
  return x;
};
exports.adjust_lon = require('./common/adjust_lon');

// IGNF - DGR : algorithms used by IGN France

// Function to adjust latitude to -90 to 90; input in radians
exports.adjust_lat = function(x) {
  x = (Math.abs(x) < this.HALF_PI) ? x : (x - (this.sign(x) * this.PI));
  return x;
};
exports.adjust_lat = require('./common/adjust_lat');

// Latitude Isometrique - close to tsfnz ...
exports.latiso = function(eccent, phi, sinphi) {
  if (Math.abs(phi) > this.HALF_PI) {
    return Number.NaN;
  }
  if (phi === this.HALF_PI) {
    return Number.POSITIVE_INFINITY;
  }
  if (phi === -1 * this.HALF_PI) {
    return Number.NEGATIVE_INFINITY;
  }
exports.latiso = require('./common/latiso');

  var con = eccent * sinphi;
  return Math.log(Math.tan((this.HALF_PI + phi) / 2)) + eccent * Math.log((1 - con) / (1 + con)) / 2;
};

exports.fL = function(x, L) {
  return 2 * Math.atan(x * Math.exp(L)) - this.HALF_PI;
};
exports.fL = require('./common/fL');

// Inverse Latitude Isometrique - close to ph2z
exports.invlatiso = function(eccent, ts) {
  var phi = this.fL(1, ts);
  var Iphi = 0;
  var con = 0;
  do {
    Iphi = phi;
    con = eccent * Math.sin(Iphi);
    phi = this.fL(Math.exp(eccent * Math.log((1 + con) / (1 - con)) / 2), ts);
  } while (Math.abs(phi - Iphi) > 1.0e-12);
  return phi;
};
exports.invlatiso = require('./common/invlatiso');

// Needed for Gauss Schreiber
// Original:  Denis Makarov (info@binarythings.com)
// Web Site:  http://www.binarythings.com
exports.sinh = function(x) {
  var r = Math.exp(x);
  r = (r - 1 / r) / 2;
  return r;
};
exports.sinh = require('./common/sinh');

exports.cosh = function(x) {
  var r = Math.exp(x);
  r = (r + 1 / r) / 2;
  return r;
};
exports.cosh = require('./common/cosh');

exports.tanh = function(x) {
  var r = Math.exp(x);
  r = (r - 1 / r) / (r + 1 / r);
  return r;
};
exports.tanh = require('./common/tanh');

exports.asinh = function(x) {
  var s = (x >= 0 ? 1 : -1);
  return s * (Math.log(Math.abs(x) + Math.sqrt(x * x + 1)));
};
exports.asinh = require('./common/asinh');

exports.acosh = function(x) {
  return 2 * Math.log(Math.sqrt((x + 1) / 2) + Math.sqrt((x - 1) / 2));
};
exports.acosh = require('./common/acosh');

exports.atanh = function(x) {
  return Math.log((x - 1) / (x + 1)) / 2;
};
exports.atanh = require('./common/atanh');

// Grande Normale
exports.gN = function(a, e, sinphi) {
  var temp = e * sinphi;
  return a / Math.sqrt(1 - temp * temp);
};
exports.gN = require('./common/gN');

//code from the PROJ.4 pj_mlfn.c file;  this may be useful for other projections
exports.pj_enfn = function(es) {
  var en = [];
  en[0] = this.C00 - es * (this.C02 + es * (this.C04 + es * (this.C06 + es * this.C08)));
  en[1] = es * (this.C22 - es * (this.C04 + es * (this.C06 + es * this.C08)));
  var t = es * es;
  en[2] = t * (this.C44 - es * (this.C46 + es * this.C48));
  t *= es;
  en[3] = t * (this.C66 - es * this.C68);
  en[4] = t * es * this.C88;
  return en;
};
exports.pj_enfn = require('./common/pj_enfn');

exports.pj_mlfn = function(phi, sphi, cphi, en) {
  cphi *= sphi;
  sphi *= sphi;
  return (en[0] * phi - cphi * (en[1] + sphi * (en[2] + sphi * (en[3] + sphi * en[4]))));
};
exports.pj_mlfn = require('./common/pj_mlfn');

exports.pj_inv_mlfn = function(arg, es, en) {
  var k = 1 / (1 - es);
  var phi = arg;
  for (var i = exports.MAX_ITER; i; --i) { /* rarely goes over 2 iterations */
    var s = Math.sin(phi);
    var t = 1 - es * s * s;
    //t = this.pj_mlfn(phi, s, Math.cos(phi), en) - arg;
    //phi -= t * (t * Math.sqrt(t)) * k;
    t = (this.pj_mlfn(phi, s, Math.cos(phi), en) - arg) * (t * Math.sqrt(t)) * k;
    phi -= t;
    if (Math.abs(t) < exports.EPSLN) {
      return phi;
    }
  }
  //..reportError("cass:pj_inv_mlfn: Convergence error");
  return phi;
};
exports.nadInterBreakout = function(indx, frct, letter, number, ct) {
  var inx;
  if (indx[letter] < 0) {
    if (!(indx[letter] === -1 && frct[letter] > 0.99999999999)) {
      return false;
    }
    indx[letter]++;
    frct[letter] = 0;
  }
  else {
    inx = indx[letter] + 1;
    if (inx >= ct.lim[number]) {
      if (!(inx === ct.lim[number] && frct[letter] < 1e-11)) {
        return false;
      }
      if (letter === 'x') {
        indx[letter]--;
      }
      else {
        indx[letter]++;
      }
      frct[letter] = 1;
    }
  }
  return [indx, frct];
};
exports.pj_inv_mlfn = require('./common/pj_inv_mlfn');
exports.nadInterBreakout = require('./common/nadInterBreakout');
/**
 * Determine correction values
 * source: nad_intr.c (DGR: 2012-07-29)
 */
exports.nad_intr = function(pin, ct) {
  // force computation by decreasing by 1e-7 to be as closed as possible
  // from computation under C:C++ by leveraging rounding problems ...
  var t = {
    x: (pin.x - 1e-7) / ct.del[0],
    y: (pin.y - 1e-7) / ct.del[1]
  };
  var indx = {
    x: Math.floor(t.x),
    y: Math.floor(t.y)
  };
  var frct = {
    x: t.x - 1 * indx.x,
    y: t.y - 1 * indx.y
  };
  var val = {
    x: Number.NaN,
    y: Number.NaN
  };


  var temp = exports.nadInterBreakout(indx, frct, 'x', 0, ct);
  if (temp) {
    indx = temp[0];
    frct = temp[1];
  }
  else {
    return val;
  }
  temp = exports.nadInterBreakout(indx, frct, 'y', 1, ct);
  if (temp) {
    indx = temp[0];
    frct = temp[1];
  }
  else {
    return val;
  }
  var inx = (indx.y * ct.lim[0]) + indx.x;
  var f00 = {
    x: ct.cvs[inx][0],
    y: ct.cvs[inx][1]
  };
  inx++;
  var f10 = {
    x: ct.cvs[inx][0],
    y: ct.cvs[inx][1]
  };
  inx += ct.lim[0];
  var f11 = {
    x: ct.cvs[inx][0],
    y: ct.cvs[inx][1]
  };
  inx--;
  var f01 = {
    x: ct.cvs[inx][0],
    y: ct.cvs[inx][1]
  };
  var m11 = frct.x * frct.y,
    m10 = frct.x * (1 - frct.y),
    m00 = (1 - frct.x) * (1 - frct.y),
    m01 = (1 - frct.x) * frct.y;
  val.x = (m00 * f00.x + m10 * f10.x + m01 * f01.x + m11 * f11.x);
  val.y = (m00 * f00.y + m10 * f10.y + m01 * f01.y + m11 * f11.y);
  return val;
};
exports.nad_intr = require('./common/nad_intr');

/**
 * Correct value
 * source: nad_cvt.c (DGR: 2012-07-29)
 */
exports.inverseNadCvt = function(t, val, tb, ct) {
  if (isNaN(t.x)) {
    return val;
  }
  t.x = tb.x + t.x;
  t.y = tb.y - t.y;
  var i = 9,
    tol = 1e-12;
  var dif, del;
  do {
    del = exports.nad_intr(t, ct);
    if (isNaN(del.x)) {
      this.reportError("Inverse grid shift iteration failed, presumably at grid edge.  Using first approximation.");
      break;
    }
    dif = {
      "x": t.x - del.x - tb.x,
      "y": t.y + del.y - tb.y
    };
    t.x -= dif.x;
    t.y -= dif.y;
  } while (i-- && Math.abs(dif.x) > tol && Math.abs(dif.y) > tol);
  if (i < 0) {
    this.reportError("Inverse grid shift iterator failed to converge.");
    return val;
  }
  val.x = exports.adjust_lon(t.x + ct.ll[0]);
  val.y = t.y + ct.ll[1];
  return val;
};
exports.nad_cvt = function(pin, inverse, ct) {
  var val = {
    "x": Number.NaN,
    "y": Number.NaN
  };
  if (isNaN(pin.x)) {
    return val;
  }
  var tb = {
    "x": pin.x,
    "y": pin.y
  };
  tb.x -= ct.ll[0];
  tb.y -= ct.ll[1];
  tb.x = exports.adjust_lon(tb.x - exports.PI) + exports.PI;
  var t = exports.nad_intr(tb, ct);
  if (inverse) {
    return exports.inverseNadCvt(t, val, tb, ct);
  }
  else {
    if (!isNaN(t.x)) {
      val.x = pin.x - t.x;
      val.y = pin.y + t.y;
    }
  }
  return val;
};
exports.inverseNadCvt = require('./common/inverseNadCvt');
exports.nad_cvt = require('./common/nad_cvt');

/* meridinal distance for ellipsoid and inverse
 **    8th degree - accurate to < 1e-5 meters when used in conjuction

lib/common/acosh.js

0 → 100644
+3 −0
Original line number Diff line number Diff line
module.exports = function(x) {
  return 2 * Math.log(Math.sqrt((x + 1) / 2) + Math.sqrt((x - 1) / 2));
};
 No newline at end of file
+6 −0
Original line number Diff line number Diff line
var HALF_PI = Math.PI/2;
var sign = require('./sign');

module.exports = function(x) {
  return (Math.abs(x) < HALF_PI) ? x : (x - (sign(x) * Math.PI));
};
 No newline at end of file
+6 −0
Original line number Diff line number Diff line
var TWO_PI = Math.PI * 2;
var sign = require('./sign');

module.exports = function(x) {
  return (Math.abs(x) < Math.PI) ? x : (x - (sign(x) * TWO_PI));
};
 No newline at end of file

lib/common/asinh.js

0 → 100644
+4 −0
Original line number Diff line number Diff line
module.exports = function(x) {
  var s = (x >= 0 ? 1 : -1);
  return s * (Math.log(Math.abs(x) + Math.sqrt(x * x + 1)));
};
 No newline at end of file
Loading