Implemented algorithm for checking if boat passes through a mark.

Mark rounding works for whole course (WITH BUGS)
Still some gate logic to work out.
Moved gate function to GeoUtil class

tags: #story[1124] #pair[hyi25, wmu16]
This commit is contained in:
William Muir
2017-08-07 17:28:12 +12:00
parent 7f0329dda6
commit 4375b73257
5 changed files with 78 additions and 7 deletions
+25 -5
View File
@@ -10,6 +10,8 @@ import javafx.beans.property.ReadOnlyDoubleWrapper;
import javafx.beans.property.ReadOnlyLongProperty;
import javafx.beans.property.ReadOnlyLongWrapper;
import javafx.scene.paint.Color;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seng302.gameServer.GameState;
import seng302.model.mark.CompoundMark;
import seng302.model.mark.Mark;
@@ -28,8 +30,11 @@ public class Yacht {
void notifyLocation(Yacht yacht, double lat, double lon, double heading, double velocity);
}
private Logger logger = LoggerFactory.getLogger(Yacht.class);
private static final Double ROUNDING_DISTANCE = 50d; // TODO: 3/08/17 wmu16 - Look into this value further
//BOTH AFAIK
private String boatType;
private Integer sourceId;
@@ -39,7 +44,7 @@ public class Yacht {
private String country;
private Long estimateTimeAtFinish;
private Integer currentMarkSeqID = 1;
private Integer currentMarkSeqID = 0;
private Long markRoundTime;
private Double distanceToNextMark;
private Long timeTillNext;
@@ -119,6 +124,7 @@ public class Yacht {
}
//UPDATE BOAT LOCATION
lastLocation = location;
location = GeoUtility.getGeoCoordinate(location, heading, velocity * secondsElapsed);
//CHECK FOR MARK ROUNDING
@@ -167,11 +173,22 @@ public class Yacht {
* 'mark passing algorithm'
*/
private void checkForMarkRounding() {
if (!GameState.getMarkOrder().isLastMark(currentMarkSeqID) && currentMarkSeqID != 0) {
CompoundMark currentMark = GameState.getMarkOrder().getCurrentMark(currentMarkSeqID);
if (GameState.getMarkOrder().isLastMark(currentMarkSeqID) || currentMarkSeqID == 0) {
if (GeoUtility.checkCrossedLine(currentMark.getSubMark(1),
currentMark.getSubMark(2), lastLocation, location)) {
System.out.println(
"(" + currentMarkSeqID + ") Passed gate: " + currentMark.getMarks().get(0)
.getName()
+ " ID(" + currentMark.getId() + ")");
currentMarkSeqID++;
}
} else {
//ALL OTHER MARKS
distanceToNextMark = calcDistanceToNextMark();
// System.out.println("distanceToNextMark = " + distanceToNextMark);
CompoundMark nextMark = GameState.getMarkOrder().getNextMark(currentMarkSeqID);
CompoundMark currentMark = GameState.getMarkOrder().getCurrentMark(currentMarkSeqID);
CompoundMark prevMark = GameState.getMarkOrder().getPreviousMark(currentMarkSeqID);
//1 TEST FOR ENTERING THE ROUDNING DISTANCE
@@ -188,7 +205,6 @@ public class Yacht {
if (GeoUtility.isPointInTriangle(lastLocation, location, nextMark.getMarks().get(0),
thisCurrentMark)) {
hasPassedFirstLine = true;
System.out.println("Passed first line!");
}
//3 TEST FOR CROSSING PREV - CURRENT LINE SECOND
@@ -198,7 +214,10 @@ public class Yacht {
currentMarkSeqID++;
hasPassedFirstLine = false;
hasEnteredRoundingZone = false;
System.out.println("SUCCESFUL ROUDNING!");
System.out.println(
"(" + currentMarkSeqID + ") Passed mark: " + currentMark.getMarks()
.get(0).getName()
+ " ID(" + currentMark.getId() + ")");
break;
}
}
@@ -206,6 +225,7 @@ public class Yacht {
}
}
public void adjustHeading(Double amount) {
Double newVal = heading + amount;
lastHeading = heading;
@@ -1,7 +1,10 @@
package seng302.utilities;
import javafx.geometry.Point2D;
import seng302.gameServer.GameState;
import seng302.model.GeoPoint;
import seng302.model.mark.CompoundMark;
import seng302.model.mark.Mark;
public class GeoUtility {
@@ -126,6 +129,35 @@ public class GeoUtility {
}
/**
* Checks if a point passes across a line, either direction
* See the wiki Mark Rounding algorithm for more info
*
* @param mark1 One mark of the line
* @param mark2 The second mark of the line
* @param lastLocation The last location of the point crossing this line
* @param location The current location of the point crossing this line
* @return True if crossed since last location --> current location, false otherwise
*/
public static Boolean checkCrossedLine(GeoPoint mark1, GeoPoint mark2, GeoPoint lastLocation,
GeoPoint location) {
//START GATE OR FINISH GATE
Double alpha = GeoUtility.getBearing(mark1, lastLocation);
Double beta = GeoUtility.getBearing(mark1, mark2);
Double theta = GeoUtility.getBearing(mark1, location);
alpha = (alpha > 180) ? 360 - alpha : alpha;
beta = (beta > 180) ? 360 - beta : beta;
theta = (theta > 180) ? 360 - theta : theta;
if (alpha < beta && theta > beta) {
if (!GeoUtility.isPointInTriangle(mark1, lastLocation, location, mark2)) {
return true;
}
}
return false;
}
/**
* Given a point and a vector (angle and vector length) Will create a new point, that vector
* away from the origin point
@@ -174,7 +174,6 @@ public class GameClient {
break;
case BOAT_XML:
System.out.println("GOT SUM BOATS YAY :)");
allBoatsMap = XMLParser.parseBoats(
StreamParser.extractXmlMessage(packet)
);
@@ -312,7 +312,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
updateRaceTime();
updateWindDirection();
updateOrder();
updateSparkLine();
// updateSparkLine();
}
}, 0, 1000);
}
@@ -9,9 +9,11 @@ import javafx.geometry.Point2D;
import org.junit.Before;
import org.junit.Test;
import seng302.model.GeoPoint;
import seng302.model.mark.CompoundMark;
import seng302.utilities.GeoUtility;
/**
* http://www.geoplaner.com/ For plotting geo points for visualisation
* To test methods in GeoUtility.
* Use this site to calculate distances
* https://rechneronline.de/geo-coordinates/#distance
@@ -150,4 +152,22 @@ public class GeoUtilityTest {
assertFalse(GeoUtility.isPointInTriangle(v1, v2, v3, p2));
}
@Test
public void testCheckCrossedGate() {
GeoPoint mark1 = new GeoPoint(37.40937, -122.62233);
GeoPoint mark2 = new GeoPoint(37.40938, -122.62154);
GeoPoint location1 = new GeoPoint(37.40964, -122.62196);
GeoPoint location2 = new GeoPoint(37.40910, -122.62189);
GeoPoint location3 = new GeoPoint(37.40949, -122.62202);
GeoPoint location4 = new GeoPoint(34.40955, -122.62176);
GeoPoint location5 = new GeoPoint(37.40927, -122.62152);
GeoPoint location6 = new GeoPoint(34.40933, -122.62163);
assertTrue(GeoUtility.checkCrossedLine(mark1, mark2, location1, location2));
assertFalse(GeoUtility.checkCrossedLine(mark1, mark2, location4, location3));
assertFalse(GeoUtility.checkCrossedLine(mark1, mark2, location1, location3));
assertFalse(GeoUtility.checkCrossedLine(mark1, mark2, location5, location6));
}
}