diff --git a/src/main/java/seng302/App.java b/src/main/java/seng302/App.java index ecb9e4a3..c53a4300 100644 --- a/src/main/java/seng302/App.java +++ b/src/main/java/seng302/App.java @@ -67,6 +67,7 @@ public class App extends Application { else { // sr = new StreamReceiver("localhost", 4949, "RaceStream"); sr = new StreamReceiver("livedata.americascup.com", 4941, "RaceStream"); +// sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941, "RaceStream"); } sr.start(); diff --git a/src/main/java/seng302/GeometryUtils.java b/src/main/java/seng302/GeometryUtils.java new file mode 100644 index 00000000..ce8b9fe4 --- /dev/null +++ b/src/main/java/seng302/GeometryUtils.java @@ -0,0 +1,63 @@ +package seng302; + +import javafx.geometry.Point2D; + +/** + * A Class for performing geometric calculations on the canvas + * Created by wmu16 on 24/05/17. + */ +public final class GeometryUtils { + + + /** + * Performs the line function on two points of a line and a test point to test which side of the line that point is + * on. If the return value is + * return 1, then the point is on one side of the line, + * return -1 then the point is on the other side of the line + * return 0 then the point is exactly on the line. + * @param linePoint1 One point of the line + * @param linePoint2 Second point of the line + * @param testPoint The point to test with this line + * @return A return value indicating which side of the line the point is on + */ + public static Integer lineFunction(Point2D linePoint1, Point2D linePoint2, Point2D testPoint) { + + Double x = testPoint.getX(); + Double y = testPoint.getY(); + Double x1 = linePoint1.getX(); + Double y1 = linePoint1.getY(); + Double x2 = linePoint2.getX(); + Double y2 = linePoint2.getY(); + + Double result = (x - x1)*(y2 - y1) - (y - y1)*(x2 - x1); //Line function + + if (result > 0) { + return 1; + } + else if (result < 0) { + return -1; + } + else { + return 0; + } + } + + + /** + * Given a point and a vector (angle and vector length) Will create a new point, that vector away from the origin + * point + * @param originPoint The point with which to use as the base for our vector addition + * @param angleInDeg (DEGREES) The angle at which our new point is being created (in degrees!) + * @param vectorLength The length out on this angle from the origin point to create the new point + * @return a Point2D + */ + public static Point2D makeArbitraryVectorPoint(Point2D originPoint, Double angleInDeg, Double vectorLength) { + + Double endPointX = originPoint.getX() + vectorLength * Math.cos(Math.toRadians(angleInDeg)); + Double endPointY = originPoint.getY() + vectorLength * Math.sin(Math.toRadians(angleInDeg)); + + return new Point2D(endPointX, endPointY); + + } + +} diff --git a/src/main/java/seng302/controllers/CanvasController.java b/src/main/java/seng302/controllers/CanvasController.java index 1b2ea66d..36d56507 100644 --- a/src/main/java/seng302/controllers/CanvasController.java +++ b/src/main/java/seng302/controllers/CanvasController.java @@ -435,7 +435,7 @@ public class CanvasController { return findScaledXY (unscaled.getLatitude(), unscaled.getLongitude()); } - private Point2D findScaledXY (double unscaledLat, double unscaledLon) { + public Point2D findScaledXY (double unscaledLat, double unscaledLon) { double distanceFromReference; double angleFromReference; int xAxisLocation = (int) referencePointX; @@ -468,4 +468,8 @@ public class CanvasController { List getBoatGroups() { return boatGroups; } + + List getMarkGroups() { + return markGroups; + } } \ 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 f1bd50b2..754da2eb 100644 --- a/src/main/java/seng302/controllers/RaceViewController.java +++ b/src/main/java/seng302/controllers/RaceViewController.java @@ -26,6 +26,9 @@ import seng302.controllers.annotations.ImportantAnnotationController; import seng302.controllers.annotations.ImportantAnnotationDelegate; import seng302.controllers.annotations.ImportantAnnotationsState; import seng302.models.*; +import seng302.models.mark.GateMark; +import seng302.models.mark.Mark; +import seng302.models.mark.MarkGroup; import seng302.models.stream.StreamParser; import java.io.IOException; @@ -185,14 +188,29 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel for (Yacht yacht : StreamParser.getBoatsPos().values()) { - if (yacht.getLastMarkRounded() != null) { - System.out.println("\n\nboat: " + yacht.getBoatName()); - System.out.println("last Mark: " + yacht.getLastMarkRounded().getName()); - } if (yacht.getNextMark() != null){ System.out.println("next Mark: " + yacht.getNextMark().getName()); for (BoatGroup bg : includedCanvasController.getBoatGroups()) { - bg.calculateLegDirection(); + + Boolean isUpwindLeg = null; + // Can only calc leg direction if there is a next mark and it is a gate mark + Mark nextMark = bg.getBoat().getNextMark(); + if (!(nextMark == null || !(nextMark instanceof GateMark))) { + isUpwindLeg = bg.isUpwindLeg(includedCanvasController); + } + + for (MarkGroup mg : includedCanvasController.getMarkGroups()) { + if (mg.getMainMark().equals(nextMark)) { + + } + } + if (isUpwindLeg != null) { + if (isUpwindLeg) { + + } + } + + } } diff --git a/src/main/java/seng302/models/BoatGroup.java b/src/main/java/seng302/models/BoatGroup.java index 6ee1a3d8..41d02d08 100644 --- a/src/main/java/seng302/models/BoatGroup.java +++ b/src/main/java/seng302/models/BoatGroup.java @@ -12,7 +12,11 @@ import javafx.scene.shape.Line; import javafx.scene.shape.Polygon; import javafx.scene.text.Text; import javafx.scene.transform.Rotate; +import seng302.GeometryUtils; +import seng302.controllers.CanvasController; +import seng302.models.mark.GateMark; import seng302.models.mark.Mark; +import seng302.models.mark.SingleMark; import seng302.models.stream.StreamParser; import java.text.DateFormat; @@ -364,33 +368,44 @@ public class BoatGroup extends Group { } - public void calculateLegDirection() { - Mark lastMark = boat.getLastMarkRounded(); + /** + * This function works out if a boat is going upwind or down wind. It looks at the boats current position, the next + * gates position and the current wind + * If bot the wind vector from the next gate and the boat from the next gate lay on the same side, then the boat is + * going up wind, if they are on different sides of the gate, then the boat is going downwind + * @param canvasController + */ + public Boolean isUpwindLeg(CanvasController canvasController) { Mark nextMark = boat.getNextMark(); - if (lastMark == null || nextMark == null) { - return; + + Double windAngle = StreamParser.getWindDirection(); + GateMark thisGateMark = (GateMark) nextMark; + SingleMark nextMark1 = thisGateMark.getSingleMark1(); + SingleMark nextMark2 = thisGateMark.getSingleMark2(); + Point2D nextMarkPoint1 = canvasController.findScaledXY(nextMark1.getLatitude(), nextMark1.getLongitude()); + Point2D nextMarkPoint2 = canvasController.findScaledXY(nextMark2.getLatitude(), nextMark2.getLongitude()); + + Point2D boatCurrentPoint = new Point2D(boatPoly.getLayoutX(), boatPoly.getLayoutY()); + Point2D windTestPoint = GeometryUtils.makeArbitraryVectorPoint(nextMarkPoint1, windAngle, 10d); + + + Integer boatLineFuncResult = GeometryUtils.lineFunction(nextMarkPoint1, nextMarkPoint2, boatCurrentPoint); + Integer windLineFuncResult = GeometryUtils.lineFunction(nextMarkPoint1, nextMarkPoint2, windTestPoint); + + + /* + If both the wind vector from the gate and the boat from the gate are on the same side of that gate, then the + boat is travelling into the wind. thus upwind. Otherwise if they are on different sides, then the boat is going + with the wind. + */ + System.out.println("Boat Line func result: " + boatLineFuncResult); + System.out.println("Wind Line func result: " + windLineFuncResult); + if (boatLineFuncResult == windLineFuncResult) { + return true; + } else { + return false; } - Double windDirection = StreamParser.getWindDirection(); - Double arbitraryDistance = 10d; - - Point2D lastMarkMidPoint = new Point2D(lastMark.getLatitude(), lastMark.getLongitude()); - Point2D nextMarkMidPoint = new Point2D(nextMark.getLatitude(), nextMark.getLongitude()); - - Double windDirX = lastMarkMidPoint.getX() + (lastMarkMidPoint.getX() + arbitraryDistance -lastMarkMidPoint.getX())*Math.cos(windDirection) - (lastMarkMidPoint.getY() + arbitraryDistance -lastMarkMidPoint.getY())*Math.sin(windDirection); - Double windDirY = lastMarkMidPoint.getY() + (lastMarkMidPoint.getX() + arbitraryDistance -lastMarkMidPoint.getX())*Math.sin(windDirection) + (lastMarkMidPoint.getY() + arbitraryDistance -lastMarkMidPoint.getY())*Math.cos(windDirection); - Point2D windDirPoint = new Point2D(windDirX, windDirY); - - Double angle = lastMarkMidPoint.angle(nextMarkMidPoint, windDirPoint); - - if (angle <= 90) { - System.out.println(lastMark.getName() + " is downwind"); - System.out.println(nextMark.getName() + " is upwind"); - } - -// if (lastMarkMidPoint.angle(nextMarkMidPoint, windDirPoint) <= 90) { -// boat.getNextMark().s -// } } diff --git a/src/main/java/seng302/models/mark/MarkGroup.java b/src/main/java/seng302/models/mark/MarkGroup.java index a6651434..8c4e716b 100644 --- a/src/main/java/seng302/models/mark/MarkGroup.java +++ b/src/main/java/seng302/models/mark/MarkGroup.java @@ -161,4 +161,8 @@ public class MarkGroup extends Group { idArray[i++] = mark.getId(); return idArray; } + + public Mark getMainMark() { + return mainMark; + } } \ No newline at end of file diff --git a/src/test/java/seng302/TestGeoUtils.java b/src/test/java/seng302/TestGeoUtils.java new file mode 100644 index 00000000..633cec99 --- /dev/null +++ b/src/test/java/seng302/TestGeoUtils.java @@ -0,0 +1,65 @@ +package seng302; + +import javafx.geometry.Point2D; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Test Class for the GeometryUtils class + * Created by wmu16 on 24/05/17. + */ +public class TestGeoUtils { + + //Line in x = y + private Point2D linePoint1 = new Point2D(0, 0); + private Point2D linePoint2 = new Point2D(1, 1); + + //Point below x = y + private Point2D arbitraryPoint1 = new Point2D(1, 0); + + //Point above x = y + private Point2D arbitraryPoint2 = new Point2D(0, 1); + + //Point on x = y + private Point2D arbitraryPoint3 = new Point2D(2, 2); + + @Before + public void setUp() throws Exception { + + } + + + @Test + public void testLineFunction() { + + Integer lineFunctionResult1 = GeometryUtils.lineFunction(linePoint1, linePoint2, arbitraryPoint1); + Integer lineFunctionResult2 = GeometryUtils.lineFunction(linePoint1, linePoint2, arbitraryPoint2); + Integer lineFunctionResult3 = GeometryUtils.lineFunction(linePoint1, linePoint2, arbitraryPoint3); + + //Point1 and Point2 are on opposite sides + assertEquals(Math.abs(lineFunctionResult1), Math.abs(lineFunctionResult2)); + assertNotEquals(lineFunctionResult1, lineFunctionResult2); + + //Point3 is on the line + assertEquals((long) lineFunctionResult3, 0L); + } + + @Test + public void testMakeArbitraryVectorPoint() { + + //Make a point (1,0) from point (0,0) + Point2D newPoint = GeometryUtils.makeArbitraryVectorPoint(linePoint1, 0d, 1d); + Point2D expected = new Point2D(1,0); + + assertEquals(expected.getX(), newPoint.getX(), 1E-6); + assertEquals(expected.getY(), newPoint.getY(), 1E-6); + + newPoint = GeometryUtils.makeArbitraryVectorPoint(linePoint1, 90d, 1d); + expected = new Point2D(0, 1); + + assertEquals(expected.getX(), newPoint.getX(), 1E-6); + assertEquals(expected.getY(), newPoint.getY(), 1E-6); + } +}