//"Ships" Simulation module of "Shipping Line" trading game.
//written by: Paul van Dinther
//            Dinther Product Design
//            Software development and specialists in simulation
//            email: vandinther@gmail.com

    var ge = null;
    var map = null;
    var shiplist = new Array();
    var myship = null;
    var oneOnly = true;
    var speed = 0.2;
    var lastMill;
    var lastKeyDownTime = 0;
    var roll1 = 0;
    var roll2 = 0;
    var pitch1 = 0;
    var pitch2 = 0;
    var turnRateIndicator = null;
    var compassIndicator = null;
    var wheel = null;
    var rightPower = null;
    var rudderNeedle = null;
    var rudderTargetNeedle = null;
    var speedNeedle = null;
    var fuelNeedle = null;
    var collidedBow = null;
    var collidedStern = null;
    var leftArrow = false;
    var rightArrow = false;
    var upArrow = false;
    var downArrow = false;
    var leftpowerupkey = false;
    var leftpowerdownkey = false;
    var rightpowerupkey = false;
    var rightpowerdownkey = false;
    var leftbowthrust = false;
    var rightbowthrust = false;
    var bowthrust = 0;
    var helpPad = null;
    var helpRight = 0;
    var leftArrowindex = 0;
    var rightArrowindex = 0;
    var mouseIsDown=false;
    var viewMenu = null;
    var viewMode = 0;
    var headCamHeading = 0;
    var headHeading = 0;
    var headTilt = 0;
    var currentCam = null;
    var spotDistanceRange = 4000;
    var distanceCutOff = 4000;
    var now = 0;
    var pauseIcon = null;
    var presentingBanner = null;
    var togglePauseState = false;
    var toggleBuildingsState = true;
    var toggleGrayBuildingsState = false;
    var toggleBordersState = false;
    var shipModelId = 0;
    var waterLevel = 0;
    var textInputFocus = false;
    var leftPowerControl = null;
    var rightPowerControl = null;
    var bowPowerControl = null;   
    var engineLoopFinished = true;
    var engineSound = null;
    var anchorDownSound = null;
    var environmentSound = null;
    var hornPlaying = false;
    var camBearingDistanceTilt = null;
    var engineMute = false;
    var currentViewID = 1;
    var newView = null;
    var lowUpdate = 0;
    var frameCount = 0;
    var frames = new Array();
    var frameSampleTime = 0;
    var doPerformance = false;
    var viewModeIndex = -1;
    var bannerTimeOut = 0;
    var showBanner = true;

function init() {
    handleResize();
    document.getElementById('location').onblur = function () {textInputFocus = false;}
    document.getElementById('location').onfocus = function () {textInputFocus = true;}
    if(navigator.appName.indexOf("Microsoft") != -1) { engineSound = window.engine; }
    else { engineSound = window.document.engine; }
    //if(navigator.appName.indexOf("Microsoft") != -1) { environmentSound = window.environment; }
    //else { environmentSound = window.document.environment; }
    lastMill = (new Date()).getTime();
    google.earth.createInstance("map3d", initCB, failureCB);
    if (GBrowserIsCompatible()) {
        map = new GMap2(document.getElementById("map"));
        map.setCenter(new GLatLng(51.893606, 4.308849), 12);
        var customUI = map.getDefaultUI();
        customUI.controls.menumaptypecontrol = false;
        map.setUI(customUI);        
    }
    soundManager.url = masterHost; // directory where SM2 .SWFs live
    soundManager.debugMode = false;
    soundManager.useConsole = false;
    soundManager.useHighPerformance = true;
    //soundManager.waitForWindowLoad = true; 
    
    if(navigator.appName.indexOf("Microsoft") != -1){soundManager.onload = function(){ createSounds();}}
    else createSounds();
}

function createSounds(){
    soundManager.createSound({id: 'anchor', url: 'anchorwithsplash.mp3'});
    horn1Sound = soundManager.createSound({id: 'smallhorn', url: 'horn1.mp3'});
    horn1EndSound = soundManager.createSound({id: 'smallhornend', url: 'horn1fade.mp3'});
    horn2Sound = soundManager.createSound({id: 'qm2horn', url: 'horn2.mp3'});
    horn2EndSound = soundManager.createSound({id: 'qm2hornend', url: 'horn2fade.mp3'});    
}

function handleResize(){
    document.getElementById('map3d').style.height = document.body.clientHeight - 150;    
}

function initCB(object) {
    document.title = applicationTitle;
    ge = object;
    ge.getWindow().setVisibility(true);
    //ge.getOptions().setStatusBarVisibility(true);
    ge.getNavigationControl().setVisibility(ge.VISIBILITY_SHOW);
    //ge.getOptions().setFlyToSpeed(ge.SPEED_TELEPORT);
    ge.getOptions().setFlyToSpeed(1);
    //show sun
    //ge.getSun().setVisibility(1);
    //show buildings
    ge.getLayerRoot().enableLayerById(ge.LAYER_BUILDINGS, 1);
    //hide navigation control
    //ge.getNavigationControl().setVisibility(0);
    createViewMenu();
    createViewMenuSelected();
    createTurnRateGauge(170,100)
    createSpeedGauge(70,70);
    createFuelGauge(170,33);
    //createRudderGauge(270,31);
    createRudderCompassGauge(280,70);
    createPanel();
    createWheel();
    createHelp();
    createPauseIcon();
    createPresentingBanner();
    collidedBow = createOverlay('bowcollided', 0,0,50,50, 0, masterHost + 'images/collided.png' );
    collidedBow.setVisibility(false);
    collidedStern = createOverlay('bowcollided', 0,0,50,50, 0, masterHost + 'images/collided.png' );    
    collidedStern.setVisibility(false);

    leftArrow = false;
    rightArrow = false;
    upArrow = false;
    downArrow = false;

    google.earth.fetchKml(ge, masterHost + 'gbillboard.kmz', placegbillboard);
                
    for (var i=0; i < 7; i++) {
        loadShip(i);
    }

    engineSound.engineVolume(0);   
    
    //environmentSound.enginePlay();
    google.earth.addEventListener(ge, "frameend", moveship);
    google.earth.addEventListener(ge.getWindow(), "mouseup", setMouseUp);
    google.earth.addEventListener(ge.getWindow(), "mousedown", setMouseDown);
    google.earth.addEventListener(ge.getWindow(), "mousemove", setMouseMove);
    google.earth.addEventListener(ge.getWindow(), "dblclick", setShipLocation); 
}

function placegbillboard(object){
    var billboard = object.getFeatures().getChildNodes().item(1).getGeometry();
    billboard.setAltitudeMode(ge.ALTITUDE_RELATIVE_TO_GROUND);
    var billboardlocation = ge.createLocation('');
    billboardlocation.setLatLngAlt(51.901153564453125, 4.458194732666016, 0);
    billboard.setLocation(billboardlocation);
    var billboardorientation = ge.createOrientation('');
    billboardorientation.set(90,0,0);
    billboard.setOrientation(billboardorientation);
    ge.getFeatures().appendChild(object);
}


function failureCB(object) {
    alert('load failed');
}

function setShipLocation(event){
    if (event.getDidHitGlobe()){ //only if globe was hit
        //if (event.getButton() == 0){ //only if left mouse button
        myship.model.getLocation().setLatitude(event.getLatitude());
        myship.model.getLocation().setLongitude(event.getLongitude());
        myship.model.setAltitudeMode(ge.ALTITUDE_RELATIVE_TO_GROUND);
        myship.model.getLocation().setAltitude(myship.draft);
        currentCam = ge.getView().copyAsLookAt(ge.ALTITUDE_ABSOLUTE);
        myship.heading =  currentCam.getHeading();
        myship.getOrientation().setHeading(myship.heading);
        myship.speed = 0;
        myship.turnRate = 0; 
    
        //clean up wake and bow
        myship.cleanupWake();
        myship.cleanupBow();
    }
}

function removeObject(object){
    if (object != null){
        var c = ge.getFeatures().getFirstChild();
        while (c) {
            var s = c.getNextSibling();
            if (c == object){
                ge.getFeatures().removeChild(c);
            }
            c = s;
        }   
    }
}

function selectShipfromID(id, doView){
    shipModelId = id;
    document.getElementById('ship0icon').src = 'images/closedbargeicon.png';
    document.getElementById('ship1icon').src = 'images/openbargeicon.png';
    document.getElementById('ship2icon').src = 'images/fuelshipicon.png';
    document.getElementById('ship3icon').src = 'images/qmicon.png';
    document.getElementById('ship4icon').src = 'images/hindenburgicon.png';
    document.getElementById('ship5icon').src = 'images/canalbargeicon.png'; 
    document.getElementById('ship6icon').src = 'images/containershipicon.png'; 
    switch(id){
        case 0: { document.getElementById('ship0icon').src = 'images/closedbargeiconselected.png'; break; }
        case 1: { document.getElementById('ship1icon').src = 'images/openbargeiconselected.png'; break; }
        case 2: { document.getElementById('ship2icon').src = 'images/fuelshipiconselected.png'; break; }
        case 3: { document.getElementById('ship3icon').src = 'images/qmiconselected.png'; break; }
        case 4: { document.getElementById('ship4icon').src = 'images/hindenburgiconselected.png'; break; }
        case 5: { document.getElementById('ship5icon').src = 'images/canalbargeiconselected.png'; break; }        
        case 6: { document.getElementById('ship6icon').src = 'images/containershipiconselected.png'; break; }        
    }
    selectShip(shiplist[shipModelId], doView);
}

function selectShip(ship, doView){
    myship = ship;
    leftPowerControl.ship = myship;
    rightPowerControl.ship = myship;
    bowPowerControl.ship = myship;
    //myship.leftPowerValue = leftPowerControl.f_getValue();  
    //myship.rightPowerValue = rightPowerControl.f_getValue();
    //myship.bowPowerValue = bowPowerControl.f_getValue();
    myship.model.setAltitudeMode(ge.ALTITUDE_ABSOLUTE);    
    if (myship.fuel > 0 && engineMute == false) { engineSound.enginePlay(); }
    if (doView == true) { setShipView(currentViewID); }
    syncControls();
}

function syncControls(){
    setAnchorSwitch(myship.anchorDown);
    leftPowerControl.f_setValue(myship.leftPowerValue);
    rightPowerControl.f_setValue(myship.rightPowerValue);
    bowPowerControl.f_setValue(myship.bowPowerValue);
}

