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}}]