Index: test/unit/org/openstreetmap/josm/data/gpx/GpxDistanceTest.java
===================================================================
--- test/unit/org/openstreetmap/josm/data/gpx/GpxDistanceTest.java	(nonexistent)
+++ test/unit/org/openstreetmap/josm/data/gpx/GpxDistanceTest.java	(working copy)
@@ -0,0 +1,137 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.gpx;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+/**
+ * Unit tests for class {@link GpxDistance}.
+ */
+public class GpxDistanceTest {
+
+    /**
+     * Setup test.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().projection();
+
+    @Test
+    /**
+     * Unit test of method {@link GpxDistance#getDistanceWay}.
+     */
+    public void testGetDistanceWay() {
+        Node node1 = new Node();
+        Node node2 = new Node();
+        Way way = new Way();
+        node1.setCoor(new LatLon(0, 0));
+        node2.setCoor(new LatLon(0, 1));
+        way.addNode(node1);
+        way.addNode(node2);
+
+        WayPoint waypoint = new WayPoint(new LatLon(1, 0));
+
+        double distance = GpxDistance.getDistanceWay(null, waypoint);
+        assertEquals(Double.MAX_VALUE, distance, 0.1);
+
+        distance = GpxDistance.getDistanceWay(way, null);
+        assertEquals(Double.MAX_VALUE, distance, 0.1);
+
+        distance = GpxDistance.getDistanceWay(null, null);
+        assertEquals(Double.MAX_VALUE, distance, 0.1);
+
+        distance = GpxDistance.getDistanceWay(way, waypoint);
+        /* 111319.49077 uses the WGS84/NAD38/GRS80 model for
+         * the distance between (0, 0) and (0, 1) */
+        assertEquals(111319.49077, distance, 0.1);
+    }
+
+    /**
+     * Unit test of method {@link GpxDistance#getDistanceNode}.
+     */
+    @Test
+    public void testGetDistanceNode() {
+        double distance = GpxDistance.getDistanceNode(null, null);
+        assertEquals(Double.MAX_VALUE, distance, 0.1);
+
+        Node node = new Node();
+        node.setCoor(new LatLon(0, 0));
+        distance = GpxDistance.getDistanceNode(node, null);
+        assertEquals(Double.MAX_VALUE, distance, 0.1);
+
+        WayPoint waypoint = new WayPoint(new LatLon(0, 0));
+        distance = GpxDistance.getDistanceNode(node, waypoint);
+        assertEquals(0.0, distance, 0.0001); // should be zero delta
+
+        distance = GpxDistance.getDistanceNode(null, waypoint);
+        assertEquals(Double.MAX_VALUE, distance, 0.1);
+
+        node.setCoor(new LatLon(1, 0));
+        distance = GpxDistance.getDistanceNode(node, waypoint);
+        /* 111319.49077 uses the WGS84/NAD38/GRS80 model for
+         * the distance between (0, 0) and (0, 1) */
+        assertEquals(111319.49077, distance, 0.1);
+    }
+
+    /**
+     * Unit test of method {@link GpxDistance#getDistanceEastNorth}.
+     */
+    @Test
+    public void testGetDistanceEastNorth() {
+        double distance = GpxDistance.getDistanceEastNorth(null, null);
+        assertEquals(Double.MAX_VALUE, distance, 0.1);
+
+        EastNorth en = new EastNorth(0, 0);
+        distance = GpxDistance.getDistanceEastNorth(en, null);
+        assertEquals(Double.MAX_VALUE, distance, 0.1);
+
+        WayPoint waypoint = new WayPoint(new LatLon(0, 0));
+        distance = GpxDistance.getDistanceEastNorth(en, waypoint);
+        assertEquals(0.0, distance, 0.0001); // should be zero delta
+
+        distance = GpxDistance.getDistanceEastNorth(null, waypoint);
+        assertEquals(Double.MAX_VALUE, distance, 0.1);
+
+        en = new EastNorth(0, 1);
+        distance = GpxDistance.getDistanceEastNorth(en, waypoint);
+        /* 111319.49077 uses the WGS84/NAD38/GRS80 model for
+         * the distance between (0, 0) and (0, 1) */
+        assertEquals(111319.49077, distance, 0.1);
+    }
+
+
+    /**
+     * Unit test of method {@link GpxDistance#getDistanceLatLon}.
+     */
+    @Test
+    public void testGetDistanceLatLon() {
+        double distance = GpxDistance.getDistanceLatLon(null, null);
+        assertEquals(Double.MAX_VALUE, distance, 0.1);
+
+        LatLon ll = new LatLon(0, 0);
+        distance = GpxDistance.getDistanceLatLon(ll, null);
+        assertEquals(Double.MAX_VALUE, distance, 0.1);
+
+        WayPoint waypoint = new WayPoint(ll);
+        distance = GpxDistance.getDistanceLatLon(ll, waypoint);
+        assertEquals(0.0, distance, 0.0001); // should be zero delta
+
+        distance = GpxDistance.getDistanceLatLon(null, waypoint);
+        assertEquals(Double.MAX_VALUE, distance, 0.1);
+
+        ll = new LatLon(0, 1);
+        distance = GpxDistance.getDistanceLatLon(ll, waypoint);
+        /* 111319.49077 uses the WGS84/NAD38/GRS80 model for
+         * the distance between (0, 0) and (0, 1) */
+        assertEquals(111319.49077, distance, 0.1);
+    }
+}
Index: src/org/openstreetmap/josm/data/gpx/GpxDistance.java
===================================================================
--- src/org/openstreetmap/josm/data/gpx/GpxDistance.java	(nonexistent)
+++ src/org/openstreetmap/josm/data/gpx/GpxDistance.java	(working copy)
@@ -0,0 +1,209 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.gpx;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.layer.GpxLayer;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.LayerManager;
+import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
+import org.openstreetmap.josm.tools.Geometry;
+
+/**
+ * A class to find the distance between an OsmPrimitive and a GPX point
+ *
+ * @author Taylor Smock
+ *
+ */
+public final class GpxDistance {
+    private GpxDistance() {
+        // This class should not be instantiated
+    }
+
+    /**
+     * @param p The OsmPrimitive that we are checking the maximum distance for
+     * @param maximumDistance The maximum distance from a GPX point to the OsmPrimitive
+     * @return true if the distance to the closest GPX point is lower than maximumDistance
+     * @since xxx
+     */
+    public static boolean isCloseTo(OsmPrimitive p, double maximumDistance) {
+        double distance = getLowestDistance(p);
+        return (distance < maximumDistance);
+    }
+
+    /**
+     * Get the lowest distance from the layers to p
+     * @param p OsmPrimitive from which to get the lowest distance to a GPX point
+     * @return the lowest distance from any GpxLayer to p.
+     * @since xxx
+     */
+    public static double getLowestDistance(OsmPrimitive p) {
+        LayerManager layerManager = MainApplication.getLayerManager();
+        List<Layer> layers = layerManager.getLayers();
+        double distance = Double.MAX_VALUE;
+        for (Layer layer : layers) {
+            double tdistance = getLowestDistance(p, layer);
+            if (tdistance < distance) distance = tdistance;
+        }
+        return distance;
+    }
+
+    /**
+     * Find the distance between a point and a layer of surveyed points
+     * @param p OsmPrimitive from which to get the lowest distance to a GPX point
+     * @param layer Layer from which to get the GPX points (currently, only GpxLayer is supported)
+     * @return The shortest distance
+     * @since xxx
+     */
+    public static double getLowestDistance(OsmPrimitive p, Layer layer) {
+        if (layer instanceof GpxLayer || layer instanceof GeoImageLayer) {
+            GpxLayer gpxLayer = null;
+            if (layer instanceof GpxLayer) {
+                gpxLayer = (GpxLayer) layer;
+            } else if (layer instanceof GeoImageLayer) {
+                GeoImageLayer tmp = (GeoImageLayer) layer;
+                gpxLayer = tmp.getGpxLayer();
+                // TODO build a gpxlayer from the images
+            }
+            if (gpxLayer == null) return Double.MAX_VALUE;
+            GpxData gpxData = gpxLayer.data;
+            List<WayPoint> trackPoints = gpxData.getTrackPoints().collect(Collectors.toList());
+            double lowestDistance = Double.MAX_VALUE;
+            for (WayPoint trackPoint : trackPoints) {
+                double distance = getDistance(p, trackPoint);
+                if (distance >= 0.0 && distance < lowestDistance) lowestDistance = distance;
+            }
+            return lowestDistance;
+        } else if (layer instanceof GeoImageLayer) {
+            GeoImageLayer geoImageLayer = (GeoImageLayer) layer;
+            geoImageLayer.getGpxLayer();
+            //TODO
+        }
+        return Double.MAX_VALUE;
+    }
+
+    /**
+     * Get the distance between an object and a waypoint
+     * @param p OsmPrimitive to get the distance to the WayPoint
+     * @param waypoint WayPoint to get the distance from
+     * @return The shortest distance between p and waypoint
+     * @since xxx
+     */
+    public static double getDistance(OsmPrimitive p, WayPoint waypoint) {
+        if (p instanceof Node) {
+            return getDistanceNode((Node) p, waypoint);
+        } else if (p instanceof Way) {
+            return getDistanceWay((Way) p, waypoint);
+        } else if (p instanceof Relation) {
+            return getDistanceRelation((Relation) p, waypoint);
+        }
+        return Double.MAX_VALUE;
+    }
+
+    /**
+     * Get the shortest distance between a relation and a waypoint
+     * @param relation Relation to get the distance from
+     * @param waypoint WayPoint to get the distance to
+     * @return The distance between the relation and the waypoint
+     * @since xxx
+     */
+    public static double getDistanceRelation(Relation relation, WayPoint waypoint) {
+        double shortestDistance = Double.MAX_VALUE;
+        List<Node> nodes = new ArrayList<>(relation.getMemberPrimitives(Node.class));
+        List<Way> ways = new ArrayList<>(relation.getMemberPrimitives(Way.class));
+        List<Relation> relations = new ArrayList<>(relation.getMemberPrimitives(Relation.class));
+        if (nodes.isEmpty() && ways.isEmpty() && relations.isEmpty()) return Double.MAX_VALUE;
+        for (Relation nrelation : relations) {
+            double distance = getDistanceRelation(nrelation, waypoint);
+            if (distance < shortestDistance) shortestDistance = distance;
+        }
+        for (Way way : ways) {
+            double distance = getDistanceWay(way, waypoint);
+            if (distance < shortestDistance) shortestDistance = distance;
+        }
+        for (Node node : nodes) {
+            double distance = getDistanceNode(node, waypoint);
+            if (distance < shortestDistance) shortestDistance = distance;
+        }
+        return shortestDistance;
+    }
+
+    /**
+     * Get the shortest distance between a way and a waypoint
+     * @param way Way to get the distance from
+     * @param waypoint WayPoint to get the distance to
+     * @return The distance between the way and the waypoint
+     * @since xxx
+     */
+    public static double getDistanceWay(Way way, WayPoint waypoint) {
+        double shortestDistance = Double.MAX_VALUE;
+        if (way == null || waypoint == null) return shortestDistance;
+        LatLon llwaypoint = waypoint.getCoor();
+        EastNorth enwaypoint = new EastNorth(llwaypoint.getY(), llwaypoint.getX());
+        for (int i = 0; i < way.getNodesCount() - 1; i++) {
+            double distance = Double.MAX_VALUE;
+            LatLon llfirst = way.getNode(i).getCoor();
+            LatLon llsecond = way.getNode(i + 1).getCoor();
+            EastNorth first = new EastNorth(llfirst.getY(), llfirst.getX());
+            EastNorth second = new EastNorth(llsecond.getY(), llsecond.getX());
+            if (first.isValid() && second.isValid()) {
+                EastNorth closestPoint = Geometry.closestPointToSegment(first, second, enwaypoint);
+                distance = llwaypoint.greatCircleDistance(new LatLon(closestPoint.getX(), closestPoint.getY()));
+            } else if (first.isValid() && !second.isValid()) {
+                distance = getDistanceEastNorth(first, waypoint);
+            } else if (!first.isValid() && second.isValid()) {
+                distance = getDistanceEastNorth(second, waypoint);
+            } else if (!first.isValid() && !second.isValid()) {
+                distance = Double.MAX_VALUE;
+            }
+            if (distance < shortestDistance) shortestDistance = distance;
+
+        }
+        return shortestDistance;
+    }
+
+    /**
+     * Get the distance between a node and a waypoint
+     * @param node Node to get the distance from
+     * @param waypoint WayPoint to get the distance to
+     * @return The distance between the two points
+     * @since xxx
+     */
+    public static double getDistanceNode(Node node, WayPoint waypoint) {
+        if (node == null) return Double.MAX_VALUE;
+        return getDistanceLatLon(node.getCoor(), waypoint);
+    }
+
+    /**
+     * Get the distance between coordinates (provided by EastNorth) and a waypoint
+     * @param en The EastNorth to get the distance to
+     * @param waypoint WayPoint to get the distance to
+     * @return The distance between the two points
+     * @since xxx
+     */
+    public static double getDistanceEastNorth(EastNorth en, WayPoint waypoint) {
+        if (en == null || !en.isValid()) return Double.MAX_VALUE;
+        return getDistanceLatLon(new LatLon(en.getY(), en.getX()), waypoint);
+    }
+
+    /**
+     * Get the distance between coordinates (latitude longitude) and a waypoint
+     * @param latlon LatLon to get the distance from
+     * @param waypoint WayPoint to get the distance to
+     * @return The distance between the two points
+     * @since xxx
+     */
+    public static double getDistanceLatLon(LatLon latlon, WayPoint waypoint) {
+        if (latlon == null || waypoint == null || waypoint.getCoor() == null) return Double.MAX_VALUE;
+        return waypoint.getCoor().greatCircleDistance(latlon);
+    }
+}