function loadShip(id){
    shipModelId = id;
    switch (shipModelId){
        case 0: {google.earth.fetchKml(ge, masterHost + 'barge_closed.kmz', makeFinishedCallback(0)); break;}
        case 1: {google.earth.fetchKml(ge, masterHost + 'barge_open.kmz', makeFinishedCallback(1)); break;}
        case 2: {google.earth.fetchKml(ge, masterHost + 'refuel_ship.kmz', makeFinishedCallback(2)); break;}
        case 3: {google.earth.fetchKml(ge, masterHost + 'qm2.kmz', makeFinishedCallback(3)); break;}        
        case 4: {google.earth.fetchKml(ge, masterHost + 'hindenburg.kmz', makeFinishedCallback(4)); break;}
        case 5: {google.earth.fetchKml(ge, masterHost + 'canal_barge.kmz', makeFinishedCallback(5)); break;}
        case 6: {google.earth.fetchKml(ge, masterHost + 'emma_maersk.kmz', makeFinishedCallback(6)); break;}        
    }
}

function makeFinishedCallback(id) {
  return function(object) {
    shiplist[id] = new ship();
    shiplist[id].id = id;
    shiplist[id].modelObject = object;
    shiplist[id].model = shiplist[id].modelObject.getFeatures().getChildNodes().item(1).getGeometry();
    shiplist[id].model.getLocation().setLatLngAlt(51.8938, 4.302, 0);
    shiplist[id].model.setAltitudeMode(ge.ALTITUDE_RELATIVE_TO_GROUND);
    shiplist[id].model.getOrientation().set(0,0,0);
    ge.getFeatures().appendChild(shiplist[id].modelObject);

    setShipParameters(id);
    resetControls(shiplist[id]);
    shiplist[id].initialise();
    if (id==0){
        selectShipfromID(id, false);
        currentCam = ge.createCamera('');
        //currentCam.set(51.89556418872714, 4.456439050200751, 19.715218777985292, ge.ALTITUDE_ABSOLUTE, 27.18710274392539,87.52783900211004,0);
        //currentCam.set(51.89443767538309, 4.453424958952782, 155.45363214050482,ge.ALTITUDE_ABSOLUTE, 35.05065375579893, 77.11085246762718, 0);
        currentCam.set(51.895575892145374, 4.4564290201353325, 17.447522757771228,2, 32.80236803658749, 90.72967990401953, 0);
        ge.getView().setAbstractView(currentCam);
    }  
  };
} 

function setShipParameters(id) {
    switch(id){
        //closed river barge
        case 0: {
            shiplist[id].model.getLocation().setLatLngAlt(51.896873474121094, 4.457442760467529, -2);
            shiplist[id].heading = 4.719444787635487;
            shiplist[id].engineSoundRange = 800;
            shiplist[id].mechanicSoundRange = 700;
            shiplist[id].hornSoundRange = 2000;
            shiplist[id].anchorSound = 'anchor';
            shiplist[id].hornSound = 'smallhorn';
            shiplist[id].hornEndSound = 'smallhornend';
            shiplist[id].shadowImageURL = masterHost + 'images/shipshadow.png'; 
            shiplist[id].camAlt = 3;
            shiplist[id].shadowOffset = 3;
            shiplist[id].shadowAngle = 90;
            shiplist[id].shadowWidth = 26;
            shiplist[id].shadowLength = 116;        
            shiplist[id].wakeOffset = 40;
            shiplist[id].bowOffset = -48;
            shiplist[id].draft = -2;          
            shiplist[id].mass = 1000;
            shiplist[id].turnFriction = 0.08;
            shiplist[id].turnInertia = 200;
            shiplist[id].moveFriction = 0.015;
            shiplist[id].potentialEnginePower = 500;
            shiplist[id].rollEffect = 1;
            shiplist[id].pitchEffect = 1;           
            shiplist[id].setFuelCapacity(12);
            shiplist[id].wakeImageURL = masterHost + 'images/wake.png';
            shiplist[id].wakeSize = 6;
            shiplist[id].bowImageURL = masterHost + 'images/wake.png';
            shiplist[id].bowSize = 2;
            shiplist[id].view1.setView(201.01903516014283, 160.0684043325387, 2, 17.636758992576503, 28.08292324895203, 90.72967990401949, 0.0000032461051851014595, 0);
            shiplist[id].view2.setView(180, 57, 2, 10, 0, 81, 0, 3);
            shiplist[id].view3.setView(7.543468216561678, 203.68100876202675, 2, 14.933841665159763, -176.25060871877426, 84.40791747743395, -2.0182726571362483e-10, 0);
            shiplist[id].view4.setView(0, 100, 2, 380, 270, 0, 0, 0);
            break;
        }
        //open river barge
        case 1: {
            shiplist[id].model.getLocation().setLatLngAlt(51.89844512939453, 4.443442344665527, 0);
            shiplist[id].heading = 104.97893384558321;
            shiplist[id].engineSoundRange = 800;
            shiplist[id].mechanicSoundRange = 700;
            shiplist[id].hornSoundRange = 2000;
            shiplist[id].anchorSound = 'anchor';
            shiplist[id].hornSound = 'smallhorn';
            shiplist[id].hornEndSound = 'smallhornend';
            shiplist[id].shadowImageURL = masterHost + 'images/shipshadow.png'; 
            shiplist[id].camAlt = 3;
            shiplist[id].shadowOffset = 3;
            shiplist[id].shadowAngle = 90;
            shiplist[id].shadowWidth = 26;
            shiplist[id].shadowLength = 116;
            shiplist[id].rollEffect = 1;
            shiplist[id].pitchEffect = 1;            
            shiplist[id].wakeOffset = 40;
            shiplist[id].bowOffset = -48;
            shiplist[id].draft = 0;
            shiplist[id].mass = 1000;
            shiplist[id].turnFriction = 0.08;
            shiplist[id].turnInertia = 200;
            shiplist[id].moveFriction = 0.015;
            shiplist[id].potentialEnginePower = 500;
            shiplist[id].rollEffect = 1;
            shiplist[id].pitchEffect = 1;           
            shiplist[id].setFuelCapacity(12);            
            shiplist[id].wakeImageURL = masterHost + 'images/wake.png';
            shiplist[id].wakeSize = 7;
            shiplist[id].bowImageURL = masterHost + 'images/wake.png';
            shiplist[id].bowSize = 2;
            shiplist[id].view1.setView(120, 60, 2, 22, -60, 82, 0, 0);
            shiplist[id].view2.setView(180, 57, 2, 10, 0, 81, 0, 3);
            shiplist[id].view3.setView(7.543468216561678, 203.68100876202675, 2, 14.933841665159763, -176.25060871877426, 84.40791747743395, -2.0182726571362483e-10, 0);
            shiplist[id].view4.setView(0, 100, 2, 380, 270, 0, 0, 0);            
            break;
        }
        //canal barge
        case 5: {
            shiplist[id].model.getLocation().setLatLngAlt(51.90343497180778, 4.462567316025705, -1);
            shiplist[id].heading = 165.61758337312966;
            shiplist[id].engineSoundRange = 500;
            shiplist[id].mechanicSoundRange = 700;
            shiplist[id].hornSoundRange = 800;
            shiplist[id].anchorSound = 'anchor';
            shiplist[id].hornSound = 'smallhorn';
            shiplist[id].hornEndSound = 'smallhornend';
            shiplist[id].shadowImageURL = masterHost + 'images/shipshadow.png'; 
            shiplist[id].camAlt = 3;
            shiplist[id].shadowOffset = 1.5;
            shiplist[id].shadowAngle = 90;
            shiplist[id].shadowWidth = 13;
            shiplist[id].shadowLength = 58;        
            shiplist[id].wakeOffset = 20;
            shiplist[id].bowOffset = -25;
            shiplist[id].draft = -1;          
            shiplist[id].mass = 800;
            shiplist[id].turnFriction = 0.08;
            shiplist[id].turnInertia = 100;
            shiplist[id].moveFriction = 0.015;
            shiplist[id].potentialEnginePower = 250;
            shiplist[id].rollEffect = 1;
            shiplist[id].pitchEffect = 1;           
            shiplist[id].setFuelCapacity(12);
            shiplist[id].wakeImageURL = masterHost + 'images/wake.png';
            shiplist[id].wakeSize = 3;
            shiplist[id].bowImageURL = masterHost + 'images/wake.png';
            shiplist[id].bowSize = 1;
            shiplist[id].view1.setView(121.6683497816669, 53.38638223021625, 2, 17.399531013460503, -68.38538792855779, 75.48046125387626, -2.4712909874971524e-12, 0);
            shiplist[id].view2.setView(180, 57, 2, 10, 0, 81, 0, 3);
            shiplist[id].view3.setView(7.543468216561678, 203.68100876202675, 2, 14.933841665159763, -176.25060871877426, 84.40791747743395, -2.0182726571362483e-10, 0);
            shiplist[id].view4.setView(0, 100, 2, 380, 270, 0, 0, 0);
            break;
        }     
        //refuel ship   
        case 2: {
            shiplist[id].model.getLocation().setLatLngAlt(51.902061462402344, 4.463230609893799, 0);
            shiplist[id].heading = 165.88668529277612;
            shiplist[id].engineSoundRange = 1200;
            shiplist[id].mechanicSoundRange = 1000;
            shiplist[id].hornSoundRange = 3000;
            shiplist[id].anchorSound = 'anchor';
            shiplist[id].hornSound = 'smallhorn';
            shiplist[id].hornEndSound = 'smallhornend';
            shiplist[id].shadowImageURL = masterHost + 'images/shipshadow.png'; 
            shiplist[id].camAlt = 10;
            shiplist[id].shadowOffset = 5;
            shiplist[id].shadowAngle = 90;
            shiplist[id].shadowWidth = 30;
            shiplist[id].shadowLength = 155;
            shiplist[id].rollEffect = 1;
            shiplist[id].pitchEffect = 1;            
            shiplist[id].wakeOffset = 40;
            shiplist[id].bowOffset = -63;
            shiplist[id].draft = 0;
            shiplist[id].mass = 2000;
            shiplist[id].turnFriction = 0.08;
            shiplist[id].turnInertia = 400;
            shiplist[id].moveFriction = 0.010;
            shiplist[id].potentialEnginePower = 1500;
            shiplist[id].rollEffect = 1;
            shiplist[id].pitchEffect = 1;           
            shiplist[id].setFuelCapacity(12);
            shiplist[id].wakeImageURL = masterHost + 'images/wake.png';
            shiplist[id].wakeSize = 7;
            shiplist[id].bowImageURL = masterHost + 'images/wake.png';
            shiplist[id].bowSize = 2;
            shiplist[id].view1.setView(120, 120, 2, 22, -60, 82, 0, 0);            
            shiplist[id].view2.setView(180, 81, 2, 27, 0, 78, 0, 3);
            shiplist[id].view3.setView(10.391443415653953, 306.6535915090588, 2, 17.313373543631496, -164.00028239704363, 82.23923978923972, -2.561698254317753e-11, 0);
            shiplist[id].view4.setView(0, 100, 2, 380, 270, 0, 0, 0);            
            break;
        }
        //Queen Mary 2
        case 3: {
            shiplist[id].model.getLocation().setLatLngAlt(51.90212631225586, 4.456078052520752, -10);
            shiplist[id].heading = -108.14793881836286;
            shiplist[id].engineSoundRange = 1400;
            shiplist[id].mechanicSoundRange = 1200;
            shiplist[id].hornSoundRange = 5000;
            shiplist[id].anchorSound = 'anchor';
            shiplist[id].hornSound = 'qm2horn';
            shiplist[id].hornEndSound = 'qm2hornend';
            shiplist[id].shadowImageURL = masterHost + 'images/shipshadow.png'; 
            shiplist[id].camAlt = 40;            
            shiplist[id].shadowOffset = 15;
            shiplist[id].shadowAngle = 90;
            shiplist[id].shadowWidth = 100;
            shiplist[id].shadowLength = 400;
            shiplist[id].wakeOffset = 120;
            shiplist[id].bowOffset = -150;
            shiplist[id].draft = -10;          
            shiplist[id].mass = 10000;
            shiplist[id].turnFriction = 0.08;
            shiplist[id].turnInertia = 800;
            shiplist[id].moveFriction = 0.0013;
            shiplist[id].potentialEnginePower = 3000;
            shiplist[id].rollEffect = 0.6;
            shiplist[id].pitchEffect = 0.3;          
            shiplist[id].setFuelCapacity(48);            
            shiplist[id].wakeImageURL = masterHost + 'images/wake.png';
            shiplist[id].wakeSize = 20;
            shiplist[id].bowImageURL = masterHost + 'images/wake.png';
            shiplist[id].bowSize = 10;      
            shiplist[id].view1.setView(393.52748010991206, 322.8278942649891, 2, 97.72366843191458, 225.14623217688057, 76.34975556523324, -5.050402778695918e-11, 0);
            shiplist[id].view2.setView(180, 268, 2, 87, 0, 77.2, 0, 3);
            shiplist[id].view3.setView(342.6469969949441, 786.8743790841307, 2, 57.52751455518372, 165.58067290409164, 81.22932176974987, 0.00041233379490197153, 0);          
            shiplist[id].view4.setView(0, 200, 2, 780, 270, 0, 0, 0);            
            break;
        }
        //emma maersk
        case 6: {
            shiplist[id].model.getLocation().setLatLngAlt(51.959041595458984, 4.055246353149414, -20);
            shiplist[id].heading = 83;
            shiplist[id].engineSoundRange = 1400;
            shiplist[id].mechanicSoundRange = 1200;
            shiplist[id].hornSoundRange = 5000;
            shiplist[id].anchorSound = 'anchor';
            shiplist[id].hornSound = 'qm2horn';
            shiplist[id].hornEndSound = 'qm2hornend';
            shiplist[id].shadowImageURL = masterHost + 'images/shipshadow.png'; 
            shiplist[id].camAlt = 40;            
            shiplist[id].shadowOffset = 19;
            shiplist[id].shadowAngle = 90;
            shiplist[id].shadowWidth = 130;
            shiplist[id].shadowLength = 450;
            shiplist[id].wakeOffset = 180;
            shiplist[id].bowOffset = -180;
            shiplist[id].draft = -20;          
            shiplist[id].mass = 10000;
            shiplist[id].turnFriction = 0.08;
            shiplist[id].turnInertia = 800;
            shiplist[id].moveFriction = 0.0013;
            shiplist[id].potentialEnginePower = 3750;
            shiplist[id].rollEffect = 0.6;
            shiplist[id].pitchEffect = 0.3;          
            shiplist[id].setFuelCapacity(48);            
            shiplist[id].wakeImageURL = masterHost + 'images/wake.png';
            shiplist[id].wakeSize = 35;
            shiplist[id].bowImageURL = masterHost + 'images/wake.png';
            shiplist[id].bowSize = 10;      
            shiplist[id].view1.setView(138.2363238759764, 513.2861467166317, 2, 178.67343718769908, -45.190683681212704, 72.34709756758059, -0.0007924543817579549, 0);
            shiplist[id].view2.setView(180, 339.4296584700688, 2, 142.64209649711154, 0, 79.2000000002516, 0, 3);
            shiplist[id].view3.setView(342.6469969949441, 786.8743790841307, 2, 57.52751455518372, 165.58067290409164, 81.22932176974987, 0.00041233379490197153, 0);          
            shiplist[id].view4.setView(0, 300, 2, 1200, 270, 0, 0, 0);            
            break;
        }      
        //Hindenburg  
        case 4: {
            shiplist[id].model.getLocation().setLatLngAlt(51.90673828125, 4.469770431518555, 300);
            shiplist[id].heading = -164.83940853167252;
            shiplist[id].engineSoundRange = 2000;
            shiplist[id].mechanicSoundRange = 700;
            shiplist[id].hornSoundRange = 4000;
            shiplist[id].anchorSound = '';
            shiplist[id].hornSound = 'smallhorn';
            shiplist[id].hornEndSound = 'smallhornend';            
            shiplist[id].shadowImageURL = masterHost + 'images/airshipshadow.png'; 
            shiplist[id].camAlt = -20;            
            shiplist[id].shadowOffset = 70;
            shiplist[id].shadowAngle = 90;
            shiplist[id].shadowWidth = 82;
            shiplist[id].shadowLength = 345;
            shiplist[id].wakeOffset = 130;
            shiplist[id].bowOffset = -150;
            shiplist[id].draft = 300;
            shiplist[id].mass = 2000;
            shiplist[id].turnFriction = 0.08;
            shiplist[id].turnInertia = 400;
            shiplist[id].moveFriction = 0.001;
            shiplist[id].potentialEnginePower = 1500;
            shiplist[id].rollEffect = 0.2;
            shiplist[id].pitchEffect = 0.1;         
            shiplist[id].setFuelCapacity(12);
            shiplist[id].wakeImageURL = '';
            shiplist[id].wakeSize = 20;
            shiplist[id].bowImageURL = '';
            shiplist[id].bowSize = 10;            
            shiplist[id].view1.setView(271.1687231586606, 358.7146054760826, 2, 106.32660146562364, 72.70705793515486, 65.69607306264668, -0.0022853927577132023, 0);
            shiplist[id].view2.setView(180, 320, 2, 8, 0, 81, 0, 0);
            shiplist[id].view3.setView(17.205419111008723, 736.7454120158269, 2, 19.99992673035723, -149.99927416968805, 80.99999999989565, 2.293563182174312e-9, 0);
            shiplist[id].view4.setView(0, 300, 2, 1400, 270, 0, 0, 0);            
            break;
        }        
    }
}

