Ticket #17551: 17551-v2.patch
File 17551-v2.patch, 23.6 KB (added by , 5 years ago) |
---|
-
src/org/openstreetmap/josm/actions/DownloadAlongAction.java
5 5 6 6 import java.awt.GraphicsEnvironment; 7 7 import java.awt.GridBagLayout; 8 import java.awt.event.ActionEvent; 8 9 import java.awt.geom.Area; 10 import java.awt.geom.Path2D; 11 import java.awt.geom.PathIterator; 9 12 import java.awt.geom.Rectangle2D; 10 13 import java.util.ArrayList; 11 14 import java.util.Collection; … … 17 20 import javax.swing.JPanel; 18 21 19 22 import org.openstreetmap.josm.actions.downloadtasks.DownloadTaskList; 23 import org.openstreetmap.josm.data.coor.LatLon; 20 24 import org.openstreetmap.josm.gui.MainApplication; 21 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 25 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 26 import org.openstreetmap.josm.gui.layer.gpx.DownloadAlongPanel; 27 import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 22 28 import org.openstreetmap.josm.gui.progress.swing.PleaseWaitProgressMonitor; 23 29 import org.openstreetmap.josm.tools.GBC; 30 import org.openstreetmap.josm.tools.Logging; 24 31 import org.openstreetmap.josm.tools.Shortcut; 32 import org.openstreetmap.josm.tools.Utils; 25 33 26 34 /** 27 35 * Abstract superclass of DownloadAlongTrackAction and DownloadAlongWayAction … … 30 38 public abstract class DownloadAlongAction extends JosmAction { 31 39 32 40 /** 41 * Sub classes must override this method. 42 * @return the task to start or null if nothing to do 43 */ 44 protected abstract PleaseWaitRunnable createTask(); 45 46 /** 33 47 * Constructs a new {@code DownloadAlongAction} 34 48 * @param name the action's text as displayed in the menu 35 49 * @param iconName the filename of the icon to use … … 97 111 * @param osmDownload Set to true if OSM data should be downloaded 98 112 * @param gpxDownload Set to true if GPX data should be downloaded 99 113 * @param title the title string for the confirmation dialog 100 * @param progressMonitor the progress monitor101 114 */ 102 protected static void confirmAndDownloadAreas(Area a, double maxArea, boolean osmDownload, boolean gpxDownload, String title, 103 ProgressMonitor progressMonitor) { 115 protected static void confirmAndDownloadAreas(Area a, double maxArea, boolean osmDownload, boolean gpxDownload, String title) { 104 116 List<Rectangle2D> toDownload = new ArrayList<>(); 105 117 addToDownload(a, a.getBounds(), toDownload, maxArea); 106 118 if (toDownload.isEmpty()) { … … 118 130 final Future<?> future = new DownloadTaskList().download(false, toDownload, osmDownload, gpxDownload, monitor); 119 131 waitFuture(future, monitor); 120 132 } 133 134 /** 135 * Calculate list of points between two given points so that the distance between two consecutive points is below a limit. 136 * @param p1 first point or null 137 * @param p2 second point (must not be null) 138 * @param bufferDist the maximum distance 139 * @return a list of points with at least one point (p2) and maybe more. 140 */ 141 protected static Collection<LatLon> calcBetweenPoints(LatLon p1, LatLon p2, double bufferDist) { 142 ArrayList<LatLon> intermediateNodes = new ArrayList<>(); 143 intermediateNodes.add(p2); 144 if (p1 != null && p2.greatCircleDistance(p1) > bufferDist) { 145 Double d = p2.greatCircleDistance(p1) / bufferDist; 146 int nbNodes = d.intValue(); 147 if (Logging.isDebugEnabled()) { 148 Logging.debug(tr("{0} intermediate nodes to download.", nbNodes)); 149 Logging.debug(tr("between {0} {1} and {2} {3}", p2.lat(), p2.lon(), p1.lat(), p1.lon())); 150 } 151 double latStep = (p2.lat() - p1.lat()) / (nbNodes + 1); 152 double lonStep = (p2.lon() - p1.lon()) / (nbNodes + 1); 153 for (int i = 1; i <= nbNodes; i++) { 154 LatLon intermediate = new LatLon(p1.lat() + i * latStep, p1.lon() + i * lonStep); 155 intermediateNodes.add(intermediate); 156 if (Logging.isTraceEnabled()) { 157 Logging.trace(tr(" adding {0} {1}", intermediate.lat(), intermediate.lon())); 158 } 159 } 160 } 161 return intermediateNodes; 162 } 163 164 /** 165 * Create task that downloads areas along the given path using the values specified in the panel. 166 * @param alongPath the path along which the areas are to be downloaded 167 * @param panel the panel that was displayed to the user and now contains his selections 168 * @param confirmTitle the title to display in the confirmation panel 169 * @return the task or null if canceled by user 170 */ 171 protected PleaseWaitRunnable createCalcTask(Path2D alongPath, DownloadAlongPanel panel, String confirmTitle) { 172 /* 173 * Find the average latitude for the data we're contemplating, so we can know how many 174 * metres per degree of longitude we have. 175 */ 176 double latsum = 0; 177 int latcnt = 0; 178 final PathIterator pit = alongPath.getPathIterator(null); 179 final double[] res = new double[6]; 180 while (!pit.isDone()) { 181 int type = pit.currentSegment(res); 182 if (type == PathIterator.SEG_LINETO || type == PathIterator.SEG_MOVETO) { 183 latsum += res[1]; 184 latcnt++; 185 } 186 pit.next(); 187 } 188 if (latcnt == 0) { 189 return null; 190 } 191 final double avglat = latsum / latcnt; 192 final double scale = Math.cos(Utils.toRadians(avglat)); 193 194 /* 195 * Compute buffer zone extents and maximum bounding box size. Note that the maximum we 196 * ever offer is a bbox area of 0.002, while the API theoretically supports 0.25, but as 197 * soon as you touch any built-up area, that kind of bounding box will download forever 198 * and then stop because it has more than 50k nodes. 199 */ 200 final double bufferDist = panel.getDistance(); 201 final double maxArea = panel.getArea() / 10000.0 / scale; 202 final double bufferY = bufferDist / 100000.0; 203 final double bufferX = bufferY / scale; 204 final int totalTicks = latcnt; 205 // guess if a progress bar might be useful. 206 final boolean displayProgress = totalTicks > 20_000 && bufferY < 0.01; 207 208 class CalculateDownloadArea extends PleaseWaitRunnable { 209 210 private final Path2D downloadPath = new Path2D.Double(); 211 private boolean cancel; 212 private int ticks; 213 private final Rectangle2D r = new Rectangle2D.Double(); 214 215 CalculateDownloadArea() { 216 super(tr("Calculating Download Area"), displayProgress ? null : NullProgressMonitor.INSTANCE, false); 217 } 218 219 @Override 220 protected void cancel() { 221 cancel = true; 222 } 223 224 @Override 225 protected void finish() { 226 // Do nothing 227 } 228 229 @Override 230 protected void afterFinish() { 231 if (cancel) { 232 return; 233 } 234 confirmAndDownloadAreas(new Area(downloadPath), maxArea, panel.isDownloadOsmData(), panel.isDownloadGpxData(), 235 confirmTitle); 236 } 237 238 /** 239 * increase tick count by one, report progress every 100 ticks 240 */ 241 private void tick() { 242 ticks++; 243 if (ticks % 100 == 0) { 244 progressMonitor.worked(100); 245 } 246 } 247 248 /** 249 * calculate area enclosing a single point 250 */ 251 private void calcAreaForWayPoint(LatLon c) { 252 r.setRect(c.lon() - bufferX, c.lat() - bufferY, 2 * bufferX, 2 * bufferY); 253 downloadPath.append(r, false); 254 } 255 256 @Override 257 protected void realRun() { 258 progressMonitor.setTicksCount(totalTicks); 259 PathIterator pit = alongPath.getPathIterator(null); 260 double[] res = new double[6]; 261 LatLon previous = null; 262 while (!pit.isDone()) { 263 int type = pit.currentSegment(res); 264 LatLon c = new LatLon(res[1], res[0]); 265 if (type == PathIterator.SEG_LINETO) { 266 tick(); 267 for (LatLon d : calcBetweenPoints(previous, c, bufferDist)) { 268 calcAreaForWayPoint(d); 269 } 270 previous = c; 271 } else if (type == PathIterator.SEG_MOVETO) { 272 previous = c; 273 tick(); 274 calcAreaForWayPoint(c); 275 } 276 pit.next(); 277 } 278 } 279 } 280 281 return new CalculateDownloadArea(); 282 } 283 284 @Override 285 public void actionPerformed(ActionEvent e) { 286 PleaseWaitRunnable task = createTask(); 287 if (task != null) { 288 MainApplication.worker.submit(task); 289 } 290 } 121 291 } -
src/org/openstreetmap/josm/actions/DownloadAlongWayAction.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.actions; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 import java.awt.event.KeyEvent; 7 import java.awt.geom.Path2D; 8 import java.util.Collection; 9 10 import javax.swing.JOptionPane; 11 12 import org.openstreetmap.josm.data.osm.Node; 13 import org.openstreetmap.josm.data.osm.OsmPrimitive; 14 import org.openstreetmap.josm.data.osm.Way; 15 import org.openstreetmap.josm.gui.MainApplication; 16 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 17 import org.openstreetmap.josm.gui.help.HelpUtil; 18 import org.openstreetmap.josm.gui.layer.gpx.DownloadAlongPanel; 19 import org.openstreetmap.josm.tools.Shortcut; 20 21 /** 22 * Calculate area around selected ways and split it into reasonable parts so 23 * that they can be downloaded. 24 * 25 */ 26 public class DownloadAlongWayAction extends DownloadAlongAction { 27 28 private static final String PREF_DOWNLOAD_ALONG_WAY_DISTANCE = "downloadAlongWay.distance"; 29 private static final String PREF_DOWNLOAD_ALONG_WAY_AREA = "downloadAlongWay.area"; 30 31 private static final String PREF_DOWNLOAD_ALONG_WAY_OSM = "downloadAlongWay.download.osm"; 32 private static final String PREF_DOWNLOAD_ALONG_WAY_GPS = "downloadAlongWay.download.gps"; 33 34 /** 35 * Create new {@link DownloadAlongWayAction}. 36 */ 37 public DownloadAlongWayAction() { 38 super(tr("Download along..."), "download_along_way", tr("Download OSM data along the selected ways."), 39 Shortcut.registerShortcut("tools:download_along", tr("Tool: {0}", tr("Download Along")), 40 KeyEvent.VK_D, Shortcut.ALT_SHIFT), true); 41 } 42 43 @Override 44 protected PleaseWaitRunnable createTask() { 45 Collection<Way> selectedWays = getLayerManager().getEditDataSet().getSelectedWays(); 46 47 if (selectedWays.isEmpty()) { 48 JOptionPane.showMessageDialog(MainApplication.getMainFrame(), tr("Please select 1 or more ways to download along")); 49 return null; 50 } 51 52 final DownloadAlongPanel panel = new DownloadAlongPanel( 53 PREF_DOWNLOAD_ALONG_WAY_OSM, PREF_DOWNLOAD_ALONG_WAY_GPS, 54 PREF_DOWNLOAD_ALONG_WAY_DISTANCE, PREF_DOWNLOAD_ALONG_WAY_AREA, null); 55 56 if (0 != panel.showInDownloadDialog(tr("Download from OSM along selected ways"), HelpUtil.ht("/Tools/DownloadAlong"))) { 57 return null; 58 } 59 60 // Convert OSM ways to Path2D 61 Path2D gpxPath = new Path2D.Double(); 62 for (Way way : selectedWays) { 63 boolean first = true; 64 for (Node p : way.getNodes()) { 65 if (first) { 66 gpxPath.moveTo(p.lon(), p.lat()); 67 first = false; 68 } else { 69 gpxPath.lineTo(p.lon(), p.lat()); 70 } 71 } 72 } 73 return createCalcTask(gpxPath, panel, tr("Download from OSM along selected ways")); 74 75 } 76 77 @Override 78 protected void updateEnabledState() { 79 if (getLayerManager().getEditDataSet() == null) { 80 setEnabled(false); 81 } else { 82 updateEnabledState(getLayerManager().getEditDataSet().getSelected()); 83 } 84 } 85 86 @Override 87 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) { 88 setEnabled(selection.stream().anyMatch(Way.class::isInstance)); 89 } 90 } -
src/org/openstreetmap/josm/gui/MainMenu.java
42 42 import org.openstreetmap.josm.actions.DialogsToggleAction; 43 43 import org.openstreetmap.josm.actions.DistributeAction; 44 44 import org.openstreetmap.josm.actions.DownloadAction; 45 import org.openstreetmap.josm.actions.DownloadAlongWayAction; 45 46 import org.openstreetmap.josm.actions.DownloadNotesInViewAction; 46 47 import org.openstreetmap.josm.actions.DownloadOsmInViewAction; 47 48 import org.openstreetmap.josm.actions.DownloadPrimitiveAction; 48 49 import org.openstreetmap.josm.actions.DownloadReferrersAction; 50 import org.openstreetmap.josm.actions.DrawBoundariesOfDownloadedDataAction; 49 51 import org.openstreetmap.josm.actions.DuplicateAction; 50 52 import org.openstreetmap.josm.actions.ExitAction; 51 53 import org.openstreetmap.josm.actions.ExpertToggleAction; … … 52 54 import org.openstreetmap.josm.actions.FollowLineAction; 53 55 import org.openstreetmap.josm.actions.FullscreenToggleAction; 54 56 import org.openstreetmap.josm.actions.GpxExportAction; 55 import org.openstreetmap.josm.actions.DrawBoundariesOfDownloadedDataAction;56 57 import org.openstreetmap.josm.actions.HelpAction; 57 58 import org.openstreetmap.josm.actions.HistoryInfoAction; 58 59 import org.openstreetmap.josm.actions.HistoryInfoWebAction; … … 281 282 public final CreateMultipolygonAction createMultipolygon = new CreateMultipolygonAction(false); 282 283 /** Tools / Update multipolygon */ 283 284 public final CreateMultipolygonAction updateMultipolygon = new CreateMultipolygonAction(true); 285 /** Tools / Download along way */ 286 public final DownloadAlongWayAction downloadAlongWay = new DownloadAlongWayAction(); 284 287 285 288 /* Selection menu */ 286 289 /** Selection / Select All */ … … 815 818 add(toolsMenu, joinAreas); 816 819 add(toolsMenu, createMultipolygon); 817 820 add(toolsMenu, updateMultipolygon); 821 add(toolsMenu, downloadAlongWay); 818 822 819 823 // -- changeset manager toggle action 820 824 final JCheckBoxMenuItem mi = MainMenu.addWithCheckbox(windowMenu, changesetManager, -
src/org/openstreetmap/josm/gui/layer/gpx/DownloadAlongTrackAction.java
3 3 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.awt.event.ActionEvent;7 import java.awt.geom.Area;8 6 import java.awt.geom.Path2D; 9 import java.awt.geom.Rectangle2D;10 7 11 8 import org.openstreetmap.josm.actions.DownloadAlongAction; 12 import org.openstreetmap.josm.data.coor.LatLon;13 9 import org.openstreetmap.josm.data.gpx.GpxData; 14 10 import org.openstreetmap.josm.data.gpx.GpxTrack; 15 11 import org.openstreetmap.josm.data.gpx.GpxTrackSegment; 16 12 import org.openstreetmap.josm.data.gpx.WayPoint; 17 import org.openstreetmap.josm.gui.MainApplication;18 13 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 19 14 import org.openstreetmap.josm.gui.help.HelpUtil; 20 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;21 import org.openstreetmap.josm.tools.Utils;22 15 23 16 /** 24 17 * Action that issues a series of download requests to the API, following the GPX track. … … 50 43 this.data = data; 51 44 } 52 45 53 PleaseWaitRunnable createTask() { 46 @Override 47 protected PleaseWaitRunnable createTask() { 54 48 final DownloadAlongPanel panel = new DownloadAlongPanel( 55 49 PREF_DOWNLOAD_ALONG_TRACK_OSM, PREF_DOWNLOAD_ALONG_TRACK_GPS, 56 50 PREF_DOWNLOAD_ALONG_TRACK_DISTANCE, PREF_DOWNLOAD_ALONG_TRACK_AREA, PREF_DOWNLOAD_ALONG_TRACK_NEAR); … … 61 55 62 56 final int near = panel.getNear(); 63 57 64 /* 65 * Find the average latitude for the data we're contemplating, so we can know how many 66 * metres per degree of longitude we have. 67 */ 68 double latsum = 0; 69 int latcnt = 0; 58 // Convert the GPX data into a Path2D. 59 Path2D gpxPath = new Path2D.Double(); 70 60 if (near == NEAR_TRACK || near == NEAR_BOTH) { 71 61 for (GpxTrack trk : data.tracks) { 72 62 for (GpxTrackSegment segment : trk.getSegments()) { 63 boolean first = true; 73 64 for (WayPoint p : segment.getWayPoints()) { 74 latsum += p.lat(); 75 latcnt++; 65 if (first) { 66 gpxPath.moveTo(p.lon(), p.lat()); 67 first = false; 68 } else { 69 gpxPath.lineTo(p.lon(), p.lat()); 70 } 76 71 } 77 72 } 78 73 } … … 79 74 } 80 75 if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) { 81 76 for (WayPoint p : data.waypoints) { 82 latsum += p.getCoor().lat();83 latcnt++;77 gpxPath.moveTo(p.lon(), p.lat()); 78 gpxPath.closePath(); 84 79 } 85 80 } 86 if (latcnt == 0) { 87 return null; 88 } 89 double avglat = latsum / latcnt; 90 double scale = Math.cos(Utils.toRadians(avglat)); 91 /* 92 * Compute buffer zone extents and maximum bounding box size. Note that the maximum we 93 * ever offer is a bbox area of 0.002, while the API theoretically supports 0.25, but as 94 * soon as you touch any built-up area, that kind of bounding box will download forever 95 * and then stop because it has more than 50k nodes. 96 */ 97 final double bufferDist = panel.getDistance(); 98 final double maxArea = panel.getArea() / 10000.0 / scale; 99 final double bufferY = bufferDist / 100000.0; 100 final double bufferX = bufferY / scale; 101 final int totalTicks = latcnt; 102 // guess if a progress bar might be useful. 103 final boolean displayProgress = totalTicks > 200_000 && bufferY < 0.01; 104 105 class CalculateDownloadArea extends PleaseWaitRunnable { 106 107 private final Path2D path = new Path2D.Double(); 108 private boolean cancel; 109 private int ticks; 110 private final Rectangle2D r = new Rectangle2D.Double(); 111 112 CalculateDownloadArea() { 113 super(tr("Calculating Download Area"), displayProgress ? null : NullProgressMonitor.INSTANCE, false); 114 } 115 116 @Override 117 protected void cancel() { 118 cancel = true; 119 } 120 121 @Override 122 protected void finish() { 123 // Do nothing 124 } 125 126 @Override 127 protected void afterFinish() { 128 if (cancel) { 129 return; 130 } 131 confirmAndDownloadAreas(new Area(path), maxArea, panel.isDownloadOsmData(), panel.isDownloadGpxData(), 132 tr("Download from OSM along this track"), progressMonitor); 133 } 134 135 /** 136 * increase tick count by one, report progress every 100 ticks 137 */ 138 private void tick() { 139 ticks++; 140 if (ticks % 100 == 0) { 141 progressMonitor.worked(100); 142 } 143 } 144 145 /** 146 * calculate area for single, given way point and return new LatLon if the 147 * way point has been used to modify the area. 148 */ 149 private LatLon calcAreaForWayPoint(WayPoint p, LatLon previous) { 150 tick(); 151 LatLon c = p.getCoor(); 152 if (previous == null || c.greatCircleDistance(previous) > bufferDist) { 153 // we add a buffer around the point. 154 r.setRect(c.lon() - bufferX, c.lat() - bufferY, 2 * bufferX, 2 * bufferY); 155 path.append(r, false); 156 return c; 157 } 158 return previous; 159 } 160 161 @Override 162 protected void realRun() { 163 progressMonitor.setTicksCount(totalTicks); 164 /* 165 * Collect the combined area of all gpx points plus buffer zones around them. We ignore 166 * points that lie closer to the previous point than the given buffer size because 167 * otherwise this operation takes ages. 168 */ 169 LatLon previous = null; 170 if (near == NEAR_TRACK || near == NEAR_BOTH) { 171 for (GpxTrack trk : data.tracks) { 172 for (GpxTrackSegment segment : trk.getSegments()) { 173 for (WayPoint p : segment.getWayPoints()) { 174 if (cancel) { 175 return; 176 } 177 previous = calcAreaForWayPoint(p, previous); 178 } 179 } 180 } 181 } 182 if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) { 183 for (WayPoint p : data.waypoints) { 184 if (cancel) { 185 return; 186 } 187 previous = calcAreaForWayPoint(p, previous); 188 } 189 } 190 } 191 } 192 193 return new CalculateDownloadArea(); 81 return createCalcTask(gpxPath, panel, tr("Download from OSM along this track")); 194 82 } 195 196 @Override197 public void actionPerformed(ActionEvent e) {198 PleaseWaitRunnable task = createTask();199 if (task != null) {200 MainApplication.worker.submit(task);201 }202 }203 83 } -
src/org/openstreetmap/josm/plugins/PluginHandler.java
145 145 new DeprecatedPlugin("kendzi3d_Improved_by_Andrei", tr("no longer required")), 146 146 new DeprecatedPlugin("videomapping", tr("no longer required")), 147 147 new DeprecatedPlugin("public_transport_layer", tr("replaced by new {0} plugin", "pt_assistant")), 148 new DeprecatedPlugin("lakewalker", tr("replaced by new {0} plugin", "scanaerial")) 148 new DeprecatedPlugin("lakewalker", tr("replaced by new {0} plugin", "scanaerial")), 149 new DeprecatedPlugin("download_along", inCore) 149 150 ); 150 151 } 151 152