Mark drawing moved to MarkGroup class. RaceObject and it's sub classes now describe

all functionality required for a on screen object. Improved wakes. Branch currently
untested.

#story[812, 820] #refactor #implement.
This commit is contained in:
cir27
2017-04-27 02:44:25 +12:00
parent eaff4c5aac
commit 245bd184b4
7 changed files with 392 additions and 259 deletions
@@ -6,6 +6,7 @@ import javafx.fxml.FXML;
import javafx.geometry.Point2D;
import javafx.geometry.Point3D;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.AnchorPane;
@@ -15,10 +16,8 @@ import javafx.util.Pair;
import seng302.models.Boat;
import seng302.models.BoatGroup;
import seng302.models.Colors;
import seng302.models.mark.GateMark;
import seng302.models.mark.Mark;
import seng302.models.mark.MarkType;
import seng302.models.mark.SingleMark;
import seng302.models.RaceObject;
import seng302.models.mark.*;
import seng302.models.parsers.StreamParser;
import seng302.models.parsers.StreamReceiver;
@@ -59,6 +58,7 @@ public class CanvasController {
private double referencePointX;
private double referencePointY;
private double metersToPixels;
private List<RaceObject> raceObjects = new ArrayList<>();
public AnimationTimer timer;
@@ -154,39 +154,51 @@ public class CanvasController {
Mark nextMark;
//if (countdown == 0) {
for (BoatGroup boatGroup : boatGroups) {
for (RaceObject raceObject : raceObjects) {
//if (currentRaceMarker[boatIndex] < marks.size()) {
//if (currentRaceMarker[boatIndex] == 6) {
// int debugLine = 4;
//}
double xb4 = boatGroup.getLayoutX();
double yb4 = boatGroup.getLayoutY();
nextMark = marks.get(currentRaceMarker[boatIndex]);
//double xb4 = boatGroup.getLayoutX();
//double yb4 = boatGroup.getLayoutY();
//nextMark = marks.get(currentRaceMarker[boatIndex]);
//descending = nextMark.getY() > boatGroup.getLayoutY();
//leftToRight = nextMark.getX() < boatGroup.getLayoutX();
boatGroup.updatePosition(1000 / 60);
Point3D p = StreamParser.boatPositions.get((long)boatGroup.getBoat().getId());
//System.out.println("boatGroup = " + boatGroup.getBoat().getId());
//System.out.println("StreamParser.boatPositions.toString() = " + StreamParser.boatPositions.toString());
if (p != null) {
raceObject.updatePosition(1000 / 60);
for (int id : raceObject.getRaceIds()) {
if (StreamParser.boatPositions.containsKey(id)) {
Point3D p = StreamParser.boatPositions.get((long) id);
Point2D p2d = latLonToXY(p.getX(), p.getY());
//System.out.println("p2d = " + p2d);
if (!boatGroup.isSamePos(p2d)) {
//System.out.println("p.toString() = " + p.toString());
double heading = 360.0 / 0xffff * p.getZ();
//System.out.println("heading = " + heading);
boatGroup.setDestination(p2d.getX(), p2d.getY(), heading);
raceObject.setDestination(p2d.getX(), p2d.getY(), heading, id);
}
StreamParser.boatPositions.remove((long) id);
}
//Point3D p = StreamParser.boatPositions.get((long) raceObject.getRaceIds()[0]);
//System.out.println("boatGroup = " + boatGroup.getBoat().getId());
//System.out.println("StreamParser.boatPositions.toString() = " + StreamParser.boatPositions.toString());
// if (p != null) {
// Point2D p2d = latLonToXY(p.getX(), p.getY());
// //System.out.println("p2d = " + p2d);
// if (!boatGroup.isSamePos(p2d)) {
// //System.out.println("p.toString() = " + p.toString());
// double heading = 360.0 / 0xffff * p.getZ();
// //System.out.println("heading = " + heading);
//
//
//
// boatGroup.setDestination(p2d.getX(), p2d.getY(), heading, boatGroup.getRaceIds()[0]);
//boatGroup.setDestination(p2d.getX(), p2d.getY());
}
}
// }
//}
// if (descending && nextMark.getY() < boatGroup.getLayoutY()) {
// currentRaceMarker[boatIndex]++;
@@ -208,14 +220,14 @@ public class CanvasController {
// boatGroup.setDestination(
// marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY()
// );
// }
double xnew = boatGroup.getLayoutX();
double ynew = boatGroup.getLayoutY();
double dx = xnew - xb4;
double dy = ynew -yb4;
raceFinished = false;
boatIndex++;
// double xnew = boatGroup.getLayoutX();
// double ynew = boatGroup.getLayoutY();
// double dx = xnew - xb4;
// double dy = ynew -yb4;
// raceFinished = false;
// boatIndex++;
}
//}
//if (raceFinished) {
@@ -280,11 +292,10 @@ public class CanvasController {
private void drawBoats() {
// Map<Boat, TimelineInfo> timelineInfos = raceViewController.getTimelineInfos();
List<Boat> boats = raceViewController.getStartingBoats();
List<Mark> marks = raceViewController.getRace().getCourse();
Double startingX = (double) marks.get(0).getX();
Double startingY = (double) marks.get(0).getY();
Double firstMarkX = (double) marks.get(1).getX();
Double firstMarkY = (double) marks.get(1).getY();
Double startingX = group.getChildren().get(0).getLayoutX();
Double startingY = group.getChildren().get(0).getLayoutY();
Double firstMarkX = group.getChildren().get(1).getLayoutX();
Double firstMarkY = group.getChildren().get(1).getLayoutY();
for (Boat boat : boats) {
BoatGroup boatGroup = new BoatGroup(boat, Colors.getColor());
@@ -324,67 +335,67 @@ public class CanvasController {
*/
private void drawCourse() {
fitToCanvas();
for (Mark mark : raceViewController.getRace().getCourse()) {
if (mark.getMarkType() == MarkType.SINGLE_MARK) {
drawSingleMark((SingleMark) mark, Color.BLACK);
} else {
drawGateMark((GateMark) mark);
}
}
System.out.println("MIN/MAX POINTS");
System.out.println(minLatPoint.getName() + " " + minLatPoint.getX() + " " + minLatPoint.getY());
System.out.println(maxLatPoint.getName() + " " + maxLatPoint.getX() + " " + maxLatPoint.getY());
System.out.println(minLonPoint.getName() + " " + minLonPoint.getX() + " " + minLonPoint.getY());
System.out.println(maxLonPoint.getName() + " " + maxLonPoint.getX() + " " + maxLonPoint.getY());
System.out.println(referencePointX);
System.out.println(referencePointY);
// for (Mark mark : raceViewController.getRace().getCourse()) {
// if (mark.getMarkType() == MarkType.SINGLE_MARK) {
// drawSingleMark((SingleMark) mark, Color.BLACK);
// } else {
// drawGateMark((GateMark) mark);
// }
// }
// System.out.println("MIN/MAX POINTS");
// System.out.println(minLatPoint.getName() + " " + minLatPoint.getX() + " " + minLatPoint.getY());
// System.out.println(maxLatPoint.getName() + " " + maxLatPoint.getX() + " " + maxLatPoint.getY());
// System.out.println(minLonPoint.getName() + " " + minLonPoint.getX() + " " + minLonPoint.getY());
// System.out.println(maxLonPoint.getName() + " " + maxLonPoint.getX() + " " + maxLonPoint.getY());
// System.out.println(referencePointX);
// System.out.println(referencePointY);
}
/**
* Draw a given mark on canvas
*
* @param singleMark
*/
private void drawSingleMark(SingleMark singleMark, Color color) {
gc.setFill(color);
System.out.println("DRAWING " + singleMark.getName() + " at " + singleMark.getX() + ", " + singleMark.getY());
gc.fillOval(singleMark.getX(), singleMark.getY(),MARK_SIZE,MARK_SIZE);
}
/**
* Draw a gate mark which contains two single marks
*
* @param gateMark
*/
private void drawGateMark(GateMark gateMark) {
Color color = Color.BLUE;
if (gateMark.getName().equals("Start")){
color = Color.GREEN;
}
if (gateMark.getName().equals("Finish")){
color = Color.RED;
}
drawSingleMark(gateMark.getSingleMark1(), color);
drawSingleMark(gateMark.getSingleMark2(), color);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.save();
gc.setStroke(color);
if (gateMark.getMarkType() == MarkType.OPEN_GATE)
gc.setLineDashes(3, 5);
gc.setLineWidth(2);
gc.strokeLine(
gateMark.getSingleMark1().getX() + MARK_SIZE / 2,
gateMark.getSingleMark1().getY() + MARK_SIZE / 2,
gateMark.getSingleMark2().getX() + MARK_SIZE / 2,
gateMark.getSingleMark2().getY() + MARK_SIZE / 2
);
gc.restore();
}
// /**
// * Draw a given mark on canvas
// *
// * @param singleMark
// */
// private void drawSingleMark(SingleMark singleMark, Color color) {
// gc.setFill(color);
// System.out.println("DRAWING " + singleMark.getName() + " at " + singleMark.getX() + ", " + singleMark.getY());
// gc.fillOval(singleMark.getX(), singleMark.getY(),MARK_SIZE,MARK_SIZE);
// }
//
// /**
// * Draw a gate mark which contains two single marks
// *
// * @param gateMark
// */
// private void drawGateMark(GateMark gateMark) {
// Color color = Color.BLUE;
//
// if (gateMark.getName().equals("Start")){
// color = Color.GREEN;
// }
//
// if (gateMark.getName().equals("Finish")){
// color = Color.RED;
// }
//
// drawSingleMark(gateMark.getSingleMark1(), color);
// drawSingleMark(gateMark.getSingleMark2(), color);
//
// GraphicsContext gc = canvas.getGraphicsContext2D();
// gc.save();
// gc.setStroke(color);
// if (gateMark.getMarkType() == MarkType.OPEN_GATE)
// gc.setLineDashes(3, 5);
//
// gc.setLineWidth(2);
// gc.strokeLine(
// gateMark.getSingleMark1().getX() + MARK_SIZE / 2,
// gateMark.getSingleMark1().getY() + MARK_SIZE / 2,
// gateMark.getSingleMark2().getX() + MARK_SIZE / 2,
// gateMark.getSingleMark2().getY() + MARK_SIZE / 2
// );
// gc.restore();
// }
/**
* Calculates x and y location for every marker that fits it to the canvas the race will be drawn on.
@@ -478,8 +489,8 @@ public class CanvasController {
}
referencePointX = Math.round(referencePointX);
referencePointY = Math.round(referencePointY);
referencePoint.setX((int) referencePointX);
referencePoint.setY((int) referencePointY);
// referencePoint.setX((int) referencePointX);
// referencePoint.setY((int) referencePointY);
}
/**
@@ -517,27 +528,31 @@ public class CanvasController {
* are scaled according to the distanceScaleFactor variable.
*/
private void givePointsXY() {
Point2D canvasLocation;
List<Mark> allPoints = new ArrayList<>(raceViewController.getRace().getCourse());
//Point2D canvasLocation;
// List<Mark> allPoints = new ArrayList<>(raceViewController.getRace().getCourse());
Set<Mark> unqiuePoints = new HashSet<>(raceViewController.getRace().getCourse());
System.out.println("unqiuePoints = " + unqiuePoints);
RaceObject markGroup;
for (Mark mark : allPoints) {
for (Mark mark : unqiuePoints) {
if (mark.getMarkType() != MarkType.SINGLE_MARK) {
GateMark gateMark = (GateMark) mark;
// canvasLocation = findScaledXY(gateMark.getSingleMark1());
// gateMark.getSingleMark1().setX((int) canvasLocation.getX());
// gateMark.getSingleMark1().setY((int) canvasLocation.getY());
//
// canvasLocation = findScaledXY(gateMark.getSingleMark2());
// gateMark.getSingleMark2().setX((int) canvasLocation.getX());
// gateMark.getSingleMark2().setY((int) canvasLocation.getY());
canvasLocation = findScaledXY(gateMark.getSingleMark1());
gateMark.getSingleMark1().setX((int) canvasLocation.getX());
gateMark.getSingleMark1().setY((int) canvasLocation.getY());
canvasLocation = findScaledXY(gateMark.getSingleMark2());
gateMark.getSingleMark2().setX((int) canvasLocation.getX());
gateMark.getSingleMark2().setY((int) canvasLocation.getY());
markGroup = new MarkGroup(mark, findScaledXY(gateMark.getSingleMark1()), findScaledXY(gateMark.getSingleMark2()));
group.getChildren().add(markGroup);
}
if (mark.getMarkType() == MarkType.CLOSED_GATE)
((GateMark) mark).assignXYCentered();
else {
canvasLocation = findScaledXY(mark);
mark.setX((int) canvasLocation.getX());
mark.setY((int) canvasLocation.getY());
// canvasLocation = findScaledXY(mark);
// mark.setX((int) canvasLocation.getX());
// mark.setY((int) canvasLocation.getY());
markGroup = new MarkGroup(mark, findScaledXY(mark));
}
}
}
+42 -62
View File
@@ -20,9 +20,11 @@ public class BoatGroup extends RaceObject{
private static final double BOAT_HEIGHT = 15d;
private static final double BOAT_WIDTH = 10d;
//Time between sections of race - Should be changed to 200 for actual program.
private static double expectedUpdateInterval = 2000;
private static double expectedUpdateInterval = 200;
private static int WAKE_FRAME_INTERVAL = 40;
private Boat boat;
private int wakeCounter = WAKE_FRAME_INTERVAL;
public BoatGroup (Boat boat, Color color){
this.boat = boat;
@@ -60,11 +62,7 @@ public class BoatGroup extends RaceObject{
velocityObject.setY(VELOCITY_Y_OFFSET);
velocityObject.relocate(velocityObject.getX(), velocityObject.getY());
wake.setLayoutX(0);
wake.setLayoutY(0);
wake.relocate(wake.getLayoutX(), wake.getLayoutY());
super.getChildren().addAll(boatPoly, wake, teamNameObject, velocityObject);
super.getChildren().addAll(boatPoly, teamNameObject, velocityObject);
}
private void initChildren (Color color) {
@@ -78,10 +76,10 @@ public class BoatGroup extends RaceObject{
* @param dx The amount to move the X coordinate by
* @param dy The amount to move the Y coordinate by
*/
void moveBy(double dx, double dy, double rotation) {
public void moveGroupBy(double dx, double dy, double rotation) {
super.setLayoutX(super.getLayoutX() + dx);
super.setLayoutY(super.getLayoutY() + dy);
rotateBoat(rotation);
rotateTo(currentRotation + rotation);
}
/**
@@ -90,8 +88,7 @@ public class BoatGroup extends RaceObject{
* @param y The Y coordinate to move the boat to
*/
public void moveTo (double x, double y, double rotation) {
super.currentRotation = 0;
rotateBoat(rotation);
rotateTo(rotation);
moveTo(x, y);
}
@@ -109,29 +106,26 @@ public class BoatGroup extends RaceObject{
} else if (rotationalGoal < currentRotation && rotationalVelocity < 0) {
rotation = rotationalVelocity * timeInterval;
}
moveBy(dx, dy, rotation);
moveGroupBy(dx, dy, rotation);
for (Node wake : super.getChildren().subList(4, super.getChildren().size())) {
if (!((Wake) wake).updatePosition(timeInterval))
super.getChildren().remove(wake);
}
if (wakeCounter-- == 0) {
wakeCounter = WAKE_FRAME_INTERVAL;
super.getChildren().add(
new Wake(
super.getLayoutX(), super.getLayoutY(), pixelVelocityX, pixelVelocityY
)
);
}
}
public void setDestination (double newXValue, double newYValue, double rotation) {
public void setDestination (double newXValue, double newYValue, double rotation, int... raceIds) {
if (hasRaceId(raceIds)) {
this.pixelVelocityX = (newXValue - super.getLayoutX()) / expectedUpdateInterval;
this.pixelVelocityY = (newYValue - super.getLayoutY()) / expectedUpdateInterval;
//this.destinationX = newXValue;
//this.destinationY = newYValue;
this.rotationalGoal = rotation;
// if (super.getLayoutY() >= newYValue && super.getLayoutX() <= newXValue)
// rotationalGoal = 90 - rotationalGoal;
// else if (super.getLayoutY() < newYValue && super.getLayoutX() <= newXValue)
// rotationalGoal = 90 + rotationalGoal;
// else if (super.getLayoutY() >= newYValue && super.getLayoutX() > newXValue)
// rotationalGoal = 270 + rotationalGoal;
// else
// rotationalGoal = 270 - rotationalGoal;
// if (Math.abs(360 - rotationalGoal + currentRotation) < Math.abs(rotationalGoal - currentRotation)) {
// System.out.println("ROTATE");
// this.rotationalVelocity = (360 - rotationalGoal + currentRotation) / expectedUpdateInterval;
// } else {
// this.rotationalVelocity = (rotationalGoal - currentRotation) / expectedUpdateInterval;
// }
if (Math.abs(rotationalGoal - currentRotation) > 180) {
if (rotationalGoal - currentRotation >= 0) {
this.rotationalVelocity = ((rotationalGoal - currentRotation) - 360) / expectedUpdateInterval;
@@ -142,13 +136,11 @@ public class BoatGroup extends RaceObject{
this.rotationalVelocity = (rotationalGoal - currentRotation) / expectedUpdateInterval;
}
}
}
public void setDestination (double newXValue, double newYValue) {
this.pixelVelocityX = (newXValue - super.getLayoutX()) / expectedUpdateInterval;
this.pixelVelocityY = (newYValue - super.getLayoutY()) / expectedUpdateInterval;
//this.destinationX = newXValue;
//this.destinationY = newYValue;
this.rotationalGoal = Math.abs(
public void setDestination (double newXValue, double newYValue, int... raceIDs) {
if (hasRaceId(raceIDs)) {
double rotation = Math.abs(
Math.toDegrees(
Math.atan(
(newYValue - super.getLayoutY()) / (newXValue - super.getLayoutX())
@@ -156,51 +148,35 @@ public class BoatGroup extends RaceObject{
)
);
if (super.getLayoutY() >= newYValue && super.getLayoutX() <= newXValue)
rotationalGoal = 90 - rotationalGoal;
rotation = 90 - rotation;
else if (super.getLayoutY() < newYValue && super.getLayoutX() <= newXValue)
rotationalGoal = 90 + rotationalGoal;
rotation = 90 + rotation;
else if (super.getLayoutY() >= newYValue && super.getLayoutX() > newXValue)
rotationalGoal = 270 + rotationalGoal;
rotation = 270 + rotation;
else
rotationalGoal = 270 - rotationalGoal;
if (Math.abs(rotationalGoal - currentRotation) > 180) {
if (rotationalGoal - currentRotation >= 0) {
this.rotationalVelocity = ((rotationalGoal - currentRotation) - 360) / expectedUpdateInterval;
} else {
this.rotationalVelocity = (360 + (rotationalGoal - currentRotation)) / expectedUpdateInterval;
}
} else {
this.rotationalVelocity = (rotationalGoal - currentRotation) / expectedUpdateInterval;
rotation = 270 - rotation;
setDestination(newXValue, newYValue, rotation, raceIDs);
}
}
public void rotateBoat (double rotationDeg) {
currentRotation += rotationDeg;
public void rotateTo (double rotation) {
Node boatPoly = super.getChildren().get(0);
boatPoly.getTransforms().clear();
boatPoly.getTransforms().add(new Rotate(currentRotation, BOAT_WIDTH/2, 0));
boatPoly.getTransforms().add(new Rotate(rotation, BOAT_WIDTH/2, 0));
Node wake = super.getChildren().get(1);
wake.getTransforms().clear();
wake.getTransforms().add(new Translate(0, BOAT_HEIGHT));
wake.getTransforms().add(new Rotate(currentRotation, BOAT_WIDTH/2, -BOAT_HEIGHT));
}
public static double getExpectedUpdateInterval() {
return expectedUpdateInterval;
}
public static void setExpectedUpdateInterval(double expectedUpdateInterval) {
BoatGroup.expectedUpdateInterval = expectedUpdateInterval;
wake.getTransforms().add(new Rotate(rotation, BOAT_WIDTH/2, -BOAT_HEIGHT));
}
public void forceRotation () {
rotateBoat (rotationalGoal - currentRotation);
rotateTo (rotationalGoal);
}
public void toggleAnnotations () {
super.getChildren().get(1).setVisible(false);
super.getChildren().get(2).setVisible(false);
super.getChildren().get(3).setVisible(false);
for (Node node : super.getChildren().subList(1, super.getChildren().size())) {
node.setVisible(false);
}
}
public Boat getBoat() {
@@ -214,4 +190,8 @@ public class BoatGroup extends RaceObject{
}
return false;
}
public int[] getRaceIds () {
return new int[] {boat.getId()};
}
}
+31 -7
View File
@@ -8,11 +8,14 @@ import javafx.scene.Group;
*/
public abstract class RaceObject extends Group {
double rotationalGoal;
double currentRotation;
double rotationalVelocity;
double pixelVelocityX;
double pixelVelocityY;
//Time between sections of race - Should be changed to 200 for actual program.
protected static double expectedUpdateInterval = 2000;
protected double rotationalGoal;
protected double currentRotation;
protected double rotationalVelocity;
protected double pixelVelocityX;
protected double pixelVelocityY;
public boolean isSamePos (Point2D point) {
return point.getX() == super.getLayoutX() && point.getY() == super.getLayoutY();
@@ -21,12 +24,33 @@ public abstract class RaceObject extends Group {
public Point2D getPosition () {
return new Point2D(super.getLayoutX(), getLayoutY());
}
public abstract void setDestination (double x, double y, double rotation);
public abstract void setDestination (double x, double y);
public static double getExpectedUpdateInterval() {
return expectedUpdateInterval;
}
public static void setExpectedUpdateInterval(double expectedUpdateInterval) {
RaceObject.expectedUpdateInterval = expectedUpdateInterval;
}
public abstract void setDestination (double x, double y, double rotation, int... raceIds);
public abstract void setDestination (double x, double y, int... raceIds);
public abstract void updatePosition (double timeInterval);
public abstract void moveTo (double x, double y, double rotation);
public abstract void moveTo (double x, double y);
public abstract void moveGroupBy(double x, double y, double rotation);
public abstract void rotateTo (double rotation);
public abstract boolean hasRaceId (int... raceIds);
public abstract int[] getRaceIds ();
public abstract void toggleAnnotations ();
}
+37
View File
@@ -0,0 +1,37 @@
package seng302.models;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
/**
* Created by CJIRWIN on 27/04/2017.
*/
class Wake extends Arc {
private static int VELOCITY_SCALE_FACTOR = 3;
private static int MAX_LIFESPAN = 180;
private static double LIFESPAN_PER_FRAME = 1.0 / MAX_LIFESPAN;
private double velocityX;
private double velocityY;
private int lifespan = MAX_LIFESPAN;
Wake (double startingX, double startingY, double velocityX, double velocityY) {
super(startingX, startingY, 25, 15, 160, 40);
super.setFill(Color.BLUE);
super.setType(ArcType.OPEN);
super.setStrokeWidth(2.0);
this.velocityX = -velocityX;
this.velocityY = -velocityY;
}
boolean updatePosition (double timeInterval) {
lifespan--;
super.setLayoutX(super.getLayoutX() + velocityX * timeInterval);
super.setLayoutX(super.getLayoutX() + velocityX * timeInterval);
super.setOpacity(LIFESPAN_PER_FRAME * lifespan * super.getOpacity());
return lifespan == 0;
}
}
@@ -48,15 +48,4 @@ public class GateMark extends Mark {
return (this.getSingleMark1().getLongitude());
}
public void assignXYCentered () {
System.out.println("POSSIBLE GOOF " + xValue + " " + yValue);
System.out.println(singleMark1.getX() + " " + singleMark1.getY());
System.out.println(singleMark2.getX() + " " + singleMark2.getY());
double dx = singleMark2.getX() - singleMark1.getX();
System.out.println("dx + " + dx);
double dy = singleMark2.getY() - singleMark1.getY();
xValue = (int) Math.round(singleMark1.getX() + dx / 2);
yValue = (int) Math.round(singleMark1.getY() + dy / 2);
System.out.println("PROBABLE GAAF " + xValue + " " + yValue);
}
}
@@ -11,8 +11,6 @@ public abstract class Mark {
private double latitude;
private double longitude;
private int id;
Integer xValue;
Integer yValue;
/**
* Create a mark instance by passing its name and type
@@ -127,22 +125,6 @@ public abstract class Mark {
return longitude;
}
public int getX () {
return xValue;
}
public int getY () {
return yValue;
}
public void setX (int x) {
this.xValue = x;
}
public void setY (int y) {
this.yValue = y;
}
public int getId() {
return id;
}
+134 -28
View File
@@ -1,27 +1,35 @@
package seng302.models.mark;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.transform.Rotate;
import seng302.models.RaceObject;
import java.util.ArrayList;
import java.util.List;
/**
* Created by CJIRWIN on 26/04/2017.
*/
public class MarkGroup extends RaceObject {
private static int MARK_RADIUS = 5;
private static int LINE_THICKNESS = 2;
private static double DASHED_GAP_LEN = 2d;
private static double DASHED_LINE_LEN = 5d;
private Mark mark;
private double pixelVelocityXM1;
private double pixelVelocityYM1;
private double pixelVelocityXM2;
private double pixelVelocityYM3;
private List<Mark> marks = new ArrayList<>();
private Mark mainMark;
private double[] nodePixelVelocitiesX;
private double[] nodePixelVelocitiesY;
private Point2D[] nodeDestinations;
public MarkGroup (Mark mark, Point2D... points) {
marks.add(mark);
mainMark = mark;
Color color = Color.BLACK;
if (mark.getName().equals("Start")){
color = Color.GREEN;
@@ -31,11 +39,20 @@ public class MarkGroup extends RaceObject {
if (mark.getMarkType() == MarkType.SINGLE_MARK) {
super.getChildren().add(new Circle(0, 0, MARK_RADIUS, color));
} else {
super.getChildren().add(new Circle(0, 0, MARK_RADIUS, color));
marks.add(((GateMark) mark).getSingleMark1());
marks.add(((GateMark) mark).getSingleMark2());
super.getChildren().add(
new Circle(
points[1].getX() - points[0].getX(),
points[1].getY() - points[0].getY(),
(points[1].getX() - points[0].getX() / 2),
(points[1].getY() - points[0].getY() / 2),
MARK_RADIUS,
color
)
);
super.getChildren().add(
new Circle(
-(points[1].getX() - points[0].getX() / 2),
-(points[1].getY() - points[0].getY() / 2),
MARK_RADIUS,
color
)
@@ -46,33 +63,60 @@ public class MarkGroup extends RaceObject {
points[1].getX() - points[0].getX(),
points[1].getY() - points[0].getY()
);
line.setStrokeWidth(2);
line.setStrokeWidth(LINE_THICKNESS);
if (mark.getMarkType() == MarkType.OPEN_GATE) {
line.getStrokeDashArray().addAll(3d, 5d);
line.getStrokeDashArray().addAll(DASHED_GAP_LEN, DASHED_LINE_LEN);
}
super.getChildren().add(line);
nodePixelVelocitiesX = new double[2];
nodePixelVelocitiesY = new double[2];
nodeDestinations = new Point2D[2];
}
this.mark = mark;
moveTo(points[0].getX(), points[0].getY());
}
public void setDestination (double x, double y, double rotation) {
public void setDestination (double x, double y, double rotation, int... raceIds) {
setDestination(x, y, raceIds);
this.rotationalGoal = rotation;
if (Math.abs(rotationalGoal - currentRotation) > 180) {
if (rotationalGoal - currentRotation >= 0) {
this.rotationalVelocity = ((rotationalGoal - currentRotation) - 360) / expectedUpdateInterval;
} else {
this.rotationalVelocity = (360 + (rotationalGoal - currentRotation)) / expectedUpdateInterval;
}
} else {
this.rotationalVelocity = (rotationalGoal - currentRotation) / expectedUpdateInterval;
}
}
public void setDestination (double x, double y) {
public void setDestination (double x, double y, int... raceIds) {
int childrenIndex = -1;
for (Mark mark : marks) {
for (int id : raceIds)
if (id == mark.getId() && childrenIndex != -1)
setDestinationChild(x, y, childrenIndex);
else if (id == mark.getId())
setDestinationGroup(x, y);
childrenIndex++;
}
}
public void setMarkDestination (int markId, double x, double y) {
}
public void updatePosition (double timeInterval) {
private void setDestinationChild (double x, double y, int childIndex) {
double relativeX = x - super.getLayoutX();
double relativeY = y - super.getLayoutY();
this.nodeDestinations[childIndex] = new Point2D(relativeX, relativeY);
this.nodePixelVelocitiesX[childIndex] = (relativeX - super.getChildren().get(childIndex).getLayoutX()) / expectedUpdateInterval;
this.nodePixelVelocitiesY[childIndex] = (relativeY - super.getChildren().get(childIndex).getLayoutY()) / expectedUpdateInterval;
}
public void moveTo (double x, double y, double rotation) {
moveTo(x, y);
private void setDestinationGroup (double x, double y) {
pixelVelocityX = (x - super.getLayoutX()) / expectedUpdateInterval;
pixelVelocityY = (y - super.getLayoutY()) / expectedUpdateInterval;
}
public void rotateTo (double rotation) {
super.getTransforms().clear();
super.getTransforms().add(
new Rotate(
@@ -83,20 +127,74 @@ public class MarkGroup extends RaceObject {
);
}
public void updatePosition (double timeInterval) {
double x = pixelVelocityX * timeInterval;
double y = pixelVelocityY * timeInterval;
double rotation = rotationalVelocity * timeInterval;
moveGroupBy(x, y, rotation);
updateChildren(timeInterval);
}
public void moveGroupBy (double x, double y, double rotation) {
super.setLayoutX(super.getLayoutX() + x);
super.setLayoutY(super.getOpacity() + y);
rotateTo(rotation + currentRotation);
}
private void updateChildren (double timeInterval) {
if (mainMark.getMarkType() != MarkType.SINGLE_MARK) {
Circle mark = (Circle) super.getChildren().get(0);
if (nodePixelVelocitiesX[0] > 0 && mark.getLayoutX() >= nodeDestinations[0].getX()) {
nodePixelVelocitiesX[0] = 0;
} else if (nodePixelVelocitiesX[0] < 0 && mark.getLayoutX() <= nodeDestinations[0].getX()) {
nodePixelVelocitiesX[0] = 0;
} else {
mark.setLayoutX(mark.getLayoutX() + nodePixelVelocitiesX[0] * timeInterval);
mark.setLayoutY(mark.getLayoutY() + nodePixelVelocitiesY[0] * timeInterval);
}
if (nodePixelVelocitiesY[0] >= 0 && mark.getLayoutY() > nodeDestinations[0].getY()) {
nodePixelVelocitiesY[0] = 0;
} else if (nodePixelVelocitiesY[0] < 0 && mark.getLayoutY() <= nodeDestinations[0].getY()) {
nodePixelVelocitiesY[0] = 0;
} else {
mark.setLayoutX(mark.getLayoutX() + nodePixelVelocitiesX[0] * timeInterval);
mark.setLayoutY(mark.getLayoutY() + nodePixelVelocitiesY[0] * timeInterval);
}
mark = (Circle) super.getChildren().get(1);
if (nodePixelVelocitiesX[1] > 0 && mark.getLayoutX() >= nodeDestinations[1].getX()) {
nodePixelVelocitiesX[1] = 0;
} else if (nodePixelVelocitiesX[1] < 0 && mark.getLayoutX() <= nodeDestinations[1].getX()) {
nodePixelVelocitiesX[1] = 0;
} else {
mark.setLayoutX(mark.getLayoutX() + nodePixelVelocitiesX[1] * timeInterval);
mark.setLayoutY(mark.getLayoutY() + nodePixelVelocitiesY[1] * timeInterval);
}
if (nodePixelVelocitiesY[1] >= 0 && mark.getLayoutY() > nodeDestinations[1].getY()) {
nodePixelVelocitiesY[1] = 0;
} else if (nodePixelVelocitiesY[1] < 0 && mark.getLayoutY() <= nodeDestinations[1].getY()) {
nodePixelVelocitiesY[1] = 0;
} else {
mark.setLayoutX(mark.getLayoutX() + nodePixelVelocitiesX[1] * timeInterval);
mark.setLayoutY(mark.getLayoutY() + nodePixelVelocitiesY[1] * timeInterval);
}
}
}
public void moveTo (double x, double y, double rotation) {
moveTo(x, y);
rotateTo(rotation);
}
public void moveTo (double x, double y) {
super.setLayoutX(x);
super.setLayoutY(y);
}
public boolean hasRaceId (int... raceIds) {
for (int id : raceIds) {
for (int id : raceIds)
for (Mark mark : marks)
if (id == mark.getId())
return true;
if (mark.getMarkType() != MarkType.SINGLE_MARK) {
if (id == ((GateMark) mark).getSingleMark1().getId() || id == ((GateMark) mark).getSingleMark2().getId())
return true;
}
}
return false;
}
public void toggleAnnotations () {
@@ -111,4 +209,12 @@ public class MarkGroup extends RaceObject {
MARK_RADIUS = markRadius;
}
public int[] getRaceIds () {
int[] idArray = new int[marks.size()];
int i = 0;
for (Mark mark : marks)
idArray[i++] = mark.getId();
return idArray;
}
}