function setMouseUp(event){
    var INSET_PIXELS_X = document.getElementById("map3d").offsetWidth - event.getClientX();
    var INSET_PIXELS_Y = event.getClientY();
    //click in viewmode area
    if (INSET_PIXELS_Y < 65) {
        if (INSET_PIXELS_X<277){
            if (INSET_PIXELS_X>103){viewMode = 3;}
            if (INSET_PIXELS_X>146){viewMode = 2;}
            if (INSET_PIXELS_X>192){viewMode = 1;}
            if (INSET_PIXELS_X>236){viewMode = 0;}
            setViewMode(viewMode);
        }
        //We assume the View is manually changed. Recalculate the spot view range if spot view is used
    }
    //determine click on help tab
    if (event.getButton() == 0){ //only if left mouse button
        if (event.getClientX() < helpRight + 20){
            if (event.getClientY() < 510) {toggleHelp();}
        }
    }
    currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE); 
    headTilt = currentCam.getTilt();
    headHeading = 0;
    headCamHeading = currentCam.getHeading();   
    
    if (viewMode==2){ spotDistanceRange = 0;}
    window.focus();
    mouseIsDown = false;
}

function exploreobject(object){
	alert(object);
    	if (object && object.hasChildNodes()) {
		var childNodes = object.getChildNodes();
		var numChildNodes = childNodes.getLength();
		for (var i = 0; i < numChildNodes; i++) {
			var child = childNodes.item(i);
			if (!exploreobject(child))
			          return false;
			}
	return true;
	}
}

function setMouseDown(event){
    currentCam.setAltitudeMode(ge.ALTITUDE_RELATIVE_TO_GROUND);
   mouseIsDown = true;
}

function setMouseMove(event){
    if (event.getShiftKey()) {
        switch (viewMode){
            case 3:{
                headHeading = ((event.getClientX() / document.getElementById("map3d").offsetWidth) - 0.5)*360;
                headTilt =  90 - ((event.getClientY() / document.getElementById("map3d").offsetHeight) - 0.5) * 180;
                break;
            }
        }
    }
    else if (event.getButton() != -1){
        currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE); 
        headCamHeading = currentCam.getHeading();
    }
}

function showTypeName(node, arguments){
    alert(node.getType());
}

function updateLow(deltaTime){
    fuelNeedle.setRotation(360 - myship.fuel * 90);
    if (myship.fuel <= 0) { engineSound.engineStop();}
    if (showBanner == true){     
        if (bannerTimeOut == 1) {presentingBanner.setVisibility(false); showBanner = false; toggleHelp();}
        else bannerTimeOut += 1;
    }
}

