mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Merge remote-tracking branch 'origin/30b/30c_boat_animation' into StreamReceiverMergeWithVisualiser
This commit is contained in:
@@ -1,19 +1,25 @@
|
|||||||
package seng302.controllers;
|
package seng302.controllers;
|
||||||
|
|
||||||
import javafx.animation.*;
|
import javafx.animation.*;
|
||||||
|
import javafx.beans.property.SimpleDoubleProperty;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.geometry.Point2D;
|
||||||
|
import javafx.scene.Group;
|
||||||
import javafx.scene.canvas.Canvas;
|
import javafx.scene.canvas.Canvas;
|
||||||
import javafx.scene.canvas.GraphicsContext;
|
import javafx.scene.canvas.GraphicsContext;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.scene.text.Font;
|
import javafx.scene.text.Font;
|
||||||
|
import javafx.util.Pair;
|
||||||
import seng302.models.Boat;
|
import seng302.models.Boat;
|
||||||
import seng302.models.TimelineInfo;
|
import seng302.models.BoatGroup;
|
||||||
|
import seng302.models.Colors;
|
||||||
import seng302.models.mark.GateMark;
|
import seng302.models.mark.GateMark;
|
||||||
import seng302.models.mark.Mark;
|
import seng302.models.mark.Mark;
|
||||||
import seng302.models.mark.MarkType;
|
import seng302.models.mark.MarkType;
|
||||||
import seng302.models.mark.SingleMark;
|
import seng302.models.mark.SingleMark;
|
||||||
|
|
||||||
|
import java.sql.Time;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,61 +33,174 @@ public class CanvasController {
|
|||||||
|
|
||||||
private RaceViewController raceViewController;
|
private RaceViewController raceViewController;
|
||||||
private ResizableCanvas canvas;
|
private ResizableCanvas canvas;
|
||||||
|
private Group group;
|
||||||
private GraphicsContext gc;
|
private GraphicsContext gc;
|
||||||
|
private List<BoatGroup> boatGroups = new ArrayList<>();
|
||||||
|
|
||||||
private final double ORIGIN_LAT = 32.321504;
|
private final int MARK_SIZE = 10;
|
||||||
private final double ORIGIN_LON = -64.857063;
|
private final int BUFFER_SIZE = 25;
|
||||||
private final int SCALE = 16000;
|
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;
|
||||||
|
private Mark minLatPoint;
|
||||||
|
private Mark minLonPoint;
|
||||||
|
private Mark maxLatPoint;
|
||||||
|
private Mark maxLonPoint;
|
||||||
|
private int referencePointX;
|
||||||
|
private int referencePointY;
|
||||||
|
private double metersToPixels;
|
||||||
|
|
||||||
|
public AnimationTimer timer;
|
||||||
|
|
||||||
|
private enum ScaleDirection {
|
||||||
|
HORIZONTAL,
|
||||||
|
VERTICAL
|
||||||
|
}
|
||||||
|
|
||||||
public void setup(RaceViewController raceViewController){
|
public void setup(RaceViewController raceViewController){
|
||||||
this.raceViewController = raceViewController;
|
this.raceViewController = raceViewController;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
raceViewController = new RaceViewController();
|
||||||
canvas = new ResizableCanvas();
|
canvas = new ResizableCanvas();
|
||||||
|
group = new Group();
|
||||||
|
|
||||||
canvasPane.getChildren().add(canvas);
|
canvasPane.getChildren().add(canvas);
|
||||||
|
canvasPane.getChildren().add(group);
|
||||||
// Bind canvas size to stack pane size.
|
// Bind canvas size to stack pane size.
|
||||||
canvas.widthProperty().bind(canvasPane.widthProperty());
|
canvas.widthProperty().bind(new SimpleDoubleProperty(CANVAS_WIDTH));
|
||||||
canvas.heightProperty().bind(canvasPane.heightProperty());
|
canvas.heightProperty().bind(new SimpleDoubleProperty(CANVAS_HEIGHT));
|
||||||
|
group.minWidth(CANVAS_WIDTH);
|
||||||
|
group.minHeight(CANVAS_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initializeCanvas (){
|
||||||
|
|
||||||
gc = canvas.getGraphicsContext2D();
|
gc = canvas.getGraphicsContext2D();
|
||||||
|
gc.save();
|
||||||
|
gc.setFill(Color.SKYBLUE);
|
||||||
|
gc.fillRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT);
|
||||||
|
gc.restore();
|
||||||
|
drawCourse();
|
||||||
|
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;
|
||||||
// overriding the handle so that it can clean canvas and redraw boats and course marks
|
private int[] currentRaceMarker = {1, 1, 1, 1, 1, 1};
|
||||||
AnimationTimer timer = new AnimationTimer() {
|
List<Mark> marks = raceViewController.getRace().getCourse();
|
||||||
private long lastUpdate = 0;
|
|
||||||
private long lastFpsUpdate = 0;
|
|
||||||
private int lastFpsCount = 0;
|
|
||||||
private int fpsCount = 0;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(long now) {
|
public void handle(long now) {
|
||||||
if (true){ //if statement for limiting refresh rate if needed
|
boolean raceFinished = true;
|
||||||
gc.clearRect(0, 0, canvas.getWidth(),canvas.getHeight());
|
boolean descending;
|
||||||
gc.setFill(Color.SKYBLUE);
|
boolean leftToRight;
|
||||||
gc.fillRect(0,0,canvas.getWidth(),canvas.getHeight());
|
int boatIndex = 0;
|
||||||
drawCourse();
|
Mark nextMark;
|
||||||
drawBoats();
|
if (countdown == 0) {
|
||||||
drawFps(lastFpsCount);
|
for (BoatGroup boatGroup : boatGroups) {
|
||||||
|
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]);
|
||||||
|
|
||||||
// If race has started, draw the boats and play the timeline
|
descending = nextMark.getY() > boatGroup.getLayoutY();
|
||||||
if (raceViewController.getRace().getRaceTime() > 1){
|
leftToRight = nextMark.getX() < boatGroup.getLayoutX();
|
||||||
raceViewController.playTimelines();
|
|
||||||
|
boatGroup.updatePosition(1000 / 60);
|
||||||
|
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()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// Race has not started, pause the timelines
|
|
||||||
else {
|
double xnew = boatGroup.getLayoutX();
|
||||||
raceViewController.pauseTimelines();
|
double ynew = boatGroup.getLayoutY();
|
||||||
|
double dx = xnew - xb4;
|
||||||
|
double dy = ynew -yb4;
|
||||||
|
raceFinished = false;
|
||||||
|
boatIndex++;
|
||||||
}
|
}
|
||||||
lastUpdate = now;
|
|
||||||
fpsCount ++;
|
|
||||||
if (now - lastFpsUpdate >= 1000000000){
|
|
||||||
lastFpsCount = fpsCount;
|
|
||||||
fpsCount = 0;
|
|
||||||
lastFpsUpdate = now;
|
|
||||||
}
|
}
|
||||||
|
if (raceFinished) {
|
||||||
|
System.out.println("DONZEO LADS");
|
||||||
|
this.stop();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
countdown--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
timer.start();
|
for (Mark m : raceViewController.getRace().getCourse())
|
||||||
|
System.out.println(m.getName());
|
||||||
|
//timer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResizableCanvas extends Canvas {
|
class ResizableCanvas extends Canvas {
|
||||||
@@ -129,76 +248,25 @@ public class CanvasController {
|
|||||||
* Draws all the boats.
|
* Draws all the boats.
|
||||||
*/
|
*/
|
||||||
private void drawBoats() {
|
private void drawBoats() {
|
||||||
Map<Boat, TimelineInfo> timelineInfos = raceViewController.getTimelineInfos();
|
// Map<Boat, TimelineInfo> timelineInfos = raceViewController.getTimelineInfos();
|
||||||
for (Boat boat : timelineInfos.keySet()) {
|
List<Boat> boats = raceViewController.getStartingBoats();
|
||||||
TimelineInfo timelineInfo = timelineInfos.get(boat);
|
List<Mark> marks = raceViewController.getRace().getCourse();
|
||||||
|
Double startingX = (double) marks.get(0).getX();
|
||||||
|
Double startingY = (double) marks.get(0).getY();
|
||||||
|
Double firstMarkX = (double) marks.get(1).getX();
|
||||||
|
Double firstMarkY = (double) marks.get(1).getY();
|
||||||
|
|
||||||
boat.setLocation(timelineInfo.getY().doubleValue(), timelineInfo.getX().doubleValue());
|
for (Boat boat : boats) {
|
||||||
|
BoatGroup boatGroup = new BoatGroup(boat, Colors.getColor());
|
||||||
drawBoat(boat.getLongitude(), boat.getLatitude(), boat.getColor(), boat.getShortName(), boat.getSpeedInKnots(), boat.getHeading());
|
boatGroup.moveBoatTo(startingX, startingY, 0d);
|
||||||
|
boatGroup.setDestination(firstMarkX, firstMarkY);
|
||||||
|
boatGroup.forceRotation();
|
||||||
|
group.getChildren().add(boatGroup);
|
||||||
|
boatGroups.add(boatGroup);
|
||||||
|
// drawBoat(boat.getLongitude(), boat.getLatitude(), boat.getColor(), boat.getShortName(), 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);
|
|
||||||
speed = speed * 2;
|
|
||||||
Point newP = new Point(0, speed);
|
|
||||||
newP.rotate(angle);
|
|
||||||
|
|
||||||
gc.setStroke(color);
|
|
||||||
gc.setLineWidth(1.0);
|
|
||||||
gc.strokeLine(x, y, newP.x + x, newP.y + y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Draws a boat with given (x, y) position in the given color
|
|
||||||
*
|
|
||||||
* @param lat
|
|
||||||
* @param lon
|
|
||||||
* @param color
|
|
||||||
* @param name
|
|
||||||
* @param 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;
|
|
||||||
|
|
||||||
gc.setFill(color);
|
|
||||||
|
|
||||||
if (raceViewController.isDisplayAnnotations()) {
|
|
||||||
// Set boat text
|
|
||||||
gc.setFont(new Font(14));
|
|
||||||
gc.setLineWidth(3);
|
|
||||||
gc.fillText(name + ", " + speed + " knots", x + 15, y + 15);
|
|
||||||
}
|
|
||||||
// double diameter = 9;
|
|
||||||
// gc.fillOval(x, y, diameter, diameter);
|
|
||||||
double angle = Math.toRadians(heading);
|
|
||||||
|
|
||||||
Point p1 = new Point(0, -15); // apex point
|
|
||||||
Point p2 = new Point(7, 4); // base point
|
|
||||||
Point p3 = new Point(-7, 4); // base point
|
|
||||||
p1.rotate(angle);
|
|
||||||
p2.rotate(angle);
|
|
||||||
p3.rotate(angle);
|
|
||||||
double[] xx = new double[] {p1.x + x, p2.x + x, x, p3.x + x};
|
|
||||||
double[] yy = new double[] {p1.y + y, p2.y + y, y, p3.y + y};
|
|
||||||
gc.fillPolygon(xx, yy, 4);
|
|
||||||
|
|
||||||
if (raceViewController.isDisplayAnnotations()){
|
|
||||||
drawWake(gc, x, y, speed, color, heading);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inner class for creating point so that you can rotate it around origin point.
|
* Inner class for creating point so that you can rotate it around origin point.
|
||||||
@@ -225,10 +293,11 @@ public class CanvasController {
|
|||||||
* Draws the course.
|
* Draws the course.
|
||||||
*/
|
*/
|
||||||
private void drawCourse() {
|
private void drawCourse() {
|
||||||
|
fitToCanvas();
|
||||||
for (Mark mark : raceViewController.getRace().getCourse()) {
|
for (Mark mark : raceViewController.getRace().getCourse()) {
|
||||||
if (mark.getMarkType() == MarkType.SINGLE_MARK) {
|
if (mark.getMarkType() == MarkType.SINGLE_MARK) {
|
||||||
drawSingleMark((SingleMark) mark, Color.BLACK);
|
drawSingleMark((SingleMark) mark, Color.BLACK);
|
||||||
} else if (mark.getMarkType() == MarkType.GATE_MARK) {
|
} else {
|
||||||
drawGateMark((GateMark) mark);
|
drawGateMark((GateMark) mark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,11 +309,8 @@ public class CanvasController {
|
|||||||
* @param singleMark
|
* @param singleMark
|
||||||
*/
|
*/
|
||||||
private void drawSingleMark(SingleMark singleMark, Color color) {
|
private void drawSingleMark(SingleMark singleMark, Color color) {
|
||||||
double x = (singleMark.getLongitude() - ORIGIN_LON) * SCALE;
|
|
||||||
double y = (ORIGIN_LAT - singleMark.getLatitude()) * SCALE;
|
|
||||||
|
|
||||||
gc.setFill(color);
|
gc.setFill(color);
|
||||||
gc.fillRect(x,y,5.5,5.5);
|
gc.fillOval(singleMark.getX(), singleMark.getY(),MARK_SIZE,MARK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -256,28 +322,228 @@ public class CanvasController {
|
|||||||
Color color = Color.BLUE;
|
Color color = Color.BLUE;
|
||||||
|
|
||||||
if (gateMark.getName().equals("Start")){
|
if (gateMark.getName().equals("Start")){
|
||||||
color = Color.RED;
|
color = Color.GREEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gateMark.getName().equals("Finish")){
|
if (gateMark.getName().equals("Finish")){
|
||||||
color = Color.GREEN;
|
color = Color.RED;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawSingleMark(gateMark.getSingleMark1(), color);
|
drawSingleMark(gateMark.getSingleMark1(), color);
|
||||||
drawSingleMark(gateMark.getSingleMark2(), color);
|
drawSingleMark(gateMark.getSingleMark2(), color);
|
||||||
|
|
||||||
GraphicsContext gc = canvas.getGraphicsContext2D();
|
GraphicsContext gc = canvas.getGraphicsContext2D();
|
||||||
|
gc.save();
|
||||||
gc.setStroke(color);
|
gc.setStroke(color);
|
||||||
|
if (gateMark.getMarkType() == MarkType.OPEN_GATE)
|
||||||
|
gc.setLineDashes(3, 5);
|
||||||
|
|
||||||
// Convert lat/lon to x,y
|
gc.setLineWidth(2);
|
||||||
double x1 = (gateMark.getSingleMark1().getLongitude()- ORIGIN_LON) * SCALE;
|
gc.strokeLine(
|
||||||
double y1 = (ORIGIN_LAT - gateMark.getSingleMark1().getLatitude()) * SCALE;
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
double x2 = (gateMark.getSingleMark2().getLongitude() - ORIGIN_LON) * SCALE;
|
/**
|
||||||
double y2 = (ORIGIN_LAT - gateMark.getSingleMark2().getLatitude()) * SCALE;
|
* Calculates x and y location for every marker that fits it to the canvas the race will be drawn on.
|
||||||
|
*/
|
||||||
|
private void fitToCanvas() {
|
||||||
|
findMinMaxPoint();
|
||||||
|
double minLonToMaxLon = scaleRaceExtremities();
|
||||||
|
calculateReferencePointLocation(minLonToMaxLon);
|
||||||
|
givePointsXY();
|
||||||
|
findMetersToPixels();
|
||||||
|
}
|
||||||
|
|
||||||
gc.setLineWidth(1);
|
|
||||||
gc.strokeLine(x1, y1, x2, y2);
|
/**
|
||||||
|
* Sets the class variables minLatPoint, maxLatPoint, minLonPoint, maxLonPoint to the marker with the leftmost
|
||||||
|
* marker, rightmost marker, southern most marker and northern most marker respectively.
|
||||||
|
*/
|
||||||
|
private void findMinMaxPoint() {
|
||||||
|
List<Mark> sortedPoints = new ArrayList<>();
|
||||||
|
for (Mark mark : raceViewController.getRace().getCourse())
|
||||||
|
{
|
||||||
|
if (mark.getMarkType() == MarkType.SINGLE_MARK)
|
||||||
|
sortedPoints.add(mark);
|
||||||
|
else {
|
||||||
|
sortedPoints.add(((GateMark) mark).getSingleMark1());
|
||||||
|
sortedPoints.add(((GateMark) mark).getSingleMark2());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sortedPoints.sort(Comparator.comparingDouble(Mark::getLatitude));
|
||||||
|
minLatPoint = sortedPoints.get(0);
|
||||||
|
maxLatPoint = sortedPoints.get(sortedPoints.size()-1);
|
||||||
|
|
||||||
|
sortedPoints.sort(Comparator.comparingDouble(Mark::getLongitude));
|
||||||
|
//If the course is on a point on the earth where longitudes wrap around.
|
||||||
|
// TODO: 30/03/17 cir27 - Correctly account for longitude wrapping around.
|
||||||
|
if (sortedPoints.get(sortedPoints.size()-1).getLongitude() - sortedPoints.get(0).getLongitude() > 180)
|
||||||
|
Collections.reverse(sortedPoints);
|
||||||
|
minLonPoint = sortedPoints.get(0);
|
||||||
|
maxLonPoint = sortedPoints.get(sortedPoints.size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the location of a reference point, this is always the point with minimum latitude, in relation to the
|
||||||
|
* canvas.
|
||||||
|
*
|
||||||
|
* @param minLonToMaxLon The horizontal distance between the point of minimum longitude to maximum longitude.
|
||||||
|
*/
|
||||||
|
private void calculateReferencePointLocation (double minLonToMaxLon) {
|
||||||
|
Mark referencePoint = minLatPoint;
|
||||||
|
double referenceAngle;
|
||||||
|
double mapWidth = canvas.getWidth();
|
||||||
|
double mapHeight = canvas.getHeight();
|
||||||
|
|
||||||
|
if (scaleDirection == ScaleDirection.HORIZONTAL) {
|
||||||
|
referenceAngle = Mark.calculateHeadingRad(referencePoint, minLonPoint) - (Math.PI * (3/4));
|
||||||
|
referencePointX = LHS_BUFFER + (int) Math.round(distanceScaleFactor * Math.cos(referenceAngle) * Mark.calculateDistance(referencePoint, minLonPoint));
|
||||||
|
|
||||||
|
referenceAngle = Mark.calculateHeadingRad(referencePoint, maxLatPoint);
|
||||||
|
if (referenceAngle > (Math.PI / 2)) {
|
||||||
|
referenceAngle = (Math.PI * 2) - referenceAngle;
|
||||||
|
}
|
||||||
|
referencePointY = (int) Math.round(mapHeight - (TOP_BUFFER + BOT_BUFFER));
|
||||||
|
referencePointY -= (int) Math.round(distanceScaleFactor * Math.cos(referenceAngle) * Mark.calculateDistance(referencePoint, maxLatPoint));
|
||||||
|
referencePointY = (int) Math.round(referencePointY / 2d);
|
||||||
|
referencePointY += TOP_BUFFER;
|
||||||
|
referencePointY += (int) Math.round(distanceScaleFactor * Math.cos(referenceAngle) * Mark.calculateDistance(referencePoint, maxLatPoint));
|
||||||
|
} else {
|
||||||
|
referencePointY = (int) Math.round(mapHeight - BOT_BUFFER);
|
||||||
|
|
||||||
|
referenceAngle = (Math.PI * 2) - Mark.calculateHeadingRad(referencePoint, minLonPoint);
|
||||||
|
|
||||||
|
referencePointX = LHS_BUFFER;
|
||||||
|
referencePointX += (int) Math.round(distanceScaleFactor * Math.sin(referenceAngle) * Mark.calculateDistance(referencePoint, minLonPoint));
|
||||||
|
referencePointX += (int) Math.round(((mapWidth - (LHS_BUFFER + RHS_BUFFER)) - (minLonToMaxLon * distanceScaleFactor)) / 2);
|
||||||
|
}
|
||||||
|
referencePoint.setX(referencePointX);
|
||||||
|
referencePoint.setY(referencePointY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the scale factor necessary to fit all race markers within the onscreen map and assigns it to distanceScaleFactor
|
||||||
|
* Returns the max horizontal distance of the map.
|
||||||
|
*/
|
||||||
|
private double scaleRaceExtremities () {
|
||||||
|
double vertAngle = Mark.calculateHeadingRad(minLatPoint, maxLatPoint);
|
||||||
|
if (vertAngle > Math.PI)
|
||||||
|
vertAngle = (2 * Math.PI) - vertAngle;
|
||||||
|
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
|
||||||
|
horiAngle = horiAngle - (Math.PI / 2);
|
||||||
|
double horiDistance = Math.cos(horiAngle) * Mark.calculateDistance(minLonPoint, maxLonPoint);
|
||||||
|
|
||||||
|
double vertScale = (canvas.getHeight() - (TOP_BUFFER + BOT_BUFFER)) / vertDistance;
|
||||||
|
|
||||||
|
if ((horiDistance * vertScale) > (canvas.getWidth() - (RHS_BUFFER + LHS_BUFFER))) {
|
||||||
|
distanceScaleFactor = (canvas.getWidth() - (RHS_BUFFER + LHS_BUFFER)) / horiDistance;
|
||||||
|
scaleDirection = ScaleDirection.HORIZONTAL;
|
||||||
|
} else {
|
||||||
|
distanceScaleFactor = vertScale;
|
||||||
|
scaleDirection = ScaleDirection.VERTICAL;
|
||||||
|
}
|
||||||
|
return horiDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give all markers in the course an x,y location relative to a given reference with a known x,y location. Distances
|
||||||
|
* are scaled according to the distanceScaleFactor variable.
|
||||||
|
*/
|
||||||
|
private void givePointsXY() {
|
||||||
|
Point2D canvasLocation;
|
||||||
|
List<Mark> allPoints = new ArrayList<>(raceViewController.getRace().getCourse());
|
||||||
|
|
||||||
|
for (Mark mark : allPoints) {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
if (mark.getMarkType() == MarkType.CLOSED_GATE)
|
||||||
|
((GateMark) mark).assignXYCentered();
|
||||||
|
else {
|
||||||
|
canvasLocation = findScaledXY(mark);
|
||||||
|
mark.setX((int) canvasLocation.getX());
|
||||||
|
mark.setY((int) canvasLocation.getY());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point2D findScaledXY (Mark unscaled) {
|
||||||
|
return findScaledXY (minLatPoint.getLatitude(), minLatPoint.getLongitude(),
|
||||||
|
unscaled.getLatitude(), unscaled.getLongitude());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point2D findScaledXY (double latA, double lonA, double latB, double lonB) {
|
||||||
|
double distanceFromReference;
|
||||||
|
double angleFromReference;
|
||||||
|
int yAxisLocation;
|
||||||
|
int xAxisLocation;
|
||||||
|
|
||||||
|
angleFromReference = Mark.calculateHeadingRad(latA, lonA, latB, lonB);
|
||||||
|
distanceFromReference = Mark.calculateDistance(latA, lonA, latB, lonB);
|
||||||
|
|
||||||
|
if (angleFromReference > (Math.PI / 2)) {
|
||||||
|
angleFromReference = (Math.PI * 2) - angleFromReference;
|
||||||
|
xAxisLocation = referencePointX;
|
||||||
|
xAxisLocation -= (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
||||||
|
} else {
|
||||||
|
xAxisLocation = referencePointX;
|
||||||
|
xAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
||||||
|
}
|
||||||
|
yAxisLocation = referencePointY;
|
||||||
|
yAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
||||||
|
|
||||||
|
return new Point2D(xAxisLocation, yAxisLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the number of meters per pixel.
|
||||||
|
*/
|
||||||
|
private void findMetersToPixels () {
|
||||||
|
Double angularDistance;
|
||||||
|
Double angle;
|
||||||
|
Double straightLineDistance;
|
||||||
|
if (scaleDirection == ScaleDirection.HORIZONTAL) {
|
||||||
|
angularDistance = Mark.calculateDistance(minLonPoint, maxLonPoint);
|
||||||
|
angle = Mark.calculateHeadingRad(minLonPoint, maxLonPoint);
|
||||||
|
if (angle > Math.PI / 2) {
|
||||||
|
straightLineDistance = Math.cos(angle - Math.PI) * angularDistance;
|
||||||
|
} else {
|
||||||
|
straightLineDistance = Math.cos(angle) * angularDistance;
|
||||||
|
}
|
||||||
|
metersToPixels = (CANVAS_WIDTH - RHS_BUFFER - LHS_BUFFER) / straightLineDistance;
|
||||||
|
} else {
|
||||||
|
angularDistance = Mark.calculateDistance(minLatPoint, maxLatPoint);
|
||||||
|
angle = Mark.calculateHeadingRad(minLatPoint, maxLatPoint);
|
||||||
|
if (angle < Math.PI / 2) {
|
||||||
|
straightLineDistance = Math.cos(angle) * angularDistance;
|
||||||
|
} else {
|
||||||
|
straightLineDistance = Math.cos(-angle + Math.PI * 2) * angularDistance;
|
||||||
|
}
|
||||||
|
metersToPixels = (CANVAS_HEIGHT - TOP_BUFFER - BOT_BUFFER) / straightLineDistance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point2D latLonToXY (double latitude, double longitude) {
|
||||||
|
return findScaledXY(minLatPoint.getLatitude(), minLatPoint.getLongitude(), latitude, longitude);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,10 +2,7 @@ package seng302.controllers;
|
|||||||
|
|
||||||
import javafx.animation.Animation;
|
import javafx.animation.Animation;
|
||||||
import javafx.animation.KeyFrame;
|
import javafx.animation.KeyFrame;
|
||||||
import javafx.animation.KeyValue;
|
|
||||||
import javafx.animation.Timeline;
|
import javafx.animation.Timeline;
|
||||||
import javafx.beans.property.DoubleProperty;
|
|
||||||
import javafx.beans.property.SimpleDoubleProperty;
|
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
@@ -42,6 +39,7 @@ public class RaceViewController {
|
|||||||
@FXML
|
@FXML
|
||||||
private CanvasController includedCanvasController;
|
private CanvasController includedCanvasController;
|
||||||
|
|
||||||
|
private ArrayList<Boat> startingBoats = new ArrayList<>();
|
||||||
private boolean displayAnnotations;
|
private boolean displayAnnotations;
|
||||||
private boolean displayFps;
|
private boolean displayFps;
|
||||||
private Timeline timerTimeline;
|
private Timeline timerTimeline;
|
||||||
@@ -50,24 +48,29 @@ public class RaceViewController {
|
|||||||
private Race race;
|
private Race race;
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
includedCanvasController.setup(this);
|
|
||||||
RaceController raceController = new RaceController();
|
RaceController raceController = new RaceController();
|
||||||
raceController.initializeRace();
|
raceController.initializeRace();
|
||||||
race = raceController.getRace();
|
race = raceController.getRace();
|
||||||
|
for (Boat boat : race.getBoats()) {
|
||||||
|
startingBoats.add(boat);
|
||||||
|
}
|
||||||
|
// try{
|
||||||
|
// initializeTimelines();
|
||||||
|
// }
|
||||||
|
// catch (Exception e){
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
|
||||||
initializeTimer();
|
includedCanvasController.setup(this);
|
||||||
|
includedCanvasController.initializeCanvas();
|
||||||
|
//initializeTimer();
|
||||||
initializeSettings();
|
initializeSettings();
|
||||||
try{
|
|
||||||
initializeTimelines();
|
|
||||||
}
|
|
||||||
catch (Exception e){
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
//set wind direction!!!!!!! can't find another place to put my code --haoming
|
//set wind direction!!!!!!! can't find another place to put my code --haoming
|
||||||
double windDirection = new ConfigParser("/config/config.xml").getWindDirection();
|
double windDirection = new ConfigParser("/config/config.xml").getWindDirection();
|
||||||
windDirectionText.setText(String.format("%.1f°", windDirection));
|
windDirectionText.setText(String.format("%.1f°", windDirection));
|
||||||
windArrowText.setRotate(windDirection);
|
windArrowText.setRotate(windDirection);
|
||||||
|
includedCanvasController.timer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeSettings(){
|
private void initializeSettings(){
|
||||||
@@ -114,39 +117,39 @@ public class RaceViewController {
|
|||||||
*/
|
*/
|
||||||
private void initializeTimelines() {
|
private void initializeTimelines() {
|
||||||
HashMap<Boat, List> boat_events = race.getEvents();
|
HashMap<Boat, List> boat_events = race.getEvents();
|
||||||
|
|
||||||
for (Boat boat : boat_events.keySet()) {
|
for (Boat boat : boat_events.keySet()) {
|
||||||
// x, y are the real time coordinates
|
startingBoats.add(boat);
|
||||||
DoubleProperty x = new SimpleDoubleProperty();
|
// // x, y are the real time coordinates
|
||||||
DoubleProperty y = new SimpleDoubleProperty();
|
// DoubleProperty x = new SimpleDoubleProperty();
|
||||||
|
// DoubleProperty y = new SimpleDoubleProperty();
|
||||||
List<KeyFrame> keyFrames = new ArrayList<>();
|
//
|
||||||
List<Event> events = boat_events.get(boat);
|
// List<KeyFrame> keyFrames = new ArrayList<>();
|
||||||
|
// List<Event> events = boat_events.get(boat);
|
||||||
// iterates all events and convert each event to keyFrame, then add them into a list
|
//
|
||||||
for (Event event : events) {
|
// // iterates all events and convert each event to keyFrame, then add them into a list
|
||||||
if (event.getIsFinishingEvent()) {
|
// for (Event event : events) {
|
||||||
keyFrames.add(
|
// if (event.getIsFinishingEvent()) {
|
||||||
new KeyFrame(Duration.seconds(event.getTime()),
|
// keyFrames.add(
|
||||||
onFinished -> {race.setBoatFinished(boat); handleEvent(event);},
|
// new KeyFrame(Duration.seconds(event.getTime()),
|
||||||
new KeyValue(x, event.getThisMark().getLatitude()),
|
// onFinished -> {race.setBoatFinished(boat); handleEvent(event);},
|
||||||
new KeyValue(y, event.getThisMark().getLongitude())
|
// new KeyValue(x, event.getThisMark().getLatitude()),
|
||||||
)
|
// new KeyValue(y, event.getThisMark().getLongitude())
|
||||||
);
|
// )
|
||||||
} else {
|
// );
|
||||||
keyFrames.add(
|
// } else {
|
||||||
new KeyFrame(Duration.seconds(event.getTime()),
|
// keyFrames.add(
|
||||||
onFinished ->{
|
// new KeyFrame(Duration.seconds(event.getTime()),
|
||||||
handleEvent(event);
|
// onFinished ->{
|
||||||
boat.setHeading(event.getBoatHeading());
|
// handleEvent(event);
|
||||||
},
|
// boat.setHeading(event.getBoatHeading());
|
||||||
new KeyValue(x, event.getThisMark().getLatitude()),
|
// },
|
||||||
new KeyValue(y, event.getThisMark().getLongitude())
|
// new KeyValue(x, event.getThisMark().getLatitude()),
|
||||||
)
|
// new KeyValue(y, event.getThisMark().getLongitude())
|
||||||
);
|
// )
|
||||||
}
|
// );
|
||||||
}
|
// }
|
||||||
timelineInfos.put(boat, new TimelineInfo(new Timeline(keyFrames.toArray(new KeyFrame[keyFrames.size()])), x, y));
|
// }
|
||||||
|
// timelineInfos.put(boat, new TimelineInfo(new Timeline(keyFrames.toArray(new KeyFrame[keyFrames.size()])), x, y));
|
||||||
}
|
}
|
||||||
setRaceDuration();
|
setRaceDuration();
|
||||||
}
|
}
|
||||||
@@ -277,4 +280,8 @@ public class RaceViewController {
|
|||||||
public Map<Boat, TimelineInfo> getTimelineInfos() {
|
public Map<Boat, TimelineInfo> getTimelineInfos() {
|
||||||
return timelineInfos;
|
return timelineInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ArrayList<Boat> getStartingBoats(){
|
||||||
|
return startingBoats;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,23 @@
|
|||||||
package seng302.models;
|
package seng302.models;
|
||||||
|
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.shape.Polygon;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.scene.transform.Rotate;
|
||||||
|
import javafx.scene.transform.Translate;
|
||||||
|
import javafx.util.Pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a boat in the race.
|
* Represents a boat in the race.
|
||||||
*/
|
*/
|
||||||
public class Boat {
|
public class Boat {
|
||||||
|
|
||||||
private String teamName; // The name of the team, this is also the name of the boat
|
private String teamName;
|
||||||
private double velocity; // In meters/second
|
private double velocity;
|
||||||
private double lat; // Boats position
|
private double lat;
|
||||||
private double lon; // -
|
private double lon;
|
||||||
private double distanceToNextMark;
|
|
||||||
private Color color;
|
|
||||||
private int markLastPast;
|
|
||||||
private double heading;
|
private double heading;
|
||||||
|
private int markLastPast;
|
||||||
private String shortName;
|
private String shortName;
|
||||||
|
|
||||||
public Boat(String teamName) {
|
public Boat(String teamName) {
|
||||||
@@ -22,7 +25,6 @@ public class Boat {
|
|||||||
this.velocity = 10; // Default velocity
|
this.velocity = 10; // Default velocity
|
||||||
this.lat = 0.0;
|
this.lat = 0.0;
|
||||||
this.lon = 0.0;
|
this.lon = 0.0;
|
||||||
this.distanceToNextMark = 0.0;
|
|
||||||
this.shortName = "";
|
this.shortName = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,8 +38,6 @@ public class Boat {
|
|||||||
public Boat(String teamName, double boatVelocity, String shortName) {
|
public Boat(String teamName, double boatVelocity, String shortName) {
|
||||||
this.teamName = teamName;
|
this.teamName = teamName;
|
||||||
this.velocity = boatVelocity;
|
this.velocity = boatVelocity;
|
||||||
this.distanceToNextMark = 0.0;
|
|
||||||
this.color = Colors.getColor();
|
|
||||||
this.shortName = shortName;
|
this.shortName = shortName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,8 +88,9 @@ public class Boat {
|
|||||||
this.lon = lon;
|
this.lon = lon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDistanceToNextMark(double distance){
|
public Pair<Double, Double> getLocation ()
|
||||||
this.distanceToNextMark = distance;
|
{
|
||||||
|
return new Pair<>(this.lat, this.lon);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getLatitude(){
|
public double getLatitude(){
|
||||||
@@ -100,8 +101,12 @@ public class Boat {
|
|||||||
return this.lon;
|
return this.lon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getColor() {
|
public void setLatitude (double latitude) {
|
||||||
return color;
|
this.lat = latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setlongitude (double longitude) {
|
||||||
|
this.lon =longitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getSpeedInKnots(){
|
public double getSpeedInKnots(){
|
||||||
@@ -116,15 +121,16 @@ public class Boat {
|
|||||||
return markLastPast;
|
return markLastPast;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHeading(double heading){
|
|
||||||
this.heading = heading;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getHeading(){
|
public double getHeading(){
|
||||||
return this.heading;
|
return this.heading;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setHeading(double heading) {
|
||||||
|
this.heading = heading;
|
||||||
|
}
|
||||||
|
|
||||||
public String getShortName(){
|
public String getShortName(){
|
||||||
return this.shortName;
|
return this.shortName;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
package seng302.models;
|
||||||
|
|
||||||
|
import javafx.scene.Group;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.shape.Polygon;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.scene.transform.Rotate;
|
||||||
|
import javafx.scene.transform.Translate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by CJIRWIN on 25/04/2017.
|
||||||
|
*/
|
||||||
|
public class BoatGroup extends Group{
|
||||||
|
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 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 double expectedUpdateInterval = 2000;
|
||||||
|
|
||||||
|
private Boat boat;
|
||||||
|
|
||||||
|
private double rotationalGoal;
|
||||||
|
private double currentRotation;
|
||||||
|
private double rotationalVelocity;
|
||||||
|
private double pixelVelocityX;
|
||||||
|
private double pixelVelocityY;
|
||||||
|
|
||||||
|
public BoatGroup (Boat boat, Color color){
|
||||||
|
super();
|
||||||
|
this.boat = boat;
|
||||||
|
initChildren(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoatGroup (Boat boat, Color color, double... points)
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
initChildren(color, points);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initChildren (Color color, double... points) {
|
||||||
|
Polygon boatPoly = new Polygon(points);
|
||||||
|
boatPoly.setFill(color);
|
||||||
|
|
||||||
|
Polygon wake = new Polygon(
|
||||||
|
5.0,0.0,
|
||||||
|
10.0, boat.getVelocity() * VELOCITY_WAKE_RATIO,
|
||||||
|
0.0, boat.getVelocity() * VELOCITY_WAKE_RATIO
|
||||||
|
);
|
||||||
|
wake.setFill(Color.DARKBLUE);
|
||||||
|
|
||||||
|
Text teamNameObject = new Text(boat.getShortName());
|
||||||
|
Text velocityObject = new Text(String.valueOf(boat.getVelocity()));
|
||||||
|
|
||||||
|
boatPoly.setLayoutX(0);
|
||||||
|
boatPoly.setLayoutY(0);
|
||||||
|
boatPoly.relocate(boatPoly.getLayoutX(), boatPoly.getLayoutY());
|
||||||
|
|
||||||
|
teamNameObject.setX(TEAMNAME_X_OFFSET);
|
||||||
|
teamNameObject.setY(TEAMNAME_Y_OFFSET);
|
||||||
|
teamNameObject.relocate(teamNameObject.getX(), teamNameObject.getY());
|
||||||
|
|
||||||
|
velocityObject.setX(VELOCITY_X_OFFSET);
|
||||||
|
velocityObject.setY(VELOCITY_Y_OFFSET);
|
||||||
|
velocityObject.relocate(velocityObject.getX(), velocityObject.getY());
|
||||||
|
|
||||||
|
wake.setLayoutX(0);
|
||||||
|
wake.setLayoutY(0);
|
||||||
|
wake.relocate(wake.getLayoutX(), wake.getLayoutY());
|
||||||
|
|
||||||
|
super.getChildren().addAll(boatPoly, wake, teamNameObject, velocityObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initChildren (Color color) {
|
||||||
|
initChildren(color,
|
||||||
|
BOAT_WIDTH / 2, 0.0,
|
||||||
|
BOAT_WIDTH, BOAT_HEIGHT,
|
||||||
|
0.0, BOAT_HEIGHT);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Moves the boat and its children annotations from its current coordinates by specified amounts.
|
||||||
|
* @param dx The amount to move the X coordinate by
|
||||||
|
* @param dy The amount to move the Y coordinate by
|
||||||
|
*/
|
||||||
|
void moveBy(Double dx, Double dy, Double rotation) {
|
||||||
|
super.setLayoutX(super.getLayoutX() + dx);
|
||||||
|
super.setLayoutY(super.getLayoutY() + dy);
|
||||||
|
rotateBoat(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the boat and its children annotations to coordinates specified
|
||||||
|
* @param x The X coordinate to move the boat to
|
||||||
|
* @param y The Y coordinate to move the boat to
|
||||||
|
*/
|
||||||
|
public void moveBoatTo(Double x, Double y, Double rotation) {
|
||||||
|
super.relocate(x, y);
|
||||||
|
currentRotation = 0;
|
||||||
|
rotateBoat(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updatePosition (double 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;
|
||||||
|
}
|
||||||
|
moveBy(dx, dy, rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDestination (double newXValue, double newYValue) {
|
||||||
|
this.pixelVelocityX = (newXValue - super.getLayoutX()) / expectedUpdateInterval;
|
||||||
|
this.pixelVelocityY = (newYValue - super.getLayoutY()) / expectedUpdateInterval;
|
||||||
|
//this.destinationX = newXValue;
|
||||||
|
//this.destinationY = newYValue;
|
||||||
|
this.rotationalGoal = Math.abs(
|
||||||
|
Math.toDegrees(
|
||||||
|
Math.atan(
|
||||||
|
(newYValue - super.getLayoutY()) / (newXValue - super.getLayoutX())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (super.getLayoutY() >= newYValue && super.getLayoutX() <= newXValue)
|
||||||
|
rotationalGoal = 90 - rotationalGoal;
|
||||||
|
else if (super.getLayoutY() < newYValue && super.getLayoutX() <= newXValue)
|
||||||
|
rotationalGoal = 90 + rotationalGoal;
|
||||||
|
else if (super.getLayoutY() >= newYValue && super.getLayoutX() > newXValue)
|
||||||
|
rotationalGoal = 270 + rotationalGoal;
|
||||||
|
else
|
||||||
|
rotationalGoal = 270 - rotationalGoal;
|
||||||
|
// TODO: 25/04/2017 cir27 - Verify this logic is correct. Want to produce the shortest path.
|
||||||
|
if (Math.abs(360 - rotationalGoal + currentRotation) < Math.abs(rotationalGoal - currentRotation)) {
|
||||||
|
System.out.println("ROTATE");
|
||||||
|
this.rotationalVelocity = (360 - rotationalGoal + currentRotation) / expectedUpdateInterval;
|
||||||
|
} else {
|
||||||
|
this.rotationalVelocity = (rotationalGoal - currentRotation) / expectedUpdateInterval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rotateBoat (double rotationDeg) {
|
||||||
|
currentRotation += rotationDeg;
|
||||||
|
Node boatPoly = super.getChildren().get(0);
|
||||||
|
boatPoly.getTransforms().clear();
|
||||||
|
boatPoly.getTransforms().add(new Rotate(currentRotation, BOAT_WIDTH/2, 0));
|
||||||
|
Node wake = super.getChildren().get(1);
|
||||||
|
wake.getTransforms().clear();
|
||||||
|
wake.getTransforms().add(new Translate(0, BOAT_HEIGHT));
|
||||||
|
wake.getTransforms().add(new Rotate(currentRotation, BOAT_WIDTH/2, -BOAT_HEIGHT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getExpectedUpdateInterval() {
|
||||||
|
return expectedUpdateInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setExpectedUpdateInterval(double expectedUpdateInterval) {
|
||||||
|
BoatGroup.expectedUpdateInterval = expectedUpdateInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forceRotation () {
|
||||||
|
rotateBoat (rotationalGoal - currentRotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toogleAnnotations () {
|
||||||
|
super.getChildren().get(1).setVisible(false);
|
||||||
|
super.getChildren().get(2).setVisible(false);
|
||||||
|
super.getChildren().get(3).setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,10 +11,9 @@ public enum Colors {
|
|||||||
static Integer index = 0;
|
static Integer index = 0;
|
||||||
|
|
||||||
public static Color getColor() {
|
public static Color getColor() {
|
||||||
index++;
|
if (index == 6) {
|
||||||
if (index > 6) {
|
index = 0;
|
||||||
index = 1;
|
|
||||||
}
|
}
|
||||||
return Color.valueOf(values()[index-1].toString());
|
return Color.valueOf(values()[index++].toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class Event {
|
|||||||
private Mark mark1; // This mark
|
private Mark mark1; // This mark
|
||||||
private Mark mark2; // Next mark
|
private Mark mark2; // Next mark
|
||||||
private int markPosInRace; // the position of the current mark in the race course
|
private int markPosInRace; // the position of the current mark in the race course
|
||||||
|
private double heading;
|
||||||
private final double ORIGIN_LAT = 32.320504;
|
private final double ORIGIN_LAT = 32.320504;
|
||||||
private final double ORIGIN_LON = -64.857063;
|
private final double ORIGIN_LON = -64.857063;
|
||||||
private final double SCALE = 16000;
|
private final double SCALE = 16000;
|
||||||
@@ -36,6 +36,8 @@ public class Event {
|
|||||||
this.mark1 = mark1;
|
this.mark1 = mark1;
|
||||||
this.mark2 = mark2;
|
this.mark2 = mark2;
|
||||||
this.markPosInRace = markPosInRace;
|
this.markPosInRace = markPosInRace;
|
||||||
|
this.heading = angleFromCoordinate(mark1, mark2);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,7 +94,7 @@ public class Event {
|
|||||||
if (this.isFinishingEvent) {
|
if (this.isFinishingEvent) {
|
||||||
return (this.getTimeString() + ", " + this.getBoat().getTeamName() + " finished the race");
|
return (this.getTimeString() + ", " + this.getBoat().getTeamName() + " finished the race");
|
||||||
}
|
}
|
||||||
System.out.println(this.getDistanceBetweenMarks());
|
// System.out.println(this.getDistanceBetweenMarks());
|
||||||
return (this.getTimeString() + ", " + this.getBoat().getTeamName() + " passed " + this.mark1.getName() + " going heading " + this.getBoatHeading() + "°");
|
return (this.getTimeString() + ", " + this.getBoat().getTeamName() + " passed " + this.mark1.getName() + " going heading " + this.getBoatHeading() + "°");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,6 +140,30 @@ public class Event {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the angle between to angular co-ordinates on a sphere.
|
||||||
|
*
|
||||||
|
* @param geoPointOne first geographical location
|
||||||
|
* @param geoPointTwo second geographical location
|
||||||
|
* @return the angle from point one to point two
|
||||||
|
*/
|
||||||
|
private Double angleFromCoordinate(Mark geoPointOne, Mark geoPointTwo) {
|
||||||
|
if (geoPointTwo == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
double x1 = geoPointOne.getLatitude();
|
||||||
|
double y1 = -geoPointOne.getLongitude();
|
||||||
|
double x2 = geoPointTwo.getLatitude();
|
||||||
|
double y2 = -geoPointTwo.getLongitude();
|
||||||
|
|
||||||
|
return Math.toDegrees(Math.atan2(x2-x1, y2-y1));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHeading() {
|
||||||
|
return heading;
|
||||||
|
}
|
||||||
|
|
||||||
public Mark getThisMark() {
|
public Mark getThisMark() {
|
||||||
return this.mark1;
|
return this.mark1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.util.*;
|
|||||||
* Created by mra106 on 8/3/2017.
|
* Created by mra106 on 8/3/2017.
|
||||||
*/
|
*/
|
||||||
public class Race {
|
public class Race {
|
||||||
|
|
||||||
private ArrayList<Boat> boats; // The boats in the race
|
private ArrayList<Boat> boats; // The boats in the race
|
||||||
private ArrayList<Boat> finishingOrder; // The order in which the boats finish the race
|
private ArrayList<Boat> finishingOrder; // The order in which the boats finish the race
|
||||||
private HashMap<Boat, List> events = new HashMap<>(); // The events that occur in the race
|
private HashMap<Boat, List> events = new HashMap<>(); // The events that occur in the race
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ public class GateMark extends Mark {
|
|||||||
* @param singleMark1 one single mark inside of the gate mark
|
* @param singleMark1 one single mark inside of the gate mark
|
||||||
* @param singleMark2 the second mark inside of the gate mark
|
* @param singleMark2 the second mark inside of the gate mark
|
||||||
*/
|
*/
|
||||||
public GateMark(String name, SingleMark singleMark1, SingleMark singleMark2, double latitude, double longitude) {
|
public GateMark(String name, MarkType type, SingleMark singleMark1, SingleMark singleMark2, double latitude, double longitude) {
|
||||||
super(name, MarkType.GATE_MARK, latitude, longitude);
|
super(name, type, latitude, longitude);
|
||||||
this.singleMark1 = singleMark1;
|
this.singleMark1 = singleMark1;
|
||||||
this.singleMark2 = singleMark2;
|
this.singleMark2 = singleMark2;
|
||||||
}
|
}
|
||||||
@@ -47,4 +47,16 @@ public class GateMark extends Mark {
|
|||||||
//return (this.getSingleMark1().getLongitude() + this.getSingleMark2().getLongitude()) / 2;
|
//return (this.getSingleMark1().getLongitude() + this.getSingleMark2().getLongitude()) / 2;
|
||||||
return (this.getSingleMark1().getLongitude());
|
return (this.getSingleMark1().getLongitude());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void assignXYCentered () {
|
||||||
|
System.out.println("POSSIBLE GOOF " + xValue + " " + yValue);
|
||||||
|
System.out.println(singleMark1.getX() + " " + singleMark1.getY());
|
||||||
|
System.out.println(singleMark2.getX() + " " + singleMark2.getY());
|
||||||
|
double dx = singleMark2.getX() - singleMark1.getX();
|
||||||
|
System.out.println("dx + " + dx);
|
||||||
|
double dy = singleMark2.getY() - singleMark1.getY();
|
||||||
|
xValue = (int) Math.round(singleMark1.getX() + dx / 2);
|
||||||
|
yValue = (int) Math.round(singleMark1.getY() + dy / 2);
|
||||||
|
System.out.println("PROBABLE GAAF " + xValue + " " + yValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ public abstract class Mark {
|
|||||||
private MarkType markType;
|
private MarkType markType;
|
||||||
private double latitude;
|
private double latitude;
|
||||||
private double longitude;
|
private double longitude;
|
||||||
|
Integer xValue;
|
||||||
|
Integer yValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a mark instance by passing its name and type
|
* Create a mark instance by passing its name and type
|
||||||
@@ -28,6 +30,76 @@ public abstract class Mark {
|
|||||||
this.longitude = longitude;
|
this.longitude = longitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculated the heading in radians from first Mark to the second Mark.
|
||||||
|
*
|
||||||
|
* @param pointOne First Mark
|
||||||
|
* @param pointTwo Second Mark
|
||||||
|
* @return Heading in radians
|
||||||
|
*/
|
||||||
|
public static Double calculateHeadingRad(Mark pointOne, Mark pointTwo) {
|
||||||
|
Double longitude1 = pointOne.getLongitude();
|
||||||
|
Double longitude2 = pointTwo.getLongitude();
|
||||||
|
Double latitude1 = pointOne.getLatitude();
|
||||||
|
Double latitude2 = pointTwo.getLatitude();
|
||||||
|
return calculateHeadingRad(latitude1, longitude1, latitude2, longitude2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the heading in radians from geographical location with latitude1, longitude 1 to geographical
|
||||||
|
* latitude2, longitude 2
|
||||||
|
* @param longitude1 Longitude of first point in degrees
|
||||||
|
* @param longitude2 Longitude of second point in degrees
|
||||||
|
* @param latitude1 Latitude of first point in degrees
|
||||||
|
* @param latitude2 Latitude of first point in degrees
|
||||||
|
* @return Heading in radians
|
||||||
|
*/
|
||||||
|
public static double calculateHeadingRad (Double latitude1, Double longitude1, Double latitude2, Double longitude2) {
|
||||||
|
latitude1 = Math.toRadians(latitude1);
|
||||||
|
latitude2 = Math.toRadians(latitude2);
|
||||||
|
Double longDiff= Math.toRadians(longitude2-longitude1);
|
||||||
|
Double y = Math.sin(longDiff)*Math.cos(latitude2);
|
||||||
|
Double x = Math.cos(latitude1)*Math.sin(latitude2)-Math.sin(latitude1)*Math.cos(latitude2)*Math.cos(longDiff);
|
||||||
|
return Math.atan2(y, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the distance in meters from the first Mark to a second Mark
|
||||||
|
*
|
||||||
|
* @param pointOne First Mark
|
||||||
|
* @param pointTwo Second Mark
|
||||||
|
* @return Distance in meters
|
||||||
|
*/
|
||||||
|
public static Double calculateDistance(Mark pointOne, Mark pointTwo) {
|
||||||
|
Double longitude1 = pointOne.getLongitude();
|
||||||
|
Double longitude2 = pointTwo.getLongitude();
|
||||||
|
Double latitude1 = pointOne.getLatitude();
|
||||||
|
Double latitude2 = pointTwo.getLatitude();
|
||||||
|
return calculateDistance(latitude1, longitude1, latitude2, longitude2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the distance in meters from geographical location with latitude1, longitude 1 to geographical
|
||||||
|
* latitude2, longitude 2
|
||||||
|
*
|
||||||
|
* @param longitude1 Longitude of first point in degrees
|
||||||
|
* @param longitude2 Longitude of second point in degrees
|
||||||
|
* @param latitude1 Latitude of first point in degrees
|
||||||
|
* @param latitude2 Latitude of first point in degrees
|
||||||
|
* @return Distance in meters
|
||||||
|
*/
|
||||||
|
public static Double calculateDistance (Double latitude1, Double longitude1, Double latitude2, Double longitude2) {
|
||||||
|
Double theta = longitude1 - longitude2;
|
||||||
|
Double dist = Math.sin(Math.toRadians(latitude1)) * Math.sin(Math.toRadians(latitude2)) +
|
||||||
|
Math.cos(Math.toRadians(latitude1)) * Math.cos(Math.toRadians(latitude2)) *
|
||||||
|
Math.cos(Math.toRadians(theta));
|
||||||
|
dist = Math.acos(dist);
|
||||||
|
dist = Math.toDegrees(dist);
|
||||||
|
dist = dist * 60 * 1.1508; //nautical mile (distance between two degrees) * (degrees in a minute)
|
||||||
|
dist = dist * 1609.344; //ratio of miles to metres
|
||||||
|
return dist;
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@@ -51,4 +123,21 @@ public abstract class Mark {
|
|||||||
public double getLongitude() {
|
public double getLongitude() {
|
||||||
return longitude;
|
return longitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getX () {
|
||||||
|
return xValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY () {
|
||||||
|
return yValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX (int x) {
|
||||||
|
this.xValue = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY (int y) {
|
||||||
|
this.yValue = y;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ package seng302.models.mark;
|
|||||||
* Created by Haoming Yin (hyi25) on 17/3/17.
|
* Created by Haoming Yin (hyi25) on 17/3/17.
|
||||||
*/
|
*/
|
||||||
public enum MarkType {
|
public enum MarkType {
|
||||||
SINGLE_MARK, GATE_MARK
|
SINGLE_MARK, OPEN_GATE, CLOSED_GATE
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,11 @@ public class CourseParser extends FileParser {
|
|||||||
String name = element.getElementsByTagName("name").item(0).getTextContent();
|
String name = element.getElementsByTagName("name").item(0).getTextContent();
|
||||||
SingleMark mark1 = generateSingleMark(element.getElementsByTagName("mark").item(0));
|
SingleMark mark1 = generateSingleMark(element.getElementsByTagName("mark").item(0));
|
||||||
SingleMark mark2 = generateSingleMark(element.getElementsByTagName("mark").item(1));
|
SingleMark mark2 = generateSingleMark(element.getElementsByTagName("mark").item(1));
|
||||||
GateMark gateMark = new GateMark(name, mark1, mark2, mark1.getLatitude(), mark1.getLongitude());
|
GateMark gateMark;
|
||||||
|
if (name.equals("Start") || name.equals("Finish"))
|
||||||
|
gateMark = new GateMark(name, MarkType.CLOSED_GATE, mark1, mark2, mark1.getLatitude(), mark1.getLongitude());
|
||||||
|
else
|
||||||
|
gateMark = new GateMark(name, MarkType.OPEN_GATE, mark1, mark2, mark1.getLatitude(), mark1.getLongitude());
|
||||||
marks.put(name, gateMark);
|
marks.put(name, gateMark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
package seng302;
|
package seng302;
|
||||||
|
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import seng302.models.Boat;
|
|
||||||
import seng302.models.Colors;
|
import seng302.models.Colors;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
@@ -16,30 +12,13 @@ import static org.junit.Assert.assertEquals;
|
|||||||
* Created by ryan_ on 16/03/2017.
|
* Created by ryan_ on 16/03/2017.
|
||||||
*/
|
*/
|
||||||
public class ColorsTest {
|
public class ColorsTest {
|
||||||
//@Test
|
|
||||||
|
@Test
|
||||||
public void testNextColor() {
|
public void testNextColor() {
|
||||||
List<Boat> boats = new ArrayList<>();
|
Color expectedColors[] = {Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.BLUE, Color.PURPLE};
|
||||||
boats.add(new Boat("Team 1"));
|
for (int i = 0; i<6; i++)
|
||||||
boats.add(new Boat("Team 2"));
|
{
|
||||||
boats.add(new Boat("Team 3"));
|
Assert.assertEquals(expectedColors[i], Colors.getColor());
|
||||||
boats.add(new Boat("Team 4"));
|
}
|
||||||
boats.add(new Boat("Team 5"));
|
|
||||||
boats.add(new Boat("Team 6"));
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
List<Color> enumColors = new ArrayList<>();
|
|
||||||
while (count < 6) {
|
|
||||||
Color color = Colors.getColor();
|
|
||||||
enumColors.add(color);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Color> boatColors = new ArrayList<>();
|
|
||||||
for (Boat boat : boats) {
|
|
||||||
Color color = boat.getColor();
|
|
||||||
boatColors.add(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(enumColors, boatColors);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public class MarkTest {
|
|||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
this.singleMark1 = new SingleMark("testMark_SM1", 12.23234, -34.342);
|
this.singleMark1 = new SingleMark("testMark_SM1", 12.23234, -34.342);
|
||||||
this.singleMark2 = new SingleMark("testMark_SM2", 12.23239, -34.352);
|
this.singleMark2 = new SingleMark("testMark_SM2", 12.23239, -34.352);
|
||||||
this.gateMark = new GateMark("testMark_GM", singleMark1, singleMark2, singleMark1.getLatitude(), singleMark2.getLongitude());
|
this.gateMark = new GateMark("testMark_GM", MarkType.OPEN_GATE, singleMark1, singleMark2, singleMark1.getLatitude(), singleMark2.getLongitude());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -30,7 +30,7 @@ public class MarkTest {
|
|||||||
@Test
|
@Test
|
||||||
public void getMarkType() throws Exception {
|
public void getMarkType() throws Exception {
|
||||||
assertTrue(this.singleMark2.getMarkType() == MarkType.SINGLE_MARK);
|
assertTrue(this.singleMark2.getMarkType() == MarkType.SINGLE_MARK);
|
||||||
assertTrue(this.gateMark.getMarkType() == MarkType.GATE_MARK);
|
assertTrue(this.gateMark.getMarkType() == MarkType.OPEN_GATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class CourseParserTest {
|
|||||||
public void getGates() throws Exception {
|
public void getGates() throws Exception {
|
||||||
ArrayList<Mark> course = cp.getCourse();
|
ArrayList<Mark> course = cp.getCourse();
|
||||||
|
|
||||||
assertTrue(MarkType.GATE_MARK == course.get(0).getMarkType());
|
assertTrue(MarkType.OPEN_GATE == course.get(0).getMarkType());
|
||||||
|
|
||||||
GateMark gateMark1 = (GateMark) course.get(0);
|
GateMark gateMark1 = (GateMark) course.get(0);
|
||||||
assertEquals(32.293771, gateMark1.getSingleMark2().getLatitude(), 0.00000001);
|
assertEquals(32.293771, gateMark1.getSingleMark2().getLatitude(), 0.00000001);
|
||||||
|
|||||||
Reference in New Issue
Block a user