X-Git-Url: https://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=src%2Ftim%2Fprune%2Ffunction%2Fsrtm%2FLookupSrtmFunction.java;h=c48af016b889f0df84a094de2df84db0db0ef272;hp=15997448e038e6f4bb6e9f4b9437c99491b18a6e;hb=HEAD;hpb=2302358503c38817e19f6e529f6c9e530aac0e86 diff --git a/src/tim/prune/function/srtm/LookupSrtmFunction.java b/src/tim/prune/function/srtm/LookupSrtmFunction.java index 1599744..cccc7ed 100644 --- a/src/tim/prune/function/srtm/LookupSrtmFunction.java +++ b/src/tim/prune/function/srtm/LookupSrtmFunction.java @@ -4,7 +4,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.URL; -import java.util.ArrayList; +import java.util.HashSet; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -40,6 +40,8 @@ public class LookupSrtmFunction extends GenericFunction implements Runnable private boolean _normalTrack = true; /** Flag set when any tiles had to be downloaded (rather than just loaded locally) */ private boolean _hadToDownload = false; + /** Count the number of tiles downloaded and cached */ + private int _numCached = 0; /** Flag to check whether this function is currently running or not */ private boolean _running = false; @@ -100,8 +102,6 @@ public class LookupSrtmFunction extends GenericFunction implements Runnable */ public void run() { - // Compile list of tiles to get - ArrayList tileList = new ArrayList(); boolean hasZeroAltitudePoints = false; boolean hasNonZeroAltitudePoints = false; // First, loop to see what kind of points we have @@ -128,64 +128,63 @@ public class LookupSrtmFunction extends GenericFunction implements Runnable } // Now loop again to extract the required tiles + HashSet tileSet = new HashSet(); for (int i = 0; i < _track.getNumPoints(); i++) { // Consider points which don't have altitudes or have zero values if (!_track.getPoint(i).hasAltitude() || (overwriteZeros && _track.getPoint(i).getAltitude().getValue() == 0)) { - SrtmTile tile = new SrtmTile(_track.getPoint(i)); - boolean alreadyGot = false; - for (int t = 0; t < tileList.size(); t++) - { - if (tileList.get(t).equals(tile)) { - alreadyGot = true; - } - } - if (!alreadyGot) {tileList.add(tile);} + tileSet.add(new SrtmTile(_track.getPoint(i))); } } - lookupValues(tileList, overwriteZeros); + lookupValues(tileSet, overwriteZeros); // Finished _running = false; // Show tip if lots of online lookups were necessary if (_hadToDownload) { _app.showTip(TipManager.Tip_DownloadSrtm); } + else if (_numCached > 0) { + showConfirmMessage(_numCached); + } } /** * Lookup the values from SRTM data - * @param inTileList list of tiles to get + * @param inTileSet set of tiles to get * @param inOverwriteZeros true to overwrite zero altitude values */ - private void lookupValues(ArrayList inTileList, boolean inOverwriteZeros) + private void lookupValues(HashSet inTileSet, boolean inOverwriteZeros) { UndoLookupSrtm undo = new UndoLookupSrtm(_app.getTrackInfo()); int numAltitudesFound = 0; + TileFinder tileFinder = new TileFinder(); + String errorMessage = null; + final int numTiles = inTileSet.size(); + // Update progress bar if (_progress != null) { - _progress.setMaximum(inTileList.size()); + _progress.setMaximum(numTiles); _progress.setValue(0); } - String errorMessage = null; - // Get urls for each tile - URL[] urls = TileFinder.getUrls(inTileList); - for (int t=0; t 0) System.out.println(numVoids + " voids found"); - double altitude = 0.0; - switch (numVoids) - { - case 0: altitude = bilinearInterpolate(fouralts, x, y); break; - case 1: altitude = bilinearInterpolate(fixVoid(fouralts), x, y); break; - case 2: - case 3: altitude = averageNonVoid(fouralts); break; - default: altitude = VOID_VAL; - } - // Special case for terrain tracks, don't interpolate voids yet - if (!_normalTrack && numVoids > 0) { - altitude = VOID_VAL; - } - if (altitude != VOID_VAL) - { - point.setFieldValue(Field.ALTITUDE, ""+altitude, false); - // depending on settings, this value may have been added as feet, we need to force metres - point.getAltitude().reset(new Altitude((int)altitude, UnitSetLibrary.UNITS_METRES)); - numAltitudesFound++; - } - } - catch (ArrayIndexOutOfBoundsException obe) { - // System.err.println("lat=" + point.getLatitude().getDouble() + ", x=" + x + ", y=" + y + ", idx=" + idx1); - } - } - } - } + numAltitudesFound += applySrtmTileToWholeTrack(tile, heights, inOverwriteZeros); } } - catch (IOException ioe) {errorMessage = ioe.getClass().getName() + " - " + ioe.getMessage(); + catch (IOException ioe) { + errorMessage = ioe.getClass().getName() + " - " + ioe.getMessage(); } } } @@ -281,7 +237,7 @@ public class LookupSrtmFunction extends GenericFunction implements Runnable else if (errorMessage != null) { _app.showErrorMessageNoLookup(getNameKey(), errorMessage); } - else if (inTileList.size() > 0) { + else if (numTiles > 0) { _app.showErrorMessage(getNameKey(), "error.lookupsrtm.nonefound"); } else { @@ -294,7 +250,45 @@ public class LookupSrtmFunction extends GenericFunction implements Runnable * @param inUrl URL for online resource * @return ZipInputStream either on the local file or on the downloaded zip file */ - private ZipInputStream getStreamToHgtFile(URL inUrl) + private ZipInputStream getStreamToSrtmData(URL inUrl) + throws IOException + { + ZipInputStream localData = null; + try { + localData = getStreamToLocalHgtFile(inUrl); + } + catch (IOException ioe) { + localData = null; + } + if (localData != null) + { + return localData; + } + // try to download to cache + TileDownloader cacher = new TileDownloader(); + TileDownloader.Result result = cacher.downloadTile(inUrl); + // System.out.println("Result: " + result); + if (result == TileDownloader.Result.DOWNLOADED) + { + _numCached++; + return getStreamToLocalHgtFile(inUrl); + } + // If we don't have a cache, we may be able to download it temporarily + if (result != TileDownloader.Result.DOWNLOAD_FAILED) + { + _hadToDownload = true; + return new ZipInputStream(inUrl.openStream()); + } + // everything failed + return null; + } + + /** + * Get the SRTM file from the local cache, if available + * @param inUrl URL for online resource + * @return ZipInputStream on the local file or null if not there + */ + private ZipInputStream getStreamToLocalHgtFile(URL inUrl) throws IOException { String diskCachePath = Config.getConfigString(Config.KEY_DISK_CACHE); @@ -313,10 +307,66 @@ public class LookupSrtmFunction extends GenericFunction implements Runnable } } } - // System.out.println("Lookup: Trying online: " + inUrl.toString()); - _hadToDownload = true; - // MAYBE: Only download if we're in online mode? - return new ZipInputStream(inUrl.openStream()); + return null; + } + + /** + * Given the height data read in from file, apply the given tile to all points + * in the track with missing altitude + * @param inTile tile being applied + * @param inHeights height data read in from file + * @param inOverwriteZeros true to overwrite zero altitude values + * @return number of altitudes found + */ + private int applySrtmTileToWholeTrack(SrtmTile inTile, int[] inHeights, boolean inOverwriteZeros) + { + int numAltitudesFound = 0; + // Loop over all points in track, try to apply altitude from array + for (int p = 0; p < _track.getNumPoints(); p++) + { + DataPoint point = _track.getPoint(p); + if (!point.hasAltitude() + || (inOverwriteZeros && point.getAltitude().getValue() == 0)) + { + if (new SrtmTile(point).equals(inTile)) + { + double x = (point.getLongitude().getDouble() - inTile.getLongitude()) * 1200; + double y = 1201 - (point.getLatitude().getDouble() - inTile.getLatitude()) * 1200; + int idx1 = ((int)y)*1201 + (int)x; + try + { + int[] fouralts = {inHeights[idx1], inHeights[idx1+1], inHeights[idx1-1201], inHeights[idx1-1200]}; + int numVoids = (fouralts[0]==VOID_VAL?1:0) + (fouralts[1]==VOID_VAL?1:0) + + (fouralts[2]==VOID_VAL?1:0) + (fouralts[3]==VOID_VAL?1:0); + // if (numVoids > 0) System.out.println(numVoids + " voids found"); + double altitude = 0.0; + switch (numVoids) + { + case 0: altitude = bilinearInterpolate(fouralts, x, y); break; + case 1: altitude = bilinearInterpolate(fixVoid(fouralts), x, y); break; + case 2: + case 3: altitude = averageNonVoid(fouralts); break; + default: altitude = VOID_VAL; + } + // Special case for terrain tracks, don't interpolate voids yet + if (!_normalTrack && numVoids > 0) { + altitude = VOID_VAL; + } + if (altitude != VOID_VAL) + { + point.setFieldValue(Field.ALTITUDE, ""+altitude, false); + // depending on settings, this value may have been added as feet, we need to force metres + point.getAltitude().reset(new Altitude((int)altitude, UnitSetLibrary.UNITS_METRES)); + numAltitudesFound++; + } + } + catch (ArrayIndexOutOfBoundsException obe) { + // System.err.println("lat=" + point.getLatitude().getDouble() + ", x=" + x + ", y=" + y + ", idx=" + idx1); + } + } + } + } + return numAltitudesFound; } /** @@ -383,4 +433,18 @@ public class LookupSrtmFunction extends GenericFunction implements Runnable { return _running; } + + private void showConfirmMessage(int numDownloaded) + { + if (numDownloaded == 1) + { + JOptionPane.showMessageDialog(_parentFrame, I18nManager.getTextWithNumber("confirm.downloadsrtm.1", numDownloaded), + I18nManager.getText(getNameKey()), JOptionPane.INFORMATION_MESSAGE); + } + else if (numDownloaded > 1) + { + JOptionPane.showMessageDialog(_parentFrame, I18nManager.getTextWithNumber("confirm.downloadsrtm", numDownloaded), + I18nManager.getText(getNameKey()), JOptionPane.INFORMATION_MESSAGE); + } + } }