function moveship() {
    //if (engineLoopFinished = true){ soundmanager.play('engine'); engineLoopFinished = false;}
    //measure frame time so animation is frame independant
    now = (new Date()).getTime();
    var deltaTime = (now - lastMill) / 1000.0;
    lastMill = now;
    lowUpdate += deltaTime;

    if (lowUpdate > 10){ updateLow(lowUpdate); lowUpdate = 0;}
    //animate rolling and pitching of the ship
    if (doPerformance == true){
        frameSampleTime += deltaTime;
        if (frameSampleTime < 30){
            frames[frameCount] = deltaTime;
            frameCount += 1;
        }
        else{
            document.title = applicationTitle;
            
            var mydata = '';
            var myTimes = '';
            var totalTime = 0;
            for (var i = 0; i < frames.length; i++) {
                myTimes += frames[i] + '<br/>';
                totalTime += frames[i]
            }
            mydata += 'Tot time: ' + totalTime + '<br/>';
            mydata += 'Tot sample: ' + frames.length + '<br/>';
            mydata += 'Avg time: ' + (totalTime/frames.length) + '<br/>';     
            mydata += 'Avg Fps: ' + (frames.length/totalTime) + '<br/>';
            mydata += 'Frame times:<br/>';
            mydata += myTimes;
            document.getElementById('info').innerHTML = mydata;
            frames.length = 0;
            frameCount = 0;
            frameSampleTime = 0;
            doPerformance = false;
        }
    }



    var speedRollEffect = (myship.speed/30) + 0.2;
    speedRollEffect *= myship.rollEffect;
    if (speedRollEffect>3){speedRollEffect=3;}
    roll1 += (1 * deltaTime);
    if (roll1 > radianCircle) { roll1 -= radianCircle;}
    pitch1 += (0.8* deltaTime);
    if (pitch1 > radianCircle) { pitch1 -= radianCircle;}
    var rollCos = Math.sin(roll1);
    myship.model.getOrientation().setTilt(rollCos * speedRollEffect);
    myship.model.getOrientation().setRoll(Math.sin(pitch1) * 0.5 * myship.pitchEffect);

    //pulse the pause sign if pause is on
    if (togglePauseState == true){pauseIcon.getColor().setA(rollCos * 256);}

    //handle key presses
    if (upArrow == true) {
        if (Math.abs(myship.rightPowerValue - myship.leftPowerValue) < 0.05) {myship.rightPowerValue += 0.3*deltaTime; myship.leftPowerValue += 0.3*deltaTime;}
        if (myship.rightPowerValue<myship.leftPowerValue) {myship.rightPowerValue += 0.3*deltaTime;}
        if (myship.leftPowerValue<myship.rightPowerValue) {myship.leftPowerValue += 0.3*deltaTime;}
        leftPowerControl.f_setValue(myship.leftPowerValue);        
        rightPowerControl.f_setValue(myship.rightPowerValue);
    } else if (downArrow == true) {
	   if (Math.abs(myship.rightPowerValue - myship.leftPowerValue) < 0.05) {myship.rightPowerValue -= 0.3*deltaTime; myship.leftPowerValue -= 0.3*deltaTime;}
       if (myship.rightPowerValue>myship.leftPowerValue) {myship.rightPowerValue -= 0.3*deltaTime;}
       if (myship.leftPowerValue>myship.rightPowerValue) {myship.leftPowerValue -= 0.3*deltaTime;}
       leftPowerControl.f_setValue(myship.leftPowerValue);        
       rightPowerControl.f_setValue(myship.rightPowerValue);        
    } else if (leftpowerupkey == true) {
        myship.leftPowerValue += 0.3*deltaTime;
        leftPowerControl.f_setValue(myship.leftPowerValue);
    } else if (leftpowerdownkey == true) {
        myship.leftPowerValue -= 0.3*deltaTime;
        leftPowerControl.f_setValue(myship.leftPowerValue);
    } else if (rightpowerupkey == true) {
        myship.rightPowerValue += 0.3*deltaTime;
        rightPowerControl.f_setValue(myship.rightPowerValue);
    } else if (rightpowerdownkey == true) {
        myship.rightPowerValue -= 0.3*deltaTime;
        rightPowerControl.f_setValue(myship.rightPowerValue);
    } 
  
    if (myship.leftPowerValue > 1){myship.leftPowerValue = 1;}
    if (myship.leftPowerValue < -0.4){myship.leftPowerValue = -0.4;}
    if (myship.rightPowerValue > 1){myship.rightPowerValue = 1;}
    if (myship.rightPowerValue < -0.4){myship.rightPowerValue = -0.4;}

    if (leftbowthrust == true){ bowthrust -= 0.4*deltaTime;}
    if (rightbowthrust == true){ bowthrust += 0.4*deltaTime;}
    if (bowthrust >= 1){bowthrust = 1;}
    if (bowthrust < -1){bowthrust = -1;}
    //do something with bowthrust later

    //animate help panel
    if (Math.round(helpPad.getOverlayXY().getX()) != helpRight){
        helpPad.getOverlayXY().setX(helpPad.getOverlayXY().getX() - (helpPad.getOverlayXY().getX() - helpRight)* deltaTime * 10);
    }

    map.setCenter(new GLatLng(myship.model.getLocation().getLatitude(), myship.model.getLocation().getLongitude()));

    //generically used camera position data. Provides info for sound distance and position.
    camBearingDistanceTilt = getBearingDistanceTilt(currentCam,myship);
    //update controls
    if (togglePauseState == false) {
        updateSpeedIndicator();
        rudderTargetNeedle.setRotation(myship.rudderTarget);
        compassIndicator.setRotation(myship.heading);
        rudderNeedle.setRotation(myship.rudderCurrent);
        wheel.setRotation(myship.rudderCurrent * -6);
        turnRateIndicator.setRotation(turnRateIndicator.getRotation() - (myship.turnRate * 400 * deltaTime));
        myship.update(deltaTime);    
    }
    updateView(viewMode, deltaTime);
    
    updateEngineAudio();
    //handleGroundCollision(deltaTime);
}

function handleGroundCollision(deltaTime){
    var wakeAltitude = ge.getGlobe().getGroundAltitude(myship.wakePoint.latitude, myship.wakePoint.longitude);  
    if (wakeAltitude > waterLevel){
        setLatLonBoxAsMeters(collidedStern.getLatLonBox(),myship.wakePoint.latitude,myship.wakePoint.longitude,myship.shadowWidth,myship.shadowWidth,0); 
        collidedStern.setVisibility(true);
    }
    else {
        collidedStern.setVisibility(false);
    }
    var bowAltitude = ge.getGlobe().getGroundAltitude(myship.bowPoint.latitude, myship.bowPoint.longitude);
    if (bowAltitude > waterLevel){
        setLatLonBoxAsMeters(collidedBow.getLatLonBox(),myship.bowPoint.latitude,myship.bowPoint.longitude,myship.shadowWidth,myship.shadowWidth,0); 
        collidedBow.setVisibility(true);
    }
    else {
        collidedBow.setVisibility(false);
    }
    waterLevel += (Math.max(bowAltitude, wakeAltitude)/2 - waterLevel) * deltaTime; //adjust waterlevel to average of stern and bow over 10 seconds.
    if (waterLevel < 0){waterLevel = 0;}
}

function updateSpeedIndicator(){
    var mySpeed = Math.abs(myship.speed);
    var handleCase = Math.round((mySpeed/5) + 0.5) - 1;
    switch (handleCase){
        case 0: {dialCalibration = mySpeed * 18; break;}
        case 1: {dialCalibration = 90 + (mySpeed - 5) * 11.4; break;}
        case 2: {dialCalibration = 147 + (mySpeed - 10) * 8.6; break;}
        case 3: {dialCalibration = 190 + (mySpeed - 15) * 6.1; break;}
        case 4: {dialCalibration = 220 + (mySpeed - 20) * 5.4; break;}
        case 5: {dialCalibration = 250 + (mySpeed - 25) * 5.2; break;}
        case 6: {dialCalibration = 277 + (mySpeed - 30) * 5.1; break;}
    }
    speedNeedle.setRotation(360 - dialCalibration);
}

function setViewMode(viewModeID){
    viewModeIndex = viewModeID;
    viewMode = viewModeID;
}

function setDefaultView(){
    ge.getOptions().setFlyToSpeed(1);
    //ge.getOptions().setFlyToSpeed(ge.SPEED_TELEPORT);
    ge.getNavigationControl().setVisibility(ge.VISIBILITY_SHOW);
    viewMenu.getOverlayXY().setX(282);
    currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    ge.getView().setAbstractView(currentCam);  
}

function setFollowView(){
    ge.getOptions().setFlyToSpeed(ge.SPEED_TELEPORT);
    ge.getNavigationControl().setVisibility(ge.VISIBILITY_HIDE);
    viewMenu.getOverlayXY().setX(237);
    currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    ge.getView().setAbstractView(currentCam);  
}

function setSpotView(){
    ge.getOptions().setFlyToSpeed(ge.SPEED_TELEPORT);
    ge.getNavigationControl().setVisibility(ge.VISIBILITY_HIDE);
    viewMenu.getOverlayXY().setX(191);
    currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    spotDistanceRange = 0;
    ge.getView().setAbstractView(currentCam);  
}

function setHeadView(){
    ge.getOptions().setFlyToSpeed(ge.SPEED_TELEPORT);
    viewMenu.getOverlayXY().setX(146);
    ge.getNavigationControl().setVisibility(ge.VISIBILITY_HIDE);
    currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    headTilt = currentCam.getTilt();
    ge.getView().setAbstractView(currentCam);  
}

function updateEngineAudio(){
    if (engineMute == false){
        var relativeBearing = currentCam.getHeading() - camBearingDistanceTilt.bearing;
        if (relativeBearing<-180){relativeBearing += 360}
        var newVolume = (camBearingDistanceTilt.distance / myship.engineSoundRange);
        newVolume *= newVolume;
        if (newVolume > 1){newVolume = 1;}
        newVolume = (1-newVolume) * 30;
        engineSound.engineVolume(newVolume);
        var ll = Math.abs(0.5 + Math.sin(relativeBearing * degreesToRad)/2)*100;
        var rr = 100 - ll;
        engineSound.engineTransform(ll,ll,rr,rr);
    }
}

function updateView(viewMode, deltaTime){
    currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    if (viewModeIndex != -1){
        viewModeIndex = -1;
        switch(viewMode){
            case 0: {setDefaultView(); break;}
            case 1: {setFollowView(); break;}
            case 2: {setSpotView(); break;}
            case 3: {setHeadView(); break;}
        }
    }
    if (newView != null){
        var location = getBDLocation(myship.model.getLocation(), myship.heading + newView.bearing, newView.distance);
        currentCam.setLatitude(location.latitude);
        currentCam.setLongitude(location.longitude);    
        currentCam.setAltitudeMode(newView.altitudeMode);
        currentCam.setAltitude(myship.altitude + newView.altitude + myship.draft);
        currentCam.setHeading(myship.heading + newView.heading);
        currentCam.setTilt(newView.tilt);
        currentCam.setRoll(newView.roll);
        headCamHeading = myship.heading + newView.heading;
        headHeading = 0;
        headTilt = newView.tilt;
        ge.getView().setAbstractView(currentCam);
        newView = null;   
        spotDistanceRange = 0;     
    } 
    else
    { 
        if (mouseIsDown == false){
            switch(viewMode){
                case 0: {updateGoogleView(); break;}
                case 1: {updateFollowView(); break;}
                case 2: {updateSpotView(); break;}
                case 3: {updateHeadView(deltaTime); break;}
            }
        }
    }
}

function updateGoogleView(){
    //currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
}

function updateFollowView(){
  //currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
  currentCam.setLatitude(currentCam.getLatitude() + myship.latstep);
  currentCam.setLongitude(currentCam.getLongitude() + myship.longstep);
  currentCam.setAltitude(currentCam.getAltitude() + myship.deltaAltitude);
  ge.getView().setAbstractView(currentCam);
}

