diff --git a/src/main/java/seng302/controllers/CanvasController.java b/src/main/java/seng302/controllers/CanvasController.java index dbce6849..56b24f55 100644 --- a/src/main/java/seng302/controllers/CanvasController.java +++ b/src/main/java/seng302/controllers/CanvasController.java @@ -6,20 +6,19 @@ import javafx.fxml.FXML; import javafx.geometry.Point2D; import javafx.geometry.Point3D; import javafx.scene.Group; -import javafx.scene.Node; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.layout.AnchorPane; import javafx.scene.paint.Color; +import javafx.scene.shape.Arc; +import javafx.scene.shape.ArcType; import javafx.scene.text.Font; -import javafx.util.Pair; import seng302.models.Boat; import seng302.models.BoatGroup; import seng302.models.Colors; import seng302.models.RaceObject; import seng302.models.mark.*; import seng302.models.parsers.StreamParser; -import seng302.models.parsers.StreamReceiver; import java.sql.Time; import java.text.DecimalFormat; @@ -40,14 +39,13 @@ public class CanvasController { private GraphicsContext gc; private final int MARK_SIZE = 10; - private final int BUFFER_SIZE = 100; + private final int BUFFER_SIZE = 150; private final int CANVAS_WIDTH = 1000; private final int CANVAS_HEIGHT = 1000; private final int LHS_BUFFER = BUFFER_SIZE; private final int RHS_BUFFER = BUFFER_SIZE + MARK_SIZE / 2; private final int TOP_BUFFER = BUFFER_SIZE; private final int BOT_BUFFER = TOP_BUFFER + MARK_SIZE / 2; - private final int FRAME_RATE = 60; private double distanceScaleFactor; private ScaleDirection scaleDirection; @@ -88,8 +86,8 @@ public class CanvasController { // Bind canvas size to stack pane size. canvas.widthProperty().bind(new SimpleDoubleProperty(CANVAS_WIDTH)); canvas.heightProperty().bind(new SimpleDoubleProperty(CANVAS_HEIGHT)); - group.minWidth(CANVAS_WIDTH); - group.minHeight(CANVAS_HEIGHT); + //group.minWidth(CANVAS_WIDTH); + //group.minHeight(CANVAS_HEIGHT); } public void initializeCanvas (){ @@ -99,55 +97,9 @@ public class CanvasController { gc.setFill(Color.SKYBLUE); gc.fillRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT); gc.restore(); - drawCourse(); + fitMarksToCanvas(); drawBoats(); -// drawFps(12); -// // overriding the handle so that it can clean canvas and redraw boats and course marks -// AnimationTimer timer = new AnimationTimer() { -// private long lastUpdate = 0; -// private long lastFpsUpdate = 0; -// private int lastFpsCount = 0; -// private int fpsCount = 0; -// boolean done = true; -// -// @Override -// public void handle(long now) { -// if (true){ //if statement for limiting refresh rate if needed -//// gc.clearRect(0, 0, canvas.getWidth(),canvas.getHeight()); -//// gc.setFill(Color.SKYBLUE); -//// gc.fillRect(0,0,canvas.getWidth(),canvas.getHeight()); -// -// -// // If race has started, draw the boats and play the timeline -// if (raceViewController.getRace().getRaceTime() > 1) { -// raceViewController.playTimelines(); -// } -// // Race has not started, pause the timelines -// else { -// raceViewController.pauseTimelines(); -// } -// lastUpdate = now; -// fpsCount ++; -// if (now - lastFpsUpdate >= 1000000000){ -// lastFpsCount = fpsCount; -// fpsCount = 0; -// lastFpsUpdate = now; -// } -// } -// } -// }; -// timer.start(); - //try { - // Thread.sleep(10000); - //}catch (Exception e) { - // e.printStackTrace(); - //} - - - timer = new AnimationTimer() { - - private int countdown = 60; private int[] currentRaceMarker = {1, 1, 1, 1, 1, 1}; List marks = raceViewController.getRace().getCourse(); @@ -173,98 +125,18 @@ public class CanvasController { Double frameRate = 1_000_000_000.0 / elapsedNanosPerFrame ; drawFps(frameRate.intValue()); } - - //if (countdown == 0) { - //System.out.println("called the at"); - for (RaceObject raceObject : raceObjects) { - //if (currentRaceMarker[boatIndex] < marks.size()) { - //if (currentRaceMarker[boatIndex] == 6) { - // int debugLine = 4; - //} - //double xb4 = boatGroup.getLayoutX(); - //double yb4 = boatGroup.getLayoutY(); - //nextMark = marks.get(currentRaceMarker[boatIndex]); - - //descending = nextMark.getY() > boatGroup.getLayoutY(); - //leftToRight = nextMark.getX() < boatGroup.getLayoutX(); - raceObject.updatePosition(1000 / 60); - for (int id : raceObject.getRaceIds()) { - //System.out.println("id = " + id); - if (id != 0 && StreamParser.boatPositions.size() > 0) { - boolean test = StreamParser.boatPositions.containsKey(id); - if (StreamParser.boatPositions.containsKey((long) id)) { - Point3D p = StreamParser.boatPositions.get((long) id); - Point2D p2d = latLonToXY(p.getX(), p.getY()); - //System.out.println("p2d = " + p2d); - //System.out.println("p.toString() = " + p.toString()); - double heading = 360.0 / 0xffff * p.getZ(); - //System.out.println("heading = " + heading); - - raceObject.setDestination(p2d.getX(), p2d.getY(), heading, id); - - //raceObject.setDestination(p2d.getX(), p2d.getY(), id); - } - StreamParser.boatPositions.remove((long) id); - } - } - //Point3D p = StreamParser.boatPositions.get((long) raceObject.getRaceIds()[0]); - //System.out.println("boatGroup = " + boatGroup.getBoat().getId()); - //System.out.println("StreamParser.boatPositions.toString() = " + StreamParser.boatPositions.toString()); -// if (p != null) { -// Point2D p2d = latLonToXY(p.getX(), p.getY()); -// //System.out.println("p2d = " + p2d); -// if (!boatGroup.isSamePos(p2d)) { -// //System.out.println("p.toString() = " + p.toString()); -// double heading = 360.0 / 0xffff * p.getZ(); -// //System.out.println("heading = " + heading); -// -// -// -// boatGroup.setDestination(p2d.getX(), p2d.getY(), heading, boatGroup.getRaceIds()[0]); - - - - //boatGroup.setDestination(p2d.getX(), p2d.getY()); - // } - //} - -// if (descending && nextMark.getY() < boatGroup.getLayoutY()) { -// currentRaceMarker[boatIndex]++; -// boatGroup.setDestination( -// marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY() -// ); -// } else if (!descending && nextMark.getY() > boatGroup.getLayoutY()) { -// currentRaceMarker[boatIndex]++; -// boatGroup.setDestination( -// marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY() -// ); -// } else if (leftToRight && nextMark.getX() > boatGroup.getLayoutX()) { -// currentRaceMarker[boatIndex]++; -// boatGroup.setDestination( -// marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY() -// ); -// } else if (!leftToRight && nextMark.getX() < boatGroup.getLayoutX()) { -// currentRaceMarker[boatIndex]++; -// boatGroup.setDestination( -// marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY() -// ); - - -// double xnew = boatGroup.getLayoutX(); -// double ynew = boatGroup.getLayoutY(); -// double dx = xnew - xb4; -// double dy = ynew -yb4; -// raceFinished = false; -// boatIndex++; + for (RaceObject raceObject : raceObjects) { + raceObject.updatePosition(1000 / 60); + for (int id : raceObject.getRaceIds()) { + if (StreamParser.boatPositions.containsKey((long) id)) { + Point3D p = StreamParser.boatPositions.get((long) id); + Point2D p2d = latLonToXY(p.getX(), p.getY()); + double heading = 360.0 / 0xffff * p.getZ(); + raceObject.setDestination(p2d.getX(), p2d.getY(), heading, id); } - //} - //if (raceFinished) { - // System.out.println("DONZEO LADS"); - // this.stop(); - //} - //} else { - // countdown--; - //} + StreamParser.boatPositions.remove((long) id); + } + } } }; for (Mark m : raceViewController.getRace().getCourse()) { @@ -325,21 +197,22 @@ public class CanvasController { private void drawBoats() { // Map timelineInfos = raceViewController.getTimelineInfos(); List boats = raceViewController.getStartingBoats(); - System.out.println("raceObjects " + raceObjects); Double startingX = raceObjects.get(0).getLayoutX(); Double startingY = raceObjects.get(0).getLayoutY(); - Double firstMarkX = raceObjects.get(1).getLayoutX(); - Double firstMarkY = raceObjects.get(1).getLayoutY(); + Group boatAnnotations = new Group(); for (Boat boat : boats) { BoatGroup boatGroup = new BoatGroup(boat, Colors.getColor()); boatGroup.moveTo(startingX, startingY, 0d); // boatGroup.setDestination(firstMarkX, firstMarkY); boatGroup.forceRotation(); - group.getChildren().add(boatGroup); + //group.getChildren().add(boatGroup); raceObjects.add(boatGroup); + boatAnnotations.getChildren().add(boatGroup.getLowPriorityAnnotations()); // drawBoat(boat.getLongitude(), boat.getLatitude(), boat.getColor(), boat.getShortName(), boat.getSpeedInKnots(), boat.getHeading()); } + group.getChildren().add(boatAnnotations); + group.getChildren().addAll(raceObjects); } @@ -364,77 +237,10 @@ public class CanvasController { } } - /** - * Draws the course. - */ - private void drawCourse() { - fitToCanvas(); -// for (Mark mark : raceViewController.getRace().getCourse()) { -// if (mark.getMarkType() == MarkType.SINGLE_MARK) { -// drawSingleMark((SingleMark) mark, Color.BLACK); -// } else { -// drawGateMark((GateMark) mark); -// } -// } -// System.out.println("MIN/MAX POINTS"); -// System.out.println(minLatPoint.getName() + " " + minLatPoint.getX() + " " + minLatPoint.getY()); -// System.out.println(maxLatPoint.getName() + " " + maxLatPoint.getX() + " " + maxLatPoint.getY()); -// System.out.println(minLonPoint.getName() + " " + minLonPoint.getX() + " " + minLonPoint.getY()); -// System.out.println(maxLonPoint.getName() + " " + maxLonPoint.getX() + " " + maxLonPoint.getY()); -// System.out.println(referencePointX); -// System.out.println(referencePointY); - } - -// /** -// * Draw a given mark on canvas -// * -// * @param singleMark -// */ -// private void drawSingleMark(SingleMark singleMark, Color color) { -// gc.setFill(color); -// System.out.println("DRAWING " + singleMark.getName() + " at " + singleMark.getX() + ", " + singleMark.getY()); -// gc.fillOval(singleMark.getX(), singleMark.getY(),MARK_SIZE,MARK_SIZE); -// } -// -// /** -// * Draw a gate mark which contains two single marks -// * -// * @param gateMark -// */ -// private void drawGateMark(GateMark gateMark) { -// Color color = Color.BLUE; -// -// if (gateMark.getName().equals("Start")){ -// color = Color.GREEN; -// } -// -// if (gateMark.getName().equals("Finish")){ -// color = Color.RED; -// } -// -// drawSingleMark(gateMark.getSingleMark1(), color); -// drawSingleMark(gateMark.getSingleMark2(), color); -// -// GraphicsContext gc = canvas.getGraphicsContext2D(); -// gc.save(); -// gc.setStroke(color); -// if (gateMark.getMarkType() == MarkType.OPEN_GATE) -// gc.setLineDashes(3, 5); -// -// gc.setLineWidth(2); -// gc.strokeLine( -// gateMark.getSingleMark1().getX() + MARK_SIZE / 2, -// gateMark.getSingleMark1().getY() + MARK_SIZE / 2, -// gateMark.getSingleMark2().getX() + MARK_SIZE / 2, -// gateMark.getSingleMark2().getY() + MARK_SIZE / 2 -// ); -// gc.restore(); -// } - /** * Calculates x and y location for every marker that fits it to the canvas the race will be drawn on. */ - private void fitToCanvas() { + private void fitMarksToCanvas() { findMinMaxPoint(); double minLonToMaxLon = scaleRaceExtremities(); calculateReferencePointLocation(minLonToMaxLon); @@ -469,16 +275,6 @@ public class CanvasController { Collections.reverse(sortedPoints); minLonPoint = sortedPoints.get(0); maxLonPoint = sortedPoints.get(sortedPoints.size()-1); - System.out.println("ALL POINTS"); - for (Mark m : sortedPoints) - { - System.out.println(m.getName() + " " + m.getLatitude() + " " + m.getLongitude()); - } - System.out.println("MIN/MAX POINTS"); - System.out.println(minLatPoint.getName() + " " + minLatPoint.getLatitude() + " " + minLatPoint.getLongitude()); - System.out.println(maxLatPoint.getName() + " " + maxLatPoint.getLatitude() + " " + maxLatPoint.getLongitude()); - System.out.println(minLonPoint.getName() + " " + minLonPoint.getLatitude() + " " + minLonPoint.getLongitude()); - System.out.println(maxLonPoint.getName() + " " + maxLonPoint.getLatitude() + " " + maxLonPoint.getLongitude()); } /** @@ -490,20 +286,11 @@ public class CanvasController { private void calculateReferencePointLocation (double minLonToMaxLon) { Mark referencePoint = minLatPoint; double referenceAngle; - //double mapWidth = canvas.getWidth(); - //double mapHeight = canvas.getHeight(); if (scaleDirection == ScaleDirection.HORIZONTAL) { - System.out.println("HORIZONTAL"); - System.out.println("ref angle " + Mark.calculateHeadingRad(referencePoint, minLonPoint)); - //referenceAngle = Mark.calculateHeadingRad(referencePoint, minLonPoint) - (Math.PI * (3/4)); referenceAngle = Math.abs(Mark.calculateHeadingRad(referencePoint, minLonPoint)); referencePointX = LHS_BUFFER + distanceScaleFactor * Math.sin(referenceAngle) * Mark.calculateDistance(referencePoint, minLonPoint); - //referenceAngle = Mark.calculateHeadingRad(referencePoint, maxLatPoint); - //if (referenceAngle > Math.PI) { - // referenceAngle = (Math.PI * 2) - referenceAngle; - //} referenceAngle = Math.abs(Mark.calculateHeadingRad(referencePoint, maxLatPoint)); referencePointY = CANVAS_HEIGHT - (TOP_BUFFER + BOT_BUFFER); referencePointY -= distanceScaleFactor * Math.cos(referenceAngle) * Mark.calculateDistance(referencePoint, maxLatPoint); @@ -511,20 +298,13 @@ public class CanvasController { referencePointY += TOP_BUFFER; referencePointY += distanceScaleFactor * Math.cos(referenceAngle) * Mark.calculateDistance(referencePoint, maxLatPoint); } else { - System.out.println("VERTICAL"); referencePointY = CANVAS_HEIGHT - BOT_BUFFER; - //referenceAngle = (Math.PI * 2) - Mark.calculateHeadingRad(referencePoint, minLonPoint); referenceAngle = Math.abs(Mark.calculateHeadingRad(referencePoint, minLonPoint)); - referencePointX = LHS_BUFFER; referencePointX += distanceScaleFactor * Math.sin(referenceAngle) * Mark.calculateDistance(referencePoint, minLonPoint); referencePointX += ((CANVAS_WIDTH - (LHS_BUFFER + RHS_BUFFER)) - (minLonToMaxLon * distanceScaleFactor)) / 2; } - referencePointX = Math.round(referencePointX); - referencePointY = Math.round(referencePointY); -// referencePoint.setX((int) referencePointX); -// referencePoint.setY((int) referencePointY); } /** @@ -532,13 +312,11 @@ public class CanvasController { * Returns the max horizontal distance of the map. */ private double scaleRaceExtremities () { - //double vertAngle = Mark.calculateHeadingRad(minLatPoint, maxLatPoint); - double vertAngle = Math.abs(Mark.calculateHeadingRad(minLatPoint, maxLatPoint)); -// if (vertAngle > Math.PI) -// vertAngle = (2 * Math.PI) - vertAngle; - double vertDistance = Math.cos(vertAngle) * Mark.calculateDistance(minLatPoint, maxLatPoint); + double vertAngle = Math.abs(Mark.calculateHeadingRad(minLatPoint, maxLatPoint)); + double vertDistance = Math.cos(vertAngle) * Mark.calculateDistance(minLatPoint, maxLatPoint); double horiAngle = Mark.calculateHeadingRad(minLonPoint, maxLonPoint); + if (horiAngle <= (Math.PI / 2)) horiAngle = (Math.PI / 2) - horiAngle; else @@ -562,34 +340,19 @@ public class CanvasController { * are scaled according to the distanceScaleFactor variable. */ private void givePointsXY() { - //Point2D canvasLocation; List allPoints = new ArrayList<>(raceViewController.getRace().getCourse()); List processed = new ArrayList<>(); - //Set unqiuePoints = new HashSet<>(raceViewController.getRace().getCourse()); - //System.out.println("unqiuePoints = " + unqiuePoints); RaceObject markGroup; for (Mark mark : allPoints) { if (!processed.contains(mark)) { if (mark.getMarkType() != MarkType.SINGLE_MARK) { GateMark gateMark = (GateMark) mark; -// canvasLocation = findScaledXY(gateMark.getSingleMark1()); -// gateMark.getSingleMark1().setX((int) canvasLocation.getX()); -// gateMark.getSingleMark1().setY((int) canvasLocation.getY()); -// -// canvasLocation = findScaledXY(gateMark.getSingleMark2()); -// gateMark.getSingleMark2().setX((int) canvasLocation.getX()); -// gateMark.getSingleMark2().setY((int) canvasLocation.getY()); - markGroup = new MarkGroup(mark, findScaledXY(gateMark.getSingleMark1()), findScaledXY(gateMark.getSingleMark2())); - group.getChildren().add(markGroup); raceObjects.add(markGroup); } else { -// canvasLocation = findScaledXY(mark); -// mark.setX((int) canvasLocation.getX()); -// mark.setY((int) canvasLocation.getY()); markGroup = new MarkGroup(mark, findScaledXY(mark)); - group.getChildren().add(markGroup); + raceObjects.add(markGroup); } processed.add(mark); } @@ -597,7 +360,6 @@ public class CanvasController { } private Point2D findScaledXY (Mark unscaled) { - System.out.println("unscaled.getName() = " + unscaled.getName()); return findScaledXY (minLatPoint.getLatitude(), minLatPoint.getLongitude(), unscaled.getLatitude(), unscaled.getLongitude()); } @@ -611,35 +373,21 @@ public class CanvasController { angleFromReference = Mark.calculateHeadingRad(latA, lonA, latB, lonB); distanceFromReference = Mark.calculateDistance(latA, lonA, latB, lonB); if (angleFromReference >= 0 && angleFromReference <= Math.PI / 2) { - //System.out.println("1"); xAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); yAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); } else if (angleFromReference >= 0) { - //System.out.println("2"); angleFromReference = angleFromReference - Math.PI / 2; xAxisLocation += (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); yAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); } else if (angleFromReference < 0 && angleFromReference >= -Math.PI / 2) { - //System.out.println("3"); -// System.out.println(distanceFromReference); angleFromReference = Math.abs(angleFromReference); -// System.out.println(Math.cos(angleFromReference) * distanceFromReference); xAxisLocation -= (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); yAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); } else { - //System.out.println("4"); angleFromReference = Math.abs(angleFromReference) - Math.PI / 2; xAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); yAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); } -// if (angleFromReference > (Math.PI / 2)) { -// angleFromReference = (Math.PI * 2) - angleFromReference; -// xAxisLocation -= (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); -// } else { -// xAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); -// } -// yAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); - //System.out.println(xAxisLocation + " *** " + yAxisLocation); return new Point2D(xAxisLocation, yAxisLocation); } @@ -676,4 +424,8 @@ public class CanvasController { private Point2D latLonToXY (double latitude, double longitude) { return findScaledXY(minLatPoint.getLatitude(), minLatPoint.getLongitude(), latitude, longitude); } + + List getRaceObjects() { + return raceObjects; + } } \ No newline at end of file diff --git a/src/main/java/seng302/controllers/RaceViewController.java b/src/main/java/seng302/controllers/RaceViewController.java index ad7756f0..a15fc8dc 100644 --- a/src/main/java/seng302/controllers/RaceViewController.java +++ b/src/main/java/seng302/controllers/RaceViewController.java @@ -15,10 +15,7 @@ import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.text.Text; import javafx.util.Duration; -import seng302.models.Boat; -import seng302.models.Event; -import seng302.models.Race; -import seng302.models.TimelineInfo; +import seng302.models.*; import seng302.models.parsers.ConfigParser; import seng302.models.parsers.StreamParser; @@ -303,4 +300,11 @@ public class RaceViewController extends Thread{ public ArrayList getStartingBoats(){ return startingBoats; } + + @FXML + private void toggleAnnotations () { + for (RaceObject ro : includedCanvasController.getRaceObjects()) { + ro.toggleAnnotations(); + } + } } \ No newline at end of file diff --git a/src/main/java/seng302/models/BoatGroup.java b/src/main/java/seng302/models/BoatGroup.java index 46887e5a..26c94e10 100644 --- a/src/main/java/seng302/models/BoatGroup.java +++ b/src/main/java/seng302/models/BoatGroup.java @@ -1,45 +1,42 @@ package seng302.models; import javafx.geometry.Point2D; -import javafx.scene.Node; +import javafx.scene.Group; import javafx.scene.paint.Color; import javafx.scene.shape.Line; import javafx.scene.shape.Polygon; import javafx.scene.text.Text; import javafx.scene.transform.Rotate; -import javafx.scene.transform.Translate; import seng302.models.parsers.StreamParser; -import java.util.ArrayList; -import java.util.List; - /** * Created by CJIRWIN on 25/04/2017. */ public class BoatGroup extends RaceObject{ - private static final double TEAMNAME_X_OFFSET = 15d; - private static final double TEAMNAME_Y_OFFSET = -20d; - private static final double VELOCITY_X_OFFSET = 15d; - private static final double VELOCITY_Y_OFFSET = -10d; + private static final double TEAMNAME_X_OFFSET = 10d; + private static final double TEAMNAME_Y_OFFSET = -15d; + private static final double VELOCITY_X_OFFSET = 10d; + private static final double VELOCITY_Y_OFFSET = -5d; private static final double VELOCITY_WAKE_RATIO = 2d; private static final double BOAT_HEIGHT = 15d; private static final double BOAT_WIDTH = 10d; - //Time between sections of race - Should be changed to 200 for actual program. + private static final int LINE_INTERVAL = 180; private static double expectedUpdateInterval = 200; private static int WAKE_FRAME_INTERVAL = 30; private double framesForNewLine = 0; private boolean destinationSet; private Point2D lastPoint; + private int wakeGenerationDelay; private Boat boat; private int wakeCounter = WAKE_FRAME_INTERVAL; - private List wakes = new ArrayList<>(); - private List lines = new ArrayList<>(); + private Group lineGroup = new Group(); + private Group wakeGroup = new Group(); private Polygon boatPoly; - private Polygon wakePoly; private Text teamNameObject; private Text velocityObject; + private Wake wake; public BoatGroup (Boat boat, Color color){ this.boat = boat; @@ -54,16 +51,6 @@ public class BoatGroup extends RaceObject{ private void initChildren (Color color, double... points) { boatPoly = new Polygon(points); boatPoly.setFill(color); -// boatPoly.setLayoutX(0); -// boatPoly.setLayoutY(0); -// boatPoly.relocate(boatPoly.getLayoutX(), boatPoly.getLayoutY()); -// - wakePoly = new Polygon( - 5.0,0.0, - 10.0, boat.getVelocity() * VELOCITY_WAKE_RATIO, - 0.0, boat.getVelocity() * VELOCITY_WAKE_RATIO - ); - wakePoly.setFill(Color.DARKBLUE); teamNameObject = new Text(boat.getShortName()); velocityObject = new Text(String.valueOf(boat.getVelocity())); @@ -76,14 +63,17 @@ public class BoatGroup extends RaceObject{ velocityObject.setY(VELOCITY_Y_OFFSET); velocityObject.relocate(velocityObject.getX(), velocityObject.getY()); destinationSet = false; - super.getChildren().addAll(wakePoly, boatPoly, teamNameObject, velocityObject); + + wake = new Wake(0, 0); + wakeGenerationDelay = wake.numWakes; + super.getChildren().addAll(teamNameObject, velocityObject, boatPoly); } private void initChildren (Color color) { initChildren(color, - BOAT_WIDTH / 2, 0.0, - BOAT_WIDTH, BOAT_HEIGHT, - 0.0, BOAT_HEIGHT); + -BOAT_WIDTH / 2, BOAT_HEIGHT, + 0.0, 0.0, + BOAT_WIDTH / 2, BOAT_HEIGHT); } /** @@ -98,9 +88,9 @@ public class BoatGroup extends RaceObject{ teamNameObject.setLayoutY(teamNameObject.getLayoutY() + dy); velocityObject.setLayoutX(velocityObject.getLayoutX() + dx); velocityObject.setLayoutY(velocityObject.getLayoutY() + dy); - wakePoly.setLayoutX(wakePoly.getLayoutX() + dx); - wakePoly.setLayoutY(wakePoly.getLayoutY() + dy); - rotateTo(currentRotation); + wake.setLayoutX(wake.getLayoutX() + dx); + wake.setLayoutY(wake.getLayoutY() + dy); + rotateTo(rotation + currentRotation); } /** @@ -120,78 +110,55 @@ public class BoatGroup extends RaceObject{ teamNameObject.setLayoutY(y); velocityObject.setLayoutX(x); velocityObject.setLayoutY(y); - wakePoly.setLayoutX(x); - wakePoly.setLayoutY(y); + wake.setLayoutX(x); + wake.setLayoutY(y); + wake.rotate(currentRotation); } - public void updatePosition (double timeInterval) { + public void updatePosition (long timeInterval) { double dx = pixelVelocityX * timeInterval; double dy = pixelVelocityY * timeInterval; double rotation = 0d; - if (rotationalGoal > currentRotation && rotationalVelocity > 0) { - rotation = rotationalVelocity * timeInterval; - } else if (rotationalGoal < currentRotation && rotationalVelocity < 0) { - rotation = rotationalVelocity * timeInterval; - } - moveGroupBy(dx, dy, rotation); -// if (super.getChildren().size() > 3) { -// for (Node wake : super.getChildren().subList(4, super.getChildren().size())) { -// if (!((Wake) wake).updatePosition(timeInterval)) -// super.getChildren().remove(wake); -// } -// } - for (Wake wake : wakes) { - if (wake.updatePosition(timeInterval)) { - super.getChildren().remove(wake); - } - } - if (wakeCounter-- == 0) { -// if (boat.getShortName().equals("BAR")) -// System.out.println("thinking"); - wakeCounter = WAKE_FRAME_INTERVAL; - if (pixelVelocityX > 0 && pixelVelocityY > 0) { -// super.getChildren().add( -// new Wake( -// super.getLayoutX() + BOAT_HEIGHT, super.getLayoutY() + BOAT_HEIGHT, pixelVelocityX, pixelVelocityY -// ) -// ); - Wake wake = new Wake( - boatPoly.getLayoutX(), - boatPoly.getLayoutY(), - pixelVelocityX, - pixelVelocityY, - rotation); - super.getChildren().add(wake); - wakes.add(wake); - } - } - if (framesForNewLine == 0) { - framesForNewLine = 121; + moveGroupBy(dx, dy, rotation); + + if (framesForNewLine-- == 0) { + framesForNewLine = LINE_INTERVAL; if (lastPoint != null) { - Line l = new Line(lastPoint.getX(), lastPoint.getY(), boatPoly.getLayoutX(), boatPoly.getLayoutY()); - l.getStrokeDashArray().setAll(4d, 4d); - lines.add(l); - super.getChildren().add(l); + Line l = new Line( + lastPoint.getX(), + lastPoint.getY(), + boatPoly.getLayoutX(), + boatPoly.getLayoutY() + ); + l.getStrokeDashArray().setAll(4d, 6d); + l.setStroke(boatPoly.getFill()); + lineGroup.getChildren().add(l); } if (destinationSet){ lastPoint = new Point2D(boatPoly.getLayoutX(), boatPoly.getLayoutY()); } + if (lineGroup.getChildren().size() > 100) + lineGroup.getChildren().remove(0); } - framesForNewLine -= 1; + wake.updatePosition(timeInterval); } public void setDestination (double newXValue, double newYValue, double rotation, int... raceIds) { - //System.out.println("MADE IT"); destinationSet = true; boat.setVelocity(StreamParser.boatSpeeds.get((long)boat.getId())); - resizeWake(); if (hasRaceId(raceIds)) { this.pixelVelocityX = (newXValue - boatPoly.getLayoutX()) / expectedUpdateInterval; this.pixelVelocityY = (newYValue - boatPoly.getLayoutY()) / expectedUpdateInterval; this.rotationalGoal = rotation; calculateRotationalVelocity(); rotateTo(rotation); + if (wakeGenerationDelay > 0) { + wake.rotate(rotationalGoal); + wakeGenerationDelay--; + } else { + wake.setRotationalVelocity(rotationalVelocity, rotationalGoal, pixelVelocityX, pixelVelocityY); + } } } @@ -206,15 +173,6 @@ public class BoatGroup extends RaceObject{ ) ) ); - -// if (boatPoly.getLayoutY() >= newYValue && boatPoly.getLayoutX() <= newXValue) -// rotation = 90 - rotation; -// else if (boatPoly.getLayoutY() < newYValue && boatPoly.getLayoutX() <= newXValue) -// rotation = 90 + rotation; -// else if (boatPoly.getLayoutY() >= newYValue && boatPoly.getLayoutX() > newXValue) -// rotation = 270 + rotation; -// else -// rotation = 270 - rotation; setDestination(newXValue, newYValue, rotation, raceIDs); } } @@ -235,31 +193,23 @@ public class BoatGroup extends RaceObject{ } public void rotateTo (double rotation) { - if(rotation != 0) { - rotationalGoal = rotation; - boatPoly.getTransforms().clear(); - boatPoly.getTransforms().add(new Rotate(rotation, BOAT_WIDTH / 2, 0)); - wakePoly.getTransforms().clear(); - wakePoly.getTransforms().add(new Translate(0, BOAT_HEIGHT)); - wakePoly.getTransforms().add(new Rotate(rotation, BOAT_WIDTH/2, -BOAT_HEIGHT)); - } + currentRotation = rotation; + boatPoly.getTransforms().clear(); + boatPoly.getTransforms().add(new Rotate(rotation)); } public void forceRotation () { rotateTo (rotationalGoal); + wake.rotate(rotationalGoal); } public void toggleAnnotations () { teamNameObject.setVisible(!teamNameObject.isVisible()); velocityObject.setVisible(!velocityObject.isVisible()); - for (Wake wake : wakes) { - wake.setVisible(!wake.isVisible()); - } - for (Line line : lines) { - line.setVisible(!line.isVisible()); - } + lineGroup.setVisible(!lineGroup.isVisible()); + wake.setVisible(!wake.isVisible()); } public Boat getBoat() { @@ -277,4 +227,10 @@ public class BoatGroup extends RaceObject{ public int[] getRaceIds () { return new int[] {boat.getId()}; } + + public Group getLowPriorityAnnotations () { + Group group = new Group(); + group.getChildren().addAll(wake, lineGroup); + return group; + } } diff --git a/src/main/java/seng302/models/RaceObject.java b/src/main/java/seng302/models/RaceObject.java index a5dcf6f5..30ca28f3 100644 --- a/src/main/java/seng302/models/RaceObject.java +++ b/src/main/java/seng302/models/RaceObject.java @@ -4,11 +4,12 @@ import javafx.geometry.Point2D; import javafx.scene.Group; /** - * Created by CJIRWIN on 26/04/2017. + * RaceObject defines the behaviour that animated objects whose position is updated from a yacht race data stream must + * adhere to. */ public abstract class RaceObject extends Group { - //Time between sections of race - Should be changed to 200 for actual program. + //Time between sections of race protected static double expectedUpdateInterval = 200; protected double rotationalGoal; @@ -17,10 +18,6 @@ public abstract class RaceObject extends Group { protected double pixelVelocityX; protected double pixelVelocityY; - public boolean isSamePos (Point2D point) { - return point.getX() == super.getLayoutX() && point.getY() == super.getLayoutY(); - } - public Point2D getPosition () { return new Point2D(super.getLayoutX(), getLayoutY()); } @@ -45,11 +42,19 @@ public abstract class RaceObject extends Group { } } + /** + * Sets the destination of everything within the RaceObject that has an ID in the array raceIds. The destination is + * set to the co-ordinates (x, y) with the given rotation. + * @param x + * @param y + * @param rotation + * @param raceIds + */ public abstract void setDestination (double x, double y, double rotation, int... raceIds); public abstract void setDestination (double x, double y, int... raceIds); - public abstract void updatePosition (double timeInterval); + public abstract void updatePosition (long timeInterval); public abstract void moveTo (double x, double y, double rotation); @@ -64,5 +69,4 @@ public abstract class RaceObject extends Group { public abstract int[] getRaceIds (); public abstract void toggleAnnotations (); - } diff --git a/src/main/java/seng302/models/mark/MarkGroup.java b/src/main/java/seng302/models/mark/MarkGroup.java index eba7da82..ab189034 100644 --- a/src/main/java/seng302/models/mark/MarkGroup.java +++ b/src/main/java/seng302/models/mark/MarkGroup.java @@ -28,10 +28,6 @@ public class MarkGroup extends RaceObject { private Point2D[] nodeDestinations; public MarkGroup (Mark mark, Point2D... points) { -// for (Point2D p : points) { -// System.out.println("p.getX() = " + p.getX()); -// System.out.println("p.getY() = " + p.getY()); -// } marks.add(mark); mainMark = mark; Color color = Color.BLACK; @@ -43,9 +39,6 @@ public class MarkGroup extends RaceObject { System.out.println("HERE ARE THE CHILDREN LOL"); if (mark.getMarkType() == MarkType.SINGLE_MARK) { super.getChildren().add(new Circle(0, 0, MARK_RADIUS, color)); -// System.out.println("SingleMark?"); -// System.out.println("super.getChildren().get(0).getLayoutX() = " + super.getChildren().get(0).getLayoutX()); -// System.out.println("super.getChildren().get(0).getLayoutY() = " + super.getChildren().get(0).getLayoutY()); } else { marks.add(((GateMark) mark).getSingleMark1()); marks.add(((GateMark) mark).getSingleMark2()); @@ -57,13 +50,6 @@ public class MarkGroup extends RaceObject { color ) ); -// super.getChildren().add(new Circle(0, 0, MARK_RADIUS, color)); -// super.getChildren().get(0).setLayoutX((points[1].getX() - points[0].getX()) / 2d); -// super.getChildren().get(0).setLayoutY((points[1].getY() - points[0].getY()) / 2d); -// System.out.println("!!!!!!!!!!!!!!!!!"); -// System.out.println((points[1].getX() - points[0].getX()) / 2d); -// System.out.println((points[1].getY() - points[0].getY()) / 2d); -// System.out.println(super.getChildren().get(0)); super.getChildren().add( new Circle( -(points[1].getX() - points[0].getX()) / 2d, @@ -72,9 +58,6 @@ public class MarkGroup extends RaceObject { color ) ); -// super.getChildren().add(new Circle(0, 0, MARK_RADIUS, color)); -// super.getChildren().get(1).setLayoutX(-(points[1].getX() - points[0].getX()) / 2d); -// super.getChildren().get(1).setLayoutY(-(points[1].getY() - points[0].getY()) / 2d); Line line = new Line( (points[1].getX() - points[0].getX()) / 2d, (points[1].getY() - points[0].getY()) / 2d, @@ -93,22 +76,8 @@ public class MarkGroup extends RaceObject { new Point2D(super.getChildren().get(0).getLayoutX(), super.getChildren().get(0).getLayoutY()), new Point2D(super.getChildren().get(1).getLayoutX(), super.getChildren().get(1).getLayoutY()) }; -// nodeDestinations = new Point2D[]{new Point2D(0,0), new Point2D(0,0)}; -// System.out.println("super.getChildren().get(0).getLayoutX() = " + super.getChildren().get(0).getLayoutX()); -// System.out.println("super.getChildren().get(0).getLayoutY() = " + super.getChildren().get(0).getLayoutY()); -// System.out.println("super.getChildren().get(1).getLayoutX() = " + super.getChildren().get(1).getLayoutX()); -// System.out.println("super.getChildren().get(1).getLayoutY() = " + super.getChildren().get(1).getLayoutY()); } moveTo(points[0].getX(), points[0].getY()); -// System.out.println("OKAY HERE IS A MARK"); -// System.out.println("super.getLayoutX() = " + super.getLayoutX()); -// System.out.println("super.getLayoutY() = " + super.getLayoutY()); -// System.out.println("super.getChildren().get(0).getLayoutX() = " + super.getChildren().get(0).getLayoutX()); -// System.out.println("super.getChildren().get(0).getLayoutY() = " + super.getChildren().get(0).getLayoutY()); -// pixelVelocityX = 0; -// pixelVelocityY = 0; -// rotationalVelocity = 0; -// rotationalGoal = 0; } public void setDestination (double x, double y, double rotation, int... raceIds) { @@ -146,17 +115,10 @@ public class MarkGroup extends RaceObject { public void rotateTo (double rotation) { super.getTransforms().clear(); -// super.getTransforms().add( -// new Rotate( -// rotation, -// super.getChildren().get(1).getLayoutX() - super.getChildren().get(0).getLayoutX(), -// super.getChildren().get(1).getLayoutY() - super.getChildren().get(0).getLayoutY() -// ) -// ); - super.getTransforms().add(new Rotate(rotation, 0 , 0)); + super.getTransforms().add(new Rotate(rotation)); } - public void updatePosition (double timeInterval) { + public void updatePosition (long timeInterval) { double x = pixelVelocityX * timeInterval; double y = pixelVelocityY * timeInterval; double rotation = rotationalVelocity * timeInterval; diff --git a/src/main/resources/views/RaceView.fxml b/src/main/resources/views/RaceView.fxml index 556e2df6..6de979d4 100644 --- a/src/main/resources/views/RaceView.fxml +++ b/src/main/resources/views/RaceView.fxml @@ -1,10 +1,5 @@ - - - - - @@ -17,7 +12,7 @@ - + @@ -45,14 +40,14 @@ - + - +