summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Burwell <ben.burwell@trifecta.com>2016-11-19 12:32:17 -0500
committerBen Burwell <ben.burwell@trifecta.com>2016-11-19 12:32:17 -0500
commitb8c30e5edd18fc830b944431fda32334af1f9801 (patch)
tree9ac8bda83a7f807b7184902ec18f2fbbe3e80918
parent7a2a21ec5120d2c0edadaab405ff9256a4b75635 (diff)
Refactor aircraft map into top-level classes
-rw-r--r--src/com/benburwell/planes/gui/AircraftMapComponent.java297
-rw-r--r--src/com/benburwell/planes/gui/aircraftmap/AircraftMap.java144
-rw-r--r--src/com/benburwell/planes/gui/aircraftmap/AircraftMapComponent.java118
-rw-r--r--src/com/benburwell/planes/gui/aircraftmap/Drawable.java10
-rw-r--r--src/com/benburwell/planes/gui/aircraftmap/GeoPoint.java30
-rw-r--r--src/com/benburwell/planes/gui/aircraftmap/Plane.java37
6 files changed, 339 insertions, 297 deletions
diff --git a/src/com/benburwell/planes/gui/AircraftMapComponent.java b/src/com/benburwell/planes/gui/AircraftMapComponent.java
deleted file mode 100644
index cf966b6..0000000
--- a/src/com/benburwell/planes/gui/AircraftMapComponent.java
+++ /dev/null
@@ -1,297 +0,0 @@
-package com.benburwell.planes.gui;
-
-import com.benburwell.planes.data.AircraftStore;
-import com.benburwell.planes.data.AircraftStoreListener;
-import com.benburwell.planes.data.Position;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.KeyEvent;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Collections;
-
-/**
- * Created by ben on 11/18/16.
- */
-public class AircraftMapComponent implements ViewComponent {
- private AircraftStore store;
- private AircraftMap mapPanel;
- private String focusedAircraftIdentifier = null;
-
- public AircraftMapComponent(AircraftStore store) {
- this.store = store;
- this.setupMap();
- this.bindKeys();
- this.subscribeToChanges();
- }
-
- public void focusNextAircraft() {
- List<String> aircraftIdentifiers = new ArrayList<>(this.store.getAircraft().keySet());
- Collections.sort(aircraftIdentifiers);
- if (this.focusedAircraftIdentifier == null && aircraftIdentifiers.size() > 0) {
- this.focusedAircraftIdentifier = aircraftIdentifiers.get(0);
- } else {
- int idx = aircraftIdentifiers.indexOf(this.focusedAircraftIdentifier);
- if (idx > 0 && idx < aircraftIdentifiers.size() - 1) {
- this.focusedAircraftIdentifier = aircraftIdentifiers.get(idx++);
- } else if (aircraftIdentifiers.size() > 0) {
- this.focusedAircraftIdentifier = aircraftIdentifiers.get(0);
- } else {
- this.focusedAircraftIdentifier = null;
- }
- }
- }
-
- private void setupMap() {
- this.mapPanel = new AircraftMap();
- this.mapPanel.setCenter(40.6188942, -75.4947205);
- }
-
- private void bindKeys() {
- KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(e -> {
- if (e.getKeyCode() == KeyEvent.VK_EQUALS && e.isShiftDown() && e.getID() == KeyEvent.KEY_PRESSED) {
- this.mapPanel.zoomIn();
- } else if (e.getKeyCode() == KeyEvent.VK_MINUS && e.getID() == KeyEvent.KEY_PRESSED) {
- this.mapPanel.zoomOut();
- } else if (e.getKeyCode() == KeyEvent.VK_L && e.getID() == KeyEvent.KEY_PRESSED) {
- this.mapPanel.moveEast();
- } else if (e.getKeyCode() == KeyEvent.VK_H && e.getID() == KeyEvent.KEY_PRESSED) {
- this.mapPanel.moveWest();
- } else if (e.getKeyCode() == KeyEvent.VK_J && e.getID() == KeyEvent.KEY_PRESSED) {
- this.mapPanel.moveSouth();
- } else if (e.getKeyCode() == KeyEvent.VK_K && e.getID() == KeyEvent.KEY_PRESSED) {
- this.mapPanel.moveNorth();
- } else if (e.getKeyCode() == KeyEvent.VK_0 && e.getID() == KeyEvent.KEY_PRESSED) {
- this.mapPanel.setCenter(40.6188942, -75.4947205);
- } else if (e.getKeyCode() == KeyEvent.VK_TAB && e.getID() == KeyEvent.KEY_PRESSED) {
- this.focusNextAircraft();
- this.centerMapOnPlane(this.focusedAircraftIdentifier);
- }
- return false;
- });
- }
-
- private void centerMapOnPlane(String identifier) {
- if (identifier != null) {
- Position pos = this.store.getAircraft().get(identifier).getCurrentPosition();
- this.mapPanel.setCenter(pos.getLatitude(), pos.getLongitude());
- }
- }
-
- private void subscribeToChanges() {
- this.store.subscribe(new AircraftStoreListener() {
- @Override
- public void aircraftStoreChanged() {
- List<Drawable> planes = new ArrayList<>();
- store.getAircraft().values().forEach(aircraft -> {
- String name = !aircraft.getCallsign().isEmpty() ? aircraft.getCallsign() : aircraft.getHexIdent();
- double lat = aircraft.getCurrentPosition().getLatitude();
- double lon = aircraft.getCurrentPosition().getLongitude();
- planes.add(new Plane(name, lat, lon));
- });
- mapPanel.setPlanes(planes);
- mapPanel.validate();
- mapPanel.repaint();
- }
-
- @Override
- public boolean respondTo(String aircraftId) {
- return true;
- }
- });
- }
-
- @Override
- public JComponent getComponent() {
- return this.mapPanel;
- }
-
- private class AircraftMap extends JPanel {
- // geographic constants
- private final double MAX_LATITUDE = 90.0;
- private final double MIN_LATITUDE = -90.0;
- private final double MAX_LONGITUDE = 180.0;
- private final double MIN_LONGITUDE = -180.0;
- private final double NAUTICAL_MILES_PER_DEGREE_LATITUDE = 60.0;
-
- private final float FONT_SIZE = 12;
- private final int TEXT_PADDING = 5;
- private final int ZOOM_INTERVAL = 10;
- private final double PAN_INTERVAL = 1.0 / 60.0;
- private final int RING_SPACING = 10;
- private List<Drawable> planes = new ArrayList<>();
- private double centerLatitude;
- private double centerLongitude;
- private int pixelsPerNauticalMile = 10;
-
- public AircraftMap() {
- super();
- this.setBackground(GraphicsTheme.Colors.BASE_1);
- this.setBorder(BorderFactory.createEmptyBorder());
- this.setCenter(0, 0);
- }
-
- @Override
- public void paintComponent(Graphics g) {
- super.paintComponent(g);
- this.planes.forEach(item -> item.drawOn(g, this));
- this.drawPositionAndScale(g);
- this.drawRange(g);
- }
-
- public void drawPositionAndScale(Graphics g) {
- Font currentFont = g.getFont();
- Font newFont = currentFont.deriveFont(FONT_SIZE);
- g.setFont(newFont);
- g.setColor(GraphicsTheme.Colors.BLUE);
- 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);
- }
-
- public void drawRange(Graphics g) {
- int centerX = this.getWidth() / 2;
- int centerY = this.getHeight() / 2;
- g.setColor(GraphicsTheme.Colors.BASE_3);
- int diameter = (int) this.getPixelsPerNauticalMile() * RING_SPACING;
- int ringNumber = 1;
- while (diameter < this.getWidth() || diameter < this.getHeight()) {
- g.drawOval(centerX - (diameter / 2), centerY - (diameter / 2), diameter, diameter);
- g.drawString(String.format("%d", ringNumber * RING_SPACING), centerX + (diameter / 2) + TEXT_PADDING, (int) (centerY + FONT_SIZE + TEXT_PADDING));
- g.drawString(String.format("%d", ringNumber * RING_SPACING), centerX + TEXT_PADDING, centerY - (int) ((diameter / 2) + FONT_SIZE));
- diameter += this.getPixelsPerNauticalMile() * 10;
- ringNumber++;
- }
- g.drawLine(centerX, 0, centerX, this.getHeight());
- g.drawLine(0, centerY, this.getWidth(), centerY);
- }
-
- public void setPlanes(List<Drawable> planes) {
- this.planes = planes;
- this.invalidate();
- }
-
- public void setCenter(double latitude, double longitude) {
- this.centerLatitude = latitude;
- this.centerLongitude = longitude;
- }
-
- public double getCenterLatitude() {
- return this.centerLatitude;
- }
-
- public double getCenterLongitude() {
- return this.centerLongitude;
- }
-
- public double getPixelsPerDegreeLatitude() {
- return this.pixelsPerNauticalMile * NAUTICAL_MILES_PER_DEGREE_LATITUDE;
- }
-
- public double getPixelsPerDegreeLongitude() {
- double milesPerDegree = Math.abs(Math.cos(this.centerLatitude) * NAUTICAL_MILES_PER_DEGREE_LATITUDE);
- return this.pixelsPerNauticalMile * milesPerDegree;
- }
-
- public double getPixelsPerNauticalMile() {
- return this.pixelsPerNauticalMile;
- }
-
- public void zoomIn() {
- this.pixelsPerNauticalMile += ZOOM_INTERVAL;
- this.invalidate();
- this.validate();
- this.repaint();
- }
-
- public void zoomOut() {
- this.pixelsPerNauticalMile -= ZOOM_INTERVAL;
- this.invalidate();
- this.validate();
- this.repaint();
- }
-
- public void moveEast() {
- this.centerLongitude = Math.min(this.centerLongitude + PAN_INTERVAL, MAX_LONGITUDE);
- this.invalidate();
- this.validate();
- this.repaint();
- }
-
- public void moveWest() {
- this.centerLongitude = Math.max(this.centerLongitude - PAN_INTERVAL, MIN_LONGITUDE);
- this.invalidate();
- this.validate();
- this.repaint();
- }
-
- public void moveNorth() {
- this.centerLatitude = Math.min(this.centerLatitude + PAN_INTERVAL, MAX_LATITUDE);
- this.invalidate();
- this.validate();
- this.repaint();
- }
-
- public void moveSouth() {
- this.centerLatitude = Math.max(this.centerLatitude - PAN_INTERVAL, MIN_LATITUDE);
- this.invalidate();
- this.validate();
- this.repaint();
- }
- }
-
- private interface Drawable {
- void drawOn(Graphics graphicsContext, AircraftMap map);
- }
-
- private class GeoPoint {
- private double latitude;
- private double longitude;
-
- public GeoPoint(double latitude, double longitude) {
- this.latitude = latitude;
- this.longitude = longitude;
- }
-
- public int getX(AircraftMap map) {
- double degreesFromCenter = map.getCenterLongitude() - this.longitude;
- double pixelsFromCenter = degreesFromCenter * map.getPixelsPerDegreeLongitude();
- double centerPixels = map.getSize().getWidth() / 2;
- int xPosition = (int)(centerPixels - pixelsFromCenter);
- return xPosition;
- }
-
- public int getY(AircraftMap map) {
- double degreesFromCenter = map.getCenterLatitude() - this.latitude;
- double pixelsFromCenter = degreesFromCenter * map.getPixelsPerDegreeLatitude();
- double centerPixels = map.getSize().getHeight() / 2;
- int yPosition = (int)(centerPixels + pixelsFromCenter);
- return yPosition;
- }
- }
-
- private class Plane extends GeoPoint implements Drawable {
- private String name;
- private final int DOT_DIMENSION = 10;
- private final int TEXT_OFFSET_X = 10;
- private final int TEXT_OFFSET_Y = 15;
-
- public Plane(String name, double latitude, double longitude) {
- super(latitude, longitude);
- this.name = name;
- }
-
- public void drawOn(Graphics g, AircraftMap map) {
- int x = this.getX(map);
- int y = this.getY(map);
-
- // draw the plane dot
- g.setColor(GraphicsTheme.Colors.ORANGE);
- g.fillOval(x - (DOT_DIMENSION / 2), y - (DOT_DIMENSION / 2), DOT_DIMENSION, DOT_DIMENSION);
-
- // draw the name of the plane
- g.setColor(GraphicsTheme.Colors.BLUE);
- g.drawString(this.name, this.getX(map) + TEXT_OFFSET_X, this.getY(map) + TEXT_OFFSET_Y);
- }
- }
-}
diff --git a/src/com/benburwell/planes/gui/aircraftmap/AircraftMap.java b/src/com/benburwell/planes/gui/aircraftmap/AircraftMap.java
new file mode 100644
index 0000000..127f9c8
--- /dev/null
+++ b/src/com/benburwell/planes/gui/aircraftmap/AircraftMap.java
@@ -0,0 +1,144 @@
+package com.benburwell.planes.gui.aircraftmap;
+
+import com.benburwell.planes.gui.GraphicsTheme;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by ben on 11/19/16.
+ */
+public class AircraftMap extends JPanel {
+ // geographic constants
+ private final double MAX_LATITUDE = 90.0;
+ private final double MIN_LATITUDE = -90.0;
+ private final double MAX_LONGITUDE = 180.0;
+ private final double MIN_LONGITUDE = -180.0;
+ private final double NAUTICAL_MILES_PER_DEGREE_LATITUDE = 60.0;
+
+ private final float FONT_SIZE = 12;
+ private final int TEXT_PADDING = 5;
+ private final int ZOOM_INTERVAL = 10;
+ private final double PAN_INTERVAL = 1.0 / 60.0;
+ private final int RING_SPACING = 10;
+ private List<Drawable> planes = new ArrayList<>();
+ private double centerLatitude;
+ private double centerLongitude;
+ private int pixelsPerNauticalMile = 10;
+
+ public AircraftMap() {
+ super();
+ this.setBackground(GraphicsTheme.Colors.BASE_1);
+ this.setBorder(BorderFactory.createEmptyBorder());
+ this.setCenter(0, 0);
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ this.planes.forEach(item -> item.drawOn(g, this));
+ this.drawPositionAndScale(g);
+ this.drawRange(g);
+ }
+
+ public void drawPositionAndScale(Graphics g) {
+ Font currentFont = g.getFont();
+ Font newFont = currentFont.deriveFont(FONT_SIZE);
+ g.setFont(newFont);
+ g.setColor(GraphicsTheme.Colors.BLUE);
+ 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);
+ }
+
+ public void drawRange(Graphics g) {
+ int centerX = this.getWidth() / 2;
+ int centerY = this.getHeight() / 2;
+ g.setColor(GraphicsTheme.Colors.BASE_3);
+ int diameter = (int) this.getPixelsPerNauticalMile() * RING_SPACING;
+ int ringNumber = 1;
+ while (diameter < this.getWidth() || diameter < this.getHeight()) {
+ g.drawOval(centerX - (diameter / 2), centerY - (diameter / 2), diameter, diameter);
+ g.drawString(String.format("%d", ringNumber * RING_SPACING), centerX + (diameter / 2) + TEXT_PADDING, (int) (centerY + FONT_SIZE + TEXT_PADDING));
+ g.drawString(String.format("%d", ringNumber * RING_SPACING), centerX + TEXT_PADDING, centerY - (int) ((diameter / 2) + FONT_SIZE));
+ diameter += this.getPixelsPerNauticalMile() * 10;
+ ringNumber++;
+ }
+ g.drawLine(centerX, 0, centerX, this.getHeight());
+ g.drawLine(0, centerY, this.getWidth(), centerY);
+ }
+
+ public void setPlanes(List<Drawable> planes) {
+ this.planes = planes;
+ this.invalidate();
+ }
+
+ public void setCenter(double latitude, double longitude) {
+ this.centerLatitude = latitude;
+ this.centerLongitude = longitude;
+ }
+
+ public double getCenterLatitude() {
+ return this.centerLatitude;
+ }
+
+ public double getCenterLongitude() {
+ return this.centerLongitude;
+ }
+
+ public double getPixelsPerDegreeLatitude() {
+ return this.pixelsPerNauticalMile * NAUTICAL_MILES_PER_DEGREE_LATITUDE;
+ }
+
+ public double getPixelsPerDegreeLongitude() {
+ double milesPerDegree = Math.abs(Math.cos(this.centerLatitude) * NAUTICAL_MILES_PER_DEGREE_LATITUDE);
+ return this.pixelsPerNauticalMile * milesPerDegree;
+ }
+
+ public double getPixelsPerNauticalMile() {
+ return this.pixelsPerNauticalMile;
+ }
+
+ public void zoomIn() {
+ this.pixelsPerNauticalMile += ZOOM_INTERVAL;
+ this.invalidate();
+ this.validate();
+ this.repaint();
+ }
+
+ public void zoomOut() {
+ this.pixelsPerNauticalMile -= ZOOM_INTERVAL;
+ this.invalidate();
+ this.validate();
+ this.repaint();
+ }
+
+ public void moveEast() {
+ this.centerLongitude = Math.min(this.centerLongitude + PAN_INTERVAL, MAX_LONGITUDE);
+ this.invalidate();
+ this.validate();
+ this.repaint();
+ }
+
+ public void moveWest() {
+ this.centerLongitude = Math.max(this.centerLongitude - PAN_INTERVAL, MIN_LONGITUDE);
+ this.invalidate();
+ this.validate();
+ this.repaint();
+ }
+
+ public void moveNorth() {
+ this.centerLatitude = Math.min(this.centerLatitude + PAN_INTERVAL, MAX_LATITUDE);
+ this.invalidate();
+ this.validate();
+ this.repaint();
+ }
+
+ public void moveSouth() {
+ this.centerLatitude = Math.max(this.centerLatitude - PAN_INTERVAL, MIN_LATITUDE);
+ this.invalidate();
+ this.validate();
+ this.repaint();
+ }
+}
diff --git a/src/com/benburwell/planes/gui/aircraftmap/AircraftMapComponent.java b/src/com/benburwell/planes/gui/aircraftmap/AircraftMapComponent.java
new file mode 100644
index 0000000..c1478b3
--- /dev/null
+++ b/src/com/benburwell/planes/gui/aircraftmap/AircraftMapComponent.java
@@ -0,0 +1,118 @@
+package com.benburwell.planes.gui.aircraftmap;
+
+import com.benburwell.planes.data.AircraftStore;
+import com.benburwell.planes.data.AircraftStoreListener;
+import com.benburwell.planes.data.Position;
+import com.benburwell.planes.gui.ViewComponent;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * Created by ben on 11/18/16.
+ */
+public class AircraftMapComponent implements ViewComponent {
+ private AircraftStore store;
+ private AircraftMap mapPanel;
+ private String focusedAircraftIdentifier = null;
+
+ public AircraftMapComponent(AircraftStore store) {
+ this.store = store;
+ this.setupMap();
+ this.bindKeys();
+ this.subscribeToChanges();
+
+ List<Drawable> planes = new ArrayList<>();
+ planes.add(new Plane("JBU1111", 40.6188942, -75.4947205));
+ planes.add(new Plane("JBU1112", 40.6178942, -75.4347205));
+ planes.add(new Plane("JBU1114", 40.5178942, -75.5347205));
+ planes.add(new Plane("JBU1115", 40.3178942, -75.1347205));
+ this.mapPanel.setPlanes(planes);
+ }
+
+ public void focusNextAircraft() {
+ List<String> aircraftIdentifiers = new ArrayList<>(this.store.getAircraft().keySet());
+ Collections.sort(aircraftIdentifiers);
+ if (this.focusedAircraftIdentifier == null && aircraftIdentifiers.size() > 0) {
+ this.focusedAircraftIdentifier = aircraftIdentifiers.get(0);
+ } else {
+ int idx = aircraftIdentifiers.indexOf(this.focusedAircraftIdentifier);
+ if (idx > 0 && idx < aircraftIdentifiers.size() - 1) {
+ this.focusedAircraftIdentifier = aircraftIdentifiers.get(idx++);
+ } else if (aircraftIdentifiers.size() > 0) {
+ this.focusedAircraftIdentifier = aircraftIdentifiers.get(0);
+ } else {
+ this.focusedAircraftIdentifier = null;
+ }
+ }
+ }
+
+ private void setupMap() {
+ this.mapPanel = new AircraftMap();
+ this.mapPanel.setCenter(40.6188942, -75.4947205);
+ }
+
+ private void bindKeys() {
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(e -> {
+ if (e.getKeyCode() == KeyEvent.VK_EQUALS && e.isShiftDown() && e.getID() == KeyEvent.KEY_PRESSED) {
+ this.mapPanel.zoomIn();
+ } else if (e.getKeyCode() == KeyEvent.VK_MINUS && e.getID() == KeyEvent.KEY_PRESSED) {
+ this.mapPanel.zoomOut();
+ } else if (e.getKeyCode() == KeyEvent.VK_L && e.getID() == KeyEvent.KEY_PRESSED) {
+ this.mapPanel.moveEast();
+ } else if (e.getKeyCode() == KeyEvent.VK_H && e.getID() == KeyEvent.KEY_PRESSED) {
+ this.mapPanel.moveWest();
+ } else if (e.getKeyCode() == KeyEvent.VK_J && e.getID() == KeyEvent.KEY_PRESSED) {
+ this.mapPanel.moveSouth();
+ } else if (e.getKeyCode() == KeyEvent.VK_K && e.getID() == KeyEvent.KEY_PRESSED) {
+ this.mapPanel.moveNorth();
+ } else if (e.getKeyCode() == KeyEvent.VK_0 && e.getID() == KeyEvent.KEY_PRESSED) {
+ this.mapPanel.setCenter(40.6188942, -75.4947205);
+ } else if (e.getKeyCode() == KeyEvent.VK_TAB && e.getID() == KeyEvent.KEY_PRESSED) {
+ this.focusNextAircraft();
+ this.centerMapOnPlane(this.focusedAircraftIdentifier);
+ }
+ return false;
+ });
+ }
+
+ private void centerMapOnPlane(String identifier) {
+ if (identifier != null) {
+ Position pos = this.store.getAircraft().get(identifier).getCurrentPosition();
+ this.mapPanel.setCenter(pos.getLatitude(), pos.getLongitude());
+ }
+ }
+
+ private void subscribeToChanges() {
+ this.store.subscribe(new AircraftStoreListener() {
+ @Override
+ public void aircraftStoreChanged() {
+ List<Drawable> planes = new ArrayList<>();
+ store.getAircraft().values().forEach(aircraft -> {
+ String name = !aircraft.getCallsign().isEmpty() ? aircraft.getCallsign() : aircraft.getHexIdent();
+ double lat = aircraft.getCurrentPosition().getLatitude();
+ double lon = aircraft.getCurrentPosition().getLongitude();
+ planes.add(new Plane(name, lat, lon));
+ });
+ mapPanel.setPlanes(planes);
+ mapPanel.validate();
+ mapPanel.repaint();
+ }
+
+ @Override
+ public boolean respondTo(String aircraftId) {
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public JComponent getComponent() {
+ return this.mapPanel;
+ }
+
+}
diff --git a/src/com/benburwell/planes/gui/aircraftmap/Drawable.java b/src/com/benburwell/planes/gui/aircraftmap/Drawable.java
new file mode 100644
index 0000000..01c16ba
--- /dev/null
+++ b/src/com/benburwell/planes/gui/aircraftmap/Drawable.java
@@ -0,0 +1,10 @@
+package com.benburwell.planes.gui.aircraftmap;
+
+import java.awt.*;
+
+/**
+ * Created by ben on 11/19/16.
+ */
+public interface Drawable {
+ void drawOn(Graphics graphicsContext, AircraftMap map);
+}
diff --git a/src/com/benburwell/planes/gui/aircraftmap/GeoPoint.java b/src/com/benburwell/planes/gui/aircraftmap/GeoPoint.java
new file mode 100644
index 0000000..5cd5535
--- /dev/null
+++ b/src/com/benburwell/planes/gui/aircraftmap/GeoPoint.java
@@ -0,0 +1,30 @@
+package com.benburwell.planes.gui.aircraftmap;
+
+/**
+ * Created by ben on 11/19/16.
+ */
+public class GeoPoint {
+ private double latitude;
+ private double longitude;
+
+ public GeoPoint(double latitude, double longitude) {
+ this.latitude = latitude;
+ this.longitude = longitude;
+ }
+
+ public int getX(AircraftMap map) {
+ double degreesFromCenter = map.getCenterLongitude() - this.longitude;
+ double pixelsFromCenter = degreesFromCenter * map.getPixelsPerDegreeLongitude();
+ double centerPixels = map.getSize().getWidth() / 2;
+ int xPosition = (int) (centerPixels - pixelsFromCenter);
+ return xPosition;
+ }
+
+ public int getY(AircraftMap map) {
+ double degreesFromCenter = map.getCenterLatitude() - this.latitude;
+ double pixelsFromCenter = degreesFromCenter * map.getPixelsPerDegreeLatitude();
+ double centerPixels = map.getSize().getHeight() / 2;
+ int yPosition = (int) (centerPixels + pixelsFromCenter);
+ return yPosition;
+ }
+}
diff --git a/src/com/benburwell/planes/gui/aircraftmap/Plane.java b/src/com/benburwell/planes/gui/aircraftmap/Plane.java
new file mode 100644
index 0000000..8c3c8c1
--- /dev/null
+++ b/src/com/benburwell/planes/gui/aircraftmap/Plane.java
@@ -0,0 +1,37 @@
+package com.benburwell.planes.gui.aircraftmap;
+
+import com.benburwell.planes.gui.GraphicsTheme;
+
+import java.awt.*;
+
+/**
+ * Created by ben on 11/19/16.
+ */
+public class Plane extends GeoPoint implements Drawable {
+ private String name;
+ private final int DOT_DIMENSION = 4;
+ private final int TEXT_OFFSET_X = 10;
+ private final int TEXT_OFFSET_Y = 15;
+
+ public Plane(String name, double latitude, double longitude) {
+ super(latitude, longitude);
+ this.name = name;
+ }
+
+ public void drawOn(Graphics g, AircraftMap map) {
+ int x = this.getX(map);
+ int y = this.getY(map);
+
+ if (x >= 0 && x <= map.getSize().getWidth() && y >= 0 && y <= map.getSize().getHeight()) {
+ // draw the plane dot
+ g.setColor(GraphicsTheme.Colors.ORANGE);
+ g.drawRect(x - (DOT_DIMENSION / 2), y - (DOT_DIMENSION / 2), DOT_DIMENSION, DOT_DIMENSION);
+
+ // draw the name of the plane
+ g.setColor(GraphicsTheme.Colors.BLUE);
+ g.drawString(this.name, this.getX(map) + TEXT_OFFSET_X, this.getY(map) + TEXT_OFFSET_Y);
+ } else {
+ System.out.println("Skipping drawing plane at " + x + "," + y + " which is not within bounds");
+ }
+ }
+}