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.

99 lines
3.4 KiB

package visualiser.Controllers;
import javafx.application.Platform;
import javafx.beans.property.Property;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import shared.model.Bearing;
import shared.model.Wind;
/**
* Controller for the wind direction arrow on the race screen.
*/
public class ArrowController {
private @FXML StackPane arrowStackPane;
private @FXML ImageView arrowImage;
private @FXML Label speedLabel;
private final static Integer MIN_KNOTS = 2; // knots for min_height
private final static Integer MAX_KNOTS = 30; // knots for max_height
private final static Integer MIN_HEIGHT = 25; // min arrow height
private final static Integer MAX_HEIGHT = 75; // max arrow height
/**
* Sets which wind property the arrow control should bind to.
* @param wind The wind property to bind to.
*/
public void setWindProperty(Property<Wind> wind) {
wind.addListener((observable, oldValue, newValue) -> {
if (newValue != null) {
Platform.runLater(() -> updateWind(newValue));
}
});
}
/**
* Updates the control to use the new wind value.
* This updates the arrow direction (due to bearing), arrow length (due to speed), and label (due to speed).
* @param wind The wind value to use.
*/
private void updateWind(Wind wind) {
updateWindBearing(wind.getWindDirection());
updateWindSpeed(wind.getWindSpeed());
}
/**
* Updates the control to account for the new wind speed.
* This changes the length (height) of the wind arrow, and updates the speed label.
* @param speedKnots The new wind speed, in knots.
*/
private void updateWindSpeed(double speedKnots) {
updateWindArrowLength(speedKnots);
updateWindSpeedLabel(speedKnots);
}
/**
* Updates the length of the wind arrow according to the specified wind speed.
* @param speedKnots Wind speed, in knots.
*/
private void updateWindArrowLength(double speedKnots) {
double deltaKnots = MAX_KNOTS - MIN_KNOTS;
double deltaHeight = MAX_HEIGHT - MIN_HEIGHT;
//Clamp speed.
if (speedKnots > MAX_KNOTS) {
speedKnots = MAX_KNOTS;
} else if (speedKnots < MIN_KNOTS) {
speedKnots = MIN_KNOTS;
}
//How far between the knots bounds is the current speed?
double currentDeltaKnots = speedKnots - MIN_KNOTS;
double currentKnotsScalar = currentDeltaKnots / deltaKnots;
//Thus, how far between the pixel height bounds should the arrow height be?
double newHeight = MIN_HEIGHT + (currentKnotsScalar * deltaHeight);
arrowImage.setFitHeight(newHeight);
}
/**
* Updates the wind speed label according to the specified wind speed.
* @param speedKnots Wind speed, in knots.
*/
private void updateWindSpeedLabel(double speedKnots) {
speedLabel.setText(String.format("%.1fkn", speedKnots));
}
/**
* Updates the control to account for a new wind bearing.
* This rotates the arrow according to the bearing.
* @param bearing The bearing to use to rotate arrow.
*/
private void updateWindBearing(Bearing bearing) {
//Rotate the wind arrow.
arrowStackPane.setRotate(bearing.degrees());
}
}