Index: trunk/src/org/openstreetmap/josm/actions/DownloadAlongAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/DownloadAlongAction.java	(revision 14961)
+++ trunk/src/org/openstreetmap/josm/actions/DownloadAlongAction.java	(revision 14962)
@@ -6,5 +6,8 @@
 import java.awt.GraphicsEnvironment;
 import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
 import java.awt.geom.Area;
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
 import java.awt.geom.Rectangle2D;
 import java.util.ArrayList;
@@ -18,9 +21,14 @@
 
 import org.openstreetmap.josm.actions.downloadtasks.DownloadTaskList;
+import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.gui.MainApplication;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.gui.PleaseWaitRunnable;
+import org.openstreetmap.josm.gui.layer.gpx.DownloadAlongPanel;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.gui.progress.swing.PleaseWaitProgressMonitor;
 import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.Shortcut;
+import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -29,4 +37,10 @@
  */
 public abstract class DownloadAlongAction extends JosmAction {
+
+    /**
+     * Sub classes must override this method.
+     * @return the task to start or null if nothing to do
+     */
+    protected abstract PleaseWaitRunnable createTask();
 
     /**
@@ -98,8 +112,6 @@
      * @param gpxDownload Set to true if GPX data should be downloaded
      * @param title the title string for the confirmation dialog
-     * @param progressMonitor the progress monitor
-     */
-    protected static void confirmAndDownloadAreas(Area a, double maxArea, boolean osmDownload, boolean gpxDownload, String title,
-            ProgressMonitor progressMonitor) {
+     */
+    protected static void confirmAndDownloadAreas(Area a, double maxArea, boolean osmDownload, boolean gpxDownload, String title) {
         List<Rectangle2D> toDownload = new ArrayList<>();
         addToDownload(a, a.getBounds(), toDownload, maxArea);
@@ -119,3 +131,161 @@
         waitFuture(future, monitor);
     }
+
+    /**
+     * Calculate list of points between two given points so that the distance between two consecutive points is below a limit.
+     * @param p1 first point or null
+     * @param p2 second point (must not be null)
+     * @param bufferDist the maximum distance
+     * @return a list of points with at least one point (p2) and maybe more.
+     */
+    protected static Collection<LatLon> calcBetweenPoints(LatLon p1, LatLon p2, double bufferDist) {
+        ArrayList<LatLon> intermediateNodes = new ArrayList<>();
+        intermediateNodes.add(p2);
+        if (p1 != null && p2.greatCircleDistance(p1) > bufferDist) {
+            Double d = p2.greatCircleDistance(p1) / bufferDist;
+            int nbNodes = d.intValue();
+            if (Logging.isDebugEnabled()) {
+                Logging.debug(tr("{0} intermediate nodes to download.", nbNodes));
+                Logging.debug(tr("between {0} {1} and {2} {3}", p2.lat(), p2.lon(), p1.lat(), p1.lon()));
+            }
+            double latStep = (p2.lat() - p1.lat()) / (nbNodes + 1);
+            double lonStep = (p2.lon() - p1.lon()) / (nbNodes + 1);
+            for (int i = 1; i <= nbNodes; i++) {
+                LatLon intermediate = new LatLon(p1.lat() + i * latStep, p1.lon() + i * lonStep);
+                intermediateNodes.add(intermediate);
+                if (Logging.isTraceEnabled()) {
+                    Logging.trace(tr("  adding {0} {1}", intermediate.lat(), intermediate.lon()));
+                }
+            }
+        }
+        return intermediateNodes;
+    }
+
+    /**
+     * Create task that downloads areas along the given path using the values specified in the panel.
+     * @param alongPath the path along which the areas are to be downloaded
+     * @param panel the panel that was displayed to the user and now contains his selections
+     * @param confirmTitle the title to display in the confirmation panel
+     * @return the task or null if canceled by user
+     */
+    protected PleaseWaitRunnable createCalcTask(Path2D alongPath, DownloadAlongPanel panel, String confirmTitle) {
+        /*
+         * Find the average latitude for the data we're contemplating, so we can know how many
+         * metres per degree of longitude we have.
+         */
+        double latsum = 0;
+        int latcnt = 0;
+        final PathIterator pit = alongPath.getPathIterator(null);
+        final double[] res = new double[6];
+        while (!pit.isDone()) {
+            int type = pit.currentSegment(res);
+            if (type == PathIterator.SEG_LINETO || type == PathIterator.SEG_MOVETO) {
+                latsum += res[1];
+                latcnt++;
+            }
+            pit.next();
+        }
+        if (latcnt == 0) {
+            return null;
+        }
+        final double avglat = latsum / latcnt;
+        final double scale = Math.cos(Utils.toRadians(avglat));
+
+        /*
+         * Compute buffer zone extents and maximum bounding box size. Note that the maximum we
+         * ever offer is a bbox area of 0.002, while the API theoretically supports 0.25, but as
+         * soon as you touch any built-up area, that kind of bounding box will download forever
+         * and then stop because it has more than 50k nodes.
+         */
+        final double bufferDist = panel.getDistance();
+        final double maxArea = panel.getArea() / 10000.0 / scale;
+        final double bufferY = bufferDist / 100000.0;
+        final double bufferX = bufferY / scale;
+        final int totalTicks = latcnt;
+        // guess if a progress bar might be useful.
+        final boolean displayProgress = totalTicks > 20_000 && bufferY < 0.01;
+
+        class CalculateDownloadArea extends PleaseWaitRunnable {
+
+            private final Path2D downloadPath = new Path2D.Double();
+            private boolean cancel;
+            private int ticks;
+            private final Rectangle2D r = new Rectangle2D.Double();
+
+            CalculateDownloadArea() {
+                super(tr("Calculating Download Area"), displayProgress ? null : NullProgressMonitor.INSTANCE, false);
+            }
+
+            @Override
+            protected void cancel() {
+                cancel = true;
+            }
+
+            @Override
+            protected void finish() {
+                // Do nothing
+            }
+
+            @Override
+            protected void afterFinish() {
+                if (cancel) {
+                    return;
+                }
+                confirmAndDownloadAreas(new Area(downloadPath), maxArea, panel.isDownloadOsmData(), panel.isDownloadGpxData(),
+                        confirmTitle);
+            }
+
+            /**
+             * increase tick count by one, report progress every 100 ticks
+             */
+            private void tick() {
+                ticks++;
+                if (ticks % 100 == 0) {
+                    progressMonitor.worked(100);
+                }
+            }
+
+            /**
+             * calculate area enclosing a single point
+             */
+            private void calcAreaForWayPoint(LatLon c) {
+                r.setRect(c.lon() - bufferX, c.lat() - bufferY, 2 * bufferX, 2 * bufferY);
+                downloadPath.append(r, false);
+            }
+
+            @Override
+            protected void realRun() {
+                progressMonitor.setTicksCount(totalTicks);
+                PathIterator pit = alongPath.getPathIterator(null);
+                double[] res = new double[6];
+                LatLon previous = null;
+                while (!pit.isDone()) {
+                    int type = pit.currentSegment(res);
+                    LatLon c = new LatLon(res[1], res[0]);
+                    if (type == PathIterator.SEG_LINETO) {
+                        tick();
+                        for (LatLon d : calcBetweenPoints(previous, c, bufferDist)) {
+                            calcAreaForWayPoint(d);
+                        }
+                        previous = c;
+                    } else if (type == PathIterator.SEG_MOVETO) {
+                        previous = c;
+                        tick();
+                        calcAreaForWayPoint(c);
+                    }
+                    pit.next();
+                }
+            }
+        }
+
+        return new CalculateDownloadArea();
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        PleaseWaitRunnable task = createTask();
+        if (task != null) {
+            MainApplication.worker.submit(task);
+        }
+    }
 }
Index: trunk/src/org/openstreetmap/josm/actions/DownloadAlongWayAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/DownloadAlongWayAction.java	(revision 14962)
+++ trunk/src/org/openstreetmap/josm/actions/DownloadAlongWayAction.java	(revision 14962)
@@ -0,0 +1,90 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.KeyEvent;
+import java.awt.geom.Path2D;
+import java.util.Collection;
+
+import javax.swing.JOptionPane;
+
+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.gui.MainApplication;
+import org.openstreetmap.josm.gui.PleaseWaitRunnable;
+import org.openstreetmap.josm.gui.help.HelpUtil;
+import org.openstreetmap.josm.gui.layer.gpx.DownloadAlongPanel;
+import org.openstreetmap.josm.tools.Shortcut;
+
+/**
+ * Calculate area around selected ways and split it into reasonable parts so
+ * that they can be downloaded.
+ *
+ */
+public class DownloadAlongWayAction extends DownloadAlongAction {
+
+    private static final String PREF_DOWNLOAD_ALONG_WAY_DISTANCE = "downloadAlongWay.distance";
+    private static final String PREF_DOWNLOAD_ALONG_WAY_AREA = "downloadAlongWay.area";
+
+    private static final String PREF_DOWNLOAD_ALONG_WAY_OSM = "downloadAlongWay.download.osm";
+    private static final String PREF_DOWNLOAD_ALONG_WAY_GPS = "downloadAlongWay.download.gps";
+
+    /**
+     * Create new {@link DownloadAlongWayAction}.
+     */
+    public DownloadAlongWayAction() {
+        super(tr("Download along..."), "download_along_way", tr("Download OSM data along the selected ways."),
+                Shortcut.registerShortcut("tools:download_along", tr("Tool: {0}", tr("Download Along")),
+                        KeyEvent.VK_D, Shortcut.ALT_SHIFT), true);
+    }
+
+    @Override
+    protected PleaseWaitRunnable createTask() {
+        Collection<Way> selectedWays = getLayerManager().getEditDataSet().getSelectedWays();
+
+        if (selectedWays.isEmpty()) {
+            JOptionPane.showMessageDialog(MainApplication.getMainFrame(), tr("Please select 1 or more ways to download along"));
+            return null;
+        }
+
+        final DownloadAlongPanel panel = new DownloadAlongPanel(
+                PREF_DOWNLOAD_ALONG_WAY_OSM, PREF_DOWNLOAD_ALONG_WAY_GPS,
+                PREF_DOWNLOAD_ALONG_WAY_DISTANCE, PREF_DOWNLOAD_ALONG_WAY_AREA, null);
+
+        if (0 != panel.showInDownloadDialog(tr("Download from OSM along selected ways"), HelpUtil.ht("/Tools/DownloadAlong"))) {
+            return null;
+        }
+
+        // Convert OSM ways to Path2D
+        Path2D gpxPath = new Path2D.Double();
+        for (Way way : selectedWays) {
+            boolean first = true;
+            for (Node p : way.getNodes()) {
+                if (first) {
+                    gpxPath.moveTo(p.lon(), p.lat());
+                    first = false;
+                } else {
+                    gpxPath.lineTo(p.lon(), p.lat());
+                }
+            }
+        }
+        return createCalcTask(gpxPath, panel, tr("Download from OSM along selected ways"));
+
+    }
+
+    @Override
+    protected void updateEnabledState() {
+        if (getLayerManager().getEditDataSet() == null) {
+            setEnabled(false);
+        } else {
+            updateEnabledState(getLayerManager().getEditDataSet().getSelected());
+        }
+    }
+
+    @Override
+    protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
+        setEnabled(selection.stream().anyMatch(Way.class::isInstance));
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/MainMenu.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainMenu.java	(revision 14961)
+++ trunk/src/org/openstreetmap/josm/gui/MainMenu.java	(revision 14962)
@@ -43,8 +43,10 @@
 import org.openstreetmap.josm.actions.DistributeAction;
 import org.openstreetmap.josm.actions.DownloadAction;
+import org.openstreetmap.josm.actions.DownloadAlongWayAction;
 import org.openstreetmap.josm.actions.DownloadNotesInViewAction;
 import org.openstreetmap.josm.actions.DownloadOsmInViewAction;
 import org.openstreetmap.josm.actions.DownloadPrimitiveAction;
 import org.openstreetmap.josm.actions.DownloadReferrersAction;
+import org.openstreetmap.josm.actions.DrawBoundariesOfDownloadedDataAction;
 import org.openstreetmap.josm.actions.DuplicateAction;
 import org.openstreetmap.josm.actions.ExitAction;
@@ -53,5 +55,4 @@
 import org.openstreetmap.josm.actions.FullscreenToggleAction;
 import org.openstreetmap.josm.actions.GpxExportAction;
-import org.openstreetmap.josm.actions.DrawBoundariesOfDownloadedDataAction;
 import org.openstreetmap.josm.actions.HelpAction;
 import org.openstreetmap.josm.actions.HistoryInfoAction;
@@ -282,4 +283,6 @@
     /** Tools / Update multipolygon */
     public final CreateMultipolygonAction updateMultipolygon = new CreateMultipolygonAction(true);
+    /** Tools / Download along way */
+    public final DownloadAlongWayAction downloadAlongWay = new DownloadAlongWayAction();
 
     /* Selection menu */
@@ -816,4 +819,5 @@
         add(toolsMenu, createMultipolygon);
         add(toolsMenu, updateMultipolygon);
+        add(toolsMenu, downloadAlongWay);
 
         // -- changeset manager toggle action
Index: trunk/src/org/openstreetmap/josm/gui/layer/gpx/DownloadAlongTrackAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/gpx/DownloadAlongTrackAction.java	(revision 14961)
+++ trunk/src/org/openstreetmap/josm/gui/layer/gpx/DownloadAlongTrackAction.java	(revision 14962)
@@ -4,20 +4,13 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.event.ActionEvent;
-import java.awt.geom.Area;
 import java.awt.geom.Path2D;
-import java.awt.geom.Rectangle2D;
 
 import org.openstreetmap.josm.actions.DownloadAlongAction;
-import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.gpx.GpxData;
 import org.openstreetmap.josm.data.gpx.GpxTrack;
 import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
 import org.openstreetmap.josm.data.gpx.WayPoint;
-import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.gui.help.HelpUtil;
-import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
-import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -51,5 +44,6 @@
     }
 
-    PleaseWaitRunnable createTask() {
+    @Override
+    protected PleaseWaitRunnable createTask() {
         final DownloadAlongPanel panel = new DownloadAlongPanel(
                 PREF_DOWNLOAD_ALONG_TRACK_OSM, PREF_DOWNLOAD_ALONG_TRACK_GPS,
@@ -62,16 +56,17 @@
         final int near = panel.getNear();
 
-        /*
-         * Find the average latitude for the data we're contemplating, so we can know how many
-         * metres per degree of longitude we have.
-         */
-        double latsum = 0;
-        int latcnt = 0;
+        // Convert the GPX data into a Path2D.
+        Path2D gpxPath = new Path2D.Double();
         if (near == NEAR_TRACK || near == NEAR_BOTH) {
             for (GpxTrack trk : data.tracks) {
                 for (GpxTrackSegment segment : trk.getSegments()) {
+                    boolean first = true;
                     for (WayPoint p : segment.getWayPoints()) {
-                        latsum += p.lat();
-                        latcnt++;
+                        if (first) {
+                            gpxPath.moveTo(p.lon(), p.lat());
+                            first = false;
+                        } else {
+                            gpxPath.lineTo(p.lon(), p.lat());
+                        }
                     }
                 }
@@ -80,124 +75,9 @@
         if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) {
             for (WayPoint p : data.waypoints) {
-                latsum += p.getCoor().lat();
-                latcnt++;
+                gpxPath.moveTo(p.lon(), p.lat());
+                gpxPath.closePath();
             }
         }
-        if (latcnt == 0) {
-            return null;
-        }
-        double avglat = latsum / latcnt;
-        double scale = Math.cos(Utils.toRadians(avglat));
-        /*
-         * Compute buffer zone extents and maximum bounding box size. Note that the maximum we
-         * ever offer is a bbox area of 0.002, while the API theoretically supports 0.25, but as
-         * soon as you touch any built-up area, that kind of bounding box will download forever
-         * and then stop because it has more than 50k nodes.
-         */
-        final double bufferDist = panel.getDistance();
-        final double maxArea = panel.getArea() / 10000.0 / scale;
-        final double bufferY = bufferDist / 100000.0;
-        final double bufferX = bufferY / scale;
-        final int totalTicks = latcnt;
-        // guess if a progress bar might be useful.
-        final boolean displayProgress = totalTicks > 200_000 && bufferY < 0.01;
-
-        class CalculateDownloadArea extends PleaseWaitRunnable {
-
-            private final Path2D path = new Path2D.Double();
-            private boolean cancel;
-            private int ticks;
-            private final Rectangle2D r = new Rectangle2D.Double();
-
-            CalculateDownloadArea() {
-                super(tr("Calculating Download Area"), displayProgress ? null : NullProgressMonitor.INSTANCE, false);
-            }
-
-            @Override
-            protected void cancel() {
-                cancel = true;
-            }
-
-            @Override
-            protected void finish() {
-                // Do nothing
-            }
-
-            @Override
-            protected void afterFinish() {
-                if (cancel) {
-                    return;
-                }
-                confirmAndDownloadAreas(new Area(path), maxArea, panel.isDownloadOsmData(), panel.isDownloadGpxData(),
-                        tr("Download from OSM along this track"), progressMonitor);
-            }
-
-            /**
-             * increase tick count by one, report progress every 100 ticks
-             */
-            private void tick() {
-                ticks++;
-                if (ticks % 100 == 0) {
-                    progressMonitor.worked(100);
-                }
-            }
-
-            /**
-             * calculate area for single, given way point and return new LatLon if the
-             * way point has been used to modify the area.
-             */
-            private LatLon calcAreaForWayPoint(WayPoint p, LatLon previous) {
-                tick();
-                LatLon c = p.getCoor();
-                if (previous == null || c.greatCircleDistance(previous) > bufferDist) {
-                    // we add a buffer around the point.
-                    r.setRect(c.lon() - bufferX, c.lat() - bufferY, 2 * bufferX, 2 * bufferY);
-                    path.append(r, false);
-                    return c;
-                }
-                return previous;
-            }
-
-            @Override
-            protected void realRun() {
-                progressMonitor.setTicksCount(totalTicks);
-                /*
-                 * Collect the combined area of all gpx points plus buffer zones around them. We ignore
-                 * points that lie closer to the previous point than the given buffer size because
-                 * otherwise this operation takes ages.
-                 */
-                LatLon previous = null;
-                if (near == NEAR_TRACK || near == NEAR_BOTH) {
-                    for (GpxTrack trk : data.tracks) {
-                        for (GpxTrackSegment segment : trk.getSegments()) {
-                            for (WayPoint p : segment.getWayPoints()) {
-                                if (cancel) {
-                                    return;
-                                }
-                                previous = calcAreaForWayPoint(p, previous);
-                            }
-                        }
-                    }
-                }
-                if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) {
-                    for (WayPoint p : data.waypoints) {
-                        if (cancel) {
-                            return;
-                        }
-                        previous = calcAreaForWayPoint(p, previous);
-                    }
-                }
-            }
-        }
-
-        return new CalculateDownloadArea();
-    }
-
-    @Override
-    public void actionPerformed(ActionEvent e) {
-        PleaseWaitRunnable task = createTask();
-        if (task != null) {
-            MainApplication.worker.submit(task);
-        }
+        return createCalcTask(gpxPath, panel, tr("Download from OSM along this track"));
     }
 }
Index: trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 14961)
+++ trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 14962)
@@ -146,5 +146,6 @@
             new DeprecatedPlugin("videomapping", tr("no longer required")),
             new DeprecatedPlugin("public_transport_layer", tr("replaced by new {0} plugin", "pt_assistant")),
-            new DeprecatedPlugin("lakewalker", tr("replaced by new {0} plugin", "scanaerial"))
+            new DeprecatedPlugin("lakewalker", tr("replaced by new {0} plugin", "scanaerial")),
+            new DeprecatedPlugin("download_along", inCore)
         );
     }