function updateSpotView(){
  //currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
  var camdata = getBearingDistanceTilt(currentCam,myship);
  if (spotDistanceRange == 0){spotDistanceRange = camdata.distance * 3;}
  //update spot cam location if distance is to great
  if (camdata.distance > spotDistanceRange){
    //make up a new location ahead of the movement direction
    var newRange = (Math.random() * spotDistanceRange * 0.5) + (spotDistanceRange * 0.5);
    var location = getBDLocation(myship.model.getLocation(), myship.track + (Math.random() * 120)-60, newRange);
//alert('i was coding a cutoff distance here');
    //distanceCutOff = location.distance * Math.random()*
    currentCam.setLatitude(location.latitude);
    currentCam.setLongitude(location.longitude);
    currentCam.setAltitude(Math.random()*(spotDistanceRange/4)+5+myship.altitude);
  }
  else
  {
      currentCam.setHeading(camdata.bearing);
      currentCam.setTilt(camdata.tilt);
      currentCam.setRoll(0);
  }
  ge.getView().setAbstractView(currentCam);
}

function updateHeadView(deltaTime){
  //currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
  var location = rotateLocationAround(currentCam, myship.model.getLocation(),myship.deltaHeading);
  currentCam.setLatitude(location.latitude + myship.latstep);
  currentCam.setLongitude(location.longitude + myship.longstep);
  currentCam.setAltitude(currentCam.getAltitude() + myship.deltaAltitude);
  //headHeading += myship.deltaHeading;
  headCamHeading += myship.deltaHeading;
  var heading = headCamHeading + headHeading;
  if (heading > 360){heading -= 360} 
  if (heading < 0){heading += 360}
  var deltaHeading = heading - currentCam.getHeading();
  if (deltaHeading > 180){deltaHeading -= 360} 
  if (deltaHeading < -180){deltaHeading += 360}  
  heading = currentCam.getHeading() + deltaHeading * deltaTime * 4  
  currentCam.setHeading(heading);
  currentCam.setTilt(currentCam.getTilt() + (headTilt - currentCam.getTilt()) * deltaTime * 4);
  ge.getView().setAbstractView(currentCam);
}



function createViewMenu() {

// create an image for the screen overlay
var icon = ge.createIcon('');
icon.setHref(masterHost + 'images/views.png');

// create the screen overlay
var screenOverlay = ge.createScreenOverlay('');
screenOverlay.setDrawOrder(11);
screenOverlay.setIcon(icon);

// Set the point inside the overlay that is used as the positioning
// anchor point.
screenOverlay.getScreenXY().setXUnits(ge.UNITS_FRACTION);
screenOverlay.getScreenXY().setYUnits(ge.UNITS_FRACTION);
screenOverlay.getScreenXY().setX(1);
screenOverlay.getScreenXY().setY(1);

screenOverlay.getOverlayXY().setXUnits(ge.UNITS_INSET_PIXELS);
screenOverlay.getOverlayXY().setYUnits(ge.UNITS_INSET_PIXELS);
screenOverlay.getOverlayXY().setX(100);
screenOverlay.getOverlayXY().setY(20);

// Set object's size in pixels.
screenOverlay.getSize().setXUnits(ge.UNITS_PIXELS);
screenOverlay.getSize().setYUnits(ge.UNITS_PIXELS);
screenOverlay.getSize().setX(180);
screenOverlay.getSize().setY(52);

// add the screen overlay to Earth
ge.getFeatures().appendChild(screenOverlay);
}

function createViewMenuSelected() {

// create an image for the screen overlay
var icon = ge.createIcon('');
icon.setHref(masterHost + 'images/selectedview.png');

// create the screen overlay
viewMenu = ge.createScreenOverlay('');
viewMenu.setDrawOrder(12);
viewMenu.setIcon(icon);

// Set the point inside the overlay that is used as the positioning
// anchor point.
viewMenu.getScreenXY().setXUnits(ge.UNITS_FRACTION);
viewMenu.getScreenXY().setYUnits(ge.UNITS_FRACTION);
viewMenu.getScreenXY().setX(0);
viewMenu.getScreenXY().setY(1);

viewMenu.getOverlayXY().setXUnits(ge.UNITS_INSET_PIXELS);
viewMenu.getOverlayXY().setYUnits(ge.UNITS_INSET_PIXELS);
viewMenu.getOverlayXY().setX(282);
viewMenu.getOverlayXY().setY(12);

// Set object's size in pixels.
viewMenu.getSize().setXUnits(ge.UNITS_PIXELS);
viewMenu.getSize().setYUnits(ge.UNITS_PIXELS);
viewMenu.getSize().setX(45);
viewMenu.getSize().setY(6);

// add the screen overlay to Earth
ge.getFeatures().appendChild(viewMenu);
}

function createPauseIcon() {
// create an image for the screen overlay
var icon = ge.createIcon('');
icon.setHref(masterHost + 'images/paused.png');

// create the screen overlay
pauseIcon = ge.createScreenOverlay('');
pauseIcon.setDrawOrder(10);
pauseIcon.setIcon(icon);

// Set the point inside the overlay that is used as the positioning
// anchor point.
pauseIcon.getOverlayXY().setXUnits(ge.UNITS_FRACTION);
pauseIcon.getOverlayXY().setYUnits(ge.UNITS_FRACTION);
pauseIcon.getOverlayXY().setX(0.5);
pauseIcon.getOverlayXY().setY(0.5);

pauseIcon.getScreenXY().setXUnits(ge.UNITS_FRACTION);
pauseIcon.getScreenXY().setYUnits(ge.UNITS_FRACTION);
pauseIcon.getScreenXY().setX(0.5);
pauseIcon.getScreenXY().setY(0.5);

// Set object's size in pixels.
pauseIcon.getSize().setXUnits(ge.UNITS_PIXELS);
pauseIcon.getSize().setYUnits(ge.UNITS_PIXELS);
pauseIcon.getSize().setX(253);
pauseIcon.getSize().setY(88);

pauseIcon.setVisibility(false);

// Rotate by a random number of degrees.
//screenOverlay.setRotation(Math.random() * 360);

// add the screen overlay to Earth
ge.getFeatures().appendChild(pauseIcon);
}

function createPresentingBanner() {
// create an image for the screen overlay
var icon = ge.createIcon('');
icon.setHref(masterHost + 'images/presenting2.png');

// create the screen overlay
presentingBanner = ge.createScreenOverlay('');
presentingBanner.setDrawOrder(10);
presentingBanner.setIcon(icon);

// Set the point inside the overlay that is used as the positioning
// anchor point.
presentingBanner.getOverlayXY().setXUnits(ge.UNITS_FRACTION);
presentingBanner.getOverlayXY().setYUnits(ge.UNITS_FRACTION);
presentingBanner.getOverlayXY().setX(0.5);
presentingBanner.getOverlayXY().setY(0.5);

presentingBanner.getScreenXY().setXUnits(ge.UNITS_FRACTION);
presentingBanner.getScreenXY().setYUnits(ge.UNITS_FRACTION);
presentingBanner.getScreenXY().setX(0.5);
presentingBanner.getScreenXY().setY(0.2);

// Set object's size in pixels.
presentingBanner.getSize().setXUnits(ge.UNITS_PIXELS);
presentingBanner.getSize().setYUnits(ge.UNITS_PIXELS);
presentingBanner.getSize().setX(760);
presentingBanner.getSize().setY(176);

presentingBanner.setVisibility(true);

// Rotate by a random number of degrees.
//screenOverlay.setRotation(Math.random() * 360);

// add the screen overlay to Earth
ge.getFeatures().appendChild(presentingBanner);
}

function createPanel() {

// create an image for the screen overlay
var icon = ge.createIcon('');
icon.setHref(masterHost + 'images/wood/tab.png');

// create the screen overlay
var screenOverlay = ge.createScreenOverlay('');
screenOverlay.setDrawOrder(10);
screenOverlay.setIcon(icon);

// Set the point inside the overlay that is used as the positioning
// anchor point.
screenOverlay.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
screenOverlay.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
screenOverlay.getOverlayXY().setX(0);
screenOverlay.getOverlayXY().setY(0);

screenOverlay.getScreenXY().setXUnits(ge.UNITS_PIXELS);
screenOverlay.getScreenXY().setYUnits(ge.UNITS_PIXELS);
screenOverlay.getScreenXY().setX(1);
screenOverlay.getScreenXY().setY(0);

// Set object's size in pixels.
screenOverlay.getSize().setXUnits(ge.UNITS_PIXELS);
screenOverlay.getSize().setYUnits(ge.UNITS_PIXELS);
screenOverlay.getSize().setX(429);
screenOverlay.getSize().setY(138);

// Rotate by a random number of degrees.
//screenOverlay.setRotation(Math.random() * 360);

// add the screen overlay to Earth
ge.getFeatures().appendChild(screenOverlay);
}

function createTurnRateGauge(x,y) {
    // create an image for the screen overlay
    var icon = ge.createIcon('');
    icon.setHref(masterHost + 'images/turnrategauge.png');

    // create the screen overlay
    var overlay = ge.createScreenOverlay('');
    overlay.setDrawOrder(22);
    overlay.setIcon(icon);

    // anchor point
    overlay.getScreenXY().setXUnits(ge.UNITS_FRACTION);
    overlay.getScreenXY().setYUnits(ge.UNITS_FRACTION);
    overlay.getScreenXY().setX(0.5);
    overlay.getScreenXY().setY(0.5);
    //screen point
    overlay.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
    overlay.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
    overlay.getOverlayXY().setX(x);
    overlay.getOverlayXY().setY(y);

    // Set object's size in pixels.
    overlay.getSize().setXUnits(ge.UNITS_PIXELS);
    overlay.getSize().setYUnits(ge.UNITS_PIXELS);
    overlay.getSize().setX(63);
    overlay.getSize().setY(62);

    // add the screen overlay to Earth
    ge.getFeatures().appendChild(overlay);

    // create an image for the screen overlay
    var icon = ge.createIcon('');
    icon.setHref(masterHost + 'images/turnrateneedle.png');

    // create the screen overlay
    turnRateIndicator = ge.createScreenOverlay('');
    turnRateIndicator.setDrawOrder(20);
    turnRateIndicator.setIcon(icon);

    // anchor point
    turnRateIndicator.getScreenXY().setXUnits(ge.UNITS_FRACTION);
    turnRateIndicator.getScreenXY().setYUnits(ge.UNITS_FRACTION);
    turnRateIndicator.getScreenXY().setX(0.5);
    turnRateIndicator.getScreenXY().setY(0.5);
    //screen point
    turnRateIndicator.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
    turnRateIndicator.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
    turnRateIndicator.getOverlayXY().setX(x);
    turnRateIndicator.getOverlayXY().setY(y);

    // Rotate around this center point relative to object.
    turnRateIndicator.getRotationXY().setXUnits(ge.UNITS_FRACTION);
    turnRateIndicator.getRotationXY().setYUnits(ge.UNITS_FRACTION);
    turnRateIndicator.getRotationXY().setX(0.5);
    turnRateIndicator.getRotationXY().setY(0.5);
    
    // Set object's size in pixels.
    turnRateIndicator.getSize().setXUnits(ge.UNITS_PIXELS);
    turnRateIndicator.getSize().setYUnits(ge.UNITS_PIXELS);
    turnRateIndicator.getSize().setX(55);
    turnRateIndicator.getSize().setY(55);
    
    // add the screen overlay to Earth
    ge.getFeatures().appendChild(turnRateIndicator);
}

