Changeset 4323 in josm


Ignore:
Timestamp:
2011-08-20T17:05:16+02:00 (13 years ago)
Author:
xeen
Message:

fix #3247 by showing a progress report for long calculations.

File:
1 edited

Legend:

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

    r4282 r4323  
    6565import org.openstreetmap.josm.gui.MapView;
    6666import org.openstreetmap.josm.gui.NavigatableComponent;
     67import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    6768import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
    6869import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
     
    7273import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    7374import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
     75import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    7476import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    7577import org.openstreetmap.josm.io.JpgImporter;
     
    828830     */
    829831    public class DownloadAlongTrackAction extends AbstractAction {
     832        final static int NEAR_TRACK=0;
     833        final static int NEAR_WAYPOINTS=1;
     834        final static int NEAR_BOTH=2;
     835        final Integer dist[] = { 5000, 500, 50 };
     836        final Integer area[] = { 20, 10, 5, 1 };
     837
    830838        public DownloadAlongTrackAction() {
    831839            super(tr("Download from OSM along this track"), ImageProvider.get("downloadalongtrack"));
     
    834842        @Override
    835843        public void actionPerformed(ActionEvent e) {
     844            /*
     845             * build selection dialog
     846             */
    836847            JPanel msg = new JPanel(new GridBagLayout());
    837             Integer dist[] = { 5000, 500, 50 };
    838             Integer area[] = { 20, 10, 5, 1 };
    839848
    840849            msg.add(new JLabel(tr("Download everything within:")), GBC.eol());
     
    858867            msg.add(new JLabel(tr("Download near:")), GBC.eol());
    859868            JList downloadNear = new JList(new String[] { tr("track only"), tr("waypoints only"), tr("track and waypoints") });
    860             int NEAR_TRACK=0;
    861             int NEAR_WAYPOINTS=1;
    862             int NEAR_BOTH=2;
    863869
    864870            downloadNear.setSelectedIndex(Main.pref.getInteger(PREF_DOWNLOAD_ALONG_TRACK_NEAR, 0));
     
    882888            Main.pref.putInteger(PREF_DOWNLOAD_ALONG_TRACK_DISTANCE, buffer.getSelectedIndex());
    883889            Main.pref.putInteger(PREF_DOWNLOAD_ALONG_TRACK_AREA, maxRect.getSelectedIndex());
    884             int near = downloadNear.getSelectedIndex();
     890            final int near = downloadNear.getSelectedIndex();
    885891            Main.pref.putInteger(PREF_DOWNLOAD_ALONG_TRACK_NEAR, near);
    886892
     
    920926             */
    921927            Integer i = buffer.getSelectedIndex();
    922             int buffer_dist = dist[i < 0 ? 0 : i];
    923             double buffer_y = buffer_dist / 100000.0;
    924             double buffer_x = buffer_y / scale;
     928            final int buffer_dist = dist[i < 0 ? 0 : i];
    925929            i = maxRect.getSelectedIndex();
    926             double max_area = area[i < 0 ? 0 : i] / 10000.0 / scale;
    927             Area a = new Area();
    928             Rectangle2D r = new Rectangle2D.Double();
    929 
    930             /*
    931              * Collect the combined area of all gpx points plus buffer zones around them. We ignore
    932              * points that lie closer to the previous point than the given buffer size because
    933              * otherwise this operation takes ages.
    934              */
    935             LatLon previous = null;
    936             if (near == NEAR_TRACK || near == NEAR_BOTH) {
    937                 for (GpxTrack trk : data.tracks) {
    938                     for (GpxTrackSegment segment : trk.getSegments()) {
    939                         for (WayPoint p : segment.getWayPoints()) {
    940                             LatLon c = p.getCoor();
    941                             if (previous == null || c.greatCircleDistance(previous) > buffer_dist) {
    942                                 // we add a buffer around the point.
    943                                 r.setRect(c.lon() - buffer_x, c.lat() - buffer_y, 2 * buffer_x, 2 * buffer_y);
    944                                 a.add(new Area(r));
    945                                 previous = c;
    946                             }
    947                         }
    948                     }
    949                 }
    950             }
    951             if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) {
    952                 for (WayPoint p : data.waypoints) {
     930            final double max_area = area[i < 0 ? 0 : i] / 10000.0 / scale;
     931            final double buffer_y = buffer_dist / 100000.0;
     932            final double buffer_x = buffer_y / scale;
     933
     934            final int totalTicks = latcnt;
     935            // guess if a progress bar might be useful.
     936            final boolean displayProgress = totalTicks > 2000 && buffer_y < 0.01;
     937
     938            class CalculateDownloadArea extends PleaseWaitRunnable {
     939                private Area a = new Area();
     940                private boolean cancel = false;
     941                private int ticks = 0;
     942                private Rectangle2D r = new Rectangle2D.Double();
     943
     944                public CalculateDownloadArea() {
     945                    super(tr("Calculating Download Area"),
     946                            (displayProgress ? null : NullProgressMonitor.INSTANCE),
     947                            false);
     948                }
     949
     950                @Override
     951                protected void cancel() {
     952                    cancel = true;
     953                }
     954
     955                @Override
     956                protected void finish() {
     957                    if(cancel)
     958                        return;
     959                    confirmAndDownloadAreas(a, max_area, progressMonitor);
     960                }
     961
     962                /**
     963                 * increase tick count by one, report progress every 100 ticks
     964                 */
     965                private void tick() {
     966                    ticks++;
     967                    if(ticks % 100 == 0) {
     968                        progressMonitor.worked(100);
     969                    }
     970                }
     971
     972                /**
     973                 * calculate area for single, given way point and return new LatLon if the
     974                 * way point has been used to modify the area.
     975                 */
     976                private LatLon calcAreaForWayPoint(WayPoint p, LatLon previous) {
     977                    tick();
    953978                    LatLon c = p.getCoor();
    954979                    if (previous == null || c.greatCircleDistance(previous) > buffer_dist) {
     
    956981                        r.setRect(c.lon() - buffer_x, c.lat() - buffer_y, 2 * buffer_x, 2 * buffer_y);
    957982                        a.add(new Area(r));
    958                         previous = c;
    959                     }
    960                 }
    961             }
    962 
    963             /*
    964              * Area "a" now contains the hull that we would like to download data for. however we
    965              * can only download rectangles, so the following is an attempt at finding a number of
    966              * rectangles to download.
    967              *
    968              * The idea is simply: Start out with the full bounding box. If it is too large, then
    969              * split it in half and repeat recursively for each half until you arrive at something
    970              * small enough to download. The algorithm is improved by always using the intersection
    971              * between the rectangle and the actual desired area. For example, if you have a track
    972              * that goes like this: +----+ | /| | / | | / | |/ | +----+ then we would first look at
    973              * downloading the whole rectangle (assume it's too big), after that we split it in half
    974              * (upper and lower half), but we donot request the full upper and lower rectangle, only
    975              * the part of the upper/lower rectangle that actually has something in it.
    976              */
    977 
     983                        return c;
     984                    }
     985                    return previous;
     986                }
     987
     988                @Override
     989                protected void realRun() {
     990                    progressMonitor.setTicksCount(totalTicks);
     991                    /*
     992                     * Collect the combined area of all gpx points plus buffer zones around them. We ignore
     993                     * points that lie closer to the previous point than the given buffer size because
     994                     * otherwise this operation takes ages.
     995                     */
     996                    LatLon previous = null;
     997                    if (near == NEAR_TRACK || near == NEAR_BOTH) {
     998                        for (GpxTrack trk : data.tracks) {
     999                            for (GpxTrackSegment segment : trk.getSegments()) {
     1000                                for (WayPoint p : segment.getWayPoints()) {
     1001                                    if(cancel)
     1002                                        return;
     1003                                    previous = calcAreaForWayPoint(p, previous);
     1004                                }
     1005                            }
     1006                        }
     1007                    }
     1008                    if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) {
     1009                        for (WayPoint p : data.waypoints) {
     1010                            if(cancel)
     1011                                return;
     1012                            previous = calcAreaForWayPoint(p, previous);
     1013                        }
     1014                    }
     1015                }
     1016            }
     1017
     1018            Main.worker.submit(new CalculateDownloadArea());
     1019        }
     1020
     1021        /**
     1022         * Area "a" contains the hull that we would like to download data for. however we
     1023         * can only download rectangles, so the following is an attempt at finding a number of
     1024         * rectangles to download.
     1025         *
     1026         * The idea is simply: Start out with the full bounding box. If it is too large, then
     1027         * split it in half and repeat recursively for each half until you arrive at something
     1028         * small enough to download. The algorithm is improved by always using the intersection
     1029         * between the rectangle and the actual desired area. For example, if you have a track
     1030         * that goes like this: +----+ | /| | / | | / | |/ | +----+ then we would first look at
     1031         * downloading the whole rectangle (assume it's too big), after that we split it in half
     1032         * (upper and lower half), but we donot request the full upper and lower rectangle, only
     1033         * the part of the upper/lower rectangle that actually has something in it.
     1034         *
     1035         * This functions calculates the rectangles, asks the user to continue and downloads
     1036         * the areas if applicable.
     1037         */
     1038        private void confirmAndDownloadAreas(Area a, double max_area, ProgressMonitor progressMonitor) {
    9781039            List<Rectangle2D> toDownload = new ArrayList<Rectangle2D>();
    9791040
    9801041            addToDownload(a, a.getBounds(), toDownload, max_area);
    9811042
    982             msg = new JPanel(new GridBagLayout());
     1043            if(toDownload.size() == 0)
     1044                return;
     1045
     1046            JPanel msg = new JPanel(new GridBagLayout());
    9831047
    9841048            msg.add(new JLabel(
     
    9881052
    9891053            if (toDownload.size() > 1) {
    990                 ret = JOptionPane.showConfirmDialog(
     1054                // hide progress dialog before displaying another pop up. Really closing the
     1055                // dialog will be handled by PleaseWaitRunnable.
     1056                if (progressMonitor instanceof PleaseWaitProgressMonitor) {
     1057                    ((PleaseWaitProgressMonitor) progressMonitor).getDialog().setVisible(false);
     1058                }
     1059
     1060                int ret = JOptionPane.showConfirmDialog(
    9911061                        Main.parent,
    9921062                        msg,
Note: See TracChangeset for help on using the changeset viewer.