var imageSet = false; var calibrationDone = false; var calibrationData = { x1: null, y1: null, lat1: null, lon1: null, x2: null, y2: null, lat2: null, lon2: null}; getImage = function() { try { g('image').src = g('imageURL').value; if(!imageSet) { g('image').style.borderWidth = "1px"; g('image').style.borderStyle = "solid"; g('image').style.borderColor = "#000000"; g('divCalibrate').style.display = "block"; imageStyleSet = true; } } catch(e) { alert("An exception occurred in the script.\nError name: " + e.name + ".\nError description: " + e.description + ".\nError number: " + e.number+ ".\nError message: " + e.message); } return false; } imageLoaded = function() { try { var size = document.getElementSize(g('image')); //var pos = document.getElementPosition(g('image')); //alert(size.w+','+size.h); //alert(pos.x +','+pos.y); g('divCalibrate').style.top = size.h + 20 + 'px'; g('divTC').style.top = size.h + 20 + 'px'; g('divRef').style.top = size.h + 20 + 'px'; g('divCalcResult').style.top = size.h + 20 + 'px'; return true; } catch(e) { alert("An exception occurred in the script.\nError name: " + e.name + ".\nError description: " + e.description + ".\nError number: " + e.number+ ".\nError message: " + e.message); } return false; } choosePlace = function() { try { g('divXY4').style.display = "none"; g('divLaLo4').style.display = "block"; g('imageLat4').value = null; g('imageLon4').value = null; } catch(e) { alert("An exception occurred in the script.\nError name: " + e.name + ".\nError description: " + e.description + ".\nError number: " + e.number+ ".\nError message: " + e.message); } return false; } chooseHK = function() { try { g('divXY4').style.display = "none"; g('divLaLo4').style.display = "block"; g('imageLat4').value = 22.3; g('imageLon4').value = 114.17; } catch(e) { alert("An exception occurred in the script.\nError name: " + e.name + ".\nError description: " + e.description + ".\nError number: " + e.number+ ".\nError message: " + e.message); } return false; } getImageXY = function(n) { try { g('divXY'+n).style.display = "block"; g('divLaLo'+n).style.display = "none"; var postClickHandler = null; var oldX = g('imageX'+n).value; var oldY = g('imageY'+n).value; var moveMouse = function (e) { var mousePos = document.getMousePos(e); var imagePos = document.getElementPosition(g('image')); g('imageX'+n).value = mousePos.x - imagePos.x; g('imageY'+n).value = mousePos.y - imagePos.y; document.body.style.cursor = 'crosshair'; } var mouseClick = function (e) { stopCalibration(); postClickHandler(n); } var keyDown = function (e) { if(!e) e = window.event; var k = e.keyCode; if(k == 27) { //Esc stopCalibration(); g('imageX'+n).value = oldX; g('imageY'+n).value = oldY; } } var stopCalibration = function () { unhookevent(document, 'mousemove', moveMouse); unhookevent(document, 'keydown', keyDown); unhookevent(document, 'click', mouseClick); document.body.style.cursor = ''; g('divLaLo'+n).style.display = "block"; } var finishCalibration = function(n) { g('imageLat'+n).focus(); g('imageLat'+n).select(); } postClickHandler = finishCalibration; if(getImageXY.arguments.length > 1 && typeof getImageXY.arguments[1] == 'function') postClickHandler = getImageXY.arguments[1]; hookevent(document, 'mousemove', moveMouse); hookevent(document, 'keydown', keyDown); setTimeout(function(){hookevent(document, 'click', mouseClick);}, 0); } catch(e) { try { unhookevent(document, 'mousemove', moveMouse); } catch(e) {} try { unhookevent(document, 'keydown', keyDown); } catch(e) {} try { unhookevent(document, 'click', mouseClick); } catch(e) {} alert("An exception occurred in the script.\nError name: " + e.name + ".\nError description: " + e.description + ".\nError number: " + e.number+ ".\nError message: " + e.message); } } calibrationFinish = function() { try { calibrationDone = true; var errmsg = ''; if(!isNaN(g('imageX1').value) || (calibrationDone = false)) { calibrationData.x1 = Number(g('imageX1').value); } if(!isNaN(g('imageY1').value) || (calibrationDone = false)) { calibrationData.y1 = Number(g('imageY1').value); } if(!isNaN(g('imageLat1').value) || (calibrationDone = false)) { calibrationData.lat1 = Number(g('imageLat1').value); } if(!isNaN(g('imageLon1').value) || (calibrationDone = false)) { calibrationData.lon1 = Number(g('imageLon1').value); } if(!isNaN(g('imageX2').value) || (calibrationDone = false)) { calibrationData.x2 = Number(g('imageX2').value); } if(!isNaN(g('imageY2').value) || (calibrationDone = false)) { calibrationData.y2 = Number(g('imageY2').value); } if(!isNaN(g('imageLat2').value) || (calibrationDone = false)) { calibrationData.lat2 = Number(g('imageLat2').value); } if(!isNaN(g('imageLon2').value) || (calibrationDone = false)) { calibrationData.lon2 = Number(g('imageLon2').value); } if(!calibrationDone) { errmsg += '校準出現錯誤!\n'; } else if(calibrationData.lat1 == calibrationData.lat2 || calibrationData.lon1 == calibrationData.lon2 || Math.abs(calibrationData.x1 - calibrationData.x2) < 5 || Math.abs(calibrationData.y1 - calibrationData.y2) < 5) { errmsg += '用作校準工作的兩點不能位於同一經度或者緯度!\n'; calibrationDone = false; } else if((calibrationData.x1 == 0 && calibrationData.y1 == 0) || (calibrationData.x2 == 0 && calibrationData.y2 == 0)) { errmsg += '需要尚餘一點以進行校準工作!\n'; calibrationDone = false; } if(calibrationDone) { g('divTC').style.display = "block"; g('divRef').style.display = "block"; } else { alert(errmsg); } //alert('calibrationDone = ' + calibrationDone + '\n(' + calibrationData.x1 + ', ' + calibrationData.y1 + ') = (' + calibrationData.lat1 + '\xb0N, ' + calibrationData.lon1 + '\xb0E)\n(' + calibrationData.x2 + ', ' + calibrationData.y2 + ') = (' + calibrationData.lat2 + '\xb0N, ' + calibrationData.lon2 + '\xb0E)\n'); } catch(e) { calibrationDone = false; alert("An exception occurred in the script.\nError name: " + e.name + ".\nError description: " + e.description + ".\nError number: " + e.number+ ".\nError message: " + e.message); } return false; } getImageLatLonFromXY = function(n) { try { if(calibrationDone) { var x = Number(g('imageX'+n).value); var y = Number(g('imageY'+n).value); if(isNaN(x) || isNaN(y)) { return false; } with (calibrationData) { var lon = lon1 + (lon2 - lon1) * (x - x1) / (x2 - x1); var lat = lat1 + (lat2 - lat1) * (y - y1) / (y2 - y1); } g('imageLat'+n).value = Math.round(lat * 100) / 100; //round to 2 decimal places; g('imageLon'+n).value = Math.round(lon * 100) / 100; //round to 2 decimal places; } } catch(e) { alert("An exception occurred in the script.\nError name: " + e.name + ".\nError description: " + e.description + ".\nError number: " + e.number+ ".\nError message: " + e.message); } return false; } calc = function() { try { var inrange = function(num, lowerlimit, upperlimit) { return !isNaN(num) && lowerlimit <= num && num <= upperlimit; } var tcpos = new LatLon(g('imageLat3').value.parseDeg(), g('imageLon3').value.parseDeg()); var refpos = new LatLon(g('imageLat4').value.parseDeg(), g('imageLon4').value.parseDeg()); if(inrange(tcpos.lat, -90, 90) && inrange(tcpos.lon, -180, 180) && inrange(refpos.lat, -90, 90) && inrange(refpos.lon, -180, 180)) { //Great circle distances & bearings var distanceHaversine = LatLon.distHaversine(refpos.lat, refpos.lon, tcpos.lat, tcpos.lon); var distanceCosineLaw = LatLon.distCosineLaw(refpos.lat, refpos.lon, tcpos.lat, tcpos.lon); var ref2tcInitBearing = LatLon.bearing(refpos.lat, refpos.lon, tcpos.lat, tcpos.lon); var tc2refInitBearing = LatLon.bearing(tcpos.lat, tcpos.lon, refpos.lat, refpos.lon); //not necessarily 180 degrees apart //Rhumb line distance & bearing var distanceRhumbline = LatLon.distRhumb(refpos.lat, refpos.lon, tcpos.lat, tcpos.lon); var ref2tcRhumbBearing = LatLon.brngRhumb(refpos.lat, refpos.lon, tcpos.lat, tcpos.lon); var formatAngle = function(degrees, decimalPlaces, leadingZero) { var output = ''; if(decimalPlaces > 0) { var dp = Math.round(Math.abs(degrees) % 1 * Math.pow(10, decimalPlaces)).toString(); while(dp.length < decimalPlaces) dp += '0'; output += (leadingZero ? ('000' + Math.floor(degrees)).slice(-3) : Math.floor(degrees).toString()) + '.' + dp; } else { output += (leadingZero) ? ('000' + Math.round(degrees)).slice(-3) : Math.round(degrees).toString(); } output += '°(' + (leadingZero ? degrees.toDMS() : degrees.toDMS().replace(/^0+(?!\u00B0)/g, '')) + ')'; return output; } var formatDistance = function(dist) { return Math.round(dist) + ' km / ' + Math.round(dist / 1.852) + ' nm / ' + Math.round(dist * 0.621) + ' miles'; } var ihtml = '

 

計算結果:

'; ihtml += ''; ihtml += ''; ihtml += ''; ihtml += '
Reference position:' + formatAngle(Math.abs(refpos.lat), 2, false) + (refpos.lat < 0 ? ' S' : ' N') + ', ' + formatAngle(Math.abs(refpos.lon), 2, false) + (refpos.lon < 0 ? ' W' : ' E') + '
TC position:' + formatAngle(Math.abs(tcpos.lat), 2, false) + (tcpos.lat < 0 ? ' S' : ' N') + ', ' + formatAngle(Math.abs(tcpos.lon), 2, false) + (tcpos.lon < 0 ? ' W' : ' E') + '
'; ihtml += ''; ihtml += ''; ihtml += ''; ihtml += ''; ihtml += ''; ihtml += '
Distance methodInitial BearingFinal BearingDistance
Great Circle:[Ref→TC]: ' + formatAngle(ref2tcInitBearing, 0, true) + '[Ref→TC]: ' + formatAngle((tc2refInitBearing + 180) % 360, 0, true) + '' + Math.round(distanceHaversine) + ' km / ' + Math.round(distanceHaversine / 1.852) + ' nm / ' + Math.round(distanceHaversine * 0.621) + ' miles (Haversine formula)
[TC→Ref]: ' + formatAngle(tc2refInitBearing, 0, true) + '[TC→Ref]: ' + formatAngle((ref2tcInitBearing + 180) % 360, 0, true) + '' + Math.round(distanceCosineLaw) + ' km / ' + Math.round(distanceCosineLaw / 1.852) + ' nm / ' + Math.round(distanceCosineLaw * 0.621) + ' miles (cosine law)
Rhumb line:[Ref→TC]: ' + formatAngle(ref2tcRhumbBearing, 0, true) + '[TC→Ref]: ' + formatAngle((ref2tcRhumbBearing + 180) % 360, 0, true) + '' + Math.round(distanceRhumbline) + ' km / ' + Math.round(distanceRhumbline / 1.852) + ' nm / ' + Math.round(distanceRhumbline * 0.621) + ' miles
'; g('divCalcResult').innerHTML = ihtml; } else { alert('資料出現錯誤!'); } } catch(e) { alert("An exception occurred in the script.\nError name: " + e.name + ".\nError description: " + e.description + ".\nError number: " + e.number+ ".\nError message: " + e.message); } return false; }