mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 06:18:44 +00:00
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:
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user