﻿var poly; var polyinter; var count = 0; var points = new Array; var markers = new Array; var tooltip; var currentspeed = 0; var lineColor = "#FFFF00"; var lineWeight = 2; var lineOpacity = 0.8;
function showTooltip(marker) { tooltip.innerHTML = marker.tooltip; tooltip.style.display = "block"; if (typeof tooltip.style.filter == "string") tooltip.style.filter = "alpha(opacity:70)"; var width = 16; var height = 10; var mapoffset = projection.fromLatLngToDivPixel(marker.getPosition(), map.getZoom()); tooltip.style.top = mapoffset.y - 10 - height + "px"; tooltip.style.left = mapoffset.x - 5 + width + "px"; tooltip.style.visibility = "visible" }
function initDistance(y, x, speed) { if (!tooltip) tooltip = document.createElement("div"); tooltip.className = "distancetip"; tooltip.style.position = "absolute"; overlay.getPanes().floatShadow.appendChild(tooltip); currentspeed = speed; leftClick(new google.maps.LatLng(y, x)); google.maps.event.addListener(map, "click", function (event) { leftClick(event.latLng) }) }
function leftClick(point) {
    if (point) {
        count++; marker = new google.maps.Marker({ map: map, position: point, draggable: true, animation: google.maps.Animation.DROP, icon: "icons/marker_purple.png" }); markers.push(marker); google.maps.event.addListener(marker, "mouseover", function () { showTooltip(this) }); google.maps.event.addListener(marker, "mouseout", function () { tooltip.style.display = "none" }); google.maps.event.addListener(marker, "dragend", function () { tooltip.style.display = "none"; drawDistance() }); google.maps.event.addListener(map,
"rightclick", function () { clearDistance() }); drawDistance()
    } 
}
function drawDistance() {
    if (markers.length == 0) return; if (poly) poly.setMap(null); points.length = 0; for (i = 0; i < markers.length; i++) { points.push(markers[i].getPosition()); markers[i].setMap(map) } poly = new google.maps.Polyline({ path: points, strokeColor: lineColor, strokeOpacity: lineOpacity, strokeWeight: lineWeight }); poly.setMap(map); var dist = google.maps.geometry.spherical.computeLength(poly.getPath().getArray()) / 1852; var course = 0; if (markers.length > 1) course = Math.round(google.maps.geometry.spherical.computeHeading(markers[markers.length -
2].getPosition(), markers[markers.length - 1].getPosition())); if (course < 0) course += 360; var totalmins = Math.floor(dist * 60 / currentspeed); var days = Math.floor(totalmins / 1440); totalmins %= 1440; var hours = Math.floor(totalmins / 60); totalmins %= 60; var minutes = Math.floor(totalmins); var eta = new Date; eta.setTime(eta.valueOf() + dist * 36E5 / currentspeed); var tip = ""; if (markers.length > 1 && currentspeed > 0.5) tip = "Waypoint" + (markers.length - 1).toString() + ": " + dist.toFixed(1) + " NM, " + course + "&deg;" + "<br/>" + days + "d " + hours + "h " + minutes +
"min (at " + currentspeed.toFixed(1) + " knots)" + "<br/>ETA: " + eta.getUTCFullYear() + "-" + zeroPad(eta.getUTCMonth(), 2) + "-" + zeroPad(eta.getUTCDate(), 2) + " " + zeroPad(eta.getUTCHours(), 2) + ":" + zeroPad(eta.getUTCMinutes(), 2) + " (UTC)" + '<br/><span style="font-size:7pt">(Click on next waypoint' + "<br/>or Right-click to clear)</span>"; else if (markers.length > 1 && currentspeed <= 0.5) tip = "Waypoint" + (markers.length - 1).toString() + ": " + dist.toFixed(1) + " NM, " + course + "&deg;" + '<br/><span style="font-size:7pt">(Click on next waypoint' +
"<br/>or Right-click to clear)</span>"; else tip = 'Waypoint0<br/><span style="font-size:7pt">Click on next waypoint</span>'; markers[markers.length - 1].tooltip = tip; showTooltip(markers[markers.length - 1])
}
function clearDistance() { if (markers.length > 1) { tooltip.style.display = "none"; google.maps.event.clearListeners(map, "rightclick"); google.maps.event.clearListeners(map, "click"); for (var i = 0; i < markers.length; i++) markers[i].setMap(null); poly.setMap(null); points.length = 0; markers.length = 0; count = 0 } if (polyinter) { tooltip.style.display = "none"; google.maps.event.clearListeners(map, "rightclick"); inter1 = 0; inter2 = 0 } }
function zeroPad(num, count) { var numZeropad = num + ""; while (numZeropad.length < count) numZeropad = "0" + numZeropad; return numZeropad } function bearing(from, to) { var lat1 = from.lat() * Math.PI / 180; var lon1 = from.lng() * Math.PI / 180; var lat2 = to.lat() * Math.PI / 180; var lon2 = to.lng() * Math.PI / 180; var angle = -Math.atan2(Math.sin(lon1 - lon2) * Math.cos(lat2), Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2)); if (angle < 0) angle += Math.PI * 2; angle = angle * 180 / Math.PI; angle = angle.toFixed(1); return angle }
function intersection(p1, brng1, p2, brng2) {
    var lat1 = p1.lat() * Math.PI / 180; var lon1 = p1.lng() * Math.PI / 180; var lat2 = p2.lat() * Math.PI / 180; var lon2 = p2.lng() * Math.PI / 180; var brng13 = brng1 * Math.PI / 180, brng23 = brng2 * Math.PI / 180; var dLat = lat2 - lat1, dLon = lon2 - lon1; dist12 = 2 * Math.asin(Math.sqrt(Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLon / 2) * Math.sin(dLon / 2))); if (dist12 == 0) return null; brngA = Math.acos((Math.sin(lat2) - Math.sin(lat1) * Math.cos(dist12)) / (Math.sin(dist12) * Math.cos(lat1)));
    if (isNaN(brngA)) brngA = 0; brngB = Math.acos((Math.sin(lat1) - Math.sin(lat2) * Math.cos(dist12)) / (Math.sin(dist12) * Math.cos(lat2))); if (Math.sin(lon2 - lon1) > 0) { brng12 = brngA; brng21 = 2 * Math.PI - brngB } else { brng12 = 2 * Math.PI - brngA; brng21 = brngB } alpha1 = (brng13 - brng12 + Math.PI) % (2 * Math.PI) - Math.PI; alpha2 = (brng21 - brng23 + Math.PI) % (2 * Math.PI) - Math.PI; if (Math.sin(alpha1) == 0 && Math.sin(alpha2) == 0) return null; if (Math.sin(alpha1) * Math.sin(alpha2) < 0) return null; alpha3 = Math.acos(-Math.cos(alpha1) * Math.cos(alpha2) + Math.sin(alpha1) *
Math.sin(alpha2) * Math.cos(dist12)); dist13 = Math.atan2(Math.sin(dist12) * Math.sin(alpha1) * Math.sin(alpha2), Math.cos(alpha2) + Math.cos(alpha1) * Math.cos(alpha3)); lat3 = Math.asin(Math.sin(lat1) * Math.cos(dist13) + Math.cos(lat1) * Math.sin(dist13) * Math.cos(brng13)); dLon13 = Math.atan2(Math.sin(brng13) * Math.sin(dist13) * Math.cos(lat1), Math.cos(dist13) - Math.sin(lat1) * Math.sin(lat3)); lon3 = lon1 + dLon13; lon3 = (lon3 + Math.PI) % (2 * Math.PI) - Math.PI; return new google.maps.LatLng(lat3 * 180 / Math.PI, lon3 * 180 / Math.PI)
}
function drawIntersection(index1, index2) {
    if (polyinter) polyinter.setMap(null); points = new Array; p1 = new google.maps.LatLng(y[mmsi[index1]], x[mmsi[index1]]); p2 = new google.maps.LatLng(y[mmsi[index2]], x[mmsi[index2]]); interpoint = intersection(p1, course[index1], p2, course[index2]); if (interpoint && google.maps.geometry.spherical.computeDistanceBetween(p1, interpoint) / 1852 < 100) {
        google.maps.event.addListener(map, "rightclick", function () { clearDistance() }); points.push(p1); points.push(interpoint); points.push(p2); polyinter =
new google.maps.Polyline({ path: points, strokeColor: lineColor, strokeOpacity: lineOpacity, strokeWeight: lineWeight }); polyinter.setMap(map); var marker = new google.maps.Marker({ position: interpoint, map: map, draggable: false, icon: "icons/marker_purple.png" }); var distance1 = google.maps.geometry.spherical.computeDistanceBetween(p1, interpoint) / 1852; var distance2 = google.maps.geometry.spherical.computeDistanceBetween(p2, interpoint) / 1852; var time1 = Math.floor(distance1 / speed[index1] * 600); var time2 = Math.floor(distance2 /
speed[index2] * 600); distance1 = Math.round(distance1 * 100) / 100; distance2 = Math.round(distance2 * 100) / 100; var info = "Course Intersection at:<br/>"; info += shipname[index1] + ": " + time1 + " minutes (" + distance1 + " n.miles at " + speed[index1] / 10 + " knots)<br/>"; info += shipname[index2] + ": " + time2 + " minutes (" + distance2 + " n.miles at " + speed[index2] / 10 + " knots)"; if (!tooltip) tooltip = document.createElement("div"); tooltip.className = "distancetip"; tooltip.style.position = "absolute"; overlay.getPanes().floatShadow.appendChild(tooltip);
        marker.tooltip = info; showTooltip(marker)
    } 
}
function predicted(startpoint, bearing, speed, minutes) { var d = speed * minutes / 60; var R = 3440; var brng = bearing * Math.PI / 180; var lat1 = startpoint.lat() * Math.PI / 180; var lon1 = startpoint.lng() * Math.PI / 180; var lat2 = Math.asin(Math.sin(lat1) * Math.cos(d / R) + Math.cos(lat1) * Math.sin(d / R) * Math.cos(brng)); var lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(d / R) * Math.cos(lat1), Math.cos(d / R) - Math.sin(lat1) * Math.sin(lat2)); return new google.maps.LatLng(lat2 * 180 / Math.PI, lon2 * 180 / Math.PI) }
function drawPredicted(shipindex, minutes) { if (speed[shipindex] > 5 && minutes > 0) { points = new Array; p1 = new google.maps.LatLng(y[mmsi[shipindex]], x[mmsi[shipindex]]); p2 = predicted(p1, course[shipindex], speed[shipindex] / 10, minutes); points.push(p1); points.push(p2); poly = new google.maps.Polyline({ path: points, strokeColor: trackcolor[shiptype[shipindex]], strokeOpacity: lineOpacity, strokeWeight: 1 }); poly.setMap(map); return poly } else return null };
