package seng302.Model; import com.sun.xml.internal.bind.v2.runtime.reflect.opt.Const; 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.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){ gc.setFill(paint); gc.fillOval(graphCoordinate.getX(), graphCoordinate.getY(), 15, 15); } /** * 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.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 = name + ", " + speed + " knots"; gc.fillText(text, coordinate.getX()+20, coordinate.getY()); } /** * 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) { // System.out.print("Drawing Boat At: " + boat.getCurrentPosition()); 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); } /** * Draws a boat at a certain GPSCoordinate * @param colour Colour to colour boat. * @param gpsCoordinates GPScoordinate that the boat is to be drawn at. * @see GPSCoordinate * @see Color */ public void drawBoat(Color colour, GPSCoordinate gpsCoordinates) { GraphCoordinate graphCoordinate = this.map.convertGPS(gpsCoordinates); //System.out.println("DrawingBoat" + gpsCoordinates.getLongitude()); displayPoint(graphCoordinate, colour); } /** * 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(); } }