Implemented a factory class that creates mark arrows as needed. Needs to integrated with the real world data and tested to work. Works with all test data so far.

#implement #story[1118]
This commit is contained in:
cir27
2017-08-14 03:44:46 +12:00
parent 126d8ea870
commit a185c9dc96
3 changed files with 105 additions and 44 deletions
+12 -13
View File
@@ -6,6 +6,8 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import javafx.animation.AnimationTimer;
import javafx.application.Platform;
import javafx.collections.ObservableList;
@@ -27,11 +29,7 @@ import seng302.model.mark.CompoundMark;
import seng302.model.mark.Corner;
import seng302.model.mark.Mark;
import seng302.utilities.GeoUtility;
import seng302.visualiser.fxObjects.AnnotationBox;
import seng302.visualiser.fxObjects.BoatObject;
import seng302.visualiser.fxObjects.CourseBoundary;
import seng302.visualiser.fxObjects.Gate;
import seng302.visualiser.fxObjects.Marker;
import seng302.visualiser.fxObjects.*;
import seng302.visualiser.map.Boundary;
import seng302.visualiser.map.CanvasMap;
@@ -222,8 +220,8 @@ public class GameView extends Pane {
//Move the Markers to initial position.
markerObjects.forEach(((mark, marker) -> {
Point2D p2d = findScaledXY(mark.getLat(), mark.getLng());
marker.setCenterX(p2d.getX());
marker.setCenterY(p2d.getY());
marker.setLayoutX(p2d.getX());
marker.setLayoutY(p2d.getY());
}));
Platform.runLater(() -> {
markers.getChildren().clear();
@@ -240,11 +238,12 @@ public class GameView extends Pane {
*/
private void makeAndBindMarker(Mark observableMark, Paint colour) {
Marker marker = new Marker(colour);
marker.constructArrows(MarkArrowFactory.RoundingSide.PORT, ThreadLocalRandom.current().nextDouble(91, 180), ThreadLocalRandom.current().nextDouble(1, 90));
markerObjects.put(observableMark, marker);
observableMark.addPositionListener((mark, lat, lon) -> {
Point2D p2d = findScaledXY(lat, lon);
markerObjects.get(mark).setCenterX(p2d.getX());
markerObjects.get(mark).setCenterY(p2d.getY());
markerObjects.get(mark).setLayoutX(p2d.getX());
markerObjects.get(mark).setLayoutY(p2d.getY());
});
}
@@ -259,16 +258,16 @@ public class GameView extends Pane {
private Gate makeAndBindGate(Marker m1, Marker m2, Paint colour) {
Gate gate = new Gate(colour);
gate.startXProperty().bind(
m1.centerXProperty()
m1.layoutXProperty()
);
gate.startYProperty().bind(
m1.centerYProperty()
m1.layoutYProperty()
);
gate.endXProperty().bind(
m2.centerXProperty()
m2.layoutXProperty()
);
gate.endYProperty().bind(
m2.centerYProperty()
m2.layoutYProperty()
);
return gate;
}
@@ -1,56 +1,105 @@
package seng302.visualiser.fxObjects;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polyline;
import javafx.scene.shape.*;
import javafx.scene.transform.Rotate;
/**
* Created by cir27 on 9/08/17.
* Factory class for making rounding arrows for mark objects out of JavaFX objects.
*/
public class MarkArrowFactory {
public enum RoundingType {
/**
* The side of the boat that will be closest to the mark.
*/
public enum RoundingSide {
PORT,
STARBOARD,
}
public static Group constructEntryArrow (RoundingType roundingSide, double angleOfEntry,
double angleOfExit, Paint colour) {
public static final double MARK_ARROW_SEPARATION = 15;
public static final double ARROW_LENGTH = 75;
public static final double ARROW_HEAD_DEPTH = 10;
public static final double ARROW_HEAD_WIDTH = 6;
public static final double STROKE_WIDTH = 3;
/**
* Creates an entry arrow group showing an arrow into and out of the rounding area. It is centered on (0, 0).
* @param roundingSide The side of the boat that will be closest to the mark.
* @param angleOfEntry The angle between this mark and the last one as a heading from north in degrees.
* @param angleOfExit The angle between this mark and the next one as a heading from north in degrees.
* @param colour The desired colour of the arrows.
* @return The group containing all JavaFX objects.
*/
public static Group constructEntryArrow (RoundingSide roundingSide, double angleOfEntry,
double angleOfExit, Paint colour) {
Group arrow = new Group();
Group exitSection = constructExitArrow(roundingSide, angleOfExit, colour);
double minAngle = Math.min(angleOfEntry, angleOfExit);
double arcLen = Math.max(angleOfEntry, angleOfExit) - minAngle;
Arc roundSection = new Arc(
0, 0, MARK_ARROW_SEPARATION, MARK_ARROW_SEPARATION,
angleOfEntry, 180 - (angleOfEntry - angleOfExit)
);
roundSection.setStrokeWidth(STROKE_WIDTH);
roundSection.setType(ArcType.OPEN);
roundSection.setStroke(colour);
roundSection.setFill(new Color(0,0,0,0));
Polygon entrySection = constructLineSegment(
roundingSide == RoundingSide.PORT ? RoundingSide.STARBOARD : RoundingSide.PORT, angleOfEntry, colour
);
arrow.getChildren().addAll(exitSection, roundSection, entrySection);
return arrow;
}
public static Group constructExitArrow (RoundingType roundingSide, double angleOfEntry, Paint colour) {
/**
* Creates an exit arrow group pointing towards the next mark.
* @param roundingSide The side of the boat that will be closest to the mark.
* @param angle The angle to the next mark as a heading from north in degrees.
* @param colour The colour of the arrow.
* @return The group containing all the JavaFX objects.
*/
public static Group constructExitArrow (RoundingSide roundingSide, double angle, Paint colour) {
Group arrow = new Group();
Line arrowBody;
Polyline arrowHead = constructArrowHead();
if (roundingSide == RoundingType.PORT) {
arrowBody = new Line(
-10, -10,
-10, -30
);
arrowHead.setLayoutX(-10);
arrowHead.setLayoutY(-10);
} else {
arrowBody = new Line(
10, -10,
10, -30
);
arrowHead.setLayoutX(10);
arrowHead.setLayoutY(-10);
}
arrowBody.setFill(colour);
arrowHead.setFill(colour);
Polygon arrowBody = constructLineSegment(roundingSide, angle, colour);
Polyline arrowHead = constructArrowHead(angle, colour);
arrowHead.setLayoutX(arrowBody.getPoints().get(2));
arrowHead.setLayoutY(arrowBody.getPoints().get(3));
arrow.getChildren().addAll(arrowBody, arrowHead);
return arrow;
}
private static Polyline constructArrowHead () {
return new Polyline(
-5, -5,
0, 0,
5, -5
private static Polygon constructLineSegment (RoundingSide roundingSide, double angle, Paint colour) {
Polygon lineSegment;
angle = Math.toRadians(angle);
int multiplier = roundingSide == RoundingSide.PORT ? -1 : 1;
double xStart = multiplier * MARK_ARROW_SEPARATION * Math.sin(angle + Math.PI / 2);
double yStart = multiplier * MARK_ARROW_SEPARATION * Math.cos(angle + Math.PI / 2);
double xEnd = xStart + (ARROW_LENGTH * Math.sin(angle));
double yEnd = yStart + (ARROW_LENGTH * Math.cos(angle));
lineSegment = new Polygon(
xStart, yStart,
xEnd, yEnd
);
lineSegment.setStroke(colour);
lineSegment.setFill(Color.BLUE);
lineSegment.setStrokeWidth(STROKE_WIDTH);
lineSegment.setStrokeLineCap(StrokeLineCap.ROUND);
return lineSegment;
}
private static Polyline constructArrowHead (double rotation, Paint colour) {
Polyline arrow = new Polyline(
-ARROW_HEAD_WIDTH, -ARROW_HEAD_DEPTH,
0, 0,
ARROW_HEAD_WIDTH, -ARROW_HEAD_DEPTH
);
arrow.getTransforms().add(new Rotate(-rotation));
arrow.setStrokeLineCap(StrokeLineCap.ROUND);
arrow.setStroke(colour);
arrow.setStrokeWidth(STROKE_WIDTH);
return arrow;
}
}
@@ -2,6 +2,7 @@ package seng302.visualiser.fxObjects;
import javafx.application.Platform;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
@@ -11,18 +12,30 @@ import javafx.scene.shape.Circle;
public class Marker extends Group {
Circle mark = new Circle();
Paint colour = Color.BLACK;
Group enterArrow;
Group exitArrow;
public Marker() {
mark.setRadius(5);
mark.setCenterX(0);
mark.setCenterY(0);
Platform.runLater(() -> this.getChildren().add(mark));
}
public Marker(Paint colour) {
this();
this.colour = colour;
mark.setFill(colour);
}
public void constructArrows(MarkArrowFactory.RoundingSide roundingSide, double entryAngle, double exitAngle) {
enterArrow = MarkArrowFactory.constructEntryArrow(roundingSide, entryAngle, exitAngle, colour);
exitArrow = MarkArrowFactory.constructExitArrow(roundingSide, exitAngle, colour);
Platform.runLater(() -> this.getChildren().add(enterArrow));
// Platform.runLater(() -> this.getChildren().add(exitArrow));
}
public void showEnterArrow () {
Platform.runLater(() -> this.getChildren().setAll(enterArrow));
}