<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic WGS84 Compliant Great Circle Distance Calculation in QlikView</title>
    <link>https://community.qlik.com/t5/QlikView/WGS84-Compliant-Great-Circle-Distance-Calculation/m-p/241910#M92302</link>
    <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Hi Alex,&lt;/P&gt;&lt;P&gt;Many thanks again for the script and instructions, I had a small (well ... quite large) panic yesterday when I compared the results I got using this to the results I had using the Haversine (spherical model) formula. Luckily, after a bit of investigation I found that all it was, was that the Lat and Long format in my file has the NSEW indicator at the front not the end so although the formula will still run (and give valid results on N and E coordinates which was confusing) it didn't seem to spot the indicator and do anything with it for the S and W directions.&lt;/P&gt;&lt;P&gt;I'm just really putting this on here for completeness in case anyone else uses the script ...&lt;/P&gt;&lt;P&gt;I have found someone here with more knowledge of Javascipt than me (not difficult!!) and there is one line of code we've amended to give a little more flexibility and allow for either a leading or trailing compass letter:&lt;/P&gt;&lt;P&gt;if (/^-|[WS]$/i.test(dmsStr.trim())) deg = -deg; // take '-', west and south as -ve&lt;/P&gt;&lt;P&gt;we have changed to&lt;/P&gt;&lt;P&gt;if (/^-|[WS]|[WS]$/i.test(dmsStr.trim())) deg = -deg; // take '-', west and south as -ve&lt;/P&gt;&lt;P&gt;A small change but means that I can plug it straight into our data without needing to convert to degrees first or try and move the compass letter from the beginning to the end of the coordinates!&lt;/P&gt;&lt;P&gt;Many thanks once again.&lt;/P&gt;&lt;P&gt;Cheers,&lt;/P&gt;&lt;P&gt;Emma&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
    <pubDate>Thu, 10 Mar 2011 11:20:13 GMT</pubDate>
    <dc:creator />
    <dc:date>2011-03-10T11:20:13Z</dc:date>
    <item>
      <title>WGS84 Compliant Great Circle Distance Calculation</title>
      <link>https://community.qlik.com/t5/QlikView/WGS84-Compliant-Great-Circle-Distance-Calculation/m-p/241905#M92297</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Hi,&lt;/P&gt;&lt;P&gt;I am trying to create a system that shows the distance between two coordinates. So far I've managed to get part way there using the Haversine formula to calculate great circle distance based on a spherical earth model. However, the requirements have just been tightened up and I now need to try and find a way of using a WGS84 compliant method (oblate spheroid model) which is much more complex.&lt;/P&gt;&lt;P&gt;I've found a suitable formula (the Vincenty algorithm &lt;A href="http://www.movable-type.co.uk/scripts/latlong-vincenty.html"&gt;http://www.movable-type.co.uk/scripts/latlong-vincenty.html&lt;/A&gt; ) but have yet to figure out how to get this into QlikView! The database the information is coming out of is clunky, in-house written (and those that wrote it no longer work for the company) and not Oracle based so ideally I need to figure this out without involving the source database. I have a a list of journeys in a qvd file with to and from coordinates in them and I need to calculate the distance ... any ideas? &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;&lt;P&gt;Ever hopeful!&lt;/P&gt;&lt;P&gt;Emma&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Tue, 08 Mar 2011 17:43:11 GMT</pubDate>
      <guid>https://community.qlik.com/t5/QlikView/WGS84-Compliant-Great-Circle-Distance-Calculation/m-p/241905#M92297</guid>
      <dc:creator />
      <dc:date>2011-03-08T17:43:11Z</dc:date>
    </item>
    <item>
      <title>WGS84 Compliant Great Circle Distance Calculation</title>
      <link>https://community.qlik.com/t5/QlikView/WGS84-Compliant-Great-Circle-Distance-Calculation/m-p/241906#M92298</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;hi,&lt;/P&gt;&lt;P&gt;Take a look at the source of the linked HTML page == there is Javascript with the formula &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt; !&lt;/P&gt;&lt;P&gt;Makea QlikView file with a module written in Jscript. Paste the code there.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;BLOCKQUOTE style="overflow-x: scroll;"&gt;&lt;PRE style="margin: 0px;"&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Calculates geodetic distance between two points specified by latitude/longitude using&lt;BR /&gt; * Vincenty inverse formula for ellipsoids&lt;BR /&gt; *&lt;BR /&gt; * @param {Number} lat1, lon1: first point in decimal degrees&lt;BR /&gt; * @param {Number} lat2, lon2: second point in decimal degrees&lt;BR /&gt; * @returns (Number} distance in metres between points&lt;BR /&gt; */&lt;BR /&gt;function distVincenty(lat1, lon1, lat2, lon2) {&lt;BR /&gt; var a = 6378137, b = 6356752.3142, f = 1/298.257223563; // WGS-84 ellipsoid params&lt;BR /&gt; var L = (lon2-lon1).toRad();&lt;BR /&gt; var U1 = Math.atan((1-f) * Math.tan(lat1.toRad()));&lt;BR /&gt; var U2 = Math.atan((1-f) * Math.tan(lat2.toRad()));&lt;BR /&gt; var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);&lt;BR /&gt; var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);&lt;BR /&gt;&lt;BR /&gt; var lambda = L, lambdaP, iterLimit = 100;&lt;BR /&gt; do {&lt;BR /&gt; var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);&lt;BR /&gt; var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +&lt;BR /&gt; (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));&lt;BR /&gt; if (sinSigma==0) return 0; // co-incident points&lt;BR /&gt; var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;&lt;BR /&gt; var sigma = Math.atan2(sinSigma, cosSigma);&lt;BR /&gt; var sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;&lt;BR /&gt; var cosSqAlpha = 1 - sinAlpha*sinAlpha;&lt;BR /&gt; var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;&lt;BR /&gt; if (isNaN(cos2SigmaM)) cos2SigmaM = 0; // equatorial line: cosSqAlpha=0 (§6)&lt;BR /&gt; var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));&lt;BR /&gt; lambdaP = lambda;&lt;BR /&gt; lambda = L + (1-C) * f * sinAlpha *&lt;BR /&gt; (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));&lt;BR /&gt; } while (Math.abs(lambda-lambdaP) &amp;gt; 1e-12 &amp;amp;&amp;amp; --iterLimit&amp;gt;0);&lt;BR /&gt; if (iterLimit==0) return NaN // formula failed to converge&lt;BR /&gt;&lt;BR /&gt; var uSq = cosSqAlpha * (a*a - b*b) / (b*b);&lt;BR /&gt; var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));&lt;BR /&gt; var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));&lt;BR /&gt; var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-&lt;BR /&gt; B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));&lt;BR /&gt; var s = b*A*(sigma-deltaSigma);&lt;BR /&gt;&lt;BR /&gt; s = s.toFixed(3); // round to 1mm precision&lt;BR /&gt; return s;&lt;BR /&gt;&lt;BR /&gt; // note: to return initial/final bearings in addition to distance, use something like:&lt;BR /&gt; var fwdAz = Math.atan2(cosU2*sinLambda, cosU1*sinU2-sinU1*cosU2*cosLambda);&lt;BR /&gt; var revAz = Math.atan2(cosU1*sinLambda, -sinU1*cosU2+cosU1*sinU2*cosLambda);&lt;BR /&gt; return { distance: s, initialBearing: fwdAz.toDeg(), finalBearing: revAz.toDeg() };&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */&lt;BR /&gt;&lt;BR /&gt;/** extend Number object with methods for converting degrees/radians */&lt;BR /&gt;toRad = function() { // convert degrees to radians&lt;BR /&gt; return this * Math.PI / 180;&lt;BR /&gt;}&lt;BR /&gt;toDeg = function() { // convert radians to degrees&lt;BR /&gt; return this * 180 / Math.PI;&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */&lt;BR /&gt;/* Latitude/longitude spherical geodesy formulae &amp;amp; scripts (c) Chris Veness 2002-2010 */&lt;BR /&gt;/* - www.movable-type.co.uk/scripts/latlong.html */&lt;BR /&gt;/* */&lt;BR /&gt;/* Sample usage: */&lt;BR /&gt;/* var p1 = new LatLon(51.5136, -0.0983); */&lt;BR /&gt;/* var p2 = new LatLon(51.4778, -0.0015); */&lt;BR /&gt;/* var dist = p1.distanceTo(p2); // in km */&lt;BR /&gt;/* var brng = p1.bearingTo(p2); // in degrees clockwise from north */&lt;BR /&gt;/* ... etc */&lt;BR /&gt;/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */&lt;BR /&gt;&lt;BR /&gt;/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */&lt;BR /&gt;/* Note that minimal error checking is performed in this example code! */&lt;BR /&gt;/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Creates a point on the earth's surface at the supplied latitude / longitude&lt;BR /&gt; *&lt;BR /&gt; * @constructor&lt;BR /&gt; * @param {Number} lat: latitude in numeric degrees&lt;BR /&gt; * @param {Number} lon: longitude in numeric degrees&lt;BR /&gt; * @param {Number} [rad=6371]: radius of earth if different value is required from standard 6,371km&lt;BR /&gt; */&lt;BR /&gt;function LatLon(lat, lon, rad) {&lt;BR /&gt; if (typeof(rad) == 'undefined') rad = 6371; // earth's mean radius in km&lt;BR /&gt; // only accept numbers or valid numeric strings&lt;BR /&gt; this._lat = typeof(lat)=='number' ? lat : typeof(lat)=='string' &amp;amp;&amp;amp; lat.trim()!='' ? +lat : NaN;&lt;BR /&gt; this._lon = typeof(lat)=='number' ? lon : typeof(lon)=='string' &amp;amp;&amp;amp; lon.trim()!='' ? +lon : NaN;&lt;BR /&gt; this._radius = typeof(rad)=='number' ? rad : typeof(rad)=='string' &amp;amp;&amp;amp; trim(lon)!='' ? +rad : NaN;&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Returns the distance from this point to the supplied point, in km&lt;BR /&gt; * (using Haversine formula)&lt;BR /&gt; *&lt;BR /&gt; * from: Haversine formula - R. W. Sinnott, "Virtues of the Haversine",&lt;BR /&gt; * Sky and Telescope, vol 68, no 2, 1984&lt;BR /&gt; *&lt;BR /&gt; * @param {LatLon} point: Latitude/longitude of destination point&lt;BR /&gt; * @param {Number} [precision=4]: no of significant digits to use for returned value&lt;BR /&gt; * @returns {Number} Distance in km between this point and destination point&lt;BR /&gt; */&lt;BR /&gt;distanceTo = function(point, precision) {&lt;BR /&gt; // default 4 sig figs reflects typical 0.3% accuracy of spherical model&lt;BR /&gt; if (typeof precision == 'undefined') precision = 4;&lt;BR /&gt;&lt;BR /&gt; var R = this._radius;&lt;BR /&gt; var lat1 = this._lat.toRad(), lon1 = this._lon.toRad();&lt;BR /&gt; var lat2 = point._lat.toRad(), lon2 = point._lon.toRad();&lt;BR /&gt; var dLat = lat2 - lat1;&lt;BR /&gt; var dLon = lon2 - lon1;&lt;BR /&gt;&lt;BR /&gt; var a = Math.sin(dLat/2) * Math.sin(dLat/2) +&lt;BR /&gt; Math.cos(lat1) * Math.cos(lat2) *&lt;BR /&gt; Math.sin(dLon/2) * Math.sin(dLon/2);&lt;BR /&gt; var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));&lt;BR /&gt; var d = R * c;&lt;BR /&gt; return d.toPrecisionFixed(precision);&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Returns the (initial) bearing from this point to the supplied point, in degrees&lt;BR /&gt; * see http://williams.best.vwh.net/avform.htm#Crs&lt;BR /&gt; *&lt;BR /&gt; * @param {LatLon} point: Latitude/longitude of destination point&lt;BR /&gt; * @returns {Number} Initial bearing in degrees from North&lt;BR /&gt; */&lt;BR /&gt;bearingTo = function(point) {&lt;BR /&gt; var lat1 = this._lat.toRad(), lat2 = point._lat.toRad();&lt;BR /&gt; var dLon = (point._lon-this._lon).toRad();&lt;BR /&gt;&lt;BR /&gt; var y = Math.sin(dLon) * Math.cos(lat2);&lt;BR /&gt; var x = Math.cos(lat1)*Math.sin(lat2) -&lt;BR /&gt; Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);&lt;BR /&gt; var brng = Math.atan2(y, x);&lt;BR /&gt;&lt;BR /&gt; return (brng.toDeg()+360) % 360;&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Returns final bearing arriving at supplied destination point from this point; the final bearing&lt;BR /&gt; * will differ from the initial bearing by varying degrees according to distance and latitude&lt;BR /&gt; *&lt;BR /&gt; * @param {LatLon} point: Latitude/longitude of destination point&lt;BR /&gt; * @returns {Number} Final bearing in degrees from North&lt;BR /&gt; */&lt;BR /&gt;finalBearingTo = function(point) {&lt;BR /&gt; // get initial bearing from supplied point back to this point...&lt;BR /&gt; var lat1 = point._lat.toRad(), lat2 = this._lat.toRad();&lt;BR /&gt; var dLon = (this._lon-point._lon).toRad();&lt;BR /&gt;&lt;BR /&gt; var y = Math.sin(dLon) * Math.cos(lat2);&lt;BR /&gt; var x = Math.cos(lat1)*Math.sin(lat2) -&lt;BR /&gt; Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);&lt;BR /&gt; var brng = Math.atan2(y, x);&lt;BR /&gt;&lt;BR /&gt; // ... &amp;amp; reverse it by adding 180°&lt;BR /&gt; return (brng.toDeg()+180) % 360;&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Returns the midpoint between this point and the supplied point.&lt;BR /&gt; * see http://mathforum.org/library/drmath/view/51822.html for derivation&lt;BR /&gt; *&lt;BR /&gt; * @param {LatLon} point: Latitude/longitude of destination point&lt;BR /&gt; * @returns {LatLon} Midpoint between this point and the supplied point&lt;BR /&gt; */&lt;BR /&gt;midpointTo = function(point) {&lt;BR /&gt; lat1 = this._lat.toRad(), lon1 = this._lon.toRad();&lt;BR /&gt; lat2 = point._lat.toRad();&lt;BR /&gt; var dLon = (point._lon-this._lon).toRad();&lt;BR /&gt;&lt;BR /&gt; var Bx = Math.cos(lat2) * Math.cos(dLon);&lt;BR /&gt; var By = Math.cos(lat2) * Math.sin(dLon);&lt;BR /&gt;&lt;BR /&gt; lat3 = Math.atan2(Math.sin(lat1)+Math.sin(lat2),&lt;BR /&gt; Math.sqrt( (Math.cos(lat1)+Bx)*(Math.cos(lat1)+Bx) + By*By) );&lt;BR /&gt; lon3 = lon1 + Math.atan2(By, Math.cos(lat1) + Bx);&lt;BR /&gt;&lt;BR /&gt; return new LatLon(lat3.toDeg(), lon3.toDeg());&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Returns the destination point from this point having travelled the given distance (in km) on the&lt;BR /&gt; * given initial bearing (bearing may vary before destination is reached)&lt;BR /&gt; *&lt;BR /&gt; * see http://williams.best.vwh.net/avform.htm#LL&lt;BR /&gt; *&lt;BR /&gt; * @param {Number} brng: Initial bearing in degrees&lt;BR /&gt; * @param {Number} dist: Distance in km&lt;BR /&gt; * @returns {LatLon} Destination point&lt;BR /&gt; */&lt;BR /&gt;destinationPoint = function(brng, dist) {&lt;BR /&gt; dist = typeof(dist)=='number' ? dist : typeof(dist)=='string' &amp;amp;&amp;amp; dist.trim()!='' ? +dist : NaN;&lt;BR /&gt; dist = dist/this._radius; // convert dist to angular distance in radians&lt;BR /&gt; brng = brng.toRad(); //&lt;BR /&gt; var lat1 = this._lat.toRad(), lon1 = this._lon.toRad();&lt;BR /&gt;&lt;BR /&gt; var lat2 = Math.asin( Math.sin(lat1)*Math.cos(dist) +&lt;BR /&gt; Math.cos(lat1)*Math.sin(dist)*Math.cos(brng) );&lt;BR /&gt; var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(dist)*Math.cos(lat1),&lt;BR /&gt; Math.cos(dist)-Math.sin(lat1)*Math.sin(lat2));&lt;BR /&gt; lon2 = (lon2+3*Math.PI)%(2*Math.PI) - Math.PI; // normalise to -180...+180&lt;BR /&gt;&lt;BR /&gt; return new LatLon(lat2.toDeg(), lon2.toDeg());&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Returns the point of intersection of two paths defined by point and bearing&lt;BR /&gt; *&lt;BR /&gt; * see http://williams.best.vwh.net/avform.htm#Intersection&lt;BR /&gt; *&lt;BR /&gt; * @param {LatLon} p1: First point&lt;BR /&gt; * @param {Number} brng1: Initial bearing from first point&lt;BR /&gt; * @param {LatLon} p2: Second point&lt;BR /&gt; * @param {Number} brng2: Initial bearing from second point&lt;BR /&gt; * @returns {LatLon} Destination point (null if no unique intersection defined)&lt;BR /&gt; */&lt;BR /&gt;intersection = function(p1, brng1, p2, brng2) {&lt;BR /&gt; brng1 = typeof brng1 == 'number' ? brng1 : typeof brng1 == 'string' &amp;amp;&amp;amp; trim(brng1)!='' ? +brng1 : NaN;&lt;BR /&gt; brng2 = typeof brng2 == 'number' ? brng2 : typeof brng2 == 'string' &amp;amp;&amp;amp; trim(brng2)!='' ? +brng2 : NaN;&lt;BR /&gt; lat1 = p1._lat.toRad(), lon1 = p1._lon.toRad();&lt;BR /&gt; lat2 = p2._lat.toRad(), lon2 = p2._lon.toRad();&lt;BR /&gt; brng13 = brng1.toRad(), brng23 = brng2.toRad();&lt;BR /&gt; dLat = lat2-lat1, dLon = lon2-lon1;&lt;BR /&gt;&lt;BR /&gt; dist12 = 2*Math.asin( Math.sqrt( Math.sin(dLat/2)*Math.sin(dLat/2) +&lt;BR /&gt; Math.cos(lat1)*Math.cos(lat2)*Math.sin(dLon/2)*Math.sin(dLon/2) ) );&lt;BR /&gt; if (dist12 == 0) return null;&lt;BR /&gt;&lt;BR /&gt; // initial/final bearings between points&lt;BR /&gt; brngA = Math.acos( ( Math.sin(lat2) - Math.sin(lat1)*Math.cos(dist12) ) /&lt;BR /&gt; ( Math.sin(dist12)*Math.cos(lat1) ) );&lt;BR /&gt; if (isNaN(brngA)) brngA = 0; // protect against rounding&lt;BR /&gt; brngB = Math.acos( ( Math.sin(lat1) - Math.sin(lat2)*Math.cos(dist12) ) /&lt;BR /&gt; ( Math.sin(dist12)*Math.cos(lat2) ) );&lt;BR /&gt;&lt;BR /&gt; if (Math.sin(lon2-lon1) &amp;gt; 0) {&lt;BR /&gt; brng12 = brngA;&lt;BR /&gt; brng21 = 2*Math.PI - brngB;&lt;BR /&gt; } else {&lt;BR /&gt; brng12 = 2*Math.PI - brngA;&lt;BR /&gt; brng21 = brngB;&lt;BR /&gt; }&lt;BR /&gt;&lt;BR /&gt; alpha1 = (brng13 - brng12 + Math.PI) % (2*Math.PI) - Math.PI; // angle 2-1-3&lt;BR /&gt; alpha2 = (brng21 - brng23 + Math.PI) % (2*Math.PI) - Math.PI; // angle 1-2-3&lt;BR /&gt;&lt;BR /&gt; if (Math.sin(alpha1)==0 &amp;amp;&amp;amp; Math.sin(alpha2)==0) return null; // infinite intersections&lt;BR /&gt; if (Math.sin(alpha1)*Math.sin(alpha2) &amp;lt; 0) return null; // ambiguous intersection&lt;BR /&gt;&lt;BR /&gt; //alpha1 = Math.abs(alpha1);&lt;BR /&gt; //alpha2 = Math.abs(alpha2);&lt;BR /&gt; // ... Ed Williams takes abs of alpha1/alpha2, but seems to break calculation?&lt;BR /&gt;&lt;BR /&gt; alpha3 = Math.acos( -Math.cos(alpha1)*Math.cos(alpha2) +&lt;BR /&gt; Math.sin(alpha1)*Math.sin(alpha2)*Math.cos(dist12) );&lt;BR /&gt; dist13 = Math.atan2( Math.sin(dist12)*Math.sin(alpha1)*Math.sin(alpha2),&lt;BR /&gt; Math.cos(alpha2)+Math.cos(alpha1)*Math.cos(alpha3) )&lt;BR /&gt; lat3 = Math.asin( Math.sin(lat1)*Math.cos(dist13) +&lt;BR /&gt; Math.cos(lat1)*Math.sin(dist13)*Math.cos(brng13) );&lt;BR /&gt; dLon13 = Math.atan2( Math.sin(brng13)*Math.sin(dist13)*Math.cos(lat1),&lt;BR /&gt; Math.cos(dist13)-Math.sin(lat1)*Math.sin(lat3) );&lt;BR /&gt; lon3 = lon1+dLon13;&lt;BR /&gt; lon3 = (lon3+Math.PI) % (2*Math.PI) - Math.PI; // normalise to -180..180º&lt;BR /&gt;&lt;BR /&gt; return new LatLon(lat3.toDeg(), lon3.toDeg());&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Returns the distance from this point to the supplied point, in km, travelling along a rhumb line&lt;BR /&gt; *&lt;BR /&gt; * see http://williams.best.vwh.net/avform.htm#Rhumb&lt;BR /&gt; *&lt;BR /&gt; * @param {LatLon} point: Latitude/longitude of destination point&lt;BR /&gt; * @returns {Number} Distance in km between this point and destination point&lt;BR /&gt; */&lt;BR /&gt;rhumbDistanceTo = function(point) {&lt;BR /&gt; var R = this._radius;&lt;BR /&gt; var lat1 = this._lat.toRad(), lat2 = point._lat.toRad();&lt;BR /&gt; var dLat = (point._lat-this._lat).toRad();&lt;BR /&gt; var dLon = Math.abs(point._lon-this._lon).toRad();&lt;BR /&gt;&lt;BR /&gt; var dPhi = Math.log(Math.tan(lat2/2+Math.PI/4)/Math.tan(lat1/2+Math.PI/4));&lt;BR /&gt; var q = (!isNaN(dLat/dPhi)) ? dLat/dPhi : Math.cos(lat1); // E-W line gives dPhi=0&lt;BR /&gt; // if dLon over 180° take shorter rhumb across 180° meridian:&lt;BR /&gt; if (dLon &amp;gt; Math.PI) dLon = 2*Math.PI - dLon;&lt;BR /&gt; var dist = Math.sqrt(dLat*dLat + q*q*dLon*dLon) * R;&lt;BR /&gt;&lt;BR /&gt; return dist.toPrecisionFixed(4); // 4 sig figs reflects typical 0.3% accuracy of spherical model&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Returns the bearing from this point to the supplied point along a rhumb line, in degrees&lt;BR /&gt; *&lt;BR /&gt; * @param {LatLon} point: Latitude/longitude of destination point&lt;BR /&gt; * @returns {Number} Bearing in degrees from North&lt;BR /&gt; */&lt;BR /&gt;LatLon.prototype.rhumbBearingTo = function(point) {&lt;BR /&gt; var lat1 = this._lat.toRad(), lat2 = point._lat.toRad();&lt;BR /&gt; var dLon = (point._lon-this._lon).toRad();&lt;BR /&gt;&lt;BR /&gt; var dPhi = Math.log(Math.tan(lat2/2+Math.PI/4)/Math.tan(lat1/2+Math.PI/4));&lt;BR /&gt; if (Math.abs(dLon) &amp;gt; Math.PI) dLon = dLon&amp;gt;0 ? -(2*Math.PI-dLon) : (2*Math.PI+dLon);&lt;BR /&gt; var brng = Math.atan2(dLon, dPhi);&lt;BR /&gt;&lt;BR /&gt; return (brng.toDeg()+360) % 360;&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Returns the destination point from this point having travelled the given distance (in km) on the&lt;BR /&gt; * given bearing along a rhumb line&lt;BR /&gt; *&lt;BR /&gt; * @param {Number} brng: Bearing in degrees from North&lt;BR /&gt; * @param {Number} dist: Distance in km&lt;BR /&gt; * @returns {LatLon} Destination point&lt;BR /&gt; */&lt;BR /&gt;rhumbDestinationPoint = function(brng, dist) {&lt;BR /&gt; var R = this._radius;&lt;BR /&gt; var d = parseFloat(dist)/R; // d = angular distance covered on earth's surface&lt;BR /&gt; var lat1 = this._lat.toRad(), lon1 = this._lon.toRad();&lt;BR /&gt; brng = brng.toRad();&lt;BR /&gt;&lt;BR /&gt; var lat2 = lat1 + d*Math.cos(brng);&lt;BR /&gt; var dLat = lat2-lat1;&lt;BR /&gt; var dPhi = Math.log(Math.tan(lat2/2+Math.PI/4)/Math.tan(lat1/2+Math.PI/4));&lt;BR /&gt; var q = (!isNaN(dLat/dPhi)) ? dLat/dPhi : Math.cos(lat1); // E-W line gives dPhi=0&lt;BR /&gt; var dLon = d*Math.sin(brng)/q;&lt;BR /&gt; // check for some daft bugger going past the pole&lt;BR /&gt; if (Math.abs(lat2) &amp;gt; Math.PI/2) lat2 = lat2&amp;gt;0 ? Math.PI-lat2 : -(Math.PI-lat2);&lt;BR /&gt; lon2 = (lon1+dLon+3*Math.PI)%(2*Math.PI) - Math.PI;&lt;BR /&gt;&lt;BR /&gt; return new LatLon(lat2.toDeg(), lon2.toDeg());&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Returns the latitude of this point; signed numeric degrees if no format, otherwise format &amp;amp; dp&lt;BR /&gt; * as per Geo.toLat()&lt;BR /&gt; *&lt;BR /&gt; * @param {String} [format]: Return value as 'd', 'dm', 'dms'&lt;BR /&gt; * @param {Number} [dp=0|2|4]: No of decimal places to display&lt;BR /&gt; * @returns {Number|String} Numeric degrees if no format specified, otherwise deg/min/sec&lt;BR /&gt; *&lt;BR /&gt; * @requires Geo&lt;BR /&gt; */&lt;BR /&gt;lat = function(format, dp) {&lt;BR /&gt; if (typeof format == 'undefined') return this._lat;&lt;BR /&gt;&lt;BR /&gt; return Geo.toLat(this._lat, format, dp);&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Returns the longitude of this point; signed numeric degrees if no format, otherwise format &amp;amp; dp&lt;BR /&gt; * as per Geo.toLon()&lt;BR /&gt; *&lt;BR /&gt; * @param {String} [format]: Return value as 'd', 'dm', 'dms'&lt;BR /&gt; * @param {Number} [dp=0|2|4]: No of decimal places to display&lt;BR /&gt; * @returns {Number|String} Numeric degrees if no format specified, otherwise deg/min/sec&lt;BR /&gt; *&lt;BR /&gt; * @requires Geo&lt;BR /&gt; */&lt;BR /&gt;lon = function(format, dp) {&lt;BR /&gt; if (typeof format == 'undefined') return this._lon;&lt;BR /&gt;&lt;BR /&gt; return Geo.toLon(this._lon, format, dp);&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Returns a string representation of this point; format and dp as per lat()/lon()&lt;BR /&gt; *&lt;BR /&gt; * @param {String} [format]: Return value as 'd', 'dm', 'dms'&lt;BR /&gt; * @param {Number} [dp=0|2|4]: No of decimal places to display&lt;BR /&gt; * @returns {String} Comma-separated latitude/longitude&lt;BR /&gt; *&lt;BR /&gt; * @requires Geo&lt;BR /&gt; */&lt;BR /&gt;toString = function(format, dp) {&lt;BR /&gt; if (typeof format == 'undefined') format = 'dms';&lt;BR /&gt;&lt;BR /&gt; if (isNaN(this._lat) || isNaN(this._lon)) return '-,-';&lt;BR /&gt;&lt;BR /&gt; return Geo.toLat(this._lat, format, dp) + ', ' + Geo.toLon(this._lon, format, dp);&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */&lt;BR /&gt;&lt;BR /&gt;// ---- extend Number object with methods for converting degrees/radians&lt;BR /&gt;&lt;BR /&gt;/** Converts numeric degrees to radians */&lt;BR /&gt;if (typeof(Number.prototype.toRad) === "undefined") {&lt;BR /&gt; Number.prototype.toRad = function() {&lt;BR /&gt; return this * Math.PI / 180;&lt;BR /&gt; }&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/** Converts radians to numeric (signed) degrees */&lt;BR /&gt;if (typeof(Number.prototype.toDeg) === "undefined") {&lt;BR /&gt; Number.prototype.toDeg = function() {&lt;BR /&gt; return this * 180 / Math.PI;&lt;BR /&gt; }&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Formats the significant digits of a number, using only fixed-point notation (no exponential)&lt;BR /&gt; *&lt;BR /&gt; * @param {Number} precision: Number of significant digits to appear in the returned string&lt;BR /&gt; * @returns {String} A string representation of number which contains precision significant digits&lt;BR /&gt; */&lt;BR /&gt;if (typeof(Number.prototype.toPrecisionFixed) === "undefined") {&lt;BR /&gt; Number.prototype.toPrecisionFixed = function(precision) {&lt;BR /&gt; if (isNaN(this)) return 'NaN';&lt;BR /&gt; var numb = this &amp;lt; 0 ? -this : this; // can't take log of -ve number...&lt;BR /&gt; var sign = this &amp;lt; 0 ? '-' : '';&lt;BR /&gt;&lt;BR /&gt; if (numb == 0) { n = '0.'; while (precision--) n += '0'; return n }; // can't take log of zero&lt;BR /&gt;&lt;BR /&gt; var scale = Math.ceil(Math.log(numb)*Math.LOG10E); // no of digits before decimal&lt;BR /&gt; var n = String(Math.round(numb * Math.pow(10, precision-scale)));&lt;BR /&gt; if (scale &amp;gt; 0) { // add trailing zeros &amp;amp; insert decimal as required&lt;BR /&gt; l = scale - n.length;&lt;BR /&gt; while (l-- &amp;gt; 0) n = n + '0';&lt;BR /&gt; if (scale &amp;lt; n.length) n = n.slice(0,scale) + '.' + n.slice(scale);&lt;BR /&gt; } else { // prefix decimal and leading zeros if required&lt;BR /&gt; while (scale++ &amp;lt; 0) n = '0' + n;&lt;BR /&gt; n = '0.' + n;&lt;BR /&gt; }&lt;BR /&gt; return sign + n;&lt;BR /&gt; }&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/** Trims whitespace from string (q.v. blog.stevenlevithan.com/archives/faster-trim-javascript) */&lt;BR /&gt;if (typeof(String.prototype.trim) === "undefined") {&lt;BR /&gt; String.prototype.trim = function() {&lt;BR /&gt; return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, '');&lt;BR /&gt; }&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */&lt;BR /&gt;/* Geodesy representation conversion functions (c) Chris Veness 2002-2010 */&lt;BR /&gt;/* - www.movable-type.co.uk/scripts/latlong.html */&lt;BR /&gt;/* */&lt;BR /&gt;/* Sample usage: */&lt;BR /&gt;/* var lat = Geo.parseDMS('51° 28′ 40.12″ N'); */&lt;BR /&gt;/* var lon = Geo.parseDMS('000° 00′ 05.31″ W'); */&lt;BR /&gt;/* var p1 = new LatLon(lat, lon); */&lt;BR /&gt;/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */&lt;BR /&gt;&lt;BR /&gt;var Geo = {}; // Geo namespace, representing static class&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Parses string representing degrees/minutes/seconds into numeric degrees&lt;BR /&gt; *&lt;BR /&gt; * This is very flexible on formats, allowing signed decimal degrees, or deg-min-sec optionally&lt;BR /&gt; * suffixed by compass direction (NSEW). A variety of separators are accepted (eg 3º 37' 09"W)&lt;BR /&gt; * or fixed-width format without separators (eg 0033709W). Seconds and minutes may be omitted.&lt;BR /&gt; * (Note minimal validation is done).&lt;BR /&gt; *&lt;BR /&gt; * @param {String|Number} dmsStr: Degrees or deg/min/sec in variety of formats&lt;BR /&gt; * @returns {Number} Degrees as decimal number&lt;BR /&gt; * @throws {TypeError} dmsStr is an object, perhaps DOM object without .value?&lt;BR /&gt; */&lt;BR /&gt;parseDMS = function(dmsStr) {&lt;BR /&gt; if (typeof deg == 'object') throw new TypeError('Geo.parseDMS - dmsStr is [DOM?] object');&lt;BR /&gt;&lt;BR /&gt; // check for signed decimal degrees without NSEW, if so return it directly&lt;BR /&gt; if (typeof dmsStr === 'number' &amp;amp;&amp;amp; isFinite(dmsStr)) return Number(dmsStr);&lt;BR /&gt;&lt;BR /&gt; // strip off any sign or compass dir'n &amp;amp; split out separate d/m/s&lt;BR /&gt; var dms = String(dmsStr).trim().replace(/^-/,'').replace(/[NSEW]$/i,'').split(/[^0-9.,]+/);&lt;BR /&gt; if (dms[dms.length-1]=='') dms.splice(dms.length-1); // from trailing symbol&lt;BR /&gt;&lt;BR /&gt; if (dms == '') return NaN;&lt;BR /&gt;&lt;BR /&gt; // and convert to decimal degrees...&lt;BR /&gt; switch (dms.length) {&lt;BR /&gt; case 3: // interpret 3-part result as d/m/s&lt;BR /&gt; var deg = dms[0]/1 + dms[1]/60 + dms[2]/3600;&lt;BR /&gt; break;&lt;BR /&gt; case 2: // interpret 2-part result as d/m&lt;BR /&gt; var deg = dms[0]/1 + dms[1]/60;&lt;BR /&gt; break;&lt;BR /&gt; case 1: // just d (possibly decimal) or non-separated dddmmss&lt;BR /&gt; var deg = dms[0];&lt;BR /&gt; // check for fixed-width unseparated format eg 0033709W&lt;BR /&gt; if (/[NS]/i.test(dmsStr)) deg = '0' + deg; // - normalise N/S to 3-digit degrees&lt;BR /&gt; if (/[0-9]{7}/.test(deg)) deg = deg.slice(0,3)/1 + deg.slice(3,5)/60 + deg.slice(5)/3600;&lt;BR /&gt; break;&lt;BR /&gt; default:&lt;BR /&gt; return NaN;&lt;BR /&gt; }&lt;BR /&gt; if (/^-|[WS]$/i.test(dmsStr.trim())) deg = -deg; // take '-', west and south as -ve&lt;BR /&gt; return Number(deg);&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Convert decimal degrees to deg/min/sec format&lt;BR /&gt; * - degree, prime, double-prime symbols are added, but sign is discarded, though no compass&lt;BR /&gt; * direction is added&lt;BR /&gt; *&lt;BR /&gt; * @private&lt;BR /&gt; * @param {Number} deg: Degrees&lt;BR /&gt; * @param {String} [format=dms]: Return value as 'd', 'dm', 'dms'&lt;BR /&gt; * @param {Number} [dp=0|2|4]: No of decimal places to use - default 0 for dms, 2 for dm, 4 for d&lt;BR /&gt; * @returns {String} deg formatted as deg/min/secs according to specified format&lt;BR /&gt; * @throws {TypeError} deg is an object, perhaps DOM object without .value?&lt;BR /&gt; */&lt;BR /&gt;toDMS = function(deg, format, dp) {&lt;BR /&gt; if (typeof deg == 'object') throw new TypeError('Geo.toDMS - deg is [DOM?] object');&lt;BR /&gt; if (isNaN(deg)) return 'NaN'; // give up here if we can't make a number from deg&lt;BR /&gt;&lt;BR /&gt; // default values&lt;BR /&gt; if (typeof format == 'undefined') format = 'dms';&lt;BR /&gt; if (typeof dp == 'undefined') {&lt;BR /&gt; switch (format) {&lt;BR /&gt; case 'd': dp = 4; break;&lt;BR /&gt; case 'dm': dp = 2; break;&lt;BR /&gt; case 'dms': dp = 0; break;&lt;BR /&gt; default: format = 'dms'; dp = 0; // be forgiving on invalid format&lt;BR /&gt; }&lt;BR /&gt; }&lt;BR /&gt;&lt;BR /&gt; deg = Math.abs(deg); // (unsigned result ready for appending compass dir'n)&lt;BR /&gt;&lt;BR /&gt; switch (format) {&lt;BR /&gt; case 'd':&lt;BR /&gt; d = deg.toFixed(dp); // round degrees&lt;BR /&gt; if (d&amp;lt;100) d = '0' + d; // pad with leading zeros&lt;BR /&gt; if (d&amp;lt;10) d = '0' + d;&lt;BR /&gt; dms = d + '\u00B0'; // add º symbol&lt;BR /&gt; break;&lt;BR /&gt; case 'dm':&lt;BR /&gt; var min = (deg*60).toFixed(dp); // convert degrees to minutes &amp;amp; round&lt;BR /&gt; var d = Math.floor(min / 60); // get component deg/min&lt;BR /&gt; var m = (min % 60).toFixed(dp); // pad with trailing zeros&lt;BR /&gt; if (d&amp;lt;100) d = '0' + d; // pad with leading zeros&lt;BR /&gt; if (d&amp;lt;10) d = '0' + d;&lt;BR /&gt; if (m&amp;lt;10) m = '0' + m;&lt;BR /&gt; dms = d + '\u00B0' + m + '\u2032'; // add º, ' symbols&lt;BR /&gt; break;&lt;BR /&gt; case 'dms':&lt;BR /&gt; var sec = (deg*3600).toFixed(dp); // convert degrees to seconds &amp;amp; round&lt;BR /&gt; var d = Math.floor(sec / 3600); // get component deg/min/sec&lt;BR /&gt; var m = Math.floor(sec/60) % 60;&lt;BR /&gt; var s = (sec % 60).toFixed(dp); // pad with trailing zeros&lt;BR /&gt; if (d&amp;lt;100) d = '0' + d; // pad with leading zeros&lt;BR /&gt; if (d&amp;lt;10) d = '0' + d;&lt;BR /&gt; if (m&amp;lt;10) m = '0' + m;&lt;BR /&gt; if (s&amp;lt;10) s = '0' + s;&lt;BR /&gt; dms = d + '\u00B0' + m + '\u2032' + s + '\u2033'; // add º, ', " symbols&lt;BR /&gt; break;&lt;BR /&gt; }&lt;BR /&gt;&lt;BR /&gt; return dms;&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Convert numeric degrees to deg/min/sec latitude (suffixed with N/S)&lt;BR /&gt; *&lt;BR /&gt; * @param {Number} deg: Degrees&lt;BR /&gt; * @param {String} [format=dms]: Return value as 'd', 'dm', 'dms'&lt;BR /&gt; * @param {Number} [dp=0|2|4]: No of decimal places to use - default 0 for dms, 2 for dm, 4 for d&lt;BR /&gt; * @returns {String} Deg/min/seconds&lt;BR /&gt; */&lt;BR /&gt;toLat = function(deg, format, dp) {&lt;BR /&gt; var lat = Geo.toDMS(deg, format, dp);&lt;BR /&gt; return lat=='' ? '' : lat.slice(1) + (deg&amp;lt;0 ? 'S' : 'N'); // knock off initial '0' for lat!&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Convert numeric degrees to deg/min/sec longitude (suffixed with E/W)&lt;BR /&gt; *&lt;BR /&gt; * @param {Number} deg: Degrees&lt;BR /&gt; * @param {String} [format=dms]: Return value as 'd', 'dm', 'dms'&lt;BR /&gt; * @param {Number} [dp=0|2|4]: No of decimal places to use - default 0 for dms, 2 for dm, 4 for d&lt;BR /&gt; * @returns {String} Deg/min/seconds&lt;BR /&gt; */&lt;BR /&gt;toLon = function(deg, format, dp) {&lt;BR /&gt; var lon = Geo.toDMS(deg, format, dp);&lt;BR /&gt; return lon=='' ? '' : lon + (deg&amp;lt;0 ? 'W' : 'E');&lt;BR /&gt;}&lt;BR /&gt;&lt;BR /&gt;/**&lt;BR /&gt; * Convert numeric degrees to deg/min/sec as a bearing (0º..360º)&lt;BR /&gt; *&lt;BR /&gt; * @param {Number} deg: Degrees&lt;BR /&gt; * @param {String} [format=dms]: Return value as 'd', 'dm', 'dms'&lt;BR /&gt; * @param {Number} [dp=0|2|4]: No of decimal places to use - default 0 for dms, 2 for dm, 4 for d&lt;BR /&gt; * @returns {String} Deg/min/seconds&lt;BR /&gt; */&lt;BR /&gt;toBrng = function(deg, format, dp) {&lt;BR /&gt; deg = (Number(deg)+360) % 360; // normalise -ve values to 180º..360º&lt;BR /&gt; var brng = Geo.toDMS(deg, format, dp);&lt;BR /&gt; return brng.replace('360', '0'); // just in case rounding took us up to 360º!&lt;BR /&gt;}&lt;BR /&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;BR /&gt;&lt;BR /&gt; &lt;P&gt;&lt;/P&gt;&lt;P&gt;Load some example data:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;BLOCKQUOTE style="overflow-x: scroll;"&gt;&lt;PRE style="margin: 0px;"&gt;&lt;BR /&gt;GEO:&lt;BR /&gt;LOAD * INLINE [&lt;BR /&gt; ROUTE, LAT_1, LONG_1, LAT_2, LONG_2&lt;BR /&gt; R1, 53 09 02N, 001 50 40W, 52 12 19N, 000 08 33W&lt;BR /&gt;];&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;DIST:&lt;BR /&gt;LOAD&lt;BR /&gt; *,&lt;BR /&gt; distVincenty(parseDMS(LAT_1), parseDMS(LONG_1), parseDMS(LAT_2), parseDMS(LONG_2)) as DIST&lt;BR /&gt;resident GEO;&lt;BR /&gt;&lt;BR /&gt;drop table GEO;&lt;BR /&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;BR /&gt;&lt;BR /&gt; &lt;P&gt;-Alex&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Wed, 09 Mar 2011 10:19:08 GMT</pubDate>
      <guid>https://community.qlik.com/t5/QlikView/WGS84-Compliant-Great-Circle-Distance-Calculation/m-p/241906#M92298</guid>
      <dc:creator />
      <dc:date>2011-03-09T10:19:08Z</dc:date>
    </item>
    <item>
      <title>WGS84 Compliant Great Circle Distance Calculation</title>
      <link>https://community.qlik.com/t5/QlikView/WGS84-Compliant-Great-Circle-Distance-Calculation/m-p/241907#M92299</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;See file from my profile: http://community.qlik.com/members/alxtoth/files/Attached+Files/geo.qvw.aspx&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;-Alex&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Wed, 09 Mar 2011 10:34:28 GMT</pubDate>
      <guid>https://community.qlik.com/t5/QlikView/WGS84-Compliant-Great-Circle-Distance-Calculation/m-p/241907#M92299</guid>
      <dc:creator />
      <dc:date>2011-03-09T10:34:28Z</dc:date>
    </item>
    <item>
      <title>WGS84 Compliant Great Circle Distance Calculation</title>
      <link>https://community.qlik.com/t5/QlikView/WGS84-Compliant-Great-Circle-Distance-Calculation/m-p/241908#M92300</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Excellent ... many thanks ... now all I need to do is figure out how to use Java script stuff! &lt;span class="lia-unicode-emoji" title=":face_with_open_mouth:"&gt;😮&lt;/span&gt;&lt;/P&gt;&lt;P&gt;Keep watching this space ...&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Cheers,&lt;/P&gt;&lt;P&gt;Emma&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Wed, 09 Mar 2011 11:27:02 GMT</pubDate>
      <guid>https://community.qlik.com/t5/QlikView/WGS84-Compliant-Great-Circle-Distance-Calculation/m-p/241908#M92300</guid>
      <dc:creator />
      <dc:date>2011-03-09T11:27:02Z</dc:date>
    </item>
    <item>
      <title>WGS84 Compliant Great Circle Distance Calculation</title>
      <link>https://community.qlik.com/t5/QlikView/WGS84-Compliant-Great-Circle-Distance-Calculation/m-p/241909#M92301</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Awsome! Many thanks - I've got it working &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;&lt;P&gt;Now, all I need to do is get approval from the verifier and you'll have made us WGS84 compliant - as everyone should be of course! Thank you so much!!&lt;/P&gt;&lt;P&gt;&lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;&lt;P&gt;Emma&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Wed, 09 Mar 2011 12:42:52 GMT</pubDate>
      <guid>https://community.qlik.com/t5/QlikView/WGS84-Compliant-Great-Circle-Distance-Calculation/m-p/241909#M92301</guid>
      <dc:creator />
      <dc:date>2011-03-09T12:42:52Z</dc:date>
    </item>
    <item>
      <title>WGS84 Compliant Great Circle Distance Calculation</title>
      <link>https://community.qlik.com/t5/QlikView/WGS84-Compliant-Great-Circle-Distance-Calculation/m-p/241910#M92302</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Hi Alex,&lt;/P&gt;&lt;P&gt;Many thanks again for the script and instructions, I had a small (well ... quite large) panic yesterday when I compared the results I got using this to the results I had using the Haversine (spherical model) formula. Luckily, after a bit of investigation I found that all it was, was that the Lat and Long format in my file has the NSEW indicator at the front not the end so although the formula will still run (and give valid results on N and E coordinates which was confusing) it didn't seem to spot the indicator and do anything with it for the S and W directions.&lt;/P&gt;&lt;P&gt;I'm just really putting this on here for completeness in case anyone else uses the script ...&lt;/P&gt;&lt;P&gt;I have found someone here with more knowledge of Javascipt than me (not difficult!!) and there is one line of code we've amended to give a little more flexibility and allow for either a leading or trailing compass letter:&lt;/P&gt;&lt;P&gt;if (/^-|[WS]$/i.test(dmsStr.trim())) deg = -deg; // take '-', west and south as -ve&lt;/P&gt;&lt;P&gt;we have changed to&lt;/P&gt;&lt;P&gt;if (/^-|[WS]|[WS]$/i.test(dmsStr.trim())) deg = -deg; // take '-', west and south as -ve&lt;/P&gt;&lt;P&gt;A small change but means that I can plug it straight into our data without needing to convert to degrees first or try and move the compass letter from the beginning to the end of the coordinates!&lt;/P&gt;&lt;P&gt;Many thanks once again.&lt;/P&gt;&lt;P&gt;Cheers,&lt;/P&gt;&lt;P&gt;Emma&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Thu, 10 Mar 2011 11:20:13 GMT</pubDate>
      <guid>https://community.qlik.com/t5/QlikView/WGS84-Compliant-Great-Circle-Distance-Calculation/m-p/241910#M92302</guid>
      <dc:creator />
      <dc:date>2011-03-10T11:20:13Z</dc:date>
    </item>
  </channel>
</rss>