function createRudderCompassGauge(x,y) {
    var icon = ge.createIcon('');
    icon.setHref(masterHost + 'images/ruddercompassdisc.png');
    compassIndicator = ge.createScreenOverlay('');
    compassIndicator.setDrawOrder(20);
    compassIndicator.setIcon(icon);
    compassIndicator.getScreenXY().setXUnits(ge.UNITS_FRACTION);
    compassIndicator.getScreenXY().setYUnits(ge.UNITS_FRACTION);
    compassIndicator.getScreenXY().setX(0.5);
    compassIndicator.getScreenXY().setY(0.5);
    compassIndicator.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
    compassIndicator.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
    compassIndicator.getOverlayXY().setX(x);
    compassIndicator.getOverlayXY().setY(y);
    compassIndicator.getRotationXY().setXUnits(ge.UNITS_FRACTION);
    compassIndicator.getRotationXY().setYUnits(ge.UNITS_FRACTION);
    compassIndicator.getRotationXY().setX(0.5);
    compassIndicator.getRotationXY().setY(0.5);    
    compassIndicator.getSize().setXUnits(ge.UNITS_PIXELS);
    compassIndicator.getSize().setYUnits(ge.UNITS_PIXELS);
    compassIndicator.getSize().setX(115);
    compassIndicator.getSize().setY(116);
    ge.getFeatures().appendChild(compassIndicator);

    icon = ge.createIcon('');
    icon.setHref(masterHost + 'images/ruddercompasback.png');
    var overlay = ge.createScreenOverlay('');
    overlay.setDrawOrder(21);
    overlay.setIcon(icon);
    overlay.getScreenXY().setXUnits(ge.UNITS_FRACTION);
    overlay.getScreenXY().setYUnits(ge.UNITS_FRACTION);
    overlay.getScreenXY().setX(0.5);
    overlay.getScreenXY().setY(1);
    overlay.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
    overlay.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
    overlay.getOverlayXY().setX(x);
    overlay.getOverlayXY().setY(y);
    overlay.getSize().setXUnits(ge.UNITS_PIXELS);
    overlay.getSize().setYUnits(ge.UNITS_PIXELS);
    overlay.getSize().setX(115);
    overlay.getSize().setY(59);
    ge.getFeatures().appendChild(overlay);

    icon = ge.createIcon('');
    icon.setHref(masterHost + 'images/ruddercompasrpos.png');
    rudderNeedle = ge.createScreenOverlay('');
    rudderNeedle.setDrawOrder(22);
    rudderNeedle.setIcon(icon);
    rudderNeedle.getScreenXY().setXUnits(ge.UNITS_FRACTION);
    rudderNeedle.getScreenXY().setYUnits(ge.UNITS_FRACTION);
    rudderNeedle.getScreenXY().setX(0.38);
    rudderNeedle.getScreenXY().setY(1);
    rudderNeedle.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
    rudderNeedle.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
    rudderNeedle.getOverlayXY().setX(x-1);
    rudderNeedle.getOverlayXY().setY(y);
    rudderNeedle.getRotationXY().setXUnits(ge.UNITS_FRACTION);
    rudderNeedle.getRotationXY().setYUnits(ge.UNITS_FRACTION);
    rudderNeedle.getRotationXY().setX(0.38);
    rudderNeedle.getRotationXY().setY(1);
    rudderNeedle.getSize().setXUnits(ge.UNITS_PIXELS);
    rudderNeedle.getSize().setYUnits(ge.UNITS_PIXELS);
    rudderNeedle.getSize().setX(18);
    rudderNeedle.getSize().setY(47);
    ge.getFeatures().appendChild(rudderNeedle);

    var icon = ge.createIcon('');
    icon.setHref(masterHost + 'images/ruddercompasrtarget.png');
    rudderTargetNeedle = ge.createScreenOverlay('');
    rudderTargetNeedle.setDrawOrder(23);
    rudderTargetNeedle.setIcon(icon);
    rudderTargetNeedle.getScreenXY().setXUnits(ge.UNITS_FRACTION);
    rudderTargetNeedle.getScreenXY().setYUnits(ge.UNITS_FRACTION);
    rudderTargetNeedle.getScreenXY().setX(0.38);
    rudderTargetNeedle.getScreenXY().setY(1);
    rudderTargetNeedle.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
    rudderTargetNeedle.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
    rudderTargetNeedle.getOverlayXY().setX(x-1);
    rudderTargetNeedle.getOverlayXY().setY(y);
    rudderTargetNeedle.getRotationXY().setXUnits(ge.UNITS_FRACTION);
    rudderTargetNeedle.getRotationXY().setYUnits(ge.UNITS_FRACTION);
    rudderTargetNeedle.getRotationXY().setX(0.38);
    rudderTargetNeedle.getRotationXY().setY(1);
    rudderTargetNeedle.getSize().setXUnits(ge.UNITS_PIXELS);
    rudderTargetNeedle.getSize().setYUnits(ge.UNITS_PIXELS);
    rudderTargetNeedle.getSize().setX(18);
    rudderTargetNeedle.getSize().setY(47);
    ge.getFeatures().appendChild(rudderTargetNeedle);

    icon = ge.createIcon('');
    icon.setHref(masterHost + 'images/ruddercompasgauge.png');
    var overlay = ge.createScreenOverlay('');
    overlay.setDrawOrder(24);
    overlay.setIcon(icon);
    overlay.getScreenXY().setXUnits(ge.UNITS_FRACTION);
    overlay.getScreenXY().setYUnits(ge.UNITS_FRACTION);
    overlay.getScreenXY().setX(0.5);
    overlay.getScreenXY().setY(0.5);
    overlay.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
    overlay.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
    overlay.getOverlayXY().setX(x);
    overlay.getOverlayXY().setY(y);
    overlay.getSize().setXUnits(ge.UNITS_PIXELS);
    overlay.getSize().setYUnits(ge.UNITS_PIXELS);
    overlay.getSize().setX(125);
    overlay.getSize().setY(125);
    ge.getFeatures().appendChild(overlay);
}

function createSpeedGauge(x,y) {
    // create an image for the screen overlay
    var icon = ge.createIcon('');
    icon.setHref(masterHost + 'images/speedgauge.png');

    // create the screen overlay
    var overlay = ge.createScreenOverlay('');
    overlay.setDrawOrder(22);
    overlay.setIcon(icon);

    // anchor point
    overlay.getScreenXY().setXUnits(ge.UNITS_FRACTION);
    overlay.getScreenXY().setYUnits(ge.UNITS_FRACTION);
    overlay.getScreenXY().setX(0.5);
    overlay.getScreenXY().setY(0.5);
    //screen point
    overlay.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
    overlay.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
    overlay.getOverlayXY().setX(x);
    overlay.getOverlayXY().setY(y);

    // Set object's size in pixels.
    overlay.getSize().setXUnits(ge.UNITS_PIXELS);
    overlay.getSize().setYUnits(ge.UNITS_PIXELS);
    overlay.getSize().setX(125);
    overlay.getSize().setY(125);

    // add the screen overlay to Earth
    ge.getFeatures().appendChild(overlay);

    // create an image for the screen overlay
    var icon = ge.createIcon('');
    icon.setHref(masterHost + 'images/speedneedle.png');

    // create the screen overlay
    speedNeedle = ge.createScreenOverlay('');
    speedNeedle.setDrawOrder(24);
    speedNeedle.setIcon(icon);

    // anchor point.
    speedNeedle.getScreenXY().setXUnits(ge.UNITS_FRACTION);
    speedNeedle.getScreenXY().setYUnits(ge.UNITS_FRACTION);
    speedNeedle.getScreenXY().setX(0.75);
    speedNeedle.getScreenXY().setY(0.75);

    speedNeedle.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
    speedNeedle.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
    speedNeedle.getOverlayXY().setX(x);
    speedNeedle.getOverlayXY().setY(y);

    // Rotate around object's center point.
    speedNeedle.getRotationXY().setXUnits(ge.UNITS_FRACTION);
    speedNeedle.getRotationXY().setYUnits(ge.UNITS_FRACTION);
    speedNeedle.getRotationXY().setX(0.75);
    speedNeedle.getRotationXY().setY(0.75);

    // Set object's size in pixels.
    speedNeedle.getSize().setXUnits(ge.UNITS_PIXELS);
    speedNeedle.getSize().setYUnits(ge.UNITS_PIXELS);
    speedNeedle.getSize().setX(34);
    speedNeedle.getSize().setY(39);

    // add the screen overlay to Earth
    ge.getFeatures().appendChild(speedNeedle);
}

function createSpeedNeedle() {

// create an image for the screen overlay
var icon = ge.createIcon('');
icon.setHref(masterHost + 'images/speedneedle.png');

// create the screen overlay
speedNeedle = ge.createScreenOverlay('');
speedNeedle.setDrawOrder(24);
speedNeedle.setIcon(icon);

// anchor point.
speedNeedle.getScreenXY().setXUnits(ge.UNITS_FRACTION);
speedNeedle.getScreenXY().setYUnits(ge.UNITS_FRACTION);
speedNeedle.getScreenXY().setX(0.75);
speedNeedle.getScreenXY().setY(0.75);

speedNeedle.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
speedNeedle.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
speedNeedle.getOverlayXY().setX(70);
speedNeedle.getOverlayXY().setY(70);

// Rotate around object's center point.
speedNeedle.getRotationXY().setXUnits(ge.UNITS_FRACTION);
speedNeedle.getRotationXY().setYUnits(ge.UNITS_FRACTION);
speedNeedle.getRotationXY().setX(0.75);
speedNeedle.getRotationXY().setY(0.75);

// Set object's size in pixels.
speedNeedle.getSize().setXUnits(ge.UNITS_PIXELS);
speedNeedle.getSize().setYUnits(ge.UNITS_PIXELS);
speedNeedle.getSize().setX(34);
speedNeedle.getSize().setY(39);

// add the screen overlay to Earth
ge.getFeatures().appendChild(speedNeedle);
}

