001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.layer.gpx; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Component; 007import java.awt.geom.Path2D; 008import java.util.Collection; 009import java.util.List; 010import java.util.stream.Collectors; 011 012import javax.swing.Action; 013import javax.swing.JMenuItem; 014 015import org.openstreetmap.josm.actions.DownloadAlongAction; 016import org.openstreetmap.josm.data.gpx.GpxData; 017import org.openstreetmap.josm.data.gpx.WayPoint; 018import org.openstreetmap.josm.gui.PleaseWaitRunnable; 019import org.openstreetmap.josm.gui.help.HelpUtil; 020import org.openstreetmap.josm.gui.layer.GpxLayer; 021import org.openstreetmap.josm.gui.layer.Layer; 022import org.openstreetmap.josm.tools.Utils; 023 024/** 025 * Action that issues a series of download requests to the API, following the GPX track. 026 * 027 * @author fred 028 * @since 5715 029 */ 030public class DownloadAlongTrackAction extends DownloadAlongAction implements Layer.LayerAction, Layer.MultiLayerAction { 031 032 private static final int NEAR_TRACK = 0; 033 private static final int NEAR_WAYPOINTS = 1; 034 private static final int NEAR_BOTH = 2; 035 036 private static final String PREF_DOWNLOAD_ALONG_TRACK_OSM = "downloadAlongTrack.download.osm"; 037 private static final String PREF_DOWNLOAD_ALONG_TRACK_GPS = "downloadAlongTrack.download.gps"; 038 039 private static final String PREF_DOWNLOAD_ALONG_TRACK_DISTANCE = "downloadAlongTrack.distance"; 040 private static final String PREF_DOWNLOAD_ALONG_TRACK_AREA = "downloadAlongTrack.area"; 041 private static final String PREF_DOWNLOAD_ALONG_TRACK_NEAR = "downloadAlongTrack.near"; 042 043 private final transient Collection<GpxData> data; 044 045 /** 046 * Constructs a new {@code DownloadAlongTrackAction} 047 * @param data The GPX data used to download along 048 */ 049 public DownloadAlongTrackAction(Collection<GpxData> data) { 050 super(tr("Download from OSM along this track"), "downloadalongtrack", null, null, false); 051 this.data = data; 052 } 053 054 @Override 055 protected PleaseWaitRunnable createTask() { 056 final DownloadAlongPanel panel = new DownloadAlongPanel( 057 PREF_DOWNLOAD_ALONG_TRACK_OSM, PREF_DOWNLOAD_ALONG_TRACK_GPS, 058 PREF_DOWNLOAD_ALONG_TRACK_DISTANCE, PREF_DOWNLOAD_ALONG_TRACK_AREA, PREF_DOWNLOAD_ALONG_TRACK_NEAR); 059 060 int ret = panel.showInDownloadDialog(tr("Download from OSM along this track"), HelpUtil.ht("/Action/DownloadAlongTrack")); 061 if (0 != ret && 1 != ret) { 062 return null; 063 } 064 065 final int near = panel.getNear(); 066 067 // Convert the GPX data into a Path2D. 068 Path2D gpxPath = new Path2D.Double(); 069 if (near == NEAR_TRACK || near == NEAR_BOTH) { 070 data.stream().flatMap(GpxData::getTrackSegmentsStream).forEach(segment -> { 071 boolean first = true; 072 for (WayPoint p : segment.getWayPoints()) { 073 if (first) { 074 gpxPath.moveTo(p.lon(), p.lat()); 075 first = false; 076 } else { 077 gpxPath.lineTo(p.lon(), p.lat()); 078 } 079 } 080 }); 081 } 082 if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) { 083 data.stream().flatMap(d -> d.getWaypoints().stream()).forEach(p -> { 084 gpxPath.moveTo(p.lon(), p.lat()); 085 gpxPath.closePath(); 086 }); 087 } 088 return createCalcTask(gpxPath, panel, tr("Download from OSM along this track"), 1 == ret); 089 } 090 091 @Override 092 public Component createMenuComponent() { 093 return new JMenuItem(this); 094 } 095 096 @Override 097 public boolean supportLayers(List<Layer> layers) { 098 return !Utils.filteredCollection(layers, GpxLayer.class).isEmpty(); 099 } 100 101 @Override 102 public Action getMultiLayerAction(List<Layer> layers) { 103 final List<GpxData> gpxData = Utils.filteredCollection(layers, GpxLayer.class) 104 .stream().map(layer -> layer.data) 105 .collect(Collectors.toList()); 106 return new DownloadAlongTrackAction(gpxData); 107 } 108}