Calculation of upwind downwind leg given a boat, wind and next mark now works. created GeometryUtils class

Can accurately calculate if a boat is going upwind or downward using a line function for the wind vector from the gate and the boat position from the gate.

Requires knowledge of the next mark which requires the boat to have passed a mark. This could be fixed by extracting the leg number from the race status packet and mapping these to gates in an initalisation step

tags: #story[956]
This commit is contained in:
William Muir
2017-05-24 14:57:22 +12:00
parent 89464e033e
commit 1cac7cc189
7 changed files with 200 additions and 30 deletions
+1
View File
@@ -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();
+63
View File
@@ -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);
}
}
@@ -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<BoatGroup> getBoatGroups() {
return boatGroups;
}
List<MarkGroup> getMarkGroups() {
return markGroups;
}
}
@@ -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) {
}
}
}
}
+39 -24
View File
@@ -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
// }
}
@@ -161,4 +161,8 @@ public class MarkGroup extends Group {
idArray[i++] = mark.getId();
return idArray;
}
public Mark getMainMark() {
return mainMark;
}
}