function createFuelGauge(x,y) {

// create an image for the screen overlay
var icon = ge.createIcon('');
icon.setHref(masterHost + 'images/fuelgauge.png');

// create the screen overlay
var overlay = ge.createScreenOverlay('');
overlay.setDrawOrder(22);
overlay.setIcon(icon);

// anchor point
overlay.getScreenXY().setXUnits(ge.UNITS_FRACTION);
overlay.getScreenXY().setYUnits(ge.UNITS_FRACTION);
overlay.getScreenXY().setX(0.5);
overlay.getScreenXY().setY(0.5);
//screen point
overlay.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
overlay.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
overlay.getOverlayXY().setX(x);
overlay.getOverlayXY().setY(y);

// Set object's size in pixels.
overlay.getSize().setXUnits(ge.UNITS_PIXELS);
overlay.getSize().setYUnits(ge.UNITS_PIXELS);
overlay.getSize().setX(63);
overlay.getSize().setY(62);

// add the screen overlay to Earth
ge.getFeatures().appendChild(overlay);

// create an image for the screen overlay
var icon = ge.createIcon('');
icon.setHref(masterHost + 'images/fuelneedle.png');

// create the screen overlay
fuelNeedle = ge.createScreenOverlay('');
fuelNeedle.setDrawOrder(24);
fuelNeedle.setIcon(icon);

// anchor point.
fuelNeedle.getScreenXY().setXUnits(ge.UNITS_FRACTION);
fuelNeedle.getScreenXY().setYUnits(ge.UNITS_FRACTION);
fuelNeedle.getScreenXY().setX(0.75);
fuelNeedle.getScreenXY().setY(0.25);

fuelNeedle.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
fuelNeedle.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
fuelNeedle.getOverlayXY().setX(x);
fuelNeedle.getOverlayXY().setY(y-13);

// Rotate around object's center point.
fuelNeedle.getRotationXY().setXUnits(ge.UNITS_FRACTION);
fuelNeedle.getRotationXY().setYUnits(ge.UNITS_FRACTION);
fuelNeedle.getRotationXY().setX(0.75);
fuelNeedle.getRotationXY().setY(0.25);

// Set object's size in pixels.
fuelNeedle.getSize().setXUnits(ge.UNITS_PIXELS);
fuelNeedle.getSize().setYUnits(ge.UNITS_PIXELS);
fuelNeedle.getSize().setX(28);
fuelNeedle.getSize().setY(26);

// add the screen overlay to Earth
ge.getFeatures().appendChild(fuelNeedle);
}

function createWheel() {

// create an image for the screen overlay
var icon = ge.createIcon('');
icon.setHref(masterHost + 'images/yachtwheel.png');

// create the screen overlay
wheel = ge.createScreenOverlay('');
wheel.setDrawOrder(9);
wheel.setIcon(icon);

// anchor point.
wheel.getScreenXY().setXUnits(ge.UNITS_FRACTION);
wheel.getScreenXY().setYUnits(ge.UNITS_FRACTION);
wheel.getScreenXY().setX(0.5);
wheel.getScreenXY().setY(0.87);

wheel.getOverlayXY().setXUnits(ge.UNITS_FRACTION);
wheel.getOverlayXY().setYUnits(ge.UNITS_PIXELS);
wheel.getOverlayXY().setX(0.5);
wheel.getOverlayXY().setY(0);

// Rotate around object's center point.
wheel.getRotationXY().setXUnits(ge.UNITS_FRACTION);
wheel.getRotationXY().setYUnits(ge.UNITS_FRACTION);
wheel.getRotationXY().setX(0.5);
wheel.getRotationXY().setY(0.5);

// Set object's size in pixels.
wheel.getSize().setXUnits(ge.UNITS_PIXELS);
wheel.getSize().setYUnits(ge.UNITS_PIXELS);
wheel.getSize().setX(800);
wheel.getSize().setY(800);

// add the screen overlay to Earth
ge.getFeatures().appendChild(wheel);
}

function createHelp() {

// create an image for the screen overlay
var icon = ge.createIcon('');
icon.setHref(masterHost + 'images/helppadsingle4.png');

5// create the screen overlay
helpPad = ge.createScreenOverlay('');
helpPad.setDrawOrder(60);
helpPad.setIcon(icon);

// anchor point.
helpPad.getScreenXY().setXUnits(ge.UNITS_FRACTION);
helpPad.getScreenXY().setYUnits(ge.UNITS_FRACTION);
helpPad.getScreenXY().setX(0.95);
helpPad.getScreenXY().setY(1);

helpPad.getOverlayXY().setXUnits(ge.UNITS_PIXELS);
helpPad.getOverlayXY().setYUnits(ge.UNITS_FRACTION);
helpRight = 0;
helpPad.getOverlayXY().setX(helpRight);
helpPad.getOverlayXY().setY(1);

// Set object's size in pixels.
helpPad.getSize().setXUnits(ge.UNITS_PIXELS);
helpPad.getSize().setYUnits(ge.UNITS_PIXELS);
helpPad.getSize().setY(512);
helpPad.getSize().setX(512);

// add the screen overlay to Earth
ge.getFeatures().appendChild(helpPad);
}

function togglePause(){
  togglePauseState = !togglePauseState;
  myship.latstep = 0;
  myship.longstep = 0;
  myship.deltaHeading = 0;
  pauseIcon.setVisibility(togglePauseState);
}

function toggleHelp(){
  if (helpRight==0){helpRight = 480;}else{helpRight = 0;}
}

function toggleBuildings(){
  toggleBuildingsState = !toggleBuildingsState;
  ge.getLayerRoot().enableLayerById(ge.LAYER_BUILDINGS, toggleBuildingsState);
}

function toggleGrayBuildings(){
  toggleGrayBuildingsState = !toggleGrayBuildingsState;
  ge.getLayerRoot().enableLayerById(ge.LAYER_BUILDINGS_LOW_RESOLUTION, toggleGrayBuildingsState);
}

function toggleBorders(){
  toggleBordersState = !toggleBordersState;
  ge.getLayerRoot().enableLayerById(ge.LAYER_BORDERS, toggleBordersState);
}

function resetControls(whichShip){
    whichShip.leftPowerValue = 0;
    whichShip.rightPowerValue = 0;
    bowThrust = 0;
    whichShip.rudderTarget = 0;
    leftPowerControl.f_setValue(whichShip.leftPowerValue * 100);        
    rightPowerControl.f_setValue(whichShip.rightPowerValue * 100);
}

//returns approximate bearing and tilt in degrees and distance in meters of location2 in relation to location1
//Tilt value where 0 means looking straight down. Pass Camera as location1 and target
//Values can be applied directly to camera properties
//more accurate but slower calculations here: http://www.movable-type.co.uk/scripts/latlong.html
function getBearingDistanceTilt(camera, ship){
  //calc lat and lon delta distances in meters  
  var deltalat = (ship.model.getLocation().getLatitude() - camera.getLatitude()) * DeltaLatitudeToMeters;
  var deltalon = myship.cosLatitude * ((ship.model.getLocation().getLongitude()-camera.getLongitude()) * DeltaLatitudeToMeters);
  var bearing = Math.atan(deltalon/deltalat)/degreesToRad;
  if (deltalat < 0) {bearing = 180 + bearing;}
  //calculate distance
  var hdistance = Math.sqrt((deltalat * deltalat) + (deltalon * deltalon));
  //calculate tilt
  var deltaAltitude = camera.getAltitude() - ship.altitude - myship.camAlt - ship.draft;
  var tilt = Math.atan( hdistance/deltaAltitude)/degreesToRad;
  if (tilt < 0){tilt = 180 + tilt}
  //Include altitude in true distance reading
  var distance = Math.sqrt((deltaAltitude * deltaAltitude) + (hdistance * hdistance));
  return{bearing:bearing, tilt:tilt, hdistance:hdistance, distance:distance};
}

//Rotates location1 around location2 at the given angle in degrees
//uses intermediate variable to cut down of calculations
function rotateLocationAround(location1, location2, angle){
 var x = (location1.getLongitude() - location2.getLongitude()) * myship.cosLatitude;
 var y = location1.getLatitude() - location2.getLatitude();
 var radAngle = -angle * degreesToRad;
 var cosAngle = Math.cos(radAngle);
 var sinAngle = Math.sin(radAngle);
 var latnew = location2.getLatitude() + (y * cosAngle + x * sinAngle);
 var longnew = location2.getLongitude() + (x * cosAngle - y * sinAngle)/myship.cosLatitude;
 return{latitude: latnew, longitude: longnew};
}

//tests point in KMLPolygon
function locationInPolygon(poly, latitude, longitude){
  var locationInBoundary = function(boundary, latitude, longitude){
      var j=0;
      var inside = false;
      var x = longitude;
      var y = latitude;
      var lat1 = 0;
      var lat2 = 0;
      var lon1 = 0;
      var lon2 = 0;
      var coordinates = boundary.getCoordinates();
      var pointCount = coordinates.getLength();
      
      for (var i=0; i < pointCount; i++) {
        j++;
        if (j == pointCount) {j = 0;}
        lat1 = coordinates.get(i).getLatitude();
        lat2 =coordinates.get(j).getLatitude();
        lon1 = coordinates.get(i).getLongitude();
        lon2 = coordinates.get(j).getLongitude();
        if (((lat1 < y) && (lat2 >= y)) 
        || ((lat2 < y) && (lat1 >= y))) {
          if ( lon1 + (y - lat1)
          /  (lat2-lat1)
          *  (lon2 - lon1)<x ) {
            inside = !inside
          }
        }
      }
      return inside;
    }
  var inside = false;
  var outer = poly.getOuterBoundary();
  inside = locationInBoundary(outer, latitude, longitude);
  if (inside){
    //check all inner boundaries if any.
    var inners = poly.getInnerBoundaries().getChildNodes();
    for (var i=0; i < inners.getLength(); i++) {
	inside = locationInBoundary(inners.item(i), location);
       //inners are like holes in a polygon
       if (inside){ inside = !inside; break;}
   }
  } 
  return inside;
 }

//defines latlonbox at a given location expressed in size and width and height in meters and angle
function setLatLonBoxAsMeters(latLonBox, latitude, longitude, height, width, angle){
    var radLatitude = latitude * degreesToRad;
    var cosLatitude = Math.cos(radLatitude);         
    height = height / DeltaLatitudeToMeters;  
    width = width / (DeltaLatitudeToMeters * cosLatitude );
    latLonBox.setNorth(latitude + height);
    latLonBox.setSouth(latitude - height);
    latLonBox.setEast(longitude + width);
    latLonBox.setWest(longitude - width);
    latLonBox.setRotation(-angle+90);
    return (latLonBox);
}

//scales latlonbox by given x and y scale factor
function scaleLatLonBox(latLonBox, heightFactor, widthFactor){
    heightFactor = (heightFactor - 1)/2;
    widthFactor = (widthFactor - 1)/2;
    var boxHeight = (latLonBox.getNorth() - latLonBox.getSouth()) * heightFactor;
    var boxWidth = (latLonBox.getEast() - latLonBox.getWest()) * widthFactor;
    boxHeight = boxHeight * heightFactor;
    latLonBox.setNorth(latLonBox.getNorth() + boxHeight);
    latLonBox.setSouth(latLonBox.getSouth() - boxHeight);
    latLonBox.setEast(latLonBox.getEast() + boxWidth);
    latLonBox.setWest(latLonBox.getWest() - boxWidth);
    return (latLonBox);
}

