mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 06:18:44 +00:00
Removed dead code in MeesageFactory and redundant classes
tags: #story[1273]
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
package seng302.gameServer;
|
package seng302.gameServer;
|
||||||
|
|
||||||
import seng302.gameServer.messages.*;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import seng302.gameServer.messages.BoatLocationMessage;
|
import seng302.gameServer.messages.BoatLocationMessage;
|
||||||
@@ -25,9 +24,6 @@ import seng302.model.token.Token;
|
|||||||
import seng302.model.token.TokenType;
|
import seng302.model.token.TokenType;
|
||||||
import seng302.utilities.XMLGenerator;
|
import seng302.utilities.XMLGenerator;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Class for interfacing between the data we have in the GameState to the messages we need to send
|
* A Class for interfacing between the data we have in the GameState to the messages we need to send
|
||||||
* through the MainServerThread.
|
* through the MainServerThread.
|
||||||
@@ -77,9 +73,6 @@ public class MessageFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void updateBoats(List<ServerYacht> yachts) {
|
public static void updateBoats(List<ServerYacht> yachts) {
|
||||||
// for (ServerYacht serverYacht : yachts) {
|
|
||||||
// System.out.println(serverYacht);
|
|
||||||
// }
|
|
||||||
xmlGenerator.getRace().setBoats(yachts);
|
xmlGenerator.getRace().setBoats(yachts);
|
||||||
String xmlStr = xmlGenerator.getBoatsAsXml();
|
String xmlStr = xmlGenerator.getBoatsAsXml();
|
||||||
MessageFactory.boats = new XMLMessage(xmlStr, XMLMessageSubType.BOAT, xmlStr.length());
|
MessageFactory.boats = new XMLMessage(xmlStr, XMLMessageSubType.BOAT, xmlStr.length());
|
||||||
|
|||||||
@@ -1,14 +1,5 @@
|
|||||||
package seng302.visualiser;
|
package seng302.visualiser;
|
||||||
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.util.Pair;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import seng302.gameServer.messages.*;
|
|
||||||
import seng302.model.stream.packets.PacketType;
|
|
||||||
import seng302.model.stream.packets.StreamPacket;
|
|
||||||
import seng302.utilities.XMLParser;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -43,7 +34,7 @@ import seng302.model.stream.xml.generator.RaceXMLTemplate;
|
|||||||
import seng302.model.stream.xml.generator.RegattaXMLTemplate;
|
import seng302.model.stream.xml.generator.RegattaXMLTemplate;
|
||||||
import seng302.utilities.XMLGenerator;
|
import seng302.utilities.XMLGenerator;
|
||||||
import seng302.utilities.XMLParser;
|
import seng302.utilities.XMLParser;
|
||||||
import seng302.visualiser.controllers.ViewManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class describing a single connection to a Server for the purposes of sending and receiving on
|
* A class describing a single connection to a Server for the purposes of sending and receiving on
|
||||||
|
|||||||
@@ -108,10 +108,6 @@ public class MapMaker {
|
|||||||
return mapPreviews.get(index).getAssets();
|
return mapPreviews.get(index).getAssets();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RaceXMLData getCurrentRace() {
|
|
||||||
return races.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RegattaXMLData getCurrentRegatta() {
|
public RegattaXMLData getCurrentRegatta() {
|
||||||
return regattas.get(index);
|
return regattas.get(index);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package seng302.visualiser;
|
package seng302.visualiser;
|
||||||
|
|
||||||
import seng302.gameServer.ServerAdvertiser;
|
import static seng302.gameServer.ServerAdvertiser.getLocalHostIp;
|
||||||
import seng302.gameServer.ServerDescription;
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import javax.jmdns.JmDNS;
|
import javax.jmdns.JmDNS;
|
||||||
import javax.jmdns.ServiceEvent;
|
import javax.jmdns.ServiceEvent;
|
||||||
import javax.jmdns.ServiceListener;
|
import javax.jmdns.ServiceListener;
|
||||||
import javax.jmdns.impl.JmDNSImpl;
|
import seng302.gameServer.ServerAdvertiser;
|
||||||
import java.io.IOException;
|
import seng302.gameServer.ServerDescription;
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import static seng302.gameServer.ServerAdvertiser.getLocalHostIp;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listens for servers on the local network
|
* Listens for servers on the local network
|
||||||
@@ -58,7 +58,7 @@ public class ServerListener{
|
|||||||
servers.remove(toRemove);
|
servers.remove(toRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate.serverRemoved(new ArrayList<ServerDescription>(servers));
|
delegate.serverRemoved(new ArrayList<>(servers));
|
||||||
|
|
||||||
// Get all other servers with the same name to respond if they are up
|
// Get all other servers with the same name to respond if they are up
|
||||||
jmdns.requestServiceInfo(ServerAdvertiser.SERVICE_TYPE, serverName);
|
jmdns.requestServiceInfo(ServerAdvertiser.SERVICE_TYPE, serverName);
|
||||||
@@ -94,13 +94,6 @@ public class ServerListener{
|
|||||||
|
|
||||||
listener = new GameServeMonitor();
|
listener = new GameServeMonitor();
|
||||||
jmdns.addServiceListener(ServerAdvertiser.SERVICE_TYPE, listener);
|
jmdns.addServiceListener(ServerAdvertiser.SERVICE_TYPE, listener);
|
||||||
|
|
||||||
/*new Timer().schedule(new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
}, 50, SERVICE_REFRESH_INTERVAL);*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ServerListener getInstance() throws IOException {
|
public static ServerListener getInstance() throws IOException {
|
||||||
@@ -134,7 +127,7 @@ public class ServerListener{
|
|||||||
for (ServerDescription server : servers){
|
for (ServerDescription server : servers){
|
||||||
if (server.serverShouldBeRemoved()){
|
if (server.serverShouldBeRemoved()){
|
||||||
listener.servers.remove(server);
|
listener.servers.remove(server);
|
||||||
delegate.serverRemoved(new ArrayList<ServerDescription>(listener.servers));
|
delegate.serverRemoved(new ArrayList<>(listener.servers));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import javafx.scene.layout.StackPane;
|
|||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* The pre loading screen before launch the start view
|
||||||
* Created by Kusal on 26-Sep-17.
|
* Created by Kusal on 26-Sep-17.
|
||||||
*/
|
*/
|
||||||
public class SplashScreenController implements Initializable{
|
public class SplashScreenController implements Initializable{
|
||||||
@@ -26,17 +27,14 @@ public class SplashScreenController implements Initializable{
|
|||||||
public void run(){
|
public void run(){
|
||||||
try {
|
try {
|
||||||
Thread.sleep(3000);
|
Thread.sleep(3000);
|
||||||
Platform.runLater(new Runnable() {
|
Platform.runLater(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
Stage stage = new Stage();
|
||||||
try {
|
ViewManager.getInstance().initialStartView(stage);
|
||||||
Stage stage = new Stage();
|
} catch (Exception e) {
|
||||||
ViewManager.getInstance().initialStartView(stage);
|
e.printStackTrace();
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
rootPane.getScene().getWindow().hide();
|
|
||||||
}
|
}
|
||||||
|
rootPane.getScene().getWindow().hide();
|
||||||
});
|
});
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|||||||
@@ -1,230 +0,0 @@
|
|||||||
package seng302.visualiser.fxObjects.assets_2D;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.beans.value.ObservableValue;
|
|
||||||
import javafx.scene.CacheHint;
|
|
||||||
import javafx.scene.Group;
|
|
||||||
import javafx.scene.paint.Color;
|
|
||||||
import javafx.scene.paint.Paint;
|
|
||||||
import javafx.scene.shape.Rectangle;
|
|
||||||
import javafx.scene.text.Text;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Grouping of string objects over a semi transparent background.
|
|
||||||
*/
|
|
||||||
public class AnnotationBox extends Group {
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface AnnotationFormatter<T> {
|
|
||||||
String transformString (T input);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class stores a text object and relationship for updating the text object if needed
|
|
||||||
*
|
|
||||||
* @param <T> The type of observable value passed to the annotation, if there is one.
|
|
||||||
*/
|
|
||||||
public class Annotation<T> {
|
|
||||||
private Text text;
|
|
||||||
private ObservableValue<T> source;
|
|
||||||
private AnnotationFormatter<T> format;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for observing annotation
|
|
||||||
* @param textObject the javaFX text object the annotation is displayed in
|
|
||||||
* @param source observable value that the annotation is taken from
|
|
||||||
* @param formatter interface describing how to format the source data if needed
|
|
||||||
*/
|
|
||||||
public Annotation (Text textObject, ObservableValue<T> source, AnnotationFormatter<T> formatter) {
|
|
||||||
this.text = textObject;
|
|
||||||
this.source = source;
|
|
||||||
this.format = formatter;
|
|
||||||
source.addListener((obs, oldVal, newVal) ->
|
|
||||||
Platform.runLater(() -> text.setText(format.transformString(newVal)))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for a static annotation
|
|
||||||
* @param textObject the javaFX text object the annotation is displayed in
|
|
||||||
* @param annotationText the static value of the test object
|
|
||||||
*/
|
|
||||||
public Annotation (Text textObject, String annotationText) {
|
|
||||||
textObject.setText(annotationText);
|
|
||||||
text = textObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Text getText () {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Text offset constants
|
|
||||||
private static final double X_OFFSET_TEXT = 20d;
|
|
||||||
private static final double Y_OFFSET_TEXT_INIT = -35d;
|
|
||||||
private static final double Y_OFFSET_PER_TEXT = 12d;
|
|
||||||
//Background constants
|
|
||||||
private static final double TEXT_BUFFER = 3;
|
|
||||||
private static final double BACKGROUND_X = X_OFFSET_TEXT - TEXT_BUFFER;
|
|
||||||
private static final double BACKGROUND_Y = Y_OFFSET_TEXT_INIT - TEXT_BUFFER;
|
|
||||||
private static final double BACKGROUND_H_PER_TEXT = 9.5d;
|
|
||||||
private static final double BACKGROUND_ARC_SIZE = 10;
|
|
||||||
|
|
||||||
private int visibleAnnotations = 0;
|
|
||||||
private double backgroundWidth = 145d;
|
|
||||||
|
|
||||||
private Rectangle background = new Rectangle();
|
|
||||||
private Paint theme = Color.BLACK;
|
|
||||||
|
|
||||||
private Map<String, Annotation> annotationsByName = new HashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an empty annotation box. The box is offset from (0,0) by (17, -38).
|
|
||||||
*/
|
|
||||||
public AnnotationBox() {
|
|
||||||
this.setCache(true);
|
|
||||||
background.setX(BACKGROUND_X);
|
|
||||||
background.setY(BACKGROUND_Y);
|
|
||||||
background.setWidth(backgroundWidth);
|
|
||||||
background.setHeight(Math.abs(BACKGROUND_X) + TEXT_BUFFER + BACKGROUND_H_PER_TEXT * 4);
|
|
||||||
background.setArcHeight(BACKGROUND_ARC_SIZE);
|
|
||||||
background.setArcWidth(BACKGROUND_ARC_SIZE);
|
|
||||||
background.setFill(new Color(1, 1, 1, 0.75));
|
|
||||||
background.setStroke(theme);
|
|
||||||
background.setStrokeWidth(2);
|
|
||||||
background.setCache(true);
|
|
||||||
background.setCacheHint(CacheHint.SCALE);
|
|
||||||
this.getChildren().add(background);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an annotation to the box. Use the name to reference the annotation for removal or\
|
|
||||||
* changing visibility.
|
|
||||||
* @param annotationName the name of the annotation.
|
|
||||||
* @param annotation the annotation.
|
|
||||||
*/
|
|
||||||
public void addAnnotation (String annotationName, Annotation annotation) {
|
|
||||||
annotationsByName.put(annotationName, annotation);
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
this.getChildren().add(annotation.getText());
|
|
||||||
visibleAnnotations++;
|
|
||||||
update();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an annotation with a constant text.
|
|
||||||
* @param annotationName The name of the annotation. Will be used to reference it later.
|
|
||||||
* @param annotationText The desired text.
|
|
||||||
*/
|
|
||||||
public void addAnnotation (String annotationName, String annotationText) {
|
|
||||||
Text text = getTextObject();
|
|
||||||
addAnnotation(annotationName, new Annotation(text, annotationText));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an annotation with the given name. The annotation will contain the value of the given
|
|
||||||
* ObservableValue. The formatter should return a String and takes an object of the same type as
|
|
||||||
* the ObservableValue as a parameter. The String is how you want the annotation to look.
|
|
||||||
* @param annotationName The annotation name.
|
|
||||||
* @param observable The observable value the annotation will display.
|
|
||||||
* @param formatter A formatting function for the observable value.
|
|
||||||
* @param <E> The type of ObservableValue.
|
|
||||||
*/
|
|
||||||
public <E> void addAnnotation (String annotationName, ObservableValue<E> observable,
|
|
||||||
AnnotationFormatter<E> formatter) {
|
|
||||||
Text newText = getTextObject();
|
|
||||||
addAnnotation(annotationName, new Annotation<>(newText, observable, formatter));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the visibility of the annotation with the given name if it exists.
|
|
||||||
* @param annotationName The name of the annotation
|
|
||||||
* @param visibility the desired visibility
|
|
||||||
*/
|
|
||||||
public void setAnnotationVisibility (String annotationName, boolean visibility) {
|
|
||||||
if (annotationsByName.containsKey(annotationName)) {
|
|
||||||
Text textField = annotationsByName.get(annotationName).text;
|
|
||||||
boolean currentState = textField.visibleProperty().get();
|
|
||||||
if (visibility != currentState) {
|
|
||||||
if (visibility)
|
|
||||||
visibleAnnotations++;
|
|
||||||
else
|
|
||||||
visibleAnnotations--;
|
|
||||||
}
|
|
||||||
textField.setVisible(visibility);
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the annotation with the given name if it exits.
|
|
||||||
* @param annotationName The name given when the annotation was created.
|
|
||||||
*/
|
|
||||||
public void removeAnnotation (String annotationName) {
|
|
||||||
if (annotationName.contains(annotationName)) {
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
this.getChildren().remove(annotationsByName.remove(annotationName).getText());
|
|
||||||
visibleAnnotations--;
|
|
||||||
update();
|
|
||||||
});
|
|
||||||
annotationsByName.remove(annotationName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves the annotation.
|
|
||||||
* @param x x location
|
|
||||||
* @param y y location
|
|
||||||
*/
|
|
||||||
public void setLocation (double x, double y) {
|
|
||||||
Platform.runLater(()-> this.relocate(x + BACKGROUND_X, y + BACKGROUND_Y));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the width of the annotation box. Default is 145.
|
|
||||||
* @param width new width.
|
|
||||||
*/
|
|
||||||
public void setWidth (double width) {
|
|
||||||
backgroundWidth = width;
|
|
||||||
Platform.runLater(() -> background.setWidth(backgroundWidth));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void update () {
|
|
||||||
background.setVisible(visibleAnnotations != 0);
|
|
||||||
background.setHeight(Math.abs(BACKGROUND_X) + TEXT_BUFFER + BACKGROUND_H_PER_TEXT * visibleAnnotations);
|
|
||||||
for (int i = 1; i <= visibleAnnotations; i++) {
|
|
||||||
Text text = (Text) this.getChildren().get(i);
|
|
||||||
if (text.visibleProperty().get()) {
|
|
||||||
text.setX(X_OFFSET_TEXT);
|
|
||||||
text.setY(Y_OFFSET_TEXT_INIT + Y_OFFSET_PER_TEXT * i);
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a text object for an annotation.
|
|
||||||
* @return The text object
|
|
||||||
*/
|
|
||||||
private Text getTextObject() {
|
|
||||||
Text text = new Text();
|
|
||||||
text.setFill(theme);
|
|
||||||
text.setStrokeWidth(2);
|
|
||||||
// text.setCacheHint(CacheHint.QUALITY);
|
|
||||||
text.setCache(true);
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the colour of the annotation box's border and text colour.
|
|
||||||
* @param value desired colour.
|
|
||||||
*/
|
|
||||||
public void setFill (Paint value) {
|
|
||||||
theme = value;
|
|
||||||
background.setStroke(theme);
|
|
||||||
annotationsByName.forEach((name, annotation) -> annotation.getText().setFill(theme));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,10 +16,6 @@ public class Wake extends Group {
|
|||||||
|
|
||||||
//The number of wakes
|
//The number of wakes
|
||||||
private int numWakes = 8;
|
private int numWakes = 8;
|
||||||
//The total possible difference between the first wake and the last. Increasing/Decreasing this will make wakes fan out more/less.
|
|
||||||
private final double MAX_DIFF = 75;
|
|
||||||
//Increasing/decreasing this will alter the speed that wakes converge when the heading stop changing. Anything over about 1500 may cause oscillation.
|
|
||||||
private final int UNIFICATION_SPEED = 45;
|
|
||||||
|
|
||||||
|
|
||||||
private Arc[] arcs = new Arc[numWakes];
|
private Arc[] arcs = new Arc[numWakes];
|
||||||
@@ -69,34 +65,6 @@ public class Wake extends Group {
|
|||||||
rad += (14 / numWakes) + (velocity / 2.5);
|
rad += (14 / numWakes) + (velocity / 2.5);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// } else {
|
|
||||||
// rotations[0] = rotation;
|
|
||||||
// ((Rotate) arcs[0].getTransforms().get(0)).setAngle(rotation);
|
|
||||||
// for (int i = 1; i < numWakes; i++) {
|
|
||||||
// double wakeSeparationRad = Math.toRadians(rotations[i - 1] - rotations[i]);
|
|
||||||
// double shortestDistance = Math.atan2(
|
|
||||||
// Math.sin(wakeSeparationRad),
|
|
||||||
// Math.cos(wakeSeparationRad)
|
|
||||||
// );
|
|
||||||
// double distDeg = Math.toDegrees(shortestDistance);
|
|
||||||
// if (rotationalVelocities[i - 1] < 0.01 && rotationalVelocities[i - 1] > -0.01) {
|
|
||||||
// rotationalVelocities[i] = distDeg / UNIFICATION_SPEED * 2 * Math.log(Math.abs(distDeg) + 1) / Math.log(MAX_DIFF / numWakes);
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// if (distDeg < (MAX_DIFF / numWakes)) {
|
|
||||||
// rotationalVelocities[i] = distDeg / UNIFICATION_SPEED * Math.log(Math.abs(distDeg) + 1) / Math.log(MAX_DIFF / numWakes);
|
|
||||||
// } else
|
|
||||||
// rotationalVelocities[i] = rotationalVelocities[i - 1];
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// double rad = (14 / numWakes) + velocity;
|
|
||||||
// for (Arc arc : arcs) {
|
|
||||||
// arc.setRadiusX(rad);
|
|
||||||
// arc.setRadiusY(rad);
|
|
||||||
// rad += (14 / numWakes) + (velocity / 2.5);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
package seng302.visualiser.fxObjects.assets_2D;
|
|
||||||
|
|
||||||
import javafx.scene.paint.Paint;
|
|
||||||
import javafx.scene.shape.Polyline;
|
|
||||||
import javafx.scene.shape.StrokeLineCap;
|
|
||||||
import javafx.scene.shape.StrokeLineJoin;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by cir27 on 5/09/17.
|
|
||||||
*/
|
|
||||||
public class WindArrow extends Polyline {
|
|
||||||
public WindArrow(Paint fill) {
|
|
||||||
this.getPoints().addAll(
|
|
||||||
-10d, 15d,
|
|
||||||
0d, 25d,
|
|
||||||
0d, -25d,
|
|
||||||
0d, 25d,
|
|
||||||
10d, 15d
|
|
||||||
);
|
|
||||||
this.setStrokeLineCap(StrokeLineCap.ROUND);
|
|
||||||
this.setStroke(fill);
|
|
||||||
this.setStrokeWidth(5);
|
|
||||||
this.setStrokeLineJoin(StrokeLineJoin.ROUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package seng302.visualiser.map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Boundary class represents a rectangle territorial boundary on a map. It
|
|
||||||
* contains four extremity double values(N, E, S, W). N and S are represented as
|
|
||||||
* latitudes in radians. E and W are represented as longitudes in radians.
|
|
||||||
*
|
|
||||||
* Created by Haoming on 10/5/17
|
|
||||||
*/
|
|
||||||
public class Boundary {
|
|
||||||
|
|
||||||
private double northLat, eastLng, southLat, westLng;
|
|
||||||
|
|
||||||
public Boundary(double northLat, double eastLng, double southLat, double westLng) {
|
|
||||||
this.northLat = northLat;
|
|
||||||
this.eastLng = eastLng;
|
|
||||||
this.southLat = southLat;
|
|
||||||
this.westLng = westLng;
|
|
||||||
}
|
|
||||||
|
|
||||||
double getCentreLat() {
|
|
||||||
return (northLat + southLat) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
double getCentreLng() {
|
|
||||||
return (eastLng + westLng) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
double getNorthLat() {
|
|
||||||
return northLat;
|
|
||||||
}
|
|
||||||
|
|
||||||
double getEastLng() {
|
|
||||||
return eastLng;
|
|
||||||
}
|
|
||||||
|
|
||||||
double getSouthLat() {
|
|
||||||
return southLat;
|
|
||||||
}
|
|
||||||
|
|
||||||
double getWestLng() {
|
|
||||||
return westLng;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
package seng302.visualiser.map;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import javafx.geometry.Point2D;
|
|
||||||
import javafx.scene.image.Image;
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
import seng302.model.GeoPoint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CanvasMap retrieves a map image with given geo boundary from Google Map server.
|
|
||||||
* By passing a rectangle like geo boundary, it returns a map image with the
|
|
||||||
* highest resolution. However, due to free quote account usage limit, the maximum
|
|
||||||
* resolution is only 1280 * 1280.
|
|
||||||
*
|
|
||||||
* Created by Haoming on 15/5/2017
|
|
||||||
*/
|
|
||||||
public class CanvasMap {
|
|
||||||
|
|
||||||
private Boundary boundary;
|
|
||||||
private long width, height; // desired image size
|
|
||||||
private int zoom;
|
|
||||||
|
|
||||||
private String KEY = "AIzaSyC-5oOShMCY5Oy_9L7guYMPUPFHDMr37wE";
|
|
||||||
|
|
||||||
public CanvasMap(Boundary boundary) {
|
|
||||||
this.boundary = boundary;
|
|
||||||
calculateOptimalMapSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Image getMapImage() {
|
|
||||||
try {
|
|
||||||
URL url = new URL(getRequest());
|
|
||||||
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
|
|
||||||
|
|
||||||
return new Image(connection.getInputStream());
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("[CanvasMap] Exception");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getRequest() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("https://maps.googleapis.com/maps/api/staticmap?");
|
|
||||||
sb.append(String.format("center=%f,%f", boundary.getCentreLat(), boundary.getCentreLng()));
|
|
||||||
sb.append(String.format("&zoom=%d", zoom));
|
|
||||||
sb.append(String.format("&size=%dx%d&scale=2", width, height));
|
|
||||||
sb.append("&style=feature:all|element:labels|visibility:off"); // hide all labels on map
|
|
||||||
// sb.append(String.format("&markers=%f,%f", boundary.getSouthLat(), boundary.getWestLng()));
|
|
||||||
// sb.append(String.format("&key=%s", KEY));
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calculateOptimalMapSize() {
|
|
||||||
for (int z = 20; z > 0; z--) {
|
|
||||||
MapSize mapSize = getMapSize(z, boundary);
|
|
||||||
zoom = z;
|
|
||||||
width = mapSize.width;
|
|
||||||
height = mapSize.height;
|
|
||||||
// if map size is valid, exit the loop as we have the highest resolution
|
|
||||||
if (mapSize.isValid()) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private MapSize getMapSize(int zoom, Boundary boundary) {
|
|
||||||
double scale = Math.pow(2, zoom);
|
|
||||||
GeoPoint geoSW = new GeoPoint(boundary.getSouthLat(), boundary.getWestLng());
|
|
||||||
GeoPoint geoNE = new GeoPoint(boundary.getNorthLat(), boundary.getEastLng());
|
|
||||||
Point2D pointSW = MercatorProjection.toMapPoint(geoSW);
|
|
||||||
Point2D pointNE = MercatorProjection.toMapPoint(geoNE);
|
|
||||||
return new MapSize(Math.abs(pointNE.getX() - pointSW.getX()) * scale,
|
|
||||||
Math.abs(pointNE.getY() - pointSW.getY()) * scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
class MapSize {
|
|
||||||
long width, height;
|
|
||||||
|
|
||||||
MapSize(double width, double height) {
|
|
||||||
this.width = Math.round(width);
|
|
||||||
this.height = Math.round(height);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map size is valid when width and height are both less than 640 pixels
|
|
||||||
* @return true if both dimensions are less than 640px
|
|
||||||
*/
|
|
||||||
boolean isValid() {
|
|
||||||
return Math.max(width, height) <= 640;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getWidth() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getZoom() {
|
|
||||||
return zoom;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
package seng302.visualiser.map;
|
|
||||||
|
|
||||||
import javafx.geometry.Point2D;
|
|
||||||
import seng302.model.GeoPoint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An utility class useful to convert between Geo locations and Mercator projection
|
|
||||||
* planar coordinates.
|
|
||||||
* Created by Haoming on 15/5/2017
|
|
||||||
*/
|
|
||||||
public class MercatorProjection {
|
|
||||||
|
|
||||||
private static final double MERCATOR_RANGE = 256;
|
|
||||||
private static final double pixelsPerLngDegree = MERCATOR_RANGE / 360.0;
|
|
||||||
private static final double pixelsPerLngRadian = MERCATOR_RANGE / (2 * Math.PI);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A help function keeps the value in bound between -0.9999 and 0.9999.
|
|
||||||
* @param value in bound value
|
|
||||||
* @return the value in bound
|
|
||||||
*/
|
|
||||||
private static double bound(double value) {
|
|
||||||
return Math.min(Math.max(value, -0.9999), 0.9999);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Projects a Geo Location (lat, lng) on a planar
|
|
||||||
* @param geo GeoPoint (lat, lng) location to be projected
|
|
||||||
* @return the projection Point2D (x, y) on planar
|
|
||||||
*/
|
|
||||||
public static Point2D toMapPoint(GeoPoint geo) {
|
|
||||||
double x, y;
|
|
||||||
Point2D origin = new Point2D(MERCATOR_RANGE / 2.0, MERCATOR_RANGE / 2.0);
|
|
||||||
x = (origin.getX() + geo.getLng() * pixelsPerLngDegree);
|
|
||||||
|
|
||||||
// NOTE(appleton): Truncating to 0.9999 effectively limits latitude to
|
|
||||||
// 89.189. This is about a third of a tile past the edge of the world tile.
|
|
||||||
double sinY = bound(Math.sin(Math.toRadians(geo.getLat())));
|
|
||||||
y = origin.getY() + 0.5 * Math.log((1 + sinY) / (1 - sinY)) * (-pixelsPerLngRadian);
|
|
||||||
return new Point2D(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the planar projection (x, y) back to Geo Location (lat, lng)
|
|
||||||
* @param point Point2D (x, y) to be converted back
|
|
||||||
* @return the original Geo location converted from the given projection point
|
|
||||||
*/
|
|
||||||
public static GeoPoint toMapGeo(Point2D point) {
|
|
||||||
Point2D origin = new Point2D(MERCATOR_RANGE / 2.0, MERCATOR_RANGE / 2.0);
|
|
||||||
double lng = (point.getX() - origin.getX()) / pixelsPerLngDegree;
|
|
||||||
double latRadians = (point.getY() - origin.getY()) / (-pixelsPerLngRadian);
|
|
||||||
double lat = Math.toDegrees(2 * Math.atan(Math.exp(latRadians)) - Math.PI / 2.0);
|
|
||||||
return new GeoPoint(lat, lng);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package seng302.visualiser.map;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
import javafx.fxml.FXML;
|
|
||||||
import javafx.fxml.Initializable;
|
|
||||||
import javafx.scene.canvas.Canvas;
|
|
||||||
import javafx.scene.canvas.GraphicsContext;
|
|
||||||
|
|
||||||
public class TestMapController implements Initializable{
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private Canvas mapCanvas;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
|
||||||
GraphicsContext gc = mapCanvas.getGraphicsContext2D();
|
|
||||||
Boundary bound = new Boundary(57.662943, 11.848501, 57.673945, 11.824966);
|
|
||||||
CanvasMap canvasMap = new CanvasMap(bound);
|
|
||||||
gc.drawImage(canvasMap.getMapImage(), 0, 0, canvasMap.getWidth(), canvasMap.getHeight());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package seng302.visualiser.map;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import seng302.model.GeoPoint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit test for Mercator Project class.
|
|
||||||
* Created by hyi25 on 15/05/17.
|
|
||||||
*/
|
|
||||||
public class MercatorProjectionTest {
|
|
||||||
@Test
|
|
||||||
public void toMapPoint() throws Exception {
|
|
||||||
GeoPoint geo1 = new GeoPoint(12.485394, 19.38947);
|
|
||||||
javafx.geometry.Point2D actualPoint1 = MercatorProjection.toMapPoint(geo1);
|
|
||||||
javafx.geometry.Point2D expectedPoint1 = new javafx.geometry.Point2D(141.78806755555556, 119.0503853635612);
|
|
||||||
assertEquals(expectedPoint1.getX(), actualPoint1.getX(), 0.0001);
|
|
||||||
assertEquals(expectedPoint1.getY(), actualPoint1.getY(), 0.0001);
|
|
||||||
|
|
||||||
GeoPoint geo2 = new GeoPoint(77.456432, -23.456462);
|
|
||||||
javafx.geometry.Point2D actualPoint2 = MercatorProjection.toMapPoint(geo2);
|
|
||||||
javafx.geometry.Point2D expectedPoint2 = new javafx.geometry.Point2D(111.31984924444444, 38.03143323746788);
|
|
||||||
assertEquals(expectedPoint2.getX(), actualPoint2.getX(), 0.0001);
|
|
||||||
assertEquals(expectedPoint2.getY(), actualPoint2.getY(), 0.0001);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void toMapGeo() throws Exception {
|
|
||||||
javafx.geometry.Point2D point1 = new javafx.geometry.Point2D(123.1234, 25.4565);
|
|
||||||
GeoPoint actualGeo1 = MercatorProjection.toMapGeo(point1);
|
|
||||||
GeoPoint expectedGeo1 = new GeoPoint(80.77043127275441, -6.857718749999995);
|
|
||||||
assertEquals(expectedGeo1.getLat(), actualGeo1.getLat(), 0.0001);
|
|
||||||
assertEquals(expectedGeo1.getLng(), actualGeo1.getLng(), 0.0001);
|
|
||||||
|
|
||||||
javafx.geometry.Point2D point2 = new javafx.geometry.Point2D(1.235, 255.4565);
|
|
||||||
GeoPoint actualGeo2 = MercatorProjection.toMapGeo(point2);
|
|
||||||
GeoPoint expectedGeo2 = new GeoPoint(-84.98475532898011, -178.26328125);
|
|
||||||
assertEquals(expectedGeo2.getLat(), actualGeo2.getLat(), 0.0001);
|
|
||||||
assertEquals(expectedGeo2.getLng(), actualGeo2.getLng(), 0.0001);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user