Index: trunk/src/org/openstreetmap/josm/data/gpx/GpxDistance.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/gpx/GpxDistance.java	(revision 14802)
+++ trunk/src/org/openstreetmap/josm/data/gpx/GpxDistance.java	(revision 14802)
@@ -0,0 +1,148 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.gpx;
+
+import java.util.ArrayList;
+import java.util.List;
+
+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.tools.Geometry;
+
+/**
+ * A class to find the distance between an {@link OsmPrimitive} and a GPX point.
+ *
+ * @author Taylor Smock
+ * @since 14802
+ */
+public final class GpxDistance {
+    private GpxDistance() {
+        // This class should not be instantiated
+    }
+
+    /**
+     * Find the distance between a point and a dataset of surveyed points
+     * @param p OsmPrimitive from which to get the lowest distance to a GPX point
+     * @param gpxData Data from which to get the GPX points
+     * @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);
+    }
+
+    /**
+     * 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
+     */
+    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
+     */
+    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
+     */
+    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
+     */
+    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
+     */
+    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
+     */
+    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);
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/layer/MainLayerManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/MainLayerManager.java	(revision 14801)
+++ trunk/src/org/openstreetmap/josm/gui/layer/MainLayerManager.java	(revision 14802)
@@ -13,8 +13,10 @@
 import javax.swing.JOptionPane;
 
+import org.openstreetmap.josm.data.gpx.GpxData;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmData;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.io.AsynchronousUploadPrimitivesTask;
+import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
 import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.tools.Logging;
@@ -542,3 +544,20 @@
         }
     }
+
+    /**
+     * Returns all {@link GpxData} we can get from current layers.
+     * @return all {@code GpxData} we can get from current layers
+     * @since 14802
+     */
+    public List<GpxData> getAllGpxData() {
+        List<GpxData> result = new ArrayList<>();
+        for (Layer layer : getLayers()) {
+            if (layer instanceof GpxLayer) {
+                result.add(((GpxLayer) layer).data);
+            } else if (layer instanceof GeoImageLayer) {
+                result.add(((GeoImageLayer) layer).getFauxGpxLayer().data);
+            }
+        }
+        return result;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java	(revision 14801)
+++ trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java	(revision 14802)
@@ -43,4 +43,6 @@
 import org.openstreetmap.josm.data.ImageData;
 import org.openstreetmap.josm.data.ImageData.ImageDataUpdateListener;
+import org.openstreetmap.josm.data.gpx.GpxData;
+import org.openstreetmap.josm.data.gpx.WayPoint;
 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
 import org.openstreetmap.josm.gui.MainApplication;
@@ -76,4 +78,5 @@
     private final ImageData data;
     GpxLayer gpxLayer;
+    GpxLayer gpxFauxLayer;
 
     private final Icon icon = ImageProvider.get("dialogs/geoimage/photo-marker");
@@ -925,4 +928,23 @@
     }
 
+    /**
+     * Returns a faux GPX layer built from the images or the associated GPX layer.
+     * @return A faux GPX layer or the associated GPX layer
+     * @since 14802
+     */
+    public synchronized GpxLayer getFauxGpxLayer() {
+        if (gpxLayer != null) return getGpxLayer();
+        if (gpxFauxLayer == null) {
+            GpxData gpxData = new GpxData();
+            List<ImageEntry> imageList = data.getImages();
+            for (ImageEntry image : imageList) {
+                WayPoint twaypoint = new WayPoint(image.getPos());
+                gpxData.addWaypoint(twaypoint);
+            }
+            gpxFauxLayer = new GpxLayer(gpxData);
+        }
+        return gpxFauxLayer;
+    }
+
     @Override
     public void jumpToNextMarker() {
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java	(revision 14801)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java	(revision 14802)
@@ -25,10 +25,13 @@
 
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.gpx.GpxDistance;
 import org.openstreetmap.josm.data.osm.IPrimitive;
 import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.search.SearchCompiler;
 import org.openstreetmap.josm.data.osm.search.SearchCompiler.Match;
 import org.openstreetmap.josm.data.osm.search.SearchParseError;
+import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.mappaint.Cascade;
 import org.openstreetmap.josm.gui.mappaint.Environment;
@@ -520,4 +523,20 @@
 
         /**
+         * Returns the lowest distance between the OSM object and a GPX point
+         * <p>
+         * @param env the environment
+         * @return the distance between the object and the closest gpx point or {@code Double.MAX_VALUE}
+         * @since 14802
+         */
+        public static double gpx_distance(final Environment env) { // NO_UCD (unused code)
+            if (env.osm instanceof OsmPrimitive) {
+                return MainApplication.getLayerManager().getAllGpxData().stream()
+                        .mapToDouble(gpx -> GpxDistance.getLowestDistance((OsmPrimitive) env.osm, gpx))
+                        .min().orElse(Double.MAX_VALUE);
+            }
+            return Double.MAX_VALUE;
+        }
+
+        /**
          * Determines whether the object has a tag with the given key.
          * @param env the environment
