diff --git a/doc/examples/config.json b/doc/examples/config.json index 80c3b3e4..856bac25 100644 --- a/doc/examples/config.json +++ b/doc/examples/config.json @@ -5,27 +5,27 @@ "teams": [ { "team-name": "Oracle Team USA", - "velocity": 30.9 + "velocity": 60.0 }, { "team-name": "Artemis Racing", - "velocity": 59.3 + "velocity": 10.0 }, { "team-name": "Emirates Team New Zealand", - "velocity": 51.5 + "velocity": 90.0 }, { "team-name": "Groupama Team France", - "velocity": 29.9 + "velocity": 15.0 }, { "team-name": "Land Rover BAR", - "velocity": 99.6 + "velocity": 70.0 }, { "team-name": "SoftBank Team Japan", - "velocity": 45.6 + "velocity": 45.0 } ] } \ No newline at end of file diff --git a/src/main/java/seng302/controllers/CanvasController.java b/src/main/java/seng302/controllers/CanvasController.java index 437926bc..16ac28e6 100644 --- a/src/main/java/seng302/controllers/CanvasController.java +++ b/src/main/java/seng302/controllers/CanvasController.java @@ -48,6 +48,7 @@ public class CanvasController { @FXML private AnchorPane contentAnchorPane; + @FXML private Text windArrowText, windDirectionText; @@ -132,7 +133,6 @@ public class CanvasController { */ public void initialize() { gc = canvas.getGraphicsContext2D(); - //gc.scale(2, 2); RaceController raceController = new RaceController(); raceController.initializeRace(); race = raceController.getRace(); @@ -145,9 +145,6 @@ public class CanvasController { @Override public void handle(long now) { if (now - lastUpdate >= 33000000){ - gc.clearRect(0, 0, 19200, 10800); - drawCourse(); - drawBoats(); gc.clearRect(0, 0, canvas.getWidth(),canvas.getHeight()); gc.setFill(Color.SKYBLUE); gc.fillRect(0,0,canvas.getWidth(),canvas.getHeight()); @@ -163,14 +160,17 @@ public class CanvasController { else if (race.getRaceTime() < 1 || raceStatus == Animation.Status.RUNNING){ pauseTimelines(); } - lastUpdate = now; } - } }; - generateTimelines(); + try{ + generateTimelines(); + } + catch (Exception e){ + e.printStackTrace(); + } timer.start(); loadTimerView(); @@ -229,7 +229,10 @@ public class CanvasController { } else { keyFrames.add( new KeyFrame(Duration.seconds(event.getTime() / 60 / 60 / 5), - onFinished -> teamPositionsController.handleEvent(event), + onFinished ->{ + teamPositionsController.handleEvent(event); + boat.setHeading(event.getBoatHeading()); + }, new KeyValue(x, event.getThisMark().getLatitude()), new KeyValue(y, event.getThisMark().getLongitude()) ) @@ -248,10 +251,34 @@ public class CanvasController { private void drawBoats() { for (Boat boat : timelineInfos.keySet()) { TimelineInfo timelineInfo = timelineInfos.get(boat); - drawBoat(timelineInfo.getX().doubleValue(), timelineInfo.getY().doubleValue(), boat.getColor(), boat.getTeamName(), boat.getSpeedInKnots()); + + boat.setLocation(timelineInfo.getY().doubleValue(), timelineInfo.getX().doubleValue()); + + drawBoat(boat.getLongitude(), boat.getLatitude(), boat.getColor(), boat.getTeamName(), boat.getSpeedInKnots(), boat.getHeading()); } } + /** + * Draw the wake line behind a boat + * @param gc The graphics context used for drawing the wake + * @param x the x position of the boat + * @param y the y position of the boat + * @param speed the speed of the boat + * @param color the color of the wake line + * @param heading the heading of the boat + */ + private void drawWake(GraphicsContext gc, double x, double y, double speed, Color color, double heading){ + double angle = Math.toRadians(heading); + + double newX = x + speed * Math.cos(angle);//(nextX * Math.cos(angle) - nextY * Math.sin(angle)) * length; + double newY = y + speed * Math.sin(angle);//(nextX * Math.sin(angle) + nextY * Math.cos(angle)) * length; + + gc.setStroke(color); + gc.setLineWidth(1.0); + + gc.strokeLine(x+5, y+5, newX, newY); + } + /** * Draws a boat with given (x, y) position in the given color * @@ -259,7 +286,7 @@ public class CanvasController { * @param lon * @param color */ - private void drawBoat(double lat, double lon, Color color, String name, double speed) { + private void drawBoat(double lat, double lon, Color color, String name, double speed, double heading) { // Latitude double x = (lon - ORIGIN_LON) * SCALE; double y = (ORIGIN_LAT - lat) * SCALE; @@ -274,6 +301,7 @@ public class CanvasController { gc.fillText(name + ", " + speed + " knots",x+15,y+15); gc.fillOval(x, y, diameter, diameter); + drawWake(gc, x, y, speed, color, heading); } /** diff --git a/src/main/java/seng302/models/Boat.java b/src/main/java/seng302/models/Boat.java index 0403f76d..a64bf9c4 100644 --- a/src/main/java/seng302/models/Boat.java +++ b/src/main/java/seng302/models/Boat.java @@ -14,6 +14,7 @@ public class Boat { private double distanceToNextMark; private Color color; private int markLastPast; + private double heading; public Boat(String teamName) { this.teamName = teamName; @@ -110,4 +111,12 @@ public class Boat { public int getMarkLastPast() { return markLastPast; } + + public void setHeading(double heading){ + this.heading = heading; + } + + public double getHeading(){ + return this.heading; + } } \ No newline at end of file diff --git a/src/main/java/seng302/models/Event.java b/src/main/java/seng302/models/Event.java index 5f4dde72..576c1e44 100644 --- a/src/main/java/seng302/models/Event.java +++ b/src/main/java/seng302/models/Event.java @@ -17,6 +17,11 @@ public class Event { private Mark mark2; // Next mark private int markPosInRace; // the position of the current mark in the race course + private final double ORIGIN_LAT = 32.320504; + private final double ORIGIN_LON = -64.857063; + private final double SCALE = 16000; + + /** * Event class containing the time of specific event, related team/boat, and @@ -95,7 +100,6 @@ public class Event { * @return the distance between the two marks */ public double getDistanceBetweenMarks() { - //return Math.sqrt(Math.pow(mark1.getLatitude()-mark2.getLatitude(), 2) + Math.pow(mark1.getLongitude()-mark2.getLongitude(), 2)); double earth_radius = 6378.137; double dLat = this.mark2.getLatitude() * Math.PI / 180 - this.mark1.getLatitude() * Math.PI / 180; double dLon = this.mark2.getLongitude() * Math.PI / 180 - this.mark1.getLongitude() * Math.PI / 180; @@ -112,11 +116,23 @@ public class Event { * @return the boats heading */ public double getBoatHeading() { - double bearing = Math.atan2(mark2.getLatitude() - mark1.getLatitude(), mark2.getLongitude() - mark1.getLongitude()); - if (bearing < 0) { - bearing += Math.PI * 2; + if (mark2 == null){ + return 0.0; } - return bearing * 180 / Math.PI; + + double x1 = (mark1.getLongitude() - ORIGIN_LON) * SCALE; + double y1 = (ORIGIN_LAT - mark1.getLatitude()) * SCALE; + double x2 = (mark2.getLongitude() - ORIGIN_LON) * SCALE; + double y2 = (ORIGIN_LAT - mark2.getLatitude()) * SCALE; + + double headingRadians = Math.atan2(y2-y1, x2-x1); + + if (headingRadians < 0){ + headingRadians += 2 * Math.PI; + } + + // Convert back to degrees, and flip 180 degrees + return (Math.toDegrees(headingRadians) + 180) % 360; } public Mark getThisMark() { diff --git a/src/main/java/seng302/models/mark/GateMark.java b/src/main/java/seng302/models/mark/GateMark.java index edf4f4ec..2b152e65 100644 --- a/src/main/java/seng302/models/mark/GateMark.java +++ b/src/main/java/seng302/models/mark/GateMark.java @@ -39,10 +39,12 @@ public class GateMark extends Mark { } public double getLatitude(){ - return (this.getSingleMark1().getLatitude() + this.getSingleMark2().getLatitude()) / 2; + //return (this.getSingleMark1().getLatitude() + this.getSingleMark2().getLatitude()) / 2; + return (this.getSingleMark1().getLatitude()); } public double getLongitude(){ - return (this.getSingleMark1().getLongitude() + this.getSingleMark2().getLongitude()) / 2; + //return (this.getSingleMark1().getLongitude() + this.getSingleMark2().getLongitude()) / 2; + return (this.getSingleMark1().getLongitude()); } } diff --git a/src/main/java/seng302/models/mark/Mark.java b/src/main/java/seng302/models/mark/Mark.java index 08d1f1eb..3e635856 100644 --- a/src/main/java/seng302/models/mark/Mark.java +++ b/src/main/java/seng302/models/mark/Mark.java @@ -33,7 +33,7 @@ public abstract class Mark { } public void setName(String name) { - this.name = name; + this.name = name; } public MarkType getMarkType() {