216 wiersze
7.8 KiB
JavaScript
216 wiersze
7.8 KiB
JavaScript
/*
|
|
* CUSF Landing Prediction Version 2
|
|
* Jon Sowman 2010
|
|
* jon@hexoc.com
|
|
* http://www.hexoc.com
|
|
*
|
|
* http://github.com/jonsowman/cusf-standalone-predictor
|
|
*
|
|
* This file contains all of the prediction javascript functions
|
|
* that are explicitly related to Google Map manipulation
|
|
*
|
|
*/
|
|
|
|
// Initialise the map canvas with (lat, long, zoom)
|
|
function initMap(centre_lat, centre_lon, zoom_level) {
|
|
// Make the map and set center
|
|
var latlng = new google.maps.LatLng(centre_lat, centre_lon);
|
|
var myOptions = {
|
|
zoom: zoom_level,
|
|
scaleControl: true,
|
|
scaleControlOptions: { position: google.maps.ControlPosition.BOTTOM_LEFT } ,
|
|
mapTypeId: google.maps.MapTypeId.TERRAIN,
|
|
center: latlng
|
|
};
|
|
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
|
|
}
|
|
|
|
// Enable or disable user control of the map canvas, including scrolling,
|
|
// zooming and clicking
|
|
function enableMap(map, state) {
|
|
if ( state != false && state != true) {
|
|
appendDebug("Unrecognised map state");
|
|
} else if (state == false) {
|
|
map.draggable = false;
|
|
map.disableDoubleClickZoom = true;
|
|
map.scrollwheel = false;
|
|
map.navigationControl = false;
|
|
} else if (state == true ) {
|
|
map.draggable = true;
|
|
map.disableDoubleClickZoom = false;
|
|
map.scrollwheel = false;
|
|
map.navigationControl = true;
|
|
}
|
|
}
|
|
|
|
// This should be called on a "mousemove" event handler on the map canvas
|
|
// and will update scenario information display
|
|
function showMousePos(GLatLng) {
|
|
var curr_lat = GLatLng.lat().toFixed(4);
|
|
var curr_lon = GLatLng.lng().toFixed(4);
|
|
$("#cursor_lat").html(curr_lat);
|
|
$("#cursor_lon").html(curr_lon);
|
|
// if we have a prediction displayed
|
|
// show range from launch and land:
|
|
if ( current_uuid != 0 && map_items['launch_marker'] != null ) {
|
|
var launch_pt = map_items['launch_marker'].position;
|
|
var land_pt = map_items['land_marker'].position;
|
|
var range_launch = distHaversine(launch_pt, GLatLng, 1);
|
|
var range_land = distHaversine(land_pt, GLatLng, 1);
|
|
$("#cursor_pred_launchrange").html(range_launch);
|
|
$("#cursor_pred_landrange").html(range_land);
|
|
}
|
|
|
|
}
|
|
|
|
// Takes an array of points and the name of the gmap object and plots
|
|
// the polygon onto the map
|
|
function drawPolygon(points, gmap_object) {
|
|
var newPoly = new google.maps.Polyline({
|
|
path: points,
|
|
strokeColor: "#FF0000",
|
|
strokeOpacity: 0.4,
|
|
//fillColor: "#FFFFFF",
|
|
//fillOpacity: 0,
|
|
strokeWeight: 2
|
|
});
|
|
map_items['delta_square'] = newPoly;
|
|
newPoly.setMap(gmap_object);
|
|
}
|
|
|
|
// Read the latitude and longitude currently in the launch card and plot
|
|
// a marker there with hover information
|
|
function plotClick() {
|
|
// Clear the old marker
|
|
clearMapItems();
|
|
// Get the new values from the form
|
|
click_lat = parseFloat($("#lat").val());
|
|
click_lon = parseFloat($("#lon").val());
|
|
// Make sure the data is valid before we try and do anything with it
|
|
if ( isNaN(click_lat) || isNaN(click_lon) ) return;
|
|
var click_pt = new google.maps.LatLng(click_lat, click_lon);
|
|
clickMarker = new google.maps.Marker({
|
|
position: click_pt,
|
|
map: map,
|
|
icon: 'images/target-1-sm.png',
|
|
title: 'Currently selected launch location (' + click_lat + ', '
|
|
+ click_lon+')'
|
|
});
|
|
map_items['clickMarker'] = clickMarker;
|
|
// Redraw the delta square
|
|
drawDeltaSquare(map);
|
|
map.panTo(click_pt);
|
|
map.setZoom(8);
|
|
}
|
|
|
|
// Uses the currently selected lat, lon and delta values in the launch
|
|
// card to draw a square of the GFS data to be downloaded for the prediction
|
|
function drawDeltaSquare(map) {
|
|
// Clear the old delta square if it exists
|
|
if ( map_items['delta_square'] ) map_items['delta_square'].setMap(null);
|
|
// Get the values from the form
|
|
var lat = Math.round(parseFloat($("#lat").val()));
|
|
var lon = Math.round(parseFloat($("#lon").val()));
|
|
var dlat = parseFloat($("#delta_lat").val());
|
|
var dlon = parseFloat($("#delta_lon").val());
|
|
// Construct a rectange of points
|
|
var points = [
|
|
new google.maps.LatLng(lat+dlat, lon+dlon),
|
|
new google.maps.LatLng(lat-dlat, lon+dlon),
|
|
new google.maps.LatLng(lat-dlat, lon-dlon),
|
|
new google.maps.LatLng(lat+dlat, lon-dlon),
|
|
new google.maps.LatLng(lat+dlat, lon+dlon)
|
|
]
|
|
// Draw this polygon onto the map canvas
|
|
drawPolygon(points, map);
|
|
}
|
|
|
|
// Given a GLatLng object, write the latitude and longitude to the launch card
|
|
function setFormLatLon(GLatLng) {
|
|
appendDebug("Trying to set the form lat long");
|
|
$("#lat").val(GLatLng.lat().toFixed(4));
|
|
$("#lon").val(GLatLng.lng().toFixed(4));
|
|
// Remove the event handler so another click doesn't register
|
|
setLatLonByClick(false);
|
|
// Change the dropdown to read "other"
|
|
SetSiteOther();
|
|
// Plot the new marker for launch location
|
|
appendDebug("Plotting the new launch location marker");
|
|
plotClick();
|
|
}
|
|
|
|
// Enable or disable an event handler which, when a mouse click is detected
|
|
// on the map canvas, will write the coordinates of the clicked place to the
|
|
// launch card
|
|
function setLatLonByClick(state) {
|
|
if ( state == true ) {
|
|
// Check this listener doesn't already exist
|
|
if (!clickListener) {
|
|
appendDebug("Enabling the set with click listener");
|
|
clickListener = google.maps.event.addListener(map, 'click', function(event) {
|
|
appendDebug("Got a click from user, setting values into form");
|
|
$("#error_window").fadeOut();
|
|
setFormLatLon(event.latLng);
|
|
});
|
|
}
|
|
// Tell the user what to do next
|
|
throwError("Now click your desired launch location on the map");
|
|
} else if ( state == false ) {
|
|
appendDebug("Removing the set with click listener");
|
|
google.maps.event.removeListener(clickListener);
|
|
clickListener = null;
|
|
} else {
|
|
appendDebug("Unrecognised state for setLatLonByClick");
|
|
}
|
|
}
|
|
|
|
// An associative array exists globally containing all objects we have placed
|
|
// onto the map canvas - this function clears all of them
|
|
function clearMapItems() {
|
|
$("#cursor_pred").hide();
|
|
if( getAssocSize(map_items) > 0 ) {
|
|
appendDebug("Clearing previous map trace");
|
|
for( i in map_items ) {
|
|
map_items[i].setMap(null);
|
|
}
|
|
}
|
|
map_items = [];
|
|
}
|
|
|
|
// The Haversine formula to calculate the distance across the surface between
|
|
// two points on the Earth
|
|
distHaversine = function(p1, p2, precision) {
|
|
var R = 6371; // earth's mean radius in km
|
|
var dLat = rad(p2.lat() - p1.lat());
|
|
var dLong = rad(p2.lng() - p1.lng());
|
|
|
|
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
|
|
Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2);
|
|
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
|
|
var d = R * c;
|
|
if ( precision == null ) {
|
|
return d.toFixed(3);
|
|
} else {
|
|
return d.toFixed(precision);
|
|
}
|
|
}
|
|
|
|
// Given a latitude, longitude, and a field to write the result to,
|
|
// find the name of the place using Google "reverse Geocode" API feature
|
|
function rvGeocode(lat, lon, fillField) {
|
|
var geocoder = new google.maps.Geocoder();
|
|
var latlng = new google.maps.LatLng(parseFloat(lat), parseFloat(lon));
|
|
var coded = "Unnamed";
|
|
geocoder.geocode({'latLng': latlng}, function(results, status) {
|
|
if ( status == google.maps.GeocoderStatus.OK ) {
|
|
// Successfully got rv-geocode information
|
|
appendDebug("Got a good response from the geocode server");
|
|
coded = results[1].address_components[1].short_name;
|
|
} else {
|
|
appendDebug("The rv-geocode failed: " + status);
|
|
}
|
|
// Now write the value to the field
|
|
$("#"+fillField+"").val(coded);
|
|
});
|
|
}
|