diff options
Diffstat (limited to 'src/main/java')
14 files changed, 234 insertions, 28 deletions
diff --git a/src/main/java/com/benburwell/planes/data/Intersection.java b/src/main/java/com/benburwell/planes/data/Intersection.java new file mode 100644 index 0000000..453d6bc --- /dev/null +++ b/src/main/java/com/benburwell/planes/data/Intersection.java @@ -0,0 +1,50 @@ +package com.benburwell.planes.data; + +import org.apache.commons.csv.CSVRecord; + +/** + * @author ben + */ +public class Intersection extends AbstractCSVReader { + private String airway1; + private String airway2; + private String center; + private double latitude; + private double longitude; + private int numberedFix; + + @Override + public void readRecord(CSVRecord record) { + String[] airways = record.get("Airways").split(" "); + this.airway1 = airways[0]; + this.airway2 = airways[1]; + this.center = record.get("Center"); + this.latitude = Double.valueOf(record.get("Latitude")); + this.longitude = Double.valueOf(record.get("Longitude")); + this.numberedFix = Integer.valueOf(record.get("Numbered Fix")); + } + + public String getAirway1() { + return airway1; + } + + public String getAirway2() { + return airway2; + } + + public String getCenter() { + return center; + } + + public double getLatitude() { + return latitude; + } + + public double getLongitude() { + return longitude; + } + + public int getNumberedFix() { + return numberedFix; + } +} diff --git a/src/main/java/com/benburwell/planes/graph/Airway.java b/src/main/java/com/benburwell/planes/graph/Airway.java new file mode 100644 index 0000000..0a40d45 --- /dev/null +++ b/src/main/java/com/benburwell/planes/graph/Airway.java @@ -0,0 +1,29 @@ +package com.benburwell.planes.graph; + +import com.benburwell.planes.data.Position; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author ben + */ +public class Airway { + private String code; + private List<Position> points = new ArrayList<>(); + + public Airway(String code) { + this.code = code; + } + + public void addPoint(double latitude, double longitude) { + Position pos = new Position(); + pos.setLatitude(latitude); + pos.setLongitude(longitude); + this.points.add(pos); + } + + public List<Position> getPoints() { + return this.points; + } +} diff --git a/src/main/java/com/benburwell/planes/graph/RouteGraph.java b/src/main/java/com/benburwell/planes/graph/RouteGraph.java new file mode 100644 index 0000000..34048ac --- /dev/null +++ b/src/main/java/com/benburwell/planes/graph/RouteGraph.java @@ -0,0 +1,29 @@ +package com.benburwell.planes.graph; + +import com.benburwell.planes.data.Intersection; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * @author ben + */ +public class RouteGraph { + private Map<String,Airway> airways = new HashMap<>(); + + public void addIntersection(Intersection in) { + if (!this.airways.containsKey(in.getAirway1())) { + this.airways.put(in.getAirway1(), new Airway(in.getAirway1())); + } + if (!this.airways.containsKey(in.getAirway2())) { + this.airways.put(in.getAirway2(), new Airway(in.getAirway2())); + } + this.airways.get(in.getAirway1()).addPoint(in.getLatitude(), in.getLongitude()); + this.airways.get(in.getAirway2()).addPoint(in.getLatitude(), in.getLongitude()); + } + + public Collection<Airway> getAirways() { + return this.airways.values(); + } +} diff --git a/src/main/java/com/benburwell/planes/gui/GraphicsTheme.java b/src/main/java/com/benburwell/planes/gui/GraphicsTheme.java index 02d75ba..f4a6525 100644 --- a/src/main/java/com/benburwell/planes/gui/GraphicsTheme.java +++ b/src/main/java/com/benburwell/planes/gui/GraphicsTheme.java @@ -24,4 +24,16 @@ public class GraphicsTheme { public static final Color CYAN = new Color(51, 133, 158); public static final Color GREEN = new Color(42, 168, 137); } + + public static class Styles { + public static final Color MAP_BACKGROUND_COLOR = Colors.BASE_0; + public static final Color MAP_RANGE_COLOR = Colors.BASE_3; + public static final Color MAP_NAVAID_COLOR = Colors.VIOLET; + public static final Color MAP_AIRPORT_COLOR = Colors.MAGENTA; + public static final Color MAP_ROUTE_COLOR = Colors.BASE_2; + public static final Color MAP_LABEL_COLOR = Colors.BLUE; + public static final Color MAP_PLANE_MIN_COLOR = Colors.RED; + public static final Color MAP_PLANE_MAX_COLOR = Colors.GREEN; + public static final Color MAP_PLANE_TRACK_COLOR = Colors.BASE_4; + } } diff --git a/src/main/java/com/benburwell/planes/gui/Main1090.java b/src/main/java/com/benburwell/planes/gui/Main1090.java index a48fb93..ac75d03 100644 --- a/src/main/java/com/benburwell/planes/gui/Main1090.java +++ b/src/main/java/com/benburwell/planes/gui/Main1090.java @@ -4,10 +4,8 @@ package com.benburwell.planes.gui; -import com.benburwell.planes.data.AircraftStore; -import com.benburwell.planes.data.Airport; -import com.benburwell.planes.data.CSVObjectStore; -import com.benburwell.planes.data.NavigationAid; +import com.benburwell.planes.data.*; +import com.benburwell.planes.graph.RouteGraph; import com.benburwell.planes.gui.aircraftmap.AircraftMapComponent; import com.benburwell.planes.gui.aircrafttable.AircraftTableComponent; import com.benburwell.planes.gui.airportstable.AirportsComponent; @@ -31,6 +29,7 @@ public class Main1090 extends JFrame { private AircraftStore aircraft = new AircraftStore(); private CSVObjectStore<NavigationAid> navaids = new CSVObjectStore<>(); private CSVObjectStore<Airport> airports = new CSVObjectStore<>(); + private RouteGraph routeGraph = new RouteGraph(); private int currentTcpConnection = 0; private JTabbedPane tabbedPane = new JTabbedPane(); @@ -60,12 +59,20 @@ public class Main1090 extends JFrame { System.out.println("Could not read airport file: " + e.getMessage()); } + try { + CSVObjectStore<Intersection> intersections = new CSVObjectStore<>(); + intersections.readFromResource("/airways_db.csv", Intersection.class); + intersections.getObjects().forEach(intersection -> this.routeGraph.addIntersection(intersection)); + } catch (IOException | InstantiationException | IllegalAccessException e) { + System.out.println("Could not read route intersection file: " + e.getMessage()); + } + this.createTabs(); } private void createTabs() { List<Tabbable> tabs = new ArrayList<>(); - tabs.add(new AircraftMapComponent(this.aircraft, this.navaids, this.airports)); + tabs.add(new AircraftMapComponent(this.aircraft, this.navaids, this.airports, this.routeGraph)); tabs.add(new AircraftTableComponent(this.aircraft)); tabs.add(new NavigationAidComponent(this.navaids)); tabs.add(new AirportsComponent(this.airports)); diff --git a/src/main/java/com/benburwell/planes/gui/aircraftmap/AircraftMap.java b/src/main/java/com/benburwell/planes/gui/aircraftmap/AircraftMap.java index 72edaaf..cb8ed3c 100644 --- a/src/main/java/com/benburwell/planes/gui/aircraftmap/AircraftMap.java +++ b/src/main/java/com/benburwell/planes/gui/aircraftmap/AircraftMap.java @@ -3,12 +3,9 @@ package com.benburwell.planes.gui.aircraftmap; import com.benburwell.planes.data.Airport; import com.benburwell.planes.data.NavigationAid; import com.benburwell.planes.data.Position; +import com.benburwell.planes.graph.RouteGraph; import com.benburwell.planes.gui.GraphicsTheme; -import com.benburwell.planes.gui.aircraftmap.symbols.AirportSymbol; -import com.benburwell.planes.gui.aircraftmap.symbols.NDBSymbol; -import com.benburwell.planes.gui.aircraftmap.symbols.VORDMESymbol; -import com.benburwell.planes.gui.aircraftmap.symbols.VORSymbol; -import com.benburwell.planes.gui.aircraftmap.symbols.VORTACSymbol; +import com.benburwell.planes.gui.aircraftmap.symbols.*; import javax.swing.BorderFactory; import javax.swing.JPanel; @@ -53,18 +50,20 @@ public class AircraftMap extends JPanel { private List<Drawable> planes = new ArrayList<>(); private List<Drawable> navaids = new ArrayList<>(); private List<Drawable> airports = new ArrayList<>(); + private List<Drawable> routes = new ArrayList<>(); private double centerLatitude; private double centerLongitude; private int pixelsPerNauticalMile = 10; private boolean showNavAids = true; private boolean showAirports = true; + private boolean showRoutes = true; /** * Construct a map */ public AircraftMap() { super(); - this.setBackground(GraphicsTheme.Colors.BASE_1); + this.setBackground(GraphicsTheme.Styles.MAP_BACKGROUND_COLOR); this.setBorder(BorderFactory.createEmptyBorder()); this.setCenter(0, 0); } @@ -110,6 +109,10 @@ public class AircraftMap extends JPanel { }); } + public void addRoutes(RouteGraph routes) { + routes.getAirways().forEach(airway -> this.routes.add(new RouteSymbol(airway))); + } + /** * Paint the Tabbable on a Graphics instance * @@ -120,15 +123,29 @@ public class AircraftMap extends JPanel { super.paintComponent(g); Graphics2D g2d = (Graphics2D)g.create(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + // Base layer -- Routes + if (this.showRoutes) { + this.routes.forEach(route -> route.drawOn(g2d, this)); + } + + // Compass rose this.drawPositionAndScale(g2d); this.drawRange(g2d); + + // Aids to Navigation if (this.showNavAids) { this.navaids.forEach(aid -> aid.drawOn(g2d, this)); } + + // Airports if (this.showAirports) { this.airports.forEach(airport -> airport.drawOn(g2d, this)); } + + // Planes this.planes.forEach(item -> item.drawOn(g2d, this)); + g2d.dispose(); } @@ -142,11 +159,16 @@ public class AircraftMap extends JPanel { this.redraw(); } + public void toggleRoutes() { + this.showRoutes = !this.showRoutes; + this.redraw(); + } + private void drawPositionAndScale(Graphics g) { Font currentFont = g.getFont(); Font newFont = currentFont.deriveFont(FONT_SIZE); g.setFont(newFont); - g.setColor(GraphicsTheme.Colors.BLUE); + g.setColor(GraphicsTheme.Styles.MAP_LABEL_COLOR); g.drawString(String.format("%08.5f N", this.centerLatitude), TEXT_PADDING, (int) FONT_SIZE + TEXT_PADDING); g.drawString(String.format("%08.5f E", this.centerLongitude), TEXT_PADDING, (int) FONT_SIZE * 2 + TEXT_PADDING); g.drawString(String.format("%d nm", this.getRangeRadius()), TEXT_PADDING, (int) FONT_SIZE * 3 + TEXT_PADDING); @@ -172,7 +194,7 @@ public class AircraftMap extends JPanel { private void drawRange(Graphics g) { int centerX = this.getWidth() / 2; int centerY = this.getHeight() / 2; - g.setColor(GraphicsTheme.Colors.BASE_3); + g.setColor(GraphicsTheme.Styles.MAP_RANGE_COLOR); for (Integer radius : this.getRangeRadii()) { int pixelRadius = (int) (this.getPixelsPerNauticalMile() * radius); g.drawOval(centerX - pixelRadius, centerY - pixelRadius, pixelRadius * 2, pixelRadius * 2); @@ -256,4 +278,5 @@ public class AircraftMap extends JPanel { this.centerLatitude = Math.max(this.centerLatitude - degreesToMove, MIN_LATITUDE); this.redraw(); } + } diff --git a/src/main/java/com/benburwell/planes/gui/aircraftmap/AircraftMapComponent.java b/src/main/java/com/benburwell/planes/gui/aircraftmap/AircraftMapComponent.java index 48f8cfd..db3e603 100644 --- a/src/main/java/com/benburwell/planes/gui/aircraftmap/AircraftMapComponent.java +++ b/src/main/java/com/benburwell/planes/gui/aircraftmap/AircraftMapComponent.java @@ -1,10 +1,7 @@ package com.benburwell.planes.gui.aircraftmap; -import com.benburwell.planes.data.AircraftStore; -import com.benburwell.planes.data.AircraftStoreListener; -import com.benburwell.planes.data.Airport; -import com.benburwell.planes.data.CSVObjectStore; -import com.benburwell.planes.data.NavigationAid; +import com.benburwell.planes.data.*; +import com.benburwell.planes.graph.RouteGraph; import com.benburwell.planes.gui.Tabbable; import com.benburwell.planes.gui.aircraftmap.symbols.PlaneSymbol; @@ -27,7 +24,7 @@ public class AircraftMapComponent implements Tabbable { private AircraftMap mapPanel; private AircraftStoreListener aircraftStoreListener; - public AircraftMapComponent(AircraftStore store, CSVObjectStore<NavigationAid> navaids, CSVObjectStore<Airport> airportStore) { + public AircraftMapComponent(AircraftStore store, CSVObjectStore<NavigationAid> navaids, CSVObjectStore<Airport> airportStore, RouteGraph routeGraph) { this.store = store; this.setupMap(); @@ -37,6 +34,7 @@ public class AircraftMapComponent implements Tabbable { this.store.subscribe(this.aircraftStoreListener); this.mapPanel.addNavAids(navaids.getObjects()); this.mapPanel.addAirports(airportStore.getObjects()); + this.mapPanel.addRoutes(routeGraph); final Timer t = new Timer(MAX_REFRESH_MILLIS, e -> { AircraftMapComponent.this.aircraftStoreListener.aircraftStoreChanged(); @@ -69,6 +67,8 @@ public class AircraftMapComponent implements Tabbable { this.mapPanel.toggleNavAids(); } else if (e.getKeyCode() == KeyEvent.VK_A && e.getID() == KeyEvent.KEY_PRESSED) { this.mapPanel.toggleAirports(); + } else if (e.getKeyCode() == KeyEvent.VK_R && e.getID() == KeyEvent.KEY_PRESSED) { + this.mapPanel.toggleRoutes(); } return false; }); diff --git a/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/AirportSymbol.java b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/AirportSymbol.java index b97a7fa..7467a0f 100644 --- a/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/AirportSymbol.java +++ b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/AirportSymbol.java @@ -39,7 +39,7 @@ public class AirportSymbol extends GeoPoint implements Drawable { int x = this.getX(map); int y = this.getY(map); - g.setColor(GraphicsTheme.Colors.MAGENTA); + g.setColor(GraphicsTheme.Styles.MAP_AIRPORT_COLOR); g.drawRect(x - 2, y - 2, 4, 4); g.drawString(this.getDisplayName(), x + 6, y); diff --git a/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/NDBSymbol.java b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/NDBSymbol.java index 74f4441..e3b23f5 100644 --- a/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/NDBSymbol.java +++ b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/NDBSymbol.java @@ -28,7 +28,7 @@ public class NDBSymbol extends GeoPoint implements Drawable { @Override public void drawOn(Graphics g, AircraftMap map) { if (this.shouldDrawOn(map)) { - g.setColor(GraphicsTheme.Colors.VIOLET); + g.setColor(GraphicsTheme.Styles.MAP_NAVAID_COLOR); int x = this.getX(map); int y = this.getY(map); diff --git a/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/PlaneSymbol.java b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/PlaneSymbol.java index 3e6b51c..a522b04 100644 --- a/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/PlaneSymbol.java +++ b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/PlaneSymbol.java @@ -50,8 +50,8 @@ public class PlaneSymbol extends GeoPoint implements Drawable { } public Color getPlaneColor() { - Color minColor = GraphicsTheme.Colors.RED; - Color maxColor = GraphicsTheme.Colors.GREEN; + Color minColor = GraphicsTheme.Styles.MAP_PLANE_MIN_COLOR; + Color maxColor = GraphicsTheme.Styles.MAP_PLANE_MAX_COLOR; float[] minHsb = Color.RGBtoHSB(minColor.getRed(), minColor.getGreen(), minColor.getBlue(), null); float[] maxHsb = Color.RGBtoHSB(maxColor.getRed(), maxColor.getGreen(), maxColor.getBlue(), null); @@ -123,14 +123,14 @@ public class PlaneSymbol extends GeoPoint implements Drawable { g2d.dispose(); // draw the history track - g.setColor(GraphicsTheme.Colors.BASE_4); + g.setColor(GraphicsTheme.Styles.MAP_PLANE_TRACK_COLOR); this.historyTrack.forEach(pos -> { GeoPoint p = new GeoPoint(pos); g.fillRect(p.getX(map) - 2, p.getY(map) - 2, 4, 4); }); // draw the name of the plane - g.setColor(GraphicsTheme.Colors.BASE_5); + g.setColor(GraphicsTheme.Styles.MAP_LABEL_COLOR); g.drawString(this.getDisplayName(), x + TEXT_OFFSET_X, y + TEXT_OFFSET_Y); String infoString = String.format("%d%s %.1f", this.getFlightLevel(), this.getVerticalRateIndicator(), this.getSpeed()); g.drawString(infoString, x + TEXT_OFFSET_X, y + TEXT_OFFSET_Y + g.getFontMetrics().getHeight()); diff --git a/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/RouteSymbol.java b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/RouteSymbol.java new file mode 100644 index 0000000..edd622a --- /dev/null +++ b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/RouteSymbol.java @@ -0,0 +1,56 @@ +package com.benburwell.planes.gui.aircraftmap.symbols; + +import com.benburwell.planes.graph.Airway; +import com.benburwell.planes.gui.GraphicsTheme; +import com.benburwell.planes.gui.aircraftmap.AircraftMap; +import com.benburwell.planes.gui.aircraftmap.Drawable; +import com.benburwell.planes.gui.aircraftmap.GeoPoint; + +import java.awt.Graphics; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author ben + */ +public class RouteSymbol implements Drawable { + private final Airway airway; + + public RouteSymbol(Airway airway) { + this.airway = airway; + } + + private boolean inRange(int lo, int n, int hi) { + return lo <= n && n <= hi; + } + + @Override + public void drawOn(Graphics graphicsContext, AircraftMap map) { + int w = map.getWidth(); + int h = map.getHeight(); + graphicsContext.setColor(GraphicsTheme.Styles.MAP_ROUTE_COLOR); + List<GeoPoint> points = this.airway.getPoints().stream().map(GeoPoint::new).collect(Collectors.toList()); + for (int i = 0; i < points.size() - 1; i++) { + GeoPoint p1 = points.get(i); + int p1x = p1.getX(map); + int p1y = p1.getY(map); + + GeoPoint p2 = points.get(i + 1); + int p2x = p2.getX(map); + int p2y = p2.getY(map); + + boolean p1OnMap = inRange(0, p1x, w) && inRange(0, p1y, h); + boolean p2OnMap = inRange(0, p2x, w) && inRange(0, p2y, h); + boolean showEdge = p1OnMap || p2OnMap; + if (showEdge) { + graphicsContext.drawLine(p1x, p1y, p2x, p2y); + graphicsContext.fillOval(p1x - 2, p1y - 2, 4, 4); + } + } + int pnx = points.get(points.size() - 1).getX(map); + int pny = points.get(points.size() - 1).getY(map); + if (inRange(0, pnx, w) && inRange(0, pny, h)) { + graphicsContext.fillOval(pnx - 2, pny - 2, 4, 4); + } + } +} diff --git a/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/VORDMESymbol.java b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/VORDMESymbol.java index b4edc28..6b12260 100644 --- a/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/VORDMESymbol.java +++ b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/VORDMESymbol.java @@ -21,7 +21,7 @@ public class VORDMESymbol extends VORSymbol implements Drawable { if (this.shouldDrawOn(map)) { int x = this.getX(map); int y = this.getY(map); - graphicsContext.setColor(GraphicsTheme.Colors.VIOLET); + graphicsContext.setColor(GraphicsTheme.Styles.MAP_NAVAID_COLOR); graphicsContext.drawRect(x - VORSymbol.RADIUS, y - VORSymbol.HEIGHT, VORSymbol.RADIUS * 2, VORSymbol.HEIGHT * 2); } } diff --git a/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/VORSymbol.java b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/VORSymbol.java index 5164248..f4a73dc 100644 --- a/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/VORSymbol.java +++ b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/VORSymbol.java @@ -32,7 +32,7 @@ public class VORSymbol extends GeoPoint implements Drawable { if (this.shouldDrawOn(map)) { int x = this.getX(map); int y = this.getY(map); - graphicsContext.setColor(GraphicsTheme.Colors.VIOLET); + graphicsContext.setColor(GraphicsTheme.Styles.MAP_NAVAID_COLOR); // center dot graphicsContext.fillOval(x - DOT_RADIUS, y - DOT_RADIUS, DOT_RADIUS * 2, DOT_RADIUS * 2); diff --git a/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/VORTACSymbol.java b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/VORTACSymbol.java index a8d0bdb..1ca1290 100644 --- a/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/VORTACSymbol.java +++ b/src/main/java/com/benburwell/planes/gui/aircraftmap/symbols/VORTACSymbol.java @@ -21,7 +21,7 @@ public class VORTACSymbol extends VORSymbol implements Drawable { if (this.shouldDrawOn(map)) { int x = this.getX(map); int y = this.getY(map); - graphicsContext.setColor(GraphicsTheme.Colors.VIOLET); + graphicsContext.setColor(GraphicsTheme.Styles.MAP_NAVAID_COLOR); int[] xs = { x - VORSymbol.X_OFFSET, x + VORSymbol.X_OFFSET, x + VORSymbol.X_OFFSET, x - VORSymbol.X_OFFSET, x - VORSymbol.X_OFFSET }; int[] ys = { y + VORSymbol.RADIUS, y + VORSymbol.RADIUS, y + VORSymbol.RADIUS * 2, y + VORSymbol.RADIUS * 2, y + VORSymbol.RADIUS }; |