diff --git a/src/main/java/seng302/App.java b/src/main/java/seng302/App.java index ac264db6..20c01788 100644 --- a/src/main/java/seng302/App.java +++ b/src/main/java/seng302/App.java @@ -15,8 +15,10 @@ public class App extends Application { public void start(Stage primaryStage) throws Exception { Parent root = FXMLLoader.load(getClass().getResource("/views/MainView.fxml")); primaryStage.setTitle("RaceVision"); - primaryStage.setScene(new Scene(root)); - primaryStage.setMaximized(true); + primaryStage.setScene(new Scene(root, 1530, 960)); + primaryStage.setMaxWidth(1530); + primaryStage.setMaxHeight(960); +// primaryStage.setMaximized(true); primaryStage.show(); primaryStage.setOnCloseRequest(e -> { @@ -64,6 +66,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/controllers/CanvasController.java b/src/main/java/seng302/controllers/CanvasController.java index 0bdeae25..a1a83e8b 100644 --- a/src/main/java/seng302/controllers/CanvasController.java +++ b/src/main/java/seng302/controllers/CanvasController.java @@ -12,12 +12,15 @@ import javafx.geometry.Point2D; import javafx.scene.Group; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; +import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; import javafx.scene.paint.Color; import javafx.scene.text.Font; import seng302.models.BoatGroup; import seng302.models.Colors; import seng302.models.Yacht; +import seng302.models.map.Boundary; +import seng302.models.map.CanvasMap; import seng302.models.mark.GateMark; import seng302.models.mark.Mark; import seng302.models.mark.MarkGroup; @@ -28,6 +31,8 @@ import seng302.models.stream.XMLParser; import seng302.models.stream.XMLParser.RaceXMLObject.Limit; import seng302.models.stream.XMLParser.RaceXMLObject.Participant; import seng302.models.stream.packets.BoatPositionPacket; +import seng302.server.simulator.GeoUtility; +import seng302.server.simulator.mark.Position; /** * Created by ptg19 on 15/03/17. @@ -42,15 +47,18 @@ public class CanvasController { private ResizableCanvas canvas; private Group group; private GraphicsContext gc; + private ImageView mapImage; private final int MARK_SIZE = 10; private final int BUFFER_SIZE = 50; + private final int PANEL_WIDTH = 1260; // it should be 1280 but, minors 40 to cancel the bias. + private final int PANEL_HEIGHT = 960; private final int CANVAS_WIDTH = 720; private final int CANVAS_HEIGHT = 720; private final int LHS_BUFFER = BUFFER_SIZE; - private final int RHS_BUFFER = BUFFER_SIZE + MARK_SIZE / 2; + private final int RHS_BUFFER = BUFFER_SIZE; private final int TOP_BUFFER = BUFFER_SIZE; - private final int BOT_BUFFER = TOP_BUFFER + MARK_SIZE / 2; + private final int BOT_BUFFER = TOP_BUFFER; private boolean horizontalInversion = false; private double distanceScaleFactor; @@ -61,6 +69,8 @@ public class CanvasController { private Mark maxLonPoint; private double referencePointX; private double referencePointY; + private double metersPerPixelX; + private double metersPerPixelY; private List markGroups = new ArrayList<>(); private List boatGroups = new ArrayList<>(); @@ -87,6 +97,12 @@ public class CanvasController { canvas = new ResizableCanvas(); group = new Group(); + // create image view for map, bind panel size to image + mapImage = new ImageView(); + canvasPane.getChildren().add(mapImage); + mapImage.fitWidthProperty().bind(canvasPane.widthProperty()); + mapImage.fitHeightProperty().bind(canvasPane.heightProperty()); + canvasPane.getChildren().add(canvas); canvasPane.getChildren().add(group); // Bind canvas size to stack pane size. @@ -97,11 +113,13 @@ public class CanvasController { public void initializeCanvas (){ gc = canvas.getGraphicsContext2D(); - gc.save(); - gc.setFill(Color.SKYBLUE); - gc.fillRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT); - gc.restore(); +// gc.save(); +// gc.setFill(Color.SKYBLUE); +// gc.fillRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT); +// gc.restore(); + gc.setGlobalAlpha(0.5); fitMarksToCanvas(); + drawGoogleMap(); // TODO: 1/05/17 wmu16 - Change this call to now draw the marks as from the xml @@ -137,6 +155,30 @@ public class CanvasController { }; } + /** + * First find the top right and bottom left points' geo locations, then retrieve + * map from google to display on image view. - Haoming 22/5/2017 + */ + private void drawGoogleMap() { + findMetersPerPixel(); + Point2D topLeftPoint = findScaledXY(maxLatPoint.getLatitude(), minLonPoint.getLongitude()); + // distance from top left extreme to panel origin (top left corner) + double distanceFromTopLeftToOrigin = Math.sqrt(Math.pow(topLeftPoint.getX() * metersPerPixelX, 2) + Math.pow(topLeftPoint.getY() * metersPerPixelY, 2)); + // angle from top left extreme to panel origin + double bearingFromTopLeftToOrigin = Math.toDegrees(Math.atan2(-topLeftPoint.getX(), topLeftPoint.getY())); + // the top left extreme + Position topLeftPos = new Position(maxLatPoint.getLatitude(), minLonPoint.getLongitude()); + Position originPos = GeoUtility.getGeoCoordinate(topLeftPos, bearingFromTopLeftToOrigin, distanceFromTopLeftToOrigin); + + // distance from origin corner to bottom right corner of the panel + double distanceFromOriginToBottomRight = Math.sqrt(Math.pow(PANEL_HEIGHT* metersPerPixelY, 2) + Math.pow(PANEL_WIDTH * metersPerPixelX, 2)); + double bearingFromOriginToBottomRight = Math.toDegrees(Math.atan2(PANEL_WIDTH, -PANEL_HEIGHT)); + Position bottomRightPos = GeoUtility.getGeoCoordinate(originPos, bearingFromOriginToBottomRight, distanceFromOriginToBottomRight); + + Boundary boundary = new Boundary(originPos.getLat(), bottomRightPos.getLng(), bottomRightPos.getLat(), originPos.getLng()); + CanvasMap canvasMap = new CanvasMap(boundary); + mapImage.setImage(canvasMap.getMapImage()); + } /** * Adds border marks to the canvas, taken from the XML file @@ -174,8 +216,8 @@ public class CanvasController { borderPoint2.getX(), borderPoint2.getY()); xBoundaryPoints[courseLimits.size()-1] = borderPoint1.getX(); yBoundaryPoints[courseLimits.size()-1] = borderPoint1.getY(); - gc.setFill(Color.LIGHTBLUE); - gc.fillPolygon(xBoundaryPoints,yBoundaryPoints,yBoundaryPoints.length); +// gc.setFill(Color.LIGHTBLUE); +// gc.fillPolygon(xBoundaryPoints,yBoundaryPoints,yBoundaryPoints.length); } private void updateGroups(){ @@ -201,11 +243,13 @@ public class CanvasController { private void checkForCourseChanges() { if (StreamParser.isNewRaceXmlReceived()){ - gc.setFill(Color.SKYBLUE); - gc.fillRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT); - gc.restore(); +// gc.setFill(Color.SKYBLUE); +// gc.fillRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT); +// gc.restore(); + gc.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); + drawGoogleMap(); addRaceBorder(); - canvas.toBack(); +// canvas.toBack(); } } @@ -465,6 +509,27 @@ public class CanvasController { return new Point2D(xAxisLocation, yAxisLocation); } + /** + * Find the number of meters per pixel. + */ + private void findMetersPerPixel () { + Point2D p1, p2; + Mark m1, m2; + double theta, distance, dx, dy, dHorizontal, dVertical; + m1 = new SingleMark("m1", maxLatPoint.getLatitude(), minLonPoint.getLongitude(), 1); + m2 = new SingleMark("m2", minLatPoint.getLatitude(), maxLonPoint.getLongitude(), 2); + p1 = findScaledXY(m1); + p2 = findScaledXY(m2); + theta = Mark.calculateHeadingRad(m1, m2); + distance = Mark.calculateDistance(m1, m2); + dHorizontal = Math.abs(Math.sin(theta) * distance); + dVertical = Math.abs(Math.cos(theta) * distance); + dx = Math.abs(p1.getX() - p2.getX()); + dy = Math.abs(p1.getY() - p2.getY()); + metersPerPixelX = dHorizontal / dx; + metersPerPixelY = dVertical / dy; + } + List getBoatGroups() { return boatGroups; }