source: josm/trunk/src/org/openstreetmap/josm/gui/layer/gpx/DownloadAlongTrackAction.java@ 12167

Last change on this file since 12167 was 12167, checked in by michael2402, 7 years ago

Make WayPoint implement ILatLon.

  • Property svn:eol-style set to native
File size: 7.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.layer.gpx;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.event.ActionEvent;
7import java.awt.geom.Area;
8import java.awt.geom.Rectangle2D;
9
10import org.openstreetmap.josm.Main;
11import org.openstreetmap.josm.actions.DownloadAlongAction;
12import org.openstreetmap.josm.data.coor.LatLon;
13import org.openstreetmap.josm.data.gpx.GpxData;
14import org.openstreetmap.josm.data.gpx.GpxTrack;
15import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
16import org.openstreetmap.josm.data.gpx.WayPoint;
17import org.openstreetmap.josm.gui.PleaseWaitRunnable;
18import org.openstreetmap.josm.gui.help.HelpUtil;
19import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
20import org.openstreetmap.josm.tools.Utils;
21
22/**
23 * Action that issues a series of download requests to the API, following the GPX track.
24 *
25 * @author fred
26 * @since 5715
27 */
28public class DownloadAlongTrackAction extends DownloadAlongAction {
29
30 private static final int NEAR_TRACK = 0;
31 private static final int NEAR_WAYPOINTS = 1;
32 private static final int NEAR_BOTH = 2;
33
34 private static final String PREF_DOWNLOAD_ALONG_TRACK_OSM = "downloadAlongTrack.download.osm";
35 private static final String PREF_DOWNLOAD_ALONG_TRACK_GPS = "downloadAlongTrack.download.gps";
36
37 private static final String PREF_DOWNLOAD_ALONG_TRACK_DISTANCE = "downloadAlongTrack.distance";
38 private static final String PREF_DOWNLOAD_ALONG_TRACK_AREA = "downloadAlongTrack.area";
39 private static final String PREF_DOWNLOAD_ALONG_TRACK_NEAR = "downloadAlongTrack.near";
40
41 private final transient GpxData data;
42
43 /**
44 * Constructs a new {@code DownloadAlongTrackAction}
45 * @param data The GPX data used to download along
46 */
47 public DownloadAlongTrackAction(GpxData data) {
48 super(tr("Download from OSM along this track"), "downloadalongtrack", null, null, false);
49 this.data = data;
50 }
51
52 PleaseWaitRunnable createTask() {
53 final DownloadAlongPanel panel = new DownloadAlongPanel(
54 PREF_DOWNLOAD_ALONG_TRACK_OSM, PREF_DOWNLOAD_ALONG_TRACK_GPS,
55 PREF_DOWNLOAD_ALONG_TRACK_DISTANCE, PREF_DOWNLOAD_ALONG_TRACK_AREA, PREF_DOWNLOAD_ALONG_TRACK_NEAR);
56
57 if (0 != panel.showInDownloadDialog(tr("Download from OSM along this track"), HelpUtil.ht("/Action/DownloadAlongTrack"))) {
58 return null;
59 }
60
61 final int near = panel.getNear();
62
63 /*
64 * Find the average latitude for the data we're contemplating, so we can know how many
65 * metres per degree of longitude we have.
66 */
67 double latsum = 0;
68 int latcnt = 0;
69 if (near == NEAR_TRACK || near == NEAR_BOTH) {
70 for (GpxTrack trk : data.tracks) {
71 for (GpxTrackSegment segment : trk.getSegments()) {
72 for (WayPoint p : segment.getWayPoints()) {
73 latsum += p.lat();
74 latcnt++;
75 }
76 }
77 }
78 }
79 if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) {
80 for (WayPoint p : data.waypoints) {
81 latsum += p.getCoor().lat();
82 latcnt++;
83 }
84 }
85 if (latcnt == 0) {
86 return null;
87 }
88 double avglat = latsum / latcnt;
89 double scale = Math.cos(Utils.toRadians(avglat));
90 /*
91 * Compute buffer zone extents and maximum bounding box size. Note that the maximum we
92 * ever offer is a bbox area of 0.002, while the API theoretically supports 0.25, but as
93 * soon as you touch any built-up area, that kind of bounding box will download forever
94 * and then stop because it has more than 50k nodes.
95 */
96 final double bufferDist = panel.getDistance();
97 final double maxArea = panel.getArea() / 10000.0 / scale;
98 final double bufferY = bufferDist / 100000.0;
99 final double bufferX = bufferY / scale;
100 final int totalTicks = latcnt;
101 // guess if a progress bar might be useful.
102 final boolean displayProgress = totalTicks > 2000 && bufferY < 0.01;
103
104 class CalculateDownloadArea extends PleaseWaitRunnable {
105
106 private final Area a = new Area();
107 private boolean cancel;
108 private int ticks;
109 private final Rectangle2D r = new Rectangle2D.Double();
110
111 CalculateDownloadArea() {
112 super(tr("Calculating Download Area"), displayProgress ? null : NullProgressMonitor.INSTANCE, false);
113 }
114
115 @Override
116 protected void cancel() {
117 cancel = true;
118 }
119
120 @Override
121 protected void finish() {
122 // Do nothing
123 }
124
125 @Override
126 protected void afterFinish() {
127 if (cancel) {
128 return;
129 }
130 confirmAndDownloadAreas(a, maxArea, panel.isDownloadOsmData(), panel.isDownloadGpxData(),
131 tr("Download from OSM along this track"), progressMonitor);
132 }
133
134 /**
135 * increase tick count by one, report progress every 100 ticks
136 */
137 private void tick() {
138 ticks++;
139 if (ticks % 100 == 0) {
140 progressMonitor.worked(100);
141 }
142 }
143
144 /**
145 * calculate area for single, given way point and return new LatLon if the
146 * way point has been used to modify the area.
147 */
148 private LatLon calcAreaForWayPoint(WayPoint p, LatLon previous) {
149 tick();
150 LatLon c = p.getCoor();
151 if (previous == null || c.greatCircleDistance(previous) > bufferDist) {
152 // we add a buffer around the point.
153 r.setRect(c.lon() - bufferX, c.lat() - bufferY, 2 * bufferX, 2 * bufferY);
154 a.add(new Area(r));
155 return c;
156 }
157 return previous;
158 }
159
160 @Override
161 protected void realRun() {
162 progressMonitor.setTicksCount(totalTicks);
163 /*
164 * Collect the combined area of all gpx points plus buffer zones around them. We ignore
165 * points that lie closer to the previous point than the given buffer size because
166 * otherwise this operation takes ages.
167 */
168 LatLon previous = null;
169 if (near == NEAR_TRACK || near == NEAR_BOTH) {
170 for (GpxTrack trk : data.tracks) {
171 for (GpxTrackSegment segment : trk.getSegments()) {
172 for (WayPoint p : segment.getWayPoints()) {
173 if (cancel) {
174 return;
175 }
176 previous = calcAreaForWayPoint(p, previous);
177 }
178 }
179 }
180 }
181 if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) {
182 for (WayPoint p : data.waypoints) {
183 if (cancel) {
184 return;
185 }
186 previous = calcAreaForWayPoint(p, previous);
187 }
188 }
189 }
190 }
191
192 return new CalculateDownloadArea();
193 }
194
195 @Override
196 public void actionPerformed(ActionEvent e) {
197 PleaseWaitRunnable task = createTask();
198 if (task != null) {
199 Main.worker.submit(task);
200 }
201 }
202}
Note: See TracBrowser for help on using the repository browser.