Index: src/org/openstreetmap/josm/data/gpx/GpxDistance.java
===================================================================
--- src/org/openstreetmap/josm/data/gpx/GpxDistance.java	(revision 14813)
+++ src/org/openstreetmap/josm/data/gpx/GpxDistance.java	(working copy)
@@ -2,8 +2,11 @@
 package org.openstreetmap.josm.data.gpx;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
+import java.util.TreeMap;
 
+import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.Node;
@@ -30,10 +33,33 @@
      * @return The shortest distance
      */
     public static double getLowestDistance(OsmPrimitive p, GpxData gpxData) {
-        return gpxData.getTrackPoints()
-                .mapToDouble(tp -> getDistance(p, tp))
-                .filter(x -> x >= 0)
-                .min().orElse(Double.MAX_VALUE);
+        Collection<GpxTrack> tracks = gpxData.getTracks();
+        TreeMap<GpxTrack, Double> trackDistances = new TreeMap<>();
+        for (GpxTrack track : tracks) {
+                Bounds bounds = track.getBounds();
+                double distance = getMinDistanceBounds(p, bounds);
+                trackDistances.put(track, distance);
+
+        }
+        if (trackDistances.containsValue(0.0)) {
+            double minDistance = Double.MAX_VALUE;
+            for (GpxTrack track : trackDistances.keySet()) {
+                if (trackDistances.get(track).equals(0.0)) {
+                    for (GpxTrackSegment segment : track.getSegments()) {
+                        for (WayPoint wp : segment.getWayPoints()) {
+                            double distance = getDistance(p, wp);
+                            if (distance < minDistance) minDistance = distance;
+                        }
+                    }
+                }
+            }
+            return minDistance;
+        } else {
+            return gpxData.getTrackPoints()
+                    .mapToDouble(tp -> getDistance(p, tp))
+                    .filter(x -> x >= 0)
+                    .min().orElse(Double.MAX_VALUE);
+        }
     }
 
     /**
@@ -145,4 +171,53 @@
         if (latlon == null || waypoint == null || waypoint.getCoor() == null) return Double.MAX_VALUE;
         return waypoint.getCoor().greatCircleDistance(latlon);
     }
+
+    /**
+     * @param p OsmPrimitive to get the lowest distance to its centroid
+     * @param bounds The bounds with which we are getting the distance to
+     * @return The distance to the bounds (0 if the OsmPrimitive is inside the bounds)
+     */
+    public static double getMinDistanceBounds(OsmPrimitive p, Bounds bounds) {
+        return getDistanceBounds(p, bounds, true);
+    }
+
+    /**
+     * @param p OsmPrimitive to get the furthest distance to its centroid
+     * @param bounds The bounds with which we are getting the distance to
+     * @return The furthest distance to the bounds
+     */
+    public static double getMaxDistanceBounds(OsmPrimitive p, Bounds bounds) {
+        return getDistanceBounds(p, bounds, false);
+    }
+
+    private static double getDistanceBounds(OsmPrimitive p, Bounds bounds, boolean closest) {
+        // If the primitive is within the bounds, return 0
+        if (bounds.toBBox().intersects(p.getBBox()) && closest) return 0;
+
+        // The order the corners are added is important! When connected in order, they _must_ form a rectangle.
+        ArrayList<Node> corners = new ArrayList<>();
+        corners.add(new Node(bounds.getMax()));
+        corners.add(new Node(new LatLon(bounds.getMaxLat(), bounds.getMinLon())));
+        corners.add(new Node(bounds.getMin()));
+        corners.add(new Node(new LatLon(bounds.getMinLat(), bounds.getMaxLon())));
+
+        ArrayList<Way> ways = new ArrayList<>();
+        for (int i = 0; i < corners.size(); i++) {
+            ways.add(new Way());
+            ways.get(i).addNode(corners.get(i));
+            // Doing % corners.size() avoids requiring an if statement to avoid overflow (which _is_ expected)
+            ways.get(i).addNode(corners.get((i + 1) % corners.size()));
+        }
+        double distance;
+        if (closest) distance = Double.MAX_VALUE;
+        else distance = Double.MIN_VALUE;
+        for (Way way : ways) {
+            // Not the best of ideas, but there isn't a method implemented for two ways
+            double tdistance = getDistance(way, new WayPoint(p.getBBox().getCenter()));
+            if ((closest && tdistance < distance) || (!closest && tdistance > distance)) {
+                distance = tdistance;
+            }
+        }
+        return distance;
+    }
 }
