package Views; import java.util.ArrayList; import Controllers.*; import Models.LogicalRunway; import Services.CalculationService; import Views.Visualisation.VisualisationType; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.assets.AssetManager; import com.badlogic.gdx.graphics.*; import com.badlogic.gdx.graphics.g2d.*; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; import com.badlogic.gdx.math.*; public class VisPanel { private static final int SIDE_VIEW_GROUND_HEIGHT = 150; private static final int TOP_VIEW_LEFT_START = 70; private static final int TOP_VIEW_RIGHT_START = 830; private VisualisationType currentDisplay; private Sprite background, clearwayL, stopwayL, clearwayR, stopwayR, clearwayMarkerL, stopwayMarkerL, clearwayMarkerR, stopwayMarkerR, clearedNGraded, runwayImage, displacedThreshold, displacedThresholdR, sideOnBackground, currentPlane, currentObstacle; private ArrayList<Sprite> controls; public ArrayList<Integer> controlStartX, controlStartY, controlWidth; private LogicalRunway currentLogicalRunway; private AssetManager manager; private int width, height, offsetY; private Runway runway; private boolean isApproachingFromLeft = true; private boolean isLanding = false; private BitmapFont[] fonts; private OrthographicCamera cam; private OrthographicCamera camFixed; public double zoomLevel = 1.0; public float panLevel = +0.0f; public float tiltLevel = +00.0f; public float rotation = +00.0f; public int buttonWidth = 20; private String landingAvoidDistanceString; private String takeOffAvoidDistanceString; public boolean screenshotInProgress = false; public VisPanel(AssetManager manager, VisualisationType type, int width, int height, int offsetY, Runway runway, BitmapFont big, BitmapFont small) { this.manager = manager; this.currentDisplay = type; this.width = width; this.height = height; this.offsetY = offsetY; this.runway = runway; this.isApproachingFromLeft = true; this.fonts = new BitmapFont[2]; this.fonts[0] = big; this.fonts[1] = small; float w = Gdx.graphics.getWidth(); float h = Gdx.graphics.getHeight(); cam = new OrthographicCamera(w, h); cam.position.set(cam.viewportWidth / 2f, cam.viewportHeight / 2f, 0); cam.update(); camFixed = new OrthographicCamera(w, h); camFixed.position.set(cam.viewportWidth / 2f, cam.viewportHeight / 2f, 0); camFixed.update(); setBackdrop(); } public void updateVis(Runway runway) { this.runway = runway; setBackdrop(); } private boolean isTopDown() { return currentDisplay == VisualisationType.TopDown; } private void setBackdrop() { // Defines sprites for runway components: this.background = new Sprite(manager.get( "assets/data/New_Runway_Graphics/grassbottom.png", Texture.class)); this.clearwayL = new Sprite(manager.get( "assets/data/New_Runway_Graphics/Clearway.PNG", Texture.class)); this.stopwayL = new Sprite(manager.get( "assets/data/New_Runway_Graphics/Stopway.PNG", Texture.class)); this.clearwayMarkerL = new Sprite(manager.get( "assets/data/New_Runway_Graphics/ClearwayMarker.PNG", Texture.class)); this.stopwayMarkerL = new Sprite(manager.get( "assets/data/New_Runway_Graphics/stopwayMarker.jpg", Texture.class)); this.clearwayR = new Sprite(manager.get( "assets/data/New_Runway_Graphics/ClearwayR.PNG", Texture.class)); this.stopwayR = new Sprite(manager.get( "assets/data/New_Runway_Graphics/StopwayR.PNG", Texture.class)); this.clearwayMarkerR = new Sprite(manager.get( "assets/data/New_Runway_Graphics/ClearwayMarkerR.PNG", Texture.class)); this.stopwayMarkerR = new Sprite(manager.get( "assets/data/New_Runway_Graphics/stopwayMarkerR.jpg", Texture.class)); this.runwayImage = new Sprite(manager.get( "assets/data/New_Runway_Graphics/Runway.PNG", Texture.class)); this.sideOnBackground = new Sprite(manager.get( "assets/data/New_Runway_Graphics/sidevis.png", Texture.class)); this.clearedNGraded = new Sprite(manager.get( "assets/data/New_Runway_Graphics/ClearedAndGraded.png", Texture.class)); this.displacedThreshold = new Sprite(manager.get( "assets/data/New_Runway_Graphics/DisplacedThreshold.png", Texture.class)); this.displacedThresholdR = new Sprite(manager.get( "assets/data/New_Runway_Graphics/DisplacedThresholdR.png", Texture.class)); // Set the sizes and positions of controls and obstructions: switch (currentDisplay) { case TopDown: this.currentPlane = new Sprite(manager.get( "assets/data/topplane.png", Texture.class)); this.currentObstacle = new Sprite(manager.get( "assets/data/topcar.png", Texture.class)); this.controls = new ArrayList<Sprite>(); this.controlStartX = new ArrayList<Integer>(); this.controlStartY = new ArrayList<Integer>(); this.controlWidth = new ArrayList<Integer>(); int buttonPosX = (int) (Gdx.graphics.getWidth() / 2.0f) - 40; int nextButtonPosY = (int) ((Gdx.graphics.getHeight() / 2.0f) - 100); this.controlStartX.add(buttonPosX); this.controlStartY.add(nextButtonPosY); this.controlWidth.add(buttonWidth - 7); this.controls.add(new Sprite(manager .get("assets/data/Navigation_Controls/ZoomIn.PNG", Texture.class))); nextButtonPosY -= buttonWidth; this.controlStartX.add(buttonPosX); this.controlStartY.add(nextButtonPosY); this.controlWidth.add(buttonWidth - 7); this.controls.add(new Sprite(manager.get( "assets/data/Navigation_Controls/ZoomOut.PNG", Texture.class))); nextButtonPosY -= buttonWidth * 1.5; this.controlStartX.add(buttonPosX); this.controlStartY.add(nextButtonPosY); this.controlWidth.add(buttonWidth - 7); this.controls.add(new Sprite(manager.get( "assets/data/Navigation_Controls/RightRotate.PNG", Texture.class))); nextButtonPosY -= buttonWidth; this.controlStartX.add(buttonPosX); this.controlStartY.add(nextButtonPosY); this.controlWidth.add(buttonWidth - 7); this.controls.add(new Sprite(manager.get( "assets/data/Navigation_Controls/LeftRotate.PNG", Texture.class))); nextButtonPosY -= buttonWidth * 1.5; this.controlStartX.add(buttonPosX); this.controlStartY.add(nextButtonPosY); this.controlWidth.add(buttonWidth - 7); this.controls.add(new Sprite(manager .get("assets/data/Navigation_Controls/TiltUp.PNG", Texture.class))); nextButtonPosY -= buttonWidth; this.controlStartX.add(buttonPosX); this.controlStartY.add(nextButtonPosY); this.controlWidth.add(buttonWidth - 7); this.controls.add(new Sprite(manager.get( "assets/data/Navigation_Controls/ResetView.PNG", Texture.class))); this.controlStartX.add(buttonPosX - buttonWidth); this.controlStartY.add(nextButtonPosY); this.controlWidth.add(buttonWidth - 7); this.controls.add(new Sprite(manager.get( "assets/data/Navigation_Controls/PanLeft.PNG", Texture.class))); this.controlStartX.add(buttonPosX + buttonWidth); this.controlStartY.add(nextButtonPosY); this.controlWidth.add(buttonWidth - 7); this.controls.add(new Sprite(manager.get( "assets/data/Navigation_Controls/PanRight.PNG", Texture.class))); nextButtonPosY -= buttonWidth; this.controlStartX.add(buttonPosX); this.controlStartY.add(nextButtonPosY); this.controlWidth.add(buttonWidth - 7); this.controls.add(new Sprite(manager.get( "assets/data/Navigation_Controls/TiltDown.PNG", Texture.class))); nextButtonPosY -= buttonWidth * 2.0; this.controlStartX.add(buttonPosX); this.controlStartY.add(nextButtonPosY); this.controlWidth.add(buttonWidth); this.controls.add(new Sprite(manager.get( "assets/data/Navigation_Controls/Compass.PNG", Texture.class))); break; case SideView: this.currentPlane = new Sprite(manager.get( "assets/data/sideplane.png", Texture.class)); this.currentObstacle = new Sprite(manager.get( "assets/data/sidecar.png", Texture.class)); break; default: break; } // Set the sizes and positions of runway components: int runwayDisplayWidth = 30; double leftStopwayLength = runway.getOriginalLogicalRunwayFromRight().stopwayLength; double rightStopwayLength = runway.getOriginalLogicalRunwayFromLeft().stopwayLength; double leftClearwayLength = runway.getOriginalLogicalRunwayFromRight().clearwayLength; double rightClearwayLength = runway.getOriginalLogicalRunwayFromLeft().clearwayLength; double runwayLength = runway.getOriginalLogicalRunwayFromLeft().lda; double totalLength = leftStopwayLength + runwayLength + rightStopwayLength; switch (currentDisplay) { case TopDown: int yPos = (height * 4 / 3) + (runwayDisplayWidth / 2) + 39; this.background.setSize(width, height); this.background.setPosition(0, offsetY); this.stopwayL.setSize( (int) (width * (leftStopwayLength / totalLength)), (int) (runwayDisplayWidth)); this.stopwayL.setPosition(0, yPos); this.stopwayR.setSize( (int) (width * (rightStopwayLength / totalLength)), (int) (runwayDisplayWidth)); this.stopwayR .setPosition( (int) (width * ((leftStopwayLength + runwayLength) / totalLength)), yPos); this.runwayImage.setSize( (int) (width * (runwayLength / totalLength)), (int) (runwayDisplayWidth)); this.runwayImage.setPosition( (int) (width * (leftStopwayLength / totalLength)), yPos); this.clearwayL.setSize( (int) (width * (leftClearwayLength / totalLength)), (int) (runwayDisplayWidth * 3.0)); this.clearwayL .setPosition( (int) (width * ((leftStopwayLength - leftClearwayLength) / totalLength)), yPos - runwayDisplayWidth); this.clearwayR.setSize( (int) (width * (rightClearwayLength / totalLength)), (int) (runwayDisplayWidth * 3.0)); this.clearwayR .setPosition( (int) (width * ((leftStopwayLength + runwayLength) / totalLength)), yPos - runwayDisplayWidth); this.clearedNGraded .setSize(width, (int) (runwayDisplayWidth * 6.0)); this.clearedNGraded.setPosition(0, (int) (yPos - runwayDisplayWidth * 2.5)); this.displacedThreshold.setSize( (int) (width * (runwayLength / (totalLength * 10))), (int) (runwayDisplayWidth)); this.displacedThreshold.setPosition(-50000, yPos); this.displacedThresholdR.setSize( (int) (width * (runwayLength / (totalLength * 10))), (int) (runwayDisplayWidth)); this.displacedThresholdR.setPosition(-50000, yPos); break; case SideView: int yPosS = 117 + (runwayDisplayWidth / 2); int markerSize = 5; this.sideOnBackground.setSize(width, height); this.sideOnBackground.setPosition(0, offsetY); this.clearwayMarkerL.setSize( (int) (width * (leftClearwayLength / totalLength)), markerSize); this.clearwayMarkerL .setPosition( (int) (width * ((leftStopwayLength - leftClearwayLength) / totalLength)), yPosS); this.clearwayMarkerR.setSize( (int) (width * (rightClearwayLength / totalLength)), markerSize); this.clearwayMarkerR .setPosition( (int) (width * ((leftStopwayLength + runwayLength) / totalLength)), yPosS); this.stopwayMarkerL.setSize( (int) (width * (leftStopwayLength / totalLength)), markerSize); this.stopwayMarkerL.setPosition(0, yPosS + markerSize); this.stopwayMarkerR.setSize( (int) (width * (rightStopwayLength / totalLength)), markerSize); this.stopwayMarkerR .setPosition( (int) (width * ((leftStopwayLength + runwayLength) / totalLength)), yPosS + markerSize); break; } this.currentLogicalRunway = runway.getLeftLandLogicalRunway(); currentPlane.setScale(0.2f); this.currentPlane.setPosition(0, isTopDown() ? offsetY - 210 : offsetY + 200); } private boolean isObstacleValid() { return runway.getFirstObstruction() != null && runway.getFirstObstruction().getWidth() > 0.01; } public void render(SpriteBatch batch, SpriteBatch controlsBatch, SpriteBatch sideOnViewBatch) { float w = Gdx.graphics.getWidth(); float h = Gdx.graphics.getHeight(); if (isTopDown()) { cam = new OrthographicCamera((int) (w / zoomLevel), (int) (h / zoomLevel)); cam.position.set((cam.viewportWidth / 2f) + panLevel, (cam.viewportHeight / 2f) + tiltLevel + 35, 0); cam.rotate(rotation); cam.update(); batch.setProjectionMatrix(cam.combined); } else { cam = new OrthographicCamera(w, h); cam.position.set((cam.viewportWidth / 2f), (cam.viewportHeight / 2f), 0); cam.rotate(0.0f); cam.update(); batch.setProjectionMatrix(cam.combined); } CharSequence leftThreshold; if (runway.getRunwayID() < 10) { leftThreshold = runway.getRunwayName() + " (0" + runway.getRunwayID() + "L)"; } else { leftThreshold = runway.getRunwayName() + " (" + runway.getRunwayID() + "L)"; } CharSequence rightThreshold = runway.getRunwayName() + " (" + (runway.getRunwayID() + 18) + "R)"; // decide on x position of text depending on length int textLength = leftThreshold.length(); int textPositionX = width - (14 * textLength); // Draws sprites (previously prepared above): switch (currentDisplay) { case TopDown: background.draw(batch); clearedNGraded.draw(batch); runwayImage.draw(batch); clearwayL.draw(batch); stopwayL.draw(batch); clearwayR.draw(batch); stopwayR.draw(batch); break; case SideView: sideOnBackground.draw(batch); clearwayMarkerL.draw(batch); stopwayMarkerL.draw(batch); clearwayMarkerR.draw(batch); stopwayMarkerR.draw(batch); break; } if (isObstacleValid()) { currentObstacle.draw(batch); drawArrows(batch); } currentPlane.draw(batch); fonts[0].draw(batch, leftThreshold, 15, offsetY + 40); fonts[0].draw(batch, rightThreshold, textPositionX, offsetY + 40); drawControls(controlsBatch); } private void drawStopperedLine(ShapeRenderer r, Vector2 start, Vector2 end, float height, int thickness) { start.y -= (transformToScreenCoords(new Vector2(0.0f, 0.0f))).y; end.y -= (transformToScreenCoords(new Vector2(0.0f, 0.0f))).y; r.rectLine(start.x, start.y + height, end.x, end.y + height, 3); r.rectLine(start.x, start.y + height - 10, start.x, end.y + height + 10, 3); r.rectLine(end.x, start.y + height - 10, end.x, end.y + height + 10, 3); } private void drawArrows(SpriteBatch batch) { batch.end(); ShapeRenderer r = new ShapeRenderer(); float w2 = Gdx.graphics.getWidth(); float h2 = Gdx.graphics.getHeight(); if (isTopDown()) { cam = new OrthographicCamera((int) (w2 / zoomLevel), (int) (h2 / zoomLevel)); cam.position.set((cam.viewportWidth / 2f) + panLevel, (cam.viewportHeight / 2f) + tiltLevel + 35, 0); cam.rotate(rotation); cam.update(); r.setProjectionMatrix(cam.combined); } else { cam = new OrthographicCamera(w2, h2); cam.position.set((cam.viewportWidth / 2f), (cam.viewportHeight / 2f), 0); cam.rotate(0.0f); cam.update(); r.setProjectionMatrix(cam.combined); } r.begin(ShapeType.Filled); float ldaHeight = (this.isTopDown() ? 100 : 70) + offsetY; float toraHeight = (this.isTopDown() ? 250 : 250) + offsetY; float asdaHeight = (this.isTopDown() ? 280 : 280) + offsetY; float todaHeight = (this.isTopDown() ? 310 : 310) + offsetY; float avoidHeight = (this.isTopDown() ? 230 : 180) + offsetY; Vector2 ldaStart = Vector2.Zero, ldaEnd = Vector2.Zero; Vector2 landingThreshold = Vector2.Zero, takeOffThreshold = Vector2.Zero; Vector2 toraStart = Vector2.Zero, toraEnd = Vector2.Zero; Vector2 todaStart = Vector2.Zero, todaEnd = Vector2.Zero; Vector2 landingAsdaStart = Vector2.Zero, landingAsdaEnd = Vector2.Zero; Vector2 takeOffAsdaStart = Vector2.Zero, takeOffAsdaEnd = Vector2.Zero; Vector2 landingAvoidDistanceStart = Vector2.Zero, landingAvoidDistanceEnd = Vector2.Zero; Vector2 takeOffAvoidDistanceStart = Vector2.Zero, takeOffAvoidDistanceEnd = Vector2.Zero; // transformToScreenCoords TAKES COORDINATES FROM THE POINT WHERE THE // LEFT STOPWAY BEGINS double leftStopwayLength = runway.getOriginalLogicalRunwayFromRight().stopwayLength; double rightStopwayLength = runway.getOriginalLogicalRunwayFromLeft().stopwayLength; double leftClearwayLength = runway.getOriginalLogicalRunwayFromRight().clearwayLength; double rightClearwayLength = runway.getOriginalLogicalRunwayFromLeft().clearwayLength; double runwayLength = runway.getOriginalLogicalRunwayFromLeft().lda; if (CalculationService.obstacleIsOnLeft(runway.getFirstObstruction(), runway)) {/*obstacle_on_left */ if (isApproachingFromLeft) {/*land_from_left DIAGRAM 1*/ this.currentLogicalRunway = runway.getLeftLandLogicalRunway() .clone(); landingAsdaEnd = ((new Vector2((float) (runwayLength + leftStopwayLength + rightStopwayLength), 0))); // als / Tocs: landingAvoidDistanceStart = new Vector2( (float) (runway.getFirstObstruction() .getPositionAlongRunway() + 0.5 * runway .getFirstObstruction().getLength()), 0.5f); landingAvoidDistanceEnd = new Vector2( (float) (landingAvoidDistanceStart.x + runway.getLeftLandLogicalRunway().resa + 60.0f), 0.0f); landingAvoidDistanceStart = transformToScreenCoords(landingAvoidDistanceStart); landingAvoidDistanceEnd = transformToScreenCoords(landingAvoidDistanceEnd); landingAvoidDistanceString = "ALS/TOCS"; } else {/*land_from_right DIAGRAM 3*/ this.currentLogicalRunway = runway.getRightLandLogicalRunway() .clone(); landingAsdaEnd = ((new Vector2( (float) (runwayLength + leftStopwayLength), 0))); // avoidDistance: landingAvoidDistanceStart = new Vector2( (float) (runway.getFirstObstruction() .getPositionAlongRunway() + 0.5 * runway .getFirstObstruction().getLength()), 0.0f); landingAvoidDistanceEnd = new Vector2( (float) (landingAvoidDistanceStart.x + runway.getLeftLandLogicalRunway().resa + 60.0f), 0.0f); landingAvoidDistanceStart = transformToScreenCoords(landingAvoidDistanceStart); landingAvoidDistanceEnd = transformToScreenCoords(landingAvoidDistanceEnd); landingAvoidDistanceString = "AVOID"; } ldaEnd = ((new Vector2((float) (runwayLength + leftStopwayLength), 0))); landingThreshold = (new Vector2( // This is threshold + leftStopwayLength (float) (currentLogicalRunway.displacedThreshold + leftStopwayLength), 0)); ldaStart = (new Vector2( (float) (ldaEnd.x - currentLogicalRunway.lda), 0)); landingAsdaStart = (new Vector2( (float) (landingAsdaEnd.x - currentLogicalRunway.asda), 0)); if (isApproachingFromLeft) {/*takeOff_from_left DIAGRAM 5*/ this.currentLogicalRunway = runway .getLeftTakeOffLogicalRunway().clone(); todaEnd = (new Vector2((float) (leftStopwayLength + runwayLength + rightClearwayLength), 0)); takeOffAsdaEnd = (new Vector2((float) (leftStopwayLength + runwayLength + rightStopwayLength), 0)); // avoidDistance: takeOffAvoidDistanceStart = new Vector2( (float) (runway.getFirstObstruction() .getPositionAlongRunway() + 0.5 * runway .getFirstObstruction().getLength()), 0.0f); takeOffAvoidDistanceEnd = new Vector2( (float) (takeOffAvoidDistanceStart.x + runway .getBlastDistance()), 0.0f); takeOffAvoidDistanceStart = transformToScreenCoords(takeOffAvoidDistanceStart); takeOffAvoidDistanceEnd = transformToScreenCoords(takeOffAvoidDistanceEnd); takeOffAvoidDistanceString = "BLAST"; this.displacedThreshold.setPosition( (float) (takeOffAvoidDistanceEnd.x - displacedThreshold .getWidth()), displacedThreshold.getY()); // if (currentDisplay == VisualisationType.TopDown) { // batch.begin(); // displacedThreshold.draw(batch); // batch.end(); // } } else {/*takeOff_from_right DIAGRAM 7*/ this.currentLogicalRunway = runway .getRightTakeOffLogicalRunway().clone(); todaEnd = (new Vector2( (float) (leftStopwayLength + runwayLength), 0)); takeOffAsdaEnd = (new Vector2( (float) (leftStopwayLength + runwayLength), 0)); // als/Tocs: takeOffAvoidDistanceStart = new Vector2( (float) (runway.getFirstObstruction() .getPositionAlongRunway() + 0.5 * runway .getFirstObstruction().getLength()), 0.5f); takeOffAvoidDistanceEnd = new Vector2( (float) (takeOffAvoidDistanceStart.x + currentLogicalRunway.resa + 60.0f), 0.0f); takeOffAvoidDistanceStart = transformToScreenCoords(takeOffAvoidDistanceStart); takeOffAvoidDistanceEnd = transformToScreenCoords(takeOffAvoidDistanceEnd); takeOffAvoidDistanceString = "ALS/TOCS"; } toraEnd = (new Vector2((float) (leftStopwayLength + runwayLength), 0)); takeOffThreshold = (new Vector2( // This is threshold + leftStopwayLength (float) (currentLogicalRunway.displacedThreshold + leftStopwayLength), 0)); toraStart = (new Vector2( (float) (toraEnd.x - currentLogicalRunway.tora), 0)); todaStart = (new Vector2( (float) (todaEnd.x - currentLogicalRunway.toda), 0)); takeOffAsdaStart = (new Vector2( (float) (takeOffAsdaEnd.x - currentLogicalRunway.asda), 0)); } else {/*obstacle_on_right*/ if (isApproachingFromLeft) {/*land_from_left DIAGRAM 2*/ this.currentLogicalRunway = runway.getLeftLandLogicalRunway() .clone(); landingAsdaStart = (new Vector2((float) leftStopwayLength, 0)); // avoidDistance: landingAvoidDistanceEnd = new Vector2( (float) (runway.getFirstObstruction() .getPositionAlongRunway() - 0.5 * runway .getFirstObstruction().getLength()), 0.0f); landingAvoidDistanceStart = new Vector2( (float) (landingAvoidDistanceEnd.x - (currentLogicalRunway.resa + 60.0f)), 0.0f); landingAvoidDistanceStart = transformToScreenCoords(landingAvoidDistanceStart); landingAvoidDistanceEnd = transformToScreenCoords(landingAvoidDistanceEnd); landingAvoidDistanceString = "AVOID"; } else {/*land_from_right DIAGRAM 4*/ this.currentLogicalRunway = runway.getRightLandLogicalRunway() .clone(); landingAsdaStart = (new Vector2(0.0f, 0)); // als/tocs: landingAvoidDistanceEnd = new Vector2( (float) (runway.getFirstObstruction() .getPositionAlongRunway() - 0.5 * runway .getFirstObstruction().getLength()), 0.5f); landingAvoidDistanceStart = new Vector2( (float) (landingAvoidDistanceEnd.x - (currentLogicalRunway.resa + 60.0f)), 0.0f); landingAvoidDistanceStart = transformToScreenCoords(landingAvoidDistanceStart); landingAvoidDistanceEnd = transformToScreenCoords(landingAvoidDistanceEnd); landingAvoidDistanceString = "ALS/TOCS"; } ldaStart = (new Vector2((float) leftStopwayLength, 0)); landingThreshold = (new Vector2( // This is threshold + leftStopwayLength (float) (currentLogicalRunway.displacedThreshold + leftStopwayLength), 0)); ldaEnd = (new Vector2( (float) (ldaStart.x + currentLogicalRunway.lda), 0)); landingAsdaEnd = (new Vector2( (float) (landingAsdaStart.x + currentLogicalRunway.asda), 0)); if (isApproachingFromLeft) {/*takeOff_from_left DIAGRAM 6*/ this.currentLogicalRunway = runway .getLeftTakeOffLogicalRunway().clone(); todaStart = (new Vector2((float) leftStopwayLength, 0)); takeOffAsdaStart = (new Vector2((float) leftStopwayLength, 0)); // als/tocs: takeOffAvoidDistanceEnd = new Vector2( (float) (runway.getFirstObstruction() .getPositionAlongRunway() - 0.5 * runway .getFirstObstruction().getLength()), 0.5f); takeOffAvoidDistanceStart = new Vector2( (float) (takeOffAvoidDistanceEnd.x - (currentLogicalRunway.resa + 60.0f)), 0.0f); takeOffAvoidDistanceStart = transformToScreenCoords(takeOffAvoidDistanceStart); takeOffAvoidDistanceEnd = transformToScreenCoords(takeOffAvoidDistanceEnd); takeOffAvoidDistanceString = "ALS/TOCS"; } else {/*takeOff_from_right DIAGRAM 8*/ this.currentLogicalRunway = runway .getRightTakeOffLogicalRunway().clone(); todaStart = (new Vector2( (float) (leftStopwayLength - leftClearwayLength), 0)); takeOffAsdaStart = (new Vector2(0.0f, 0)); // blastDistance: takeOffAvoidDistanceEnd = new Vector2( (float) (runway.getFirstObstruction() .getPositionAlongRunway() - 0.5 * runway .getFirstObstruction().getLength()), 0.0f); takeOffAvoidDistanceStart = new Vector2( (float) (takeOffAvoidDistanceEnd.x - runway .getBlastDistance()), 0.0f); takeOffAvoidDistanceStart = transformToScreenCoords(takeOffAvoidDistanceStart); takeOffAvoidDistanceEnd = transformToScreenCoords(takeOffAvoidDistanceEnd); takeOffAvoidDistanceString = "BLAST"; this.displacedThresholdR.setPosition( (float) (takeOffAvoidDistanceStart.x), displacedThreshold.getY()); } toraStart = (new Vector2((float) leftStopwayLength, 0)); takeOffThreshold = (new Vector2( // This is threshold + leftStopwayLength (float) (currentLogicalRunway.displacedThreshold + leftStopwayLength), 0)); toraEnd = (new Vector2( (float) (toraStart.x + currentLogicalRunway.tora), 0)); todaEnd = (new Vector2( (float) (todaStart.x + currentLogicalRunway.toda), 0)); takeOffAsdaEnd = (new Vector2( (float) (takeOffAsdaStart.x + currentLogicalRunway.asda), 0)); } landingAsdaEnd = transformToScreenCoords(landingAsdaEnd); ldaEnd = transformToScreenCoords(ldaEnd); landingThreshold = transformToScreenCoords(landingThreshold); ldaStart = transformToScreenCoords(ldaStart); landingAsdaStart = transformToScreenCoords(landingAsdaStart); todaEnd = transformToScreenCoords(todaEnd); takeOffAsdaEnd = transformToScreenCoords(takeOffAsdaEnd); toraEnd = transformToScreenCoords(toraEnd); takeOffThreshold = transformToScreenCoords(takeOffThreshold); toraStart = transformToScreenCoords(toraStart); todaStart = transformToScreenCoords(todaStart); takeOffAsdaStart = transformToScreenCoords(takeOffAsdaStart); if (!isTopDown()) { Obstruction o = runway.getFirstObstruction(); if (isObstacleValid()) { Vector2 transCoords = (transformToScreenCoords( o.getPositionAlongRunway(), o.getDistanceFromRunway())); } } if (isTopDown()) { landingAvoidDistanceStart = new Vector2( landingAvoidDistanceStart.x, (transformToScreenCoords(new Vector2(0.0f, 0.0f))).y); landingAvoidDistanceEnd = new Vector2(landingAvoidDistanceEnd.x, (transformToScreenCoords(new Vector2(0.0f, 0.0f))).y); takeOffAvoidDistanceStart = new Vector2( takeOffAvoidDistanceStart.x, (transformToScreenCoords(new Vector2(0.0f, 0.0f))).y); takeOffAvoidDistanceEnd = new Vector2(takeOffAvoidDistanceEnd.x, (transformToScreenCoords(new Vector2(0.0f, 0.0f))).y); batch.begin(); if (isApproachingFromLeft && CalculationService.obstacleIsOnLeft( runway.getFirstObstruction(), runway) && !isLanding) displacedThreshold.draw(batch); if (!isApproachingFromLeft && !CalculationService.obstacleIsOnLeft( runway.getFirstObstruction(), runway) && !isLanding) displacedThresholdR.draw(batch); batch.end(); } if (isLanding) { drawStopperedLine(r, ldaStart, ldaEnd, ldaHeight, 3); drawStopperedLine(r, landingAsdaStart, landingAsdaEnd, asdaHeight, 3); drawStopperedLine(r, landingAvoidDistanceStart, landingAvoidDistanceEnd, avoidHeight, 3); } else { drawStopperedLine(r, toraStart, toraEnd, toraHeight, 3); drawStopperedLine(r, todaStart, todaEnd, todaHeight, 3); drawStopperedLine(r, takeOffAsdaStart, takeOffAsdaEnd, asdaHeight, 3); drawStopperedLine(r, takeOffAvoidDistanceStart, takeOffAvoidDistanceEnd, avoidHeight, 3); } r.end(); batch.begin(); if (isLanding) { fonts[1].draw(batch, "LDA", (ldaStart.x + ldaEnd.x) / 2f - 15, ldaHeight - 10); fonts[1].draw(batch, "ASDA", (landingAsdaStart.x + landingAsdaEnd.x) / 2f - 15, asdaHeight - 10); fonts[1].draw( batch, landingAvoidDistanceString, (landingAvoidDistanceStart.x + landingAvoidDistanceEnd.x) / 2f - 15, (float) avoidHeight); } else { fonts[1].draw(batch, "TORA", (toraStart.x + toraEnd.x) / 2f - 20, toraHeight - 10); fonts[1].draw(batch, "TODA", (todaStart.x + todaEnd.x) / 2f - 20, todaHeight - 10); fonts[1].draw(batch, "ASDA", (takeOffAsdaStart.x + takeOffAsdaEnd.x) / 2f - 20, asdaHeight - 10); fonts[1].draw( batch, takeOffAvoidDistanceString, (takeOffAvoidDistanceStart.x + takeOffAvoidDistanceEnd.x) / 2f - 15, (float) avoidHeight); } } private void drawControls(SpriteBatch controlsBatch) { if (!screenshotInProgress) { float w = Gdx.graphics.getWidth(); float h = Gdx.graphics.getHeight(); camFixed = new OrthographicCamera(w, h); camFixed.position.set(camFixed.viewportWidth / 2f, camFixed.viewportHeight / 2f, 0); camFixed.update(); controlsBatch.setProjectionMatrix(camFixed.combined); if (controls != null) { for (int i = 0; i < controls.size(); i++) { this.controls.get(i).setScale(controlWidth.get(i) * 0.002f); this.controls.get(i).setPosition(controlStartX.get(i), controlStartY.get(i)); this.controls.get(i).draw(controlsBatch); } } } } public void toggleIsLanding() { this.isLanding = !this.isLanding; } public void toggleApproachFromLeft() { this.isApproachingFromLeft = !this.isApproachingFromLeft; } private Vector2 transformToScreenCoords(Vector2 pos) { float posX; float posY; double leftStopwayLength = runway.getOriginalLogicalRunwayFromRight().stopwayLength; double rightStopwayLength = runway.getOriginalLogicalRunwayFromLeft().stopwayLength; double runwayLength = runway.getOriginalLogicalRunwayFromLeft().lda; double runwayAreaWidth = 500.0; posX = (float) (Gdx.graphics.getWidth() * pos.x / (leftStopwayLength + runwayLength + rightStopwayLength)); if (currentDisplay == VisualisationType.TopDown) { posY = (float) ((Gdx.graphics.getHeight() * (3.27f / 4.0f) + (Gdx.graphics .getHeight() * pos.y / runwayAreaWidth))); } else { posY = (float) ((Gdx.graphics.getHeight() / 4.0f) - (Gdx.graphics .getHeight() / (20.0f))) + 2.7f; } return new Vector2(posX, posY); } private Vector2 transformToScreenCoords(double x, double y) { return transformToScreenCoords(new Vector2((float) x, (float) y)); } private Vector2 getRelativeObstructionPosition(Obstruction o) { return new Vector2(transformToScreenCoords(o.getPositionAlongRunway(), o.getDistanceFromRunway()).x, VisPanel.SIDE_VIEW_GROUND_HEIGHT + offsetY); } public void update(float deltaTime) { float rateOfChangePosX = 25.0f; // isApproachingFromLeft = true; currentPlane.setFlip(!isApproachingFromLeft, false); currentLogicalRunway = isApproachingFromLeft ? runway .getLeftLandLogicalRunway() : runway .getRightLandLogicalRunway(); currentPlane.setPosition( currentPlane.getX() + (isApproachingFromLeft ? rateOfChangePosX : -rateOfChangePosX) * deltaTime, currentPlane.getY()); if (currentPlane.getX() > width - 200) currentPlane.setPosition(0, currentPlane.getY()); else if (!isApproachingFromLeft && currentPlane.getX() <= rateOfChangePosX) currentPlane.setPosition(width - 300, currentPlane.getY()); Obstruction o = runway.getFirstObstruction(); if (o != null) { if (isObstacleValid()) { this.currentObstacle.setSize(70, 25); float yOffset = (currentDisplay == VisualisationType.TopDown) ? 0.07f : -0.8f; Vector2 obstructionDrawPosition = transformToScreenCoords(new Vector2( (float) (o.getPositionAlongRunway() - 0.5 * currentObstacle .getWidth()), (float) (o .getDistanceFromRunway() + yOffset))); this.currentObstacle.setPosition(obstructionDrawPosition.x, obstructionDrawPosition.y); } else { this.currentObstacle.setPosition(0, 0); } } } }