Ignore:
Timestamp:
2019-04-05T09:35:22+02:00 (5 years ago)
Author:
GerdP
Message:

fix #17551: Download along track doesn't completely download areas along the track

  • merge plugin code from plugin download_along into core
  • use common code base for actions DownloadAlongTrackAction and DownloadAlongWayAction
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/layer/gpx/DownloadAlongTrackAction.java

    r14875 r14962  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    6 import java.awt.event.ActionEvent;
    7 import java.awt.geom.Area;
    86import java.awt.geom.Path2D;
    9 import java.awt.geom.Rectangle2D;
    107
    118import org.openstreetmap.josm.actions.DownloadAlongAction;
    12 import org.openstreetmap.josm.data.coor.LatLon;
    139import org.openstreetmap.josm.data.gpx.GpxData;
    1410import org.openstreetmap.josm.data.gpx.GpxTrack;
    1511import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
    1612import org.openstreetmap.josm.data.gpx.WayPoint;
    17 import org.openstreetmap.josm.gui.MainApplication;
    1813import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    1914import org.openstreetmap.josm.gui.help.HelpUtil;
    20 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    21 import org.openstreetmap.josm.tools.Utils;
    2215
    2316/**
     
    5144    }
    5245
    53     PleaseWaitRunnable createTask() {
     46    @Override
     47    protected PleaseWaitRunnable createTask() {
    5448        final DownloadAlongPanel panel = new DownloadAlongPanel(
    5549                PREF_DOWNLOAD_ALONG_TRACK_OSM, PREF_DOWNLOAD_ALONG_TRACK_GPS,
     
    6256        final int near = panel.getNear();
    6357
    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();
    7060        if (near == NEAR_TRACK || near == NEAR_BOTH) {
    7161            for (GpxTrack trk : data.tracks) {
    7262                for (GpxTrackSegment segment : trk.getSegments()) {
     63                    boolean first = true;
    7364                    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                        }
    7671                    }
    7772                }
     
    8075        if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) {
    8176            for (WayPoint p : data.waypoints) {
    82                 latsum += p.getCoor().lat();
    83                 latcnt++;
     77                gpxPath.moveTo(p.lon(), p.lat());
     78                gpxPath.closePath();
    8479            }
    8580        }
    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();
    194     }
    195 
    196     @Override
    197     public void actionPerformed(ActionEvent e) {
    198         PleaseWaitRunnable task = createTask();
    199         if (task != null) {
    200             MainApplication.worker.submit(task);
    201         }
     81        return createCalcTask(gpxPath, panel, tr("Download from OSM along this track"));
    20282    }
    20383}
Note: See TracChangeset for help on using the changeset viewer.