Changeset 4323 in josm


Ignore:
Timestamp:
Aug 20, 2011 5:05:16 PM (22 months 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.