@ -1,107 +1,161 @@
package visualiser.model ;
import javafx.collections.ObservableList ;
import javafx.scene.Node ;
import javafx.scene.image.Image ;
import javafx.scene.paint.Color ;
import javafx.scene.paint.Paint ;
import javafx.scene.transform.Rotate ;
import seng302.Mock.StreamedCourse ;
import seng302.RaceDataSource ;
import seng302.RaceMap ;
import network.Messages.Enums.BoatStatusEnum ;
import shared.dataInput.RaceDataSource ;
import shared.model.GPSCoordinate ;
import shared.model.Mark ;
import shared.model.RaceClock ;
import java.time.Duration ;
import java.time.ZonedDateTime ;
import java.util.* ;
import java.util.List ;
/ * *
* This JavaFX Canvas is used to update and display details for a
* { @link seng302. RaceMap RaceMap} via the
* { @link seng302. Controllers . RaceController RaceController} . < br >
* { @link RaceMap} via the
* { @link visualiser. Controllers . RaceController} . < br >
* It fills it ' s parent and cannot be downsized . < br >
* Details displayed include :
* { @link seng302. Model . Boat Boats } ( and their
* { @link seng302. Model . TrackPoint TrackPoint} s ) ,
* { @link s eng302. Model . Marker Markers } , a
* { @link seng302. Model . RaceClock RaceClock} , a wind direction arrow and
* various user selected { @link seng302. Model . Annotations Annotations} .
* { @link VisualiserBoat} s ( and their
* { @link TrackPoint} s ) ,
* { @link s hared. model . Mark } s , a
* { @link RaceClock} , a wind direction arrow and
* various user selected { @link Annotations} .
* /
public class ResizableRaceCanvas extends ResizableCanvas {
/ * *
* The RaceMap used for converting GPSCoordinates to GraphCoordinates .
* /
private RaceMap map ;
private List < Boat > boats ;
private List < Marker > boatMarkers ;
/ * *
* The race we read data from and draw .
* /
private VisualiserRace visualiserRace ;
/ * *
* The background of the race .
* We render the background whenever the race boundary changes , or the screen size changes .
* /
private Image background ;
private boolean annoName = true ;
private boolean annoAbbrev = true ;
private boolean annoSpeed = true ;
private boolean annoPath = true ;
private boolean annoEstTime = true ;
private boolean annoTimeSinceLastMark = true ;
private List < Color > colours ;
private final List < Marker > markers ;
private final RaceDataSource raceData ;
private Map < Integer , Color > boatColours = new HashMap < > ( ) ;
/ * *
* The wind arrow node .
* /
private Node arrow ;
private RaceClock raceClock ;
public ResizableRaceCanvas ( RaceDataSource raceData ) {
/ * *
* Constructs a { @link ResizableRaceCanvas } using a given { @link VisualiserRace } .
* @param visualiserRace The race that data is read from in order to be drawn .
* @param arrow The wind arrow ' s node .
* /
public ResizableRaceCanvas ( VisualiserRace visualiserRace , Node arrow ) {
super ( ) ;
this . visualiserRace = visualiserRace ;
this . arrow = arrow ;
RaceDataSource raceData = visualiserRace . getRaceDataSource ( ) ;
double lat1 = raceData . getMapTopLeft ( ) . getLatitude ( ) ;
double long1 = raceData . getMapTopLeft ( ) . getLongitude ( ) ;
double lat2 = raceData . getMapBottomRight ( ) . getLatitude ( ) ;
double long2 = raceData . getMapBottomRight ( ) . getLongitude ( ) ;
setMap ( new RaceMap ( lat1 , long1 , lat2 , long2 , ( int ) getWidth ( ) , ( int ) getHeight ( ) ) ) ;
this . map = new RaceMap (
lat1 , long1 , lat2 , long2 ,
( int ) getWidth ( ) , ( int ) getHeight ( ) ) ;
this . markers = raceData . getMarkers ( ) ;
makeColours ( ) ;
this . raceData = raceData ;
}
/ * *
* Sets the boats that are to be displayed in this race .
*
* @param boats in race
* Toggle name display in annotation
* /
public void toggleAnnoName ( ) {
annoName = ! annoName ;
}
/ * *
* Toggle boat path display in annotation
* /
public void setBoats ( List < Boat > boats ) {
this . boats = boats ;
mapBoatColours ( ) ;
public void toggleBoatPath ( ) {
annoPath = ! annoPath ;
}
public void toggleAnnoEstTime ( ) {
annoEstTime = ! annoEstTime ;
}
/ * *
* Sets the boat markers that are to be displayed in this race .
*
* @param boatMarkers in race
* Toggle boat time display in annotation
* /
public void setBoatMarkers( ObservableList < Marker > boatMarkers ) {
this . boatMarkers = boatMarkers ;
public void toggleAnnoTime ( ) {
annoTimeSinceLastMark = ! annoTimeSinceLastMark ;
}
/ * *
* Sets the RaceMap that the RaceCanvas is to be displaying for .
*
* @param map race map
* Toggle abbreviation display in annotation
* /
p rivate void setMap ( RaceMap map ) {
this . map = map ;
public void toggleAnnoAbbrev ( ) {
annoAbbrev = ! annoAbbrev ;
}
private void displayBoat ( Boat boat , double angle , Color colour ) {
if ( boat . getCurrentPosition ( ) ! = null ) {
GraphCoordinate pos = this . map . convertGPS ( boat . getCurrentPosition ( ) ) ;
/ * *
* Toggle speed display in annotation
* /
public void toggleAnnoSpeed ( ) {
annoSpeed = ! annoSpeed ;
}
double [ ] x = { pos . getX ( ) - 6 , pos . getX ( ) , pos . getX ( ) + 6 } ;
double [ ] y = { pos . getY ( ) + 12 , pos . getY ( ) - 12 , pos . getY ( ) + 12 } ;
gc . setFill ( colour ) ;
gc . save ( ) ;
rotate ( angle , pos . getX ( ) , pos . getY ( ) ) ;
gc . fillPolygon ( x , y , 3 ) ;
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 degrees Bearing degrees to rotate .
* @param px Pivot point x of rotation .
* @param py Pivot point y of rotation .
* /
private void rotate ( double degrees , double px , double py ) {
Rotate r = new Rotate ( degrees , px , py ) ;
gc . setTransform ( r . getMxx ( ) , r . getMyx ( ) , r . getMxy ( ) , r . getMyy ( ) , r . getTx ( ) , r . getTy ( ) ) ;
}
/ * *
* 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 .
* /
private void drawCircle ( GraphCoordinate center , double diameter ) {
//The graphCoordinates are for the center of the point, so we offset them to get the corner coordinate.
gc . fillOval (
center . getX ( ) - ( diameter / 2 ) ,
center . getY ( ) - ( diameter / 2 ) ,
diameter , diameter ) ;
}
/ * *
@ -110,63 +164,48 @@ 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 .
* @see GraphCoordinate
* @see Color
* @see Paint
* /
private void displayLine ( GraphCoordinate graphCoordinateA , GraphCoordinate graphCoordinateB , Paint paint ) {
private void drawLine ( 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
* /
private void displayPoint ( GraphCoordinate graphCoordinate , Paint paint ) {
gc . setFill ( paint ) ;
gc . fillOval ( graphCoordinate . getX ( ) , graphCoordinate . getY ( ) , 10 , 10 ) ;
}
double endPointDiameter = 6 ;
/ * *
* Displays an arrow representing wind direction on the Canvas
*
* @param angle Angle that the arrow is to be facing in degrees 0 degrees = North ( Up ) .
* @see GraphCoordinate
* /
private void displayWindArrow ( double angle ) {
angle = angle % 360 ;
//Draw first end-point.
drawCircle ( graphCoordinateA , endPointDiameter ) ;
// show direction wind is coming from
if ( angle < 180 ) { angle = angle + 180 ; }
else { angle = angle - 180 ; }
//Draw second end-point.
drawCircle ( graphCoordinateB , endPointDiameter ) ;
//Draw line between them.
gc . strokeLine (
graphCoordinateA . getX ( ) ,
graphCoordinateA . getY ( ) ,
graphCoordinateB . getX ( ) ,
graphCoordinateB . getY ( ) ) ;
if ( arrow ! = null & & arrow . getRotate ( ) ! = angle ) {
arrow . setRotate ( angle ) ;
}
}
/ * *
* Rotates things on the canvas Note : this must be called in between gc . save ( ) and gc . restore ( ) else they will rotate everything
* Display a point on the Canvas . It has a diameter of 10 pixels .
*
* @param angle Bearing angle to rotate at in degrees
* @param px Pivot point x of rotation .
* @param py Pivot point y of rotation .
* @param graphCoordinate Coordinate that the point is to be displayed at .
* @param paint Paint to use for the point .
* /
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 ( ) ) ;
private void drawPoint ( GraphCoordinate graphCoordinate , Paint paint ) {
//Set paint.
gc . setFill ( paint ) ;
double pointDiameter = 10 ;
//Draw the point.
drawCircle ( graphCoordinate , pointDiameter ) ;
}
/ * *
* Display given name and speed of boat at a graph coordinate
*
@ -174,220 +213,348 @@ public class ResizableRaceCanvas extends ResizableCanvas {
* @param abbrev abbreviation of the boat name
* @param speed speed of the boat
* @param coordinate coordinate the text appears
* @param timeSinceLastMark time since the last mark was passed
* @param timeToNextMark The time until the boat reaches the next mark .
* @param timeSinceLastMark The time since the boat passed the last mark .
* /
private void displayText ( String name , String abbrev , double speed , GraphCoordinate coordinate , String estTime , ZonedDateTime timeSinceLastMark ) {
private void drawText ( String name , String abbrev , double speed , GraphCoordinate coordinate , String timeToNextMark , String timeSinceLastMark ) {
//The text to draw. Built during the function.
String text = "" ;
//Check name toggle value
if ( annoName ) {
//Draw name if annotation is enabled.
if ( annoName ) {
text + = String . format ( "%s " , name ) ;
}
//Check abbreviation toggle value
if ( annoAbbrev ) {
//Draw abbreviation/country if annotation is enabled.
if ( annoAbbrev ) {
text + = String . format ( "%s " , abbrev ) ;
}
//Check speed toggle value
//Draw speed if annotation is enabled.
if ( annoSpeed ) {
text + = String . format ( "%.2fkn " , speed ) ;
}
//Draw time to reach next mark if annotation is enabled.
if ( annoEstTime ) {
text + = estTime ;
text + = timeToNextMark ;
}
//Check time since last mark toggle value
if ( annoTimeSinceLastMark ) {
Duration timeSince = Duration . between ( timeSinceLastMark , raceClock . getTime ( ) ) ;
text + = String. format ( " %ds " , timeSince . getSeconds ( ) ) ;
//Draw time since last mark if annotation is enabled.
if ( annoTimeSinceLastMark ) {
text + = timeSinceLastMark ;
}
//String text = String.format("%s, %2$.2fkn", name, speed);
//Offset by 20 pixels horizontally.
long xCoord = coordinate . getX ( ) + 20 ;
long yCoord = coordinate . getY ( ) ;
//If the text would extend out of the canvas (to the right), move it left.
if ( xCoord + ( text . length ( ) * 7 ) > = getWidth ( ) ) {
xCoord - = text . length ( ) * 7 ;
}
if ( yCoord - ( text . length ( ) * 2 ) < = 0 ) {
yCoord + = 30 ;
}
//Draw text.
gc . fillText ( text , xCoord , yCoord ) ;
}
/ * *
* Draws race map with up to date data .
* Draws the label for a given boat . Includes name , abbreviation , speed , time since mark , and time to next mark .
* @param boat The boat to draw text for .
* /
public void update ( ) {
this . draw ( ) ;
this . updateBoats ( ) ;
private void drawBoatText ( VisualiserBoat boat ) {
drawText (
boat . getName ( ) ,
boat . getCountry ( ) ,
boat . getCurrentSpeed ( ) ,
this . map . convertGPS ( boat . getCurrentPosition ( ) ) ,
boat . getTimeToNextMarkFormatted ( this . visualiserRace . getRaceClock ( ) . getCurrentTime ( ) ) ,
boat . getTimeSinceLastMarkFormatted ( this . visualiserRace . getRaceClock ( ) . getCurrentTime ( ) ) ) ;
}
/ * *
* Draw race markers
* Draw s all of the boats on the canvas .
* /
private void drawMarkers ( ) {
for ( Marker marker : markers ) {
GraphCoordinate mark1 = this . map . convertGPS ( marker . getMark1 ( ) ) ;
// removed drawing of lines between the marks as only
// the start and finish line should have a line drawn
if ( marker . isCompoundMark ( ) ) {
GraphCoordinate mark2 = this . map . convertGPS ( marker . getMark2 ( ) ) ;
displayPoint ( mark1 , Color . LIMEGREEN ) ;
displayPoint ( mark2 , Color . LIMEGREEN ) ;
} else {
displayPoint ( mark1 , Color . GREEN ) ;
private void drawBoats ( ) {
for ( VisualiserBoat boat : visualiserRace . getBoats ( ) ) {
//Draw the boat.
drawBoat ( boat ) ;
//Only draw wake if they are currently racing.
if ( boat . getStatus ( ) = = BoatStatusEnum . RACING ) {
drawWake ( 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 . getRaceClock ( ) . getCurrentTime ( ) ) ;
}
//Draw boat label.
drawBoatText ( boat ) ;
//Draw track.
drawTrack ( boat ) ;
}
}
/ * *
* Draws the Race Map
* Draws a given boat on the canvas .
* @param boat The boat to draw .
* /
public void draw ( ) {
private void drawBoat ( VisualiserBoat boat ) {
//The position may be null if we haven't received any BoatLocation messages yet.
if ( boat . getCurrentPosition ( ) ! = null ) {
double width = getWidth ( ) ;
double height = getHeight ( ) ;
//Convert position to graph coordinate.
GraphCoordinate pos = this . map . convertGPS ( boat . getCurrentPosition ( ) ) ;
gc . clearRect ( 0 , 0 , width , height ) ;
//The x coordinates of each vertex of the boat.
double [ ] x = {
pos . getX ( ) - 6 ,
pos . getX ( ) ,
pos . getX ( ) + 6 } ;
if ( map = = null ) {
return ; //TODO this should return a exception in the future
}
this . map . setHeight ( ( int ) height ) ;
this . map . setWidth ( ( int ) width ) ;
//The y coordinates of each vertex of the boat.
double [ ] y = {
pos . getY ( ) + 12 ,
pos . getY ( ) - 12 ,
pos . getY ( ) + 12 } ;
gc . setLineWidth ( 2 ) ;
updateBoats ( ) ;
drawMarkers ( ) ;
//The above shape is essentially a triangle 12px wide, and 24px long.
//Draw the boat.
gc . setFill ( boat . getColor ( ) ) ;
gc . save ( ) ;
rotate ( boat . getBearing ( ) . degrees ( ) , pos . getX ( ) , pos . getY ( ) ) ;
gc . fillPolygon ( x , y , 3 ) ;
gc . restore ( ) ;
//display wind direction arrow - specify origin point and angle - angle now set to random angle
if ( raceData instanceof StreamedCourse ) {
displayWindArrow ( ( ( StreamedCourse ) raceData ) . getWindDirection ( ) ) ;
} else {
displayWindArrow ( 150 ) ;
}
}
/ * *
* Toggle name display in annotation
* Draws the wake for a given boat .
* @param boat Boat to draw wake for .
* /
public void toggleAnnoName ( ) {
annoName = ! annoName ;
private void drawWake ( VisualiserBoat boat ) {
//Calculate either end of wake line.
GraphCoordinate wakeFrom = this . map . convertGPS ( boat . getCurrentPosition ( ) ) ;
GraphCoordinate wakeTo = this . map . convertGPS ( boat . getWake ( ) ) ;
//Draw.
drawLine ( wakeFrom , wakeTo , boat . getColor ( ) ) ;
}
/ * *
* Toggle boat path display in annotation
* Displays an arrow representing wind direction on the Canvas .
* This function accepts a wind - to bearing , but displays a wind - from bearing .
*
* @param angle Angle that the arrow is to be facing in degrees 0 degrees = North ( Up ) .
* @see GraphCoordinate
* /
public void toggleBoatPath ( ) {
annoPath = ! annoPath ;
private void displayWindArrow ( double angle ) {
//We need to display wind-from, so add 180 degrees.
angle + = 180 d ;
//Get it within [0, 360).
while ( angle > = 360 d ) {
angle - = 360 d ;
}
public void toggleAnnoEstTime ( ) {
annoEstTime = ! annoEstTime ;
//Rotate the wind arrow.
if ( arrow ! = null & & arrow . getRotate ( ) ! = angle ) {
arrow . setRotate ( angle ) ;
}
}
/ * *
* Toggle boat time display in annotation
* Draws all of the { @link Mark } s on the canvas .
* /
public void toggleAnnoTime ( ) { annoTimeSinceLastMark = ! annoTimeSinceLastMark ; }
private void drawMarks ( ) {
for ( Mark mark : this . visualiserRace . getMarks ( ) ) {
drawMark ( mark ) ;
}
}
/ * *
* Toggle abbreviation display in annotation
* Draws a given mark on the canvas .
* @param mark The mark to draw .
* /
public void toggleAnnoAbbrev ( ) {
annoAbbrev = ! annoAbbrev ;
private void drawMark ( Mark mark ) {
//Calculate screen position.
GraphCoordinate mark1 = this . map . convertGPS ( mark . getPosition ( ) ) ;
//Draw.
drawPoint ( mark1 , Color . LIMEGREEN ) ;
}
/ * *
* Toggle speed display in annotation
* Draws the Race Map .
* Called when the canvas is resized .
* /
public void toggleAnnoSpeed ( ) {
annoSpeed = ! annoSpeed ;
public void draw ( ) {
//Clear canvas.
clear ( ) ;
//Update our RaceMap using new canvas size.
this . map . setWidth ( ( int ) getWidth ( ) ) ;
this . map . setHeight ( ( int ) getHeight ( ) ) ;
//Redraw the boundary.
redrawBoundaryImage ( ) ;
//Draw the race.
drawRace ( ) ;
}
/ * *
* Draws boats while race in progress , when leg heading is set .
* Clears the canvas .
* /
private void updateBoats ( ) {
if ( boats ! = null ) {
if ( boatColours . size ( ) < boats . size ( ) ) mapBoatColours ( ) ;
for ( Boat boat : boats ) {
boolean finished = boat . getCurrentLeg ( ) . getName ( ) . equals ( "Finish" ) | | boat . getCurrentLeg ( ) . getName ( ) . equals ( "DNF" ) ;
boolean isStart = boat . isStarted ( ) ;
int sourceID = boat . getSourceID ( ) ;
if ( ! finished & & isStart ) {
displayBoat ( boat , boat . getHeading ( ) , boatColours . get ( sourceID ) ) ;
GraphCoordinate wakeFrom = this . map . convertGPS ( boat . getCurrentPosition ( ) ) ;
GraphCoordinate wakeTo = this . map . convertGPS ( boat . getWake ( ) ) ;
displayLine ( wakeFrom , wakeTo , boatColours . get ( sourceID ) ) ;
} else if ( ! isStart ) {
displayBoat ( boat , boat . getHeading ( ) , boatColours . get ( sourceID ) ) ;
} else {
displayBoat ( boat , 0 , boatColours . get ( sourceID ) ) ;
private void clear ( ) {
gc . clearRect ( 0 , 0 , getWidth ( ) , getHeight ( ) ) ;
}
if ( Duration . between ( boat . getTimeSinceLastMark ( ) , raceClock . getTime ( ) ) . getSeconds ( ) < 0 ) {
boat . setTimeSinceLastMark ( raceClock . getTime ( ) ) ;
}
//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 . isStarted ( ) = = false ) {
boat . setTimeSinceLastMark ( raceClock . getTime ( ) ) ;
/ * *
* Draws the race boundary , and saves the image to { @link # background } .
* You should call { @link # clear ( ) } before calling this .
* /
private void redrawBoundaryImage ( ) {
//Prepare to draw.
gc . setLineWidth ( 1 ) ;
gc . setFill ( Color . AQUA ) ;
//Calculate the screen coordinates of the boundary.
List < GPSCoordinate > boundary = this . visualiserRace . getBoundary ( ) ;
double [ ] xpoints = new double [ boundary . size ( ) ] ;
double [ ] ypoints = new double [ boundary . size ( ) ] ;
//For each boundary coordinate.
for ( int i = 0 ; i < boundary . size ( ) ; i + + ) {
//Convert.
GraphCoordinate coord = map . convertGPS ( boundary . get ( i ) ) ;
//Use.
xpoints [ i ] = coord . getX ( ) ;
ypoints [ i ] = coord . getY ( ) ;
}
displayText ( boat . toString ( ) , boat . getAbbrev ( ) , boat . getVelocity ( ) , this . map . convertGPS ( boat . getCurrentPosition ( ) ) , boat . getFormattedEstTime ( ) , boat . getTimeSinceLastMark ( ) ) ;
//TODO this needs to be fixed.
drawTrack ( boat , boatColours . get ( sourceID ) ) ;
//Draw the boundary.
gc . fillPolygon ( xpoints , ypoints , xpoints . length ) ;
//Render boundary to image.
this . background = snapshot ( null , null ) ;
}
/ * *
* Draws the race .
* Called once per frame , and on canvas resize .
* /
public void drawRace ( ) {
gc . setLineWidth ( 2 ) ;
clear ( ) ;
//Race boundary.
drawBoundary ( ) ;
//Boats.
drawBoats ( ) ;
//Marks.
drawMarks ( ) ;
//Wind arrow. This rotates the wind arrow node.
displayWindArrow ( this . visualiserRace . getWindDirection ( ) . degrees ( ) ) ;
}
/ * *
* Draws the race boundary image onto the canvas .
* See { @link # background } .
* /
private void drawBoundary ( ) {
gc . drawImage ( this . background , 0 , 0 ) ;
}
/ * *
* Draws all track points for a given boat . Colour is set by boat , opacity by track point .
* @param boat whose track is displayed
* @param colour The color to use for the track .
* @see seng302 . Model . TrackPoint
* This checks if { @link # annoPath } is enabled .
* @param boat The boat to draw tracks for .
* @see TrackPoint
* /
private void drawTrack ( Boat boat , Color colour ) {
if ( annoPath ) {
private void drawTrack ( VisualiserBoat boat ) {
//Check that track points are enabled.
if ( this . annoPath ) {
//Apply the boat color.
gc . setFill ( boat . getColor ( ) ) ;
//Draw each TrackPoint.
for ( TrackPoint point : boat . getTrack ( ) ) {
//Convert the GPSCoordinate to a screen coordinate.
GraphCoordinate scaledCoordinate = this . map . convertGPS ( point . getCoordinate ( ) ) ;
gc . setFill ( new Color ( colour . getRed ( ) , colour . getGreen ( ) , colour . getBlue ( ) , point . getAlpha ( ) ) ) ;
gc . fillOval ( scaledCoordinate . getX ( ) , scaledCoordinate . getY ( ) , 5 , 5 ) ;
}
//Draw a circle for the trackpoint.
gc . fillOval ( scaledCoordinate . getX ( ) , scaledCoordinate . getY ( ) , point . getDiameter ( ) , point . getDiameter ( ) ) ;
}
}
/ * *
* makes colours
* /
private void makeColours ( ) {
colours = new ArrayList < > ( Arrays . asList (
Color . BLUEVIOLET ,
Color . BLACK ,
Color . RED ,
Color . ORANGE ,
Color . DARKOLIVEGREEN ,
Color . LIMEGREEN ,
Color . PURPLE ,
Color . DARKGRAY ,
Color . YELLOW
) ) ;
}
public void setArrow ( Node arrow ) {
this . arrow = arrow ;
}
public void setRaceClock ( RaceClock raceClock ) {
this . raceClock = raceClock ;
}
private void mapBoatColours ( ) {
int currentColour = 0 ;
for ( Boat boat : boats ) {
if ( ! boatColours . containsKey ( boat . getSourceID ( ) ) ) {
boatColours . put ( boat . getSourceID ( ) , colours . get ( currentColour ) ) ;
}
currentColour = ( currentColour + 1 ) % colours . size ( ) ;
}
}
}