From 224c16a7139947c22ed69c0797a87b528635220f Mon Sep 17 00:00:00 2001 From: Fan-Wu Yang Date: Wed, 29 Mar 2017 03:18:47 +1300 Subject: [PATCH 1/2] Implemented Map Boundaries in XML - RaceXMLReader will calculate the top left latitude and longitude and the bottom right latitude and longitude, and make the layout the map accordingly. - The Boundaries are draw on the Race Canvas in Aqua. #story[22] --- .../seng302/Controllers/RaceController.java | 8 ++- .../seng302/Model/ResizableRaceCanvas.java | 33 ++++++++-- src/main/java/seng302/RaceMap.java | 8 +++ src/main/java/seng302/RaceXMLReader.java | 64 ++++++++++++++++++- src/main/resources/raceXML/bermuda_AC35.xml | 44 +++++++++++-- 5 files changed, 146 insertions(+), 11 deletions(-) diff --git a/src/main/java/seng302/Controllers/RaceController.java b/src/main/java/seng302/Controllers/RaceController.java index 2405a105..ff135580 100644 --- a/src/main/java/seng302/Controllers/RaceController.java +++ b/src/main/java/seng302/Controllers/RaceController.java @@ -143,12 +143,16 @@ public class RaceController extends Controller{ BoatInRace[] boats = new BoatInRace[raceXMLReader.getBoats().size()]; boats = raceXMLReader.getBoats().toArray(boats); //BoatInRace[] boats = generateAC35Competitors(); - - raceMap = new ResizableRaceCanvas(); + double lat1 = raceXMLReader.getMapTopLeft().getLatitude(); + double long1 = raceXMLReader.getMapTopLeft().getLongitude(); + double lat2 = raceXMLReader.getMapBottomRight().getLatitude(); + double long2 = raceXMLReader.getMapBottomRight().getLongitude(); + raceMap = new ResizableRaceCanvas(lat1, long1, lat2, long2); raceMap.setMouseTransparent(true); raceMap.widthProperty().bind(canvasBase.widthProperty()); raceMap.heightProperty().bind(canvasBase.heightProperty()); raceMap.setBoats(boats); + raceMap.setRaceBoundaries(raceXMLReader.getBoundary()); raceMap.drawRaceMap(); raceMap.setVisible(true); diff --git a/src/main/java/seng302/Model/ResizableRaceCanvas.java b/src/main/java/seng302/Model/ResizableRaceCanvas.java index a8962d05..4f74a990 100644 --- a/src/main/java/seng302/Model/ResizableRaceCanvas.java +++ b/src/main/java/seng302/Model/ResizableRaceCanvas.java @@ -1,6 +1,7 @@ package seng302.Model; +import com.sun.corba.se.impl.orbutil.graph.Graph; import javafx.application.Platform; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; @@ -29,6 +30,7 @@ public class ResizableRaceCanvas extends Canvas { private BoatInRace[] boats; private RaceController controller; private boolean raceAnno = true; + private ArrayList raceBoundaries; /** * Sets the boats that are to be displayed in this race. @@ -41,6 +43,7 @@ public class ResizableRaceCanvas extends Canvas { public ResizableRaceCanvas(RaceMap map) { + super(); this.map = map; gc = this.getGraphicsContext2D(); // Redraw canvas when size changes. @@ -53,6 +56,12 @@ public class ResizableRaceCanvas extends Canvas { */ public ResizableRaceCanvas() { this(null); + setMap(new RaceMap(32.278, -64.863, 32.320989, -64.821, (int) getWidth(), (int) getHeight())); + } + + public ResizableRaceCanvas(double lat1, double long1, double lat2, double long2){ + this(null); + setMap(new RaceMap(lat1, long1, lat2, long2, (int) getWidth(), (int) getHeight())); } /** @@ -154,6 +163,18 @@ public class ResizableRaceCanvas extends Canvas { gc.fillText(text, xCoord, yCoord); } + public void drawBoundaries(){ + gc.setFill(Color.AQUA); + double xpoints[] = new double[raceBoundaries.size()]; + double ypoints[] = new double[raceBoundaries.size()]; + for (int i = 0; i < raceBoundaries.size(); i++){ + GraphCoordinate coord = map.convertGPS(raceBoundaries.get(i)); + xpoints[i] = coord.getX(); + ypoints[i] = coord.getY(); + } + gc.fillPolygon(xpoints, ypoints, xpoints.length); + } + /** * Draws the Race Map */ @@ -161,16 +182,17 @@ public class ResizableRaceCanvas extends Canvas { double width = getWidth(); double height = getHeight(); - gc.clearRect(0, 0, width, height); //System.out.println("Race Map Canvas Width: "+ width + ", Height:" + height); - this.map = new RaceMap(32.278, -64.863, 32.320989, -64.821, (int) width, (int) height); if (map == null) { - return; + return;//TODO this should return a exception in the future } + this.map.setHeight((int)height); + this.map.setWidth((int)width); //finish line gc.setLineWidth(2); + drawBoundaries(); GraphCoordinate finishLineCoord1 = this.map.convertGPS(Constants.finishLineMarker1); GraphCoordinate finishLineCoord2 = this.map.convertGPS(Constants.finishLineMarker2); displayLine(finishLineCoord1, finishLineCoord2, Color.DARKRED); @@ -189,7 +211,6 @@ public class ResizableRaceCanvas extends Canvas { displayLine(startline1, startline2, Color.GREEN); - if (boats != null) { for (BoatInRace boat : boats) { if (boat != null) { @@ -226,6 +247,10 @@ public class ResizableRaceCanvas extends Canvas { } } + public void setRaceBoundaries(ArrayList boundaries) { + this.raceBoundaries = boundaries; + } + /** * Set the Canvas to resizable. * diff --git a/src/main/java/seng302/RaceMap.java b/src/main/java/seng302/RaceMap.java index 420214f3..172ec58b 100644 --- a/src/main/java/seng302/RaceMap.java +++ b/src/main/java/seng302/RaceMap.java @@ -50,4 +50,12 @@ public class RaceMap { public GraphCoordinate convertGPS(GPSCoordinate coordinate) { return convertGPS(coordinate.getLatitude(), coordinate.getLongitude()); } + + public void setWidth(int width) { + this.width = width; + } + + public void setHeight(int height) { + this.height = height; + } } diff --git a/src/main/java/seng302/RaceXMLReader.java b/src/main/java/seng302/RaceXMLReader.java index 746e48f5..9be593fb 100644 --- a/src/main/java/seng302/RaceXMLReader.java +++ b/src/main/java/seng302/RaceXMLReader.java @@ -19,7 +19,9 @@ public class RaceXMLReader extends XMLReader{ private Color[] colors = {Color.BLUEVIOLET, Color.BLACK, Color.RED, Color.ORANGE, Color.DARKOLIVEGREEN, Color.LIMEGREEN};//TODO make this established in xml or come up with a better system. private ArrayList legs = new ArrayList<>(); private GPSCoordinate mark, startPt1, startPt2, finishPt1, finishPt2, leewardPt1, leewardPt2, windwardPt1, windwardPt2; + private GPSCoordinate mapTopLeft, mapBottomRight; private ArrayList boundary = new ArrayList<>(); + private static double COORDINATEPADDING = 0.0005; public RaceXMLReader(String filePath) throws IOException, SAXException, ParserConfigurationException { @@ -73,9 +75,61 @@ public class RaceXMLReader extends XMLReader{ NodeList nCourse = doc.getElementsByTagName("course"); NodeList nBounds = ((Element)nCourse.item(0)).getElementsByTagName("boundaries"); + nBounds = ((Element) nBounds.item(0)).getElementsByTagName("coordinate"); + int maxLatitudeIndex = 0; + double maxLatitude = -Double.MIN_VALUE; + int maxLongitudeIndex = 0; + double maxLongitude = -180; + int minLatitudeIndex = 0; + double minLatitude = Double.MAX_VALUE; + int minLongitudeIndex = 0; + double minLongitude = Double.MAX_VALUE; for (int i = 0; i < nBounds.getLength(); i++){ - boundary.add(getCoordinates(nBounds, i)); + boundary.add(getCoordinates((Element) nBounds.item(i))); + if (boundary.get(i).getLatitude() > maxLatitude){ + maxLatitudeIndex = i; + maxLatitude = boundary.get(i).getLatitude(); + } + if (boundary.get(i).getLatitude() < minLatitude){ + minLatitudeIndex = i; + minLatitude = boundary.get(i).getLatitude(); + } + if (boundary.get(i).getLongitude() > maxLongitude){ + maxLongitudeIndex = i; + maxLongitude = boundary.get(i).getLongitude(); + } + if (boundary.get(i).getLongitude() < minLongitude){ + minLongitudeIndex = i; + minLongitude = boundary.get(i).getLongitude(); + } } + System.out.println(nBounds.getLength()); + System.out.println(maxLatitude); + System.out.println(minLatitude); + System.out.println(maxLongitude); + System.out.println(minLongitude); + + double difference = 0;//this will hold the largest difference so we can make the map square. + double latitudeDiff = Math.abs(Math.abs(boundary.get(maxLatitudeIndex).getLatitude()) - Math.abs(boundary.get(minLatitudeIndex).getLatitude())); + double longitudeDiff = Math.abs(Math.abs(boundary.get(maxLongitudeIndex).getLongitude()) - Math.abs(boundary.get(minLongitudeIndex).getLongitude())); + if (latitudeDiff >= longitudeDiff){ + difference = latitudeDiff - longitudeDiff; + maxLongitude += difference/2; + minLongitude -= difference/2; + }else{ + difference = longitudeDiff - latitudeDiff; + maxLatitude += difference/2; + minLatitude -= difference/2; + } + maxLatitude += COORDINATEPADDING; + minLatitude -= COORDINATEPADDING; + maxLongitude += COORDINATEPADDING; + minLongitude -= COORDINATEPADDING; + //now create map boundaries + //top left canvas point is min logitude, max latitude + //bottom right of canvas point is min longitude, max latitude. + mapTopLeft = new GPSCoordinate(minLatitude, minLongitude); + mapBottomRight = new GPSCoordinate(maxLatitude, maxLongitude); NodeList nMarks = ((Element)nCourse.item(0)).getElementsByTagName("marker"); startPt1 = getCoordinates(nMarks, 0); @@ -162,4 +216,12 @@ public class RaceXMLReader extends XMLReader{ public ArrayList getBoundary() { return boundary; } + + public GPSCoordinate getMapTopLeft() { + return mapTopLeft; + } + + public GPSCoordinate getMapBottomRight() { + return mapBottomRight; + } } diff --git a/src/main/resources/raceXML/bermuda_AC35.xml b/src/main/resources/raceXML/bermuda_AC35.xml index 97867f69..bac4a47f 100644 --- a/src/main/resources/raceXML/bermuda_AC35.xml +++ b/src/main/resources/raceXML/bermuda_AC35.xml @@ -119,12 +119,48 @@ - 32.278 - -64.863 + 32.313922 + -64.837168 - 32.30989 - -64.821 + 32.317403 + -64.838627 + + + 32.317911 + -64.836996 + + + 32.317548 + -64.835022 + + + 32.304273 + -64.822834 + + + 32.279097 + -64.841545 + + + 32.279604 + -64.849871 + + + 32.289545 + -64.854162 + + + 32.290198 + -64.858711 + + + 32.297164 + -64.856394 + + + 32.296148 + -64.849184 From eb97bd6aefdf125c93f5f3e520c97400652f00f9 Mon Sep 17 00:00:00 2001 From: Fan-Wu Yang Date: Wed, 29 Mar 2017 13:29:53 +1300 Subject: [PATCH 2/2] Implemented resizable map and boundary scaling. - Map can now be downsized - The boundaries are auto margined and fit in the center of the canvas. #implement --- src/main/java/seng302/App.java | 3 +- .../seng302/Controllers/RaceController.java | 3 +- .../seng302/Model/ResizableRaceCanvas.java | 28 ++++++++---- src/main/java/seng302/RaceMap.java | 10 ++++- src/main/java/seng302/RaceXMLReader.java | 4 +- src/main/resources/scenes/racepane.fxml | 43 ++++++++++++------- 6 files changed, 62 insertions(+), 29 deletions(-) diff --git a/src/main/java/seng302/App.java b/src/main/java/seng302/App.java index d840f6fb..85b89c10 100644 --- a/src/main/java/seng302/App.java +++ b/src/main/java/seng302/App.java @@ -32,7 +32,8 @@ public class App extends Application { @Override public void start(Stage primaryStage) throws Exception { this.primaryStage = primaryStage; - + primaryStage.minHeightProperty().setValue(600); + primaryStage.minWidthProperty().setValue(780); //load the first container try { FXMLLoader loader = new FXMLLoader(); diff --git a/src/main/java/seng302/Controllers/RaceController.java b/src/main/java/seng302/Controllers/RaceController.java index ff135580..ff3ba51f 100644 --- a/src/main/java/seng302/Controllers/RaceController.java +++ b/src/main/java/seng302/Controllers/RaceController.java @@ -12,6 +12,7 @@ import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.input.MouseEvent; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.HBox; +import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.layout.GridPane; import javafx.util.Callback; @@ -31,7 +32,7 @@ import java.util.ResourceBundle; */ public class RaceController extends Controller{ @FXML - AnchorPane canvasBase; + GridPane canvasBase; ResizableRaceCanvas raceMap; diff --git a/src/main/java/seng302/Model/ResizableRaceCanvas.java b/src/main/java/seng302/Model/ResizableRaceCanvas.java index 4f74a990..df6cb54a 100644 --- a/src/main/java/seng302/Model/ResizableRaceCanvas.java +++ b/src/main/java/seng302/Model/ResizableRaceCanvas.java @@ -31,6 +31,7 @@ public class ResizableRaceCanvas extends Canvas { private RaceController controller; private boolean raceAnno = true; private ArrayList raceBoundaries; + double[] xpoints = {}, ypoints = {}; /** * Sets the boats that are to be displayed in this race. @@ -164,14 +165,11 @@ public class ResizableRaceCanvas extends Canvas { } public void drawBoundaries(){ - gc.setFill(Color.AQUA); - double xpoints[] = new double[raceBoundaries.size()]; - double ypoints[] = new double[raceBoundaries.size()]; - for (int i = 0; i < raceBoundaries.size(); i++){ - GraphCoordinate coord = map.convertGPS(raceBoundaries.get(i)); - xpoints[i] = coord.getX(); - ypoints[i] = coord.getY(); + if (this.raceBoundaries == null){ + return; } + gc.setFill(Color.AQUA); + setRaceBoundCoordinates(); gc.fillPolygon(xpoints, ypoints, xpoints.length); } @@ -248,7 +246,21 @@ public class ResizableRaceCanvas extends Canvas { } public void setRaceBoundaries(ArrayList boundaries) { - this.raceBoundaries = boundaries; + this.raceBoundaries = new ArrayList<>(); + for (GPSCoordinate bound: boundaries){ + raceBoundaries.add(bound); + } + setRaceBoundCoordinates(); + } + + public void setRaceBoundCoordinates(){ + xpoints = new double[this.raceBoundaries.size()]; + ypoints = new double[this.raceBoundaries.size()]; + for (int i = 0; i < raceBoundaries.size(); i++){ + GraphCoordinate coord = map.convertGPS(raceBoundaries.get(i)); + xpoints[i] = coord.getX(); + ypoints[i] = coord.getY(); + } } /** diff --git a/src/main/java/seng302/RaceMap.java b/src/main/java/seng302/RaceMap.java index 172ec58b..88c334e7 100644 --- a/src/main/java/seng302/RaceMap.java +++ b/src/main/java/seng302/RaceMap.java @@ -35,8 +35,16 @@ public class RaceMap { * @see GraphCoordinate */ public GraphCoordinate convertGPS(double lat, double lon) { + int difference = Math.abs(width - height); + int size = width; + if (width > height){ + size = height; + return new GraphCoordinate((int) ((size * (lon - x1) / (x2 - x1)) + difference/2), (int) (size - (size * (lat - y1) / (y2 - y1)))); + }else{ + return new GraphCoordinate((int) (size * (lon - x1) / (x2 - x1)), (int) ((size - (size * (lat - y1) / (y2 - y1))) + difference/2)); + } - return new GraphCoordinate((int) (width * (lon - x1) / (x2 - x1)), (int) (height - (height * (lat - y1) / (y2 - y1)))); + //return new GraphCoordinate((int) (width * (lon - x1) / (x2 - x1)), (int) (height - (height * (lat - y1) / (y2 - y1)))); } /** diff --git a/src/main/java/seng302/RaceXMLReader.java b/src/main/java/seng302/RaceXMLReader.java index 9be593fb..e54e42fd 100644 --- a/src/main/java/seng302/RaceXMLReader.java +++ b/src/main/java/seng302/RaceXMLReader.java @@ -103,11 +103,11 @@ public class RaceXMLReader extends XMLReader{ minLongitude = boundary.get(i).getLongitude(); } } - System.out.println(nBounds.getLength()); + /*System.out.println(nBounds.getLength()); System.out.println(maxLatitude); System.out.println(minLatitude); System.out.println(maxLongitude); - System.out.println(minLongitude); + System.out.println(minLongitude);*/ double difference = 0;//this will hold the largest difference so we can make the map square. double latitudeDiff = Math.abs(Math.abs(boundary.get(maxLatitudeIndex).getLatitude()) - Math.abs(boundary.get(minLatitudeIndex).getLatitude())); diff --git a/src/main/resources/scenes/racepane.fxml b/src/main/resources/scenes/racepane.fxml index 46c4ee89..e25728c3 100644 --- a/src/main/resources/scenes/racepane.fxml +++ b/src/main/resources/scenes/racepane.fxml @@ -1,5 +1,6 @@ + @@ -61,22 +62,32 @@ - - - - + + + + + + + + + +