This page shows the javascript code of the page Distances on Globe and Flat Earth, so you can inspect it for correctness.
#INCLUDE ControlPanel.inc <jscript> Model = { // latitude and longitude input values lat1: 0, lat1min: 0, lat1sec: 0, lng1: 0, lng1min: 0, lng1sec: 0, lat2: 0, lat2min: 0, lat2sec: 0, lng2: 0, lng2min: 0, lng2sec: 0, // planet sizes R: 6371, // km EQ: 6371 * Math.PI / 2, // computed distances LG: 0, LF: 0, // choosen units tables l_unitId: 0, // 0 -> km, 1 -> nmi, 2 -> mi l_unitNameList: [ 'km', 'nmi', 'mi' ], l_unitName: 'km', l_multList: [ 1, 1.852, 1.609344 ], l_mult: 1000, l_digitsList: [ 2, 2, 2 ], l_digits: 2, ParseInput: function( inp ) { var neg = (inp.indexOf('S') >= 0 || inp.indexOf('s') >= 0 || inp.indexOf('W') >= 0 || inp.indexOf('w') >= 0) ? -1 : 1; // remove all not numeric characters inp = inp.replace( /,/g, '.' ).replace( /[^0-9\-\.]/g, ' ' ); // trim inp = inp.replace( / +/g, ' ' ).replace( /^ /, '' ).replace( / $/, '' ); if (inp.indexOf( '-' ) == 0) { neg = -1; inp = inp.replace( /-/g, '' ); } if (inp == '') return 0; var parts = inp.split( ' ' ); var res = 0; var fract = 1; for (var i = 0; i < parts.length; i++) { res += parseFloat( parts[i] ) / fract; fract *= 60; } return neg * res; }, ToDMS: function() { // convert lat/lng from degrees to degrees, minutes and seconds function dms(x) { var d = Math.abs( x ); var s = x < 0 ? -1 : 1; var r = { d: 0, m: 0, s: 0 }; r.d = Math.floor( d ); d = (d % 1) * 60; r.m = Math.floor( d ); r.s = (d % 1) * 60; // check if any seconds or minutes are displayed as 60 if (r.s >= 59.9995) { r.s = 0; r.m += 1; if (r.m >= 60) { r.m = 0; r.d += 1; } } if (s < 0) { if (r.d > 0) { r.d *= -1; } else if (r.m > 0) { r.m *= -1; } else { r.s *= -1; } } return r; }; var s = dms( this.lat1 ); this.lat1 = s.d; this.lat1min = s.m; this.lat1sec = s.s; var s = dms( this.lng1 ); this.lng1 = s.d; this.lng1min = s.m; this.lng1sec = s.s; var s = dms( this.lat2 ); this.lat2 = s.d; this.lat2min = s.m; this.lat2sec = s.s; var s = dms( this.lng2 ); this.lng2 = s.d; this.lng2min = s.m; this.lng2sec = s.s; }, ToDeg: function() { // convert lat/lng from degrees, minutes and seconds to degrees var abs = Math.abs; var s = this.lat1 < 0 ? -1 : (this.lat1min < 0 ? -1 : (this.lat1sec < 0 ? -1 : 1 )); this.lat1 = s * (abs(this.lat1) + (abs(this.lat1min) + (abs(this.lat1sec) / 60)) / 60); this.lat1min = 0; this.lat1sec = 0; var s = this.lng1 < 0 ? -1 : (this.lng1min < 0 ? -1 : (this.lng1sec < 0 ? -1 : 1 )); this.lng1 = s * (abs(this.lng1) + (abs(this.lng1min) + (abs(this.lng1sec) / 60)) / 60); this.lng1min = 0; this.lng1sec = 0; var s = this.lat2 < 0 ? -1 : (this.lat2min < 0 ? -1 : (this.lat2sec < 0 ? -1 : 1 )); this.lat2 = s * (abs(this.lat2) + (abs(this.lat2min) + (abs(this.lat2sec) / 60)) / 60); this.lat2min = 0; this.lat2sec = 0; var s = this.lng2 < 0 ? -1 : (this.lng2min < 0 ? -1 : (this.lng2sec < 0 ? -1 : 1 )); this.lng2 = s * (abs(this.lng2) + (abs(this.lng2min) + (abs(this.lng2sec) / 60)) / 60); this.lng2min = 0; this.lng2sec = 0; }, Update: function() { // checks input and updates all computed values this.l_mult = this.l_multList[this.l_unitId]; this.l_digits = this.l_digitsList[this.l_unitId]; this.l_unitName = this.l_unitNameList[this.l_unitId]; // get latitudes and longitudes as degrees var cos = Math.cos, sin = Math.sin, abs = Math.abs, DegToRad = Math.PI / 180; var sign = this.lat1 < 0 ? -1 : 1; if (this.lat1 == 0) sign = this.lat1min < 0 ? -1 : 1; if (this.lat1 == 0 && this.lat1min == 0) sign = this.lat1sec < 0 ? -1 : 1; var lat1 = DegToRad * sign * (abs(this.lat1) + abs(this.lat1min) / 60 + abs(this.lat1sec) / 3600); var sign = this.lng1 < 0 ? -1 : 1; if (this.lng1 == 0) sign = this.lng1min < 0 ? -1 : 1; if (this.lng1 == 0 && this.lng1min == 0) sign = this.lng1sec < 0 ? -1 : 1; var lng1 = DegToRad * sign * (abs(this.lng1) + abs(this.lng1min) / 60 + abs(this.lng1sec) / 3600); var sign = this.lat2 < 0 ? -1 : 1; if (this.lat2 == 0) sign = this.lat2min < 0 ? -1 : 1; if (this.lat2 == 0 && this.lat2min == 0) sign = this.lat2sec < 0 ? -1 : 1; var lat2 = DegToRad * sign * (abs(this.lat2) + abs(this.lat2min) / 60 + abs(this.lat2sec) / 3600); var sign = this.lng2 < 0 ? -1 : 1; if (this.lng2 == 0) sign = this.lng2min < 0 ? -1 : 1; if (this.lng2 == 0 && this.lng2min == 0) sign = this.lng2sec < 0 ? -1 : 1; var lng2 = DegToRad * sign * (abs(this.lng2) + abs(this.lng2min) / 60 + abs(this.lng2sec) / 3600); // compute distance on globe var r = cos( lat1 ); var v1x = cos( lng1 ) * r; var v1y = sin( lng1 ) * r; var v1z = sin( lat1 ); var r = cos( lat2 ); var v2x = cos( lng2 ) * r; var v2y = sin( lng2 ) * r; var v2z = sin( lat2 ); var alpha = Math.acos( v1x * v2x + v1y * v2y + v1z * v2z ); // 0..pi this.LG = this.R * alpha; // // compute distance on flat earth var pi2 = Math.PI / 2; var r1 = (1 - lat1/pi2) * this.EQ; var r2 = (1 - lat2/pi2) * this.EQ; var x1 = r1 * cos( lng1 ); var y1 = r1 * sin( lng1 ); var x2 = r2 * cos( lng2 ); var y2 = r2 * sin( lng2 ); var dx = x2 - x1; var dy = y2 - y1; this.LF = Math.sqrt( dx*dx + dy*dy ); } }; function UpdateAll() { // will be called from ControlPanels when any input field is changed Model.Update(); ControlPanels.Update(); } // functions called from the buttons in the title bar of the input panel function Reset() { ControlPanels.Reset(); UpdateAll(); } function ToDMS() { Model.ToDMS(); UpdateAll(); } function ToDeg() { Model.ToDeg(); UpdateAll(); } // functions called from the big buttons with departure and target function PerthSydney() { Model.lat1 = -31; Model.lat1min = 57; Model.lat1sec = 1.8972; Model.lng1 = 115; Model.lng1min = 51; Model.lng1sec = 37.6452; Model.lat2 = -33; Model.lat2min = 52; Model.lat2sec = 7.752; Model.lng2 = 151; Model.lng2min = 12; Model.lng2sec = 33.4656; UpdateAll(); } function JohannesburgPerth() { Model.lat1 = -26; Model.lat1min = 12; Model.lat1sec = 14.7708; Model.lng1 = 28; Model.lng1min = 2; Model.lng1sec = 50.298; Model.lat2 = -31; Model.lat2min = 57; Model.lat2sec = 1.8972; Model.lng2 = 115; Model.lng2min = 51; Model.lng2sec = 37.6452; UpdateAll(); } function LondonMoskau() { Model.lat1 = 51; Model.lat1min = 30; Model.lat1sec = 26.4636; Model.lng1 = 0; Model.lng1min = -7; Model.lng1sec = 39.9288; Model.lat2 = 55; Model.lat2min = 45; Model.lat2sec = 20.9736; Model.lng2 = 37; Model.lng2min = 37; Model.lng2sec = 2.28; UpdateAll(); } xOnLoad( UpdateAll ); </jscript> {{scroll}} <jscript> // create Control Panels ControlPanels.NewPanel( { ModelRef: 'Model', OnModelChange: UpdateAll, NCols: 6, Digits: 3, PanelFormat: 'LabelLeft', } ).AddHeader( { Text: '', ColSpan: 1 } ).AddHeader( { Text: 'Latitude', ColSpan: 5 } ).AddHeader( { Text: 'Longitude' + ControlPanels.ResetButtonR() + ControlPanels.SmallButtonR('→Deg','ToDeg()') + ControlPanels.SmallButtonR('→DMS','ToDMS()'), ColSpan: 6 } ).AddTextField( { Name: 'lat1', Label: 'P1', Units: '°', Digits: 6, ConvToModelFunc: function(s) { return Model.ParseInput( s ); }, } ).AddTextField( { Name: 'lat1min', Label: '-', Units: 'min', ColSpan: 2, } ).AddTextField( { Name: 'lat1sec', Label: '-', Units: 'sec', ColSpan: 2, } ).AddTextField( { Name: 'lng1', Label: '', Units: '°', ColSpan: 2, Digits: 6, ConvToModelFunc: function(s) { return Model.ParseInput( s ); }, } ).AddTextField( { Name: 'lng1min', Label: '-', Units: 'min', ColSpan: 2, } ).AddTextField( { Name: 'lng1sec', Label: '-', Units: 'sec', ColSpan: 2, } ).AddTextField( { Name: 'lat2', Label: 'P2', Units: '°', Digits: 6, ConvToModelFunc: function(s) { return Model.ParseInput( s ); }, } ).AddTextField( { Name: 'lat2min', Label: '-', Units: 'min', ColSpan: 2, } ).AddTextField( { Name: 'lat2sec', Label: '-', Units: 'sec', ColSpan: 2, } ).AddTextField( { Name: 'lng2', Units: '°', ColSpan: 2, Digits: 6, ConvToModelFunc: function(s) { return Model.ParseInput( s ); }, } ).AddTextField( { Name: 'lng2min', Label: '-', Units: 'min', ColSpan: 2, } ).AddTextField( { Name: 'lng2sec', Label: '-', Units: 'sec', ColSpan: 2, } ).Render(); </jscript> {{end scroll}} {{scroll}} <jscript> ControlPanels.NewPanel( { ModelRef: 'Model', OnModelChange: UpdateAll, NCols: 2, ReadOnly: true, Digits: 6, } ).AddHeader().AddHeader( { Text: 'Computed Distances from P1 to P2', } ).AddHeader().AddHeader( { Text: 'Planet Sizes used for Calculation', } ).AddTextField( { Name: 'LG', Label: 'Globe', MultRef: 'l_mult', UnitsRef: 'l_unitName' } ).AddTextField( { Name: 'R', Label: 'RadiusGlobe', Units: 'km', ReadOnly: false, MultRef: 'l_mult', UnitsRef: 'l_unitName' } ).AddTextField( { Name: 'LF', Label: 'Flat Earth', MultRef: 'l_mult', UnitsRef: 'l_unitName' } ).AddTextField( { Name: 'EQ', Label: 'FE-PoleEquator', ReadOnly: false, MultRef: 'l_mult', UnitsRef: 'l_unitName' } ).AddRadiobuttonField( { Name: 'l_unitId', Label: 'Units', ValueType: 'int', ColSpan: 3, Items: [ { Name: 'km', Value: 0 }, { Name: 'nmi (nautical miles)', Value: 1 }, { Name: 'mi (statute miles)', Value: 2 } ] } ).Render(); </jscript> [javascript:PerthSydney()|{{span|Perth-Sydney|$lbtn}}] [javascript:JohannesburgPerth()|{{span|Johannesburg-Perth|$lbtn}}] [javascript:LondonMoskau()|{{span|London-Moskau|$lbtn}}]