Plugged Canvas map to canvas view controller to display map

- rebase on the latest develop status
- optimised the scaling factor the map to fit the canvas view
- a new image containing map image is displayed under race canvas

#story[928]
This commit is contained in:
Haoming Yin
2017-05-24 13:52:49 +12:00
parent 8f93956ff1
commit f85d3bf5fe
2 changed files with 82 additions and 14 deletions
+5 -2
View File
@@ -15,8 +15,10 @@ public class App extends Application {
public void start(Stage primaryStage) throws Exception { public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/views/MainView.fxml")); Parent root = FXMLLoader.load(getClass().getResource("/views/MainView.fxml"));
primaryStage.setTitle("RaceVision"); primaryStage.setTitle("RaceVision");
primaryStage.setScene(new Scene(root)); primaryStage.setScene(new Scene(root, 1530, 960));
primaryStage.setMaximized(true); primaryStage.setMaxWidth(1530);
primaryStage.setMaxHeight(960);
// primaryStage.setMaximized(true);
primaryStage.show(); primaryStage.show();
primaryStage.setOnCloseRequest(e -> { primaryStage.setOnCloseRequest(e -> {
@@ -64,6 +66,7 @@ public class App extends Application {
else{ else{
// sr = new StreamReceiver("localhost", 4949, "RaceStream"); // sr = new StreamReceiver("localhost", 4949, "RaceStream");
sr = new StreamReceiver("livedata.americascup.com", 4941, "RaceStream"); sr = new StreamReceiver("livedata.americascup.com", 4941, "RaceStream");
// sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941, "RaceStream");
} }
sr.start(); sr.start();
@@ -12,12 +12,15 @@ import javafx.geometry.Point2D;
import javafx.scene.Group; import javafx.scene.Group;
import javafx.scene.canvas.Canvas; import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext; import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.scene.text.Font; import javafx.scene.text.Font;
import seng302.models.BoatGroup; import seng302.models.BoatGroup;
import seng302.models.Colors; import seng302.models.Colors;
import seng302.models.Yacht; import seng302.models.Yacht;
import seng302.models.map.Boundary;
import seng302.models.map.CanvasMap;
import seng302.models.mark.GateMark; import seng302.models.mark.GateMark;
import seng302.models.mark.Mark; import seng302.models.mark.Mark;
import seng302.models.mark.MarkGroup; 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.Limit;
import seng302.models.stream.XMLParser.RaceXMLObject.Participant; import seng302.models.stream.XMLParser.RaceXMLObject.Participant;
import seng302.models.stream.packets.BoatPositionPacket; import seng302.models.stream.packets.BoatPositionPacket;
import seng302.server.simulator.GeoUtility;
import seng302.server.simulator.mark.Position;
/** /**
* Created by ptg19 on 15/03/17. * Created by ptg19 on 15/03/17.
@@ -42,15 +47,18 @@ public class CanvasController {
private ResizableCanvas canvas; private ResizableCanvas canvas;
private Group group; private Group group;
private GraphicsContext gc; private GraphicsContext gc;
private ImageView mapImage;
private final int MARK_SIZE = 10; private final int MARK_SIZE = 10;
private final int BUFFER_SIZE = 50; 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_WIDTH = 720;
private final int CANVAS_HEIGHT = 720; private final int CANVAS_HEIGHT = 720;
private final int LHS_BUFFER = BUFFER_SIZE; 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 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 boolean horizontalInversion = false;
private double distanceScaleFactor; private double distanceScaleFactor;
@@ -61,6 +69,8 @@ public class CanvasController {
private Mark maxLonPoint; private Mark maxLonPoint;
private double referencePointX; private double referencePointX;
private double referencePointY; private double referencePointY;
private double metersPerPixelX;
private double metersPerPixelY;
private List<MarkGroup> markGroups = new ArrayList<>(); private List<MarkGroup> markGroups = new ArrayList<>();
private List<BoatGroup> boatGroups = new ArrayList<>(); private List<BoatGroup> boatGroups = new ArrayList<>();
@@ -87,6 +97,12 @@ public class CanvasController {
canvas = new ResizableCanvas(); canvas = new ResizableCanvas();
group = new Group(); 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(canvas);
canvasPane.getChildren().add(group); canvasPane.getChildren().add(group);
// Bind canvas size to stack pane size. // Bind canvas size to stack pane size.
@@ -97,11 +113,13 @@ public class CanvasController {
public void initializeCanvas (){ public void initializeCanvas (){
gc = canvas.getGraphicsContext2D(); gc = canvas.getGraphicsContext2D();
gc.save(); // gc.save();
gc.setFill(Color.SKYBLUE); // gc.setFill(Color.SKYBLUE);
gc.fillRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT); // gc.fillRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT);
gc.restore(); // gc.restore();
gc.setGlobalAlpha(0.5);
fitMarksToCanvas(); fitMarksToCanvas();
drawGoogleMap();
// TODO: 1/05/17 wmu16 - Change this call to now draw the marks as from the xml // 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 * Adds border marks to the canvas, taken from the XML file
@@ -174,8 +216,8 @@ public class CanvasController {
borderPoint2.getX(), borderPoint2.getY()); borderPoint2.getX(), borderPoint2.getY());
xBoundaryPoints[courseLimits.size()-1] = borderPoint1.getX(); xBoundaryPoints[courseLimits.size()-1] = borderPoint1.getX();
yBoundaryPoints[courseLimits.size()-1] = borderPoint1.getY(); yBoundaryPoints[courseLimits.size()-1] = borderPoint1.getY();
gc.setFill(Color.LIGHTBLUE); // gc.setFill(Color.LIGHTBLUE);
gc.fillPolygon(xBoundaryPoints,yBoundaryPoints,yBoundaryPoints.length); // gc.fillPolygon(xBoundaryPoints,yBoundaryPoints,yBoundaryPoints.length);
} }
private void updateGroups(){ private void updateGroups(){
@@ -201,11 +243,13 @@ public class CanvasController {
private void checkForCourseChanges() { private void checkForCourseChanges() {
if (StreamParser.isNewRaceXmlReceived()){ if (StreamParser.isNewRaceXmlReceived()){
gc.setFill(Color.SKYBLUE); // gc.setFill(Color.SKYBLUE);
gc.fillRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT); // gc.fillRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT);
gc.restore(); // gc.restore();
gc.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
drawGoogleMap();
addRaceBorder(); addRaceBorder();
canvas.toBack(); // canvas.toBack();
} }
} }
@@ -465,6 +509,27 @@ public class CanvasController {
return new Point2D(xAxisLocation, yAxisLocation); 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<BoatGroup> getBoatGroups() { List<BoatGroup> getBoatGroups() {
return boatGroups; return boatGroups;
} }