@ -4,6 +4,7 @@ package visualiser.model;
import javafx.scene.paint.Color ;
import javafx.scene.paint.LinearGradient ;
import javafx.scene.paint.Paint ;
import javafx.scene.text.Font ;
import javafx.scene.transform.Rotate ;
import network.Messages.Enums.BoatStatusEnum ;
import shared.dataInput.RaceDataSource ;
@ -12,6 +13,7 @@ import shared.model.*;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Comparator ;
import java.util.List ;
/ * *
@ -141,8 +143,14 @@ public class ResizableRaceCanvas extends ResizableCanvas {
* Draws a circle with a given diameter , centred on a given graph coordinate .
* @param center The center coordinate of the circle .
* @param diameter The diameter of the circle .
* @param paint The paint to use for the circle .
* /
private void drawCircle ( GraphCoordinate center , double diameter ) {
private void drawCircle ( GraphCoordinate center , double diameter , Paint paint ) {
gc . save ( ) ;
gc . setFill ( paint ) ;
gc . setStroke ( paint ) ;
//The graphCoordinates are for the center of the point, so we offset them to get the corner coordinate.
gc . fillOval (
@ -150,6 +158,7 @@ public class ResizableRaceCanvas extends ResizableCanvas {
center . getY ( ) - ( diameter / 2 ) ,
diameter , diameter ) ;
gc . restore ( ) ;
}
/ * *
@ -158,20 +167,16 @@ public class ResizableRaceCanvas extends ResizableCanvas {
* @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 .
* @param lineWidth The width of the line .
* /
private void drawLine ( GraphCoordinate graphCoordinateA , GraphCoordinate graphCoordinateB , Paint paint ) {
private void drawLine ( GraphCoordinate graphCoordinateA , GraphCoordinate graphCoordinateB , Paint paint , double lineWidth ) {
gc . save ( ) ;
gc . setStroke ( paint ) ;
gc . setFill ( paint ) ;
double endPointDiameter = 6 ;
//Draw first end-point.
drawCircle ( graphCoordinateA , endPointDiameter ) ;
//Draw second end-point.
drawCircle ( graphCoordinateB , endPointDiameter ) ;
gc . setLineWidth ( lineWidth ) ;
//Draw line between them.
gc . strokeLine (
@ -180,25 +185,10 @@ public class ResizableRaceCanvas extends ResizableCanvas {
graphCoordinateB . getX ( ) ,
graphCoordinateB . getY ( ) ) ;
gc . restore ( ) ;
}
/ * *
* Display a point on the Canvas . It has a diameter of 10 pixels .
*
* @param graphCoordinate Coordinate that the point is to be displayed at .
* @param paint Paint to use for the point .
* /
private void drawPoint ( GraphCoordinate graphCoordinate , Paint paint ) {
//Set paint.
gc . setFill ( paint ) ;
double pointDiameter = 10 ;
//Draw the point.
drawCircle ( graphCoordinate , pointDiameter ) ;
}
/ * *
@ -210,8 +200,10 @@ public class ResizableRaceCanvas extends ResizableCanvas {
* @param coordinate coordinate the text appears
* @param timeToNextMark The time until the boat reaches the next mark .
* @param timeSinceLastMark The time since the boat passed the last mark .
* @param paint The color of the text .
* @param fontSize The size of the font .
* /
private void drawText ( String name , String abbrev , double speed , GraphCoordinate coordinate , String timeToNextMark , String timeSinceLastMark ) {
private void drawText ( String name , String abbrev , double speed , GraphCoordinate coordinate , String timeToNextMark , String timeSinceLastMark , Paint paint , double fontSize ) {
//The text to draw. Built during the function.
String text = "" ;
@ -257,8 +249,15 @@ public class ResizableRaceCanvas extends ResizableCanvas {
yCoord + = 30 ;
}
gc . save ( ) ;
gc . setStroke ( paint ) ;
gc . setFont ( new Font ( gc . getFont ( ) . getName ( ) , fontSize ) ) ;
//Draw text.
gc . fillText ( text , xCoord , yCoord ) ;
gc . restore ( ) ;
}
@ -274,7 +273,9 @@ public class ResizableRaceCanvas extends ResizableCanvas {
boat . getCurrentSpeed ( ) ,
this . map . convertGPS ( boat . getCurrentPosition ( ) ) ,
boat . getTimeToNextMarkFormatted ( this . visualiserRace . getVisualiserRaceState ( ) . getRaceClock ( ) . getCurrentTime ( ) ) ,
boat . getTimeSinceLastMarkFormatted ( this . visualiserRace . getVisualiserRaceState ( ) . getRaceClock ( ) . getCurrentTime ( ) ) ) ;
boat . getTimeSinceLastMarkFormatted ( this . visualiserRace . getVisualiserRaceState ( ) . getRaceClock ( ) . getCurrentTime ( ) ) ,
Color . BLACK ,
20 ) ;
}
@ -286,29 +287,51 @@ public class ResizableRaceCanvas extends ResizableCanvas {
* /
private void drawBoats ( ) {
for ( VisualiserBoat boat : new ArrayList < > ( visualiserRace . getVisualiserRaceState ( ) . getBoats ( ) ) ) {
List < VisualiserBoat > boats = new ArrayList < > ( visualiserRace . getVisualiserRaceState ( ) . getBoats ( ) ) ;
//Sort to ensure we draw boats in consistent order.
boats . sort ( Comparator . comparingInt ( Boat : : getSourceID ) ) ;
//Draw the boat.
drawBoat ( boat ) ;
//Current draw order:
// track points
// wake
// boat
// text
//Track points.
for ( VisualiserBoat boat : boats ) {
drawTrack ( boat ) ;
}
//Wake.
for ( VisualiserBoat boat : boats ) {
//Only draw wake if they are currently racing.
if ( boat . getStatus ( ) = = BoatStatusEnum . RACING ) {
drawWake ( boat ) ;
}
}
//Boat.
for ( VisualiserBoat boat : boats ) {
drawBoat ( boat ) ;
}
//Text.
for ( VisualiserBoat boat : boats ) {
drawBoatText ( boat ) ;
}
/ *
//If the race hasn't started, we set the time since last mark to the current time, to ensure we don't start counting until the race actually starts.
if ( ( boat . getStatus ( ) ! = BoatStatusEnum . RACING ) & & ( boat . getStatus ( ) = = BoatStatusEnum . FINISHED ) ) {
boat . setTimeAtLastMark ( visualiserRace . getVisualiserRaceState ( ) . getRaceClock ( ) . getCurrentTime ( ) ) ;
}
* /
//Draw boat label.
drawBoatText ( boat ) ;
//Draw track.
drawTrack ( boat ) ;
}
}
@ -341,12 +364,14 @@ public class ResizableRaceCanvas extends ResizableCanvas {
//The above shape is essentially a triangle 12px wide, and 24px long.
gc . save ( ) ;
//Draw the boat.
gc . setFill ( boat . getColor ( ) ) ;
gc . save ( ) ;
rotate ( boat . getBearing ( ) . degrees ( ) , pos . getX ( ) , pos . getY ( ) ) ;
gc . fillPolygon ( x , y , 3 ) ;
gc . fillPolygon ( x , y , x . length ) ;
gc . restore ( ) ;
@ -375,12 +400,14 @@ public class ResizableRaceCanvas extends ResizableCanvas {
//The above shape is essentially a triangle 24px wide, and 48 long.
gc . save ( ) ;
//Draw the boat.
gc . setFill ( Color . BLACK ) ;
gc . save ( ) ;
rotate ( boat . getBearing ( ) . degrees ( ) , pos . getX ( ) , pos . getY ( ) ) ;
gc . fillPolygon ( x , y , 3 ) ;
gc . fillPolygon ( x , y , x . length ) ;
gc . restore ( ) ;
}
@ -396,8 +423,15 @@ public class ResizableRaceCanvas extends ResizableCanvas {
GraphCoordinate wakeFrom = this . map . convertGPS ( boat . getCurrentPosition ( ) ) ;
GraphCoordinate wakeTo = this . map . convertGPS ( boat . getWake ( ) ) ;
//Draw.
drawLine ( wakeFrom , wakeTo , boat . getColor ( ) ) ;
double lineWidth = 4 ;
double endPointDiameter = 12 ;
//Line.
drawLine ( wakeFrom , wakeTo , boat . getColor ( ) , lineWidth ) ;
//Draw end-point.
drawCircle ( wakeTo , endPointDiameter , Color . BLACK ) ;
}
@ -423,8 +457,10 @@ public class ResizableRaceCanvas extends ResizableCanvas {
//Calculate screen position.
GraphCoordinate mark1 = this . map . convertGPS ( mark . getPosition ( ) ) ;
double diameter = 10 ;
//Draw.
drawPoint ( mark1 , Color . LIMEGREEN ) ;
draw Circle( mark1 , diameter , Color . LIMEGREEN ) ;
}
@ -462,6 +498,8 @@ public class ResizableRaceCanvas extends ResizableCanvas {
* /
private void drawBoundary ( ) {
gc . save ( ) ;
//Prepare to draw.
gc . setLineWidth ( 1 ) ;
gc . setFill ( Color . AQUA ) ;
@ -484,6 +522,8 @@ public class ResizableRaceCanvas extends ResizableCanvas {
//Draw the boundary.
gc . fillPolygon ( xpoints , ypoints , xpoints . length ) ;
gc . restore ( ) ;
}
/ * *
@ -496,7 +536,6 @@ public class ResizableRaceCanvas extends ResizableCanvas {
this . map . setGPSTopLeft ( visualiserRace . getVisualiserRaceState ( ) . getRaceDataSource ( ) . getMapTopLeft ( ) ) ;
this . map . setGPSBotRight ( visualiserRace . getVisualiserRaceState ( ) . getRaceDataSource ( ) . getMapBottomRight ( ) ) ;
gc . setLineWidth ( 2 ) ;
clear ( ) ;
@ -604,6 +643,8 @@ public class ResizableRaceCanvas extends ResizableCanvas {
GraphCoordinate c1 = this . map . convertGPS ( controlPoint ) ;
GraphCoordinate c2 = this . map . convertGPS ( controlPoint2 ) ;
gc . save ( ) ;
gc . setLineWidth ( 2 ) ;
gc . setStroke ( Color . MEDIUMAQUAMARINE ) ;
@ -614,20 +655,26 @@ public class ResizableRaceCanvas extends ResizableCanvas {
gc . bezierCurveTo ( c1 . getX ( ) , c1 . getY ( ) , c2 . getX ( ) , c2 . getY ( ) , curvePointEnd . getX ( ) , curvePointEnd . getY ( ) ) ;
gc . stroke ( ) ;
gc . closePath ( ) ;
gc . save ( ) ;
//gc.save();
gc . restore ( ) ;
return pointToEndCurve ;
} else { //last leg so no curve
GraphCoordinate startPath = this . map . convertGPS ( legStartPoint ) ;
GraphCoordinate endPath = this . map . convertGPS ( legs . get ( index ) . getEndCompoundMark ( ) . getAverageGPSCoordinate ( ) ) ;
gc . save ( ) ;
gc . beginPath ( ) ;
gc . moveTo ( startPath . getX ( ) , startPath . getY ( ) ) ;
gc . lineTo ( endPath . getX ( ) , endPath . getY ( ) ) ;
gc . stroke ( ) ;
gc . closePath ( ) ;
gc . save ( ) ;
//gc.save();
drawArrowHead ( legStartPoint , legs . get ( index ) . getEndCompoundMark ( ) . getAverageGPSCoordinate ( ) ) ;
gc . restore ( ) ;
return null ;
}
}
@ -664,15 +711,22 @@ public class ResizableRaceCanvas extends ResizableCanvas {
//Check that track points are enabled.
if ( this . annoPath ) {
gc . save ( ) ;
gc . setLineWidth ( 3 ) ;
//Apply the boat color.
gc . setFill ( boat . getColor ( ) ) ;
gc . setStroke ( boat . getColor ( ) ) ;
double [ ] xPoints = new double [ boat . getTrack ( ) . size ( ) ] ;
double [ ] yPoints = new double [ boat . getTrack ( ) . size ( ) ] ;
List < TrackPoint > trackPoints = new ArrayList < > ( boat . getTrack ( ) ) ;
double [ ] xPoints = new double [ trackPoints . size ( ) ] ;
double [ ] yPoints = new double [ trackPoints . size ( ) ] ;
int index = 0 ;
//Copy trackpoint locations to x/y arrays.
for ( TrackPoint point : new ArrayList < > ( boat . getTrack ( ) ) ) {
for ( TrackPoint point : trackPoints ) {
//Convert the GPSCoordinate to a screen coordinate.
GraphCoordinate scaledCoordinate = this . map . convertGPS ( point . getCoordinate ( ) ) ;
@ -684,6 +738,8 @@ public class ResizableRaceCanvas extends ResizableCanvas {
}
gc . strokePolyline ( xPoints , yPoints , xPoints . length ) ;
gc . restore ( ) ;
}
}