Changeset 4745 in josm


Ignore:
Timestamp:
2011-12-29T18:07:04+01:00 (8 years ago)
Author:
jttt
Message:

Add precache wms tiles action to gpx layers (it will download wms tiles along track to cache for faster work afterwards)

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/.classpath

    r4728 r4745  
    2222        <classpathentry kind="lib" path="test/lib/unitils-core/ognl-2.6.9.jar"/>
    2323        <classpathentry kind="lib" path="test/lib/unitils-core/unitils-core-3.1.jar"/>
     24        <classpathentry kind="lib" path="test/lib/fest/debug-1.0.jar"/>
    2425        <classpathentry kind="output" path="bin"/>
    2526</classpath>
  • trunk/src/org/openstreetmap/josm/data/imagery/WmsCache.java

    r4186 r4745  
    6262        final double north;
    6363        final ProjectionBounds bounds;
     64        final String filename;
    6465
    6566        long lastUsed;
    6667        long lastModified;
    67         String filename;
    68 
    69         CacheEntry(double pixelPerDegree, double east, double north, int tileSize) {
     68
     69        CacheEntry(double pixelPerDegree, double east, double north, int tileSize, String filename) {
    7070            this.pixelPerDegree = pixelPerDegree;
    7171            this.east = east;
    7272            this.north = north;
    7373            this.bounds = new ProjectionBounds(east, north, east + tileSize / pixelPerDegree, north + tileSize / pixelPerDegree);
     74            this.filename = filename;
    7475        }
    7576    }
     
    201202                ProjectionEntries projection = getProjectionEntries(projectionType.getName(), projectionType.getCacheDirectory());
    202203                for (EntryType entry: projectionType.getEntry()) {
    203                     CacheEntry ce = new CacheEntry(entry.getPixelPerDegree(), entry.getEast(), entry.getNorth(), tileSize);
     204                    CacheEntry ce = new CacheEntry(entry.getPixelPerDegree(), entry.getEast(), entry.getNorth(), tileSize, entry.getFilename());
    204205                    ce.lastUsed = entry.getLastUsed().getTimeInMillis();
    205                     ce.filename = entry.getFilename();
    206206                    ce.lastModified = entry.getLastModified().getTimeInMillis();
    207207                    projection.entries.add(ce);
     
    315315    }
    316316
     317
    317318    private BufferedImage loadImage(ProjectionEntries projectionEntries, CacheEntry entry) throws IOException {
    318         entry.lastUsed = System.currentTimeMillis();
    319 
    320         SoftReference<BufferedImage> memCache = memoryCache.get(entry);
    321         if (memCache != null) {
    322             BufferedImage result = memCache.get();
    323             if (result != null)
     319
     320        synchronized (this) {
     321            entry.lastUsed = System.currentTimeMillis();
     322
     323            SoftReference<BufferedImage> memCache = memoryCache.get(entry);
     324            if (memCache != null) {
     325                BufferedImage result = memCache.get();
     326                if (result != null)
     327                    return result;
     328            }
     329        }
     330
     331        try {
     332            // Reading can't be in synchronized section, it's too slow
     333            BufferedImage result = ImageIO.read(getImageFile(projectionEntries, entry));
     334            synchronized (this) {
     335                if (result == null) {
     336                    projectionEntries.entries.remove(entry);
     337                    totalFileSizeDirty = true;
     338                }
    324339                return result;
    325         }
    326 
    327         try {
    328             BufferedImage result = ImageIO.read(getImageFile(projectionEntries, entry));
    329             if (result == null) {
     340            }
     341        } catch (IOException e) {
     342            synchronized (this) {
    330343                projectionEntries.entries.remove(entry);
    331344                totalFileSizeDirty = true;
    332             }
    333             return result;
    334         } catch (IOException e) {
    335             projectionEntries.entries.remove(entry);
    336             totalFileSizeDirty = true;
    337             throw e;
     345                throw e;
     346            }
    338347        }
    339348    }
     
    347356    }
    348357
    349     public synchronized BufferedImage getExactMatch(Projection projection, double pixelPerDegree, double east, double north) {
     358    public synchronized boolean hasExactMatch(Projection projection, double pixelPerDegree, double east, double north) {
    350359        ProjectionEntries projectionEntries = getProjectionEntries(projection);
    351360        CacheEntry entry = findEntry(projectionEntries, pixelPerDegree, east, north);
     361        return (entry != null);
     362    }
     363
     364    public BufferedImage getExactMatch(Projection projection, double pixelPerDegree, double east, double north) {
     365        CacheEntry entry = null;
     366        ProjectionEntries projectionEntries = null;
     367        synchronized (this) {
     368            projectionEntries = getProjectionEntries(projection);
     369            entry = findEntry(projectionEntries, pixelPerDegree, east, north);
     370        }
    352371        if (entry != null) {
    353372            try {
    354                 entry.lastUsed = System.currentTimeMillis();
    355373                return loadImage(projectionEntries, entry);
    356374            } catch (IOException e) {
     
    363381    }
    364382
    365     public synchronized BufferedImage getPartialMatch(Projection projection, double pixelPerDegree, double east, double north) {
    366         List<CacheEntry> matches = new ArrayList<WmsCache.CacheEntry>();
    367 
    368         double minPPD = pixelPerDegree / 5;
    369         double maxPPD = pixelPerDegree * 5;
    370         ProjectionEntries projectionEntries = getProjectionEntries(projection);
    371 
    372         ProjectionBounds bounds = new ProjectionBounds(east, north,
    373                 east + tileSize / pixelPerDegree, north + tileSize / pixelPerDegree);
    374 
    375         //TODO Do not load tile if it is completely overlapped by other tile with better ppd
    376         for (CacheEntry entry: projectionEntries.entries) {
    377             if (entry.pixelPerDegree >= minPPD && entry.pixelPerDegree <= maxPPD && entry.bounds.intersects(bounds)) {
    378                 entry.lastUsed = System.currentTimeMillis();
    379                 matches.add(entry);
    380             }
    381         }
    382 
    383         if (matches.isEmpty())
    384             return null;
    385 
    386 
    387         Collections.sort(matches, new Comparator<CacheEntry>() {
    388             @Override
    389             public int compare(CacheEntry o1, CacheEntry o2) {
    390                 return Double.compare(o2.pixelPerDegree, o1.pixelPerDegree);
    391             }
    392         });
     383    public  BufferedImage getPartialMatch(Projection projection, double pixelPerDegree, double east, double north) {
     384        ProjectionEntries projectionEntries;
     385        List<CacheEntry> matches;
     386        synchronized (this) {
     387            matches = new ArrayList<WmsCache.CacheEntry>();
     388
     389            double minPPD = pixelPerDegree / 5;
     390            double maxPPD = pixelPerDegree * 5;
     391            projectionEntries = getProjectionEntries(projection);
     392
     393            double size2 = tileSize / pixelPerDegree;
     394            double border = tileSize * 0.01; // Make sure not to load neighboring tiles that intersects this tile only slightly
     395            ProjectionBounds bounds = new ProjectionBounds(east + border, north + border,
     396                    east + size2 - border, north + size2 - border);
     397
     398            //TODO Do not load tile if it is completely overlapped by other tile with better ppd
     399            for (CacheEntry entry: projectionEntries.entries) {
     400                if (entry.pixelPerDegree >= minPPD && entry.pixelPerDegree <= maxPPD && entry.bounds.intersects(bounds)) {
     401                    entry.lastUsed = System.currentTimeMillis();
     402                    matches.add(entry);
     403                }
     404            }
     405
     406            if (matches.isEmpty())
     407                return null;
     408
     409
     410            Collections.sort(matches, new Comparator<CacheEntry>() {
     411                @Override
     412                public int compare(CacheEntry o1, CacheEntry o2) {
     413                    return Double.compare(o2.pixelPerDegree, o1.pixelPerDegree);
     414                }
     415            });
     416        }
    393417
    394418        //TODO Use alpha layer only when enabled on wms layer
     
    396420        Graphics2D g = result.createGraphics();
    397421
     422
    398423        boolean drawAtLeastOnce = false;
     424        Map<CacheEntry, SoftReference<BufferedImage>> localCache = new HashMap<WmsCache.CacheEntry, SoftReference<BufferedImage>>();
    399425        for (CacheEntry ce: matches) {
    400426            BufferedImage img;
    401427            try {
    402428                img = loadImage(projectionEntries, ce);
    403                 memoryCache.put(ce, new SoftReference<BufferedImage>(img));
     429                localCache.put(ce, new SoftReference<BufferedImage>(img));
    404430            } catch (IOException e) {
    405431                continue;
     
    418444        }
    419445
    420         if (drawAtLeastOnce)
     446        if (drawAtLeastOnce) {
     447            synchronized (this) {
     448                memoryCache.putAll(localCache);
     449            }
    421450            return result;
    422         else
     451        } else
    423452            return null;
    424453    }
     
    461490
    462491    /**
    463      * 
     492     *
    464493     * @param img Used only when overlapping is used, when not used, used raw from imageData
    465494     * @param imageData
     
    475504        File imageFile;
    476505        if (entry == null) {
    477             entry = new CacheEntry(pixelPerDegree, east, north, tileSize);
    478             entry.lastUsed = System.currentTimeMillis();
    479             entry.lastModified = entry.lastUsed;
    480506
    481507            String mimeType;
     
    485511                mimeType = URLConnection.guessContentTypeFromStream(imageData);
    486512            }
    487             entry.filename = generateFileName(projectionEntries, pixelPerDegree, projection, east, north, mimeType);
     513            entry = new CacheEntry(pixelPerDegree, east, north, tileSize,generateFileName(projectionEntries, pixelPerDegree, projection, east, north, mimeType));
     514            entry.lastUsed = System.currentTimeMillis();
     515            entry.lastModified = entry.lastUsed;
    488516            projectionEntries.entries.add(entry);
    489517            imageFile = getImageFile(projectionEntries, entry);
  • trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java

    r4718 r4745  
    2424import java.awt.geom.Rectangle2D;
    2525import java.io.File;
     26import java.io.IOException;
    2627import java.net.MalformedURLException;
    2728import java.net.URL;
     
    3940import javax.swing.AbstractAction;
    4041import javax.swing.Action;
     42import javax.swing.DefaultComboBoxModel;
    4143import javax.swing.Icon;
     44import javax.swing.JComboBox;
    4245import javax.swing.JComponent;
    4346import javax.swing.JFileChooser;
     
    5760
    5861import org.openstreetmap.josm.Main;
     62import org.openstreetmap.josm.actions.AbstractMergeAction.LayerListCellRenderer;
    5963import org.openstreetmap.josm.actions.RenameLayerAction;
    6064import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTaskList;
     
    8084import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
    8185import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
     86import org.openstreetmap.josm.gui.layer.WMSLayer.PrecacheTask;
    8287import org.openstreetmap.josm.gui.layer.markerlayer.AudioMarker;
    8388import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
     
    8691import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
    8792import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     93import org.openstreetmap.josm.gui.progress.ProgressTaskId;
     94import org.openstreetmap.josm.gui.progress.ProgressTaskIds;
    8895import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    8996import org.openstreetmap.josm.io.JpgImporter;
     97import org.openstreetmap.josm.io.OsmTransferException;
    9098import org.openstreetmap.josm.tools.AudioUtil;
    9199import org.openstreetmap.josm.tools.DateUtils;
     
    96104import org.openstreetmap.josm.tools.Utils;
    97105import org.openstreetmap.josm.tools.WindowGeometry;
     106import org.xml.sax.SAXException;
    98107
    99108public class GpxLayer extends Layer {
     
    297306                new ConvertToDataLayerAction(),
    298307                new DownloadAlongTrackAction(),
     308                new DownloadWmsAlongTrackAction(),
    299309                SeparatorLayerAction.INSTANCE,
    300310                new ChooseTrackVisibilityAction(),
     
    12451255        }
    12461256
     1257
    12471258        /**
    12481259         * Area "a" contains the hull that we would like to download data for. however we
     
    13091320                    }
    13101321                    );
     1322        }
     1323    }
     1324
     1325
     1326    public class DownloadWmsAlongTrackAction extends AbstractAction {
     1327        public DownloadWmsAlongTrackAction() {
     1328            super(tr("Precache imagery tiles along this track"), ImageProvider.get("downloadalongtrack"));
     1329        }
     1330
     1331        public void actionPerformed(ActionEvent e) {
     1332
     1333            final List<LatLon> points = new ArrayList<LatLon>();
     1334
     1335            for (GpxTrack trk : data.tracks) {
     1336                for (GpxTrackSegment segment : trk.getSegments()) {
     1337                    for (WayPoint p : segment.getWayPoints()) {
     1338                        points.add(p.getCoor());
     1339                    }
     1340                }
     1341            }
     1342            for (WayPoint p : data.waypoints) {
     1343                points.add(p.getCoor());
     1344            }
     1345
     1346
     1347            final WMSLayer layer = askWMSLayer();
     1348            if (layer != null) {
     1349                PleaseWaitRunnable task = new PleaseWaitRunnable(tr("Precaching WMS")) {
     1350
     1351                    private PrecacheTask precacheTask;
     1352
     1353                    @Override
     1354                    protected void realRun() throws SAXException, IOException, OsmTransferException {
     1355                        precacheTask = new PrecacheTask(progressMonitor);
     1356                        layer.downloadAreaToCache(precacheTask, points, 0, 0);
     1357                        while (!precacheTask.isFinished() && !progressMonitor.isCanceled()) {
     1358                            synchronized (this) {
     1359                                try {
     1360                                    wait(200);
     1361                                } catch (InterruptedException e) {
     1362                                    e.printStackTrace();
     1363                                }
     1364                            }
     1365                        }
     1366                    }
     1367
     1368                    @Override
     1369                    protected void finish() {
     1370                    }
     1371
     1372                    @Override
     1373                    protected void cancel() {
     1374                        precacheTask.cancel();
     1375                    }
     1376
     1377                    @Override
     1378                    public ProgressTaskId canRunInBackground() {
     1379                        return ProgressTaskIds.PRECACHE_WMS;
     1380                    }
     1381                };
     1382                Main.worker.execute(task);
     1383            }
     1384
     1385
     1386        }
     1387
     1388        protected WMSLayer askWMSLayer() {
     1389            List<WMSLayer> targetLayers = Main.map.mapView.getLayersOfType(WMSLayer.class);
     1390
     1391            if (targetLayers.isEmpty()) {
     1392                warnNoImageryLayers();
     1393                return null;
     1394            }
     1395
     1396            JComboBox layerList = new JComboBox();
     1397            layerList.setRenderer(new LayerListCellRenderer());
     1398            layerList.setModel(new DefaultComboBoxModel(targetLayers.toArray()));
     1399            layerList.setSelectedIndex(0);
     1400
     1401            JPanel pnl = new JPanel();
     1402            pnl.setLayout(new GridBagLayout());
     1403            pnl.add(new JLabel(tr("Please select the imagery layer.")), GBC.eol());
     1404            pnl.add(layerList, GBC.eol());
     1405
     1406            ExtendedDialog ed = new ExtendedDialog(Main.parent,
     1407                    tr("Select imagery layer"),
     1408                    new String[] { tr("Download"), tr("Cancel") });
     1409            ed.setButtonIcons(new String[] { "dialogs/down", "cancel" });
     1410            ed.setContent(pnl);
     1411            ed.showDialog();
     1412            if (ed.getValue() != 1)
     1413                return null;
     1414
     1415            WMSLayer targetLayer = (WMSLayer) layerList.getSelectedItem();
     1416            return targetLayer;
     1417        }
     1418
     1419        protected void warnNoImageryLayers() {
     1420            JOptionPane.showMessageDialog(Main.parent,
     1421                    tr("There are no imagery layers."),
     1422                    tr("No imagery layers"), JOptionPane.WARNING_MESSAGE);
    13111423        }
    13121424    }
  • trunk/src/org/openstreetmap/josm/gui/layer/WMSLayer.java

    r4633 r4745  
    88import java.awt.Graphics2D;
    99import java.awt.Image;
     10import java.awt.Point;
    1011import java.awt.event.ActionEvent;
    1112import java.awt.event.MouseAdapter;
     
    4546import org.openstreetmap.josm.data.ProjectionBounds;
    4647import org.openstreetmap.josm.data.coor.EastNorth;
     48import org.openstreetmap.josm.data.coor.LatLon;
    4749import org.openstreetmap.josm.data.imagery.GeorefImage;
    4850import org.openstreetmap.josm.data.imagery.GeorefImage.State;
     
    6163import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
    6264import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
     65import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    6366import org.openstreetmap.josm.io.imagery.Grabber;
    6467import org.openstreetmap.josm.io.imagery.HTMLGrabber;
     
    6770import org.openstreetmap.josm.tools.ImageProvider;
    6871
     72
    6973/**
    7074 * This is a layer that grabs the current screen from an WMS server. The data
     
    7276 */
    7377public class WMSLayer extends ImageryLayer implements ImageObserver, PreferenceChangedListener {
     78
     79    public static class PrecacheTask {
     80        private final ProgressMonitor progressMonitor;
     81        private volatile int totalCount;
     82        private volatile int processedCount;
     83        private volatile boolean isCancelled;
     84
     85        public PrecacheTask(ProgressMonitor progressMonitor) {
     86            this.progressMonitor = progressMonitor;
     87        }
     88
     89        boolean isFinished() {
     90            return totalCount == processedCount;
     91        }
     92
     93        public int getTotalCount() {
     94            return totalCount;
     95        }
     96
     97        public void cancel() {
     98            isCancelled = true;
     99        }
     100    }
    74101
    75102    private static final ObjectFactory OBJECT_FACTORY = null; // Fake reference to keep build scripts from removing ObjectFactory class. This class is not used directly but it's necessary for jaxb to work
     
    159186        }
    160187
     188
    161189        Main.pref.addPreferenceChangeListener(this);
    162190
     
    205233    public boolean hasAutoDownload(){
    206234        return autoDownloadEnabled;
     235    }
     236
     237    public void downloadAreaToCache(PrecacheTask precacheTask, List<LatLon> points, double bufferX, double bufferY) {
     238        Set<Point> requestedTiles = new HashSet<Point>();
     239        for (LatLon point: points) {
     240            EastNorth minEn = Main.getProjection().latlon2eastNorth(new LatLon(point.lat() - bufferY, point.lon() - bufferX));
     241            EastNorth maxEn = Main.getProjection().latlon2eastNorth(new LatLon(point.lat() + bufferY, point.lon() + bufferX));
     242            int minX = getImageXIndex(minEn.east());
     243            int maxX = getImageXIndex(maxEn.east());
     244            int minY = getImageYIndex(minEn.north());
     245            int maxY = getImageYIndex(maxEn.north());
     246
     247            for (int x=minX; x<=maxX; x++) {
     248                for (int y=minY; y<=maxY; y++) {
     249                    requestedTiles.add(new Point(x, y));
     250                }
     251            }
     252        }
     253
     254        for (Point p: requestedTiles) {
     255            addRequest(new WMSRequest(p.x, p.y, info.getPixelPerDegree(), true, false, precacheTask));
     256        }
     257
     258        precacheTask.progressMonitor.setTicksCount(precacheTask.getTotalCount());
     259        precacheTask.progressMonitor.setCustomText(tr("Downloaded {0}/{1} tiles", 0, precacheTask.totalCount));
    207260    }
    208261
     
    472525        int dy = request.getYIndex() - mouseY;
    473526
    474         return dx * dx + dy * dy;
    475     }
    476 
    477     public WMSRequest getRequest() {
     527        return 1 + dx * dx + dy * dy;
     528    }
     529
     530    private void sortRequests(boolean localOnly) {
     531        Iterator<WMSRequest> it = requestQueue.iterator();
     532        while (it.hasNext()) {
     533            WMSRequest item = it.next();
     534
     535            if (item.getPrecacheTask() != null && item.getPrecacheTask().isCancelled) {
     536                it.remove();
     537                continue;
     538            }
     539
     540            int priority = getRequestPriority(item);
     541            if (priority == -1 && item.isPrecacheOnly()) {
     542                priority = Integer.MAX_VALUE; // Still download, but prefer requests in current view
     543            }
     544
     545            if (localOnly && !item.hasExactMatch()) {
     546                priority = Integer.MAX_VALUE; // Only interested in tiles that can be loaded from file immediately
     547            }
     548
     549            if (       priority == -1
     550                    || finishedRequests.contains(item)
     551                    || processingRequests.contains(item)) {
     552                it.remove();
     553            } else {
     554                item.setPriority(priority);
     555            }
     556        }
     557        Collections.sort(requestQueue);
     558    }
     559
     560    public WMSRequest getRequest(boolean localOnly) {
    478561        requestQueueLock.lock();
    479562        try {
    480563            workingThreadCount--;
    481             Iterator<WMSRequest> it = requestQueue.iterator();
    482             while (it.hasNext()) {
    483                 WMSRequest item = it.next();
    484                 int priority = getRequestPriority(item);
    485                 if (priority == -1 || finishedRequests.contains(item) || processingRequests.contains(item)) {
    486                     it.remove();
    487                 } else {
    488                     item.setPriority(priority);
    489                 }
    490             }
    491             Collections.sort(requestQueue);
    492 
    493             EastNorth cursorEastNorth = mv.getEastNorth(mv.lastMEvent.getX(), mv.lastMEvent.getY());
    494             int mouseX = getImageXIndex(cursorEastNorth.east());
    495             int mouseY = getImageYIndex(cursorEastNorth.north());
    496             boolean isOnMouse = requestQueue.size() > 0 && requestQueue.get(0).getXIndex() == mouseX && requestQueue.get(0).getYIndex() == mouseY;
    497 
    498             // If there is only one thread left then keep it in case we need to download other tile urgently
    499             while (!canceled &&
    500                     (requestQueue.isEmpty() || (!isOnMouse && threadCount - workingThreadCount == 0 && threadCount > 1))) {
     564
     565            sortRequests(localOnly);
     566            while (!canceled && (requestQueue.isEmpty() || (localOnly && !requestQueue.get(0).hasExactMatch()))) {
    501567                try {
    502568                    queueEmpty.await();
     569                    sortRequests(localOnly);
    503570                } catch (InterruptedException e) {
    504571                    // Shouldn't happen
     
    523590        requestQueueLock.lock();
    524591        try {
     592            PrecacheTask task = request.getPrecacheTask();
     593            if (task != null) {
     594                task.processedCount++;
     595                if (!task.progressMonitor.isCanceled()) {
     596                    task.progressMonitor.worked(1);
     597                    task.progressMonitor.setCustomText(tr("Downloaded {0}/{1} tiles", task.processedCount, task.totalCount));
     598                }
     599            }
    525600            processingRequests.remove(request);
    526             if (request.getState() != null) {
     601            if (request.getState() != null && !request.isPrecacheOnly()) {
    527602                finishedRequests.add(request);
    528603                mv.repaint();
     
    536611        requestQueueLock.lock();
    537612        try {
     613
     614            ProjectionBounds b = getBounds(request);
     615            // Checking for exact match is fast enough, no need to do it in separated thread
     616            request.setHasExactMatch(cache.hasExactMatch(Main.getProjection(), request.getPixelPerDegree(), b.minEast, b.minNorth));
     617            if (request.isPrecacheOnly() && request.hasExactMatch())
     618                return; // We already have this tile cached
     619
    538620            if (!requestQueue.contains(request) && !finishedRequests.contains(request) && !processingRequests.contains(request)) {
    539621                requestQueue.add(request);
     622                if (request.getPrecacheTask() != null) {
     623                    request.getPrecacheTask().totalCount++;
     624                }
    540625                queueEmpty.signalAll();
    541626            }
     
    545630    }
    546631
    547     public boolean requestIsValid(WMSRequest request) {
     632    public boolean requestIsVisible(WMSRequest request) {
    548633        return bminx <= request.getXIndex() && bmaxx >= request.getXIndex() && bminy <= request.getYIndex() && bmaxy >= request.getYIndex();
    549634    }
     
    871956            grabberThreads.clear();
    872957            for (int i=0; i<threadCount; i++) {
    873                 Grabber grabber = getGrabber();
     958                Grabber grabber = getGrabber(i == 0 && threadCount > 1);
    874959                grabbers.add(grabber);
    875960                Thread t = new Thread(grabber, "WMS " + getName() + " " + i);
     
    914999    }
    9151000
    916     protected Grabber getGrabber(){
     1001    protected Grabber getGrabber(boolean localOnly){
    9171002        if(getInfo().getImageryType() == ImageryType.HTML)
    918             return new HTMLGrabber(mv, this);
     1003            return new HTMLGrabber(mv, this, localOnly);
    9191004        else if(getInfo().getImageryType() == ImageryType.WMS)
    920             return new WMSGrabber(mv, this);
     1005            return new WMSGrabber(mv, this, localOnly);
    9211006        else throw new IllegalStateException("getGrabber() called for non-WMS layer type");
     1007    }
     1008
     1009    public ProjectionBounds getBounds(WMSRequest request) {
     1010        ProjectionBounds result = new ProjectionBounds(
     1011                getEastNorth(request.getXIndex(), request.getYIndex()),
     1012                getEastNorth(request.getXIndex() + 1, request.getYIndex() + 1));
     1013
     1014        if (WMSLayer.PROP_OVERLAP.get()) {
     1015            double eastSize =  result.maxEast - result.minEast;
     1016            double northSize =  result.maxNorth - result.minNorth;
     1017
     1018            double eastCoef = WMSLayer.PROP_OVERLAP_EAST.get() / 100.0;
     1019            double northCoef = WMSLayer.PROP_OVERLAP_NORTH.get() / 100.0;
     1020
     1021            result = new ProjectionBounds(result.getMin(),
     1022                    new EastNorth(result.maxEast + eastCoef * eastSize,
     1023                            result.maxNorth + northCoef * northSize));
     1024        }
     1025        return result;
    9221026    }
    9231027
  • trunk/src/org/openstreetmap/josm/gui/progress/ProgressTaskIds.java

    r4718 r4745  
    55
    66    ProgressTaskId DOWNLOAD_GPS = new ProgressTaskId("core", "downloadGps");
     7    ProgressTaskId PRECACHE_WMS = new ProgressTaskId("core", "precacheWms");
    78
    89}
  • trunk/src/org/openstreetmap/josm/io/imagery/Grabber.java

    r4126 r4745  
    44import org.openstreetmap.josm.Main;
    55import org.openstreetmap.josm.data.ProjectionBounds;
    6 import org.openstreetmap.josm.data.coor.EastNorth;
    76import org.openstreetmap.josm.data.imagery.GeorefImage.State;
    8 import org.openstreetmap.josm.data.projection.Projection;
    97import org.openstreetmap.josm.gui.MapView;
    108import org.openstreetmap.josm.gui.layer.WMSLayer;
     
    1311    protected final MapView mv;
    1412    protected final WMSLayer layer;
     13    private final boolean localOnly;
    1514
    1615    protected ProjectionBounds b;
    17     protected Projection proj;
    18     protected double pixelPerDegree;
    19     protected WMSRequest request;
    2016    protected volatile boolean canceled;
    2117
    22     Grabber(MapView mv, WMSLayer layer) {
     18    Grabber(MapView mv, WMSLayer layer, boolean localOnly) {
    2319        this.mv = mv;
    2420        this.layer = layer;
    25     }
    26 
    27     private void updateState(WMSRequest request) {
    28         b = new ProjectionBounds(
    29                 layer.getEastNorth(request.getXIndex(), request.getYIndex()),
    30                 layer.getEastNorth(request.getXIndex() + 1, request.getYIndex() + 1));
    31         if (WMSLayer.PROP_OVERLAP.get()) {
    32             double eastSize =  b.maxEast - b.minEast;
    33             double northSize =  b.maxNorth - b.minNorth;
    34 
    35             double eastCoef = WMSLayer.PROP_OVERLAP_EAST.get() / 100.0;
    36             double northCoef = WMSLayer.PROP_OVERLAP_NORTH.get() / 100.0;
    37 
    38             this.b = new ProjectionBounds(b.getMin(),
    39                     new EastNorth(b.maxEast + eastCoef * eastSize,
    40                             b.maxNorth + northCoef * northSize));
    41         }
    42 
    43         this.proj = Main.getProjection();
    44         this.pixelPerDegree = request.getPixelPerDegree();
    45         this.request = request;
     21        this.localOnly = localOnly;
    4622    }
    4723
     
    6036            if (canceled)
    6137                return;
    62             WMSRequest request = layer.getRequest();
     38            WMSRequest request = layer.getRequest(localOnly);
    6339            if (request == null)
    6440                return;
    65             updateState(request);
    66             if(!loadFromCache(request)){
    67                 attempt(request);
     41            this.b = layer.getBounds(request);
     42            if (request.isPrecacheOnly()) {
     43                if (!layer.cache.hasExactMatch(Main.getProjection(), request.getPixelPerDegree(), b.minEast, b.minNorth)) {
     44                    attempt(request);
     45                }
     46            } else {
     47                if(!loadFromCache(request)){
     48                    attempt(request);
     49                }
    6850            }
    6951            layer.finishRequest(request);
     
    7759                return;
    7860            try {
    79                 if (!layer.requestIsValid(request))
     61                if (!request.isPrecacheOnly() && !layer.requestIsVisible(request))
    8062                    return;
    8163                fetch(request, i);
  • trunk/src/org/openstreetmap/josm/io/imagery/HTMLGrabber.java

    r4126 r4745  
    2222    public static final StringProperty PROP_BROWSER = new StringProperty("imagery.wms.browser", "webkit-image {0}");
    2323
    24     public HTMLGrabber(MapView mv, WMSLayer layer) {
    25         super(mv, layer);
     24    public HTMLGrabber(MapView mv, WMSLayer layer, boolean localOnly) {
     25        super(mv, layer, localOnly);
    2626    }
    2727
    2828    @Override
    29     protected BufferedImage grab(URL url, int attempt) throws IOException {
     29    protected BufferedImage grab(WMSRequest request, URL url, int attempt) throws IOException {
    3030        String urlstring = url.toExternalForm();
    3131
     
    5252        BufferedImage img = layer.normalizeImage(ImageIO.read(bais));
    5353        bais.reset();
    54         layer.cache.saveToCache(layer.isOverlapEnabled()?img:null, bais, Main.getProjection(), pixelPerDegree, b.minEast, b.minNorth);
     54        layer.cache.saveToCache(layer.isOverlapEnabled()?img:null, bais, Main.getProjection(), request.getPixelPerDegree(), b.minEast, b.minNorth);
    5555
    5656        return img;
  • trunk/src/org/openstreetmap/josm/io/imagery/WMSGrabber.java

    r4432 r4745  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.io.imagery;
    3 
    4 import static org.openstreetmap.josm.tools.I18n.tr;
    53
    64import java.awt.image.BufferedImage;
     
    1816import java.text.DecimalFormatSymbols;
    1917import java.text.NumberFormat;
    20 import java.util.ArrayList;
    21 import java.util.List;
    22 import java.util.Map.Entry;
     18import java.util.HashMap;
    2319import java.util.Locale;
    2420import java.util.Map;
    25 import java.util.HashMap;
     21import java.util.Map.Entry;
    2622import java.util.regex.Matcher;
    2723import java.util.regex.Pattern;
    2824
    2925import javax.imageio.ImageIO;
    30 import javax.swing.JOptionPane;
    3126
    3227import org.openstreetmap.josm.Main;
     
    5045    private Map<String, String> props = new HashMap<String, String>();
    5146
    52     public WMSGrabber(MapView mv, WMSLayer layer) {
    53         super(mv, layer);
     47    public WMSGrabber(MapView mv, WMSLayer layer, boolean localOnly) {
     48        super(mv, layer, localOnly);
    5449        this.info = layer.getInfo();
    5550        this.baseURL = info.getUrl();
     
    7772                    b.maxEast, b.maxNorth,
    7873                    width(), height());
    79             request.finish(State.IMAGE, grab(url, attempt));
     74            request.finish(State.IMAGE, grab(request, url, attempt));
    8075
    8176        } catch(Exception e) {
     
    10297
    10398        return new URL(baseURL.replaceAll("\\{proj(\\([^})]+\\))?\\}", myProj)
    104             .replaceAll("\\{bbox\\}", latLonFormat.format(w) + ","
    105                 + latLonFormat.format(s) + ","
    106                 + latLonFormat.format(e) + ","
    107                 + latLonFormat.format(n))
    108             .replaceAll("\\{w\\}", latLonFormat.format(w))
    109             .replaceAll("\\{s\\}", latLonFormat.format(s))
    110             .replaceAll("\\{e\\}", latLonFormat.format(e))
    111             .replaceAll("\\{n\\}", latLonFormat.format(n))
    112             .replaceAll("\\{width\\}", String.valueOf(wi))
    113             .replaceAll("\\{height\\}", String.valueOf(ht))
    114             .replace(" ", "%20"));
     99                .replaceAll("\\{bbox\\}", latLonFormat.format(w) + ","
     100                        + latLonFormat.format(s) + ","
     101                        + latLonFormat.format(e) + ","
     102                        + latLonFormat.format(n))
     103                        .replaceAll("\\{w\\}", latLonFormat.format(w))
     104                        .replaceAll("\\{s\\}", latLonFormat.format(s))
     105                        .replaceAll("\\{e\\}", latLonFormat.format(e))
     106                        .replaceAll("\\{n\\}", latLonFormat.format(n))
     107                        .replaceAll("\\{width\\}", String.valueOf(wi))
     108                        .replaceAll("\\{height\\}", String.valueOf(ht))
     109                        .replace(" ", "%20"));
    115110    }
    116111
    117112    @Override
    118113    public boolean loadFromCache(WMSRequest request) {
    119         BufferedImage cached = layer.cache.getExactMatch(Main.getProjection(), pixelPerDegree, b.minEast, b.minNorth);
     114        BufferedImage cached = layer.cache.getExactMatch(Main.getProjection(), request.getPixelPerDegree(), b.minEast, b.minNorth);
    120115
    121116        if (cached != null) {
     
    123118            return true;
    124119        } else if (request.isAllowPartialCacheMatch()) {
    125             BufferedImage partialMatch = layer.cache.getPartialMatch(Main.getProjection(), pixelPerDegree, b.minEast, b.minNorth);
     120            BufferedImage partialMatch = layer.cache.getPartialMatch(Main.getProjection(), request.getPixelPerDegree(), b.minEast, b.minNorth);
    126121            if (partialMatch != null) {
    127122                request.finish(State.PARTLY_IN_CACHE, partialMatch);
     
    138133    }
    139134
    140     protected BufferedImage grab(URL url, int attempt) throws IOException, OsmTransferException {
     135    protected BufferedImage grab(WMSRequest request, URL url, int attempt) throws IOException, OsmTransferException {
    141136        System.out.println("Grabbing WMS " + (attempt > 1? "(attempt " + attempt + ") ":"") + url);
    142137
     
    164159        BufferedImage img = layer.normalizeImage(ImageIO.read(bais));
    165160        bais.reset();
    166         layer.cache.saveToCache(layer.isOverlapEnabled()?img:null, bais, Main.getProjection(), pixelPerDegree, b.minEast, b.minNorth);
     161        layer.cache.saveToCache(layer.isOverlapEnabled()?img:null, bais, Main.getProjection(), request.getPixelPerDegree(), b.minEast, b.minNorth);
    167162        return img;
    168163    }
  • trunk/src/org/openstreetmap/josm/io/imagery/WMSRequest.java

    r4065 r4745  
    55
    66import org.openstreetmap.josm.data.imagery.GeorefImage.State;
     7import org.openstreetmap.josm.gui.layer.WMSLayer.PrecacheTask;
    78
    89public class WMSRequest implements Comparable<WMSRequest> {
     
    1112    private final double pixelPerDegree;
    1213    private final boolean real; // Download even if autodownloading is disabled
     14    private final PrecacheTask precacheTask; // Download even when wms tile is not currently visible (precache)
    1315    private final boolean allowPartialCacheMatch;
    1416    private int priority;
     17    private boolean hasExactMatch;
    1518    // Result
    1619    private State state;
     
    1821
    1922    public WMSRequest(int xIndex, int yIndex, double pixelPerDegree, boolean real, boolean allowPartialCacheMatch) {
     23        this(xIndex, yIndex, pixelPerDegree, real, allowPartialCacheMatch, null);
     24    }
     25
     26    public WMSRequest(int xIndex, int yIndex, double pixelPerDegree, boolean real, boolean allowPartialCacheMatch, PrecacheTask precacheTask) {
    2027        this.xIndex = xIndex;
    2128        this.yIndex = yIndex;
    2229        this.pixelPerDegree = pixelPerDegree;
    2330        this.real = real;
     31        this.precacheTask = precacheTask;
    2432        this.allowPartialCacheMatch = allowPartialCacheMatch;
    2533    }
     34
    2635
    2736    public void finish(State state, BufferedImage image) {
     
    99108    public String toString() {
    100109        return "WMSRequest [xIndex=" + xIndex + ", yIndex=" + yIndex
    101         + ", pixelPerDegree=" + pixelPerDegree + "]";
     110                + ", pixelPerDegree=" + pixelPerDegree + "]";
    102111    }
    103112
     
    106115    }
    107116
     117    public boolean isPrecacheOnly() {
     118        return precacheTask != null;
     119    }
     120
     121    public PrecacheTask getPrecacheTask() {
     122        return precacheTask;
     123    }
     124
    108125    public boolean isAllowPartialCacheMatch() {
    109126        return allowPartialCacheMatch;
    110127    }
     128
     129    public boolean hasExactMatch() {
     130        return hasExactMatch;
     131    }
     132
     133    public void setHasExactMatch(boolean hasExactMatch) {
     134        this.hasExactMatch = hasExactMatch;
     135    }
    111136}
Note: See TracChangeset for help on using the changeset viewer.