//returns approximate location coordinates based on bearing in degrees and distance in meters relative to location1
function getBDLocation(location1, bearing, distance){
  //calc lat and lon delta distances in meters  
  var radBearing = bearing * degreesToRad;
  var latDelta = Math.cos(radBearing);
  var lonDelta = Math.sin(radBearing);
  var outLatitude = location1.getLatitude() + latDelta * distance * metersToLocalLat;
  var outLongitude = location1.getLongitude() +  lonDelta * distance * myship.metersToLocalLon;
  return{latitude:outLatitude, longitude:outLongitude};
}

//places overlay with size defined in meters corrected for latitude
function createOverlay(name, latitude, longitude, height, width, angle, href) {
    var icon = ge.createIcon('');
    icon.setHref(href);
    var latLonBox = ge.createLatLonBox('');
    var myGroundOverlay = ge.createGroundOverlay('');
    myGroundOverlay.setName(name);
    myGroundOverlay.setIcon(icon);
    myGroundOverlay.setLatLonBox(latLonBox);
    setLatLonBoxAsMeters(myGroundOverlay.getLatLonBox(), latitude, longitude, height, width, angle);
    ge.getFeatures().appendChild(myGroundOverlay);
    return (myGroundOverlay);
} 

function flyto(placename) {
  setViewMode(0);
  var geocoder = new google.maps.ClientGeocoder();
  geocoder.getLatLng(placename, function(point) {
    if (point) {
      var lookAt = ge.createLookAt('');
      lookAt.set(point.y, point.x, 10, ge.ALTITUDE_RELATIVE_TO_GROUND, 0, 60, 20000);
      ge.getView().setAbstractView(lookAt);
    }
  });
}

function keyDown(event) {
  if (textInputFocus == true) {return true; exit;};
  if (!event) {
    event = window.event;
  }
  switch(event.keyCode){
  
    case 37: case 100: {myship.setRudderTarget(myship.rudderTarget - 5); event.returnValue = false; break;} //left
    case 39: case 102:{myship.setRudderTarget(myship.rudderTarget + 5); event.returnValue = false; break;} //right
    case 38: case 104: {upArrow = true; event.returnValue = false; break;} //up
    case 40: case 98: {downArrow = true; event.returnValue = false; break;} //down
    case 36: case 103: {leftpowerupkey = true; event.returnValue = false; break;}//left power up
    case 35: case 97: {leftpowerdownkey = true; event.returnValue = false; break;}//left power down
    case 33: case 105: {rightpowerupkey = true; event.returnValue = false; break;}//right power up
    case 34: case 99: {rightpowerdownkey = true; event.returnValue = false; break;}//right power down
    case 45: case 96: {leftbowthrust = true; event.returnValue = false; break;}//left bow thrust
    case 46: case 110: {rightbowthrust = true; event.returnValue = false; break;}//right bow thrust
    case 70: {if (hornPlaying != true){soundHorn(1); event.returnValue = false; break;}}//F to sound horn
    default: return true;
  }
  return false;
  mouseIsDown = false;
}

function keyUp(event) {
  if (textInputFocus == true) {return true; exit;};
  if (!event) {
    event = window.event;
  }

  switch(event.keyCode){
    //case 37: { leftArrowindex = 0; event.returnValue = false; break;} //left
    //case 39: {rightArrowindex = 0; event.returnValue = false; break;} //right
    case 38: case 104: {upArrow = false; event.returnValue = false; break;} //up
    case 40: case 98: {downArrow = false; event.returnValue = false; break;} //down
    case 36: case 103: {leftpowerupkey = false; event.returnValue = false; break;}//left power up
    case 35: case 97: {leftpowerdownkey = false; event.returnValue = false; break;}//left power down    
    case 33: case 105: {rightpowerupkey = false; event.returnValue = false; break;}//right power up
    case 34: case 99: {rightpowerdownkey = false; event.returnValue = false; break;}//right power down
    case 45: case 96: {leftbowthrust = false; event.returnValue = false; break;}//left bow thrust
    case 46: case 110: {rightbowthrust = false; event.returnValue = false; break;}//right bow thrust
    case 70: {soundHorn(0); event.returnValue = false; break;}//F release to silence horn
    default: return true;
  }
  return false;
  mouseIsDown = false;
}

function keyPress(event) {
  if (textInputFocus == true) {return true; exit;};

  if (!event) {
    var event = window.event;
  }
  
  switch(event.keyCode){
    //case 37: case 52: {myship.setRudderTarget(myship.rudderTarget - 5); event.returnValue = false; break;} //left
    //case 39: case 54: {myship.setRudderTarget(myship.rudderTarget + 5); event.returnValue = false; break;} //right
    case 12: {resetControls(myship); event.returnValue = false; break;} //5 key on keypad 
    case 113: {copyViewToScreen(); break; }//F2
    case 114: {copyShipToScreen(); break; } //F3
    case 115: {copyCameraToScreen(); break; } //F4
    case 119: {document.title = 'Testing performance 30 sec...'; doPerformance = true; break; } //F8
  }


  switch(event.charCode){
    case 112: case 80: case 32: {togglePause(); returnValue = false; break;}//P for toggle Pause
    case 66: case 98: {toggleBuildings(); returnValue = false; break;}//B for toggle Buildings
    case 71: case 103: {toggleGrayBuildings(); returnValue = false; break;}//G to toggle Gray Buildings
    case 77: case 109: {toggleMute(); returnValue = false; break;}//M to toggle mute
    case 76: case 108: {toggleBorders(); returnValue = false; break;}//L for toggle borders and labels
    case 72: case 104: {toggleHelp(); break;} //H for help
    case 53: {resetControls(myship); event.returnValue = false; break;} //5 key on keypad
    default: return true;
  }

  return true;
  mouseIsDown = false; //Sometimes mouse up event fails to fire which leaves the mousedown set. A keypress always means the mouse is up since focus is on the page
}

function setShipView(id){
    document.getElementById('view1button').src = 'images/view1off.png';
    document.getElementById('view2button').src = 'images/view2off.png';
    document.getElementById('view3button').src = 'images/view3off.png';
    document.getElementById('view4button').src = 'images/view4off.png';
    var myView = null;
    switch(id){
        case 1: {document.getElementById('view1button').src = 'images/view1on.png'; myView = myship.view1; break;}
        case 2: {document.getElementById('view2button').src = 'images/view2on.png'; myView = myship.view2; break;}
        case 3: {document.getElementById('view3button').src = 'images/view3on.png'; myView = myship.view3; break;}
        case 4: {document.getElementById('view4button').src = 'images/view4on.png'; myView = myship.view4; break;}
    }
    //when set it will cause the view update to handle it.
    currentViewID = id;
    newView = myView;
    //headHeading = -myView.heading;
}

function copyViewToScreen(){
    currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    var mybearingDistanceTilt = getBearingDistanceTilt(currentCam, myship);
    mybearingDistanceTilt.bearing += 180;
    if (mybearingDistanceTilt.bearing > 360){mybearingDistanceTilt.bearing -= 360};
    document.getElementById('info').innerHTML = 'View rel to ship: bearing, dist, altmode, alt, hdg, tilt, roll, viewmode<br/>' + (mybearingDistanceTilt.bearing - myship.heading) + ', ' + mybearingDistanceTilt.hdistance + ', ' + currentCam.getAltitudeMode() + ', ' + (currentCam.getAltitude() - myship.altitude - myship.draft) + ', ' + (currentCam.getHeading() - myship.heading) + ', ' + currentCam.getTilt() + ', ' + currentCam.getRoll() + ', ' + viewMode;
}

function copyShipToScreen(){
    document.getElementById('info').innerHTML = 'Ship location: hdg, alt, lat,lon<br/>' + myship.heading + ', ' + myship.model.getLocation().getAltitude() + ', ' + myship.model.getLocation().getLatitude() + ', ' + myship.model.getLocation().getLongitude();
}

function copyCameraToScreen(){
    document.getElementById('info').innerHTML = 'Camera location: lat, lon, alt, altmode, hdg, tilt, roll<br/>' + currentCam.getLatitude() + ', ' + currentCam.getLongitude() + ', ' + currentCam.getAltitude() + ',' + currentCam.getAltitudeMode() + ', ' + currentCam.getHeading() + ', ' + currentCam.getTilt() + ', ' + currentCam.getRoll();
}

function soundHorn(value){
    if (value == 1){
        var newVolume = (1 - (camBearingDistanceTilt.distance / myship.hornSoundRange)) * 100;
        if (newVolume < 0){newVolume = 0;} 
        soundManager.play(myship.hornSound, {volume:newVolume});      
        document.getElementById('hornbutton').src = 'images/pushbuttondown.png';
        hornPlaying = true;
    }
    else if (hornPlaying==true){
        var newVolume = (1 - (camBearingDistanceTilt.distance / myship.hornSoundRange)) * 100;
        if (newVolume < 0){newVolume = 0;}  
        //alert(myship.hornSound);
        soundManager.stop(myship.hornSound);
        soundManager.play(myship.hornEndSound, {volume:newVolume}); 
        document.getElementById('hornbutton').src = 'images/pushbuttonup.png';
        hornPlaying = false;
    }
}

function toggleAnchor(){
    myship.anchorDown = !myship.anchorDown;
    setAnchorSwitch(myship.anchorDown);
    if (myship.anchorDown == true){
        var newVolume = (1 - (camBearingDistanceTilt.distance / myship.mechanicSoundRange)) * 100;
        if (newVolume < 0){newVolume = 0;}
        soundManager.play(myship.anchorSound, {volume:newVolume});
    }
    else {
        soundManager.stop(myship.anchorSound);
    }
}

function setAnchorSwitch(down){
    if (down == true){ document.getElementById('toggle1').src = 'images/toggleswitchdown.png'; }
    else { document.getElementById('toggle1').src = 'images/toggleswitchup.png'; }        
}

function toggleMute(){
    engineMute = !engineMute
    myship.anchorDown = !myship.anchorDown;
    if (engineMute == true){
        document.getElementById('toggle2').src = 'images/mute.png';      
        engineSound.engineStop();
    }
    else {
        document.getElementById('toggle2').src = 'images/sound.png';
        engineSound.engineVolume(0);
        if (myship.fuel > 0) { engineSound.enginePlay(); }
    }
}

function toggleShowInfo(){
    if (document.getElementById('info').style.display == "none"){
        document.getElementById('info').style.display = "block";
        presentingBanner.setVisibility(true);      
        document.getElementById('moreinfolink').innerHTML = "Less info";
    }
    else{
        document.getElementById('info').style.display = "none";
        presentingBanner.setVisibility(false);
        document.getElementById('moreinfolink').innerHTML = "More info";
    }
    
}
