You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
8.3 KiB

package seng302.Model;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.transform.Rotate;
import seng302.Constants;
import seng302.GPSCoordinate;
import seng302.GraphCoordinate;
import seng302.RaceMap;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Random;
/**
* This creates a JavaFX Canvas that is fills it's parent.
* Cannot be downsized.
* Created by fwy13 on 17/03/17.
*/
public class ResizableRaceCanvas extends Canvas {
private GraphicsContext gc;
private RaceMap map;
private BoatInRace[] boats;
/**
* Sets the boats that are to be displayed in this race.
* @param boats
*/
public void setBoats(BoatInRace[] boats) {
this.boats = boats;
}
public ResizableRaceCanvas(RaceMap map) {
this.map = map;
gc = this.getGraphicsContext2D();
// Redraw canvas when size changes.
widthProperty().addListener(evt -> drawRaceMap());
heightProperty().addListener(evt -> drawRaceMap());
}
/**
* Constructor
*/
public ResizableRaceCanvas(){
this(null);
}
/**
* Sets the RaceMap that the RaceCanvas is to be displaying for.
* @param map
*/
public void setMap (RaceMap map) {
this.map = map;
}
/**
* Displays the mark of a race as a circle.
* @param graphCoordinate Latitude and Logintude in GraphCoordinate that it is to be displayed as.
* @param paint Colour the mark is to be coloured.
* @see GraphCoordinate
* @see Color
* @see Paint
*/
public void displayMark(GraphCoordinate graphCoordinate, Paint paint){
double d = 15;
gc.setFill(paint);
gc.fillOval(graphCoordinate.getX() - (d/2), graphCoordinate.getY() - (d/2), d, d);
}
/**
* Displays a line on the map with rectangles on the starting and ending point of the line.
* @param graphCoordinateA Starting Point of the line in GraphCoordinate.
* @param graphCoordinateB End Point of the line in GraphCoordinate.
* @param paint Colour the line is to coloured.
* @see GraphCoordinate
* @see Color
* @see Paint
*/
public void displayLine(GraphCoordinate graphCoordinateA, GraphCoordinate graphCoordinateB, Paint paint){
gc.setStroke(paint);
gc.setFill(paint);
gc.fillOval(graphCoordinateA.getX() - 3, graphCoordinateA.getY() - 3, 6, 6);
gc.fillOval(graphCoordinateB.getX() - 3, graphCoordinateB.getY() - 3, 6, 6);
gc.strokeLine(graphCoordinateA.getX(), graphCoordinateA.getY(), graphCoordinateB.getX(), graphCoordinateB.getY());
}
/**
* Display a point on the Canvas
* @param graphCoordinate Coordinate that the point is to be displayed at.
* @param paint Colour that the boat is to be coloured.
* @see GraphCoordinate
* @see Paint
* @see Color
*/
public void displayPoint(GraphCoordinate graphCoordinate, Paint paint){
gc.setFill(paint);
gc.fillOval(graphCoordinate.getX(), graphCoordinate.getY(), 10, 10);
}
/**
* Displays an arrow on the Canvas
* @param coordinate Coordinate that the arrow is to be displayed at.
* @param angle Angle that the arrow is to be facing in degrees 0 degrees = North (Up).
* @see GraphCoordinate
*/
public void displayArrow(GraphCoordinate coordinate, int angle){
gc.save();
rotate(angle, coordinate.getX(),coordinate.getY());
gc.setFill(Color.BLACK);
gc.fillPolygon(new double[]{coordinate.getX()-12, coordinate.getX()-6, coordinate.getX(), coordinate.getX()-4, coordinate.getX()-4, coordinate.getX()-8, coordinate.getX()-8},
new double[]{coordinate.getY()-5, coordinate.getY()-20, coordinate.getY()-5, coordinate.getY()-5, coordinate.getY()+20, coordinate.getY()+20, coordinate.getY()-5},
7);
gc.restore();
}
/**
* Rotates things on the canvas Note: this must be called in between gc.save() and gc.restore() else they will rotate everything
* @param angle Bearing angle to rotate at in degrees
* @param px Pivot point x of rotation.
* @param py Pivot point y of rotation.
*/
private void rotate(double angle, double px, double py) {
Rotate r = new Rotate(angle, px, py);
gc.setTransform(r.getMxx(), r.getMyx(), r.getMxy(), r.getMyy(), r.getTx(), r.getTy());
}
/**
* Display given name and speed of boat at a graph coordinate
* @param name name of the boat
* @param speed speed of the boat
* @param coordinate coordinate the text appears
*/
public void displayText(String name, double speed, GraphCoordinate coordinate){
String text = String.format("%s, %2$.2f knots", name, speed);
//System.out.println(text.length()*7);
long xCoord = coordinate.getX()+20;
long yCoord = coordinate.getY();
if (xCoord+(text.length()*7) >= getWidth()){
xCoord -= text.length()*7;
}
if (yCoord-(text.length()*2) <= 0){
yCoord += 30;
}
gc.fillText(text, xCoord, yCoord);
}
/**
* Draws the Race Map
*/
public void drawRaceMap() {
double width = getWidth();
double height = getHeight();
gc.clearRect(0, 0, width, height);
//System.out.println("Race Map Canvas Width: "+ width + ", Height:" + height);
this.map = new RaceMap(32.278, -64.863, 32.320989, -64.821, (int)width, (int)height);
if (map == null){
return;
}
//finish line
gc.setLineWidth(2);
GraphCoordinate finishLineCoord1 = this.map.convertGPS(Constants.finishLineMarker1);
GraphCoordinate finishLineCoord2 = this.map.convertGPS(Constants.finishLineMarker2);
displayLine(finishLineCoord1, finishLineCoord2, Color.DARKRED);
//marks
GraphCoordinate markCoord = this.map.convertGPS(Constants.mark1);
GraphCoordinate windwardGate1 = this.map.convertGPS(Constants.windwardGate1);
GraphCoordinate windwardGate2 = this.map.convertGPS(Constants.windwardGate2);
GraphCoordinate leewardGate1 = this.map.convertGPS(Constants.leewardGate1);
GraphCoordinate leewardGate2 = this.map.convertGPS(Constants.leewardGate2);
displayMark(markCoord, Color.GOLD);
displayLine(windwardGate1, windwardGate2, Color.DARKCYAN);
displayLine(leewardGate1, leewardGate2, Color.DARKVIOLET);
//start line
GraphCoordinate startline1 = this.map.convertGPS(Constants.startLineMarker1);
GraphCoordinate startline2 = this.map.convertGPS(Constants.startLineMarker2);
displayLine(startline1, startline2, Color.GREEN);
if (boats != null) {
for (BoatInRace boat : boats) {
if (boat != null) {
displayMark(this.map.convertGPS(boat.getCurrentPosition()), boat.getColour());
displayText(boat.getAbbrev(), boat.getVelocity(), this.map.convertGPS(boat.getCurrentPosition()));
}
}
}
//display wind direction arrow - specify origin point and angle
displayArrow(new GraphCoordinate(500, 20), 100);
}
public void updateBoats() {
if (boats != null) {
for (BoatInRace boat : boats) {
if (boat != null && !boat.getCurrentLeg().getName().equals("Finish")) {
GraphCoordinate wakeFrom = this.map.convertGPS(boat.getCurrentPosition());
GraphCoordinate wakeTo = this.map.convertGPS(boat.getWake());
displayLine(wakeFrom, wakeTo, boat.getColour());
}
}
}
}
/**
* Set the Canvas to resizable.
* @return That the Canvas is resizable.
*/
@Override
public boolean isResizable() {
return true;
}
/**
* Returns the preferred width of the Canvas
* @param width
* @return Returns the width of the Canvas
*/
@Override
public double prefWidth(double width) {
return getWidth();
}
/**
* Returns the preferred height of the Canvas
* @param height
* @return Returns the height of the Canvas
*/
@Override
public double prefHeight(double height) {
return getHeight();
}
}