diff --git a/racevisionGame/src/main/java/mock/model/MockBoat.java b/racevisionGame/src/main/java/mock/model/MockBoat.java index 6e51295d..6fa3fd2b 100644 --- a/racevisionGame/src/main/java/mock/model/MockBoat.java +++ b/racevisionGame/src/main/java/mock/model/MockBoat.java @@ -211,11 +211,22 @@ public class MockBoat extends Boat { * @return true if mark is on port side */ public boolean isPortSide(Mark mark){ - //if this boat is lower than the mark check which way it is facing - if(this.getCurrentPosition().getLongitude() < mark.getPosition().getLongitude()){ + Bearing towardsMark = GPSCoordinate.calculateBearing(this.getCurrentPosition(), mark.getPosition()); + if (towardsMark.degrees() > 315 || towardsMark.degrees() <= 45){ + //south quadrant return this.getBearing().degrees() <= 180; + } else if(towardsMark.degrees() > 45 && towardsMark.degrees() <= 135){ + //west quadrant + return (this.getBearing().degrees() <= 270 && this.getBearing().degrees() >= 90); + }else if(towardsMark.degrees() > 135 && towardsMark.degrees() <= 225){ + //north quadrant + return this.getBearing().degrees() >= 180; + }else if(towardsMark.degrees() > 225 && towardsMark.degrees() <= 315){ + //east quadrant + return (this.getBearing().degrees() <= 90 || this.getBearing().degrees() >= 270); }else{ - return this.getBearing().degrees() > 180; + //should not reach here + return false; } } @@ -226,10 +237,22 @@ public class MockBoat extends Boat { */ public boolean isStarboardSide(Mark mark){ //if this boat is lower than the mark check which way it is facing - if(this.getCurrentPosition().getLongitude() < mark.getPosition().getLongitude()){ - return this.getBearing().degrees() >= 180; + Bearing towardsMark = GPSCoordinate.calculateBearing(this.getCurrentPosition(), mark.getPosition()); + if (towardsMark.degrees() > 315 || towardsMark.degrees() <= 45){ + //south quadrant + return !(this.getBearing().degrees() <= 180); + } else if(towardsMark.degrees() > 45 && towardsMark.degrees() <= 135){ + //west quadrant + return !(this.getBearing().degrees() <= 270 && this.getBearing().degrees() >= 90); + }else if(towardsMark.degrees() > 135 && towardsMark.degrees() <= 225){ + //north quadrant + return !(this.getBearing().degrees() >= 180); + }else if(towardsMark.degrees() > 225 && towardsMark.degrees() <= 315){ + //east quadrant + return !(this.getBearing().degrees() <= 90 || this.getBearing().degrees() >= 270); }else{ - return this.getBearing().degrees() < 180; + //should not reach here + return false; } } diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index 71e74109..345f3075 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -3,12 +3,10 @@ package mock.model; import network.Messages.Enums.BoatStatusEnum; import network.Messages.Enums.RaceStatusEnum; import network.Messages.LatestMessages; -import org.opengis.geometry.primitive.*; import shared.dataInput.BoatDataSource; import shared.dataInput.RaceDataSource; import shared.dataInput.RegattaDataSource; import shared.model.*; -import shared.model.Bearing; import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; @@ -321,6 +319,8 @@ public class MockRace extends Race { if (!finish && totalElapsedMilliseconds >= updatePeriodMilliseconds) { + checkPosition(boat, totalElapsedMilliseconds); + if (boat.getCurrentSpeed() == 0) { newOptimalVMG(boat); boat.setBearing(boat.calculateBearingToNextMarker()); @@ -467,22 +467,22 @@ public class MockRace extends Race { * @param boat the boat that is rounding a mark * @param roundingChecks the checks to run */ - private void boatRoundingCheckPort(MockBoat boat, List roundingChecks){ + private void boatRoundingCheckPort(MockBoat boat, List roundingChecks, Bearing legBearing){ //boats must pass all checks in order to round a mark switch (boat.getRoundingStatus()) { case 0://hasn't started rounding -// System.out.println("round 0"); - if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && - GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), - roundingChecks.get(0), boat.getCurrentPosition())) { + if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMarkForRounding(legBearing)) && + GPSCoordinate.passesLine(boat.getCurrentLeg().getEndCompoundMark().getMarkForRounding(legBearing).getPosition(), + roundingChecks.get(0), boat.getCurrentPosition(), legBearing)) { + System.out.println("true"); boat.increaseRoundingStatus(); } break; case 1://has been parallel to the mark // System.out.println("round 1"); - if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMark1()) && - GPSCoordinate.intersects(boat.getCurrentLeg().getEndCompoundMark().getMark1().getPosition(), - roundingChecks.get(1), boat.getCurrentPosition())) { + if (boat.isPortSide(boat.getCurrentLeg().getEndCompoundMark().getMarkForRounding(legBearing)) && + GPSCoordinate.passesLine(boat.getCurrentLeg().getEndCompoundMark().getMarkForRounding(legBearing).getPosition(), + roundingChecks.get(1), boat.getCurrentPosition(), Bearing.fromDegrees(legBearing.degrees() - 90))) {//negitive 90 from bearing because of port rounding boat.increaseRoundingStatus(); } break; @@ -533,7 +533,6 @@ public class MockRace extends Race { * @param timeElapsed The total time, in milliseconds, that has elapsed since the race started. */ protected void checkPosition(MockBoat boat, long timeElapsed) { - //The distance, in nautical miles, within which the boat needs to get in order to consider that it has reached the marker. double epsilonNauticalMiles = 250.0 / Constants.NMToMetersConversion; //250 meters. @@ -541,17 +540,15 @@ public class MockRace extends Race { //Boat is within an acceptable distance from the mark. GPSCoordinate startDirectionLinePoint = boat.getCurrentLeg().getStartCompoundMark().getMark1Position(); - //todo will need to change this for gates, so that the end point is the side of the gate needed to be rounded GPSCoordinate endDirectionLinePoint = boat.getCurrentLeg().getEndCompoundMark().getMark1Position(); - Bearing bearingOfDirectionLine = GPSCoordinate.calculateBearing(startDirectionLinePoint, endDirectionLinePoint); //use the direction line to create three invisible points that act as crossover lines a boat must cross //to round a mark - GPSCoordinate roundCheck1 = GPSCoordinate.calculateNewPosition(startDirectionLinePoint, + GPSCoordinate roundCheck1 = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, epsilonNauticalMiles, Azimuth.fromDegrees(bearingOfDirectionLine.degrees() + 90));//adding 90 so the check line is parallel - GPSCoordinate roundCheck2 = GPSCoordinate.calculateNewPosition(startDirectionLinePoint, + GPSCoordinate roundCheck2 = GPSCoordinate.calculateNewPosition(endDirectionLinePoint, epsilonNauticalMiles, Azimuth.fromDegrees(bearingOfDirectionLine.degrees())); List roundingChecks = new ArrayList(Arrays.asList(roundCheck1, roundCheck2)); @@ -559,7 +556,7 @@ public class MockRace extends Race { switch (boat.getCurrentLeg().getEndCompoundMark().getRoundingType()) { case SP://Not yet implemented so these gates will be rounded port side case Port: - boatRoundingCheckPort(boat, roundingChecks); + boatRoundingCheckPort(boat, roundingChecks, bearingOfDirectionLine); break; case PS://not yet implemented so these gates will be rounded starboard side case Starboard: diff --git a/racevisionGame/src/main/java/shared/model/GPSCoordinate.java b/racevisionGame/src/main/java/shared/model/GPSCoordinate.java index 566413c6..8bd1511d 100644 --- a/racevisionGame/src/main/java/shared/model/GPSCoordinate.java +++ b/racevisionGame/src/main/java/shared/model/GPSCoordinate.java @@ -170,6 +170,46 @@ public class GPSCoordinate { } + /** + * Checks to see if a point passes or lands on a line + * @param linePointA first point for a line + * @param linePointB second point for a line + * @param point point to check + * @param directionBearing direction of the correct side of line + * @return true if on the correct side + */ + public static boolean passesLine(GPSCoordinate linePointA, GPSCoordinate linePointB, GPSCoordinate point, Bearing directionBearing) { + double d = lineCheck(linePointA, linePointB, point);//this gives a number < 0 for one side and > 0 for an other + + //to find if the side is the correct one + //compare with point that is known on the correct side + GPSCoordinate pointForComparison = GPSCoordinate.calculateNewPosition(linePointA, + 250, Azimuth.fromDegrees(directionBearing.degrees())); + double d2 = lineCheck(linePointA, linePointB, pointForComparison); + + return (d > 0 && d2 > 0) || (d < 0 && d2 < 0) || d == 0; + } + + /** + * returns a double that is positive or negative based on which + * side of the line it is on. returns 0 if it is on the line + * @param linePointA first point to make up the line + * @param linePointB second point to make up the line + * @param point the point to check + * @return greater than 0 for one side, less than 0 for another + */ + private static double lineCheck(GPSCoordinate linePointA, GPSCoordinate linePointB, GPSCoordinate point) { + double linePointALat = linePointA.getLatitude(); + double linePointALon = linePointA.getLongitude(); + double linePointBLat = linePointB.getLatitude(); + double linePointBLon = linePointB.getLongitude(); + double pointLat = point.getLatitude(); + double pointLon = point.getLongitude(); + + double d1 = (pointLat - linePointALat) * (linePointBLon - linePointALon); + double d2 = (pointLon - linePointALon) * (linePointBLat - linePointALat); + return d1 - d2; //this gives a number < 0 for one side and > 0 for an other + } /** diff --git a/racevisionGame/src/main/java/visualiser/gameController/ControllerClient.java b/racevisionGame/src/main/java/visualiser/gameController/ControllerClient.java index bb91f2a4..441f61e2 100644 --- a/racevisionGame/src/main/java/visualiser/gameController/ControllerClient.java +++ b/racevisionGame/src/main/java/visualiser/gameController/ControllerClient.java @@ -11,8 +11,6 @@ import visualiser.gameController.Keys.ControlKey; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; -import java.net.SocketException; -import java.nio.ByteBuffer; import java.util.logging.Level; import java.util.logging.Logger; @@ -62,7 +60,7 @@ public class ControllerClient { BinaryMessageEncoder binaryMessage = new BinaryMessageEncoder(MessageType.BOATACTION, System.currentTimeMillis(), 0, (short) encodedBoatAction.length, encodedBoatAction); - System.out.println("Sending out key: " + protocolCode); +// System.out.println("Sending out key: " + protocolCode); outputStream.write(binaryMessage.getFullMessage()); } catch (InvalidMessageException e) { diff --git a/racevisionGame/src/main/java/visualiser/gameController/ControllerServer.java b/racevisionGame/src/main/java/visualiser/gameController/ControllerServer.java index eef4212d..dbbca586 100644 --- a/racevisionGame/src/main/java/visualiser/gameController/ControllerServer.java +++ b/racevisionGame/src/main/java/visualiser/gameController/ControllerServer.java @@ -1,8 +1,6 @@ package visualiser.gameController; import mock.model.RaceLogic; -import mock.model.commandFactory.Command; -import mock.model.commandFactory.CommandFactory; import network.BinaryMessageDecoder; import network.Exceptions.InvalidMessageException; import network.MessageDecoders.BoatActionDecoder; @@ -12,8 +10,8 @@ import network.Messages.Enums.BoatActionEnum; import java.io.DataInputStream; import java.io.IOException; import java.net.Socket; -import java.util.logging.Level; import java.util.Observable; +import java.util.logging.Level; import java.util.logging.Logger; /** diff --git a/racevisionGame/src/main/java/visualiser/gameController/InputChecker.java b/racevisionGame/src/main/java/visualiser/gameController/InputChecker.java index 34a7d544..057b5721 100644 --- a/racevisionGame/src/main/java/visualiser/gameController/InputChecker.java +++ b/racevisionGame/src/main/java/visualiser/gameController/InputChecker.java @@ -7,8 +7,6 @@ import visualiser.gameController.Keys.KeyFactory; import java.util.HashMap; -import static javafx.application.Application.launch; - /** * Class for checking what keys are currently being used */ @@ -28,7 +26,7 @@ public class InputChecker { ControlKey controlKey = keyFactory.getKey(codeString); if (controlKey != null) { controlKey.onAction(); - System.out.println(controlKey.toString() + " is Pressed."); +// System.out.println(controlKey.toString() + " is Pressed."); } currentlyActiveKeys.put(codeString, true); } @@ -39,7 +37,7 @@ public class InputChecker { ControlKey controlKey = keyFactory.getKey(codeString); if (controlKey != null) { controlKey.onRelease(); - System.out.println(controlKey.toString() + " is Released."); +// System.out.println(controlKey.toString() + " is Released."); } currentlyActiveKeys.remove(event.getCode().toString()); }); @@ -51,7 +49,7 @@ public class InputChecker { ControlKey controlKey = keyFactory.getKey(key); if (controlKey != null){ controlKey.onHold(); - System.out.println(controlKey.toString() + " is Held."); +// System.out.println(controlKey.toString() + " is Held."); } } // for (String key : InputKeys.stringKeysMap.keySet()){ diff --git a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java index 7af6feb8..84b79270 100644 --- a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java +++ b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java @@ -1,7 +1,6 @@ package visualiser.model; -import javafx.scene.image.Image; import javafx.scene.paint.Color; import javafx.scene.paint.Paint; import javafx.scene.transform.Rotate;